From: Mats Klepsland Date: Wed, 18 May 2016 13:12:48 +0000 (+0200) Subject: tls: add function for decoding client_hello X-Git-Tag: suricata-3.2beta1~303 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=12da0e8681fea7b3ac781c9cfff403d9373a1461;p=thirdparty%2Fsuricata.git tls: add function for decoding client_hello Add function TLSDecodeHandshakeHello() to enable using the same code for decoding both client_hello and server_hello. --- diff --git a/src/app-layer-ssl.c b/src/app-layer-ssl.c index 4342ecb0eb..cce52bc733 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -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: