📄 asn1.c
字号:
{
/*
* 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("dump_recv", data, bufp - data);
DEBUGMSG(("dump_recv", " ASN NULL\n"));
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.
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
*/
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.
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("dump_recv", data, bufp - data);
DEBUGMSG(("dump_recv", " ASN Bitstring: "));
DEBUGMSGHEX(("dump_recv", data, asn_length));
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))
return NULL;
data = asn_build_header(data, datalength, type, strlength);
if (_asn_build_header_check(errpre,data,*datalength,strlength))
return NULL;
memmove(data, 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.
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("dump_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))) {
DEBUGMSG(("dump_recv", "Opaque %.2x %.2x: ", *bufp, *(bufp+1)));
/* 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("dump_recv") {
char i64buf[I64CHARSZ+1];
printU64(i64buf, cp);
}
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;
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;
}
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -