From 27cb46c266683e4e839fd27c679b8261b414fce0 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 (cherry picked from commit 51ac40009f3b39986b8e92447af732e769bb6746) --- 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 ebf2b05225..f39c2af0ea 100644 --- a/src/app-layer-smtp.c +++ b/src/app-layer-smtp.c @@ -1078,8 +1078,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); }