1 20 21 22 23 24 25 package org.snmp4j.asn1; 26 27 import java.io.OutputStream ; 28 import java.io.IOException ; 29 30 36 public class BER { 37 38 public static final byte ASN_BOOLEAN = 0x01; 39 public static final byte ASN_INTEGER = 0x02; 40 public static final byte ASN_BIT_STR = 0x03; 41 public static final byte ASN_OCTET_STR = 0x04; 42 public static final byte ASN_NULL = 0x05; 43 public static final byte ASN_OBJECT_ID = 0x06; 44 public static final byte ASN_SEQUENCE = 0x10; 45 public static final byte ASN_SET = 0x11; 46 public static final byte ASN_UNIVERSAL = 0x00; 47 public static final byte ASN_APPLICATION = 0x40; 48 public static final byte ASN_CONTEXT = (byte)0x80; 49 public static final byte ASN_PRIVATE = (byte)0xC0; 50 public static final byte ASN_PRIMITIVE = (byte)0x00; 51 public static final byte ASN_CONSTRUCTOR = (byte)0x20; 52 53 public static final byte ASN_LONG_LEN = (byte)0x80; 54 public static final byte ASN_EXTENSION_ID = (byte)0x1F; 55 public static final byte ASN_BIT8 = (byte)0x80; 56 57 public static final byte INTEGER = ASN_UNIVERSAL | 0x02; 58 public static final byte INTEGER32 = ASN_UNIVERSAL | 0x02; 59 public static final byte BITSTRING = ASN_UNIVERSAL | 0x03; 60 public static final byte OCTETSTRING = ASN_UNIVERSAL | 0x04; 61 public static final byte NULL = ASN_UNIVERSAL | 0x05; 62 public static final byte OID = ASN_UNIVERSAL | 0x06; 63 public static final byte SEQUENCE = ASN_CONSTRUCTOR | 0x10; 64 65 public static final byte IPADDRESS = ASN_APPLICATION | 0x00; 66 public static final byte COUNTER = ASN_APPLICATION | 0x01; 67 public static final byte COUNTER32 = ASN_APPLICATION | 0x01; 68 public static final byte GAUGE = ASN_APPLICATION | 0x02; 69 public static final byte GAUGE32 = ASN_APPLICATION | 0x02; 70 public static final byte TIMETICKS = ASN_APPLICATION | 0x03; 71 public static final byte OPAQUE = ASN_APPLICATION | 0x04; 72 public static final byte COUNTER64 = ASN_APPLICATION | 0x06; 73 74 public static final int NOSUCHOBJECT = 0x80; 75 public static final int NOSUCHINSTANCE = 0x81; 76 public static final int ENDOFMIBVIEW = 0x82; 77 78 private static final int LENMASK = 0x0ff; 79 public static final int MAX_OID_LENGTH = 127; 80 81 private static boolean checkSequenceLength = true; 82 private static boolean checkValueLength = true; 83 84 91 public static class MutableByte { 92 byte value = 0; 93 94 public MutableByte() { } 95 96 public MutableByte(byte value) { 97 setValue(value); 98 } 99 100 public void setValue(byte value) { 101 this.value = value; 102 } 103 104 public byte getValue() { 105 return value; 106 } 107 } 108 109 120 public static final void encodeHeader(OutputStream os, int type, int length) 121 throws IOException 122 { 123 os.write(type); 124 encodeLength(os, length); 125 } 126 127 140 public static final void encodeHeader(OutputStream os, int type, int length, 141 int numBytesLength) 142 throws IOException 143 { 144 os.write(type); 145 encodeLength(os, length, numBytesLength); 146 } 147 148 156 public static final int getBERLengthOfLength(int length) { 157 if (length < 0) { 158 return 5; 159 } 160 else if (length < 0x80){ 161 return 1; 162 } 163 else if (length <= 0xFF){ 164 return 2; 165 } 166 else if (length <= 0xFFFF) { 167 return 3; 168 } 169 else if (length <= 0xFFFFFF) { 170 return 4; 171 } 172 return 5; 173 } 174 175 183 public static final void encodeLength(OutputStream os, int length) 184 throws IOException 185 { 186 if (length < 0) { 187 os.write(0x04 | ASN_LONG_LEN); 188 os.write((length >> 24) & 0xFF); 189 os.write((length >> 16) & 0xFF); 190 os.write((length >> 8) & 0xFF); 191 os.write(length & 0xFF); 192 } 193 else if (length < 0x80){ 194 os.write(length); 195 } 196 else if (length <= 0xFF){ 197 os.write((0x01 | ASN_LONG_LEN)); 198 os.write(length); 199 } 200 else if (length <= 0xFFFF) { 201 os.write(0x02 | ASN_LONG_LEN); 202 os.write((length >> 8) & 0xFF); 203 os.write(length & 0xFF); 204 } 205 else if (length <= 0xFFFFFF) { 206 os.write(0x03 | ASN_LONG_LEN); 207 os.write((length >> 16) & 0xFF); 208 os.write((length >> 8) & 0xFF); 209 os.write(length & 0xFF); 210 } 211 else { 212 os.write(0x04 | ASN_LONG_LEN); 213 os.write((length >> 24) & 0xFF); 214 os.write((length >> 16) & 0xFF); 215 os.write((length >> 8) & 0xFF); 216 os.write(length & 0xFF); 217 } 218 } 219 220 231 public static final void encodeLength(OutputStream os, int length, 232 int numLengthBytes) 233 throws IOException 234 { 235 os.write((numLengthBytes | ASN_LONG_LEN)); 236 for (int i=(numLengthBytes-1)*8; i>=0; i-=8) { 237 os.write(((length >> i) & 0xFF)); 238 } 239 } 240 241 251 public static final void encodeInteger(OutputStream os, byte type, int value) 252 throws IOException 253 { 254 int integer = value; 255 int mask; 256 int intsize = 4; 257 258 264 mask = 0x1FF << ((8 * 3) - 1); 265 266 while((((integer & mask) == 0) || ((integer & mask) == mask)) 267 && intsize > 1){ 268 intsize--; 269 integer <<= 8; 270 } 271 encodeHeader(os, type, intsize); 272 mask = 0xFF << (8 * 3); 273 274 while ((intsize--) > 0){ 275 os.write(((integer & mask) >> (8 * 3))); 276 integer <<= 8; 277 } 278 } 279 280 291 public static final void encodeUnsignedInteger(OutputStream os, byte type, long value) 292 throws IOException 293 { 294 int len = 1; 296 if ((( value >> 24) & LENMASK) != 0) { 297 len = 4; 298 } 299 else if ((( value >> 16) & LENMASK) !=0) { 300 len = 3; 301 } 302 else if ((( value >> 8) & LENMASK) !=0) { 303 len = 2; 304 } 305 if ((( value >> (8 * (len -1))) & 0x080) !=0) { 308 len++; 309 } 310 311 encodeHeader(os, type, len); 314 if (len == 5) { 316 os.write(0); 317 for (int x=1; x<len; x++) { 318 os.write((int) (value >> (8 * (4 - x) & LENMASK))); 319 } 320 } 321 else 322 { 323 for (int x=0; x<len; x++) { 324 os.write((int) (value >> (8 * ((len - 1) - x) & LENMASK))); 325 } 326 } 327 } 328 329 339 public static final void encodeString(OutputStream os, byte type, byte[] string) 340 throws IOException 341 { 342 348 encodeHeader(os, type, string.length); 349 os.write(string); 351 } 352 353 366 public static final void encodeSequence(OutputStream os, byte type, int length) 367 throws IOException 368 { 369 os.write(type); 370 encodeLength(os, length); 371 } 372 373 380 public static final int getOIDLength(int[] value) { 381 int length = 1; for (int i = 2; i < value.length; i++) { 383 long v = value[i] & 0xFFFFFFFFL; 384 if (v < 0x80) { length += 1; 386 } 387 else if (v < 0x4000) { length += 2; 389 } 390 else if (v < 0x200000) { length += 3; 392 } 393 else if (v < 0x10000000) { length += 4; 395 } 396 else { length += 5; 398 } 399 } 400 return length; 401 } 402 403 414 public static final void encodeOID(OutputStream os, byte type, int[] oid) 415 throws IOException 416 { 417 423 encodeHeader(os, type, getOIDLength(oid)); 424 425 int encodedLength = oid.length; 426 int rpos = 0; 427 428 if (oid.length < 2){ 429 os.write(0); 430 encodedLength = 0; 431 } 432 else { 433 os.write(((oid[1] + (oid[0] * 40)) & 0xFF)); 434 encodedLength -= 2; 435 rpos = 2; 436 } 437 438 while (encodedLength-- > 0){ 439 long subid = (oid[rpos++] & 0xFFFFFFFFL); 440 if (subid < 127) { 441 os.write((int)subid & 0xFF); 442 } 443 else { 444 long mask = 0x7F; 445 long bits = 0; 446 447 448 for (long testmask = 0x7F, testbits = 0; testmask != 0; 449 testmask <<= 7, testbits += 7) { 450 if ((subid & testmask) > 0) { 451 mask = testmask; 452 bits = testbits; 453 } 454 } 455 456 for (; mask != 0x7F; mask >>= 7, bits -= 7){ 457 458 if (mask == 0x1E00000) { 459 mask = 0xFE00000; 460 } 461 os.write((int)(((subid & mask) >> bits) | ASN_BIT8)); 462 } 463 os.write((int)(subid & mask)); 464 } 465 } 466 } 467 468 469 public static final void encodeUnsignedInt64(OutputStream os, byte type, long value) 470 throws IOException 471 { 472 int len; 473 479 for (len = 8; len > 1; len--) { 480 if (((value >> (8 * (len - 1))) & 0xFF) != 0) { 481 break; 482 } 483 } 484 if ((( value >> (8 * (len -1))) & 0x080) !=0) { 485 len++; 486 } 487 encodeHeader(os, type, len); 488 if (len == 9) { 489 os.write(0); 490 len--; 491 } 492 for (int x=0; x<len; x++) { 493 os.write((int) (value >> (8 * ((len - 1) - x) & LENMASK))); 494 } 495 } 496 497 505 public static final int decodeLength(BERInputStream is) 506 throws IOException 507 { 508 return decodeLength(is, true); 509 } 510 511 521 public static final int decodeLength(BERInputStream is, boolean checkLength) 522 throws IOException 523 { 524 int length = 0; 525 int lengthbyte = is.read(); 526 527 if ((lengthbyte & ASN_LONG_LEN) > 0) { 528 lengthbyte &= ~ASN_LONG_LEN; 529 if (lengthbyte == 0){ 530 throw new IOException ("Indefinite lengths are not supported"); 531 } 532 if (lengthbyte > 4){ 533 throw new IOException ("Data length > 4 bytes are not supported!"); 534 } 535 for (int i=0; i<lengthbyte; i++) { 536 int l = is.read() & 0xFF; 537 length |= (l << (8*((lengthbyte-1)-i))); 538 } 539 if (length < 0) { 540 throw new IOException ("SNMP does not support data lengths > 2^31"); 541 } 542 } 543 else { 544 length = lengthbyte & 0xFF; 545 } 546 550 if (checkLength) { 551 checkLength(is, length); 552 } 553 return length; 554 } 555 556 577 public static final int decodeHeader(BERInputStream is, MutableByte type, 578 boolean checkLength) 579 throws IOException 580 { 581 582 byte t = (byte)is.read(); 583 if ((t & ASN_EXTENSION_ID) == ASN_EXTENSION_ID) { 584 throw new IOException ("Cannot process extension IDs"+ 585 getPositionMessage(is)); 586 } 587 type.setValue(t); 588 return decodeLength(is, checkLength); 589 } 590 591 610 public static final int decodeHeader(BERInputStream is, MutableByte type) 611 throws IOException 612 { 613 return decodeHeader(is, type, true); 614 } 615 616 public static final int decodeInteger(BERInputStream is, MutableByte type) 617 throws IOException 618 { 619 int length; 620 int value = 0; 621 622 type.setValue((byte)is.read()); 623 624 if ((type.value != 0x02) && (type.value != 0x43) && 625 (type.value != 0x41)) { 626 throw new IOException ("Wrong ASN.1 type. Not an integer: "+type.value+ 627 getPositionMessage(is)); 628 } 629 length = decodeLength(is); 630 if (length > 4) { 631 throw new IOException ("Length greater than 32bit are not supported "+ 632 " for integers: "+getPositionMessage(is)); 633 } 634 int b = is.read() & 0xFF; 635 if ((b & 0x80) > 0) { 636 value = -1; 637 } 638 while (length-- > 0) { 639 value = (value << 8) | b; 640 if (length > 0) { 641 b = is.read(); 642 } 643 } 644 return value; 645 } 646 647 private static String getPositionMessage(BERInputStream is) { 648 return " at position "+is.getPosition(); 649 } 650 651 public static final long decodeUnsignedInteger(BERInputStream is, MutableByte type) 652 throws IOException 653 { 654 int length; 655 long value = 0; 656 657 type.setValue((byte)is.read()); 659 if ((type.value != 0x02) && (type.value != 0x43) && 660 (type.value != 0x41) && (type.value != 0x42) && 661 (type.value != 0x47)) { 662 throw new IOException ("Wrong ASN.1 type. Not an unsigned integer: "+ 663 type.value+ 664 getPositionMessage(is)); 665 } 666 length = decodeLength(is); 668 669 int b = is.read(); 671 if ((length > 5) || ((length > 4) && (b != 0x00))) { 672 throw new IOException ("Only 32bit unsigned integers are supported"+ 673 getPositionMessage(is)); 674 } 675 676 if (b == 0x00) { 678 if (length > 1) { 679 b = is.read(); 680 } 681 length--; 682 } 683 684 for (int i=0; i<length; i++) { 686 value = (value << 8) | (b & 0xFF); 687 if (i+1<length) { 688 b = is.read(); 689 } 690 } 691 return value; 692 } 693 694 public static final byte[] decodeString(BERInputStream is, MutableByte type) 695 throws IOException 696 { 697 703 type.setValue((byte)is.read()); 705 if ((type.value != BER.OCTETSTRING) && (type.value != 0x24) && 706 (type.value != BER.IPADDRESS) && (type.value != BER.OPAQUE) && 707 (type.value != BER.BITSTRING) && 708 (type.value != 0x45)) { 709 throw new IOException ("Wrong ASN.1 type. Not a string: "+type.value+ 710 getPositionMessage(is)); 711 } 712 int length = decodeLength(is); 713 714 byte[] value = new byte[length]; 715 int pos = 0; 716 717 while ((pos < length) && (is.available()>0)) { 718 int read = is.read(value); 719 if (read > 0) { 720 pos += read; 721 } 722 else if (read < 0) { 723 throw new IOException ("Wrong string length "+read+" < "+length); 724 } 725 } 726 return value; 727 } 728 729 730 public static final int[] decodeOID(BERInputStream is, MutableByte type) 731 throws IOException 732 { 733 739 int subidentifier; 740 int length; 741 742 type.setValue((byte)is.read()); 744 if (type.value != 0x06) { 745 throw new IOException ("Wrong type. Not an OID: "+type.value+ 746 getPositionMessage(is)); 747 } 748 length = decodeLength(is); 749 750 int[] oid = new int[length+2]; 751 752 if (length == 0) { 753 oid[0] = oid[1] = 0; 754 } 755 int pos = 1; 756 while (length > 0){ 757 subidentifier = 0; 758 int b; 759 do { 760 int next = is.read(); 761 if (next < 0) { 762 throw new IOException ("Unexpected end of input stream" + 763 getPositionMessage(is)); 764 } 765 b = next & 0xFF; 766 subidentifier = (subidentifier << 7) + (b & ~ASN_BIT8); 767 length--; 768 } while ((length > 0) && ((b & ASN_BIT8) != 0)); 769 oid[pos++] = subidentifier; 770 } 771 772 778 subidentifier = oid[1]; 779 if (subidentifier == 0x2B){ 780 oid[0] = 1; 781 oid[1] = 3; 782 } 783 else { 784 oid[1] = (subidentifier % 40); 785 oid[0] = ((subidentifier - oid[1]) / 40); 786 } 787 if (pos < 2) { 788 pos = 2; 789 } 790 int[] value = new int[pos]; 791 System.arraycopy(oid, 0, value, 0, pos); 792 return value; 793 } 794 795 public static final void decodeNull(BERInputStream is, MutableByte type) 796 throws IOException 797 { 798 type.setValue((byte)(is.read() & 0xFF)); 800 if ((type.value != (byte)0x05) && (type.value != (byte)0x80) && 801 (type.value != (byte)0x81) && (type.value != (byte)0x82)) { 802 throw new IOException ("Wrong ASN.1 type. Is not null: " + type.value+ 803 getPositionMessage(is)); 804 } 805 int length = decodeLength(is); 806 if (length != 0) { 807 throw new IOException ("Invalid Null encoding, length is not zero: "+ 808 length+getPositionMessage(is)); 809 } 810 } 811 812 public static final long decodeUnsignedInt64(BERInputStream is, MutableByte type) 813 throws IOException 814 { 815 type.setValue((byte)is.read()); 817 if ((type.value != 0x02) && (type.value != 0x46)) { 818 throw new IOException ("Wrong type. Not an integer 64: "+type.value+ 819 getPositionMessage(is)); 820 } 821 int length = decodeLength(is); 822 int b = is.read() & 0xFF; 823 if (length > 9) { 824 throw new IOException ("Invalid 64bit unsigned integer length: "+length+ 825 getPositionMessage(is)); 826 } 827 if (b == 0x00) { 829 if (length > 1) { 830 b = is.read(); 831 } 832 length--; 833 } 834 long value = 0; 835 for (int i=0; i<length; i++) { 837 value = (value << 8) | (b & 0xFF); 838 if (i+1<length) { 839 b = is.read(); 840 } 841 } 842 return value; 843 } 844 845 851 public static boolean isCheckSequenceLength() { 852 return checkSequenceLength; 853 } 854 855 861 public static void setCheckSequenceLength(boolean checkSequenceLen) { 862 checkSequenceLength = checkSequenceLen; 863 } 864 865 public static void checkSequenceLength(int expectedLength, 866 BERSerializable sequence) 867 throws IOException 868 { 869 if ((isCheckSequenceLength()) && 870 (expectedLength != sequence.getBERPayloadLength())) { 871 throw new IOException ("The actual length of the SEQUENCE object "+ 872 sequence.getClass().getName()+ 873 " is "+sequence.getBERPayloadLength()+", but "+ 874 expectedLength+" was expected"); 875 } 876 } 877 878 public static void checkSequenceLength(int expectedLength, int actualLength, 879 BERSerializable sequence) 880 throws IOException 881 { 882 if ((isCheckSequenceLength()) && 883 (expectedLength != actualLength)) { 884 throw new IOException ("The actual length of the SEQUENCE object "+ 885 sequence.getClass().getName()+ 886 " is "+actualLength+", but "+ 887 expectedLength+" was expected"); 888 } 889 } 890 891 901 private static void checkLength(BERInputStream is, int length) throws 902 IOException { 903 if (!checkValueLength) { 904 return; 905 } 906 if ((length < 0) || (length > is.getAvailableBytes())) { 907 throw new IOException ("The encoded length "+ 908 length+ 909 " exceeds the number of bytes left in input"+ 910 getPositionMessage(is)+ 911 " which actually is "+is.getAvailableBytes()); 912 } 913 } 914 915 public boolean isCheckValueLength() { 916 return checkValueLength; 917 } 918 919 public void setCheckValueLength(boolean checkValueLength) { 920 BER.checkValueLength = checkValueLength; 921 } 922 923 } 924 925 926 | Popular Tags |