From: Mats Klepsland Date: Tue, 13 Oct 2015 12:06:37 +0000 (+0200) Subject: app-layer-ssl: get server name from SNI extension X-Git-Tag: suricata-3.0RC1~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3ac1a3d9fe5d955d8351c6f942dafc5df3ae0304;p=thirdparty%2Fsuricata.git app-layer-ssl: get server name from SNI extension Decode client hello handshake to get server name from SNI extension. --- diff --git a/src/app-layer-ssl.c b/src/app-layer-ssl.c index 5fb41ba15a..2c20a05448 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -119,10 +119,15 @@ SslConfig ssl_config; #define SSLV3_RECORD_HDR_LEN 5 #define SSLV3_MESSAGE_HDR_LEN 4 +#define SSLV3_CLIENT_HELLO_VERSION_LEN 2 +#define SSLV3_CLIENT_HELLO_RANDOM_LEN 32 + /* TLS heartbeat protocol types */ #define TLS_HB_REQUEST 1 #define TLS_HB_RESPONSE 2 +#define HAS_SPACE(n) (((input) + (n) - (initial_input)) > (input_len)) ? 0 : 1 + static void SSLParserReset(SSLState *ssl_state) { ssl_state->curr_connp->bytes_processed = 0; @@ -143,11 +148,101 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, uint8_t *input, switch (ssl_state->curr_connp->handshake_type) { case SSLV3_HS_CLIENT_HELLO: ssl_state->flags |= SSL_AL_FLAG_STATE_CLIENT_HELLO; + + /* skip version */ + input += SSLV3_CLIENT_HELLO_VERSION_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; + + /* skip cipher suites */ + uint16_t cipher_suites_length = ntohs(*(uint16_t *)input); + input += 2; + + input += cipher_suites_length; + + if (!(HAS_SPACE(1))) + goto end; + + /* skip compression methods */ + uint8_t compression_methods_length = *(input++); + + input += compression_methods_length; + + if (!(HAS_SPACE(2))) + goto end; + + uint16_t extensions_len = ntohs(*(uint16_t *)input); + input += 2; + + uint16_t processed_len = 0; + while (processed_len < extensions_len) + { + if (!(HAS_SPACE(2))) + goto end; + + uint16_t ext_type = ntohs(*(uint16_t *)input); + input += 2; + + if (!(HAS_SPACE(2))) + goto end; + + uint16_t ext_len = ntohs(*(uint16_t *)input); + input += 2; + + + switch (ext_type) { + case SSL_EXTENSION_SNI: + { + /* skip sni_list_length and sni_type */ + input += 3; + + if (!(HAS_SPACE(2))) + goto end; + + uint16_t sni_len = ntohs(*(uint16_t *)input); + input += 2; + + size_t sni_strlen = sni_len + 1; + ssl_state->curr_connp->sni = SCMalloc(sni_strlen); + + if (unlikely(ssl_state->curr_connp->sni == NULL)) + goto end; + + if (!(HAS_SPACE(sni_len))) + goto end; + + memcpy(ssl_state->curr_connp->sni, input, + sni_strlen - 1); + ssl_state->curr_connp->sni[sni_strlen-1] = 0; + + input += sni_len; + break; + } + default: + { + input += ext_len; + break; + } + } + processed_len += ext_len + 4; + } +end: break; case SSLV3_HS_SERVER_HELLO: ssl_state->flags |= SSL_AL_FLAG_STATE_SERVER_HELLO; - break; case SSLV3_HS_SERVER_KEY_EXCHANGE: @@ -1141,6 +1236,8 @@ void SSLStateFree(void *p) SCFree(ssl_state->client_connp.cert0_issuerdn); if (ssl_state->client_connp.cert0_fingerprint) SCFree(ssl_state->client_connp.cert0_fingerprint); + if (ssl_state->client_connp.sni) + SCFree(ssl_state->client_connp.sni); if (ssl_state->server_connp.trec) SCFree(ssl_state->server_connp.trec); @@ -1150,6 +1247,8 @@ void SSLStateFree(void *p) SCFree(ssl_state->server_connp.cert0_issuerdn); if (ssl_state->server_connp.cert0_fingerprint) SCFree(ssl_state->server_connp.cert0_fingerprint); + if (ssl_state->server_connp.sni) + SCFree(ssl_state->server_connp.sni); /* Free certificate chain */ while ((item = TAILQ_FIRST(&ssl_state->server_connp.certs))) { diff --git a/src/app-layer-ssl.h b/src/app-layer-ssl.h index 2fc1a9699b..e6274249b9 100644 --- a/src/app-layer-ssl.h +++ b/src/app-layer-ssl.h @@ -86,7 +86,8 @@ enum { /* config flags */ #define SSL_TLS_LOG_PEM (1 << 0) - +/* extensions */ +#define SSL_EXTENSION_SNI 0x0000 /* SSL versions. We'll use a unified format for all, with the top byte * holding the major version and the lower byte the minor version */ @@ -134,6 +135,9 @@ typedef struct SSLStateConnp_ { char *cert0_issuerdn; char *cert0_fingerprint; + /* ssl server name indication extension */ + char *sni; + uint8_t *cert_input; uint32_t cert_input_len;