net-snmp
5.4.1
|
00001 /* 00002 * Abstract Syntax Notation One, ASN.1 00003 * As defined in ISO/IS 8824 and ISO/IS 8825 00004 * This implements a subset of the above International Standards that 00005 * is sufficient to implement SNMP. 00006 * 00007 * Encodes abstract data types into a machine independent stream of bytes. 00008 * 00009 */ 00010 /********************************************************************** 00011 Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University 00012 00013 All Rights Reserved 00014 00015 Permission to use, copy, modify, and distribute this software and its 00016 documentation for any purpose and without fee is hereby granted, 00017 provided that the above copyright notice appear in all copies and that 00018 both that copyright notice and this permission notice appear in 00019 supporting documentation, and that the name of CMU not be 00020 used in advertising or publicity pertaining to distribution of the 00021 software without specific, written prior permission. 00022 00023 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 00024 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 00025 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 00026 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00027 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 00028 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00029 SOFTWARE. 00030 ******************************************************************/ 00156 #include <net-snmp/net-snmp-config.h> 00157 00158 #ifdef KINETICS 00159 #include "gw.h" 00160 #endif 00161 00162 #if HAVE_STRING_H 00163 #include <string.h> 00164 #else 00165 #include <strings.h> 00166 #endif 00167 00168 #include <sys/types.h> 00169 #include <stdio.h> 00170 #ifdef HAVE_STDLIB_H 00171 #include <stdlib.h> 00172 #endif 00173 #if HAVE_WINSOCK_H 00174 #include <winsock.h> 00175 #endif 00176 #if HAVE_NETINET_IN_H 00177 #include <netinet/in.h> 00178 #endif 00179 00180 #ifdef vms 00181 #include <in.h> 00182 #endif 00183 00184 #if HAVE_DMALLOC_H 00185 #include <dmalloc.h> 00186 #endif 00187 00188 #include <net-snmp/output_api.h> 00189 #include <net-snmp/utilities.h> 00190 00191 #include <net-snmp/library/asn1.h> 00192 #include <net-snmp/library/int64.h> 00193 #include <net-snmp/library/mib.h> 00194 00195 #ifndef NULL 00196 #define NULL 0 00197 #endif 00198 00199 #include <net-snmp/library/snmp_api.h> 00200 00201 #ifndef INT32_MAX 00202 # define INT32_MAX 2147483647 00203 #endif 00204 00205 #ifndef INT32_MIN 00206 # define INT32_MIN (0 - INT32_MAX - 1) 00207 #endif 00208 00209 00210 #if SIZEOF_LONG == 4 00211 # define CHECK_OVERFLOW_S(x,y) 00212 # define CHECK_OVERFLOW_U(x,y) 00213 #else 00214 # define CHECK_OVERFLOW_S(x,y) do { int trunc = 0; \ 00215 if (x > INT32_MAX) { \ 00216 trunc = 1; \ 00217 x &= 0xffffffff; \ 00218 } else if (x < INT32_MIN) { \ 00219 trunc = 1; \ 00220 x = 0 - (x & 0xffffffff); \ 00221 } \ 00222 if (trunc) \ 00223 snmp_log(LOG_ERR,"truncating signed value to 32 bits (%d)\n",y); \ 00224 } while(0) 00225 00226 # define CHECK_OVERFLOW_U(x,y) do { \ 00227 if (x > UINT32_MAX) { \ 00228 x &= 0xffffffff; \ 00229 snmp_log(LOG_ERR,"truncating unsigned value to 32 bits (%d)\n",y); \ 00230 } \ 00231 } while(0) 00232 #endif 00233 00242 static 00243 void 00244 _asn_size_err(const char *str, size_t wrongsize, size_t rightsize) 00245 { 00246 char ebuf[128]; 00247 00248 snprintf(ebuf, sizeof(ebuf), 00249 "%s size %lu: s/b %lu", str, 00250 (unsigned long)wrongsize, (unsigned long)rightsize); 00251 ebuf[ sizeof(ebuf)-1 ] = 0; 00252 ERROR_MSG(ebuf); 00253 } 00254 00263 static 00264 void 00265 _asn_length_err(const char *str, size_t wrongsize, size_t rightsize) 00266 { 00267 char ebuf[128]; 00268 00269 snprintf(ebuf, sizeof(ebuf), 00270 "%s length %lu too large: exceeds %lu", str, 00271 (unsigned long)wrongsize, (unsigned long)rightsize); 00272 ebuf[ sizeof(ebuf)-1 ] = 0; 00273 ERROR_MSG(ebuf); 00274 } 00275 00288 static 00289 int 00290 _asn_parse_length_check(const char *str, 00291 const u_char * bufp, const u_char * data, 00292 u_long plen, size_t dlen) 00293 { 00294 char ebuf[128]; 00295 size_t header_len; 00296 00297 if (bufp == NULL) { 00298 /* 00299 * error message is set 00300 */ 00301 return 1; 00302 } 00303 header_len = bufp - data; 00304 if (plen > 0x7fffffff || header_len > 0x7fffffff || 00305 ((size_t) plen + header_len) > dlen) { 00306 snprintf(ebuf, sizeof(ebuf), 00307 "%s: message overflow: %d len + %d delta > %d len", 00308 str, (int) plen, (int) header_len, (int) dlen); 00309 ebuf[ sizeof(ebuf)-1 ] = 0; 00310 ERROR_MSG(ebuf); 00311 return 1; 00312 } 00313 return 0; 00314 } 00315 00316 00328 static 00329 int 00330 _asn_build_header_check(const char *str, const u_char * data, 00331 size_t datalen, size_t typedlen) 00332 { 00333 char ebuf[128]; 00334 00335 if (data == NULL) { 00336 /* 00337 * error message is set 00338 */ 00339 return 1; 00340 } 00341 if (datalen < typedlen) { 00342 snprintf(ebuf, sizeof(ebuf), 00343 "%s: bad header, length too short: %lu < %lu", str, 00344 (unsigned long)datalen, (unsigned long)typedlen); 00345 ebuf[ sizeof(ebuf)-1 ] = 0; 00346 ERROR_MSG(ebuf); 00347 return 1; 00348 } 00349 return 0; 00350 } 00351 00363 static 00364 int 00365 _asn_realloc_build_header_check(const char *str, 00366 u_char ** pkt, 00367 const size_t * pkt_len, size_t typedlen) 00368 { 00369 char ebuf[128]; 00370 00371 if (pkt == NULL || *pkt == NULL) { 00372 /* 00373 * Error message is set. 00374 */ 00375 return 1; 00376 } 00377 00378 if (*pkt_len < typedlen) { 00379 snprintf(ebuf, sizeof(ebuf), 00380 "%s: bad header, length too short: %lu < %lu", str, 00381 (unsigned long)*pkt_len, (unsigned long)typedlen); 00382 ebuf[ sizeof(ebuf)-1 ] = 0; 00383 ERROR_MSG(ebuf); 00384 return 1; 00385 } 00386 return 0; 00387 } 00388 00398 int 00399 asn_check_packet(u_char * pkt, size_t len) 00400 { 00401 u_long asn_length; 00402 00403 if (len < 2) 00404 return 0; /* always too short */ 00405 00406 if (*pkt != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) 00407 return -1; /* wrong type */ 00408 00409 if (*(pkt + 1) & 0x80) { 00410 /* 00411 * long length 00412 */ 00413 if ((int) len < (int) (*(pkt + 1) & ~0x80) + 2) 00414 return 0; /* still to short, incomplete length */ 00415 asn_parse_length(pkt + 1, &asn_length); 00416 return (asn_length + 2 + (*(pkt + 1) & ~0x80)); 00417 } else { 00418 /* 00419 * short length 00420 */ 00421 return (*(pkt + 1) + 2); 00422 } 00423 } 00424 00425 static 00426 int 00427 _asn_bitstring_check(const char *str, size_t asn_length, u_char datum) 00428 { 00429 char ebuf[128]; 00430 00431 if (asn_length < 1) { 00432 snprintf(ebuf, sizeof(ebuf), 00433 "%s: length %d too small", str, (int) asn_length); 00434 ebuf[ sizeof(ebuf)-1 ] = 0; 00435 ERROR_MSG(ebuf); 00436 return 1; 00437 } 00438 /* 00439 * if (datum > 7){ 00440 * sprintf(ebuf,"%s: datum %d >7: too large", str, (int)(datum)); 00441 * ERROR_MSG(ebuf); 00442 * return 1; 00443 * } 00444 */ 00445 return 0; 00446 } 00447 00469 u_char * 00470 asn_parse_int(u_char * data, 00471 size_t * datalength, 00472 u_char * type, long *intp, size_t intsize) 00473 { 00474 /* 00475 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 00476 */ 00477 static const char *errpre = "parse int"; 00478 register u_char *bufp = data; 00479 u_long asn_length; 00480 register long value = 0; 00481 00482 if (intsize != sizeof(long)) { 00483 _asn_size_err(errpre, intsize, sizeof(long)); 00484 return NULL; 00485 } 00486 *type = *bufp++; 00487 bufp = asn_parse_length(bufp, &asn_length); 00488 if (_asn_parse_length_check 00489 (errpre, bufp, data, asn_length, *datalength)) 00490 return NULL; 00491 00492 if ((size_t) asn_length > intsize) { 00493 _asn_length_err(errpre, (size_t) asn_length, intsize); 00494 return NULL; 00495 } 00496 00497 *datalength -= (int) asn_length + (bufp - data); 00498 if (*bufp & 0x80) 00499 value = -1; /* integer is negative */ 00500 00501 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 00502 00503 while (asn_length--) 00504 value = (value << 8) | *bufp++; 00505 00506 CHECK_OVERFLOW_S(value,1); 00507 00508 DEBUGMSG(("dumpv_recv", " Integer:\t%ld (0x%.2X)\n", value, value)); 00509 00510 *intp = value; 00511 return bufp; 00512 } 00513 00514 00536 u_char * 00537 asn_parse_unsigned_int(u_char * data, 00538 size_t * datalength, 00539 u_char * type, u_long * intp, size_t intsize) 00540 { 00541 /* 00542 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 00543 */ 00544 static const char *errpre = "parse uint"; 00545 register u_char *bufp = data; 00546 u_long asn_length; 00547 register u_long value = 0; 00548 00549 if (intsize != sizeof(long)) { 00550 _asn_size_err(errpre, intsize, sizeof(long)); 00551 return NULL; 00552 } 00553 *type = *bufp++; 00554 bufp = asn_parse_length(bufp, &asn_length); 00555 if (_asn_parse_length_check 00556 (errpre, bufp, data, asn_length, *datalength)) 00557 return NULL; 00558 00559 if (((int) asn_length > (intsize + 1)) || 00560 (((int) asn_length == intsize + 1) && *bufp != 0x00)) { 00561 _asn_length_err(errpre, (size_t) asn_length, intsize); 00562 return NULL; 00563 } 00564 *datalength -= (int) asn_length + (bufp - data); 00565 if (*bufp & 0x80) 00566 value = ~value; /* integer is negative */ 00567 00568 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 00569 00570 while (asn_length--) 00571 value = (value << 8) | *bufp++; 00572 00573 CHECK_OVERFLOW_U(value,2); 00574 00575 DEBUGMSG(("dumpv_recv", " UInteger:\t%ld (0x%.2X)\n", value, value)); 00576 00577 *intp = value; 00578 return bufp; 00579 } 00580 00581 00605 u_char * 00606 asn_build_int(u_char * data, 00607 size_t * datalength, u_char type, const long *intp, size_t intsize) 00608 { 00609 /* 00610 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 00611 */ 00612 static const char *errpre = "build int"; 00613 register long integer; 00614 register u_long mask; 00615 #ifndef NETSNMP_NO_DEBUGGING 00616 u_char *initdatap = data; 00617 #endif 00618 00619 if (intsize != sizeof(long)) { 00620 _asn_size_err(errpre, intsize, sizeof(long)); 00621 return NULL; 00622 } 00623 integer = *intp; 00624 CHECK_OVERFLOW_S(integer,3); 00625 /* 00626 * Truncate "unnecessary" bytes off of the most significant end of this 00627 * 2's complement integer. There should be no sequence of 9 00628 * consecutive 1's or 0's at the most significant end of the 00629 * integer. 00630 */ 00631 mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1); 00632 /* 00633 * mask is 0xFF800000 on a big-endian machine 00634 */ 00635 while ((((integer & mask) == 0) || ((integer & mask) == mask)) 00636 && intsize > 1) { 00637 intsize--; 00638 integer <<= 8; 00639 } 00640 data = asn_build_header(data, datalength, type, intsize); 00641 if (_asn_build_header_check(errpre, data, *datalength, intsize)) 00642 return NULL; 00643 00644 *datalength -= intsize; 00645 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); 00646 /* 00647 * mask is 0xFF000000 on a big-endian machine 00648 */ 00649 while (intsize--) { 00650 *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(long) - 1))); 00651 integer <<= 8; 00652 } 00653 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 00654 DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2X)\n", *intp, *intp)); 00655 return data; 00656 } 00657 00658 00659 00683 u_char * 00684 asn_build_unsigned_int(u_char * data, 00685 size_t * datalength, 00686 u_char type, const u_long * intp, size_t intsize) 00687 { 00688 /* 00689 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 00690 */ 00691 static const char *errpre = "build uint"; 00692 register u_long integer; 00693 register u_long mask; 00694 int add_null_byte = 0; 00695 #ifndef NETSNMP_NO_DEBUGGING 00696 u_char *initdatap = data; 00697 #endif 00698 00699 if (intsize != sizeof(long)) { 00700 _asn_size_err(errpre, intsize, sizeof(long)); 00701 return NULL; 00702 } 00703 integer = *intp; 00704 CHECK_OVERFLOW_U(integer,4); 00705 00706 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); 00707 /* 00708 * mask is 0xFF000000 on a big-endian machine 00709 */ 00710 if ((u_char) ((integer & mask) >> (8 * (sizeof(long) - 1))) & 0x80) { 00711 /* 00712 * if MSB is set 00713 */ 00714 add_null_byte = 1; 00715 intsize++; 00716 } else { 00717 /* 00718 * Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer. 00719 * There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the 00720 * integer. 00721 */ 00722 mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1); 00723 /* 00724 * mask is 0xFF800000 on a big-endian machine 00725 */ 00726 while ((((integer & mask) == 0) || ((integer & mask) == mask)) 00727 && intsize > 1) { 00728 intsize--; 00729 integer <<= 8; 00730 } 00731 } 00732 data = asn_build_header(data, datalength, type, intsize); 00733 if (_asn_build_header_check(errpre, data, *datalength, intsize)) 00734 return NULL; 00735 00736 *datalength -= intsize; 00737 if (add_null_byte == 1) { 00738 *data++ = '\0'; 00739 intsize--; 00740 } 00741 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); 00742 /* 00743 * mask is 0xFF000000 on a big-endian machine 00744 */ 00745 while (intsize--) { 00746 *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(long) - 1))); 00747 integer <<= 8; 00748 } 00749 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 00750 DEBUGMSG(("dumpv_send", " UInteger:\t%ld (0x%.2X)\n", *intp, *intp)); 00751 return data; 00752 } 00753 00754 00783 u_char * 00784 asn_parse_string(u_char * data, 00785 size_t * datalength, 00786 u_char * type, u_char * str, size_t * strlength) 00787 { 00788 static const char *errpre = "parse string"; 00789 u_char *bufp = data; 00790 u_long asn_length; 00791 00792 *type = *bufp++; 00793 bufp = asn_parse_length(bufp, &asn_length); 00794 if (_asn_parse_length_check 00795 (errpre, bufp, data, asn_length, *datalength)) { 00796 return NULL; 00797 } 00798 00799 if ((int) asn_length > *strlength) { 00800 _asn_length_err(errpre, (size_t) asn_length, *strlength); 00801 return NULL; 00802 } 00803 00804 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 00805 00806 memmove(str, bufp, asn_length); 00807 if (*strlength > (int) asn_length) 00808 str[asn_length] = 0; 00809 *strlength = (int) asn_length; 00810 *datalength -= (int) asn_length + (bufp - data); 00811 00812 DEBUGIF("dumpv_recv") { 00813 u_char *buf = (u_char *) malloc(1 + asn_length); 00814 size_t l = (buf != NULL) ? (1 + asn_length) : 0, ol = 0; 00815 00816 if (sprint_realloc_asciistring 00817 (&buf, &l, &ol, 1, str, asn_length)) { 00818 DEBUGMSG(("dumpv_recv", " String:\t%s\n", buf)); 00819 } else { 00820 if (buf == NULL) { 00821 DEBUGMSG(("dumpv_recv", " String:\t[TRUNCATED]\n")); 00822 } else { 00823 DEBUGMSG(("dumpv_recv", " String:\t%s [TRUNCATED]\n", 00824 buf)); 00825 } 00826 } 00827 if (buf != NULL) { 00828 free(buf); 00829 } 00830 } 00831 00832 return bufp + asn_length; 00833 } 00834 00835 00858 u_char * 00859 asn_build_string(u_char * data, 00860 size_t * datalength, 00861 u_char type, const u_char * str, size_t strlength) 00862 { 00863 /* 00864 * ASN.1 octet string ::= primstring | cmpdstring 00865 * primstring ::= 0x04 asnlength byte {byte}* 00866 * cmpdstring ::= 0x24 asnlength string {string}* 00867 * This code will never send a compound string. 00868 */ 00869 #ifndef NETSNMP_NO_DEBUGGING 00870 u_char *initdatap = data; 00871 #endif 00872 data = asn_build_header(data, datalength, type, strlength); 00873 if (_asn_build_header_check 00874 ("build string", data, *datalength, strlength)) 00875 return NULL; 00876 00877 if (strlength) { 00878 if (str == NULL) { 00879 memset(data, 0, strlength); 00880 } else { 00881 memmove(data, str, strlength); 00882 } 00883 } 00884 *datalength -= strlength; 00885 DEBUGDUMPSETUP("send", initdatap, data - initdatap + strlength); 00886 DEBUGIF("dumpv_send") { 00887 u_char *buf = (u_char *) malloc(1 + strlength); 00888 size_t l = (buf != NULL) ? (1 + strlength) : 0, ol = 0; 00889 00890 if (sprint_realloc_asciistring 00891 (&buf, &l, &ol, 1, str, strlength)) { 00892 DEBUGMSG(("dumpv_send", " String:\t%s\n", buf)); 00893 } else { 00894 if (buf == NULL) { 00895 DEBUGMSG(("dumpv_send", " String:\t[TRUNCATED]\n")); 00896 } else { 00897 DEBUGMSG(("dumpv_send", " String:\t%s [TRUNCATED]\n", 00898 buf)); 00899 } 00900 } 00901 if (buf != NULL) { 00902 free(buf); 00903 } 00904 } 00905 return data + strlength; 00906 } 00907 00908 00909 00929 u_char * 00930 asn_parse_header(u_char * data, size_t * datalength, u_char * type) 00931 { 00932 register u_char *bufp; 00933 u_long asn_length; 00934 00935 if (!data || !datalength || !type) { 00936 ERROR_MSG("parse header: NULL pointer"); 00937 return NULL; 00938 } 00939 bufp = data; 00940 /* 00941 * this only works on data types < 30, i.e. no extension octets 00942 */ 00943 if (IS_EXTENSION_ID(*bufp)) { 00944 ERROR_MSG("can't process ID >= 30"); 00945 return NULL; 00946 } 00947 *type = *bufp; 00948 bufp = asn_parse_length(bufp + 1, &asn_length); 00949 00950 if (_asn_parse_length_check 00951 ("parse header", bufp, data, asn_length, *datalength)) 00952 return NULL; 00953 00954 #ifdef DUMP_PRINT_HEADERS 00955 DEBUGDUMPSETUP("recv", data, (bufp - data)); 00956 DEBUGMSG(("dumpv_recv", " Header: 0x%.2X, len = %d (0x%X)\n", *data, 00957 asn_length, asn_length)); 00958 #else 00959 /* 00960 * DEBUGMSGHEXTLI(("recv",data,(bufp-data))); 00961 * DEBUGMSG(("dumpH_recv","\n")); 00962 */ 00963 #endif 00964 00965 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00966 00967 if ((*type == ASN_OPAQUE) && (*bufp == ASN_OPAQUE_TAG1)) { 00968 00969 /* 00970 * check if 64-but counter 00971 */ 00972 switch (*(bufp + 1)) { 00973 case ASN_OPAQUE_COUNTER64: 00974 case ASN_OPAQUE_U64: 00975 case ASN_OPAQUE_FLOAT: 00976 case ASN_OPAQUE_DOUBLE: 00977 case ASN_OPAQUE_I64: 00978 *type = *(bufp + 1); 00979 break; 00980 00981 default: 00982 /* 00983 * just an Opaque 00984 */ 00985 *datalength = (int) asn_length; 00986 return bufp; 00987 } 00988 /* 00989 * value is encoded as special format 00990 */ 00991 bufp = asn_parse_length(bufp + 2, &asn_length); 00992 if (_asn_parse_length_check("parse opaque header", bufp, data, 00993 asn_length, *datalength)) 00994 return NULL; 00995 } 00996 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 00997 00998 *datalength = (int) asn_length; 00999 01000 return bufp; 01001 } 01002 01017 u_char * 01018 asn_parse_sequence(u_char * data, size_t * datalength, u_char * type, u_char expected_type, /* must be this type */ 01019 const char *estr) 01020 { /* error message prefix */ 01021 data = asn_parse_header(data, datalength, type); 01022 if (data && (*type != expected_type)) { 01023 char ebuf[128]; 01024 snprintf(ebuf, sizeof(ebuf), 01025 "%s header type %02X: s/b %02X", estr, 01026 (u_char) * type, (u_char) expected_type); 01027 ebuf[ sizeof(ebuf)-1 ] = 0; 01028 ERROR_MSG(ebuf); 01029 return NULL; 01030 } 01031 return data; 01032 } 01033 01034 01035 01058 u_char * 01059 asn_build_header(u_char * data, 01060 size_t * datalength, u_char type, size_t length) 01061 { 01062 char ebuf[128]; 01063 01064 if (*datalength < 1) { 01065 snprintf(ebuf, sizeof(ebuf), 01066 "bad header length < 1 :%lu, %lu", 01067 (unsigned long)*datalength, (unsigned long)length); 01068 ebuf[ sizeof(ebuf)-1 ] = 0; 01069 ERROR_MSG(ebuf); 01070 return NULL; 01071 } 01072 *data++ = type; 01073 (*datalength)--; 01074 return asn_build_length(data, datalength, length); 01075 } 01076 01100 u_char * 01101 asn_build_sequence(u_char * data, 01102 size_t * datalength, u_char type, size_t length) 01103 { 01104 static const char *errpre = "build seq"; 01105 char ebuf[128]; 01106 01107 if (*datalength < 4) { 01108 snprintf(ebuf, sizeof(ebuf), 01109 "%s: length %d < 4: PUNT", errpre, 01110 (int) *datalength); 01111 ebuf[ sizeof(ebuf)-1 ] = 0; 01112 ERROR_MSG(ebuf); 01113 return NULL; 01114 } 01115 *datalength -= 4; 01116 *data++ = type; 01117 *data++ = (u_char) (0x02 | ASN_LONG_LEN); 01118 *data++ = (u_char) ((length >> 8) & 0xFF); 01119 *data++ = (u_char) (length & 0xFF); 01120 return data; 01121 } 01122 01140 u_char * 01141 asn_parse_length(u_char * data, u_long * length) 01142 { 01143 static const char *errpre = "parse length"; 01144 char ebuf[128]; 01145 register u_char lengthbyte; 01146 01147 if (!data || !length) { 01148 ERROR_MSG("parse length: NULL pointer"); 01149 return NULL; 01150 } 01151 lengthbyte = *data; 01152 01153 if (lengthbyte & ASN_LONG_LEN) { 01154 lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */ 01155 if (lengthbyte == 0) { 01156 snprintf(ebuf, sizeof(ebuf), 01157 "%s: indefinite length not supported", errpre); 01158 ebuf[ sizeof(ebuf)-1 ] = 0; 01159 ERROR_MSG(ebuf); 01160 return NULL; 01161 } 01162 if (lengthbyte > sizeof(long)) { 01163 snprintf(ebuf, sizeof(ebuf), 01164 "%s: data length %d > %lu not supported", errpre, 01165 lengthbyte, (unsigned long)sizeof(long)); 01166 ebuf[ sizeof(ebuf)-1 ] = 0; 01167 ERROR_MSG(ebuf); 01168 return NULL; 01169 } 01170 data++; 01171 *length = 0; /* protect against short lengths */ 01172 while (lengthbyte--) { 01173 *length <<= 8; 01174 *length |= *data++; 01175 } 01176 if ((long) *length < 0) { 01177 snprintf(ebuf, sizeof(ebuf), 01178 "%s: negative data length %ld\n", errpre, 01179 (long) *length); 01180 ebuf[ sizeof(ebuf)-1 ] = 0; 01181 ERROR_MSG(ebuf); 01182 return NULL; 01183 } 01184 return data; 01185 } else { /* short asnlength */ 01186 *length = (long) lengthbyte; 01187 return data + 1; 01188 } 01189 } 01190 01211 u_char * 01212 asn_build_length(u_char * data, size_t * datalength, size_t length) 01213 { 01214 static const char *errpre = "build length"; 01215 char ebuf[128]; 01216 01217 u_char *start_data = data; 01218 01219 /* 01220 * no indefinite lengths sent 01221 */ 01222 if (length < 0x80) { 01223 if (*datalength < 1) { 01224 snprintf(ebuf, sizeof(ebuf), 01225 "%s: bad length < 1 :%lu, %lu", errpre, 01226 (unsigned long)*datalength, (unsigned long)length); 01227 ebuf[ sizeof(ebuf)-1 ] = 0; 01228 ERROR_MSG(ebuf); 01229 return NULL; 01230 } 01231 *data++ = (u_char) length; 01232 } else if (length <= 0xFF) { 01233 if (*datalength < 2) { 01234 snprintf(ebuf, sizeof(ebuf), 01235 "%s: bad length < 2 :%lu, %lu", errpre, 01236 (unsigned long)*datalength, (unsigned long)length); 01237 ebuf[ sizeof(ebuf)-1 ] = 0; 01238 ERROR_MSG(ebuf); 01239 return NULL; 01240 } 01241 *data++ = (u_char) (0x01 | ASN_LONG_LEN); 01242 *data++ = (u_char) length; 01243 } else { /* 0xFF < length <= 0xFFFF */ 01244 if (*datalength < 3) { 01245 snprintf(ebuf, sizeof(ebuf), 01246 "%s: bad length < 3 :%lu, %lu", errpre, 01247 (unsigned long)*datalength, (unsigned long)length); 01248 ebuf[ sizeof(ebuf)-1 ] = 0; 01249 ERROR_MSG(ebuf); 01250 return NULL; 01251 } 01252 *data++ = (u_char) (0x02 | ASN_LONG_LEN); 01253 *data++ = (u_char) ((length >> 8) & 0xFF); 01254 *data++ = (u_char) (length & 0xFF); 01255 } 01256 *datalength -= (data - start_data); 01257 return data; 01258 01259 } 01260 01286 u_char * 01287 asn_parse_objid(u_char * data, 01288 size_t * datalength, 01289 u_char * type, oid * objid, size_t * objidlength) 01290 { 01291 /* 01292 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* 01293 * subidentifier ::= {leadingbyte}* lastbyte 01294 * leadingbyte ::= 1 7bitvalue 01295 * lastbyte ::= 0 7bitvalue 01296 */ 01297 register u_char *bufp = data; 01298 register oid *oidp = objid + 1; 01299 register u_long subidentifier; 01300 register long length; 01301 u_long asn_length; 01302 01303 *type = *bufp++; 01304 bufp = asn_parse_length(bufp, &asn_length); 01305 if (_asn_parse_length_check("parse objid", bufp, data, 01306 asn_length, *datalength)) 01307 return NULL; 01308 01309 *datalength -= (int) asn_length + (bufp - data); 01310 01311 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 01312 01313 /* 01314 * Handle invalid object identifier encodings of the form 06 00 robustly 01315 */ 01316 if (asn_length == 0) 01317 objid[0] = objid[1] = 0; 01318 01319 length = asn_length; 01320 (*objidlength)--; /* account for expansion of first byte */ 01321 01322 while (length > 0 && (*objidlength)-- > 0) { 01323 subidentifier = 0; 01324 do { /* shift and add in low order 7 bits */ 01325 subidentifier = 01326 (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8); 01327 length--; 01328 } while (*(u_char *) bufp++ & ASN_BIT8); /* last byte has high bit clear */ 01329 01330 #if defined(EIGHTBIT_SUBIDS) || (SIZEOF_LONG != 4) 01331 if (subidentifier > (u_long) MAX_SUBID) { 01332 ERROR_MSG("subidentifier too large"); 01333 return NULL; 01334 } 01335 #endif 01336 *oidp++ = (oid) subidentifier; 01337 } 01338 01339 if (0 != length) { 01340 ERROR_MSG("OID length exceeds buffer size"); 01341 return NULL; 01342 } 01343 01344 /* 01345 * The first two subidentifiers are encoded into the first component 01346 * with the value (X * 40) + Y, where: 01347 * X is the value of the first subidentifier. 01348 * Y is the value of the second subidentifier. 01349 */ 01350 subidentifier = (u_long) objid[1]; 01351 if (subidentifier == 0x2B) { 01352 objid[0] = 1; 01353 objid[1] = 3; 01354 } else { 01355 if (subidentifier < 40) { 01356 objid[0] = 0; 01357 objid[1] = subidentifier; 01358 } else if (subidentifier < 80) { 01359 objid[0] = 1; 01360 objid[1] = subidentifier - 40; 01361 } else { 01362 objid[0] = 2; 01363 objid[1] = subidentifier - 80; 01364 } 01365 } 01366 01367 *objidlength = (int) (oidp - objid); 01368 01369 DEBUGMSG(("dumpv_recv", " ObjID: ")); 01370 DEBUGMSGOID(("dumpv_recv", objid, *objidlength)); 01371 DEBUGMSG(("dumpv_recv", "\n")); 01372 return bufp; 01373 } 01374 01398 u_char * 01399 asn_build_objid(u_char * data, 01400 size_t * datalength, 01401 u_char type, oid * objid, size_t objidlength) 01402 { 01403 /* 01404 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* 01405 * subidentifier ::= {leadingbyte}* lastbyte 01406 * leadingbyte ::= 1 7bitvalue 01407 * lastbyte ::= 0 7bitvalue 01408 */ 01409 size_t asnlength; 01410 register oid *op = objid; 01411 u_char objid_size[MAX_OID_LEN]; 01412 register u_long objid_val; 01413 u_long first_objid_val; 01414 register int i; 01415 #ifndef NETSNMP_NO_DEBUGGING 01416 u_char *initdatap = data; 01417 #endif 01418 01419 /* 01420 * check if there are at least 2 sub-identifiers 01421 */ 01422 if (objidlength == 0) { 01423 /* 01424 * there are not, so make OID have two with value of zero 01425 */ 01426 objid_val = 0; 01427 objidlength = 2; 01428 } else if (objid[0] > 2) { 01429 ERROR_MSG("build objid: bad first subidentifier"); 01430 return NULL; 01431 } else if (objidlength == 1) { 01432 /* 01433 * encode the first value 01434 */ 01435 objid_val = (op[0] * 40); 01436 objidlength = 2; 01437 op++; 01438 } else { 01439 /* 01440 * combine the first two values 01441 */ 01442 if ((op[1] > 40) && 01443 (op[0] < 2)) { 01444 ERROR_MSG("build objid: bad second subidentifier"); 01445 return NULL; 01446 } 01447 objid_val = (op[0] * 40) + op[1]; 01448 op += 2; 01449 } 01450 first_objid_val = objid_val; 01451 01452 /* 01453 * ditch illegal calls now 01454 */ 01455 if (objidlength > MAX_OID_LEN) 01456 return NULL; 01457 01458 /* 01459 * calculate the number of bytes needed to store the encoded value 01460 */ 01461 for (i = 1, asnlength = 0;;) { 01462 01463 CHECK_OVERFLOW_U(objid_val,5); 01464 if (objid_val < (unsigned) 0x80) { 01465 objid_size[i] = 1; 01466 asnlength += 1; 01467 } else if (objid_val < (unsigned) 0x4000) { 01468 objid_size[i] = 2; 01469 asnlength += 2; 01470 } else if (objid_val < (unsigned) 0x200000) { 01471 objid_size[i] = 3; 01472 asnlength += 3; 01473 } else if (objid_val < (unsigned) 0x10000000) { 01474 objid_size[i] = 4; 01475 asnlength += 4; 01476 } else { 01477 objid_size[i] = 5; 01478 asnlength += 5; 01479 } 01480 i++; 01481 if (i >= (int) objidlength) 01482 break; 01483 objid_val = *op++; /* XXX - doesn't handle 2.X (X > 40) */ 01484 } 01485 01486 /* 01487 * store the ASN.1 tag and length 01488 */ 01489 data = asn_build_header(data, datalength, type, asnlength); 01490 if (_asn_build_header_check 01491 ("build objid", data, *datalength, asnlength)) 01492 return NULL; 01493 01494 /* 01495 * store the encoded OID value 01496 */ 01497 for (i = 1, objid_val = first_objid_val, op = objid + 2; 01498 i < (int) objidlength; i++) { 01499 if (i != 1) { 01500 objid_val = *op++; 01501 #if SIZEOF_LONG != 4 01502 if (objid_val > 0xffffffff) /* already logged warning above */ 01503 objid_val &= 0xffffffff; 01504 #endif 01505 } 01506 switch (objid_size[i]) { 01507 case 1: 01508 *data++ = (u_char) objid_val; 01509 break; 01510 01511 case 2: 01512 *data++ = (u_char) ((objid_val >> 7) | 0x80); 01513 *data++ = (u_char) (objid_val & 0x07f); 01514 break; 01515 01516 case 3: 01517 *data++ = (u_char) ((objid_val >> 14) | 0x80); 01518 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80); 01519 *data++ = (u_char) (objid_val & 0x07f); 01520 break; 01521 01522 case 4: 01523 *data++ = (u_char) ((objid_val >> 21) | 0x80); 01524 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80); 01525 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80); 01526 *data++ = (u_char) (objid_val & 0x07f); 01527 break; 01528 01529 case 5: 01530 *data++ = (u_char) ((objid_val >> 28) | 0x80); 01531 *data++ = (u_char) ((objid_val >> 21 & 0x7f) | 0x80); 01532 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80); 01533 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80); 01534 *data++ = (u_char) (objid_val & 0x07f); 01535 break; 01536 } 01537 } 01538 01539 /* 01540 * return the length and data ptr 01541 */ 01542 *datalength -= asnlength; 01543 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 01544 DEBUGMSG(("dumpv_send", " ObjID: ")); 01545 DEBUGMSGOID(("dumpv_send", objid, objidlength)); 01546 DEBUGMSG(("dumpv_send", "\n")); 01547 return data; 01548 } 01549 01569 u_char * 01570 asn_parse_null(u_char * data, size_t * datalength, u_char * type) 01571 { 01572 /* 01573 * ASN.1 null ::= 0x05 0x00 01574 */ 01575 register u_char *bufp = data; 01576 u_long asn_length; 01577 01578 *type = *bufp++; 01579 bufp = asn_parse_length(bufp, &asn_length); 01580 if (bufp == NULL) { 01581 ERROR_MSG("parse null: bad length"); 01582 return NULL; 01583 } 01584 if (asn_length != 0) { 01585 ERROR_MSG("parse null: malformed ASN.1 null"); 01586 return NULL; 01587 } 01588 01589 *datalength -= (bufp - data); 01590 01591 DEBUGDUMPSETUP("recv", data, bufp - data); 01592 DEBUGMSG(("dumpv_recv", " NULL\n")); 01593 01594 return bufp + asn_length; 01595 } 01596 01597 01618 u_char * 01619 asn_build_null(u_char * data, size_t * datalength, u_char type) 01620 { 01621 /* 01622 * ASN.1 null ::= 0x05 0x00 01623 */ 01624 #ifndef NETSNMP_NO_DEBUGGING 01625 u_char *initdatap = data; 01626 #endif 01627 data = asn_build_header(data, datalength, type, 0); 01628 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 01629 DEBUGMSG(("dumpv_send", " NULL\n")); 01630 return data; 01631 } 01632 01656 u_char * 01657 asn_parse_bitstring(u_char * data, 01658 size_t * datalength, 01659 u_char * type, u_char * str, size_t * strlength) 01660 { 01661 /* 01662 * bitstring ::= 0x03 asnlength unused {byte}* 01663 */ 01664 static const char *errpre = "parse bitstring"; 01665 register u_char *bufp = data; 01666 u_long asn_length; 01667 01668 *type = *bufp++; 01669 bufp = asn_parse_length(bufp, &asn_length); 01670 if (_asn_parse_length_check(errpre, bufp, data, 01671 asn_length, *datalength)) 01672 return NULL; 01673 01674 if ((size_t) asn_length > *strlength) { 01675 _asn_length_err(errpre, (size_t) asn_length, *strlength); 01676 return NULL; 01677 } 01678 if (_asn_bitstring_check(errpre, asn_length, *bufp)) 01679 return NULL; 01680 01681 DEBUGDUMPSETUP("recv", data, bufp - data); 01682 DEBUGMSG(("dumpv_recv", " Bitstring: ")); 01683 DEBUGMSGHEX(("dumpv_recv", data, asn_length)); 01684 DEBUGMSG(("dumpv_recv", "\n")); 01685 01686 memmove(str, bufp, asn_length); 01687 *strlength = (int) asn_length; 01688 *datalength -= (int) asn_length + (bufp - data); 01689 return bufp + asn_length; 01690 } 01691 01692 01715 u_char * 01716 asn_build_bitstring(u_char * data, 01717 size_t * datalength, 01718 u_char type, const u_char * str, size_t strlength) 01719 { 01720 /* 01721 * ASN.1 bit string ::= 0x03 asnlength unused {byte}* 01722 */ 01723 static const char *errpre = "build bitstring"; 01724 if (_asn_bitstring_check 01725 (errpre, strlength, (u_char)((str) ? *str : 0))) 01726 return NULL; 01727 01728 data = asn_build_header(data, datalength, type, strlength); 01729 if (_asn_build_header_check(errpre, data, *datalength, strlength)) 01730 return NULL; 01731 01732 if (strlength > 0 && str) 01733 memmove(data, str, strlength); 01734 else if (strlength > 0 && !str) { 01735 ERROR_MSG("no string passed into asn_build_bitstring\n"); 01736 return NULL; 01737 } 01738 01739 *datalength -= strlength; 01740 DEBUGDUMPSETUP("send", data, strlength); 01741 DEBUGMSG(("dumpv_send", " Bitstring: ")); 01742 DEBUGMSGHEX(("dumpv_send", data, strlength)); 01743 DEBUGMSG(("dumpv_send", "\n")); 01744 return data + strlength; 01745 } 01746 01769 u_char * 01770 asn_parse_unsigned_int64(u_char * data, 01771 size_t * datalength, 01772 u_char * type, 01773 struct counter64 * cp, size_t countersize) 01774 { 01775 /* 01776 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 01777 */ 01778 static const char *errpre = "parse uint64"; 01779 const int uint64sizelimit = (4 * 2) + 1; 01780 register u_char *bufp = data; 01781 u_long asn_length; 01782 register u_long low = 0, high = 0; 01783 01784 if (countersize != sizeof(struct counter64)) { 01785 _asn_size_err(errpre, countersize, sizeof(struct counter64)); 01786 return NULL; 01787 } 01788 *type = *bufp++; 01789 bufp = asn_parse_length(bufp, &asn_length); 01790 if (_asn_parse_length_check 01791 (errpre, bufp, data, asn_length, *datalength)) 01792 return NULL; 01793 01794 DEBUGDUMPSETUP("recv", data, bufp - data); 01795 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 01796 /* 01797 * 64 bit counters as opaque 01798 */ 01799 if ((*type == ASN_OPAQUE) && 01800 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) && 01801 (*bufp == ASN_OPAQUE_TAG1) && 01802 ((*(bufp + 1) == ASN_OPAQUE_COUNTER64) || 01803 (*(bufp + 1) == ASN_OPAQUE_U64))) { 01804 /* 01805 * change type to Counter64 or U64 01806 */ 01807 *type = *(bufp + 1); 01808 /* 01809 * value is encoded as special format 01810 */ 01811 bufp = asn_parse_length(bufp + 2, &asn_length); 01812 if (_asn_parse_length_check("parse opaque uint64", bufp, data, 01813 asn_length, *datalength)) 01814 return NULL; 01815 } 01816 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 01817 if (((int) asn_length > uint64sizelimit) || 01818 (((int) asn_length == uint64sizelimit) && *bufp != 0x00)) { 01819 _asn_length_err(errpre, (size_t) asn_length, uint64sizelimit); 01820 return NULL; 01821 } 01822 *datalength -= (int) asn_length + (bufp - data); 01823 if (*bufp & 0x80) { 01824 low = 0xFFFFFF; /* first byte bit 1 means start the data with 1s */ 01825 high = 0xFFFFFF; 01826 } 01827 01828 while (asn_length--) { 01829 high = ((0x00FFFFFF & high) << 8) | ((low & 0xFF000000) >> 24); 01830 low = ((low & 0x00FFFFFF) << 8) | *bufp++; 01831 } 01832 01833 CHECK_OVERFLOW_U(high,6); 01834 CHECK_OVERFLOW_U(low,6); 01835 01836 cp->low = low; 01837 cp->high = high; 01838 01839 DEBUGIF("dumpv_recv") { 01840 char i64buf[I64CHARSZ + 1]; 01841 printU64(i64buf, cp); 01842 DEBUGMSG(("dumpv_recv", "Counter64: %s", i64buf)); 01843 } 01844 01845 return bufp; 01846 } 01847 01848 01870 u_char * 01871 asn_build_unsigned_int64(u_char * data, 01872 size_t * datalength, 01873 u_char type, 01874 const struct counter64 * cp, size_t countersize) 01875 { 01876 /* 01877 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 01878 */ 01879 01880 register u_long low, high; 01881 register u_long mask, mask2; 01882 int add_null_byte = 0; 01883 size_t intsize; 01884 #ifndef NETSNMP_NO_DEBUGGING 01885 u_char *initdatap = data; 01886 #endif 01887 01888 if (countersize != sizeof(struct counter64)) { 01889 _asn_size_err("build uint64", countersize, 01890 sizeof(struct counter64)); 01891 return NULL; 01892 } 01893 intsize = 8; 01894 low = cp->low; 01895 high = cp->high; 01896 01897 CHECK_OVERFLOW_U(high,7); 01898 CHECK_OVERFLOW_U(low,7); 01899 01900 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); 01901 /* 01902 * mask is 0xFF000000 on a big-endian machine 01903 */ 01904 if ((u_char) ((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80) { 01905 /* 01906 * if MSB is set 01907 */ 01908 add_null_byte = 1; 01909 intsize++; 01910 } else { 01911 /* 01912 * Truncate "unnecessary" bytes off of the most significant end of this 2's 01913 * complement integer. 01914 * There should be no sequence of 9 consecutive 1's or 0's at the most 01915 * significant end of the integer. 01916 */ 01917 mask2 = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1); 01918 /* 01919 * mask2 is 0xFF800000 on a big-endian machine 01920 */ 01921 while ((((high & mask2) == 0) || ((high & mask2) == mask2)) 01922 && intsize > 1) { 01923 intsize--; 01924 high = (high << 8) 01925 | ((low & mask) >> (8 * (sizeof(long) - 1))); 01926 low <<= 8; 01927 } 01928 } 01929 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 01930 /* 01931 * encode a Counter64 as an opaque (it also works in SNMPv1) 01932 */ 01933 /* 01934 * turn into Opaque holding special tagged value 01935 */ 01936 if (type == ASN_OPAQUE_COUNTER64) { 01937 /* 01938 * put the tag and length for the Opaque wrapper 01939 */ 01940 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3); 01941 if (_asn_build_header_check 01942 ("build counter u64", data, *datalength, intsize + 3)) 01943 return NULL; 01944 01945 /* 01946 * put the special tag and length 01947 */ 01948 *data++ = ASN_OPAQUE_TAG1; 01949 *data++ = ASN_OPAQUE_COUNTER64; 01950 *data++ = (u_char) intsize; 01951 *datalength = *datalength - 3; 01952 } else 01953 /* 01954 * Encode the Unsigned int64 in an opaque 01955 */ 01956 /* 01957 * turn into Opaque holding special tagged value 01958 */ 01959 if (type == ASN_OPAQUE_U64) { 01960 /* 01961 * put the tag and length for the Opaque wrapper 01962 */ 01963 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3); 01964 if (_asn_build_header_check 01965 ("build opaque u64", data, *datalength, intsize + 3)) 01966 return NULL; 01967 01968 /* 01969 * put the special tag and length 01970 */ 01971 *data++ = ASN_OPAQUE_TAG1; 01972 *data++ = ASN_OPAQUE_U64; 01973 *data++ = (u_char) intsize; 01974 *datalength = *datalength - 3; 01975 } else { 01976 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 01977 data = asn_build_header(data, datalength, type, intsize); 01978 if (_asn_build_header_check 01979 ("build uint64", data, *datalength, intsize)) 01980 return NULL; 01981 01982 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 01983 } 01984 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 01985 *datalength -= intsize; 01986 if (add_null_byte == 1) { 01987 *data++ = '\0'; 01988 intsize--; 01989 } 01990 while (intsize--) { 01991 *data++ = (u_char) ((high & mask) >> (8 * (sizeof(long) - 1))); 01992 high = (high << 8) 01993 | ((low & mask) >> (8 * (sizeof(long) - 1))); 01994 low <<= 8; 01995 01996 } 01997 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 01998 DEBUGIF("dumpv_send") { 01999 char i64buf[I64CHARSZ + 1]; 02000 printU64(i64buf, cp); 02001 DEBUGMSG(("dumpv_send", i64buf)); 02002 } 02003 return data; 02004 } 02005 02006 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 02007 02008 02032 u_char * 02033 asn_parse_signed_int64(u_char * data, 02034 size_t * datalength, 02035 u_char * type, 02036 struct counter64 * cp, size_t countersize) 02037 { 02038 static const char *errpre = "parse int64"; 02039 const int int64sizelimit = (4 * 2) + 1; 02040 char ebuf[128]; 02041 register u_char *bufp = data; 02042 u_long asn_length; 02043 register u_int low = 0, high = 0; 02044 02045 if (countersize != sizeof(struct counter64)) { 02046 _asn_size_err(errpre, countersize, sizeof(struct counter64)); 02047 return NULL; 02048 } 02049 *type = *bufp++; 02050 bufp = asn_parse_length(bufp, &asn_length); 02051 if (_asn_parse_length_check 02052 (errpre, bufp, data, asn_length, *datalength)) 02053 return NULL; 02054 02055 DEBUGDUMPSETUP("recv", data, bufp - data); 02056 if ((*type == ASN_OPAQUE) && 02057 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) && 02058 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_I64)) { 02059 /* 02060 * change type to Int64 02061 */ 02062 *type = *(bufp + 1); 02063 /* 02064 * value is encoded as special format 02065 */ 02066 bufp = asn_parse_length(bufp + 2, &asn_length); 02067 if (_asn_parse_length_check("parse opaque int64", bufp, data, 02068 asn_length, *datalength)) 02069 return NULL; 02070 } 02071 /* 02072 * this should always have been true until snmp gets int64 PDU types 02073 */ 02074 else { 02075 snprintf(ebuf, sizeof(ebuf), 02076 "%s: wrong type: %d, len %d, buf bytes (%02X,%02X)", 02077 errpre, *type, (int) asn_length, *bufp, *(bufp + 1)); 02078 ebuf[ sizeof(ebuf)-1 ] = 0; 02079 ERROR_MSG(ebuf); 02080 return NULL; 02081 } 02082 if (((int) asn_length > int64sizelimit) || 02083 (((int) asn_length == int64sizelimit) && *bufp != 0x00)) { 02084 _asn_length_err(errpre, (size_t) asn_length, int64sizelimit); 02085 return NULL; 02086 } 02087 *datalength -= (int) asn_length + (bufp - data); 02088 if (*bufp & 0x80) { 02089 low = 0xFFFFFF; /* first byte bit 1 means start the data with 1s */ 02090 high = 0xFFFFFF; 02091 } 02092 02093 while (asn_length--) { 02094 high = ((0x00FFFFFF & high) << 8) | ((low & 0xFF000000) >> 24); 02095 low = ((low & 0x00FFFFFF) << 8) | *bufp++; 02096 } 02097 02098 CHECK_OVERFLOW_U(high,8); 02099 CHECK_OVERFLOW_U(low,8); 02100 02101 cp->low = low; 02102 cp->high = high; 02103 02104 DEBUGIF("dumpv_recv") { 02105 char i64buf[I64CHARSZ + 1]; 02106 printI64(i64buf, cp); 02107 DEBUGMSG(("dumpv_recv", "Integer64: %s", i64buf)); 02108 } 02109 02110 return bufp; 02111 } 02112 02113 02114 02136 u_char * 02137 asn_build_signed_int64(u_char * data, 02138 size_t * datalength, 02139 u_char type, 02140 const struct counter64 * cp, size_t countersize) 02141 { 02142 /* 02143 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 02144 */ 02145 02146 struct counter64 c64; 02147 register u_int mask, mask2; 02148 u_long low, high; 02149 size_t intsize; 02150 #ifndef NETSNMP_NO_DEBUGGING 02151 u_char *initdatap = data; 02152 #endif 02153 02154 if (countersize != sizeof(struct counter64)) { 02155 _asn_size_err("build int64", countersize, 02156 sizeof(struct counter64)); 02157 return NULL; 02158 } 02159 intsize = 8; 02160 memcpy(&c64, cp, sizeof(struct counter64)); /* we're may modify it */ 02161 low = c64.low; 02162 high = c64.high; 02163 02164 CHECK_OVERFLOW_S(high,9); 02165 CHECK_OVERFLOW_U(low,9); 02166 02167 /* 02168 * Truncate "unnecessary" bytes off of the most significant end of this 02169 * 2's complement integer. There should be no sequence of 9 02170 * consecutive 1's or 0's at the most significant end of the 02171 * integer. 02172 */ 02173 mask = ((u_int) 0xFF) << (8 * (sizeof(u_int) - 1)); 02174 mask2 = ((u_int) 0x1FF) << ((8 * (sizeof(u_int) - 1)) - 1); 02175 /* 02176 * mask is 0xFF800000 on a big-endian machine 02177 */ 02178 while ((((high & mask2) == 0) || ((high & mask2) == mask2)) 02179 && intsize > 1) { 02180 intsize--; 02181 high = (high << 8) 02182 | ((low & mask) >> (8 * (sizeof(u_int) - 1))); 02183 low <<= 8; 02184 } 02185 /* 02186 * until a real int64 gets incorperated into SNMP, we are going to 02187 * encode it as an opaque instead. First, we build the opaque 02188 * header and then the int64 tag type we use to mark it as an 02189 * int64 in the opaque string. 02190 */ 02191 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3); 02192 if (_asn_build_header_check 02193 ("build int64", data, *datalength, intsize + 3)) 02194 return NULL; 02195 02196 *data++ = ASN_OPAQUE_TAG1; 02197 *data++ = ASN_OPAQUE_I64; 02198 *data++ = (u_char) intsize; 02199 *datalength -= (3 + intsize); 02200 02201 while (intsize--) { 02202 *data++ = (u_char) ((high & mask) >> (8 * (sizeof(u_int) - 1))); 02203 high = (high << 8) 02204 | ((low & mask) >> (8 * (sizeof(u_int) - 1))); 02205 low <<= 8; 02206 } 02207 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 02208 DEBUGIF("dumpv_send") { 02209 char i64buf[I64CHARSZ + 1]; 02210 printU64(i64buf, cp); 02211 DEBUGMSG(("dumpv_send", i64buf)); 02212 } 02213 return data; 02214 } 02215 02216 02238 u_char * 02239 asn_parse_float(u_char * data, 02240 size_t * datalength, 02241 u_char * type, float *floatp, size_t floatsize) 02242 { 02243 register u_char *bufp = data; 02244 u_long asn_length; 02245 union { 02246 float floatVal; 02247 long longVal; 02248 u_char c[sizeof(float)]; 02249 } fu; 02250 02251 if (floatsize != sizeof(float)) { 02252 _asn_size_err("parse float", floatsize, sizeof(float)); 02253 return NULL; 02254 } 02255 *type = *bufp++; 02256 bufp = asn_parse_length(bufp, &asn_length); 02257 if (_asn_parse_length_check("parse float", bufp, data, 02258 asn_length, *datalength)) 02259 return NULL; 02260 02261 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 02262 /* 02263 * the float is encoded as an opaque 02264 */ 02265 if ((*type == ASN_OPAQUE) && 02266 (asn_length == ASN_OPAQUE_FLOAT_BER_LEN) && 02267 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_FLOAT)) { 02268 02269 /* 02270 * value is encoded as special format 02271 */ 02272 bufp = asn_parse_length(bufp + 2, &asn_length); 02273 if (_asn_parse_length_check("parse opaque float", bufp, data, 02274 asn_length, *datalength)) 02275 return NULL; 02276 02277 /* 02278 * change type to Float 02279 */ 02280 *type = ASN_OPAQUE_FLOAT; 02281 } 02282 02283 if (asn_length != sizeof(float)) { 02284 _asn_size_err("parse seq float", asn_length, sizeof(float)); 02285 return NULL; 02286 } 02287 02288 *datalength -= (int) asn_length + (bufp - data); 02289 memcpy(&fu.c[0], bufp, asn_length); 02290 02291 /* 02292 * correct for endian differences 02293 */ 02294 fu.longVal = ntohl(fu.longVal); 02295 02296 *floatp = fu.floatVal; 02297 02298 DEBUGMSG(("dumpv_recv", "Opaque float: %f\n", *floatp)); 02299 return bufp; 02300 } 02301 02325 u_char * 02326 asn_build_float(u_char * data, 02327 size_t * datalength, 02328 u_char type, const float *floatp, size_t floatsize) 02329 { 02330 union { 02331 float floatVal; 02332 int intVal; 02333 u_char c[sizeof(float)]; 02334 } fu; 02335 #ifndef NETSNMP_NO_DEBUGGING 02336 u_char *initdatap = data; 02337 #endif 02338 02339 if (floatsize != sizeof(float)) { 02340 _asn_size_err("build float", floatsize, sizeof(float)); 02341 return NULL; 02342 } 02343 /* 02344 * encode the float as an opaque 02345 */ 02346 /* 02347 * turn into Opaque holding special tagged value 02348 */ 02349 02350 /* 02351 * put the tag and length for the Opaque wrapper 02352 */ 02353 data = asn_build_header(data, datalength, ASN_OPAQUE, floatsize + 3); 02354 if (_asn_build_header_check 02355 ("build float", data, *datalength, (floatsize + 3))) 02356 return NULL; 02357 02358 /* 02359 * put the special tag and length 02360 */ 02361 *data++ = ASN_OPAQUE_TAG1; 02362 *data++ = ASN_OPAQUE_FLOAT; 02363 *data++ = (u_char) floatsize; 02364 *datalength = *datalength - 3; 02365 02366 fu.floatVal = *floatp; 02367 /* 02368 * correct for endian differences 02369 */ 02370 fu.intVal = htonl(fu.intVal); 02371 02372 *datalength -= floatsize; 02373 memcpy(data, &fu.c[0], floatsize); 02374 02375 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 02376 DEBUGMSG(("dumpv_send", "Opaque float: %f\n", *floatp)); 02377 data += floatsize; 02378 return data; 02379 } 02380 02381 02403 u_char * 02404 asn_parse_double(u_char * data, 02405 size_t * datalength, 02406 u_char * type, double *doublep, size_t doublesize) 02407 { 02408 register u_char *bufp = data; 02409 u_long asn_length; 02410 long tmp; 02411 union { 02412 double doubleVal; 02413 int intVal[2]; 02414 u_char c[sizeof(double)]; 02415 } fu; 02416 02417 02418 if (doublesize != sizeof(double)) { 02419 _asn_size_err("parse double", doublesize, sizeof(double)); 02420 return NULL; 02421 } 02422 *type = *bufp++; 02423 bufp = asn_parse_length(bufp, &asn_length); 02424 if (_asn_parse_length_check("parse double", bufp, data, 02425 asn_length, *datalength)) 02426 return NULL; 02427 02428 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 02429 /* 02430 * the double is encoded as an opaque 02431 */ 02432 if ((*type == ASN_OPAQUE) && 02433 (asn_length == ASN_OPAQUE_DOUBLE_BER_LEN) && 02434 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_DOUBLE)) { 02435 02436 /* 02437 * value is encoded as special format 02438 */ 02439 bufp = asn_parse_length(bufp + 2, &asn_length); 02440 if (_asn_parse_length_check("parse opaque double", bufp, data, 02441 asn_length, *datalength)) 02442 return NULL; 02443 02444 /* 02445 * change type to Double 02446 */ 02447 *type = ASN_OPAQUE_DOUBLE; 02448 } 02449 02450 if (asn_length != sizeof(double)) { 02451 _asn_size_err("parse seq double", asn_length, sizeof(double)); 02452 return NULL; 02453 } 02454 *datalength -= (int) asn_length + (bufp - data); 02455 memcpy(&fu.c[0], bufp, asn_length); 02456 02457 /* 02458 * correct for endian differences 02459 */ 02460 02461 tmp = ntohl(fu.intVal[0]); 02462 fu.intVal[0] = ntohl(fu.intVal[1]); 02463 fu.intVal[1] = tmp; 02464 02465 *doublep = fu.doubleVal; 02466 DEBUGMSG(("dumpv_recv", " Opaque Double:\t%f\n", *doublep)); 02467 02468 return bufp; 02469 } 02470 02471 02494 u_char * 02495 asn_build_double(u_char * data, 02496 size_t * datalength, 02497 u_char type, const double *doublep, size_t doublesize) 02498 { 02499 long tmp; 02500 union { 02501 double doubleVal; 02502 int intVal[2]; 02503 u_char c[sizeof(double)]; 02504 } fu; 02505 #ifndef NETSNMP_NO_DEBUGGING 02506 u_char *initdatap = data; 02507 #endif 02508 02509 if (doublesize != sizeof(double)) { 02510 _asn_size_err("build double", doublesize, sizeof(double)); 02511 return NULL; 02512 } 02513 02514 /* 02515 * encode the double as an opaque 02516 */ 02517 /* 02518 * turn into Opaque holding special tagged value 02519 */ 02520 02521 /* 02522 * put the tag and length for the Opaque wrapper 02523 */ 02524 data = asn_build_header(data, datalength, ASN_OPAQUE, doublesize + 3); 02525 if (_asn_build_header_check 02526 ("build double", data, *datalength, doublesize + 3)) 02527 return NULL; 02528 02529 /* 02530 * put the special tag and length 02531 */ 02532 *data++ = ASN_OPAQUE_TAG1; 02533 *data++ = ASN_OPAQUE_DOUBLE; 02534 *data++ = (u_char) doublesize; 02535 *datalength = *datalength - 3; 02536 02537 fu.doubleVal = *doublep; 02538 /* 02539 * correct for endian differences 02540 */ 02541 tmp = htonl(fu.intVal[0]); 02542 fu.intVal[0] = htonl(fu.intVal[1]); 02543 fu.intVal[1] = tmp; 02544 *datalength -= doublesize; 02545 memcpy(data, &fu.c[0], doublesize); 02546 02547 data += doublesize; 02548 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 02549 DEBUGMSG(("dumpv_send", " Opaque double: %f", *doublep)); 02550 return data; 02551 } 02552 02553 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 02554 02555 02570 int 02571 asn_realloc(u_char ** pkt, size_t * pkt_len) 02572 { 02573 if (pkt != NULL && pkt_len != NULL) { 02574 size_t old_pkt_len = *pkt_len; 02575 02576 DEBUGMSGTL(("asn_realloc", " old_pkt %08p, old_pkt_len %08x\n", 02577 *pkt, old_pkt_len)); 02578 02579 if (snmp_realloc(pkt, pkt_len)) { 02580 DEBUGMSGTL(("asn_realloc", " new_pkt %08p, new_pkt_len %08x\n", 02581 *pkt, *pkt_len)); 02582 DEBUGMSGTL(("asn_realloc", 02583 " memmove(%08p + %08x, %08p, %08x)\n", *pkt, 02584 (*pkt_len - old_pkt_len), *pkt, old_pkt_len)); 02585 memmove(*pkt + (*pkt_len - old_pkt_len), *pkt, old_pkt_len); 02586 memset(*pkt, (int) ' ', *pkt_len - old_pkt_len); 02587 return 1; 02588 } else { 02589 DEBUGMSG(("asn_realloc", " CANNOT REALLOC()\n")); 02590 } 02591 } 02592 return 0; 02593 } 02594 02595 #ifdef NETSNMP_USE_REVERSE_ASNENCODING 02596 02611 int 02612 asn_realloc_rbuild_length(u_char ** pkt, size_t * pkt_len, 02613 size_t * offset, int r, size_t length) 02614 { 02615 static const char *errpre = "build length"; 02616 char ebuf[128]; 02617 int tmp_int; 02618 size_t start_offset = *offset; 02619 02620 if (length <= 0x7f) { 02621 if (((*pkt_len - *offset) < 1) 02622 && !(r && asn_realloc(pkt, pkt_len))) { 02623 snprintf(ebuf, sizeof(ebuf), 02624 "%s: bad length < 1 :%ld, %lu", errpre, 02625 (long)(*pkt_len - *offset), (unsigned long)length); 02626 ebuf[ sizeof(ebuf)-1 ] = 0; 02627 ERROR_MSG(ebuf); 02628 return 0; 02629 } 02630 *(*pkt + *pkt_len - (++*offset)) = length; 02631 } else { 02632 while (length > 0xff) { 02633 if (((*pkt_len - *offset) < 1) 02634 && !(r && asn_realloc(pkt, pkt_len))) { 02635 snprintf(ebuf, sizeof(ebuf), 02636 "%s: bad length < 1 :%ld, %lu", errpre, 02637 (long)(*pkt_len - *offset), (unsigned long)length); 02638 ebuf[ sizeof(ebuf)-1 ] = 0; 02639 ERROR_MSG(ebuf); 02640 return 0; 02641 } 02642 *(*pkt + *pkt_len - (++*offset)) = length & 0xff; 02643 length >>= 8; 02644 } 02645 02646 while ((*pkt_len - *offset) < 2) { 02647 if (!(r && asn_realloc(pkt, pkt_len))) { 02648 snprintf(ebuf, sizeof(ebuf), 02649 "%s: bad length < 1 :%ld, %lu", errpre, 02650 (long)(*pkt_len - *offset), (unsigned long)length); 02651 ebuf[ sizeof(ebuf)-1 ] = 0; 02652 ERROR_MSG(ebuf); 02653 return 0; 02654 } 02655 } 02656 02657 *(*pkt + *pkt_len - (++*offset)) = length & 0xff; 02658 tmp_int = *offset - start_offset; 02659 *(*pkt + *pkt_len - (++*offset)) = tmp_int | 0x80; 02660 } 02661 02662 return 1; 02663 } 02664 02682 int 02683 asn_realloc_rbuild_header(u_char ** pkt, size_t * pkt_len, 02684 size_t * offset, int r, 02685 u_char type, size_t length) 02686 { 02687 char ebuf[128]; 02688 02689 if (asn_realloc_rbuild_length(pkt, pkt_len, offset, r, length)) { 02690 if (((*pkt_len - *offset) < 1) 02691 && !(r && asn_realloc(pkt, pkt_len))) { 02692 snprintf(ebuf, sizeof(ebuf), 02693 "bad header length < 1 :%ld, %lu", 02694 (long)(*pkt_len - *offset), (unsigned long)length); 02695 ebuf[ sizeof(ebuf)-1 ] = 0; 02696 ERROR_MSG(ebuf); 02697 return 0; 02698 } 02699 *(*pkt + *pkt_len - (++*offset)) = type; 02700 return 1; 02701 } 02702 return 0; 02703 } 02704 02722 int 02723 asn_realloc_rbuild_int(u_char ** pkt, size_t * pkt_len, 02724 size_t * offset, int r, 02725 u_char type, const long *intp, size_t intsize) 02726 { 02727 static const char *errpre = "build int"; 02728 register long integer = *intp; 02729 int testvalue; 02730 size_t start_offset = *offset; 02731 02732 if (intsize != sizeof(long)) { 02733 _asn_size_err(errpre, intsize, sizeof(long)); 02734 return 0; 02735 } 02736 02737 CHECK_OVERFLOW_S(integer,10); 02738 testvalue = (integer < 0) ? -1 : 0; 02739 02740 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { 02741 return 0; 02742 } 02743 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer; 02744 integer >>= 8; 02745 02746 while (integer != testvalue) { 02747 if (((*pkt_len - *offset) < 1) 02748 && !(r && asn_realloc(pkt, pkt_len))) { 02749 return 0; 02750 } 02751 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer; 02752 integer >>= 8; 02753 } 02754 02755 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (testvalue & 0x80)) { 02756 /* 02757 * Make sure left most bit is representational of the rest of the bits 02758 * that aren't encoded. 02759 */ 02760 if (((*pkt_len - *offset) < 1) 02761 && !(r && asn_realloc(pkt, pkt_len))) { 02762 return 0; 02763 } 02764 *(*pkt + *pkt_len - (++*offset)) = testvalue & 0xff; 02765 } 02766 02767 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 02768 (*offset - start_offset))) { 02769 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len, 02770 (*offset - start_offset))) { 02771 return 0; 02772 } else { 02773 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 02774 (*offset - start_offset)); 02775 DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2X)\n", *intp, 02776 *intp)); 02777 return 1; 02778 } 02779 } 02780 02781 return 0; 02782 } 02783 02802 int 02803 asn_realloc_rbuild_string(u_char ** pkt, size_t * pkt_len, 02804 size_t * offset, int r, 02805 u_char type, 02806 const u_char * str, size_t strlength) 02807 { 02808 static const char *errpre = "build string"; 02809 size_t start_offset = *offset; 02810 02811 while ((*pkt_len - *offset) < strlength) { 02812 if (!(r && asn_realloc(pkt, pkt_len))) { 02813 return 0; 02814 } 02815 } 02816 02817 *offset += strlength; 02818 memcpy(*pkt + *pkt_len - *offset, str, strlength); 02819 02820 if (asn_realloc_rbuild_header 02821 (pkt, pkt_len, offset, r, type, strlength)) { 02822 if (_asn_realloc_build_header_check 02823 (errpre, pkt, pkt_len, strlength)) { 02824 return 0; 02825 } else { 02826 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 02827 *offset - start_offset); 02828 DEBUGIF("dumpv_send") { 02829 if (strlength == 0) { 02830 DEBUGMSG(("dumpv_send", " String: [NULL]\n")); 02831 } else { 02832 u_char *buf = (u_char *) malloc(2 * strlength); 02833 size_t l = 02834 (buf != NULL) ? (2 * strlength) : 0, ol = 0; 02835 02836 if (sprint_realloc_asciistring 02837 (&buf, &l, &ol, 1, str, strlength)) { 02838 DEBUGMSG(("dumpv_send", " String:\t%s\n", buf)); 02839 } else { 02840 if (buf == NULL) { 02841 DEBUGMSG(("dumpv_send", 02842 " String:\t[TRUNCATED]\n")); 02843 } else { 02844 DEBUGMSG(("dumpv_send", 02845 " String:\t%s [TRUNCATED]\n", buf)); 02846 } 02847 } 02848 if (buf != NULL) { 02849 free(buf); 02850 } 02851 } 02852 } 02853 } 02854 return 1; 02855 } 02856 02857 return 0; 02858 } 02859 02877 int 02878 asn_realloc_rbuild_unsigned_int(u_char ** pkt, size_t * pkt_len, 02879 size_t * offset, int r, 02880 u_char type, const u_long * intp, size_t intsize) 02881 { 02882 static const char *errpre = "build uint"; 02883 register u_long integer = *intp; 02884 size_t start_offset = *offset; 02885 02886 if (intsize != sizeof(unsigned long)) { 02887 _asn_size_err(errpre, intsize, sizeof(unsigned long)); 02888 return 0; 02889 } 02890 02891 CHECK_OVERFLOW_U(integer,11); 02892 02893 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { 02894 return 0; 02895 } 02896 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer; 02897 integer >>= 8; 02898 02899 while (integer != 0) { 02900 if (((*pkt_len - *offset) < 1) 02901 && !(r && asn_realloc(pkt, pkt_len))) { 02902 return 0; 02903 } 02904 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer; 02905 integer >>= 8; 02906 } 02907 02908 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) { 02909 /* 02910 * Make sure left most bit is representational of the rest of the bits 02911 * that aren't encoded. 02912 */ 02913 if (((*pkt_len - *offset) < 1) 02914 && !(r && asn_realloc(pkt, pkt_len))) { 02915 return 0; 02916 } 02917 *(*pkt + *pkt_len - (++*offset)) = 0; 02918 } 02919 02920 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 02921 (*offset - start_offset))) { 02922 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len, 02923 (*offset - start_offset))) { 02924 return 0; 02925 } else { 02926 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 02927 (*offset - start_offset)); 02928 DEBUGMSG(("dumpv_send", " UInteger:\t%lu (0x%.2X)\n", *intp, 02929 *intp)); 02930 return 1; 02931 } 02932 } 02933 02934 return 0; 02935 } 02936 02954 int 02955 asn_realloc_rbuild_sequence(u_char ** pkt, size_t * pkt_len, 02956 size_t * offset, int r, 02957 u_char type, size_t length) 02958 { 02959 return asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 02960 length); 02961 } 02962 02981 int 02982 asn_realloc_rbuild_objid(u_char ** pkt, size_t * pkt_len, 02983 size_t * offset, int r, 02984 u_char type, 02985 const oid * objid, size_t objidlength) 02986 { 02987 /* 02988 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* 02989 * subidentifier ::= {leadingbyte}* lastbyte 02990 * leadingbyte ::= 1 7bitvalue 02991 * lastbyte ::= 0 7bitvalue 02992 */ 02993 register size_t i; 02994 register oid tmpint; 02995 size_t start_offset = *offset; 02996 const char *errpre = "build objid"; 02997 02998 /* 02999 * Check if there are at least 2 sub-identifiers. 03000 */ 03001 if (objidlength == 0) { 03002 /* 03003 * There are not, so make OID have two with value of zero. 03004 */ 03005 while ((*pkt_len - *offset) < 2) { 03006 if (!(r && asn_realloc(pkt, pkt_len))) { 03007 return 0; 03008 } 03009 } 03010 03011 *(*pkt + *pkt_len - (++*offset)) = 0; 03012 *(*pkt + *pkt_len - (++*offset)) = 0; 03013 } else if (objid[0] > 2) { 03014 ERROR_MSG("build objid: bad first subidentifier"); 03015 return 0; 03016 } else if (objidlength == 1) { 03017 /* 03018 * Encode the first value. 03019 */ 03020 if (((*pkt_len - *offset) < 1) 03021 && !(r && asn_realloc(pkt, pkt_len))) { 03022 return 0; 03023 } 03024 *(*pkt + *pkt_len - (++*offset)) = (u_char) objid[0]; 03025 } else { 03026 for (i = objidlength; i > 2; i--) { 03027 tmpint = objid[i - 1]; 03028 CHECK_OVERFLOW_U(tmpint,12); 03029 03030 if (((*pkt_len - *offset) < 1) 03031 && !(r && asn_realloc(pkt, pkt_len))) { 03032 return 0; 03033 } 03034 *(*pkt + *pkt_len - (++*offset)) = (u_char) tmpint & 0x7f; 03035 tmpint >>= 7; 03036 03037 while (tmpint > 0) { 03038 if (((*pkt_len - *offset) < 1) 03039 && !(r && asn_realloc(pkt, pkt_len))) { 03040 return 0; 03041 } 03042 *(*pkt + *pkt_len - (++*offset)) = 03043 (u_char) ((tmpint & 0x7f) | 0x80); 03044 tmpint >>= 7; 03045 } 03046 } 03047 03048 /* 03049 * Combine the first two values. 03050 */ 03051 if ((objid[1] > 40) && 03052 (objid[0] < 2)) { 03053 ERROR_MSG("build objid: bad second subidentifier"); 03054 return 0; 03055 } 03056 tmpint = ((objid[0] * 40) + objid[1]); 03057 if (((*pkt_len - *offset) < 1) 03058 && !(r && asn_realloc(pkt, pkt_len))) { 03059 return 0; 03060 } 03061 *(*pkt + *pkt_len - (++*offset)) = (u_char) tmpint & 0x7f; 03062 tmpint >>= 7; 03063 03064 while (tmpint > 0) { 03065 if (((*pkt_len - *offset) < 1) 03066 && !(r && asn_realloc(pkt, pkt_len))) { 03067 return 0; 03068 } 03069 *(*pkt + *pkt_len - (++*offset)) = 03070 (u_char) ((tmpint & 0x7f) | 0x80); 03071 tmpint >>= 7; 03072 } 03073 } 03074 03075 tmpint = *offset - start_offset; 03076 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 03077 (*offset - start_offset))) { 03078 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len, 03079 (*offset - start_offset))) { 03080 return 0; 03081 } else { 03082 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 03083 (*offset - start_offset)); 03084 DEBUGMSG(("dumpv_send", " ObjID: ")); 03085 DEBUGMSGOID(("dumpv_send", objid, objidlength)); 03086 DEBUGMSG(("dumpv_send", "\n")); 03087 return 1; 03088 } 03089 } 03090 03091 return 0; 03092 } 03093 03110 int 03111 asn_realloc_rbuild_null(u_char ** pkt, size_t * pkt_len, 03112 size_t * offset, int r, u_char type) 03113 { 03114 /* 03115 * ASN.1 null ::= 0x05 0x00 03116 */ 03117 size_t start_offset = *offset; 03118 03119 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 0)) { 03120 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 03121 (*offset - start_offset)); 03122 DEBUGMSG(("dumpv_send", " NULL\n")); 03123 return 1; 03124 } else { 03125 return 0; 03126 } 03127 } 03128 03147 int 03148 asn_realloc_rbuild_bitstring(u_char ** pkt, size_t * pkt_len, 03149 size_t * offset, int r, 03150 u_char type, 03151 const u_char * str, size_t strlength) 03152 { 03153 /* 03154 * ASN.1 bit string ::= 0x03 asnlength unused {byte}* 03155 */ 03156 static const char *errpre = "build bitstring"; 03157 size_t start_offset = *offset; 03158 03159 while ((*pkt_len - *offset) < strlength) { 03160 if (!(r && asn_realloc(pkt, pkt_len))) { 03161 return 0; 03162 } 03163 } 03164 03165 *offset += strlength; 03166 memcpy(*pkt + *pkt_len - *offset, str, strlength); 03167 03168 if (asn_realloc_rbuild_header 03169 (pkt, pkt_len, offset, r, type, strlength)) { 03170 if (_asn_realloc_build_header_check 03171 (errpre, pkt, pkt_len, strlength)) { 03172 return 0; 03173 } else { 03174 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 03175 *offset - start_offset); 03176 DEBUGIF("dumpv_send") { 03177 if (strlength == 0) { 03178 DEBUGMSG(("dumpv_send", " Bitstring: [NULL]\n")); 03179 } else { 03180 u_char *buf = (u_char *) malloc(2 * strlength); 03181 size_t l = 03182 (buf != NULL) ? (2 * strlength) : 0, ol = 0; 03183 03184 if (sprint_realloc_asciistring 03185 (&buf, &l, &ol, 1, str, strlength)) { 03186 DEBUGMSG(("dumpv_send", " Bitstring:\t%s\n", 03187 buf)); 03188 } else { 03189 if (buf == NULL) { 03190 DEBUGMSG(("dumpv_send", 03191 " Bitstring:\t[TRUNCATED]\n")); 03192 } else { 03193 DEBUGMSG(("dumpv_send", 03194 " Bitstring:\t%s [TRUNCATED]\n", 03195 buf)); 03196 } 03197 } 03198 if (buf != NULL) { 03199 free(buf); 03200 } 03201 } 03202 } 03203 } 03204 return 1; 03205 } 03206 03207 return 0; 03208 } 03209 03227 int 03228 asn_realloc_rbuild_unsigned_int64(u_char ** pkt, size_t * pkt_len, 03229 size_t * offset, int r, 03230 u_char type, 03231 const struct counter64 *cp, size_t countersize) 03232 { 03233 /* 03234 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 03235 */ 03236 register u_long low = cp->low, high = cp->high; 03237 size_t intsize, start_offset = *offset; 03238 int count; 03239 03240 if (countersize != sizeof(struct counter64)) { 03241 _asn_size_err("build uint64", countersize, 03242 sizeof(struct counter64)); 03243 return 0; 03244 } 03245 03246 CHECK_OVERFLOW_U(high,13); 03247 CHECK_OVERFLOW_U(low,13); 03248 03249 /* 03250 * Encode the low 4 bytes first. 03251 */ 03252 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { 03253 return 0; 03254 } 03255 *(*pkt + *pkt_len - (++*offset)) = (u_char) low; 03256 low >>= 8; 03257 count = 1; 03258 03259 while (low != 0) { 03260 count++; 03261 if (((*pkt_len - *offset) < 1) 03262 && !(r && asn_realloc(pkt, pkt_len))) { 03263 return 0; 03264 } 03265 *(*pkt + *pkt_len - (++*offset)) = (u_char) low; 03266 low >>= 8; 03267 } 03268 03269 /* 03270 * Then the high byte if present. 03271 */ 03272 if (high) { 03273 /* 03274 * Do the rest of the low byte. 03275 */ 03276 for (; count < 4; count++) { 03277 if (((*pkt_len - *offset) < 1) 03278 && !(r && asn_realloc(pkt, pkt_len))) { 03279 return 0; 03280 } 03281 *(*pkt + *pkt_len - (++*offset)) = 0; 03282 } 03283 03284 /* 03285 * Do high byte. 03286 */ 03287 if (((*pkt_len - *offset) < 1) 03288 && !(r && asn_realloc(pkt, pkt_len))) { 03289 return 0; 03290 } 03291 *(*pkt + *pkt_len - (++*offset)) = (u_char) high; 03292 high >>= 8; 03293 03294 while (high != 0) { 03295 if (((*pkt_len - *offset) < 1) 03296 && !(r && asn_realloc(pkt, pkt_len))) { 03297 return 0; 03298 } 03299 *(*pkt + *pkt_len - (++*offset)) = (u_char) high; 03300 high >>= 8; 03301 } 03302 } 03303 03304 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) { 03305 /* 03306 * Make sure left most bit is representational of the rest of the bits 03307 * that aren't encoded. 03308 */ 03309 if (((*pkt_len - *offset) < 1) 03310 && !(r && asn_realloc(pkt, pkt_len))) { 03311 return 0; 03312 } 03313 *(*pkt + *pkt_len - (++*offset)) = 0; 03314 } 03315 03316 intsize = *offset - start_offset; 03317 03318 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 03319 /* 03320 * Encode a Counter64 as an opaque (it also works in SNMPv1). 03321 */ 03322 if (type == ASN_OPAQUE_COUNTER64) { 03323 while ((*pkt_len - *offset) < 5) { 03324 if (!(r && asn_realloc(pkt, pkt_len))) { 03325 return 0; 03326 } 03327 } 03328 03329 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize; 03330 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_COUNTER64; 03331 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1; 03332 03333 /* 03334 * Put the tag and length for the Opaque wrapper. 03335 */ 03336 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, 03337 ASN_OPAQUE, intsize + 3)) { 03338 if (_asn_realloc_build_header_check 03339 ("build counter u64", pkt, pkt_len, intsize + 3)) { 03340 return 0; 03341 } 03342 } else { 03343 return 0; 03344 } 03345 } else if (type == ASN_OPAQUE_U64) { 03346 /* 03347 * Encode the Unsigned int64 in an opaque. 03348 */ 03349 while ((*pkt_len - *offset) < 5) { 03350 if (!(r && asn_realloc(pkt, pkt_len))) { 03351 return 0; 03352 } 03353 } 03354 03355 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize; 03356 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_U64; 03357 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1; 03358 03359 /* 03360 * Put the tag and length for the Opaque wrapper. 03361 */ 03362 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, 03363 ASN_OPAQUE, intsize + 3)) { 03364 if (_asn_realloc_build_header_check 03365 ("build counter u64", pkt, pkt_len, intsize + 3)) { 03366 return 0; 03367 } 03368 } else { 03369 return 0; 03370 } 03371 } else { 03372 03373 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 03374 if (asn_realloc_rbuild_header 03375 (pkt, pkt_len, offset, r, type, intsize)) { 03376 if (_asn_realloc_build_header_check 03377 ("build uint64", pkt, pkt_len, intsize)) { 03378 return 0; 03379 } 03380 } else { 03381 return 0; 03382 } 03383 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 03384 } 03385 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 03386 03387 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), intsize); 03388 DEBUGMSG(("dumpv_send", " U64:\t%lu %lu\n", cp->high, cp->low)); 03389 return 1; 03390 } 03391 03392 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 03393 03394 03412 int 03413 asn_realloc_rbuild_signed_int64(u_char ** pkt, size_t * pkt_len, 03414 size_t * offset, int r, 03415 u_char type, 03416 const struct counter64 *cp, size_t countersize) 03417 { 03418 /* 03419 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 03420 */ 03421 register long low = cp->low, high = cp->high; 03422 size_t intsize, start_offset = *offset; 03423 int count, testvalue = (high & 0x80000000) ? -1 : 0; 03424 03425 if (countersize != sizeof(struct counter64)) { 03426 _asn_size_err("build uint64", countersize, 03427 sizeof(struct counter64)); 03428 return 0; 03429 } 03430 03431 CHECK_OVERFLOW_S(high,14); 03432 CHECK_OVERFLOW_U(low,14); 03433 03434 /* 03435 * Encode the low 4 bytes first. 03436 */ 03437 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { 03438 return 0; 03439 } 03440 *(*pkt + *pkt_len - (++*offset)) = (u_char) low; 03441 low >>= 8; 03442 count = 1; 03443 03444 while ((int) low != testvalue && count < 4) { 03445 count++; 03446 if (((*pkt_len - *offset) < 1) 03447 && !(r && asn_realloc(pkt, pkt_len))) { 03448 return 0; 03449 } 03450 *(*pkt + *pkt_len - (++*offset)) = (u_char) low; 03451 low >>= 8; 03452 } 03453 03454 /* 03455 * Then the high byte if present. 03456 */ 03457 if (high != testvalue) { 03458 /* 03459 * Do the rest of the low byte. 03460 */ 03461 for (; count < 4; count++) { 03462 if (((*pkt_len - *offset) < 1) 03463 && !(r && asn_realloc(pkt, pkt_len))) { 03464 return 0; 03465 } 03466 *(*pkt + *pkt_len - (++*offset)) = (testvalue == 0) ? 0 : 0xff; 03467 } 03468 03469 /* 03470 * Do high byte. 03471 */ 03472 if (((*pkt_len - *offset) < 1) 03473 && !(r && asn_realloc(pkt, pkt_len))) { 03474 return 0; 03475 } 03476 *(*pkt + *pkt_len - (++*offset)) = (u_char) high; 03477 high >>= 8; 03478 03479 while ((int) high != testvalue) { 03480 if (((*pkt_len - *offset) < 1) 03481 && !(r && asn_realloc(pkt, pkt_len))) { 03482 return 0; 03483 } 03484 *(*pkt + *pkt_len - (++*offset)) = (u_char) high; 03485 high >>= 8; 03486 } 03487 } 03488 03489 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (testvalue & 0x80)) { 03490 /* 03491 * Make sure left most bit is representational of the rest of the bits 03492 * that aren't encoded. 03493 */ 03494 if (((*pkt_len - *offset) < 1) 03495 && !(r && asn_realloc(pkt, pkt_len))) { 03496 return 0; 03497 } 03498 *(*pkt + *pkt_len - (++*offset)) = (testvalue == 0) ? 0 : 0xff; 03499 } 03500 03501 intsize = *offset - start_offset; 03502 03503 while ((*pkt_len - *offset) < 5) { 03504 if (!(r && asn_realloc(pkt, pkt_len))) { 03505 return 0; 03506 } 03507 } 03508 03509 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize; 03510 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_I64; 03511 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1; 03512 03513 /* 03514 * Put the tag and length for the Opaque wrapper. 03515 */ 03516 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, 03517 ASN_OPAQUE, intsize + 3)) { 03518 if (_asn_realloc_build_header_check 03519 ("build counter u64", pkt, pkt_len, intsize + 3)) { 03520 return 0; 03521 } 03522 } else { 03523 return 0; 03524 } 03525 03526 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), intsize); 03527 DEBUGMSG(("dumpv_send", " UInt64:\t%lu %lu\n", cp->high, cp->low)); 03528 return 1; 03529 } 03530 03549 int 03550 asn_realloc_rbuild_float(u_char ** pkt, size_t * pkt_len, 03551 size_t * offset, int r, 03552 u_char type, const float *floatp, size_t floatsize) 03553 { 03554 size_t start_offset = *offset; 03555 union { 03556 float floatVal; 03557 int intVal; 03558 u_char c[sizeof(float)]; 03559 } fu; 03560 03561 /* 03562 * Floatsize better not be larger than realistic. 03563 */ 03564 if (floatsize != sizeof(float) || floatsize > 122) { 03565 return 0; 03566 } 03567 03568 while ((*pkt_len - *offset) < floatsize + 3) { 03569 if (!(r && asn_realloc(pkt, pkt_len))) { 03570 return 0; 03571 } 03572 } 03573 03574 /* 03575 * Correct for endian differences and copy value. 03576 */ 03577 fu.floatVal = *floatp; 03578 fu.intVal = htonl(fu.intVal); 03579 *offset += floatsize; 03580 memcpy(*pkt + *pkt_len - *offset, &(fu.c[0]), floatsize); 03581 03582 /* 03583 * Put the special tag and length (3 bytes). 03584 */ 03585 *(*pkt + *pkt_len - (++*offset)) = (u_char) floatsize; 03586 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_FLOAT; 03587 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1; 03588 03589 /* 03590 * Put the tag and length for the Opaque wrapper. 03591 */ 03592 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, 03593 ASN_OPAQUE, floatsize + 3)) { 03594 if (_asn_realloc_build_header_check("build float", pkt, pkt_len, 03595 floatsize + 3)) { 03596 return 0; 03597 } else { 03598 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 03599 *offset - start_offset); 03600 DEBUGMSG(("dumpv_send", "Opaque Float:\t%f\n", *floatp)); 03601 return 1; 03602 } 03603 } 03604 03605 return 0; 03606 } 03607 03626 int 03627 asn_realloc_rbuild_double(u_char ** pkt, size_t * pkt_len, 03628 size_t * offset, int r, 03629 u_char type, const double *doublep, size_t doublesize) 03630 { 03631 size_t start_offset = *offset; 03632 long tmp; 03633 union { 03634 double doubleVal; 03635 int intVal[2]; 03636 u_char c[sizeof(double)]; 03637 } fu; 03638 03639 /* 03640 * Doublesize better not be larger than realistic. 03641 */ 03642 if (doublesize != sizeof(double) || doublesize > 122) { 03643 return 0; 03644 } 03645 03646 while ((*pkt_len - *offset) < doublesize + 3) { 03647 if (!(r && asn_realloc(pkt, pkt_len))) { 03648 return 0; 03649 } 03650 } 03651 03652 /* 03653 * Correct for endian differences and copy value. 03654 */ 03655 fu.doubleVal = *doublep; 03656 tmp = htonl(fu.intVal[0]); 03657 fu.intVal[0] = htonl(fu.intVal[1]); 03658 fu.intVal[1] = tmp; 03659 *offset += doublesize; 03660 memcpy(*pkt + *pkt_len - *offset, &(fu.c[0]), doublesize); 03661 03662 /* 03663 * Put the special tag and length (3 bytes). 03664 */ 03665 *(*pkt + *pkt_len - (++*offset)) = (u_char) doublesize; 03666 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_DOUBLE; 03667 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1; 03668 03669 /* 03670 * Put the tag and length for the Opaque wrapper. 03671 */ 03672 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, 03673 ASN_OPAQUE, doublesize + 3)) { 03674 if (_asn_realloc_build_header_check("build float", pkt, pkt_len, 03675 doublesize + 3)) { 03676 return 0; 03677 } else { 03678 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 03679 *offset - start_offset); 03680 DEBUGMSG(("dumpv_send", " Opaque Double:\t%f\n", *doublep)); 03681 return 1; 03682 } 03683 } 03684 03685 return 0; 03686 } 03687 03688 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 03689 #endif /* NETSNMP_USE_REVERSE_ASNENCODING */ 03690