asn1.cpp
来自「HP公司的SNMP++的Win32版本源码」· C++ 代码 · 共 1,758 行 · 第 1/4 页
CPP
1,758 行
int length)
{
if (*datalength < 1)
return NULL;
*data++ = type;
(*datalength)--;
return asn_build_length(data, datalength, length);
};
/*
* asn_build_sequence - builds an ASN header for a sequence with the ID and
* length specified.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* in this object following the id and length.
*
* This only works on data types < 30, i.e. no extension octets.
* The maximum length is 0xFFFF;
*
* Returns a pointer to the first byte of the contents of this object.
* Returns NULL on any error.
*/
unsigned char * asn_build_sequence( unsigned char *data,
int *datalength,
unsigned char type,
int length)
{
*datalength -= 4;
if (*datalength < 0){
*datalength += 4; /* fix up before punting */
return NULL;
}
*data++ = type;
*data++ = (unsigned char)(0x02 | ASN_LONG_LEN);
*data++ = (unsigned char)((length >> 8) & 0xFF);
*data++ = (unsigned char)(length & 0xFF);
return data;
};
/*
* 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.
*/
unsigned char * asn_parse_length( unsigned char *data,
unsigned long *length)
{
unsigned char lengthbyte = *data;
if (lengthbyte & ASN_LONG_LEN){
lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
if (lengthbyte == 0){
ASNERROR("We don't support indefinite lengths");
return NULL;
}
if (lengthbyte > sizeof(long)){
ASNERROR("we can't support data lengths that long");
return NULL;
}
// fixed
memcpy((char *)length, (char *)data + 1, (int)lengthbyte);
*length = ntohl(*length);
*length >>= (8 * ((sizeof *length) - lengthbyte));
return data + lengthbyte + 1;
} else { /* short asnlength */
*length = (long)lengthbyte;
return data + 1;
}
};
unsigned char *asn_build_length( unsigned char *data,
int *datalength,
int length)
{
unsigned char *start_data = data;
/* no indefinite lengths sent */
if (length < 0x80){
if (*datalength < 1){
ASNERROR("build_length");
return NULL;
}
*data++ = (unsigned char)length;
} else if (length <= 0xFF){
if (*datalength < 2){
ASNERROR("build_length");
return NULL;
}
*data++ = (unsigned char)(0x01 | ASN_LONG_LEN);
*data++ = (unsigned char)length;
} else { /* 0xFF < length <= 0xFFFF */
if (*datalength < 3){
ASNERROR("build_length");
return NULL;
}
*data++ = (unsigned char)(0x02 | ASN_LONG_LEN);
*data++ = (unsigned char)((length >> 8) & 0xFF);
*data++ = (unsigned 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.
*/
unsigned char *asn_parse_objid( unsigned char *data,
int *datalength,
unsigned char *type,
oid *objid,
int *objidlength)
{
/*
* ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
* subidentifier ::= {leadingbyte}* lastbyte
* leadingbyte ::= 1 7bitvalue
* lastbyte ::= 0 7bitvalue
*/
unsigned char *bufp = data;
oid *oidp = objid + 1;
unsigned long subidentifier;
long length;
unsigned long asn_length;
*type = *bufp++;
bufp = asn_parse_length(bufp, &asn_length);
if (bufp == NULL)
return NULL;
if ((int)asn_length + (bufp - data) > *datalength){
ASNERROR("overflow of message");
return NULL;
}
*datalength -= (int)asn_length + (bufp - data);
/* 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) + (*(unsigned char *)bufp & ~ASN_BIT8);
length--;
} while (*(unsigned char *)bufp++ & ASN_BIT8); /* last byte has high bit clear */
if (subidentifier > (unsigned long)MAX_SUBID){
ASNERROR("subidentifier too long");
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 = (unsigned long)objid[1];
if (subidentifier == 0x2B){
objid[0] = 1;
objid[1] = 3;
} else {
objid[1] = (unsigned char)(subidentifier % 40);
objid[0] = (unsigned char)((subidentifier - objid[1]) / 40);
}
*objidlength = (int)(oidp - objid);
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.
*/
unsigned char *asn_build_objid( unsigned char *data,
int *datalength,
unsigned char type,
oid *objid,
int objidlength)
{
/*
* ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
* subidentifier ::= {leadingbyte}* lastbyte
* leadingbyte ::= 1 7bitvalue
* lastbyte ::= 0 7bitvalue
*/
unsigned char buf[MAX_OID_LEN];
unsigned char *bp = buf;
oid *op = objid;
int asnlength;
unsigned long subid, mask, testmask;
int bits, testbits;
if (objidlength < 2){
*bp++ = 0;
objidlength = 0;
} else {
*bp++ = (unsigned char) (op[1] + (op[0] * 40));
objidlength -= 2;
op += 2;
}
while(objidlength-- > 0){
subid = *op++;
if (subid < 127){ /* off by one? */
*bp++ = (unsigned char )subid;
} else {
mask = 0x7F; /* handle subid == 0 case */
bits = 0;
/* testmask *MUST* !!!! be of an unsigned type */
for(testmask = 0x7F, testbits = 0; testmask != 0;
testmask <<= 7, testbits += 7){
if (subid & testmask){ /* if any bits set */
mask = testmask;
bits = testbits;
}
}
/* mask can't be zero here */
for(;mask != 0x7F; mask >>= 7, bits -= 7){
/* fix a mask that got truncated above */
if (mask == 0x1E00000)
mask = 0xFE00000;
*bp++ = (unsigned char)(((subid & mask) >> bits) | ASN_BIT8);
}
*bp++ = (unsigned char)(subid & mask);
}
}
asnlength = bp - buf;
data = asn_build_header(data, datalength, type, asnlength);
if (data == NULL)
return NULL;
if (*datalength < asnlength)
return NULL;
// fixed
memcpy((char *)data, (char *)buf, asnlength);
*datalength -= asnlength;
return data + asnlength;
};
/*
* 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.
*/
unsigned char *asn_parse_null(unsigned char *data,
int *datalength,
unsigned char *type)
{
/*
* ASN.1 null ::= 0x05 0x00
*/
unsigned char *bufp = data;
unsigned long asn_length;
*type = *bufp++;
bufp = asn_parse_length(bufp, &asn_length);
if (bufp == NULL)
return NULL;
if (asn_length != 0){
ASNERROR("Malformed NULL");
return NULL;
}
*datalength -= (bufp - data);
return bufp + asn_length;
};
/*
* 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.
*/
unsigned char *asn_build_null( unsigned char *data,
int *datalength,
unsigned char type)
{
/*
* ASN.1 null ::= 0x05 0x00
*/
return asn_build_header(data, datalength, type, 0);
};
/*
* 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.
*/
unsigned char *asn_parse_bitstring( unsigned char *data,
int *datalength,
unsigned char *type,
unsigned char *string,
int *strlength)
{
/*
* bitstring ::= 0x03 asnlength unused {byte}*
*/
unsigned char *bufp = data;
unsigned long asn_length;
*type = *bufp++;
bufp = asn_parse_length(bufp, &asn_length);
if (bufp == NULL)
return NULL;
if ((int)(asn_length + (bufp - data)) > *datalength){
ASNERROR("overflow of message");
return NULL;
}
if ((int) asn_length > *strlength){
ASNERROR("I don't support such long bitstrings");
return NULL;
}
if (asn_length < 1){
ASNERROR("Invalid bitstring");
return NULL;
}
//if (*bufp < 0 || *bufp > 7){
//ASNERROR("Invalid bitstring");
//return NULL;
//}
// fixed
memcpy((char *)string,(char *)bufp, (int)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.
*/
unsigned char *asn_build_bitstring( unsigned char *data,
int *datalength,
unsigned char type,
unsigned char *string,
int strlength)
{
/*
* ASN.1 bit string ::= 0x03 asnlength unused {byte}*
*/
//if (strlength < 1 || *string < 0 || *string > 7){
//ASNERROR("Building invalid bitstring");
//return NULL;
//}
data = asn_build_header(data, datalength, type, strlength);
if (data == NULL)
return NULL;
if (*datalength < strlength)
return NULL;
// fixed
memcpy((char *)data,(char *)string, strlength);
*datalength -= strlength;
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.
*/
unsigned char * asn_parse_unsigned_int64( unsigned char *data,
int *datalength,
unsigned char *type,
struct counter64 *cp,
int countersize)
{
/*
* ASN.1 integer ::= 0x02 asnlength byte {byte}*
*/
unsigned char *bufp = data;
unsigned long asn_length;
unsigned long low = 0, high = 0;
int intsize = 4;
if (countersize != sizeof(struct counter64)){
ASNERROR("not right size");
return NULL;
}
*type = *bufp++;
bufp = asn_parse_length(bufp, &asn_length);
if (bufp == NULL){
ASNERROR("bad length");
return NULL;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?