]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
TLS: add variable to store the error code in the decoder
authorPierre Chifflier <pierre.chifflier@ssi.gouv.fr>
Tue, 13 Mar 2012 21:08:39 +0000 (22:08 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 19 Mar 2012 11:13:04 +0000 (12:13 +0100)
Use a variable to store the decoding error code if required, and remove
the calls to SCLogInfo and SCLogDebug.

src/app-layer-ssl.c
src/app-layer-ssl.h
src/app-layer-tls-handshake.c
src/util-decode-der-get.c
src/util-decode-der-get.h
src/util-decode-der.c
src/util-decode-der.h

index e32fd6325754e3c8a69c8532c4bc0d0c03570b87..0f5193fb035fb10c577348d150f47b5709edefc2 100644 (file)
 
 SCEnumCharMap tls_decoder_event_table[ ] = {
     /* TLS protocol messages */
-    { "INVALID_SSLV2_HEADER",       TLS_DECODER_EVENT_INVALID_SSLV2_HEADER },
-    { "INVALID_TLS_HEADER",         TLS_DECODER_EVENT_INVALID_TLS_HEADER },
-    { "INVALID_RECORD_TYPE",        TLS_DECODER_EVENT_INVALID_RECORD_TYPE },
-    { "INVALID_HANDSHAKE_MESSAGE",  TLS_DECODER_EVENT_INVALID_HANDSHAKE_MESSAGE },
+    { "INVALID_SSLV2_HEADER",        TLS_DECODER_EVENT_INVALID_SSLV2_HEADER },
+    { "INVALID_TLS_HEADER",          TLS_DECODER_EVENT_INVALID_TLS_HEADER },
+    { "INVALID_RECORD_TYPE",         TLS_DECODER_EVENT_INVALID_RECORD_TYPE },
+    { "INVALID_HANDSHAKE_MESSAGE",   TLS_DECODER_EVENT_INVALID_HANDSHAKE_MESSAGE },
     /* Certificates decoding messages */
-    { "INVALID_CERTIFICATE",        TLS_DECODER_EVENT_INVALID_CERTIFICATE },
-    { "CERTIFICATE_MISSING_FIELD",  TLS_DECODER_EVENT_CERTIFICATE_MISSING_FIELD },
-    { NULL,                      -1 },
+    { "INVALID_CERTIFICATE",         TLS_DECODER_EVENT_INVALID_CERTIFICATE },
+    { "CERTIFICATE_MISSING_ELEMENT", TLS_DECODER_EVENT_CERTIFICATE_MISSING_ELEMENT },
+    { "CERTIFICATE_UNKNOWN_ELEMENT", TLS_DECODER_EVENT_CERTIFICATE_UNKNOWN_ELEMENT },
+    { "CERTIFICATE_INVALID_LENGTH",  TLS_DECODER_EVENT_CERTIFICATE_INVALID_LENGTH },
+    { "CERTIFICATE_INVALID_STRING",  TLS_DECODER_EVENT_CERTIFICATE_INVALID_STRING },
+    { NULL,                          -1 },
 };
 
 typedef struct SslConfig_ {
index 21309108d0c1384a1e325f39d09072eaf31a455e..b1751740fdeed1fbb2700f1b3f509c8c7aeb6644 100644 (file)
@@ -36,7 +36,10 @@ enum {
     TLS_DECODER_EVENT_INVALID_HANDSHAKE_MESSAGE,
     /* Certificates decoding messages */
     TLS_DECODER_EVENT_INVALID_CERTIFICATE,
-    TLS_DECODER_EVENT_CERTIFICATE_MISSING_FIELD,
+    TLS_DECODER_EVENT_CERTIFICATE_MISSING_ELEMENT,
+    TLS_DECODER_EVENT_CERTIFICATE_UNKNOWN_ELEMENT,
+    TLS_DECODER_EVENT_CERTIFICATE_INVALID_LENGTH,
+    TLS_DECODER_EVENT_CERTIFICATE_INVALID_STRING,
 };
 
 /* Flag to indicate that server will now on send encrypted msgs */
index 88adb8826855a33c61d9c5686d797caefb455b7e..5c1089f5fb28f2c593bf28e471fa17891e60d981 100644 (file)
 
 #define SSLV3_RECORD_LEN 5
 
+static void TLSCertificateErrCodeToWarning(SSLState *ssl_state, uint32_t errcode)
+{
+    if (errcode == 0)
+        return;
+
+    switch (errcode) {
+    case ERR_DER_ELEMENT_SIZE_TOO_BIG:
+    case ERR_DER_INVALID_SIZE:
+        AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_CERTIFICATE_INVALID_LENGTH);
+        break;
+    case ERR_DER_UNSUPPORTED_STRING:
+        AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_CERTIFICATE_INVALID_STRING);
+        break;
+    case ERR_DER_UNKNOWN_ELEMENT:
+        AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_CERTIFICATE_UNKNOWN_ELEMENT);
+        break;
+    case ERR_DER_MISSING_ELEMENT:
+        AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_CERTIFICATE_MISSING_ELEMENT);
+        break;
+    case ERR_DER_GENERIC:
+    default:
+        AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_CERTIFICATE);
+        break;
+    };
+}
+
 int DecodeTLSHandshakeServerHello(SSLState *ssl_state, uint8_t *input, uint32_t input_len)
 {
     uint32_t version, length, ciphersuite;
@@ -99,6 +125,7 @@ int DecodeTLSHandshakeServerCertificate(SSLState *ssl_state, uint8_t *input, uin
     int rc;
     int parsed;
     uint8_t *start_data;
+    uint32_t errcode;
 
     if (input_len < 3)
         return 1;
@@ -119,20 +146,17 @@ int DecodeTLSHandshakeServerCertificate(SSLState *ssl_state, uint8_t *input, uin
         parsed += 3;
 
         if (input - start_data + cur_cert_length > input_len) {
-            SCLogWarning(SC_ERR_ALPARSER, "ASN.1 structure contains invalid length\n");
             AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_CERTIFICATE);
             return -1;
         }
-        cert = DecodeDer(input, cur_cert_length);
+        cert = DecodeDer(input, cur_cert_length, &errcode);
         if (cert == NULL) {
-            SCLogWarning(SC_ERR_ALPARSER, "decoding ASN.1 structure for X509 certificate failed\n");
-            AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_INVALID_CERTIFICATE);
+            TLSCertificateErrCodeToWarning(ssl_state, errcode);
         }
         if (cert != NULL) {
-            rc = Asn1DerGetSubjectDN(cert, buffer, sizeof(buffer));
+            rc = Asn1DerGetSubjectDN(cert, buffer, sizeof(buffer), &errcode);
             if (rc != 0) {
-                SCLogWarning(SC_ERR_ALPARSER, "X509: could not get subject\n");
-                AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_CERTIFICATE_MISSING_FIELD);
+                TLSCertificateErrCodeToWarning(ssl_state, errcode);
             } else {
                 //SCLogInfo("TLS Cert %d: %s\n", i, buffer);
                 if (i==0) {
@@ -143,10 +167,9 @@ int DecodeTLSHandshakeServerCertificate(SSLState *ssl_state, uint8_t *input, uin
                     }
                 }
             }
-            rc = Asn1DerGetIssuerDN(cert, buffer, sizeof(buffer));
+            rc = Asn1DerGetIssuerDN(cert, buffer, sizeof(buffer), &errcode);
             if (rc != 0) {
-                SCLogWarning(SC_ERR_ALPARSER, "X509: could not get issuerdn\n");
-                AppLayerDecoderEventsSetEvent(ssl_state->f, TLS_DECODER_EVENT_CERTIFICATE_MISSING_FIELD);
+                TLSCertificateErrCodeToWarning(ssl_state, errcode);
             } else {
                 //SCLogInfo("TLS IssuerDN %d: %s\n", i, buffer);
                 if (i==0) {
index 0da7df7dd25e12bf1712ce3508526dca45eec580..75972acbcc31ff15a0deb7e2a71dfbe08b06320f 100644 (file)
@@ -86,12 +86,15 @@ static const char *Oid2ShortStr(const char *oid)
  *
  * \retval The matching node, or NULL
  */
-const Asn1Generic * Asn1DerGet(const Asn1Generic *top, const uint8_t *seq_index, const uint32_t seqsz)
+const Asn1Generic * Asn1DerGet(const Asn1Generic *top, const uint8_t *seq_index, const uint32_t seqsz, uint32_t *errcode)
 {
     const Asn1Generic * node;
     uint8_t idx, i;
     uint8_t offset = 0;
 
+    if (errcode)
+        *errcode = ERR_DER_MISSING_ELEMENT;
+
     node = top;
     if (node == NULL || seq_index == NULL)
         return NULL;
@@ -127,10 +130,13 @@ const Asn1Generic * Asn1DerGet(const Asn1Generic *top, const uint8_t *seq_index,
         node = node->data;
     }
 
+    if (errcode)
+        *errcode = 0;
+
     return node;
 }
 
-int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length)
+int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode)
 {
     const Asn1Generic *node_oid;
     const Asn1Generic *node, *it;
@@ -140,11 +146,14 @@ int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length)
     int rc = -1;
     const char *separator = ", ";
 
+    if (errcode)
+        *errcode = ERR_DER_MISSING_ELEMENT;
+
     if (length < 10)
         goto issuer_dn_error;
     buffer[0] = '\0';
 
-    node = Asn1DerGet(cert, SEQ_IDX_ISSUER, sizeof(SEQ_IDX_ISSUER));
+    node = Asn1DerGet(cert, SEQ_IDX_ISSUER, sizeof(SEQ_IDX_ISSUER), errcode);
     if ((node == NULL) || node->type != ASN1_SEQUENCE)
         goto issuer_dn_error;
 
@@ -180,7 +189,8 @@ int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length)
                 strlcat(buffer, node_str->str, length);
                 break;
             default:
