diff options
author | Ashlee Young <ashlee@wildernessvoice.com> | 2015-11-24 23:17:00 -0800 |
---|---|---|
committer | Ashlee Young <ashlee@wildernessvoice.com> | 2015-11-24 23:17:00 -0800 |
commit | 43f0d5031db2a43ecdbee6f7dfda75cef6d4f56e (patch) | |
tree | f73f4185f5fe44cc44b823cb6137542be7edc9ef /framework/src/suricata/src/app-layer-smtp.c | |
parent | 77ce3be7567bd01c66d8ee88a93b485666723501 (diff) |
Added apache 2 license verbage
Change-Id: I6a0b484496f7f3ba77c3584f5ab5a1acf353b298
Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/suricata/src/app-layer-smtp.c')
-rw-r--r-- | framework/src/suricata/src/app-layer-smtp.c | 153 |
1 files changed, 149 insertions, 4 deletions
diff --git a/framework/src/suricata/src/app-layer-smtp.c b/framework/src/suricata/src/app-layer-smtp.c index 1951613d..0c161edb 100644 --- a/framework/src/suricata/src/app-layer-smtp.c +++ b/framework/src/suricata/src/app-layer-smtp.c @@ -220,7 +220,9 @@ SCEnumCharMap smtp_reply_map[ ] = { }; /* Create SMTP config structure */ -SMTPConfig smtp_config = { 0, { 0, 0, 0, 0 }, 0, 0, 0}; +SMTPConfig smtp_config = { 0, { 0, 0, 0, 0, 0 }, 0, 0, 0}; + +static SMTPString *SMTPStringAlloc(void); /** * \brief Configure SMTP Mime Decoder by parsing out mime section of YAML @@ -264,6 +266,11 @@ static void SMTPConfigure(void) { if (ret) { smtp_config.mime_config.extract_urls = val; } + + ret = ConfGetChildValueBool(config, "body-md5", &val); + if (ret) { + smtp_config.mime_config.body_md5 = val; + } } /* Pass mime config data to MimeDec API */ @@ -323,6 +330,7 @@ static SMTPTransaction *SMTPTransactionCreate(void) return NULL; } + TAILQ_INIT(&tx->rcpt_to_list); tx->mime_state = NULL; return tx; } @@ -366,7 +374,7 @@ int SMTPProcessDataChunk(const uint8_t *chunk, uint32_t len, if (smtp_state->files_ts == NULL) { ret = MIME_DEC_ERR_MEM; SCLogError(SC_ERR_MEM_ALLOC, "Could not create file container"); - goto end; + SCReturnInt(ret); } } files = smtp_state->files_ts; @@ -448,7 +456,7 @@ int SMTPProcessDataChunk(const uint8_t *chunk, uint32_t len, if (files != NULL) { FilePrune(files); } -end: + SCReturnInt(ret); } @@ -805,7 +813,8 @@ static int SMTPProcessCommandDATA(SMTPState *state, Flow *f, if (smtp_config.decode_mime && state->curr_tx->mime_state) { int ret = MimeDecParseLine((const uint8_t *) state->current_line, - state->current_line_len, state->curr_tx->mime_state); + state->current_line_len, state->current_line_delimiter_len, + state->curr_tx->mime_state); if (ret != MIME_DEC_OK) { SCLogDebug("MimeDecParseLine() function returned an error code: %d", ret); } @@ -955,6 +964,71 @@ 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++; + } + + *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); +} + +static int SMTPParseCommandRCPTTO(SMTPState *state) +{ + uint8_t *rcptto; + uint16_t rcptto_len; + + if (SMTPParseCommandWithParam(state, 7, &rcptto, &rcptto_len) == 0) { + SMTPString *rcptto_str = SMTPStringAlloc(); + if (rcptto_str) { + rcptto_str->str = rcptto; + rcptto_str->len = rcptto_len; + TAILQ_INSERT_TAIL(&state->curr_tx->rcpt_to_list, rcptto_str, next); + } else { + SCFree(rcptto); + return -1; + } + } else { + return -1; + } + return 0; +} + /* consider 'rset' and 'quit' to be part of the existing state */ static int NoNewTx(SMTPState *state) { @@ -1027,6 +1101,28 @@ 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 if (state->current_line_len >= 7 && + SCMemcmpLowercase("rcpt to", state->current_line, 7) == 0) { + r = SMTPParseCommandRCPTTO(state); + if (r == -1) { + SCReturnInt(-1); + } + state->current_command = SMTP_COMMAND_OTHER_CMD; } else { state->current_command = SMTP_COMMAND_OTHER_CMD; } @@ -1142,6 +1238,25 @@ void *SMTPStateAlloc(void) return smtp_state; } +static SMTPString *SMTPStringAlloc(void) +{ + SMTPString *smtp_string = SCMalloc(sizeof(SMTPString)); + if (unlikely(smtp_string == NULL)) + return NULL; + memset(smtp_string, 0, sizeof(SMTPString)); + + return smtp_string; +} + + +static void SMTPStringFree(SMTPString *str) +{ + if (str->str) { + SCFree(str->str); + } + SCFree(str); +} + static void *SMTPLocalStorageAlloc(void) { /* needed by the mpm */ @@ -1178,6 +1293,15 @@ static void SMTPTransactionFree(SMTPTransaction *tx, SMTPState *state) if (tx->de_state != NULL) DetectEngineStateFree(tx->de_state); + + if (tx->mail_from) + SCFree(tx->mail_from); + + SMTPString *str = NULL; + while ((str = TAILQ_FIRST(&tx->rcpt_to_list))) { + TAILQ_REMOVE(&tx->rcpt_to_list, str, next); + SMTPStringFree(str); + } #if 0 if (tx->decoder_events->cnt <= smtp_state->events) smtp_state->events -= tx->decoder_events->cnt; @@ -1205,6 +1329,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; @@ -4365,6 +4493,13 @@ int SMTPParserTest14(void) SCMutexUnlock(&f.m); goto end; } + + if ((smtp_state->helo_len != 7) || strncmp("boo.com", (char *)smtp_state->helo, 7)) { + printf("incorrect parsing of HELO field '%s' (%d)\n", smtp_state->helo, smtp_state->helo_len); + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); if (smtp_state->input_len != 0 || smtp_state->cmds_cnt != 0 || @@ -4402,6 +4537,16 @@ int SMTPParserTest14(void) SCMutexUnlock(&f.m); goto end; } + + if ((smtp_state->curr_tx->mail_from_len != 14) || + strncmp("asdff@asdf.com", (char *)smtp_state->curr_tx->mail_from, 14)) { + printf("incorrect parsing of MAIL FROM field '%s' (%d)\n", + smtp_state->curr_tx->mail_from, + smtp_state->curr_tx->mail_from_len); + SCMutexUnlock(&f.m); + goto end; + } + SCMutexUnlock(&f.m); if (smtp_state->input_len != 0 || smtp_state->cmds_cnt != 0 || |