]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
ssl: implement frames for SSLv3 and TLS
authorVictor Julien <vjulien@oisf.net>
Fri, 3 Dec 2021 07:17:37 +0000 (08:17 +0100)
committerVictor Julien <vjulien@oisf.net>
Tue, 18 Jan 2022 11:21:53 +0000 (12:21 +0100)
src/app-layer-ssl.c
src/app-layer-ssl.h

index 9b32b173af0dffb6e5271a522d583ff3e263ae56..73700f1af6f1db526ed628f35fed012f9502d5df 100644 (file)
@@ -37,6 +37,7 @@
 #include "app-layer.h"
 #include "app-layer-protos.h"
 #include "app-layer-parser.h"
+#include "app-layer-frames.h"
 #include "app-layer-ssl.h"
 
 #include "decode-events.h"
 #include "flow-private.h"
 #include "util-validate.h"
 
+SCEnumCharMap tls_frame_table[] = {
+    {
+            "pdu",
+            TLS_FRAME_PDU,
+    },
+    {
+            "hdr",
+            TLS_FRAME_HDR,
+    },
+    {
+            "data",
+            TLS_FRAME_DATA,
+    },
+    {
+            "alert",
+            TLS_FRAME_ALERT_DATA,
+    },
+    {
+            "heartbeat",
+            TLS_FRAME_HB_DATA,
+    },
+    {
+            "ssl2.hdr",
+            TLS_FRAME_SSLV2_HDR,
+    },
+    {
+            "ssl2.pdu",
+            TLS_FRAME_SSLV2_PDU,
+    },
+    { NULL, -1 },
+};
+
 SCEnumCharMap tls_decoder_event_table[ ] = {
     /* TLS protocol messages */
     { "INVALID_SSLV2_HEADER",        TLS_DECODER_EVENT_INVALID_SSLV2_HEADER },
@@ -1980,9 +2013,8 @@ static int SSLv2ParseRecord(uint8_t direction, SSLState *ssl_state,
     return (input - initial_input);
 }
 
-static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
-                       AppLayerParserState *pstate, const uint8_t *input,
-                       uint32_t input_len)
+static int SSLv2Decode(uint8_t direction, SSLState *ssl_state, AppLayerParserState *pstate,
+        const uint8_t *input, uint32_t input_len, const StreamSlice stream_slice)
 {
     int retval = 0;
     const uint8_t *initial_input = input;
@@ -1993,18 +2025,37 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
         } else {
             ssl_state->curr_connp->record_lengths_length = 3;
         }
+
+        SCLogDebug("record start: ssl2.hdr frame");
+        AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input,
+                ssl_state->curr_connp->record_lengths_length + 1, direction, TLS_FRAME_SSLV2_HDR);
     }
 
+    SCLogDebug("direction %u ssl_state->curr_connp->record_lengths_length + 1 %u, "
+               "ssl_state->curr_connp->bytes_processed %u",
+            direction, ssl_state->curr_connp->record_lengths_length + 1,
+            ssl_state->curr_connp->bytes_processed);
     /* the +1 is because we read one extra byte inside SSLv2ParseRecord
        to read the msg_type */
     if (ssl_state->curr_connp->bytes_processed <
             (ssl_state->curr_connp->record_lengths_length + 1)) {
         retval = SSLv2ParseRecord(direction, ssl_state, input, input_len);
+        SCLogDebug("retval %d ssl_state->curr_connp->record_length %u", retval,
+                ssl_state->curr_connp->record_length);
         if (retval < 0 || retval > (int)input_len) {
             DEBUG_VALIDATE_BUG_ON(retval > (int)input_len);
             SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSLV2_HEADER);
             return -1;
         }
+        // TODO review
+        // BUG_ON(ssl_state->curr_connp->record_lengths_length + 1 !=
+        //        ssl_state->curr_connp->bytes_processed);
+
+        AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input,
+                ssl_state->curr_connp->record_lengths_length + ssl_state->curr_connp->record_length,
+                direction, TLS_FRAME_SSLV2_PDU);
+        SCLogDebug("record start: ssl2.pdu frame");
+
         input += retval;
         input_len -= retval;
     }
@@ -2249,9 +2300,8 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state,
     }
 }
 
-static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
-                       AppLayerParserState *pstate, const uint8_t *input,
-                       const uint32_t input_len)
+static int SSLv3Decode(uint8_t direction, SSLState *ssl_state, AppLayerParserState *pstate,
+        const uint8_t *input, const uint32_t input_len, const StreamSlice stream_slice)
 {
     uint32_t parsed = 0;
     uint32_t record_len; /* slice of input_len for the current record */
@@ -2264,6 +2314,12 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
             SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_TLS_HEADER);
             return -1;
         }