-                SCLogInfo("Unsupported 'string' type:'%d'", node_str->type);
+                if (errcode)
+                    *errcode = ERR_DER_UNSUPPORTED_STRING;
                 goto issuer_dn_error;
         }
 
@@ -191,12 +201,15 @@ int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length)
         it = it->next;
     }
 
+    if (errcode)
+        *errcode = 0;
+
     rc = 0;
 issuer_dn_error:
     return rc;
 }
 
-int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length)
+int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode)
 {
     const Asn1Generic *node_oid;
     const Asn1Generic *node, *it;
@@ -206,11 +219,14 @@ int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length)
     int rc = -1;
     const char *separator = ", ";
 
+    if (errcode)
+        *errcode = ERR_DER_MISSING_ELEMENT;
+
     if (length < 10)
         goto subject_dn_error;
     buffer[0] = '\0';
 
-    node = Asn1DerGet(cert, SEQ_IDX_SUBJECT, sizeof(SEQ_IDX_SUBJECT));
+    node = Asn1DerGet(cert, SEQ_IDX_SUBJECT, sizeof(SEQ_IDX_SUBJECT), errcode);
 
     if ((node == NULL) || node->type != ASN1_SEQUENCE)
         goto subject_dn_error;
@@ -247,7 +263,8 @@ int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length)
                 strlcat(buffer, node_str->str, length);
                 break;
             default:
