Skip to content

Commit eee8655

Browse files
committed
smtp: complete transactions by progress state
Add directionality to completion states, and replace tx->done by checking for both directions being complete. This means that the transaction is now not complete until the server responds to the clients of data marker, previously the tx was completed when the client send end of data without waiting for the server response. This keeps smtp:response_complete from being exposed before the server response is parsed.
1 parent ff6cd46 commit eee8655

2 files changed

Lines changed: 51 additions & 9 deletions

File tree

src/app-layer-smtp.c

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,12 @@ static inline void SMTPSetProgressTC(SMTPTransaction *tx, uint8_t progress)
230230
tx->progress_tc = progress;
231231
}
232232

233+
static bool SMTPTransactionIsComplete(const SMTPTransaction *tx)
234+
{
235+
return tx && tx->progress_ts == SMTP_REQUEST_COMPLETE &&
236+
tx->progress_tc == SMTP_RESPONSE_COMPLETE;
237+
}
238+
233239
typedef struct SMTPThreadCtx_ {
234240
MpmThreadCtx *smtp_mpm_thread_ctx;
235241
PrefilterRuleStore *pmq;
@@ -761,8 +767,28 @@ static void SetMimeEvents(SMTPState *state, uint32_t events)
761767
static inline void SMTPTransactionComplete(SMTPState *state)
762768
{
763769
DEBUG_VALIDATE_BUG_ON(state->curr_tx == NULL);
764-
if (state->curr_tx)
765-
state->curr_tx->done = true;
770+
if (state->curr_tx) {
771+
SMTPSetProgressTS(state->curr_tx, SMTP_REQUEST_COMPLETE);
772+
SMTPSetProgressTC(state->curr_tx, SMTP_RESPONSE_COMPLETE);
773+
}
774+
}
775+
776+
static inline void SMTPTransactionCompleteTS(SMTPState *state)
777+
{
778+
DEBUG_VALIDATE_BUG_ON(state->curr_tx == NULL);
779+
if (state->curr_tx) {
780+
SMTPSetProgressTS(state->curr_tx, SMTP_REQUEST_COMPLETE);
781+
SCLogDebug("marked tx as ts complete");
782+
}
783+
}
784+
785+
static inline void SMTPTransactionCompleteTC(SMTPState *state)
786+
{
787+
DEBUG_VALIDATE_BUG_ON(state->curr_tx == NULL);
788+
if (state->curr_tx) {
789+
SMTPSetProgressTC(state->curr_tx, SMTP_RESPONSE_COMPLETE);
790+
SCLogDebug("marked tx as tc complete");
791+
}
766792
}
767793

768794
/**
@@ -799,8 +825,7 @@ static int SMTPProcessCommandDATA(
799825
FileFlowToFlags(f, STREAM_TOSERVER));
800826
}
801827
}
802-
SMTPTransactionComplete(state);
803-
SCLogDebug("marked tx as done");
828+
SMTPTransactionCompleteTS(state);
804829
} else if (smtp_config.raw_extraction) {
805830
// message not over, store the line. This is a substitution of
806831
// ProcessDataChunk
@@ -1005,6 +1030,10 @@ static int SMTPProcessReply(
10051030
}
10061031
} else if (IsReplyToCommand(state, SMTP_COMMAND_BDAT)) {
10071032
SMTPSetProgressTC(state->curr_tx, SMTP_RESPONSE_DATA);
1033+
} else if (IsReplyToCommand(state, SMTP_COMMAND_DATA_MODE)) {
1034+
if (!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) {
1035+
SMTPTransactionCompleteTC(state);
1036+
}
10081037
} else if (IsReplyToCommand(state, SMTP_COMMAND_RSET)) {
10091038
if (reply_code == SMTP_REPLY_250 && state->curr_tx &&
10101039
!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) {
@@ -1206,7 +1235,8 @@ static int SMTPProcessRequest(
12061235
if (line->len == 0 && line->delim_len == 0) {
12071236
return 0;
12081237
}
1209-
if (state->curr_tx == NULL || (state->curr_tx->done && !NoNewTx(state, line))) {
1238+
if (state->curr_tx == NULL ||
1239+
(SMTPTransactionIsComplete(state->curr_tx) && !NoNewTx(state, line))) {
12101240
tx = SMTPTransactionCreate(state);
12111241
if (tx == NULL)
12121242
return -1;
@@ -1859,8 +1889,8 @@ static int SMTPStateGetAlstateProgress(void *vtx, uint8_t direction)
18591889
{
18601890
SMTPTransaction *tx = vtx;
18611891
if (direction & STREAM_TOSERVER)
1862-
return tx->done ? SMTP_REQUEST_COMPLETE : tx->progress_ts;
1863-
return tx->done ? SMTP_RESPONSE_COMPLETE : tx->progress_tc;
1892+
return tx->progress_ts;
1893+
return tx->progress_tc;
18641894
}
18651895

18661896
static AppLayerGetFileState SMTPGetTxFiles(void *txv, uint8_t direction)
@@ -2604,6 +2634,13 @@ static int SMTPParserTest02(void)
26042634
printf("smtp parser in inconsistent state\n");
26052635
goto end;
26062636
}
2637+
if (SMTPStateGetAlstateProgress(smtp_state->curr_tx, STREAM_TOSERVER) !=
2638+
SMTP_REQUEST_COMPLETE ||
2639+
SMTPStateGetAlstateProgress(smtp_state->curr_tx, STREAM_TOCLIENT) !=
2640+
SMTP_RESPONSE_DATA) {
2641+
printf("smtp progress in inconsistent state\n");
2642+
goto end;
2643+
}
26072644

26082645
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMTP,
26092646
STREAM_TOCLIENT, reply5, reply5_len);
@@ -2616,6 +2653,13 @@ static int SMTPParserTest02(void)
26162653
printf("smtp parser in inconsistent state\n");
26172654
goto end;
26182655
}
2656+
if (SMTPStateGetAlstateProgress(smtp_state->curr_tx, STREAM_TOSERVER) !=
2657+
SMTP_REQUEST_COMPLETE ||
2658+
SMTPStateGetAlstateProgress(smtp_state->curr_tx, STREAM_TOCLIENT) !=
2659+
SMTP_RESPONSE_COMPLETE) {
2660+
printf("smtp progress in inconsistent state\n");
2661+
goto end;
2662+
}
26192663

26202664
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMTP,
26212665
STREAM_TOSERVER, request6, request6_len);

src/app-layer-smtp.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,6 @@ typedef struct SMTPTransaction_ {
8888

8989
AppLayerTxData tx_data;
9090

91-
/** the tx is complete and can be logged and cleaned */
92-
bool done;
9391
/** to-server firewall progress state. */
9492
uint8_t progress_ts;
9593
/** to-client firewall progress state. */

0 commit comments

Comments
 (0)