From 51ac40009f3b39986b8e92447af732e769bb6746 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Tue, 1 Sep 2026 16:10:44 -0600 Subject: [PATCH] smtp: recover from rejected BDAT commands A server can reject a BDAT command before the client sends the advertised chunk. Suricata would keep waiting for those bytes and treat the rest of the SMTP session as chunk data. Keeps subsequent SMTP commands and message data in sync with the server. Ticket: 8995 --- src/app-layer-smtp.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/app-layer-smtp.c b/src/app-layer-smtp.c index 32d9ef2339..9b91375d9d 100644 --- a/src/app-layer-smtp.c +++ b/src/app-layer-smtp.c @@ -1086,8 +1086,20 @@ static int SMTPProcessReply( SMTPSetEvent(state, SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED); } } else if (IsReplyToCommand(state, SMTP_COMMAND_BDAT)) { + if ((state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE) && + state->current_command == SMTP_COMMAND_BDAT && + state->cmds_idx + 1 == state->cmds_cnt) { + // The server replied before receiving the entire chunk. + state->parser_state &= ~SMTP_PARSER_STATE_COMMAND_DATA_MODE; + } SMTPSetProgressTC(reply_tx, SMTP_RESPONSE_DATA); } else if (IsReplyToCommand(state, SMTP_COMMAND_BDAT_LAST)) { + if ((state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE) && + state->current_command == SMTP_COMMAND_BDAT_LAST && + state->cmds_idx + 1 == state->cmds_cnt) { + // The server replied before receiving the entire chunk. + state->parser_state &= ~SMTP_PARSER_STATE_COMMAND_DATA_MODE; + } if (reply_tx && !(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) { SMTPTransactionCompleteTC(reply_tx); }