-                SCLogInfo("Unsupported 'string' type:'%d'", node_str->type);
+                if (errcode)
+                    *errcode = ERR_DER_UNSUPPORTED_STRING;
                 goto subject_dn_error;
         }
 
@@ -257,7 +274,9 @@ int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length)
             strlcat(buffer, separator, length);
         it = it->next;
     }
-    SCLogDebug("read subject:'%s'", buffer);
+
+    if (errcode)
+        *errcode = 0;
 
     rc = 0;
 subject_dn_error:
index 9d2d323b8ced2bf329a40f968363448a9adc5527..79ecd7879c84c7d93431d0191cd7c36be5945532 100644 (file)
@@ -35,9 +35,9 @@
 #ifndef __UTIL_DECODE_DER_GET_H__
 #define __UTIL_DECODE_DER_GET_H__
 
-const Asn1Generic * Asn1DerGet(const Asn1Generic *top, const uint8_t *seq_index, const uint32_t seqsz);
+const Asn1Generic * Asn1DerGet(const Asn1Generic *top, const uint8_t *seq_index, const uint32_t seqsz, uint32_t *errcode);
 
-int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length);
-int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length);
+int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode);
+int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode);
 
 #endif /* __UTIL_DECODE_DER_GET_H__ */
index e0b273a03f7c2cebf27f6a99c3b0b90d787d97e6..b06942c65cdd44c9fa4d8f4eb545a60780828e56 100644 (file)
 
 #define MAX_OID_LENGTH 256
 
-static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer, uint32_t max_size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, uint32_t size, uint8_t depth);
-static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, uint32_t size, uint8_t depth);
+static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
+static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode);
 
 static Asn1Generic * Asn1GenericNew(void)
 {
@@ -105,7 +105,7 @@ static void Asn1SequenceAppend(Asn1Generic *seq, Asn1Generic *node)
     it->next = new_container;
 }
 
-static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t max_size, uint8_t depth, int seq_index)
+static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t max_size, uint8_t depth, int seq_index, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint32_t numbytes, el_max_size;
@@ -152,43 +152,43 @@ static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t
     el_max_size = max_size - (d_ptr-buffer);
     switch (el_type) {
         case ASN1_INTEGER:
-            child = DecodeAsn1DerInteger(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerInteger(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_BOOLEAN:
-            child = DecodeAsn1DerBoolean(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerBoolean(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_NULL:
-            child = DecodeAsn1DerNull(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerNull(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_BITSTRING:
-            child = DecodeAsn1DerBitstring(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerBitstring(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_OID:
-            child = DecodeAsn1DerOid(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerOid(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_IA5STRING:
-            child = DecodeAsn1DerIA5String(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerIA5String(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_OCTETSTRING:
-            child = DecodeAsn1DerOctetString(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerOctetString(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_UTF8STRING:
-            child = DecodeAsn1DerUTF8String(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerUTF8String(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_PRINTSTRING:
-            child = DecodeAsn1DerPrintableString(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerPrintableString(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_SEQUENCE:
-            child = DecodeAsn1DerSequence(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerSequence(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_SET:
-            child = DecodeAsn1DerSet(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerSet(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_T61STRING:
-            child = DecodeAsn1DerT61String(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerT61String(d_ptr, el_max_size, depth+1, errcode);
             break;
         case ASN1_UTCTIME:
-            child = DecodeAsn1DerUTCTime(d_ptr, el_max_size, depth+1);
+            child = DecodeAsn1DerUTCTime(d_ptr, el_max_size, depth+1, errcode);
             break;
         default:
             /* unknown ASN.1 type */
@@ -208,8 +208,8 @@ static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t
                 numbytes = c & 0x7f;
                 if (numbytes > el_max_size) {
                     SCFree(child);
-                    SCLogWarning(SC_ERR_INVALID_VALUE,
-                                 "DER message requires to read over message");
+                    if (errcode)
+                        *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG;
                     return NULL;
                 }
                 child->length = 0;
@@ -232,7 +232,7 @@ static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t
     return child;
 }
 
-static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint8_t numbytes;
@@ -243,8 +243,8 @@ static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t
     numbytes = d_ptr[1];
 
     if (numbytes > size) {
-        SCLogWarning(SC_ERR_INVALID_VALUE,
-                     "DER message requires to read over available data");
+        if (errcode)
+            *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG;
         return NULL;
     }
 
@@ -283,12 +283,13 @@ static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t
     return a;
 }
 
-static int DecodeAsn1BuildValue(const unsigned char **d_ptr, uint32_t *val, uint8_t numbytes)
+static int DecodeAsn1BuildValue(const unsigned char **d_ptr, uint32_t *val, uint8_t numbytes, uint32_t *errcode)
 {
     int i;
     uint32_t value = 0;
     if (numbytes > 4) {
-        SCLogDebug("Invalid ASN.1 num bytes: %d", numbytes);
+        if (errcode)
+            *errcode = ERR_DER_INVALID_SIZE;
         /* too big won't fit: set it to 0xffffffff by convention */
         value = 0xffffffff;
         *val = value;
@@ -303,7 +304,7 @@ static int DecodeAsn1BuildValue(const unsigned char **d_ptr, uint32_t *val, uint
     return 0;
 }
 
-static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint8_t numbytes;
@@ -313,7 +314,7 @@ static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t
     numbytes = d_ptr[1];
     d_ptr += 2;
 
-    if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes) == -1) {
+    if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes, errcode) == -1) {
         return NULL;
     }
     a = Asn1GenericNew();
@@ -326,7 +327,7 @@ static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t
     return a;
 }
 
-static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint8_t numbytes;
@@ -335,7 +336,7 @@ static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t siz
 
     numbytes = d_ptr[1];
     d_ptr += 2;
-    if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes) == -1) {
+    if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes, errcode) == -1) {
         return NULL;
     }
     a = Asn1GenericNew();
@@ -348,7 +349,7 @@ static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t siz
     return a;
 }
 
-static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_t max_size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint32_t length;
@@ -365,7 +366,7 @@ static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_
     } else { /* long form 8.1.3.5 */
         numbytes = c & 0x7f;
         d_ptr++;
-        if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes) == -1) {
+        if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
             return NULL;
         }
     }
@@ -390,7 +391,7 @@ static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_
     return a;
 }
 
-static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t max_size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint32_t oid_length, oid_value;
@@ -408,7 +409,7 @@ static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t max_
     } else { /* long form 8.1.3.5 */
         numbytes = c & 0x7f;
         d_ptr++;
-        if (DecodeAsn1BuildValue(&d_ptr, &oid_length, numbytes) == -1) {
+        if (DecodeAsn1BuildValue(&d_ptr, &oid_length, numbytes, errcode) == -1) {
             return NULL;
         }
     }
@@ -451,7 +452,7 @@ static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t max_
     return a;
 }
 
-static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_t max_size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint32_t length, numbytes;
@@ -468,7 +469,7 @@ static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_
     } else { /* long form 8.1.3.5 */
         numbytes = c & 0x7f;
         d_ptr++;
-        if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes) == -1) {
+        if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
             return NULL;
         }
     }
@@ -493,7 +494,7 @@ static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_
     return a;
 }
 
-static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint32_t max_size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint32_t length, numbytes;
@@ -510,7 +511,7 @@ static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint3
     } else { /* long form 8.1.3.5 */
         numbytes = c & 0x7f;
         d_ptr++;
-        if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes) == -1) {
+        if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
             return NULL;
         }
     }
@@ -538,15 +539,15 @@ static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint3
     return a;
 }
 
-static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer, uint32_t max_size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
 {
-    Asn1Generic *a = DecodeAsn1DerOctetString(buffer, max_size, depth);
+    Asn1Generic *a = DecodeAsn1DerOctetString(buffer, max_size, depth, errcode);
     if (a != NULL)
         a->type = ASN1_UTF8STRING;
     return a;
 }
 
-static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, uint32_t max_size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint32_t length, numbytes;
@@ -563,7 +564,7 @@ static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, u
     } else { /* long form 8.1.3.5 */
         numbytes = c & 0x7f;
         d_ptr++;
-        if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes) == -1) {
+        if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
             return NULL;
         }
     }
@@ -589,7 +590,7 @@ static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, u
     return a;
 }
 
-static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t max_size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint32_t d_length, parsed_bytes, numbytes, el_max_size;
@@ -613,7 +614,7 @@ static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t
     } else { /* long form 8.1.3.5 */
         numbytes = c & 0x7f;
         d_ptr++;
-        if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes) == -1) {
+        if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) {
             free(node);
             return NULL;
         }
@@ -630,7 +631,7 @@ static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t
     /* decode child elements */
     while (parsed_bytes < d_length) {
         el_max_size = max_size - (d_ptr-buffer);
-        child = DecodeAsn1DerGeneric(d_ptr, el_max_size, depth, seq_index);
+        child = DecodeAsn1DerGeneric(d_ptr, el_max_size, depth, seq_index, errcode);
 
         if (child == NULL) {
             break;
@@ -644,7 +645,7 @@ static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t
     return (Asn1Generic *)node;
 }
 
-static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint32_t d_length, numbytes, el_max_size;
@@ -669,7 +670,7 @@ static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_
     } else { /* long form 8.1.3.5 */
         numbytes = c & 0x7f;
         d_ptr++;
-        if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes) == -1) {
+        if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) {
             free(node);
             return NULL;
         }
@@ -677,9 +678,8 @@ static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_
     node->length = d_length + (d_ptr - buffer);
 
     if (node->length > max_size) {
-        SCLogInfo("Announced message length too big: %" PRIu32 " vs %" PRIu32,
-                  node->length,
-                  max_size);
+        if (errcode)
+            *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG;
         free(node);
         return NULL;
     }
@@ -687,36 +687,36 @@ static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_
     seq_index = 0;
 
     el_max_size = max_size - (d_ptr-buffer);
-    child = DecodeAsn1DerGeneric(d_ptr, el_max_size, depth, seq_index);
+    child = DecodeAsn1DerGeneric(d_ptr, el_max_size, depth, seq_index, errcode);
 
     node->data = child;
 
     return (Asn1Generic *)node;
 }
 
-static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, uint32_t max_size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
 {
     Asn1Generic *a;
 
-    a = DecodeAsn1DerIA5String(buffer, max_size, depth);
+    a = DecodeAsn1DerIA5String(buffer, max_size, depth, errcode);
     if (a != NULL)
         a->type = ASN1_T61STRING;
 
     return a;
 }
 
-static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, uint32_t max_size, uint8_t depth)
+static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode)
 {
     Asn1Generic *a;
 
-    a = DecodeAsn1DerIA5String(buffer, max_size, depth);
+    a = DecodeAsn1DerIA5String(buffer, max_size, depth, errcode);
     if (a != NULL)
         a->type = ASN1_UTCTIME;
 
     return a;
 }
 
-Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size)
+Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size, uint32_t *errcode)
 {
     const unsigned char *d_ptr = buffer;
     uint32_t d_length, numbytes;
@@ -733,13 +733,16 @@ Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size)
 
     numbytes = c & 0x7f;
     d_ptr += 2;
-    if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes) == -1) {
+    if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) {
         return NULL;
     }
     if (d_length+(d_ptr-buffer) != size)
         return NULL;
 
-    cert = DecodeAsn1DerGeneric(buffer, size, 0 /* depth */, 0);
+    if (errcode)
+        *errcode = 0;
+
+    cert = DecodeAsn1DerGeneric(buffer, size, 0 /* depth */, 0, errcode);
 
     return cert;
 }
index 854f02b97a27192ec9dbf9d927d5c58f136183cd..4c4b1aaf1c4a4da5f047af79a4495a0561677007 100644 (file)
@@ -77,7 +77,20 @@ typedef struct Asn1Generic_ {
        struct Asn1Generic_ *next; /* only if type is sequence */
 } Asn1Generic;
 
-Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size);
+/* Generic error */
+#define ERR_DER_GENERIC               0x01
+/* Unknown ASN.1 element type */
+#define ERR_DER_UNKNOWN_ELEMENT       0x02
+/* One element requires to read more bytes than available */
+#define ERR_DER_ELEMENT_SIZE_TOO_BIG  0x03
+/* One element size is invalid (more than 4 bytes long) */
+#define ERR_DER_INVALID_SIZE          0x04
+/* Unsupported string type */
+#define ERR_DER_UNSUPPORTED_STRING    0x05
+/* Missing field or element */
+#define ERR_DER_MISSING_ELEMENT       0x06
+
+Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size, uint32_t *errcode);
 void DerFree(Asn1Generic *a);
 
 #endif /* __UTIL_DECODE_DER_H__ */