]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
tls: store all ALPN records in the state
authorVictor Julien <vjulien@oisf.net>
Fri, 31 May 2024 12:18:15 +0000 (14:18 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 20 Jun 2024 04:57:21 +0000 (06:57 +0200)
For later logging and detection.

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

index 21797d678847cff50f303745f6e66b6201c8528f..6802fb18d743fe928331b6ed9786b81385f84083 100644 (file)
@@ -1258,6 +1258,18 @@ invalid_length:
     return -1;
 }
 
+static void StoreALPN(SSLStateConnp *connp, const uint8_t *alpn, const uint32_t size)
+{
+    if (size > 0) {
+        SSLAlpns *a = SCCalloc(1, sizeof(*a) + size);
+        if (a != NULL) {
+            memcpy(a->alpn, alpn, size);
+            a->size = size;
+            TAILQ_INSERT_TAIL(&connp->alpns, a, next);
+        }
+    }
+}
+
 static inline int TLSDecodeHSHelloExtensionALPN(
         SSLState *ssl_state, const uint8_t *const initial_input, const uint32_t input_len)
 {
@@ -1276,37 +1288,35 @@ static inline int TLSDecodeHSHelloExtensionALPN(
     if (!(HAS_SPACE(alpn_len)))
         goto invalid_length;
 
-    if (ssl_state->curr_connp->ja4 != NULL &&
-            ssl_state->current_flags & SSL_AL_FLAG_STATE_CLIENT_HELLO) {
-        /* We use 32 bits here to avoid potentially overflowing a value that
-           needs to be compared to an unsigned 16-bit value. */
-        uint32_t alpn_processed_len = 0;
-        while (alpn_processed_len < alpn_len) {
-            uint8_t protolen = *input;
-            input += 1;
-            alpn_processed_len += 1;
+    /* We use 32 bits here to avoid potentially overflowing a value that
+       needs to be compared to an unsigned 16-bit value. */
+    uint32_t alpn_processed_len = 0;
+    while (alpn_processed_len < alpn_len) {
+        uint8_t protolen = *input;
+        input += 1;
+        alpn_processed_len += 1;
 
-            if (!(HAS_SPACE(protolen)))
-                goto invalid_length;
+        if (!(HAS_SPACE(protolen)))
+            goto invalid_length;
 
-            /* Check if reading another protolen bytes would exceed the
-               overall ALPN length; if so, skip and continue */
-            if (alpn_processed_len + protolen > ((uint32_t)alpn_len)) {
-                input += alpn_len - alpn_processed_len;
-                break;
-            }
+        /* Check if reading another protolen bytes would exceed the
+           overall ALPN length; if so, skip and continue */
+        if (alpn_processed_len + protolen > ((uint32_t)alpn_len)) {
+            input += alpn_len - alpn_processed_len;
+            break;
+        }
 
-            /* Only record the first value for JA4 */
+        /* Only record the first value for JA4 */
+        if (ssl_state->curr_connp->ja4 != NULL &&
+                ssl_state->current_flags & SSL_AL_FLAG_STATE_CLIENT_HELLO) {
             if (alpn_processed_len == 1) {
                 SCJA4SetALPN(ssl_state->curr_connp->ja4, (const char *)input, protolen);
             }
-
-            alpn_processed_len += protolen;
-            input += protolen;
         }
-    } else {
-        /* Skip ALPN protocols */
-        input += alpn_len;
+        StoreALPN(ssl_state->curr_connp, input, protolen);
+
+        alpn_processed_len += protolen;
+        input += protolen;
     }
 
     return (input - initial_input);
@@ -2839,7 +2849,9 @@ static void *SSLStateAlloc(void *orig_state, AppProto proto_orig)
     memset(ssl_state->client_connp.random, 0, TLS_RANDOM_LEN);
     memset(ssl_state->server_connp.random, 0, TLS_RANDOM_LEN);
     TAILQ_INIT(&ssl_state->server_connp.certs);
+    TAILQ_INIT(&ssl_state->server_connp.alpns);
     TAILQ_INIT(&ssl_state->client_connp.certs);
+    TAILQ_INIT(&ssl_state->client_connp.alpns);
 
     return (void *)ssl_state;
 }
@@ -2930,6 +2942,18 @@ static void SSLStateFree(void *p)
     }
     TAILQ_INIT(&ssl_state->client_connp.certs);
 
+    SSLAlpns *a;
+    while ((a = TAILQ_FIRST(&ssl_state->server_connp.alpns))) {
+        TAILQ_REMOVE(&ssl_state->server_connp.alpns, a, next);
+        SCFree(a);
+    }
+    TAILQ_INIT(&ssl_state->server_connp.alpns);
+    while ((a = TAILQ_FIRST(&ssl_state->client_connp.alpns))) {
+        TAILQ_REMOVE(&ssl_state->client_connp.alpns, a, next);
+        SCFree(a);
+    }
+    TAILQ_INIT(&ssl_state->client_connp.alpns);
+
     SCFree(ssl_state);
 }
 
index 90217b037c33c10fc59fcd29df87d693a40b3673..479ccf51921d9f9561ee08b4e18fd916413d6dd9 100644 (file)
@@ -226,6 +226,11 @@ typedef struct SSLCertsChain_ {
     TAILQ_ENTRY(SSLCertsChain_) next;
 } SSLCertsChain;
 
+typedef struct SSLAlpns_ {
+    TAILQ_ENTRY(SSLAlpns_) next;
+    uint32_t size;
+    uint8_t alpn[];
+} SSLAlpns;
 
 typedef struct SSLStateConnp_ {
     /* record length */
@@ -262,6 +267,7 @@ typedef struct SSLStateConnp_ {
     char *session_id;
 
     TAILQ_HEAD(, SSLCertsChain_) certs;
+    TAILQ_HEAD(, SSLAlpns_) alpns;
 
     uint8_t *certs_buffer;
     uint32_t certs_buffer_size;