/* asn1.c
* Routines for ASN.1 BER dissection
*
- * $Id: asn1.c,v 1.17 2002/08/28 21:00:05 jmayer Exp $
+ * $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
}
/*
- * NAME: asn1_tag_decode
- * SYNOPSIS: int asn1_tag_decode
+ * NAME: asn1_tag_get
+ * SYNOPSIS: int asn1_tag_get
* (
* ASN1_SCK *asn1,
* guint *tag
* )
- * DESCRIPTION: Decodes a tag.
+ * DESCRIPTION: Decodes a tag number, combining it with existing tag bits.
* RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
*/
-int
-asn1_tag_decode(ASN1_SCK *asn1, guint *tag)
+static int
+asn1_tag_get(ASN1_SCK *asn1, guint *tag)
{
int ret;
guchar ch;
- *tag = 0;
do {
ret = asn1_octet_decode (asn1, &ch);
if (ret != ASN1_ERR_NOERROR)
return ASN1_ERR_NOERROR;
}
+/*
+ * NAME: asn1_tag_decode
+ * SYNOPSIS: int asn1_tag_decode
+ * (
+ * ASN1_SCK *asn1,
+ * guint *tag
+ * )
+ * DESCRIPTION: Decodes a tag number.
+ * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
+ */
+int
+asn1_tag_decode(ASN1_SCK *asn1, guint *tag)
+{
+ *tag = 0;
+ return asn1_tag_get(asn1, tag);
+}
+
/*
* NAME: asn1_id_decode
* SYNOPSIS: int asn1_id_decode
int ret;
guchar ch;
+ *tag = 0;
ret = asn1_octet_decode (asn1, &ch);
if (ret != ASN1_ERR_NOERROR)
return ret;
return ASN1_ERR_NOERROR;
}
+/*
+ * NAME: asn1_id_decode1
+ * SYNOPSIS: int asn1_id_decode1
+ * (
+ * ASN1_SCK *asn1,
+ * guint *tag
+ * )
+ * DESCRIPTION: Decodes an identifier.
+ * Like asn1_id_decode() except that the Class and Constructor
+ * bits are returned in the tag.
+ * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
+ */
+int
+asn1_id_decode1(ASN1_SCK *asn1, guint *tag)
+{
+ int ret;
+ guchar ch;
+
+ *tag = 0;
+ ret = asn1_octet_decode (asn1, &ch);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+
+ *tag = ch;
+ if ((*tag & 0x1F) == 0x1F) { /* high-tag-number format */
+ *tag = ch >> 5; /* leave just the Class and Constructor bits */
+ ret = asn1_tag_get (asn1, tag);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ }
+ return ASN1_ERR_NOERROR;
+}
+
/*
* NAME: asn1_length_decode
* SYNOPSIS: int asn1_length_decode
int
asn1_null_decode ( ASN1_SCK *asn1, int enc_len)
{
+ int start_off = asn1->offset;
+
asn1->offset += enc_len;
+ /*
+ * Check for integer overflows.
+ * XXX - ASN1_ERR_LENGTH_MISMATCH seemed like the most appropriate
+ * error from the ones available. Should we make a new one?
+ */
+ if (asn1->offset < 0 || asn1->offset < start_off)
+ return ASN1_ERR_LENGTH_MISMATCH;
+
return ASN1_ERR_NOERROR;
}
* RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
*/
int
-asn1_uint32_value_decode ( ASN1_SCK *asn1, int enc_len, guint *integer)
+asn1_uint32_value_decode ( ASN1_SCK *asn1, int enc_len, guint32 *integer)
{
int ret;
int eoc;
* )
* DESCRIPTION: Decodes Bit String.
* Parameters:
- * asn1: pointer to ASN1 socket.
- * eoc: offset of end of encoding, or -1 if indefinite.
- * bits: pointer to begin of Bit String.
- * size: Size of Bit String in characters.
- * len: Length of Bit String in characters.
- * unused: Number of unused bits in last character.
+ * asn1: pointer to ASN1 socket.
+ * enc_len: length of value.
+ * bits: pointer to variable we set to point to strring
+ * len: Size of Bit String in characters.
+ * unused: Number of unused bits in last character.
* RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
*/
int
-asn1_bits_decode ( ASN1_SCK *asn1, int eoc, guchar **bits,
+asn1_bits_decode ( ASN1_SCK *asn1, int enc_len, guchar **bits,
guint *len, guchar *unused)
-
{
int ret;
+ int eoc;
+ guchar *ptr;
+ eoc = asn1->offset + enc_len;
*bits = NULL;
ret = asn1_octet_decode (asn1, unused);
if (ret != ASN1_ERR_NOERROR)
return ret;
*len = 0;
- *bits = g_malloc(eoc - asn1->offset);
+
+ /*
+ * First, make sure the entire string is in the tvbuff, and throw
+ * an exception if it isn't. If the length is bogus, this should
+ * keep us from trying to allocate an immensely large buffer.
+ * (It won't help if the length is *valid* but immensely large,
+ * but that's another matter; in any case, that would happen only
+ * if we had an immensely large tvbuff....)
+ */
+ if (enc_len != 0) {
+ tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
+ *bits = g_malloc (enc_len);
+ } else {
+ /*
+ * If the length is 0, we allocate a 1-byte buffer, as
+ * "g_malloc()" returns NULL if passed 0 as an argument,
+ * and our caller expects us to return a pointer to a
+ * buffer.
+ */
+ *bits = g_malloc (1);
+ }
+
+ ptr = *bits;
while (asn1->offset < eoc) {
- ret = asn1_octet_decode (asn1, (guchar *)bits++);
+ ret = asn1_octet_decode (asn1, (guchar *)ptr++);
if (ret != ASN1_ERR_NOERROR) {
g_free(*bits);
*bits = NULL;
return ret;
- }
+ }
}
+ *len = ptr - *bits;
return ASN1_ERR_NOERROR;
}
* Parameters:
* asn1: pointer to ASN1 socket.
* enc_len: length of encoding of value.
- * octets: pointer to variable we set to point to string.
+ * octets: pointer to variable we set to point to string,
+ * which is '\0' terminated for ease of use as C-string
* RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
*/
int
* an exception if it isn't. If the length is bogus, this should
* keep us from trying to allocate an immensely large buffer.
* (It won't help if the length is *valid* but immensely large,
- * but that's another matter.)
+ * but that's another matter; in any case, that would happen only
+ * if we had an immensely large tvbuff....)
*/
- if (enc_len != 0) {
- tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
- *octets = g_malloc (enc_len);
- } else {
- /*
- * If the length is 0, we allocate a 1-byte buffer, as
- * "g_malloc()" returns NULL if passed 0 as an argument,
- * and our caller expects us to return a pointer to a
- * buffer.
- */
- *octets = g_malloc (1);
- }
+ if (enc_len != 0)
+ tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
+ *octets = g_malloc (enc_len+1);
eoc = asn1->offset + enc_len;
ptr = *octets;
return ret;
}
}
+ *(guchar *)ptr = '\0';
return ASN1_ERR_NOERROR;
}
* an exception if it isn't. If the length is bogus, this should
* keep us from trying to allocate an immensely large buffer.
* (It won't help if the length is *valid* but immensely large,
- * but that's another matter.)
+ * but that's another matter; in any case, that would happen only
+ * if we had an immensely large tvbuff....)
*/
if (enc_len != 0)
- tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
+ tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
eoc = asn1->offset + enc_len;