diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index c8410d41e4a8..71299a5de7f1 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -1067,7 +1067,7 @@ int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, { SCEnter(); int r; - if (unlikely(IS_DISRUPTED(flags))) { + if (unlikely((flags & STREAM_EOF) != 0 || IS_DISRUPTED(flags))) { r = StateGetProgressCompletionStatus(alproto, flags); } else { uint8_t direction = flags & (STREAM_TOCLIENT | STREAM_TOSERVER); diff --git a/src/app-layer-ssl.c b/src/app-layer-ssl.c index bc0c42142f1c..a479030a26f8 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -106,6 +106,7 @@ SCEnumCharMap tls_decoder_event_table[] = { { "INVALID_SNI_TYPE", TLS_DECODER_EVENT_INVALID_SNI_TYPE }, { "INVALID_SNI_LENGTH", TLS_DECODER_EVENT_INVALID_SNI_LENGTH }, { "TOO_MANY_RECORDS_IN_PACKET", TLS_DECODER_EVENT_TOO_MANY_RECORDS_IN_PACKET }, + { "INVALID_ALERT_MESSAGE", TLS_DECODER_EVENT_INVALID_ALERT }, /* certificate decoding messages */ { "INVALID_CERTIFICATE", TLS_DECODER_EVENT_INVALID_CERTIFICATE }, { "CERTIFICATE_INVALID_LENGTH", TLS_DECODER_EVENT_CERTIFICATE_INVALID_LENGTH }, @@ -1929,6 +1930,38 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, const uint8_t *input return (int)(input - initial_input); } +/** + * \internal + * \brief TLS Alert parser + * + * \param sslstate Pointer to the SSL state. + * \param input Pointer to the received input data. + * \param input_len Length in bytes of the received data. + * \param direction 1 toclient, 0 toserver + * + * \retval The number of bytes parsed on success, 0 if nothing parsed, -1 on failure. + */ +static int SSLv3ParseAlertProtocol( + SSLState *ssl_state, const uint8_t *input, uint32_t input_len, uint8_t direction) +{ + if (input_len < 2) { + SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_ALERT); + return -1; + } + + /* assume a record > 2 to be an encrypted alert record */ + if (input_len == 2) { + uint8_t level = input[0]; + // uint8_t desc = input[1]; + + /* if level Fatal, we consider the tx finished */ + if (level == 2) { + ssl_state->flags |= SSL_AL_FLAG_STATE_FINISHED; + } + } + return 0; +} + /** * \internal * \brief TLS Heartbeat parser (see RFC 6520) @@ -2556,11 +2589,17 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat } break; - case SSLV3_ALERT_PROTOCOL: + case SSLV3_ALERT_PROTOCOL: { AppLayerFrameNewByPointer(ssl_state->f, &stream_slice, input + parsed, ssl_state->curr_connp->record_length, direction, TLS_FRAME_ALERT_DATA); - break; + int retval = SSLv3ParseAlertProtocol(ssl_state, input + parsed, record_len, direction); + if (retval < 0) { + SCLogDebug("SSLv3ParseAlertProtocol returned %d", retval); + return SSL_DECODER_ERROR(-1); + } + break; + } case SSLV3_APPLICATION_PROTOCOL: /* In TLSv1.3 early data (0-RTT) could be sent before the handshake is complete (rfc8446, section 2.3). We should diff --git a/src/app-layer-ssl.h b/src/app-layer-ssl.h index 479ccf51921d..8ad65f886f90 100644 --- a/src/app-layer-ssl.h +++ b/src/app-layer-ssl.h @@ -56,6 +56,7 @@ enum { TLS_DECODER_EVENT_INVALID_SNI_TYPE, TLS_DECODER_EVENT_INVALID_SNI_LENGTH, TLS_DECODER_EVENT_TOO_MANY_RECORDS_IN_PACKET, + TLS_DECODER_EVENT_INVALID_ALERT, /* Certificates decoding messages */ TLS_DECODER_EVENT_INVALID_CERTIFICATE, TLS_DECODER_EVENT_CERTIFICATE_INVALID_LENGTH, diff --git a/src/detect.c b/src/detect.c index 03fa8437068d..5b511ffaa662 100644 --- a/src/detect.c +++ b/src/detect.c @@ -781,6 +781,10 @@ static inline void DetectRulePacketRules( goto next; // handle sig in DetectRunFrame } + /* skip pkt sigs for flow end packets */ + if ((p->flags & PKT_PSEUDO_STREAM_END) != 0 && s->type == SIG_TYPE_PKT) + goto next; + /* don't run mask check for stateful rules. * There we depend on prefilter */ if ((s->mask & scratch->pkt_mask) != s->mask) {