Make the signatures of functions passed to "register_tap_listener()"
[obnox/wireshark/wip.git] / asn1.c
diff --git a/asn1.c b/asn1.c
index afe18c8c596ccad845a42d99e86aefc208a8dd46..8edd59bcb81b9f7cdc123e5fbc16eea8c5c812de 100644 (file)
--- a/asn1.c
+++ b/asn1.c
@@ -1,7 +1,7 @@
 /* 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>
@@ -138,22 +138,21 @@ asn1_octet_decode(ASN1_SCK *asn1, guchar *ch)
 }
 
 /*
- * 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)
@@ -164,6 +163,23 @@ asn1_tag_decode(ASN1_SCK *asn1, guint *tag)
     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
@@ -182,6 +198,7 @@ asn1_id_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag)
     int    ret;
     guchar ch;
 
+    *tag = 0;
     ret = asn1_octet_decode (asn1, &ch);
     if (ret != ASN1_ERR_NOERROR)
         return ret;
@@ -196,6 +213,39 @@ asn1_id_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag)
     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
@@ -368,7 +418,17 @@ asn1_eoc_decode (ASN1_SCK *asn1, int eoc)
 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;
 }
 
@@ -506,7 +566,7 @@ done:
  * 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;
@@ -592,35 +652,59 @@ done:
  *                  )
  * 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;
 }
 
@@ -637,7 +721,8 @@ asn1_bits_decode ( ASN1_SCK *asn1, int eoc, guchar **bits,
  *              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
@@ -652,20 +737,12 @@ asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
      * 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;
@@ -677,6 +754,7 @@ asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
            return ret;
        }
     }
+    *(guchar *)ptr = '\0';
     return ASN1_ERR_NOERROR;
 }
 
@@ -819,10 +897,11 @@ asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
      * 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;