+        SCLogDebug("%s input %p record_length %u", (direction == 0) ? "toserver" : "toclient",
+                input, ssl_state->curr_connp->record_length);
+        AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input,
+                ssl_state->curr_connp->record_length + retval, direction, TLS_FRAME_PDU);
+        AppLayerFrameNewByPointer(
+                ssl_state->f, &stream_slice, input, SSLV3_RECORD_HDR_LEN, direction, TLS_FRAME_HDR);
         parsed += retval;
         record_len = MIN(input_len - parsed, ssl_state->curr_connp->record_length);
         SCLogDebug("record_len %u (input_len %u, parsed %u, ssl_state->curr_connp->record_length %u)",
@@ -2287,6 +2343,8 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
         SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_TLS_HEADER);
         return -1;
     }
+    AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input + parsed,
+            ssl_state->curr_connp->record_length, direction, TLS_FRAME_DATA);
 
     switch (ssl_state->curr_connp->content_type) {
 
@@ -2303,6 +2361,8 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
             break;
 
         case SSLV3_ALERT_PROTOCOL:
+            AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input + parsed,
+                    ssl_state->curr_connp->record_length, direction, TLS_FRAME_ALERT_DATA);
             break;
 
         case SSLV3_APPLICATION_PROTOCOL:
@@ -2395,6 +2455,8 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
             return parsed;
         }
         case SSLV3_HEARTBEAT_PROTOCOL: {
+            AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input + parsed,
+                    ssl_state->curr_connp->record_length, direction, TLS_FRAME_HB_DATA);
             int retval = SSLv3ParseHeartbeatProtocol(ssl_state, input + parsed,
                                                  record_len, direction);
             if (retval < 0) {
@@ -2474,7 +2536,8 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
 
     if (input == NULL &&
             ((direction == 0 && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) ||
-             (direction == 1 && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)))) {
+                    (direction == 1 &&
+                            AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)))) {
         /* flag session as finished if APP_LAYER_PARSER_EOF is set */
         ssl_state->flags |= SSL_AL_FLAG_STATE_FINISHED;
         SCReturnStruct(APP_LAYER_OK);
@@ -2526,8 +2589,7 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
             } else {
                 SCLogDebug("Continuing parsing SSLv2 record");
             }
-            int retval = SSLv2Decode(direction, ssl_state, pstate, input,
-                    input_len);
+            int retval = SSLv2Decode(direction, ssl_state, pstate, input, input_len, stream_slice);
             if (retval < 0 || retval > input_len) {
                 DEBUG_VALIDATE_BUG_ON(retval > input_len);
                 SCLogDebug("Error parsing SSLv2. Reseting parser "
@@ -2548,8 +2610,7 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
                 SCLogDebug("Continuing parsing TLS record: record_length %u, bytes_processed %u",
                         ssl_state->curr_connp->record_length, ssl_state->curr_connp->bytes_processed);
             }
-            int retval = SSLv3Decode(direction, ssl_state, pstate, input,
-                    input_len);
+            int retval = SSLv3Decode(direction, ssl_state, pstate, input, input_len, stream_slice);
             if (retval < 0 || retval > input_len) {
                 DEBUG_VALIDATE_BUG_ON(retval > input_len);
                 SCLogDebug("Error parsing TLS. Reseting parser "
@@ -2704,6 +2765,22 @@ static AppProto SSLProbingParser(Flow *f, uint8_t direction,
     return ALPROTO_FAILED;
 }
 
+static int SSLStateGetFrameIdByName(const char *frame_name)
+{
+    int id = SCMapEnumNameToValue(frame_name, tls_frame_table);
+    if (id < 0) {
+        SCLogError(SC_ERR_INVALID_ENUM_MAP, "unknown frame type \"%s\"", frame_name);
+        return -1;
+    }
+    return id;
+}
+
+static const char *SSLStateGetFrameNameById(const uint8_t frame_id)
+{
+    const char *name = SCMapEnumValueToName(frame_id, tls_frame_table);
+    return name;
+}
+
 static int SSLStateGetEventInfo(const char *event_name,
                          int *event_id, AppLayerEventType *event_type)
 {
@@ -2931,6 +3008,8 @@ void RegisterSSLParsers(void)
         AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TLS, STREAM_TOCLIENT,
                                      SSLParseServerRecord);
 
+        AppLayerParserRegisterGetFrameFuncs(
+                IPPROTO_TCP, ALPROTO_TLS, SSLStateGetFrameIdByName, SSLStateGetFrameNameById);
         AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_TLS, SSLStateGetEventInfo);
         AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_TLS, SSLStateGetEventInfoById);
 
index becc5c3def2957cb3af738d07c473f90579d7ff3..d7e769e5b9055ded8081277ba6519915dac39bf0 100644 (file)
 #include "util-ja3.h"
 #include "queue.h"
 
+enum TlsFrameTypes {
+    TLS_FRAME_PDU = 0, /**< whole PDU, so header + data */
+    TLS_FRAME_HDR,     /**< only header portion */
+    TLS_FRAME_DATA,    /**< only data portion */
+    TLS_FRAME_ALERT_DATA,
+    TLS_FRAME_HB_DATA,
+    TLS_FRAME_SSLV2_HDR,
+    TLS_FRAME_SSLV2_PDU,
+};
+
 enum {
     /* TLS protocol messages */
     TLS_DECODER_EVENT_INVALID_SSLV2_HEADER,