]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
tls: add function for decoding client_hello
authorMats Klepsland <mats.klepsland@gmail.com>
Wed, 18 May 2016 13:12:48 +0000 (15:12 +0200)
committerVictor Julien <victor@inliniac.net>
Sun, 25 Sep 2016 20:12:00 +0000 (22:12 +0200)
Add function TLSDecodeHandshakeHello() to enable using the same code
for decoding both client_hello and server_hello.

src/app-layer-ssl.c

index 4342ecb0ebcdd89d9aed0fe97fd610abae19dac7..cce52bc733f867be262d2c8cc5027514b72e8b75 100644 (file)
@@ -230,144 +230,161 @@ int SSLGetAlstateProgress(void *tx, uint8_t direction)
     return TLS_STATE_IN_PROGRESS;
 }
 
-static int SSLv3ParseHandshakeType(SSLState *ssl_state, uint8_t *input,
+static int TLSDecodeHandshakeHello(SSLState *ssl_state, uint8_t *input,
                                    uint32_t input_len)
 {
-    void *ptmp;
     uint8_t *initial_input = input;
-    uint32_t parsed = 0;
-    int rc;
 
-    if (input_len == 0) {
+    /* only parse the message if it is complete */
+    if (input_len < ssl_state->curr_connp->message_length || input_len < 40)
         return 0;
-    }
 
-    switch (ssl_state->curr_connp->handshake_type) {
-        case SSLV3_HS_CLIENT_HELLO:
-            ssl_state->current_flags = SSL_AL_FLAG_STATE_CLIENT_HELLO;
+    /* skip version */
+    input += SSLV3_CLIENT_HELLO_VERSION_LEN;
 
-            /* skip version */
-            input += SSLV3_CLIENT_HELLO_VERSION_LEN;
+    /* skip random */
+    input += SSLV3_CLIENT_HELLO_RANDOM_LEN;
 
-            /* skip random */
-            input += SSLV3_CLIENT_HELLO_RANDOM_LEN;
+    if (!(HAS_SPACE(1)))
+        goto end;
+
+    /* skip session id */
+    uint8_t session_id_length = *(input++);
+
+    input += session_id_length;
+
+    if (!(HAS_SPACE(2)))
+        goto end;
 
-            if (!(HAS_SPACE(1)))
-                goto end;
+    /* skip cipher suites */
+    uint16_t cipher_suites_length = input[0] << 8 | input[1];
+    input += 2;
 
-            /* skip session id */
-            uint8_t session_id_length = *(input++);
+    input += cipher_suites_length;
 
-            input += session_id_length;
+    if (!(HAS_SPACE(1)))
+        goto end;
 
-            if (!(HAS_SPACE(2)))
-                goto end;
+    /* skip compression methods */
+    uint8_t compression_methods_length = *(input++);
 
-            /* skip cipher suites */
-            uint16_t cipher_suites_length = input[0] << 8 | input[1];
-            input += 2;
+    input += compression_methods_length;
 
-            input += cipher_suites_length;
+    if (!(HAS_SPACE(2)))
+        goto end;
 
-            if (!(HAS_SPACE(1)))
-                goto end;
+    uint16_t extensions_len = input[0] << 8 | input[1];
+    input += 2;
 
-            /* skip compression methods */
-            uint8_t compression_methods_length = *(input++);
+    uint16_t processed_len = 0;
+    while (processed_len < extensions_len)
+    {
+        if (!(HAS_SPACE(2)))
+            goto end;
 
-            input += compression_methods_length;
+        uint16_t ext_type = input[0] << 8 | input[1];
+        input += 2;
 
-            if (!(HAS_SPACE(2)))
-                goto end;
+        if (!(HAS_SPACE(2)))
+            goto end;
 
-            uint16_t extensions_len = input[0] << 8 | input[1];
-            input += 2;
+        uint16_t ext_len = input[0] << 8 | input[1];
+        input += 2;
 
-            uint16_t processed_len = 0;
-            while (processed_len < extensions_len)
+        switch (ext_type) {
+            case SSL_EXTENSION_SNI:
             {
-                if (!(HAS_SPACE(2)))
-                    goto end;
+                /* there must not be more than one extension of the same
+                   type (RFC5246 section 7.4.1.4) */
+                if (ssl_state->curr_connp->sni) {
+                    SCLogDebug("Multiple SNI extensions");
+                    SSLSetEvent(ssl_state,
+                            TLS_DECODER_EVENT_MULTIPLE_SNI_EXTENSIONS);
+                    return -1;
+                }
 
-                uint16_t ext_type = input[0] << 8 | input[1];
+                /* skip sni_list_length */
                 input += 2;
 
+                if (!(HAS_SPACE(1)))
+                    goto end;
+
+                uint8_t sni_type = *(input++);
+
+                /* currently the only type allowed is host_name
+                   (RFC6066 section 3) */
+                if (sni_type != SSL_SNI_TYPE_HOST_NAME) {
+                    SCLogDebug("Unknown SNI type");
+                    SSLSetEvent(ssl_state,
+                            TLS_DECODER_EVENT_INVALID_SNI_TYPE);
+                    return -1;
+                }
+
                 if (!(HAS_SPACE(2)))
                     goto end;
 
-                uint16_t ext_len = input[0] << 8 | input[1];
+                uint16_t sni_len = input[0] << 8 | input[1];
                 input += 2;
 
-                switch (ext_type) {
-                    case SSL_EXTENSION_SNI:
-                    {
-                        /* there must not be more than one extension of the same
-                           type (RFC5246 section 7.4.1.4) */
-                        if (ssl_state->curr_connp->sni) {
-                            SCLogDebug("Multiple SNI extensions");
-                            SSLSetEvent(ssl_state,
-                                    TLS_DECODER_EVENT_MULTIPLE_SNI_EXTENSIONS);
-                            return -1;
-                        }
+                if (!(HAS_SPACE(sni_len)))
+                    goto end;
 
-                        /* skip sni_list_length */
-                        input += 2;
+                /* host_name contains the fully qualified domain name,
+                   and should therefore be limited by the maximum domain
+                   name length */
+                if (sni_len > 255) {
+                    SCLogDebug("SNI length >255");
+                    SSLSetEvent(ssl_state,
+                            TLS_DECODER_EVENT_INVALID_SNI_LENGTH);
+                    return -1;
+                }
 
-                        if (!(HAS_SPACE(1)))
-                            goto end;
+                size_t sni_strlen = sni_len + 1;
+                ssl_state->curr_connp->sni = SCMalloc(sni_strlen);
 
-                        uint8_t sni_type = *(input++);
+                if (unlikely(ssl_state->curr_connp->sni == NULL))
+                    goto end;
 
-                        /* currently the only type allowed is host_name
-                           (RFC6066 section 3) */
-                        if (sni_type != SSL_SNI_TYPE_HOST_NAME) {
-                            SCLogDebug("Unknown SNI type");
-                            SSLSetEvent(ssl_state,
-                                    TLS_DECODER_EVENT_INVALID_SNI_TYPE);
-                            return -1;
-                        }
+                memcpy(ssl_state->curr_connp->sni, input, sni_strlen - 1);
+                ssl_state->curr_connp->sni[sni_strlen-1] = 0;
 
-                        if (!(HAS_SPACE(2)))
-                            goto end;
+                input += sni_len;
+                break;
+            }
+            default:
+            {
+                input += ext_len;
+                break;
+            }
+        }
+        processed_len += ext_len + 4;
+    }
 
-                        uint16_t sni_len = input[0] << 8 | input[1];
-                        input += 2;
+end:
+    return 0;
+}
 
-                        if (!(HAS_SPACE(sni_len)))
-                            goto end;
+static int SSLv3ParseHandshakeType(SSLState *ssl_state, uint8_t *input,
+                                   uint32_t input_len)
+{
+    void *ptmp;
+    uint8_t *initial_input = input;
+    uint32_t parsed = 0;
+    int rc;
 
-                        /* host_name contains the fully qualified domain name,
-                           and should therefore be limited by the maximum domain
-                           name length */
-                        if (sni_len > 255) {
-                            SCLogDebug("SNI length >255");
-                            SSLSetEvent(ssl_state,
-                                    TLS_DECODER_EVENT_INVALID_SNI_LENGTH);
-                            return -1;
-                        }
+    if (input_len == 0) {
+        return 0;
+    }
 
-                        size_t sni_strlen = sni_len + 1;
-                        ssl_state->curr_connp->sni = SCMalloc(sni_strlen);
+    switch (ssl_state->curr_connp->handshake_type) {
+        case SSLV3_HS_CLIENT_HELLO:
+            ssl_state->current_flags = SSL_AL_FLAG_STATE_CLIENT_HELLO;
 
-                        if (unlikely(ssl_state->curr_connp->sni == NULL))
-                            goto end;
+            rc = TLSDecodeHandshakeHello(ssl_state, input, input_len);
 
-                        memcpy(ssl_state->curr_connp->sni, input,
-                               sni_strlen - 1);
-                        ssl_state->curr_connp->sni[sni_strlen-1] = 0;
+            if (rc < 0)
+                return rc;
 
-                        input += sni_len;
-                        break;
-                    }
-                    default:
-                    {
-                        input += ext_len;
-                        break;
-                    }
-                }
-                processed_len += ext_len + 4;
-            }
-end:
             break;
 
         case SSLV3_HS_SERVER_HELLO: