From: Victor Julien Date: Thu, 18 Aug 2022 08:51:35 +0000 (+0200) Subject: ssl: implement 'incomplete' handling for SSLv2 X-Git-Tag: suricata-7.0.0-beta1~207 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c8d79fb81fef91fef27d28ad06ee4136e8e282b6;p=thirdparty%2Fsuricata.git ssl: implement 'incomplete' handling for SSLv2 --- diff --git a/src/app-layer-ssl.c b/src/app-layer-ssl.c index 3499032a77..ae10eef236 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -2049,10 +2049,10 @@ static int SSLv2ParseRecord(uint8_t direction, SSLState *ssl_state, return (input - initial_input); } -static int SSLv2Decode(uint8_t direction, SSLState *ssl_state, AppLayerParserState *pstate, - const uint8_t *input, uint32_t input_len, const StreamSlice stream_slice) +static struct SSLDecoderResult SSLv2Decode(uint8_t direction, SSLState *ssl_state, + AppLayerParserState *pstate, const uint8_t *input, uint32_t input_len, + const StreamSlice stream_slice) { - int retval = 0; const uint8_t *initial_input = input; if (ssl_state->curr_connp->bytes_processed == 0) { @@ -2075,13 +2075,13 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state, AppLayerParserSta to read the msg_type */ if (ssl_state->curr_connp->bytes_processed < (ssl_state->curr_connp->record_lengths_length + 1)) { - retval = SSLv2ParseRecord(direction, ssl_state, input, input_len); + const int retval = SSLv2ParseRecord(direction, ssl_state, input, input_len); SCLogDebug("retval %d ssl_state->curr_connp->record_length %u", retval, ssl_state->curr_connp->record_length); if (retval < 0 || retval > (int)input_len) { DEBUG_VALIDATE_BUG_ON(retval > (int)input_len); SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSLV2_HEADER); - return -1; + return SSL_DECODER_ERROR(-1); } // TODO review // BUG_ON(ssl_state->curr_connp->record_lengths_length + 1 != @@ -2096,22 +2096,32 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state, AppLayerParserSta input_len -= retval; } + /* if we don't have the full record, we return incomplete */ + if (ssl_state->curr_connp->record_lengths_length + ssl_state->curr_connp->record_length > + input_len + ssl_state->curr_connp->bytes_processed) { + uint32_t needed = ssl_state->curr_connp->record_length; + SCLogDebug("record len %u input_len %u parsed %u: need %u bytes more data", + ssl_state->curr_connp->record_length, input_len, (uint32_t)(input - initial_input), + needed); + return SSL_DECODER_INCOMPLETE((input - initial_input), needed); + } + if (input_len == 0) { - return (input - initial_input); + return SSL_DECODER_OK((input - initial_input)); } /* record_length should never be zero */ if (ssl_state->curr_connp->record_length == 0) { SCLogDebug("SSLv2 record length is zero"); SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSLV2_HEADER); - return -1; + return SSL_DECODER_ERROR(-1); } /* record_lengths_length should never be zero */ if (ssl_state->curr_connp->record_lengths_length == 0) { SCLogDebug("SSLv2 record lengths length is zero"); SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSLV2_HEADER); - return -1; + return SSL_DECODER_ERROR(-1); } switch (ssl_state->curr_connp->content_type) { @@ -2325,15 +2335,14 @@ static int SSLv2Decode(uint8_t direction, SSLState *ssl_state, AppLayerParserSta ssl_state->curr_connp->bytes_processed; input += diff; SSLParserReset(ssl_state); - return (input - initial_input); - /* we still don't have the entire record for the one we are - currently parsing */ + /* we still don't have the entire record for the one we are + currently parsing */ } else { input += input_len; ssl_state->curr_connp->bytes_processed += input_len; - return (input - initial_input); } + return SSL_DECODER_OK((input - initial_input)); } static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_state, @@ -2640,19 +2649,25 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate, } else { SCLogDebug("Continuing parsing SSLv2 record"); } - int retval = SSLv2Decode(direction, ssl_state, pstate, input, input_len, stream_slice); - if (retval < 0 || retval > input_len) { - DEBUG_VALIDATE_BUG_ON(retval > input_len); + struct SSLDecoderResult r = + SSLv2Decode(direction, ssl_state, pstate, input, input_len, stream_slice); + if (r.retval < 0 || r.retval > input_len) { + DEBUG_VALIDATE_BUG_ON(r.retval > input_len); SCLogDebug("Error parsing SSLv2. Reseting parser " "state. Let's get outta here"); SSLParserReset(ssl_state); SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD); - return APP_LAYER_OK; + return APP_LAYER_ERROR; + } else if (r.needed) { + input += r.retval; + SCLogDebug("returning consumed %" PRIuMAX " needed %u", + (uintmax_t)(input - init_input), r.needed); + SCReturnStruct(APP_LAYER_INCOMPLETE(input - init_input, r.needed)); } - input_len -= retval; - input += retval; - SCLogDebug("SSLv2 decoder consumed %d bytes: %u left", retval, input_len); + input_len -= r.retval; + input += r.retval; + SCLogDebug("SSLv2 decoder consumed %d bytes: %u left", r.retval, input_len); } else { if (ssl_state->curr_connp->bytes_processed == 0) { SCLogDebug("New TLS record: record_length %u",