Skip to content

Commit 4d6c3bb

Browse files
committed
fixup
1 parent 867c499 commit 4d6c3bb

1 file changed

Lines changed: 52 additions & 5 deletions

File tree

src/app-layer-smtp.c

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@
9595
/* All other commands are represented by this var */
9696
#define SMTP_COMMAND_OTHER_CMD 5
9797
#define SMTP_COMMAND_RSET 6
98+
/* Like SMTP_COMMAND_BDAT, but the chunk was flagged LAST, so the server
99+
* reply matched to this command is the final verdict for the
100+
* transaction */
101+
#define SMTP_COMMAND_BDAT_LAST 7
98102

99103
#define SMTP_DEFAULT_MAX_TX 256
100104

@@ -906,6 +910,21 @@ static inline bool IsReplyToCommand(const SMTPState *state, const uint8_t cmd)
906910
state->cmds[state->cmds_idx] == cmd);
907911
}
908912

913+
/* Get the transaction that a DATA/BDAT related server reply applies
914+
* to: the oldest transaction that has completed on the request side
915+
* but has not yet seen its response side completed. Falls back to the
916+
* current transaction, which is the common case. */
917+
static SMTPTransaction *SMTPGetReplyTx(SMTPState *state)
918+
{
919+
SMTPTransaction *tx;
920+
TAILQ_FOREACH (tx, &state->tx_list, next) {
921+
if (tx->done && tx->progress_tc < SMTP_RESPONSE_COMPLETE) {
922+
return tx;
923+
}
924+
}
925+
return state->curr_tx;
926+
}
927+
909928
static int SMTPProcessReply(
910929
SMTPState *state, Flow *f, SMTPThreadCtx *td, SMTPInput *input, const SMTPLine *line)
911930
{
@@ -990,14 +1009,15 @@ static int SMTPProcessReply(
9901009
}
9911010
if (state->curr_tx) {
9921011
SMTPTransactionComplete(state);
1012+
SMTPSetProgressTC(state->curr_tx, SMTP_RESPONSE_COMPLETE);
9931013
}
9941014
} else {
9951015
/* decoder event */
9961016
SMTPSetEvent(state, SMTP_DECODER_EVENT_TLS_REJECTED);
9971017
}
9981018
} else if (IsReplyToCommand(state, SMTP_COMMAND_DATA)) {
9991019
if (reply_code == SMTP_REPLY_354) {
1000-
SMTPSetProgressTC(state->curr_tx, SMTP_RESPONSE_DATA);
1020+
SMTPSetProgressTC(SMTPGetReplyTx(state), SMTP_RESPONSE_DATA);
10011021
/* Next comes the mail for the DATA command in toserver direction */
10021022
state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
10031023
} else {
@@ -1009,11 +1029,32 @@ static int SMTPProcessReply(
10091029
SMTPSetEvent(state, SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED);
10101030
}
10111031
} else if (IsReplyToCommand(state, SMTP_COMMAND_BDAT)) {
1012-
SMTPSetProgressTC(state->curr_tx, SMTP_RESPONSE_DATA);
1032+
SMTPSetProgressTC(SMTPGetReplyTx(state), SMTP_RESPONSE_DATA);
1033+
} else if (IsReplyToCommand(state, SMTP_COMMAND_BDAT_LAST)) {
1034+
/* the reply to the BDAT LAST chunk is the server's verdict on
1035+
* the transaction */
1036+
if (!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) {
1037+
SMTPTransaction *reply_tx = SMTPGetReplyTx(state);
1038+
if (reply_tx != NULL) {
1039+
reply_tx->tx_data.updated_tc = true;
1040+
SMTPSetProgressTC(reply_tx, SMTP_RESPONSE_COMPLETE);
1041+
}
1042+
}
1043+
} else if (IsReplyToCommand(state, SMTP_COMMAND_DATA_MODE)) {
1044+
/* the reply to the mail data is the server's verdict on the
1045+
* transaction */
1046+
if (!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) {
1047+
SMTPTransaction *reply_tx = SMTPGetReplyTx(state);
1048+
if (reply_tx != NULL) {
1049+
reply_tx->tx_data.updated_tc = true;
1050+
SMTPSetProgressTC(reply_tx, SMTP_RESPONSE_COMPLETE);
1051+
}
1052+
}
10131053
} else if (IsReplyToCommand(state, SMTP_COMMAND_RSET)) {
10141054
if (reply_code == SMTP_REPLY_250 && state->curr_tx &&
10151055
!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) {
10161056
SMTPTransactionComplete(state);
1057+
SMTPSetProgressTC(state->curr_tx, SMTP_RESPONSE_COMPLETE);
10171058
}
10181059
} else {
10191060
/* we don't care for any other command for now */
@@ -1308,7 +1349,11 @@ static int SMTPProcessRequest(
13081349
if (r == -1) {
13091350
SCReturnInt(-1);
13101351
}
1311-
state->current_command = SMTP_COMMAND_BDAT;
1352+
if (state->bdat_last) {
1353+
state->current_command = SMTP_COMMAND_BDAT_LAST;
1354+
} else {
1355+
state->current_command = SMTP_COMMAND_BDAT;
1356+
}
13121357
SMTPSetProgressTS(tx, SMTP_REQUEST_DATA);
13131358
if (state->bdat_chunk_len == 0) {
13141359
state->parser_state &= ~SMTP_PARSER_STATE_COMMAND_DATA_MODE;
@@ -1360,6 +1405,7 @@ static int SMTPProcessRequest(
13601405
return SMTPProcessCommandDATA(state, tx, f, line);
13611406

13621407
case SMTP_COMMAND_BDAT:
1408+
case SMTP_COMMAND_BDAT_LAST:
13631409
return SMTPProcessCommandBDAT(state, line);
13641410

13651411
default:
@@ -1496,7 +1542,8 @@ static AppLayerResult SMTPParse(uint8_t direction, Flow *f, SMTPState *state,
14961542
/* toserver */
14971543
if (direction == 0) {
14981544
if (((state->current_command == SMTP_COMMAND_DATA) ||
1499-
(state->current_command == SMTP_COMMAND_BDAT)) &&
1545+
(state->current_command == SMTP_COMMAND_BDAT) ||
1546+
(state->current_command == SMTP_COMMAND_BDAT_LAST)) &&
15001547
(state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
15011548
int ret = SMTPPreProcessCommands(state, f, &stream_slice, &input, &line);
15021549
DEBUG_VALIDATE_BUG_ON(ret != 0 && ret != -1 && ret != 1);
@@ -1896,7 +1943,7 @@ static int SMTPStateGetAlstateProgress(void *vtx, uint8_t direction)
18961943
SMTPTransaction *tx = vtx;
18971944
if (direction & STREAM_TOSERVER)
18981945
return tx->done ? SMTP_REQUEST_COMPLETE : tx->progress_ts;
1899-
return tx->done ? SMTP_RESPONSE_COMPLETE : tx->progress_tc;
1946+
return tx->progress_tc;
19001947
}
19011948

19021949
static AppLayerGetFileState SMTPGetTxFiles(void *txv, uint8_t direction)

0 commit comments

Comments
 (0)