app-layer-ssl: split function into multiple smaller functions

Split 'TLSDecodeHandshakeHello' into smaller functions to make
it easier to read the code when the function grows in size.
pull/3297/head
Mats Klepsland 7 years ago committed by Victor Julien
parent ea1e13cb00
commit 3f0dea582d

@ -134,7 +134,7 @@ SslConfig ssl_config;
#define SSL_RECORD_MINIMUM_LENGTH 6 #define SSL_RECORD_MINIMUM_LENGTH 6
#define HAS_SPACE(n) ((uint32_t)((input) + (n) - (initial_input)) > (uint32_t)(input_len)) ? 0 : 1 #define HAS_SPACE(n) ((uint32_t)((*input) + (n) - (initial_input)) > (uint32_t)(input_len)) ? 0 : 1
static void SSLParserReset(SSLState *ssl_state) static void SSLParserReset(SSLState *ssl_state)
{ {
@ -250,55 +250,103 @@ static void SSLSetTxDetectFlags(void *vtx, uint8_t dir, uint64_t flags)
} }
} }
static int TLSDecodeHandshakeHello(SSLState *ssl_state, uint8_t *input, static inline int TLSDecodeHSHelloVersion(SSLState *ssl_state, uint8_t **input,
uint32_t input_len) const uint32_t input_len,
const uint8_t *initial_input)
{ {
uint8_t *initial_input = input; /* Skip version */
*input += SSLV3_CLIENT_HELLO_VERSION_LEN;
/* only parse the message if it is complete */ return 0;
if (input_len < ssl_state->curr_connp->message_length || input_len < 40) }
return 0;
/* skip version */ static inline int TLSDecodeHSHelloRandom(SSLState *ssl_state, uint8_t **input,
input += SSLV3_CLIENT_HELLO_VERSION_LEN; const uint32_t input_len,
const uint8_t *initial_input)
{
/* Skip random */
*input += SSLV3_CLIENT_HELLO_RANDOM_LEN;
/* skip random */ return 0;
input += SSLV3_CLIENT_HELLO_RANDOM_LEN; }
if (!(HAS_SPACE(1))) static inline int TLSDecodeHSHelloSessionID(SSLState *ssl_state,
goto invalid_length; uint8_t **input,
const uint32_t input_len,
const uint8_t *initial_input)
{
if (!(HAS_SPACE(1))) {
SCLogDebug("TLS handshake invalid length");
SSLSetEvent(ssl_state,
TLS_DECODER_EVENT_HANDSHAKE_INVALID_LENGTH);
return -1;
}
uint8_t session_id_length = **input;
*input += 1;
/* skip session id */
uint8_t session_id_length = *(input++);
if (session_id_length != 0) { if (session_id_length != 0) {
ssl_state->flags |= SSL_AL_FLAG_SSL_CLIENT_SESSION_ID; ssl_state->flags |= SSL_AL_FLAG_SSL_CLIENT_SESSION_ID;
} }
input += session_id_length; *input += session_id_length;
if (!(HAS_SPACE(2))) return 0;
goto invalid_length; }
/* skip cipher suites */ static inline int TLSDecodeHSHelloCipherSuites(SSLState *ssl_state,
uint16_t cipher_suites_length = input[0] << 8 | input[1]; uint8_t **input,
input += 2; const uint32_t input_len,
const uint8_t *initial_input)
{
if (!(HAS_SPACE(2))) {
SCLogDebug("TLS handshake invalid length");
SSLSetEvent(ssl_state,
TLS_DECODER_EVENT_HANDSHAKE_INVALID_LENGTH);
return -1;
}
input += cipher_suites_length; uint16_t cipher_suites_length = **input << 8 | *(*input + 1);
*input += 2;
if (!(HAS_SPACE(1))) /* Skip cipher suites */
goto invalid_length; *input += cipher_suites_length;
return 0;
}
static inline int TLSDecodeHSHelloCompressionMethods(SSLState *ssl_state,
uint8_t **input,
const uint32_t input_len,
const uint8_t *initial_input)
{
if (!(HAS_SPACE(1))) {
SCLogDebug("TLS handshake invalid length");
SSLSetEvent(ssl_state,
TLS_DECODER_EVENT_HANDSHAKE_INVALID_LENGTH);
return -1;
}
/* skip compression methods */ /* Skip compression methods */
uint8_t compression_methods_length = *(input++); uint8_t compression_methods_length = **input;
*input += 1;
input += compression_methods_length; *input += compression_methods_length;
/* extensions are optional (RFC5246 section 7.4.1.2) */ return 0;
}
static inline int TLSDecodeHSHelloExtensions(SSLState *ssl_state,
uint8_t **input,
const uint32_t input_len,
const uint8_t *initial_input)
{
/* Extensions are optional (RFC5246 section 7.4.1.2) */
if (!(HAS_SPACE(2))) if (!(HAS_SPACE(2)))
goto end; goto end;
uint16_t extensions_len = input[0] << 8 | input[1]; uint16_t extensions_len = **input << 8 | *(*input + 1);
input += 2; *input += 2;
if (!(HAS_SPACE(extensions_len))) if (!(HAS_SPACE(extensions_len)))
goto invalid_length; goto invalid_length;
@ -309,20 +357,20 @@ static int TLSDecodeHandshakeHello(SSLState *ssl_state, uint8_t *input,
if (!(HAS_SPACE(2))) if (!(HAS_SPACE(2)))
goto invalid_length; goto invalid_length;
uint16_t ext_type = input[0] << 8 | input[1]; uint16_t ext_type = **input << 8 | *(*input + 1);
input += 2; *input += 2;
if (!(HAS_SPACE(2))) if (!(HAS_SPACE(2)))
goto invalid_length; goto invalid_length;
uint16_t ext_len = input[0] << 8 | input[1]; uint16_t ext_len = **input << 8 | *(*input + 1);
input += 2; *input += 2;
switch (ext_type) { switch (ext_type) {
case SSL_EXTENSION_SNI: case SSL_EXTENSION_SNI:
{ {
/* there must not be more than one extension of the same /* There must not be more than one extension of the same
type (RFC5246 section 7.4.1.4) */ type (RFC5246 section 7.4.1.4). */
if (ssl_state->curr_connp->sni) { if (ssl_state->curr_connp->sni) {
SCLogDebug("Multiple SNI extensions"); SCLogDebug("Multiple SNI extensions");
SSLSetEvent(ssl_state, SSLSetEvent(ssl_state,
@ -330,16 +378,17 @@ static int TLSDecodeHandshakeHello(SSLState *ssl_state, uint8_t *input,
return -1; return -1;
} }
/* skip sni_list_length */ /* Skip sni_list_length */
input += 2; *input += 2;
if (!(HAS_SPACE(1))) if (!(HAS_SPACE(1)))
goto invalid_length; goto invalid_length;
uint8_t sni_type = *(input++); uint8_t sni_type = **input;
*input += 1;
/* currently the only type allowed is host_name /* Currently the only type allowed is host_name
(RFC6066 section 3) */ (RFC6066 section 3). */
if (sni_type != SSL_SNI_TYPE_HOST_NAME) { if (sni_type != SSL_SNI_TYPE_HOST_NAME) {
SCLogDebug("Unknown SNI type"); SCLogDebug("Unknown SNI type");
SSLSetEvent(ssl_state, SSLSetEvent(ssl_state,
@ -350,15 +399,15 @@ static int TLSDecodeHandshakeHello(SSLState *ssl_state, uint8_t *input,
if (!(HAS_SPACE(2))) if (!(HAS_SPACE(2)))
goto invalid_length; goto invalid_length;
uint16_t sni_len = input[0] << 8 | input[1]; uint16_t sni_len = **input << 8 | *(*input + 1);
input += 2; *input += 2;
if (!(HAS_SPACE(sni_len))) if (!(HAS_SPACE(sni_len)))
goto invalid_length; goto invalid_length;
/* host_name contains the fully qualified domain name, /* host_name contains the fully qualified domain name,
and should therefore be limited by the maximum domain and should therefore be limited by the maximum domain
name length */ name length. */
if (sni_len > 255) { if (sni_len > 255) {
SCLogDebug("SNI length >255"); SCLogDebug("SNI length >255");
SSLSetEvent(ssl_state, SSLSetEvent(ssl_state,
@ -370,17 +419,18 @@ static int TLSDecodeHandshakeHello(SSLState *ssl_state, uint8_t *input,
ssl_state->curr_connp->sni = SCMalloc(sni_strlen); ssl_state->curr_connp->sni = SCMalloc(sni_strlen);
if (unlikely(ssl_state->curr_connp->sni == NULL)) if (unlikely(ssl_state->curr_connp->sni == NULL))
goto end; return -1;
memcpy(ssl_state->curr_connp->sni, input, sni_strlen - 1); memcpy(ssl_state->curr_connp->sni, *input, sni_strlen - 1);
ssl_state->curr_connp->sni[sni_strlen-1] = 0; ssl_state->curr_connp->sni[sni_strlen-1] = 0;
input += sni_len; *input += sni_len;
break; break;
} }
default: default:
{ {
input += ext_len; *input += ext_len;
break; break;
} }
} }
@ -393,7 +443,48 @@ end:
invalid_length: invalid_length:
SCLogDebug("TLS handshake invalid length"); SCLogDebug("TLS handshake invalid length");
SSLSetEvent(ssl_state, SSLSetEvent(ssl_state,
TLS_DECODER_EVENT_HANDSHAKE_INVALID_LENGTH); TLS_DECODER_EVENT_HANDSHAKE_INVALID_LENGTH);
return -1;
}
static int TLSDecodeHandshakeHello(SSLState *ssl_state, uint8_t *input,
uint32_t input_len)
{
int rc;
uint8_t *initial_input = input;
/* Only parse the message if it is complete */
if (input_len < ssl_state->curr_connp->message_length || input_len < 40)
goto end;
rc = TLSDecodeHSHelloVersion(ssl_state, &input, input_len, initial_input);
if (rc != 0)
goto end;
rc = TLSDecodeHSHelloRandom(ssl_state, &input, input_len, initial_input);
if (rc != 0)
goto end;
rc = TLSDecodeHSHelloSessionID(ssl_state, &input, input_len, initial_input);
if (rc != 0)
goto end;
rc = TLSDecodeHSHelloCipherSuites(ssl_state, &input, input_len,
initial_input);
if (rc != 0)
goto end;
rc = TLSDecodeHSHelloCompressionMethods(ssl_state, &input, input_len,
initial_input);
if (rc != 0)
goto end;
rc = TLSDecodeHSHelloExtensions(ssl_state, &input, input_len,
initial_input);
if (rc != 0)
goto end;
end:
return 0; return 0;
} }

Loading…
Cancel
Save