diff --git a/src/app-layer-ssl.c b/src/app-layer-ssl.c index 287be4a051..9f2f54af1b 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -1921,20 +1921,36 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, const uint8_t *input SCLogDebug("bytes_processed %u", ssl_state->curr_connp->bytes_processed); SCLogDebug("input %p input_len %u", input, input_len); - if (input_len < 4) { - SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD); - SCReturnInt(-1); + const uint8_t *hs_hdr = input; + if (input_len < 4 || ssl_state->curr_connp->hs_hdr_len > 0) { + DEBUG_VALIDATE_BUG_ON(ssl_state->curr_connp->hs_hdr_len >= 4); + uint32_t add = MIN(input_len, (uint32_t)(4 - ssl_state->curr_connp->hs_hdr_len)); + if (SafeMemcpy(ssl_state->curr_connp->hs_hdr, ssl_state->curr_connp->hs_hdr_len, 4, + input, 0, input_len, add) != 0) { + return -1; + } + ssl_state->curr_connp->hs_hdr_len += add; + input += add; + input_len -= add; + if (ssl_state->curr_connp->hs_hdr_len < 4) { + /* partial header received, not enough input len, return */ + SSLParserHSReset(ssl_state->curr_connp); + return (int)(input - initial_input); + } + hs_hdr = ssl_state->curr_connp->hs_hdr; + ssl_state->curr_connp->hs_hdr_len = 0; + } else { + input += 4; + input_len -= 4; } - ssl_state->curr_connp->handshake_type = input[0]; - ssl_state->curr_connp->message_length = input[1] << 16 | input[2] << 8 | input[3]; + ssl_state->curr_connp->handshake_type = hs_hdr[0]; + ssl_state->curr_connp->message_length = hs_hdr[1] << 16 | hs_hdr[2] << 8 | hs_hdr[3]; /* the fragments of this message all belong to its phase */ SSLv3HandshakePhaseEnter(ssl_state, ssl_state->curr_connp->handshake_type); SCLogDebug("handshake_type %u message len %u input %p input_len %u", ssl_state->curr_connp->handshake_type, ssl_state->curr_connp->message_length, input, input_len); - input += 4; - input_len -= 4; const uint32_t record_len = ssl_state->curr_connp->message_length; /* see if we support this type. We check here to not use the fragment @@ -2754,13 +2770,6 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat } } - if (ssl_state->curr_connp->record_length < 4) { - SSLParserReset(ssl_state); - SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD); - SCLogDebug("record len < 4 => %u", ssl_state->curr_connp->record_length); - return SSL_DECODER_ERROR(-1); - } - int retval = SSLv3ParseHandshakeProtocol(ssl_state, input + parsed, record_len, direction); SCLogDebug("retval %d", retval); diff --git a/src/app-layer-ssl.h b/src/app-layer-ssl.h index b8da3c6173..76f5fa83ea 100644 --- a/src/app-layer-ssl.h +++ b/src/app-layer-ssl.h @@ -253,6 +253,8 @@ typedef struct SSLStateConnp_ { uint32_t hs_buffer_message_size; uint32_t hs_buffer_size; /**< allocation size */ uint32_t hs_buffer_offset; /**< write offset */ + uint8_t hs_hdr[4]; /**< handshake header */ + uint8_t hs_hdr_len; /**< handshake header length */ } SSLStateConnp; /**