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 51ac40009f)
pull/16202/head
Jason Ish 1 week ago committed by Victor Julien
parent ec3a9aa506
commit 27cb46c266

@ -1078,8 +1078,20 @@ static int SMTPProcessReply(
SMTPSetEvent(state, SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED); SMTPSetEvent(state, SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED);
} }
} else if (IsReplyToCommand(state, SMTP_COMMAND_BDAT)) { } 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); SMTPSetProgressTC(reply_tx, SMTP_RESPONSE_DATA);
} else if (IsReplyToCommand(state, SMTP_COMMAND_BDAT_LAST)) { } 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)) { if (reply_tx && !(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) {
SMTPTransactionCompleteTC(reply_tx); SMTPTransactionCompleteTC(reply_tx);
} }

Loading…
Cancel
Save