📄 asn1.c
字号:
* asn_parse_length - interprets the length of the current object. * On exit, length contains the value of this length field. * * Returns a pointer to the first byte after this length * field (aka: the start of the data field). * Returns NULL on any error. u_char * asn_parse_length( u_char *data IN - pointer to start of length field u_long *length OUT - value of length field */u_char *asn_parse_length(u_char * data, u_long * length){ static const char *errpre = "parse length"; char ebuf[128]; register u_char lengthbyte; if (!data || !length) { ERROR_MSG("parse length: NULL pointer"); return NULL; } lengthbyte = *data; if (lengthbyte & ASN_LONG_LEN) { lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */ if (lengthbyte == 0) { snprintf(ebuf, sizeof(ebuf), "%s: indefinite length not supported", errpre); ebuf[ sizeof(ebuf)-1 ] = 0; ERROR_MSG(ebuf); return NULL; } if (lengthbyte > sizeof(long)) { snprintf(ebuf, sizeof(ebuf), "%s: data length %d > %d not supported", errpre, lengthbyte, sizeof(long)); ebuf[ sizeof(ebuf)-1 ] = 0; ERROR_MSG(ebuf); return NULL; } data++; *length = 0; /* protect against short lengths */ while (lengthbyte--) { *length <<= 8; *length |= *data++; } if ((long) *length < 0) { snprintf(ebuf, sizeof(ebuf), "%s: negative data length %ld\n", errpre, (long) *length); ebuf[ sizeof(ebuf)-1 ] = 0; ERROR_MSG(ebuf); return NULL; } return data; } else { /* short asnlength */ *length = (long) lengthbyte; return data + 1; }}/* * * u_char * asn_build_length( * u_char *data IN - pointer to start of object * int *datalength IN/OUT - number of valid bytes left in buffer * int length IN - length of object */u_char *asn_build_length(u_char * data, size_t * datalength, size_t length){ static const char *errpre = "build length"; char ebuf[128]; u_char *start_data = data; /* * no indefinite lengths sent */ if (length < 0x80) { if (*datalength < 1) { snprintf(ebuf, sizeof(ebuf), "%s: bad length < 1 :%d, %d", errpre, *datalength, length); ebuf[ sizeof(ebuf)-1 ] = 0; ERROR_MSG(ebuf); return NULL; } *data++ = (u_char) length; } else if (length <= 0xFF) { if (*datalength < 2) { snprintf(ebuf, sizeof(ebuf), "%s: bad length < 2 :%d, %d", errpre, *datalength, length); ebuf[ sizeof(ebuf)-1 ] = 0; ERROR_MSG(ebuf); return NULL; } *data++ = (u_char) (0x01 | ASN_LONG_LEN); *data++ = (u_char) length; } else { /* 0xFF < length <= 0xFFFF */ if (*datalength < 3) { snprintf(ebuf, sizeof(ebuf), "%s: bad length < 3 :%d, %d", errpre, *datalength, length); ebuf[ sizeof(ebuf)-1 ] = 0; ERROR_MSG(ebuf); return NULL; } *data++ = (u_char) (0x02 | ASN_LONG_LEN); *data++ = (u_char) ((length >> 8) & 0xFF); *data++ = (u_char) (length & 0xFF); } *datalength -= (data - start_data); return data;}/* * asn_parse_objid - pulls an object indentifier out of an ASN object identifier 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. * * "objid" is filled with the object identifier. * * 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_objid( 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 oid *objid IN/OUT - pointer to start of output buffer int *objidlength IN/OUT - number of sub-id's in objid */u_char *asn_parse_objid(u_char * data, size_t * datalength, u_char * type, oid * objid, size_t * objidlength){ /* * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* * subidentifier ::= {leadingbyte}* lastbyte * leadingbyte ::= 1 7bitvalue * lastbyte ::= 0 7bitvalue */ register u_char *bufp = data; register oid *oidp = objid + 1; register u_long subidentifier; register long length; u_long asn_length; *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (_asn_parse_length_check("parse objid", bufp, data, asn_length, *datalength)) return NULL; *datalength -= (int) asn_length + (bufp - data); DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); /* * Handle invalid object identifier encodings of the form 06 00 robustly */ if (asn_length == 0) objid[0] = objid[1] = 0; length = asn_length; (*objidlength)--; /* account for expansion of first byte */ while (length > 0 && (*objidlength)-- > 0) { subidentifier = 0; do { /* shift and add in low order 7 bits */ subidentifier = (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8); length--; } while (*(u_char *) bufp++ & ASN_BIT8); /* last byte has high bit clear */ /* * ?? note, this test will never be true, since the largest value * of subidentifier is the value of MAX_SUBID! */ if (subidentifier > (u_long) MAX_SUBID) { ERROR_MSG("subidentifier too large"); return NULL; } *oidp++ = (oid) subidentifier; } /* * The first two subidentifiers are encoded into the first component * with the value (X * 40) + Y, where: * X is the value of the first subidentifier. * Y is the value of the second subidentifier. */ subidentifier = (u_long) objid[1]; if (subidentifier == 0x2B) { objid[0] = 1; objid[1] = 3; } else { if (subidentifier < 40) { objid[0] = 0; objid[1] = subidentifier; } else if (subidentifier < 80) { objid[0] = 1; objid[1] = subidentifier - 40; } else { objid[0] = 2; objid[1] = subidentifier - 80; } } *objidlength = (int) (oidp - objid); DEBUGMSG(("dumpv_recv", " ObjID: ")); DEBUGMSGOID(("dumpv_recv", objid, *objidlength)); DEBUGMSG(("dumpv_recv", "\n")); return bufp;}/* * asn_build_objid - Builds an ASN object identifier 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_objid( u_char *data IN - pointer to start of object int *datalength IN/OUT - number of valid bytes left in buffer int type IN - asn type of object oid *objid IN - pointer to start of input buffer int objidlength IN - number of sub-id's in objid */u_char *asn_build_objid(u_char * data, size_t * datalength, u_char type, oid * objid, size_t objidlength){ /* * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* * subidentifier ::= {leadingbyte}* lastbyte * leadingbyte ::= 1 7bitvalue * lastbyte ::= 0 7bitvalue */ size_t asnlength; register oid *op = objid; u_char objid_size[MAX_OID_LEN]; register u_long objid_val; u_long first_objid_val; register int i;#ifndef SNMP_NO_DEBUGGING u_char *initdatap = data;#endif /* * check if there are at least 2 sub-identifiers */ if (objidlength == 0) { /* * there are not, so make OID have two with value of zero */ objid_val = 0; objidlength = 2; } else if (objid[0] > 2) { ERROR_MSG("build objid: bad first subidentifier"); return NULL; } else if (objidlength == 1) { /* * encode the first value */ objid_val = (op[0] * 40); objidlength = 2; op++; } else { /* * combine the first two values */ if ((op[1] > 40) && (op[0] < 2)) { ERROR_MSG("build objid: bad second subidentifier"); return NULL; } objid_val = (op[0] * 40) + op[1]; op += 2; } first_objid_val = objid_val; /* * ditch illegal calls now */ if (objidlength > MAX_OID_LEN) return NULL; /* * calculate the number of bytes needed to store the encoded value */ for (i = 1, asnlength = 0;;) { if (objid_val < (unsigned) 0x80) { objid_size[i] = 1; asnlength += 1; } else if (objid_val < (unsigned) 0x4000) { objid_size[i] = 2; asnlength += 2; } else if (objid_val < (unsigned) 0x200000) { objid_size[i] = 3; asnlength += 3; } else if (objid_val < (unsigned) 0x10000000) { objid_size[i] = 4; asnlength += 4; } else { objid_size[i] = 5; asnlength += 5; } i++; if (i >= (int) objidlength) break; objid_val = *op++; /* XXX - doesn't handle 2.X (X > 40) */ } /* * store the ASN.1 tag and length */ data = asn_build_header(data, datalength, type, asnlength); if (_asn_build_header_check ("build objid", data, *datalength, asnlength)) return NULL; /* * store the encoded OID value */ for (i = 1, objid_val = first_objid_val, op = objid + 2; i < (int) objidlength; i++) { if (i != 1) objid_val = *op++; switch (objid_size[i]) { case 1: *data++ = (u_char) objid_val; break; case 2: *data++ = (u_char) ((objid_val >> 7) | 0x80); *data++ = (u_char) (objid_val & 0x07f); break; case 3: *data++ = (u_char) ((objid_val >> 14) | 0x80); *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80); *data++ = (u_char) (objid_val & 0x07f); break; case 4: *data++ = (u_char) ((objid_val >> 21) | 0x80); *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80); *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80); *data++ = (u_char) (objid_val & 0x07f); break; case 5: *data++ = (u_char) ((objid_val >> 28) | 0x80); *data++ = (u_char) ((objid_val >> 21 & 0x7f) | 0x80); *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80); *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80); *data++ = (u_char) (objid_val & 0x07f); break; } } /* * return the length and data ptr */ *datalength -= asnlength; DEBUGDUMPSETUP("send", initdatap, data - initdatap); DEBUGMSG(("dumpv_send", " ObjID: ")); DEBUGMSGOID(("dumpv_send", objid, objidlength)); DEBUGMSG(("dumpv_send", "\n")); return data;}/* * asn_parse_null - Interprets an ASN null 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. * * 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_null( 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 */u_char *asn_parse_null(u_char * data, size_t * datalength, u_char * type){ /* * ASN.1 null ::= 0x05 0x00 */ register u_char *bufp = data; u_long asn_length; *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (bufp == NULL) { ERROR_MSG("parse null: bad length"); return NULL; } if (asn_length != 0) { ERROR_MSG("parse null: malformed ASN.1 null"); return NULL; } *datalength -= (bufp - data); DEBUGDUMPSETUP("recv", data, bufp - data); DEBUGMSG(("dumpv_recv", " NULL\n")); return bufp + asn_length;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -