diff --git a/src/app-layer-smtp.c b/src/app-layer-smtp.c index 1951613d1f..d0c6589eea 100644 --- a/src/app-layer-smtp.c +++ b/src/app-layer-smtp.c @@ -955,6 +955,52 @@ static int SMTPParseCommandBDAT(SMTPState *state) return 0; } +static int SMTPParseCommandWithParam(SMTPState *state, uint8_t prefix_len, uint8_t **target, uint16_t *target_len) +{ + int i = prefix_len + 1; + int spc_i = 0; + + while (i < state->current_line_len) { + if (state->current_line[i] != ' ') { + break; + } + i++; + } + + /* rfc1870: with the size extension the mail from can be followed by an option. + We use the space separator to detect it. */ + spc_i = i; + while (spc_i < state->current_line_len) { + if (state->current_line[spc_i] == ' ') { + break; + } + spc_i++; + } + + /* FIXME check arithmetic */ + *target = SCMalloc(spc_i - i + 1); + if (*target == NULL) + return -1; + memcpy(*target, state->current_line + i, spc_i - i); + (*target)[spc_i - i] = '\0'; + *target_len = spc_i - i; + + return 0; + +} + +static int SMTPParseCommandHELO(SMTPState *state) +{ + return SMTPParseCommandWithParam(state, 4, &state->helo, &state->helo_len); +} + +static int SMTPParseCommandMAILFROM(SMTPState *state) +{ + return SMTPParseCommandWithParam(state, 9, + &state->curr_tx->mail_from, + &state->curr_tx->mail_from_len); +} + /* consider 'rset' and 'quit' to be part of the existing state */ static int NoNewTx(SMTPState *state) { @@ -1027,6 +1073,21 @@ static int SMTPProcessRequest(SMTPState *state, Flow *f, } state->current_command = SMTP_COMMAND_BDAT; state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE; + } else if (state->current_line_len >= 4 && + ((SCMemcmpLowercase("helo", state->current_line, 4) == 0) || + SCMemcmpLowercase("ehlo", state->current_line, 4) == 0)) { + r = SMTPParseCommandHELO(state); + if (r == -1) { + SCReturnInt(-1); + } + state->current_command = SMTP_COMMAND_OTHER_CMD; + } else if (state->current_line_len >= 9 && + SCMemcmpLowercase("mail from", state->current_line, 9) == 0) { + r = SMTPParseCommandMAILFROM(state); + if (r == -1) { + SCReturnInt(-1); + } + state->current_command = SMTP_COMMAND_OTHER_CMD; } else { state->current_command = SMTP_COMMAND_OTHER_CMD; } @@ -1178,6 +1239,10 @@ static void SMTPTransactionFree(SMTPTransaction *tx, SMTPState *state) if (tx->de_state != NULL) DetectEngineStateFree(tx->de_state); + + if (tx->mail_from) + SCFree(tx->mail_from); + #if 0 if (tx->decoder_events->cnt <= smtp_state->events) smtp_state->events -= tx->decoder_events->cnt; @@ -1205,6 +1270,10 @@ static void SMTPStateFree(void *p) SCFree(smtp_state->tc_db); } + if (smtp_state->helo) { + SCFree(smtp_state->helo); + } + FileContainerFree(smtp_state->files_ts); SMTPTransaction *tx = NULL; diff --git a/src/app-layer-smtp.h b/src/app-layer-smtp.h index 02090c61c0..a63061638e 100644 --- a/src/app-layer-smtp.h +++ b/src/app-layer-smtp.h @@ -65,6 +65,10 @@ typedef struct SMTPTransaction_ { AppLayerDecoderEvents *decoder_events; /**< per tx events */ DetectEngineState *de_state; + /* MAIL FROM parameters */ + uint8_t *mail_from; + uint16_t mail_from_len; + TAILQ_ENTRY(SMTPTransaction_) next; } SMTPTransaction; @@ -136,6 +140,9 @@ typedef struct SMTPState_ { /** the list of files sent to the server */ FileContainer *files_ts; + /* HELO of HELO message content */ + uint8_t *helo; + uint16_t helo_len; } SMTPState; /* Create SMTP config structure */