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.

Ticket: #8393
pull/15835/head
Jason Ish 4 months ago committed by Victor Julien
parent c2728eee01
commit 7b31f41878

@ -232,6 +232,12 @@ static inline void SMTPSetProgressTC(SMTPTransaction *tx, uint8_t progress)
}
}
static bool SMTPTransactionIsComplete(const SMTPTransaction *tx)
{
return tx && tx->progress_ts == SMTP_REQUEST_COMPLETE &&
tx->progress_tc == SMTP_RESPONSE_COMPLETE;
}
typedef struct SMTPThreadCtx_ {
MpmThreadCtx *smtp_mpm_thread_ctx;
PrefilterRuleStore *pmq;
@ -763,8 +769,28 @@ static void SetMimeEvents(SMTPState *state, uint32_t events)
static inline void SMTPTransactionComplete(SMTPState *state)
{
DEBUG_VALIDATE_BUG_ON(state->curr_tx == NULL);
if (state->curr_tx)
state->curr_tx->done = true;
if (state->curr_tx) {
SMTPSetProgressTS(state->curr_tx, SMTP_REQUEST_COMPLETE);
SMTPSetProgressTC(state->curr_tx, SMTP_RESPONSE_COMPLETE);
}
}
static inline void SMTPTransactionCompleteTS(SMTPState *state)
{
DEBUG_VALIDATE_BUG_ON(state->curr_tx == NULL);
if (state->curr_tx) {
SMTPSetProgressTS(state->curr_tx, SMTP_REQUEST_COMPLETE);
SCLogDebug("marked tx as ts complete");
}
}
static inline void SMTPTransactionCompleteTC(SMTPState *state)
{
DEBUG_VALIDATE_BUG_ON(state->curr_tx == NULL);
if (state->curr_tx) {
SMTPSetProgressTC(state->curr_tx, SMTP_RESPONSE_COMPLETE);
SCLogDebug("marked tx as tc complete");
}
}
/**
@ -801,8 +827,7 @@ static int SMTPProcessCommandDATA(
FileFlowToFlags(f, STREAM_TOSERVER));
}
}
SMTPTransactionComplete(state);
SCLogDebug("marked tx as done");
SMTPTransactionCompleteTS(state);
} else if (smtp_config.raw_extraction) {
// message not over, store the line. This is a substitution of
// ProcessDataChunk
@ -1007,6 +1032,10 @@ static int SMTPProcessReply(
}
} else if (IsReplyToCommand(state, SMTP_COMMAND_BDAT)) {
SMTPSetProgressTC(state->curr_tx, SMTP_RESPONSE_DATA);
} else if (IsReplyToCommand(state, SMTP_COMMAND_DATA_MODE)) {
if (!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) {
SMTPTransactionCompleteTC(state);
}
} else if (IsReplyToCommand(state, SMTP_COMMAND_RSET)) {
if (reply_code == SMTP_REPLY_250 && state->curr_tx &&
!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) {
@ -1208,7 +1237,8 @@ static int SMTPProcessRequest(
if (line->len == 0 && line->delim_len == 0) {
return 0;
}
if (state->curr_tx == NULL || (state->curr_tx->done && !NoNewTx(state, line))) {
if (state->curr_tx == NULL ||
(SMTPTransactionIsComplete(state->curr_tx) && !NoNewTx(state, line))) {
tx = SMTPTransactionCreate(state);
if (tx == NULL)
return -1;
@ -1861,9 +1891,9 @@ static int SMTPStateGetAlstateProgress(void *vtx, uint8_t direction)
{
SMTPTransaction *tx = vtx;
if (direction & STREAM_TOSERVER) {
return tx->done ? SMTP_REQUEST_COMPLETE : tx->progress_ts;
return tx->progress_ts;
}
return tx->done ? SMTP_RESPONSE_COMPLETE : tx->progress_tc;
return tx->progress_tc;
}
static AppLayerGetFileState SMTPGetTxFiles(void *txv, uint8_t direction)

@ -88,8 +88,6 @@ typedef struct SMTPTransaction_ {
AppLayerTxData tx_data;
/** the tx is complete and can be logged and cleaned */
bool done;
/** to-server firewall progress state. */
uint8_t progress_ts;
/** to-client firewall progress state. */

Loading…
Cancel
Save