From: Pierre Chifflier Date: Tue, 13 Mar 2012 21:08:39 +0000 (+0100) Subject: TLS: add variable to store the error code in the decoder X-Git-Tag: suricata-1.3beta1~79 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d866f389820f64eaddd252bf10e284fcd0cd1702;p=thirdparty%2Fsuricata.git TLS: add variable to store the error code in the decoder Use a variable to store the decoding error code if required, and remove the calls to SCLogInfo and SCLogDebug. --- diff --git a/src/app-layer-ssl.c b/src/app-layer-ssl.c index e32fd63257..0f5193fb03 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -55,14 +55,17 @@ 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_ { diff --git a/src/app-layer-ssl.h b/src/app-layer-ssl.h index 21309108d0..b1751740fd 100644 --- a/src/app-layer-ssl.h +++ b/src/app-layer-ssl.h @@ -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 */ diff --git a/src/app-layer-tls-handshake.c b/src/app-layer-tls-handshake.c index 88adb88268..5c1089f5fb 100644 --- a/src/app-layer-tls-handshake.c +++ b/src/app-layer-tls-handshake.c @@ -52,6 +52,32 @@ #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) { diff --git a/src/util-decode-der-get.c b/src/util-decode-der-get.c index 0da7df7dd2..75972acbcc 100644 --- a/src/util-decode-der-get.c +++ b/src/util-decode-der-get.c @@ -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: diff --git a/src/util-decode-der-get.h b/src/util-decode-der-get.h index 9d2d323b8c..79ecd7879c 100644 --- a/src/util-decode-der-get.h +++ b/src/util-decode-der-get.h @@ -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__ */ diff --git a/src/util-decode-der.c b/src/util-decode-der.c index e0b273a03f..b06942c65c 100644 --- a/src/util-decode-der.c +++ b/src/util-decode-der.c @@ -60,19 +60,19 @@ #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; } diff --git a/src/util-decode-der.h b/src/util-decode-der.h index 854f02b97a..4c4b1aaf1c 100644 --- a/src/util-decode-der.h +++ b/src/util-decode-der.h @@ -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__ */