]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
tls: remove certificate buffering code
authorVictor Julien <vjulien@oisf.net>
Fri, 5 Aug 2022 12:39:57 +0000 (14:39 +0200)
committerVictor Julien <vjulien@oisf.net>
Wed, 21 Sep 2022 04:43:48 +0000 (06:43 +0200)
TCP Buffering is now done in the app-layer using the incomplete API, on
the SSL/TLS record level. TLS level fragmentation will be implemented
separately.

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

index df3186af27adaf8b0af01806afcac875ea8a1196..4154612870da1019bb27d3a57738329306f2dd12 100644 (file)
@@ -259,25 +259,13 @@ static inline int SafeMemcpy(void *dst, size_t dst_offset, size_t dst_size,
 #define ValidateRecordState(...)
 #endif
 
-#ifdef DEBUG_VALIDATION
-#define ValidateTrecBuffer(connp)                                               \
-    do {                                                                        \
-        DEBUG_VALIDATE_BUG_ON((connp)->trec_pos > (connp)->trec_len);           \
-        DEBUG_VALIDATE_BUG_ON((connp)->trec == NULL && (connp)->trec_len > 0);  \
-        DEBUG_VALIDATE_BUG_ON((connp)->trec == NULL && (connp)->trec_pos > 0);  \
-    } while(0)
-#else
-#define ValidateTrecBuffer(...)
-#endif
-
-#define SSLParserHSReset(connp)             \
-    do {                                    \
-        (connp)->trec_pos = 0;              \
-        (connp)->handshake_type = 0;        \
-        (connp)->hs_bytes_processed = 0;    \
-        (connp)->message_length = 0;        \
-        (connp)->message_start = 0;         \
-    } while(0)
+#define SSLParserHSReset(connp)                                                                    \
+    do {                                                                                           \
+        (connp)->handshake_type = 0;                                                               \
+        (connp)->hs_bytes_processed = 0;                                                           \
+        (connp)->message_length = 0;                                                               \
+        (connp)->message_start = 0;                                                                \
+    } while (0)
 
 #define SSLParserReset(state)                       \
     do {                                            \
@@ -1406,94 +1394,6 @@ end:
     return 0;
 }
 
-/** \internal
- *  \brief Get Certificates len so we can know now much (more) we need to buffer
- *  If we already have a few bytes queued up in 'trec' we use those or a mix of
- *  those with the input.
- */
-static uint32_t GetCertsLen(SSLStateConnp *curr_connp, const uint8_t *input,
-        const uint32_t input_len)
-{
-    if (curr_connp->trec != NULL && curr_connp->trec_pos > 0) {
-        if (curr_connp->trec_pos >= 3) {
-            const uint8_t * const ptr = curr_connp->trec;
-            uint32_t len = (*ptr << 16 | *(ptr + 1) << 8 | *(ptr + 2)) + 3;
-            SCLogDebug("length %u (trec)", len);
-            return len;
-        } else if (input_len + curr_connp->trec_pos >= 3) {
-            uint8_t buf[3] = { 0, 0, 0, }; // init to 0 to make scan-build happy
-            uint32_t i = 0;
-            for (uint32_t x = 0; x < curr_connp->trec_pos && i < 3;  x++) {
-                buf[i++] = curr_connp->trec[x];
-            }
-            for (uint32_t x = 0; x < input_len && i < 3;  x++) {
-                buf[i++] = input[x];
-            }
-            uint32_t len = (buf[0] << 16 | buf[1] << 8 | buf[2]) + 3;
-            SCLogDebug("length %u (part trec, part input)", len);
-            return len;
-        }
-        return 0;
-    } else if (input_len >= 3) {
-        uint32_t len = (*input << 16 | *(input + 1) << 8 | *(input + 2)) + 3;
-        SCLogDebug("length %u (input)", len);
-        return len;
-    } else {
-        SCLogDebug("length unknown (input len %u)", input_len);
-        return 0;
-    }
-}
-
-// For certificates whose size is bigger than this,
-// we do not allocate all the required memory straight away,
-// to avoid DOS by RAM exhaustion, but we will allocate
-// this memory once a consequent part of the certificate has been seen.
-#define SSL_CERT_MAX_FIRST_ALLOC 65536 // 0x10000
-
-/** \internal
- *  \brief setup or grow the `trec` space in the connp
- */
-static int EnsureRecordSpace(SSLStateConnp *curr_connp, const uint8_t * const input,
-        const uint32_t input_len)
-{
-    ValidateTrecBuffer(curr_connp);
-
-    uint32_t certs_len = GetCertsLen(curr_connp, input, input_len);
-    if (certs_len == 0) {
-        SCLogDebug("cert_len unknown still, create small buffer to start");
-        certs_len = 256;
-    }
-    // Limit in a first time allocation for very large certificates
-    if (certs_len > SSL_CERT_MAX_FIRST_ALLOC && certs_len > curr_connp->trec_pos + input_len) {
-        certs_len = SSL_CERT_MAX_FIRST_ALLOC;
-    }
-
-    if (curr_connp->trec == NULL) {
-        curr_connp->trec_len = certs_len;
-        curr_connp->trec = SCMalloc(curr_connp->trec_len);
-        if (unlikely(curr_connp->trec == NULL))
-            goto error;
-    }
-
-    if (certs_len > curr_connp->trec_len) {
-        curr_connp->trec_len = certs_len;
-        void *ptmp = SCRealloc(curr_connp->trec, curr_connp->trec_len);
-        if (unlikely(ptmp == NULL)) {
-            SCFree(curr_connp->trec);
-            curr_connp->trec = NULL;
-            goto error;
-        }
-        curr_connp->trec = ptmp;
-    }
-    ValidateTrecBuffer(curr_connp);
-    return 0;
-error:
-    curr_connp->trec_len = 0;
-    curr_connp->trec_pos = 0;
-    ValidateTrecBuffer(curr_connp);
-    return -1;
-}
-
 static inline bool
 HaveEntireRecord(const SSLStateConnp *curr_connp, const uint32_t input_len)
 {
@@ -1514,75 +1414,18 @@ static inline int SSLv3ParseHandshakeTypeCertificate(SSLState *ssl_state,
         const uint8_t * const initial_input,
         const uint32_t input_len)
 {
-    ValidateTrecBuffer(ssl_state->curr_connp);
-    const uint32_t certs_len = GetCertsLen(ssl_state->curr_connp, initial_input, input_len);
-    SCLogDebug("certs_len %u", certs_len);
-
-    if (EnsureRecordSpace(ssl_state->curr_connp, initial_input, input_len) < 0) {
-        /* error, skip input data */
-        ssl_state->curr_connp->bytes_processed += input_len;
-        return -1;
-    }
-    ValidateTrecBuffer(ssl_state->curr_connp);
-
-    uint32_t write_len = 0;
-    if (certs_len != 0 && ssl_state->curr_connp->trec_pos + input_len >= certs_len) {
-        write_len = certs_len - ssl_state->curr_connp->trec_pos;
-        /* get data left in this frag. The length field may indicate more
-         * data than just in this record. */
-        uint32_t cur_frag_left = ssl_state->curr_connp->record_length +
-                SSLV3_RECORD_HDR_LEN - ssl_state->curr_connp->bytes_processed;
-        SCLogDebug("write_len %u cur_frag_left %u", write_len, cur_frag_left);
-        write_len = MIN(write_len, cur_frag_left);
-    } else {
-        uint32_t cur_frag_left = (ssl_state->curr_connp->record_length +
-                SSLV3_RECORD_HDR_LEN - ssl_state->curr_connp->bytes_processed);
-        SCLogDebug("cur_frag_left %u", cur_frag_left);
-        write_len = MIN(input_len, cur_frag_left);
-        SCLogDebug("write_len %u", write_len);
-    }
-    if (write_len == 0) {
-        /* no (new) data, so we're done */
-        ValidateTrecBuffer(ssl_state->curr_connp);
-        return 0;
-    }
-    BUG_ON(write_len > input_len);
-
-    if (SafeMemcpy(ssl_state->curr_connp->trec,
-                ssl_state->curr_connp->trec_pos,
-                ssl_state->curr_connp->trec_len,
-                initial_input, 0, input_len, write_len) != 0) {
-        return -1;
-    }
-    ssl_state->curr_connp->trec_pos += write_len;
-    SCLogDebug("ssl_state->curr_connp->trec_pos %u", ssl_state->curr_connp->trec_pos);
-    DEBUG_VALIDATE_BUG_ON(certs_len != 0 && certs_len < ssl_state->curr_connp->trec_pos);
-
-    /* if we didn't yet get enough to determine the certs len, or we can
-     * see we didn't buffer enough for the certs, don't bother trying to
-     * parse it the data */
-    if (certs_len == 0 || certs_len > ssl_state->curr_connp->trec_pos) {
-        ssl_state->curr_connp->bytes_processed += write_len;
-        SCLogDebug("bytes_processed %u record_len %u",
-                ssl_state->curr_connp->bytes_processed, ssl_state->curr_connp->record_length);
-        ValidateTrecBuffer(ssl_state->curr_connp);
-        return write_len;
-    }
-
-    int rc = TlsDecodeHSCertificate(ssl_state, ssl_state->curr_connp->trec,
-            ssl_state->curr_connp->trec_pos);
+    int rc = TlsDecodeHSCertificate(ssl_state, initial_input, input_len);
     SCLogDebug("rc %d", rc);
     if (rc > 0) {
-        DEBUG_VALIDATE_BUG_ON(rc != (int)ssl_state->curr_connp->trec_pos);
+        DEBUG_VALIDATE_BUG_ON(rc > (int)input_len);
         SSLParserHSReset(ssl_state->curr_connp);
     } else if (rc < 0) {
         SCLogDebug("error parsing cert, reset state");
         SSLParserHSReset(ssl_state->curr_connp);
         /* fall through to still consume the cert bytes */
     }
-    ssl_state->curr_connp->bytes_processed += write_len;
-    ValidateTrecBuffer(ssl_state->curr_connp);
-    return write_len;
+    ssl_state->curr_connp->bytes_processed += input_len;
+    return input_len;
 }
 
 /**
@@ -2671,8 +2514,6 @@ static void SSLStateFree(void *p)
     SSLState *ssl_state = (SSLState *)p;
     SSLCertsChain *item;
 
-    if (ssl_state->client_connp.trec)
-        SCFree(ssl_state->client_connp.trec);
     if (ssl_state->client_connp.cert0_subject)
         rs_cstring_free(ssl_state->client_connp.cert0_subject);
     if (ssl_state->client_connp.cert0_issuerdn)
@@ -2686,8 +2527,6 @@ static void SSLStateFree(void *p)
     if (ssl_state->client_connp.session_id)
         SCFree(ssl_state->client_connp.session_id);
 
-    if (ssl_state->server_connp.trec)
-        SCFree(ssl_state->server_connp.trec);
     if (ssl_state->server_connp.cert0_subject)
         rs_cstring_free(ssl_state->server_connp.cert0_subject);
     if (ssl_state->server_connp.cert0_issuerdn)
index b6ad25dbf0ff600d94dfedae038819cdc0a419f4..2ef6944dac9b9342f11073ba433ff79e121c1f39 100644 (file)
@@ -235,11 +235,6 @@ typedef struct SSLStateConnp_ {
     JA3Buffer *ja3_str;
     char *ja3_hash;
 
-    /* buffer for the tls record.
-     * We use a malloced buffer, if the record is fragmented */
-    uint8_t *trec;
-    uint32_t trec_len;
-    uint32_t trec_pos;
 } SSLStateConnp;
 
 /**