📄 asn1.c
字号:
}/* * asn_build_null - Builds an ASN null object. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the beginning of the next object. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_build_null( u_char *data IN - pointer to start of object int *datalength IN/OUT - number of valid bytes left in buffer u_char type IN - asn type of object */u_char *asn_build_null(u_char * data, size_t * datalength, u_char type){ /* * ASN.1 null ::= 0x05 0x00 */#ifndef SNMP_NO_DEBUGGING u_char *initdatap = data;#endif data = asn_build_header(data, datalength, type, 0); DEBUGDUMPSETUP("send", initdatap, data - initdatap); DEBUGMSG(("dumpv_send", " NULL\n")); return data;}/* * asn_parse_bitstring - pulls a bitstring out of an ASN bitstring type. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the beginning of the next object. * * "string" is filled with the bit string. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_parse_bitstring( u_char *data IN - pointer to start of object size_t *datalength IN/OUT - number of valid bytes left in buffer u_char *type OUT - asn type of object u_char *string IN/OUT - pointer to start of output buffer size_t *strlength IN/OUT - size of output buffer */u_char *asn_parse_bitstring(u_char * data, size_t * datalength, u_char * type, u_char * string, size_t * strlength){ /* * bitstring ::= 0x03 asnlength unused {byte}* */ static const char *errpre = "parse bitstring"; register u_char *bufp = data; u_long asn_length; *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (_asn_parse_length_check(errpre, bufp, data, asn_length, *datalength)) return NULL; if ((size_t) asn_length > *strlength) { _asn_length_err(errpre, (size_t) asn_length, *strlength); return NULL; } if (_asn_bitstring_check(errpre, asn_length, *bufp)) return NULL; DEBUGDUMPSETUP("recv", data, bufp - data); DEBUGMSG(("dumpv_recv", " Bitstring: ")); DEBUGMSGHEX(("dumpv_recv", data, asn_length)); DEBUGMSG(("dumpv_recv", "\n")); memmove(string, bufp, asn_length); *strlength = (int) asn_length; *datalength -= (int) asn_length + (bufp - data); return bufp + asn_length;}/* * asn_build_bitstring - Builds an ASN bit string object containing the * input string. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the beginning of the next object. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_build_bitstring( u_char *data IN - pointer to start of object int *datalength IN/OUT - number of valid bytes left in buffer u_char type IN - asn type of object u_char *string IN - pointer to start of input buffer int strlength IN - size of input buffer */u_char *asn_build_bitstring(u_char * data, size_t * datalength, u_char type, u_char * string, size_t strlength){ /* * ASN.1 bit string ::= 0x03 asnlength unused {byte}* */ static const char *errpre = "build bitstring"; if (_asn_bitstring_check (errpre, strlength, ((string) ? *string : (u_char) 0))) return NULL; data = asn_build_header(data, datalength, type, strlength); if (_asn_build_header_check(errpre, data, *datalength, strlength)) return NULL; if (strlength > 0 && string) memmove(data, string, strlength); else if (strlength > 0 && !string) { ERROR_MSG("no string passed into asn_build_bitstring\n"); return NULL; } *datalength -= strlength; DEBUGDUMPSETUP("send", data, strlength); DEBUGMSG(("dumpv_send", " Bitstring: ")); DEBUGMSGHEX(("dumpv_send", data, strlength)); DEBUGMSG(("dumpv_send", "\n")); return data + strlength;}/* * asn_parse_unsigned_int64 - pulls a 64 bit unsigned long out of an ASN int * type. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the end of this object. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_parse_unsigned_int64( u_char *data IN - pointer to start of object int *datalength IN/OUT - number of valid bytes left in buffer u_char *type OUT - asn type of object struct counter64 *cp IN/OUT - pointer to counter struct int countersize IN - size of output buffer */u_char *asn_parse_unsigned_int64(u_char * data, size_t * datalength, u_char * type, struct counter64 * cp, size_t countersize){ /* * ASN.1 integer ::= 0x02 asnlength byte {byte}* */ static const char *errpre = "parse uint64"; const int uint64sizelimit = (4 * 2) + 1; register u_char *bufp = data; u_long asn_length; register u_long low = 0, high = 0; if (countersize != sizeof(struct counter64)) { _asn_size_err(errpre, countersize, sizeof(struct counter64)); return NULL; } *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (_asn_parse_length_check (errpre, bufp, data, asn_length, *datalength)) return NULL; DEBUGDUMPSETUP("recv", data, bufp - data);#ifdef OPAQUE_SPECIAL_TYPES /* * 64 bit counters as opaque */ if ((*type == ASN_OPAQUE) && (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) && (*bufp == ASN_OPAQUE_TAG1) && ((*(bufp + 1) == ASN_OPAQUE_COUNTER64) || (*(bufp + 1) == ASN_OPAQUE_U64))) { /* * change type to Counter64 or U64 */ *type = *(bufp + 1); /* * value is encoded as special format */ bufp = asn_parse_length(bufp + 2, &asn_length); if (_asn_parse_length_check("parse opaque uint64", bufp, data, asn_length, *datalength)) return NULL; }#endif /* OPAQUE_SPECIAL_TYPES */ if (((int) asn_length > uint64sizelimit) || (((int) asn_length == uint64sizelimit) && *bufp != 0x00)) { _asn_length_err(errpre, (size_t) asn_length, uint64sizelimit); return NULL; } *datalength -= (int) asn_length + (bufp - data); if (*bufp & 0x80) { low = ~low; /* integer is negative */ high = ~high; } while (asn_length--) { high = (high << 8) | ((low & 0xFF000000) >> 24); low = (low << 8) | *bufp++; } cp->low = low; cp->high = high; DEBUGIF("dumpv_recv") { char i64buf[I64CHARSZ + 1]; printU64(i64buf, cp); DEBUGMSG(("dumpv_recv", "Counter64: ", i64buf)); } return bufp;}/* * asn_build_unsigned_int64 - builds an ASN object containing a 64 bit integer. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the end of this object. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_build_unsigned_int64( u_char *data IN - pointer to start of output buffer size_t *datalength IN/OUT - number of valid bytes left in buffer u_char type IN - asn type of object struct counter64 *cp IN - pointer to counter struct size_t countersize IN - size of input buffer */u_char *asn_build_unsigned_int64(u_char * data, size_t * datalength, u_char type, struct counter64 * cp, size_t countersize){ /* * ASN.1 integer ::= 0x02 asnlength byte {byte}* */ register u_long low, high; register u_long mask, mask2; int add_null_byte = 0; size_t intsize;#ifndef SNMP_NO_DEBUGGING u_char *initdatap = data;#endif if (countersize != sizeof(struct counter64)) { _asn_size_err("build uint64", countersize, sizeof(struct counter64)); return NULL; } intsize = 8; low = cp->low; high = cp->high; mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); /* * mask is 0xFF000000 on a big-endian machine */ if ((u_char) ((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80) { /* * if MSB is set */ add_null_byte = 1; intsize++; } else { /* * Truncate "unnecessary" bytes off of the most significant end of this 2's * complement integer. * There should be no sequence of 9 consecutive 1's or 0's at the most * significant end of the integer. */ mask2 = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1); /* * mask2 is 0xFF800000 on a big-endian machine */ while ((((high & mask2) == 0) || ((high & mask2) == mask2)) && intsize > 1) { intsize--; high = (high << 8) | ((low & mask) >> (8 * (sizeof(long) - 1))); low <<= 8; } }#ifdef OPAQUE_SPECIAL_TYPES /* * encode a Counter64 as an opaque (it also works in SNMPv1) */ /* * turn into Opaque holding special tagged value */ if (type == ASN_OPAQUE_COUNTER64) { /* * put the tag and length for the Opaque wrapper */ data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3); if (_asn_build_header_check ("build counter u64", data, *datalength, intsize + 3)) return NULL; /* * put the special tag and length */ *data++ = ASN_OPAQUE_TAG1; *data++ = ASN_OPAQUE_COUNTER64; *data++ = (u_char) intsize; *datalength = *datalength - 3; } else /* * Encode the Unsigned int64 in an opaque */ /* * turn into Opaque holding special tagged value */ if (type == ASN_OPAQUE_U64) { /* * put the tag and length for the Opaque wrapper */ data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3); if (_asn_build_header_check ("build opaque u64", data, *datalength, intsize + 3)) return NULL; /* * put the special tag and length */ *data++ = ASN_OPAQUE_TAG1; *data++ = ASN_OPAQUE_U64; *data++ = (u_char) intsize; *datalength = *datalength - 3; } else {#endif /* OPAQUE_SPECIAL_TYPES */ data = asn_build_header(data, datalength, type, intsize); if (_asn_build_header_check ("build uint64", data, *datalength, intsize)) return NULL;#ifdef OPAQUE_SPECIAL_TYPES }#endif /* OPAQUE_SPECIAL_TYPES */ *datalength -= intsize; if (add_null_byte == 1) { *data++ = '\0'; intsize--; } while (intsize--) { *data++ = (u_char) ((high & mask) >> (8 * (sizeof(long) - 1))); high = (high << 8) | ((low & mask) >> (8 * (sizeof(long) - 1))); low <<= 8; } DEBUGDUMPSETUP("send", initdatap, data - initdatap); DEBUGIF("dumpv_send") { char i64buf[I64CHARSZ + 1]; printU64(i64buf, cp); DEBUGMSG(("dumpv_send", i64buf)); } return data;}#ifdef OPAQUE_SPECIAL_TYPES/* * * u_char * asn_parse_signed_int64( * u_char *data IN - pointer to start of object * int *datalength IN/OUT - number of valid bytes left in buffer * u_char *type OUT - asn type of object * struct counter64 *cp IN/OUT - pointer to counter struct * int countersize IN - size of output buffer */u_char *asn_parse_signed_int64(u_char * data, size_t * datalength, u_char * type, struct counter64 * cp, size_t countersize){ static const char *errpre = "parse int64"; const int int64sizelimit = (4 * 2) + 1; char ebuf[128]; register u_char *bufp = data; u_long asn_length; register u_int low = 0, high = 0; if (countersize != sizeof(struct counter64)) { _asn_size_err(errpre, countersize, sizeof(struct counter64)); return NULL; } *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (_asn_parse_length_check (errpre, bufp, data, asn_length, *datalength)) return NULL; DEBUGDUMPSETUP("recv", data, bufp - data); if ((*type == ASN_OPAQUE) && (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) && (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_I64)) { /* * change type to Int64 */ *type = *(bufp + 1); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -