tls: add function for decoding client_hello

Add function TLSDecodeHandshakeHello() to enable using the same code
for decoding both client_hello and server_hello.
pull/2284/head
Mats Klepsland 10 years ago committed by Victor Julien
parent 04da43d65d
commit 12da0e8681

@ -230,144 +230,161 @@ int SSLGetAlstateProgress(void *tx, uint8_t direction)
return TLS_STATE_IN_PROGRESS; 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) uint32_t input_len)
{ {
void *ptmp;
uint8_t *initial_input = input; 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; return 0;
}
switch (ssl_state->curr_connp->handshake_type) { /* skip version */
case SSLV3_HS_CLIENT_HELLO: input += SSLV3_CLIENT_HELLO_VERSION_LEN;
ssl_state->current_flags = SSL_AL_FLAG_STATE_CLIENT_HELLO;
/* skip version */ /* skip random */
input += SSLV3_CLIENT_HELLO_VERSION_LEN; input += SSLV3_CLIENT_HELLO_RANDOM_LEN;
/* skip random */ if (!(HAS_SPACE(1)))
input += SSLV3_CLIENT_HELLO_RANDOM_LEN; 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))) /* skip cipher suites */
goto end; uint16_t cipher_suites_length = input[0] << 8 | input[1];
input += 2;
/* skip session id */ input += cipher_suites_length;
uint8_t session_id_length = *(input++);
input += session_id_length; if (!(HAS_SPACE(1)))
goto end;
if (!(HAS_SPACE(2))) /* skip compression methods */
goto end; uint8_t compression_methods_length = *(input++);
/* skip cipher suites */ input += compression_methods_length;
uint16_t cipher_suites_length = input[0] << 8 | input[1];
input += 2;
input += cipher_suites_length; if (!(HAS_SPACE(2)))
goto end;
if (!(HAS_SPACE(1))) uint16_t extensions_len = input[0] << 8 | input[1];
goto end; input += 2;
/* skip compression methods */ uint16_t processed_len = 0;
uint8_t compression_methods_length = *(input++); 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))) if (!(HAS_SPACE(2)))
goto end; goto end;
uint16_t extensions_len = input[0] << 8 | input[1]; uint16_t ext_len = input[0] << 8 | input[1];
input += 2; input += 2;
uint16_t processed_len = 0; switch (ext_type) {
while (processed_len < extensions_len) case SSL_EXTENSION_SNI:
{ {
if (!(HAS_SPACE(2))) /* there must not be more than one extension of the same
goto end; 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; 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))) if (!(HAS_SPACE(2)))
goto end; goto end;
uint16_t ext_len = input[0] << 8 | input[1]; uint16_t sni_len = input[0] << 8 | input[1];
input += 2; input += 2;
switch (ext_type) { if (!(HAS_SPACE(sni_len)))
case SSL_EXTENSION_SNI: 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;
}
/* skip sni_list_length */ /* host_name contains the fully qualified domain name,
input += 2; 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))) size_t sni_strlen = sni_len + 1;
goto end; 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 memcpy(ssl_state->curr_connp->sni, input, sni_strlen - 1);
(RFC6066 section 3) */ ssl_state->curr_connp->sni[sni_strlen-1] = 0;
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))) input += sni_len;
goto end; break;
}
default:
{
input += ext_len;
break;
}
}
processed_len += ext_len + 4;
}
uint16_t sni_len = input[0] << 8 | input[1]; end:
input += 2; return 0;
}
if (!(HAS_SPACE(sni_len))) static int SSLv3ParseHandshakeType(SSLState *ssl_state, uint8_t *input,
goto end; 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, if (input_len == 0) {
and should therefore be limited by the maximum domain return 0;
name length */ }
if (sni_len > 255) {
SCLogDebug("SNI length >255");
SSLSetEvent(ssl_state,
TLS_DECODER_EVENT_INVALID_SNI_LENGTH);
return -1;
}
size_t sni_strlen = sni_len + 1; switch (ssl_state->curr_connp->handshake_type) {
ssl_state->curr_connp->sni = SCMalloc(sni_strlen); case SSLV3_HS_CLIENT_HELLO:
ssl_state->current_flags = SSL_AL_FLAG_STATE_CLIENT_HELLO;
if (unlikely(ssl_state->curr_connp->sni == NULL)) rc = TLSDecodeHandshakeHello(ssl_state, input, input_len);
goto end;
memcpy(ssl_state->curr_connp->sni, input, if (rc < 0)
sni_strlen - 1); return rc;
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; break;
case SSLV3_HS_SERVER_HELLO: case SSLV3_HS_SERVER_HELLO:

Loading…
Cancel
Save