]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
tls: keep pointers to all certificates in chain
authorEric Leblond <eric@regit.org>
Wed, 18 Jul 2012 13:13:49 +0000 (15:13 +0200)
committerEric Leblond <eric@regit.org>
Fri, 24 Aug 2012 10:59:12 +0000 (12:59 +0200)
When multiple certificates forming a chain are sent. A pointer to
the start of each certificate is kept. This will allow treatment
on certificates chains.

src/app-layer-ssl.c
src/app-layer-ssl.h
src/app-layer-tls-handshake.c

index 6c71a44c19839d5ccf9b815cdf516e39543c867c..1571636317bf2f96a4d3d3943e7266fb62c00bf0 100644 (file)
@@ -862,6 +862,7 @@ void *SSLStateAlloc(void)
     memset(ssl_state, 0, sizeof(SSLState));
     ((SSLState*)ssl_state)->client_connp.cert_log_flag = 0;
     ((SSLState*)ssl_state)->server_connp.cert_log_flag = 0;
+    TAILQ_INIT(&((SSLState*)ssl_state)->server_connp.certs);
 
     return ssl_state;
 }
@@ -873,6 +874,7 @@ void *SSLStateAlloc(void)
 void SSLStateFree(void *p)
 {
     SSLState *ssl_state = (SSLState *)p;
+    SSLCertsChain *item;
 
     if (ssl_state->client_connp.trec)
         SCFree(ssl_state->client_connp.trec);
@@ -892,6 +894,13 @@ void SSLStateFree(void *p)
     if (ssl_state->server_connp.cert0_fingerprint)
         SCFree(ssl_state->server_connp.cert0_fingerprint);
 
+    /* Free certificate chain */
+    while ((item = TAILQ_FIRST(&ssl_state->server_connp.certs))) {
+        TAILQ_REMOVE(&ssl_state->server_connp.certs, item, next);
+        SCFree(item);
+    }
+    TAILQ_INIT(&ssl_state->server_connp.certs);
+
     SCFree(ssl_state);
 
     return;
index 1d6f1f81bbcfe20c59910928ac8d13c43e8d33a0..9ca516f7b4e3d4138cc7b31a9d1621143b8631da 100644 (file)
@@ -27,6 +27,7 @@
 #define __APP_LAYER_SSL_H__
 
 #include "decode-events.h"
+#include "queue.h"
 
 enum {
     /* TLS protocol messages */
@@ -79,6 +80,13 @@ enum {
     TLS_VERSION_12 = 0x0303,
 };
 
+typedef struct SSLCertsChain_ {
+    uint8_t *cert_data;
+    uint32_t cert_len;
+    TAILQ_ENTRY(SSLCertsChain_) next;
+} SSLCertsChain;
+
+
 typedef struct SSLStateConnp_ {
     /* record length */
     uint32_t record_length;
@@ -108,6 +116,8 @@ typedef struct SSLStateConnp_ {
     uint8_t *cert_input;
     uint32_t cert_input_len;
 
+    TAILQ_HEAD(, SSLCertsChain_) certs;
+
     uint32_t cert_log_flag;
 
     /* buffer for the tls record.
index 8c086cbeec9e3d7b01beb2c3fd70d33309fe8abc..a9cffe09bf5e971aae7d07df9aeeb8231a890b39 100644 (file)
@@ -122,6 +122,7 @@ int DecodeTLSHandshakeServerCertificate(SSLState *ssl_state, uint8_t *input, uin
             if (rc != 0) {
                 TLSCertificateErrCodeToWarning(ssl_state, errcode);
             } else {
+                SSLCertsChain *ncert;
                 //SCLogInfo("TLS Cert %d: %s\n", i, buffer);
                 if (i==0) {
                     ssl_state->server_connp.cert0_subject = SCStrdup(buffer);
@@ -130,6 +131,15 @@ int DecodeTLSHandshakeServerCertificate(SSLState *ssl_state, uint8_t *input, uin
                         return -1;
                     }
                 }
+                ncert = (SSLCertsChain *)SCMalloc(sizeof(SSLCertsChain));
+                if (ncert == NULL) {
+                        DerFree(cert);
+                        return -1;
+                }
+                memset(ncert, 0, sizeof(*ncert));
+                ncert->cert_data = input;
+                ncert->cert_len = cur_cert_length;
+                TAILQ_INSERT_TAIL(&ssl_state->server_connp.certs, ncert, next);
             }
             rc = Asn1DerGetIssuerDN(cert, buffer, sizeof(buffer), &errcode);
             if (rc != 0) {