diff options
Diffstat (limited to 'framework/src/suricata/src/app-layer-smtp.c')
-rw-r--r-- | framework/src/suricata/src/app-layer-smtp.c | 5025 |
1 files changed, 0 insertions, 5025 deletions
diff --git a/framework/src/suricata/src/app-layer-smtp.c b/framework/src/suricata/src/app-layer-smtp.c deleted file mode 100644 index cd0a732e..00000000 --- a/framework/src/suricata/src/app-layer-smtp.c +++ /dev/null @@ -1,5025 +0,0 @@ -/* Copyright (C) 2007-2012 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Anoop Saldanha <anoopsaldanha@gmail.com> - */ - -#include "suricata.h" -#include "suricata-common.h" -#include "debug.h" -#include "decode.h" -#include "threads.h" - -#include "stream-tcp-private.h" -#include "stream-tcp-reassemble.h" -#include "stream-tcp.h" -#include "stream.h" - -#include "app-layer.h" -#include "app-layer-detect-proto.h" -#include "app-layer-protos.h" -#include "app-layer-parser.h" -#include "app-layer-smtp.h" - -#include "util-mpm.h" -#include "util-debug.h" -#include "util-byte.h" -#include "util-unittest.h" -#include "util-byte.h" -#include "util-unittest-helper.h" -#include "util-memcmp.h" -#include "flow-util.h" - -#include "detect-engine.h" -#include "detect-engine-state.h" -#include "detect-parse.h" - -#include "decode-events.h" -#include "conf.h" - -#include "util-mem.h" -#include "util-misc.h" - -/* content-limit default value */ -#define FILEDATA_CONTENT_LIMIT 1000 -/* content-inspect-min-size default value */ -#define FILEDATA_CONTENT_INSPECT_MIN_SIZE 1000 -/* content-inspect-window default value */ -#define FILEDATA_CONTENT_INSPECT_WINDOW 1000 - -#define SMTP_MAX_REQUEST_AND_REPLY_LINE_LENGTH 510 - -#define SMTP_COMMAND_BUFFER_STEPS 5 - -/* we are in process of parsing a fresh command. Just a placeholder. If we - * are not in STATE_COMMAND_DATA_MODE, we have to be in this mode */ -#define SMTP_PARSER_STATE_COMMAND_MODE 0x00 -/* we are in mode of parsing a command's data. Used when we are parsing tls - * or accepting the rfc 2822 mail after DATA command */ -#define SMTP_PARSER_STATE_COMMAND_DATA_MODE 0x01 -/* Used when we are still in the process of parsing a server command. Used - * with multi-line replies and the stream is fragmented before all the lines - * for a response is seen */ -#define SMTP_PARSER_STATE_PARSING_SERVER_RESPONSE 0x02 -/* Used to indicate that the parser has seen the first reply */ -#define SMTP_PARSER_STATE_FIRST_REPLY_SEEN 0x04 -/* Used to indicate that the parser is parsing a multiline reply */ -#define SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY 0x08 - -/* Various SMTP commands - * We currently have var-ified just STARTTLS and DATA, since we need to them - * for state transitions. The rest are just indicate as OTHER_CMD. Other - * commands would be introduced as and when needed */ -#define SMTP_COMMAND_STARTTLS 1 -#define SMTP_COMMAND_DATA 2 -#define SMTP_COMMAND_BDAT 3 -/* not an actual command per se, but the mode where we accept the mail after - * DATA has it's own reply code for completion, from the server. We give this - * stage a pseudo command of it's own, so that we can add this to the command - * buffer to match with the reply */ -#define SMTP_COMMAND_DATA_MODE 4 -/* All other commands are represented by this var */ -#define SMTP_COMMAND_OTHER_CMD 5 - -/* Different EHLO extensions. Not used now. */ -#define SMTP_EHLO_EXTENSION_PIPELINING -#define SMTP_EHLO_EXTENSION_SIZE -#define SMTP_EHLO_EXTENSION_DSN -#define SMTP_EHLO_EXTENSION_STARTTLS -#define SMTP_EHLO_EXTENSION_8BITMIME - -SCEnumCharMap smtp_decoder_event_table[ ] = { - { "INVALID_REPLY", SMTP_DECODER_EVENT_INVALID_REPLY }, - { "UNABLE_TO_MATCH_REPLY_WITH_REQUEST", - SMTP_DECODER_EVENT_UNABLE_TO_MATCH_REPLY_WITH_REQUEST }, - { "MAX_COMMAND_LINE_LEN_EXCEEDED", - SMTP_DECODER_EVENT_MAX_COMMAND_LINE_LEN_EXCEEDED }, - { "MAX_REPLY_LINE_LEN_EXCEEDED", - SMTP_DECODER_EVENT_MAX_REPLY_LINE_LEN_EXCEEDED }, - { "INVALID_PIPELINED_SEQUENCE", - SMTP_DECODER_EVENT_INVALID_PIPELINED_SEQUENCE }, - { "BDAT_CHUNK_LEN_EXCEEDED", - SMTP_DECODER_EVENT_BDAT_CHUNK_LEN_EXCEEDED }, - { "NO_SERVER_WELCOME_MESSAGE", - SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE }, - { "TLS_REJECTED", - SMTP_DECODER_EVENT_TLS_REJECTED }, - { "DATA_COMMAND_REJECTED", - SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED }, - - /* MIME Events */ - { "MIME_PARSE_FAILED", - SMTP_DECODER_EVENT_MIME_PARSE_FAILED }, - { "MIME_MALFORMED_MSG", - SMTP_DECODER_EVENT_MIME_MALFORMED_MSG }, - { "MIME_INVALID_BASE64", - SMTP_DECODER_EVENT_MIME_INVALID_BASE64 }, - { "MIME_INVALID_QP", - SMTP_DECODER_EVENT_MIME_INVALID_QP }, - { "MIME_LONG_LINE", - SMTP_DECODER_EVENT_MIME_LONG_LINE }, - { "MIME_LONG_ENC_LINE", - SMTP_DECODER_EVENT_MIME_LONG_ENC_LINE }, - { "MIME_LONG_HEADER_NAME", - SMTP_DECODER_EVENT_MIME_LONG_HEADER_NAME }, - { "MIME_LONG_HEADER_VALUE", - SMTP_DECODER_EVENT_MIME_LONG_HEADER_VALUE }, - { "MIME_LONG_BOUNDARY", - SMTP_DECODER_EVENT_MIME_BOUNDARY_TOO_LONG }, - - { NULL, -1 }, -}; - -#define SMTP_MPM DEFAULT_MPM - -static MpmCtx *smtp_mpm_ctx = NULL; -MpmThreadCtx *smtp_mpm_thread_ctx; - -/* smtp reply codes. If an entry is made here, please make a simultaneous - * entry in smtp_reply_map */ -enum { - SMTP_REPLY_211, - SMTP_REPLY_214, - SMTP_REPLY_220, - SMTP_REPLY_221, - SMTP_REPLY_235, - SMTP_REPLY_250, - SMTP_REPLY_251, - SMTP_REPLY_252, - - SMTP_REPLY_334, - SMTP_REPLY_354, - - SMTP_REPLY_421, - SMTP_REPLY_450, - SMTP_REPLY_451, - SMTP_REPLY_452, - SMTP_REPLY_455, - - SMTP_REPLY_500, - SMTP_REPLY_501, - SMTP_REPLY_502, - SMTP_REPLY_503, - SMTP_REPLY_504, - SMTP_REPLY_550, - SMTP_REPLY_551, - SMTP_REPLY_552, - SMTP_REPLY_553, - SMTP_REPLY_554, - SMTP_REPLY_555, -}; - -SCEnumCharMap smtp_reply_map[ ] = { - { "211", SMTP_REPLY_211 }, - { "214", SMTP_REPLY_214 }, - { "220", SMTP_REPLY_220 }, - { "221", SMTP_REPLY_221 }, - { "235", SMTP_REPLY_235 }, - { "250", SMTP_REPLY_250 }, - { "251", SMTP_REPLY_251 }, - { "252", SMTP_REPLY_252 }, - - { "334", SMTP_REPLY_334 }, - { "354", SMTP_REPLY_354 }, - - { "421", SMTP_REPLY_421 }, - { "450", SMTP_REPLY_450 }, - { "451", SMTP_REPLY_451 }, - { "452", SMTP_REPLY_452 }, - { "455", SMTP_REPLY_455 }, - - { "500", SMTP_REPLY_500 }, - { "501", SMTP_REPLY_501 }, - { "502", SMTP_REPLY_502 }, - { "503", SMTP_REPLY_503 }, - { "504", SMTP_REPLY_504 }, - { "550", SMTP_REPLY_550 }, - { "551", SMTP_REPLY_551 }, - { "552", SMTP_REPLY_552 }, - { "553", SMTP_REPLY_553 }, - { "554", SMTP_REPLY_554 }, - { "555", SMTP_REPLY_555 }, - { NULL, -1 }, -}; - -/* Create SMTP config structure */ -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 - * config file - * - * \return none - */ -static void SMTPConfigure(void) { - - SCEnter(); - int ret = 0, val; - intmax_t imval; - uint32_t content_limit = 0; - uint32_t content_inspect_min_size = 0; - uint32_t content_inspect_window = 0; - - ConfNode *config = ConfGetNode("app-layer.protocols.smtp.mime"); - if (config != NULL) { - - ret = ConfGetChildValueBool(config, "decode-mime", &val); - if (ret) { - smtp_config.decode_mime = val; - } - - ret = ConfGetChildValueBool(config, "decode-base64", &val); - if (ret) { - smtp_config.mime_config.decode_base64 = val; - } - - ret = ConfGetChildValueBool(config, "decode-quoted-printable", &val); - if (ret) { - smtp_config.mime_config.decode_quoted_printable = val; - } - - ret = ConfGetChildValueInt(config, "header-value-depth", &imval); - if (ret) { - smtp_config.mime_config.header_value_depth = (uint32_t) imval; - } - - ret = ConfGetChildValueBool(config, "extract-urls", &val); - 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 */ - MimeDecSetConfig(&smtp_config.mime_config); - - ConfNode *t = ConfGetNode("app-layer.protocols.smtp.inspected-tracker"); - ConfNode *p = NULL; - - if (t == NULL) - return; - - TAILQ_FOREACH(p, &t->head, next) { - if (strcasecmp("content-limit", p->name) == 0) { - if (ParseSizeStringU32(p->val, &content_limit) < 0) { - SCLogWarning(SC_ERR_SIZE_PARSE, "Error parsing content-limit " - "from conf file - %s. Killing engine", p->val); - content_limit = FILEDATA_CONTENT_LIMIT; - } - } - - if (strcasecmp("content-inspect-min-size", p->name) == 0) { - if (ParseSizeStringU32(p->val, &content_inspect_min_size) < 0) { - SCLogWarning(SC_ERR_SIZE_PARSE, "Error parsing content-inspect-min-size-limit " - "from conf file - %s. Killing engine", p->val); - content_inspect_min_size = FILEDATA_CONTENT_INSPECT_MIN_SIZE; - } - } - - if (strcasecmp("content-inspect-window", p->name) == 0) { - if (ParseSizeStringU32(p->val, &content_inspect_window) < 0) { - SCLogWarning(SC_ERR_SIZE_PARSE, "Error parsing content-inspect-window " - "from conf file - %s. Killing engine", p->val); - content_inspect_window = FILEDATA_CONTENT_INSPECT_WINDOW; - } - } - } - - SCReturn; -} - -void SMTPSetEvent(SMTPState *s, uint8_t e) -{ - SCLogDebug("setting event %u", e); - - if (s->curr_tx != NULL) { - AppLayerDecoderEventsSetEventRaw(&s->curr_tx->decoder_events, e); -// s->events++; - return; - } - SCLogDebug("couldn't set event %u", e); -} - -static SMTPTransaction *SMTPTransactionCreate(void) -{ - SMTPTransaction *tx = SCCalloc(1, sizeof(*tx)); - if (tx == NULL) { - return NULL; - } - - TAILQ_INIT(&tx->rcpt_to_list); - tx->mime_state = NULL; - return tx; -} - -int SMTPProcessDataChunk(const uint8_t *chunk, uint32_t len, - MimeDecParseState *state) { - - int ret = MIME_DEC_OK; - Flow *flow = (Flow *) state->data; - SMTPState *smtp_state = (SMTPState *) flow->alstate; - MimeDecEntity *entity = (MimeDecEntity *) state->stack->top->data; - FileContainer *files = NULL; - uint16_t flags = 0; - - /* Set flags */ - if (flow->flags & FLOW_FILE_NO_STORE_TS) { - flags |= FILE_NOSTORE; - } - - if (flow->flags & FLOW_FILE_NO_MAGIC_TS) { - flags |= FILE_NOMAGIC; - } - - if (flow->flags & FLOW_FILE_NO_MD5_TS) { - flags |= FILE_NOMD5; - } - - /* Determine whether to process files */ - if ((flags & (FILE_NOSTORE | FILE_NOMAGIC | FILE_NOMD5)) == - (FILE_NOSTORE | FILE_NOMAGIC | FILE_NOMD5)) { - SCLogDebug("File content ignored"); - return 0; - } - - /* Find file */ - if (entity->ctnt_flags & CTNT_IS_ATTACHMENT) { - - /* Make sure file container allocated */ - if (smtp_state->files_ts == NULL) { - smtp_state->files_ts = FileContainerAlloc(); - if (smtp_state->files_ts == NULL) { - ret = MIME_DEC_ERR_MEM; - SCLogError(SC_ERR_MEM_ALLOC, "Could not create file container"); - SCReturnInt(ret); - } - } - files = smtp_state->files_ts; - - /* Open file if necessary */ - if (state->body_begin) { - - if (SCLogDebugEnabled()) { - SCLogDebug("Opening file...%u bytes", len); - printf("File - "); - for (uint32_t i = 0; i < entity->filename_len; i++) { - printf("%c", entity->filename[i]); - } - printf("\n"); - } - - /* Set storage flag if applicable since only the first file in the - * flow seems to be processed by the 'filestore' detector */ - if (files->head != NULL && (files->head->flags & FILE_STORE)) { - flags |= FILE_STORE; - } - - if (FileOpenFile(files, (uint8_t *) entity->filename, entity->filename_len, - (uint8_t *) chunk, len, flags) == NULL) { - ret = MIME_DEC_ERR_DATA; - SCLogDebug("FileOpenFile() failed"); - } - - /* If close in the same chunk, then pass in empty bytes */ - if (state->body_end) { - - SCLogDebug("Closing file...%u bytes", len); - - if (files->tail->state == FILE_STATE_OPENED) { - ret = FileCloseFile(files, (uint8_t *) NULL, 0, flags); - if (ret != 0) { - SCLogDebug("FileCloseFile() failed: %d", ret); - ret = MIME_DEC_ERR_DATA; - } - } else { - SCLogDebug("File already closed"); - } - } - } else if (state->body_end) { - /* Close file */ - SCLogDebug("Closing file...%u bytes", len); - - if (files && files->tail && files->tail->state == FILE_STATE_OPENED) { - ret = FileCloseFile(files, (uint8_t *) chunk, len, flags); - if (ret != 0) { - SCLogDebug("FileCloseFile() failed: %d", ret); - ret = MIME_DEC_ERR_DATA; - } - } else { - SCLogDebug("File already closed"); - } - } else { - /* Append data chunk to file */ - SCLogDebug("Appending file...%u bytes", len); - - /* 0 is ok, -2 is not stored, -1 is error */ - ret = FileAppendData(files, (uint8_t *) chunk, len); - if (ret == -2) { - ret = 0; - SCLogDebug("FileAppendData() - file no longer being extracted"); - } else if (ret < 0) { - SCLogDebug("FileAppendData() failed: %d", ret); - ret = MIME_DEC_ERR_DATA; - } - } - - if (ret == 0) { - SCLogDebug("Successfully processed file data!"); - } - } else { - SCLogDebug("Body not a Ctnt_attachment"); - } - - if (files != NULL) { - FilePrune(files); - } - - SCReturnInt(ret); -} - -/** - * \internal - * \brief Get the next line from input. It doesn't do any length validation. - * - * \param state The smtp state. - * - * \retval 0 On suceess. - * \retval -1 Either when we don't have any new lines to supply anymore or - * on failure. - */ -static int SMTPGetLine(SMTPState *state) -{ - SCEnter(); - void *ptmp; - - /* we have run out of input */ - if (state->input_len <= 0) - return -1; - - /* toserver */ - if (state->direction == 0) { - if (state->ts_current_line_lf_seen == 1) { - /* we have seen the lf for the previous line. Clear the parser - * details to parse new line */ - state->ts_current_line_lf_seen = 0; - if (state->ts_current_line_db == 1) { - state->ts_current_line_db = 0; - SCFree(state->ts_db); - state->ts_db = NULL; - state->ts_db_len = 0; - state->current_line = NULL; - state->current_line_len = 0; - } - } - - uint8_t *lf_idx = memchr(state->input, 0x0a, state->input_len); - - if (lf_idx == NULL) { - /* fragmented lines. Decoder event for special cases. Not all - * fragmented lines should be treated as a possible evasion - * attempt. With multi payload smtp chunks we can have valid - * cases of fragmentation. But within the same segment chunk - * if we see fragmentation then it's definitely something you - * should alert about */ - if (state->ts_current_line_db == 0) { - state->ts_db = SCMalloc(state->input_len); - if (state->ts_db == NULL) { - return -1; - } - state->ts_current_line_db = 1; - memcpy(state->ts_db, state->input, state->input_len); - state->ts_db_len = state->input_len; - } else { - ptmp = SCRealloc(state->ts_db, - (state->ts_db_len + state->input_len)); - if (ptmp == NULL) { - SCFree(state->ts_db); - state->ts_db = NULL; - state->ts_db_len = 0; - return -1; - } - state->ts_db = ptmp; - - memcpy(state->ts_db + state->ts_db_len, - state->input, state->input_len); - state->ts_db_len += state->input_len; - } /* else */ - state->input += state->input_len; - state->input_len = 0; - - return -1; - - } else { - state->ts_current_line_lf_seen = 1; - - if (state->ts_current_line_db == 1) { - ptmp = SCRealloc(state->ts_db, - (state->ts_db_len + (lf_idx + 1 - state->input))); - if (ptmp == NULL) { - SCFree(state->ts_db); - state->ts_db = NULL; - state->ts_db_len = 0; - return -1; - } - state->ts_db = ptmp; - - memcpy(state->ts_db + state->ts_db_len, - state->input, (lf_idx + 1 - state->input)); - state->ts_db_len += (lf_idx + 1 - state->input); - - if (state->ts_db_len > 1 && - state->ts_db[state->ts_db_len - 2] == 0x0D) { - state->ts_db_len -= 2; - state->current_line_delimiter_len = 2; - } else { - state->ts_db_len -= 1; - state->current_line_delimiter_len = 1; - } - - state->current_line = state->ts_db; - state->current_line_len = state->ts_db_len; - - } else { - state->current_line = state->input; - state->current_line_len = lf_idx - state->input; - - if (state->input != lf_idx && - *(lf_idx - 1) == 0x0D) { - state->current_line_len--; - state->current_line_delimiter_len = 2; - } else { - state->current_line_delimiter_len = 1; - } - } - - state->input_len -= (lf_idx - state->input) + 1; - state->input = (lf_idx + 1); - - return 0; - } - - /* toclient */ - } else { - if (state->tc_current_line_lf_seen == 1) { - /* we have seen the lf for the previous line. Clear the parser - * details to parse new line */ - state->tc_current_line_lf_seen = 0; - if (state->tc_current_line_db == 1) { - state->tc_current_line_db = 0; - SCFree(state->tc_db); - state->tc_db = NULL; - state->tc_db_len = 0; - state->current_line = NULL; - state->current_line_len = 0; - } - } - - uint8_t *lf_idx = memchr(state->input, 0x0a, state->input_len); - - if (lf_idx == NULL) { - /* fragmented lines. Decoder event for special cases. Not all - * fragmented lines should be treated as a possible evasion - * attempt. With multi payload smtp chunks we can have valid - * cases of fragmentation. But within the same segment chunk - * if we see fragmentation then it's definitely something you - * should alert about */ - if (state->tc_current_line_db == 0) { - state->tc_db = SCMalloc(state->input_len); - if (state->tc_db == NULL) { - return -1; - } - state->tc_current_line_db = 1; - memcpy(state->tc_db, state->input, state->input_len); - state->tc_db_len = state->input_len; - } else { - ptmp = SCRealloc(state->tc_db, - (state->tc_db_len + state->input_len)); - if (ptmp == NULL) { - SCFree(state->tc_db); - state->tc_db = NULL; - state->tc_db_len = 0; - return -1; - } - state->tc_db = ptmp; - - memcpy(state->tc_db + state->tc_db_len, - state->input, state->input_len); - state->tc_db_len += state->input_len; - } /* else */ - state->input += state->input_len; - state->input_len = 0; - - return -1; - - } else { - state->tc_current_line_lf_seen = 1; - - if (state->tc_current_line_db == 1) { - ptmp = SCRealloc(state->tc_db, - (state->tc_db_len + (lf_idx + 1 - state->input))); - if (ptmp == NULL) { - SCFree(state->tc_db); - state->tc_db = NULL; - state->tc_db_len = 0; - return -1; - } - state->tc_db = ptmp; - - memcpy(state->tc_db + state->tc_db_len, - state->input, (lf_idx + 1 - state->input)); - state->tc_db_len += (lf_idx + 1 - state->input); - - if (state->tc_db_len > 1 && - state->tc_db[state->tc_db_len - 2] == 0x0D) { - state->tc_db_len -= 2; - state->current_line_delimiter_len = 2; - } else { - state->tc_db_len -= 1; - state->current_line_delimiter_len = 1; - } - - state->current_line = state->tc_db; - state->current_line_len = state->tc_db_len; - - } else { - state->current_line = state->input; - state->current_line_len = lf_idx - state->input; - - if (state->input != lf_idx && - *(lf_idx - 1) == 0x0D) { - state->current_line_len--; - state->current_line_delimiter_len = 2; - } else { - state->current_line_delimiter_len = 1; - } - } - - state->input_len -= (lf_idx - state->input) + 1; - state->input = (lf_idx + 1); - - return 0; - } /* else - if (lf_idx == NULL) */ - } - -} - -static int SMTPInsertCommandIntoCommandBuffer(uint8_t command, SMTPState *state, Flow *f) -{ - SCEnter(); - void *ptmp; - - if (state->cmds_cnt >= state->cmds_buffer_len) { - int increment = SMTP_COMMAND_BUFFER_STEPS; - if ((int)(state->cmds_buffer_len + SMTP_COMMAND_BUFFER_STEPS) > (int)USHRT_MAX) { - increment = USHRT_MAX - state->cmds_buffer_len; - } - - ptmp = SCRealloc(state->cmds, - sizeof(uint8_t) * (state->cmds_buffer_len + increment)); - if (ptmp == NULL) { - SCFree(state->cmds); - state->cmds = NULL; - SCLogDebug("SCRealloc failure"); - return -1; - } - state->cmds = ptmp; - - state->cmds_buffer_len += increment; - } - if (state->cmds_cnt >= 1 && - ((state->cmds[state->cmds_cnt - 1] == SMTP_COMMAND_STARTTLS) || - (state->cmds[state->cmds_cnt - 1] == SMTP_COMMAND_DATA))) { - /* decoder event */ - SMTPSetEvent(state, SMTP_DECODER_EVENT_INVALID_PIPELINED_SEQUENCE); - /* we have to have EHLO, DATA, VRFY, EXPN, TURN, QUIT, NOOP, - * STARTTLS as the last command in pipelined mode */ - } - - /** \todo decoder event */ - if ((int)(state->cmds_cnt + 1) > (int)USHRT_MAX) { - SCLogDebug("command buffer overflow"); - return -1; - } - - state->cmds[state->cmds_cnt] = command; - state->cmds_cnt++; - - return 0; -} - -static int SMTPProcessCommandBDAT(SMTPState *state, Flow *f, - AppLayerParserState *pstate) -{ - SCEnter(); - - state->bdat_chunk_idx += (state->current_line_len + - state->current_line_delimiter_len); - if (state->bdat_chunk_idx > state->bdat_chunk_len) { - state->parser_state &= ~SMTP_PARSER_STATE_COMMAND_DATA_MODE; - /* decoder event */ - SMTPSetEvent(state, SMTP_DECODER_EVENT_BDAT_CHUNK_LEN_EXCEEDED); - SCReturnInt(-1); - } else if (state->bdat_chunk_idx == state->bdat_chunk_len) { - state->parser_state &= ~SMTP_PARSER_STATE_COMMAND_DATA_MODE; - } - - SCReturnInt(0); -} - -static int SMTPProcessCommandDATA(SMTPState *state, Flow *f, - AppLayerParserState *pstate) -{ - SCEnter(); - - if (!(state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - /* looks like are still waiting for a confirmination from the server */ - return 0; - } - - if (state->current_line_len == 1 && state->current_line[0] == '.') { - state->parser_state &= ~SMTP_PARSER_STATE_COMMAND_DATA_MODE; - /* kinda like a hack. The mail sent in DATA mode, would be - * acknowledged with a reply. We insert a dummy command to - * the command buffer to be used by the reply handler to match - * the reply received */ - SMTPInsertCommandIntoCommandBuffer(SMTP_COMMAND_DATA_MODE, state, f); - - if (smtp_config.decode_mime) { - /* Complete parsing task */ - int ret = MimeDecParseComplete(state->curr_tx->mime_state); - if (ret != MIME_DEC_OK) { - - SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_PARSE_FAILED); - SCLogDebug("MimeDecParseComplete() function failed"); - } - - /* Generate decoder events */ - MimeDecEntity *msg = state->curr_tx->mime_state->msg; - if (msg->anomaly_flags & ANOM_INVALID_BASE64) { - SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_INVALID_BASE64); - } - if (msg->anomaly_flags & ANOM_INVALID_QP) { - SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_INVALID_QP); - } - if (msg->anomaly_flags & ANOM_LONG_LINE) { - SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_LONG_LINE); - } - if (msg->anomaly_flags & ANOM_LONG_ENC_LINE) { - SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_LONG_ENC_LINE); - } - if (msg->anomaly_flags & ANOM_LONG_HEADER_NAME) { - SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_LONG_HEADER_NAME); - } - if (msg->anomaly_flags & ANOM_LONG_HEADER_VALUE) { - SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_LONG_HEADER_VALUE); - } - if (msg->anomaly_flags & ANOM_MALFORMED_MSG) { - SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_MALFORMED_MSG); - } - if (msg->anomaly_flags & ANOM_LONG_BOUNDARY) { - SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_BOUNDARY_TOO_LONG); - } - } - state->curr_tx->done = 1; - SCLogDebug("marked tx as done"); - } - - /* If DATA, then parse out a MIME message */ - if (state->current_command == SMTP_COMMAND_DATA && - (state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - - if (smtp_config.decode_mime && state->curr_tx->mime_state) { - int ret = MimeDecParseLine((const uint8_t *) state->current_line, - 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); - } - } - } - - return 0; -} - -static int SMTPProcessCommandSTARTTLS(SMTPState *state, Flow *f, - AppLayerParserState *pstate) -{ - return 0; -} - -static int SMTPProcessReply(SMTPState *state, Flow *f, - AppLayerParserState *pstate) -{ - SCEnter(); - - uint64_t reply_code = 0; - PatternMatcherQueue *pmq = state->thread_local_data; - - /* the reply code has to contain at least 3 bytes, to hold the 3 digit - * reply code */ - if (state->current_line_len < 3) { - /* decoder event */ - SMTPSetEvent(state, SMTP_DECODER_EVENT_INVALID_REPLY); - return -1; - } - - if (state->current_line_len >= 4) { - if (state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY) { - if (state->current_line[3] != '-') { - state->parser_state &= ~SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY; - } - } else { - if (state->current_line[3] == '-') { - state->parser_state |= SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY; - } - } - } else { - if (state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY) { - state->parser_state &= ~SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY; - } - } - - /* I don't like this pmq reset here. We'll devise a method later, that - * should make the use of the mpm very efficient */ - PmqReset(pmq); - int mpm_cnt = mpm_table[SMTP_MPM].Search(smtp_mpm_ctx, smtp_mpm_thread_ctx, - pmq, state->current_line, - 3); - if (mpm_cnt == 0) { - /* set decoder event - reply code invalid */ - SMTPSetEvent(state, SMTP_DECODER_EVENT_INVALID_REPLY); - SCLogDebug("invalid reply code %02x %02x %02x", - state->current_line[0], state->current_line[1], state->current_line[2]); - SCReturnInt(-1); - } - reply_code = smtp_reply_map[pmq->pattern_id_array[0]].enum_value; - - if (state->cmds_idx == state->cmds_cnt) { - if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - /* the first server reply can be a multiline message. Let's - * flag the fact that we have seen the first reply only at the end - * of a multiline reply - */ - if (!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) - state->parser_state |= SMTP_PARSER_STATE_FIRST_REPLY_SEEN; - if (reply_code == SMTP_REPLY_220) - SCReturnInt(0); - else - SMTPSetEvent(state, SMTP_DECODER_EVENT_INVALID_REPLY); - } else { - /* decoder event - unable to match reply with request */ - SCLogDebug("unable to match reply with request"); - SCReturnInt(-1); - } - } - - if (state->cmds_cnt == 0) { - /* reply but not a command we have stored, fall through */ - } else if (state->cmds[state->cmds_idx] == SMTP_COMMAND_STARTTLS) { - if (reply_code == SMTP_REPLY_220) { - /* we are entering STARRTTLS data mode */ - state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE; - AppLayerParserStateSetFlag(pstate, - APP_LAYER_PARSER_NO_INSPECTION | - APP_LAYER_PARSER_NO_REASSEMBLY); - } else { - /* decoder event */ - SMTPSetEvent(state, SMTP_DECODER_EVENT_TLS_REJECTED); - } - } else if (state->cmds[state->cmds_idx] == SMTP_COMMAND_DATA) { - if (reply_code == SMTP_REPLY_354) { - /* Next comes the mail for the DATA command in toserver direction */ - state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE; - } else { - /* decoder event */ - SMTPSetEvent(state, SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED); - } - } else { - /* we don't care for any other command for now */ - /* check if reply falls in the valid list of replies for SMTP. If not - * decoder event */ - } - - /* if it is a multi-line reply, we need to move the index only once for all - * the line of the reply. We unset the multiline flag on the last - * line of the multiline reply, following which we increment the index */ - if (!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) { - state->cmds_idx++; - } - - /* if we have matched all the buffered commands, reset the cnt and index */ - if (state->cmds_idx == state->cmds_cnt) { - state->cmds_cnt = 0; - state->cmds_idx = 0; - } - - return 0; -} - -static int SMTPParseCommandBDAT(SMTPState *state) -{ - SCEnter(); - - int i = 4; - while (i < state->current_line_len) { - if (state->current_line[i] != ' ') { - break; - } - i++; - } - if (i == 4) { - /* decoder event */ - return -1; - } - if (i == state->current_line_len) { - /* decoder event */ - return -1; - } - char *endptr = NULL; - state->bdat_chunk_len = strtoul((const char *)state->current_line + i, - (char **)&endptr, 10); - if ((uint8_t *)endptr == state->current_line + i) { - /* decoder event */ - return -1; - } - - 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) -{ - if (!(state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - if (state->current_line_len >= 4 && - SCMemcmpLowercase("rset", state->current_line, 4) == 0) { - return 1; - } else if (state->current_line_len >= 4 && - SCMemcmpLowercase("quit", state->current_line, 4) == 0) { - return 1; - } - } - return 0; -} - -static int SMTPProcessRequest(SMTPState *state, Flow *f, - AppLayerParserState *pstate) -{ - SCEnter(); - SMTPTransaction *tx = state->curr_tx; - - if (state->curr_tx == NULL || (state->curr_tx->done && !NoNewTx(state))) { - tx = SMTPTransactionCreate(); - if (tx == NULL) - return -1; - state->curr_tx = tx; - TAILQ_INSERT_TAIL(&state->tx_list, tx, next); - tx->tx_id = state->tx_cnt++; - } - - if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - SMTPSetEvent(state, SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE); - } - - /* there are 2 commands that can push it into this COMMAND_DATA mode - - * STARTTLS and DATA */ - if (!(state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - int r = 0; - - if (state->current_line_len >= 8 && - SCMemcmpLowercase("starttls", state->current_line, 8) == 0) { - state->current_command = SMTP_COMMAND_STARTTLS; - } else if (state->current_line_len >= 4 && - SCMemcmpLowercase("data", state->current_line, 4) == 0) { - state->current_command = SMTP_COMMAND_DATA; - if (smtp_config.decode_mime) { - tx->mime_state = MimeDecInitParser(f, SMTPProcessDataChunk); - if (tx->mime_state == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, "MimeDecInitParser() failed to " - "allocate data"); - return MIME_DEC_ERR_MEM; - } - - /* Add new MIME message to end of list */ - if (tx->msg_head == NULL) { - tx->msg_head = tx->mime_state->msg; - tx->msg_tail = tx->mime_state->msg; - } - else { - tx->msg_tail->next = tx->mime_state->msg; - tx->msg_tail = tx->mime_state->msg; - } - } - - } else if (state->current_line_len >= 4 && - SCMemcmpLowercase("bdat", state->current_line, 4) == 0) { - r = SMTPParseCommandBDAT(state); - if (r == -1) { - SCReturnInt(-1); - } - 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; - } - - /* Every command is inserted into a command buffer, to be matched - * against reply(ies) sent by the server */ - if (SMTPInsertCommandIntoCommandBuffer(state->current_command, - state, f) == -1) { - SCReturnInt(-1); - } - - SCReturnInt(r); - } - - switch (state->current_command) { - case SMTP_COMMAND_STARTTLS: - return SMTPProcessCommandSTARTTLS(state, f, pstate); - - case SMTP_COMMAND_DATA: - return SMTPProcessCommandDATA(state, f, pstate); - - case SMTP_COMMAND_BDAT: - return SMTPProcessCommandBDAT(state, f, pstate); - - default: - /* we have nothing to do with any other command at this instant. - * Just let it go through */ - SCReturnInt(0); - } -} - -static int SMTPParse(int direction, Flow *f, SMTPState *state, - AppLayerParserState *pstate, uint8_t *input, - uint32_t input_len, - PatternMatcherQueue *local_data) -{ - SCEnter(); - - if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { - SCReturnInt(1); - } else if (input == NULL || input_len == 0) { - SCReturnInt(-1); - } - - state->input = input; - state->input_len = input_len; - state->direction = direction; - state->thread_local_data = local_data; - - /* toserver */ - if (direction == 0) { - while (SMTPGetLine(state) >= 0) { - if (SMTPProcessRequest(state, f, pstate) == -1) - SCReturnInt(-1); - } - - /* toclient */ - } else { - while (SMTPGetLine(state) >= 0) { - if (SMTPProcessReply(state, f, pstate) == -1) - SCReturnInt(-1); - } - } - - SCReturnInt(0); -} - -static int SMTPParseClientRecord(Flow *f, void *alstate, - AppLayerParserState *pstate, - uint8_t *input, uint32_t input_len, - void *local_data) -{ - SCEnter(); - - /* first arg 0 is toserver */ - return SMTPParse(0, f, alstate, pstate, input, input_len, local_data); -} - -static int SMTPParseServerRecord(Flow *f, void *alstate, - AppLayerParserState *pstate, - uint8_t *input, uint32_t input_len, - void *local_data) -{ - SCEnter(); - - /* first arg 1 is toclient */ - return SMTPParse(1, f, alstate, pstate, input, input_len, local_data); - - return 0; -} - -/** - * \internal - * \brief Function to allocate SMTP state memory. - */ -void *SMTPStateAlloc(void) -{ - SMTPState *smtp_state = SCMalloc(sizeof(SMTPState)); - if (unlikely(smtp_state == NULL)) - return NULL; - memset(smtp_state, 0, sizeof(SMTPState)); - - smtp_state->cmds = SCMalloc(sizeof(uint8_t) * - SMTP_COMMAND_BUFFER_STEPS); - if (smtp_state->cmds == NULL) { - SCFree(smtp_state); - return NULL; - } - smtp_state->cmds_buffer_len = SMTP_COMMAND_BUFFER_STEPS; - - TAILQ_INIT(&smtp_state->tx_list); - - 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 */ - PatternMatcherQueue *pmq = SCMalloc(sizeof(PatternMatcherQueue)); - if (unlikely(pmq == NULL)) { - exit(EXIT_FAILURE); - } - PmqSetup(pmq, - sizeof(smtp_reply_map)/sizeof(SCEnumCharMap) - 2); - - return pmq; -} - -static void SMTPLocalStorageFree(void *pmq) -{ - if (pmq != NULL) { - PmqFree(pmq); - SCFree(pmq); - } - - return; -} - -static void SMTPTransactionFree(SMTPTransaction *tx, SMTPState *state) -{ - if (tx->mime_state != NULL) { - MimeDecDeInitParser(tx->mime_state); - } - /* Free list of MIME message recursively */ - MimeDecFreeEntity(tx->msg_head); - - if (tx->decoder_events != NULL) - AppLayerDecoderEventsFreeEvents(&tx->decoder_events); - - 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; - else - smtp_state->events = 0; -#endif - SCFree(tx); -} - -/** - * \internal - * \brief Function to free SMTP state memory. - */ -static void SMTPStateFree(void *p) -{ - SMTPState *smtp_state = (SMTPState *)p; - - if (smtp_state->cmds != NULL) { - SCFree(smtp_state->cmds); - } - if (smtp_state->ts_current_line_db) { - SCFree(smtp_state->ts_db); - } - if (smtp_state->tc_current_line_db) { - SCFree(smtp_state->tc_db); - } - - if (smtp_state->helo) { - SCFree(smtp_state->helo); - } - - FileContainerFree(smtp_state->files_ts); - - SMTPTransaction *tx = NULL; - while ((tx = TAILQ_FIRST(&smtp_state->tx_list))) { - TAILQ_REMOVE(&smtp_state->tx_list, tx, next); - SMTPTransactionFree(tx, smtp_state); - } - - SCFree(smtp_state); - - return; -} - -static void SMTPSetMpmState(void) -{ - smtp_mpm_ctx = SCMalloc(sizeof(MpmCtx)); - if (unlikely(smtp_mpm_ctx == NULL)) { - exit(EXIT_FAILURE); - } - memset(smtp_mpm_ctx, 0, sizeof(MpmCtx)); - MpmInitCtx(smtp_mpm_ctx, SMTP_MPM); - - smtp_mpm_thread_ctx = SCMalloc(sizeof(MpmThreadCtx)); - if (unlikely(smtp_mpm_thread_ctx == NULL)) { - exit(EXIT_FAILURE); - } - memset(smtp_mpm_thread_ctx, 0, sizeof(MpmThreadCtx)); - MpmInitThreadCtx(smtp_mpm_thread_ctx, SMTP_MPM, 0); - - uint32_t i = 0; - for (i = 0; i < sizeof(smtp_reply_map)/sizeof(SCEnumCharMap) - 1; i++) { - SCEnumCharMap *map = &smtp_reply_map[i]; - /* The third argument is 3, because reply code is always 3 bytes. */ - MpmAddPatternCI(smtp_mpm_ctx, (uint8_t *)map->enum_name, 3, - 0 /* defunct */, 0 /* defunct */, - i /* pattern id */, 0, 0 /* no flags */); - } - - mpm_table[SMTP_MPM].Prepare(smtp_mpm_ctx); -} - -int SMTPStateGetEventInfo(const char *event_name, - int *event_id, AppLayerEventType *event_type) -{ - *event_id = SCMapEnumNameToValue(event_name, smtp_decoder_event_table); - if (*event_id == -1) { - SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in " - "smtp's enum map table.", event_name); - /* yes this is fatal */ - return -1; - } - - *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION; - - return 0; -} - -static int SMTPRegisterPatternsForProtocolDetection(void) -{ - if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMTP, - "EHLO", 4, 0, STREAM_TOSERVER) < 0) - { - return -1; - } - if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMTP, - "HELO", 4, 0, STREAM_TOSERVER) < 0) - { - return -1; - } - if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMTP, - "QUIT", 4, 0, STREAM_TOSERVER) < 0) - { - return -1; - } - - return 0; -} - -static void SMTPStateTransactionFree (void *state, uint64_t tx_id) -{ - SMTPState *smtp_state = state; - SMTPTransaction *tx = NULL; - TAILQ_FOREACH(tx, &smtp_state->tx_list, next) { - if (tx_id < tx->tx_id) - break; - else if (tx_id > tx->tx_id) - continue; - - if (tx == smtp_state->curr_tx) - smtp_state->curr_tx = NULL; - TAILQ_REMOVE(&smtp_state->tx_list, tx, next); - SMTPTransactionFree(tx, state); - break; - } - - -} - -/** \retval cnt highest tx id */ -static uint64_t SMTPStateGetTxCnt(void *state) -{ - uint64_t cnt = 0; - SMTPState *smtp_state = state; - if (smtp_state) { - cnt = smtp_state->tx_cnt; - } - SCLogDebug("returning %"PRIu64, cnt); - return cnt; -} - -static void *SMTPStateGetTx(void *state, uint64_t id) -{ - SMTPState *smtp_state = state; - if (smtp_state) { - SMTPTransaction *tx = NULL; - - if (smtp_state->curr_tx == NULL) - return NULL; - if (smtp_state->curr_tx->tx_id == id) - return smtp_state->curr_tx; - - TAILQ_FOREACH(tx, &smtp_state->tx_list, next) { - if (tx->tx_id == id) - return tx; - } - } - return NULL; - -} - -static int SMTPStateGetAlstateProgressCompletionStatus(uint8_t direction) { - return 1; -} - -static int SMTPStateGetAlstateProgress(void *vtx, uint8_t direction) -{ - SMTPTransaction *tx = vtx; - return tx->done; -} - -static FileContainer *SMTPStateGetFiles(void *state, uint8_t direction) -{ - if (state == NULL) - return NULL; - - SMTPState *smtp_state = (SMTPState *)state; - - if (direction & STREAM_TOCLIENT) { - SCReturnPtr(NULL, "FileContainer"); - } else { - SCLogDebug("smtp_state->files_ts %p", smtp_state->files_ts); - SCReturnPtr(smtp_state->files_ts, "FileContainer"); - } -} - -static void SMTPStateTruncate(void *state, uint8_t direction) -{ - FileContainer *fc = SMTPStateGetFiles(state, direction); - if (fc != NULL) { - SCLogDebug("truncating stream, closing files in %s direction (container %p)", - direction & STREAM_TOCLIENT ? "STREAM_TOCLIENT" : "STREAM_TOSERVER", fc); - FileTruncateAllOpenFiles(fc); - } -} - -static AppLayerDecoderEvents *SMTPGetEvents(void *state, uint64_t tx_id) -{ - SCLogDebug("get SMTP events for TX %"PRIu64, tx_id); - - SMTPTransaction *tx = SMTPStateGetTx(state, tx_id); - if (tx != NULL) { - return tx->decoder_events; - } - return NULL; -} - -static DetectEngineState *SMTPGetTxDetectState(void *vtx) -{ - SMTPTransaction *tx = (SMTPTransaction *)vtx; - return tx->de_state; -} - -static int SMTPSetTxDetectState(void *state, void *vtx, DetectEngineState *s) -{ - SMTPTransaction *tx = (SMTPTransaction *)vtx; - tx->de_state = s; - return 0; -} - -/** - * \brief Register the SMTP Protocol parser. - */ -void RegisterSMTPParsers(void) -{ - char *proto_name = "smtp"; - - if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) { - AppLayerProtoDetectRegisterProtocol(ALPROTO_SMTP, proto_name); - if (SMTPRegisterPatternsForProtocolDetection() < 0 ) - return; - } else { - SCLogInfo("Protocol detection and parser disabled for %s protocol.", - proto_name); - return; - } - - if (AppLayerParserConfParserEnabled("tcp", proto_name)) { - AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateAlloc, SMTPStateFree); - - AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMTP, STREAM_TOSERVER, - SMTPParseClientRecord); - AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMTP, STREAM_TOCLIENT, - SMTPParseServerRecord); - - AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetEventInfo); - AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPGetEvents); - AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_SMTP, NULL, - SMTPGetTxDetectState, SMTPSetTxDetectState); - - AppLayerParserRegisterLocalStorageFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPLocalStorageAlloc, - SMTPLocalStorageFree); - - AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateTransactionFree); - AppLayerParserRegisterGetFilesFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetFiles); - AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetAlstateProgress); - AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetTxCnt); - AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetTx); - AppLayerParserRegisterGetStateProgressCompletionStatus(IPPROTO_TCP, ALPROTO_SMTP, - SMTPStateGetAlstateProgressCompletionStatus); - AppLayerParserRegisterTruncateFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateTruncate); - } else { - SCLogInfo("Parsed disabled for %s protocol. Protocol detection" - "still on.", proto_name); - } - - SMTPSetMpmState(); - - SMTPConfigure(); - -#ifdef UNITTESTS - AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_SMTP, SMTPParserRegisterTests); -#endif - return; -} - -/***************************************Unittests******************************/ - -#ifdef UNITTESTS - -/* - * \test Test STARTTLS. - */ -int SMTPParserTest01(void) -{ - int result = 0; - Flow f; - int r = 0; - - /* 220 mx.google.com ESMTP d15sm986283wfl.6<CR><LF> */ - uint8_t welcome_reply[] = { - 0x32, 0x32, 0x30, 0x20, 0x6d, 0x78, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x20, 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, - 0x64, 0x31, 0x35, 0x73, 0x6d, 0x39, 0x38, 0x36, - 0x32, 0x38, 0x33, 0x77, 0x66, 0x6c, 0x2e, 0x36, - 0x0d, 0x0a - }; - uint32_t welcome_reply_len = sizeof(welcome_reply); - - /* EHLO [192.168.0.158]<CR><LF> */ - uint8_t request1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x5b, 0x31, 0x39, - 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x30, 0x2e, - 0x31, 0x35, 0x38, 0x5d, 0x0d, 0x0a - }; - uint32_t request1_len = sizeof(request1); - /* 250-mx.google.com at your service, [117.198.115.50]<CR><LF> - * 250-SIZE 35882577<CR><LF> - * 250-8BITMIME<CR><LF> - * 250-STARTTLS<CR><LF> - * 250 ENHANCEDSTATUSCODES<CR><LF> - */ - uint8_t reply1[] = { - 0x32, 0x35, 0x30, 0x2d, 0x6d, 0x78, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x20, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, - 0x72, 0x20, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2c, 0x20, 0x5b, 0x31, 0x31, 0x37, 0x2e, - 0x31, 0x39, 0x38, 0x2e, 0x31, 0x31, 0x35, 0x2e, - 0x35, 0x30, 0x5d, 0x0d, 0x0a, 0x32, 0x35, 0x30, - 0x2d, 0x53, 0x49, 0x5a, 0x45, 0x20, 0x33, 0x35, - 0x38, 0x38, 0x32, 0x35, 0x37, 0x37, 0x0d, 0x0a, - 0x32, 0x35, 0x30, 0x2d, 0x38, 0x42, 0x49, 0x54, - 0x4d, 0x49, 0x4d, 0x45, 0x0d, 0x0a, 0x32, 0x35, - 0x30, 0x2d, 0x53, 0x54, 0x41, 0x52, 0x54, 0x54, - 0x4c, 0x53, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x20, - 0x45, 0x4e, 0x48, 0x41, 0x4e, 0x43, 0x45, 0x44, - 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x43, 0x4f, - 0x44, 0x45, 0x53, 0x0d, 0x0a - }; - uint32_t reply1_len = sizeof(reply1); - - /* STARTTLS<CR><LF> */ - uint8_t request2[] = { - 0x53, 0x54, 0x41, 0x52, 0x54, 0x54, 0x4c, 0x53, - 0x0d, 0x0a - }; - uint32_t request2_len = sizeof(request2); - /* 220 2.0.0 Ready to start TLS<CR><LF> */ - uint8_t reply2[] = { - 0x32, 0x32, 0x30, 0x20, 0x32, 0x2e, 0x30, 0x2e, - 0x30, 0x20, 0x52, 0x65, 0x61, 0x64, 0x79, 0x20, - 0x74, 0x6f, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x20, 0x54, 0x4c, 0x53, 0x0d, 0x0a - }; - uint32_t reply2_len = sizeof(reply2); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply1, reply1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_STARTTLS || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply2, reply2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - if (!(f.flags & FLOW_NOPAYLOAD_INSPECTION) || - !(ssn.flags & STREAMTCP_FLAG_APP_LAYER_DISABLED) || - !(((TcpSession *)f.protoctx)->server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) || - !(((TcpSession *)f.protoctx)->client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) { - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -/** - * \test Test multiple DATA commands(full mail transactions). - */ -int SMTPParserTest02(void) -{ - int result = 0; - Flow f; - int r = 0; - - /* 220 mx.google.com ESMTP d15sm986283wfl.6<CR><LF> */ - uint8_t welcome_reply[] = { - 0x32, 0x32, 0x30, 0x20, 0x6d, 0x78, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x20, 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, - 0x64, 0x31, 0x35, 0x73, 0x6d, 0x39, 0x38, 0x36, - 0x32, 0x38, 0x33, 0x77, 0x66, 0x6c, 0x2e, 0x36, - 0x0d, 0x0a - }; - uint32_t welcome_reply_len = sizeof(welcome_reply); - - /* EHLO boo.com<CR><LF> */ - uint8_t request1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a - }; - uint32_t request1_len = sizeof(request1); - /* 250-mx.google.com at your service, [117.198.115.50]<CR><LF> - * 250-SIZE 35882577<CR><LF> - * 250-8BITMIME<CR><LF> - * 250-STARTTLS<CR><LF> - * 250 ENHANCEDSTATUSCODES<CR><LF> - */ - uint8_t reply1[] = { - 0x32, 0x35, 0x30, 0x2d, 0x70, 0x6f, 0x6f, 0x6e, - 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f, - 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x50, 0x49, 0x50, - 0x45, 0x4c, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x53, 0x49, 0x5a, - 0x45, 0x20, 0x31, 0x30, 0x32, 0x34, 0x30, 0x30, - 0x30, 0x30, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, - 0x56, 0x52, 0x46, 0x59, 0x0d, 0x0a, 0x32, 0x35, - 0x30, 0x2d, 0x45, 0x54, 0x52, 0x4e, 0x0d, 0x0a, - 0x32, 0x35, 0x30, 0x2d, 0x45, 0x4e, 0x48, 0x41, - 0x4e, 0x43, 0x45, 0x44, 0x53, 0x54, 0x41, 0x54, - 0x55, 0x53, 0x43, 0x4f, 0x44, 0x45, 0x53, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x38, 0x42, 0x49, - 0x54, 0x4d, 0x49, 0x4d, 0x45, 0x0d, 0x0a, 0x32, - 0x35, 0x30, 0x20, 0x44, 0x53, 0x4e, 0x0d, 0x0a - }; - uint32_t reply1_len = sizeof(reply1); - - /* MAIL FROM:asdff@asdf.com<CR><LF> */ - uint8_t request2[] = { - 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, - 0x4d, 0x3a, 0x61, 0x73, 0x64, 0x66, 0x66, 0x40, - 0x61, 0x73, 0x64, 0x66, 0x2e, 0x63, 0x6f, 0x6d, - 0x0d, 0x0a - }; - uint32_t request2_len = sizeof(request2); - /* 250 2.1.0 Ok<CR><LF> */ - uint8_t reply2[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, - 0x30, 0x20, 0x4f, 0x6b, 0x0d, 0x0a - }; - uint32_t reply2_len = sizeof(reply2); - - /* RCPT TO:bimbs@gmail.com<CR><LF> */ - uint8_t request3[] = { - 0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a, - 0x62, 0x69, 0x6d, 0x62, 0x73, 0x40, 0x67, 0x6d, - 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x0d, - 0x0a - }; - uint32_t request3_len = sizeof(request3); - /* 250 2.1.5 Ok<CR><LF> */ - uint8_t reply3[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, - 0x35, 0x20, 0x4f, 0x6b, 0x0d, 0x0a - }; - uint32_t reply3_len = sizeof(reply3); - - /* DATA<CR><LF> */ - uint8_t request4[] = { - 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a - }; - uint32_t request4_len = sizeof(request4); - /* 354 End data with <CR><LF>.<CR><LF>|<CR><LF>| */ - uint8_t reply4[] = { - 0x33, 0x35, 0x34, 0x20, 0x45, 0x6e, 0x64, 0x20, - 0x64, 0x61, 0x74, 0x61, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x20, 0x3c, 0x43, 0x52, 0x3e, 0x3c, 0x4c, - 0x46, 0x3e, 0x2e, 0x3c, 0x43, 0x52, 0x3e, 0x3c, - 0x4c, 0x46, 0x3e, 0x0d, 0x0a - }; - uint32_t reply4_len = sizeof(reply4); - - /* FROM:asdff@asdf.com<CR><LF> */ - uint8_t request5_1[] = { - 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x61, 0x73, 0x64, - 0x66, 0x66, 0x40, 0x61, 0x73, 0x64, 0x66, 0x2e, - 0x63, 0x6f, 0x6d, 0x0d, 0x0a - }; - uint32_t request5_1_len = sizeof(request5_1); - /* TO:bimbs@gmail.com<CR><LF> */ - uint8_t request5_2[] = { - 0x54, 0x4f, 0x3a, 0x62, 0x69, 0x6d, 0x62, 0x73, - 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63, - 0x6f, 0x6d, 0x0d, 0x0a - }; - uint32_t request5_2_len = sizeof(request5_2); - /* <CR><LF> */ - uint8_t request5_3[] = { - 0x0d, 0x0a - }; - uint32_t request5_3_len = sizeof(request5_3); - /* this is test mail1<CR><LF> */ - uint8_t request5_4[] = { - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, - 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x61, 0x69, - 0x6c, 0x31, 0x0d, 0x0a - }; - uint32_t request5_4_len = sizeof(request5_4); - /* .<CR><LF> */ - uint8_t request5_5[] = { - 0x2e, 0x0d, 0x0a - }; - uint32_t request5_5_len = sizeof(request5_5); - /* 250 2.0.0 Ok: queued as 6A1AF20BF2<CR><LF> */ - uint8_t reply5[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x30, 0x2e, - 0x30, 0x20, 0x4f, 0x6b, 0x3a, 0x20, 0x71, 0x75, - 0x65, 0x75, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, - 0x36, 0x41, 0x31, 0x41, 0x46, 0x32, 0x30, 0x42, - 0x46, 0x32, 0x0d, 0x0a - }; - uint32_t reply5_len = sizeof(reply5); - - /* MAIL FROM:asdfg@asdf.com<CR><LF> */ - uint8_t request6[] = { - 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, - 0x4d, 0x3a, 0x61, 0x73, 0x64, 0x66, 0x67, 0x40, - 0x61, 0x73, 0x64, 0x66, 0x2e, 0x63, 0x6f, 0x6d, - 0x0d, 0x0a - }; - uint32_t request6_len = sizeof(request6); - /* 250 2.1.0 Ok<CR><LF> */ - uint8_t reply6[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, - 0x30, 0x20, 0x4f, 0x6b, 0x0d, 0x0a - }; - uint32_t reply6_len = sizeof(reply6); - - /* RCPT TO:bimbs@gmail.com<CR><LF> */ - uint8_t request7[] = { - 0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a, - 0x62, 0x69, 0x6d, 0x62, 0x73, 0x40, 0x67, 0x6d, - 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x0d, - 0x0a - }; - uint32_t request7_len = sizeof(request7); - /* 250 2.1.5 Ok<CR><LF> */ - uint8_t reply7[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, - 0x35, 0x20, 0x4f, 0x6b, 0x0d, 0x0a - }; - uint32_t reply7_len = sizeof(reply7); - - /* DATA<CR><LF> */ - uint8_t request8[] = { - 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a - }; - uint32_t request8_len = sizeof(request8); - /* 354 End data with <CR><LF>.<CR><LF>|<CR><LF>| */ - uint8_t reply8[] = { - 0x33, 0x35, 0x34, 0x20, 0x45, 0x6e, 0x64, 0x20, - 0x64, 0x61, 0x74, 0x61, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x20, 0x3c, 0x43, 0x52, 0x3e, 0x3c, 0x4c, - 0x46, 0x3e, 0x2e, 0x3c, 0x43, 0x52, 0x3e, 0x3c, - 0x4c, 0x46, 0x3e, 0x0d, 0x0a - }; - uint32_t reply8_len = sizeof(reply8); - - /* FROM:asdfg@gmail.com<CR><LF> */ - uint8_t request9_1[] = { - 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x61, 0x73, 0x64, - 0x66, 0x67, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a - }; - uint32_t request9_1_len = sizeof(request9_1); - /* TO:bimbs@gmail.com<CR><LF> */ - uint8_t request9_2[] = { - 0x54, 0x4f, 0x3a, 0x62, 0x69, 0x6d, 0x62, 0x73, - 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63, - 0x6f, 0x6d, 0x0d, 0x0a - }; - uint32_t request9_2_len = sizeof(request9_2); - /* <CR><LF> */ - uint8_t request9_3[] = { - 0x0d, 0x0a - }; - uint32_t request9_3_len = sizeof(request9_3); - /* this is test mail2<CR><LF> */ - uint8_t request9_4[] = { - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, - 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x61, 0x69, - 0x6c, 0x32, 0x0d, 0x0a - }; - uint32_t request9_4_len = sizeof(request9_4); - /* .<CR><LF> */ - uint8_t request9_5[] = { - 0x2e, 0x0d, 0x0a - }; - uint32_t request9_5_len = sizeof(request9_5); - /* 250 2.0.0 Ok: queued as 28CFF20BF2<CR><LF> */ - uint8_t reply9[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x30, 0x2e, - 0x30, 0x20, 0x4f, 0x6b, 0x3a, 0x20, 0x71, 0x75, - 0x65, 0x75, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, - 0x32, 0x38, 0x43, 0x46, 0x46, 0x32, 0x30, 0x42, - 0x46, 0x32, 0x0d, 0x0a - }; - uint32_t reply9_len = sizeof(reply9); - - /* QUIT<CR><LF> */ - uint8_t request10[] = { - 0x51, 0x55, 0x49, 0x54, 0x0d, 0x0a - }; - uint32_t request10_len = sizeof(request10); - /* 221 2.0.0 Bye<CR><LF> */ - uint8_t reply10[] = { - 0x32, 0x32, 0x31, 0x20, 0x32, 0x2e, 0x30, 0x2e, - 0x30, 0x20, 0x42, 0x79, 0x65, 0x0d, 0x0a - }; - uint32_t reply10_len = sizeof(reply10); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply1, reply1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply2, reply2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request3, request3_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply3, reply3_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request4, request4_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_DATA || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply4, reply4_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request5_1, request5_1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request5_2, request5_2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request5_3, request5_3_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request5_4, request5_4_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request5_5, request5_5_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_DATA_MODE || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply5, reply5_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request6, request6_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply6, reply6_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request7, request7_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply7, reply7_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request8, request8_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_DATA || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply8, reply8_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request9_1, request9_1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request9_2, request9_2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request9_3, request9_3_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request9_4, request9_4_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request9_5, request9_5_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_DATA_MODE || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply9, reply9_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request10, request10_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply10, reply10_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -/** - * \test Testing parsing pipelined commands. - */ -int SMTPParserTest03(void) -{ - int result = 0; - Flow f; - int r = 0; - - /* 220 poona_slack_vm1.localdomain ESMTP Postfix<CR><LF> */ - uint8_t welcome_reply[] = { - 0x32, 0x32, 0x30, 0x20, 0x70, 0x6f, 0x6f, 0x6e, - 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f, - 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, - 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, 0x50, 0x6f, - 0x73, 0x74, 0x66, 0x69, 0x78, 0x0d, 0x0a - }; - uint32_t welcome_reply_len = sizeof(welcome_reply); - - /* EHLO boo.com<CR><LF> */ - uint8_t request1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0a - }; - uint32_t request1_len = sizeof(request1); - /* 250-poona_slack_vm1.localdomain<CR><LF> - * 250-PIPELINING<CR><LF> - * 250-SIZE 10240000<CR><LF> - * 250-VRFY<CR><LF> - * 250-ETRN<CR><LF> - * 250-ENHANCEDSTATUSCODES<CR><LF> - * 250-8BITMIME<CR><LF> - * 250 DSN<CR><LF> - */ - uint8_t reply1[] = { - 0x32, 0x35, 0x30, 0x2d, 0x70, 0x6f, 0x6f, 0x6e, - 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f, - 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x50, 0x49, 0x50, - 0x45, 0x4c, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x53, 0x49, 0x5a, - 0x45, 0x20, 0x31, 0x30, 0x32, 0x34, 0x30, 0x30, - 0x30, 0x30, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, - 0x56, 0x52, 0x46, 0x59, 0x0d, 0x0a, 0x32, 0x35, - 0x30, 0x2d, 0x45, 0x54, 0x52, 0x4e, 0x0d, 0x0a, - 0x32, 0x35, 0x30, 0x2d, 0x45, 0x4e, 0x48, 0x41, - 0x4e, 0x43, 0x45, 0x44, 0x53, 0x54, 0x41, 0x54, - 0x55, 0x53, 0x43, 0x4f, 0x44, 0x45, 0x53, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x38, 0x42, 0x49, - 0x54, 0x4d, 0x49, 0x4d, 0x45, 0x0d, 0x0a, 0x32, - 0x35, 0x30, 0x20, 0x44, 0x53, 0x4e, 0x0d, 0x0a - }; - uint32_t reply1_len = sizeof(reply1); - - /* MAIL FROM:pbsf@asdfs.com<CR><LF> - * RCPT TO:pbsf@asdfs.com<CR><LF> - * DATA<CR><LF> - */ - uint8_t request2[] = { - 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, - 0x4d, 0x3a, 0x70, 0x62, 0x73, 0x66, 0x40, 0x61, - 0x73, 0x64, 0x66, 0x73, 0x2e, 0x63, 0x6f, 0x6d, - 0x0d, 0x0a, 0x52, 0x43, 0x50, 0x54, 0x20, 0x54, - 0x4f, 0x3a, 0x70, 0x62, 0x73, 0x66, 0x40, 0x61, - 0x73, 0x64, 0x66, 0x73, 0x2e, 0x63, 0x6f, 0x6d, - 0x0d, 0x0a, 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a - }; - uint32_t request2_len = sizeof(request2); - /* 250 2.1.0 Ok<CR><LF> - * 250 2.1.5 Ok<CR><LF> - * 354 End data with <CR><LF>.<CR><LF>|<CR><LF>| - */ - uint8_t reply2[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, - 0x30, 0x20, 0x4f, 0x6b, 0x0d, 0x0a, 0x32, 0x35, - 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, 0x35, 0x20, - 0x4f, 0x6b, 0x0d, 0x0a, 0x33, 0x35, 0x34, 0x20, - 0x45, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x3c, 0x43, - 0x52, 0x3e, 0x3c, 0x4c, 0x46, 0x3e, 0x2e, 0x3c, - 0x43, 0x52, 0x3e, 0x3c, 0x4c, 0x46, 0x3e, 0x0d, - 0x0a - }; - uint32_t reply2_len = sizeof(reply2); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply1, reply1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 3 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->cmds[1] != SMTP_COMMAND_OTHER_CMD || - smtp_state->cmds[2] != SMTP_COMMAND_DATA || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply2, reply2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -/* - * \test Test smtp with just <LF> delimter instead of <CR><LF>. - */ -int SMTPParserTest04(void) -{ - int result = 0; - Flow f; - int r = 0; - - /* 220 poona_slack_vm1.localdomain ESMTP Postfix<CR><LF> */ - uint8_t welcome_reply[] = { - 0x32, 0x32, 0x30, 0x20, 0x70, 0x6f, 0x6f, 0x6e, - 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f, - 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, - 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, 0x50, 0x6f, - 0x73, 0x74, 0x66, 0x69, 0x78, 0x0d, 0x0a - }; - uint32_t welcome_reply_len = sizeof(welcome_reply); - - /* EHLO boo.com<CR><LF> */ - uint8_t request1[] = { - 0x32, 0x32, 0x30, 0x20, 0x70, 0x6f, 0x6f, 0x6e, - 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f, - 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, - 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, 0x50, 0x6f, - 0x73, 0x74, 0x66, 0x69, 0x78, 0x0d, 0x0a - }; - uint32_t request1_len = sizeof(request1); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -/* - * \test Test STARTTLS fail. - */ -int SMTPParserTest05(void) -{ - int result = 0; - Flow f; - int r = 0; - - /* 220 poona_slack_vm1.localdomain ESMTP Postfix<CR><LF> */ - uint8_t welcome_reply[] = { - 0x32, 0x32, 0x30, 0x20, 0x70, 0x6f, 0x6f, 0x6e, - 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f, - 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x20, - 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, 0x50, 0x6f, - 0x73, 0x74, 0x66, 0x69, 0x78, 0x0d, 0x0a - }; - uint32_t welcome_reply_len = sizeof(welcome_reply); - - /* EHLO boo.com<CR><LF> */ - uint8_t request1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a - }; - uint32_t request1_len = sizeof(request1); - /* 250-poona_slack_vm1.localdomain<CR><LF> - * 250-PIPELINING<CR><LF> - * 250-SIZE 10240000<CR><LF> - * 250-VRFY<CR><LF> - * 250-ETRN<CR><LF> - * 250-ENHANCEDSTATUSCODES<CR><LF> - * 250-8BITMIME<CR><LF> - * 250 DSN<CR><LF> - */ - uint8_t reply1[] = { - 0x32, 0x35, 0x30, 0x2d, 0x70, 0x6f, 0x6f, 0x6e, - 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f, - 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x50, 0x49, 0x50, - 0x45, 0x4c, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x53, 0x49, 0x5a, - 0x45, 0x20, 0x31, 0x30, 0x32, 0x34, 0x30, 0x30, - 0x30, 0x30, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, - 0x56, 0x52, 0x46, 0x59, 0x0d, 0x0a, 0x32, 0x35, - 0x30, 0x2d, 0x45, 0x54, 0x52, 0x4e, 0x0d, 0x0a, - 0x32, 0x35, 0x30, 0x2d, 0x45, 0x4e, 0x48, 0x41, - 0x4e, 0x43, 0x45, 0x44, 0x53, 0x54, 0x41, 0x54, - 0x55, 0x53, 0x43, 0x4f, 0x44, 0x45, 0x53, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x38, 0x42, 0x49, - 0x54, 0x4d, 0x49, 0x4d, 0x45, 0x0d, 0x0a, 0x32, - 0x35, 0x30, 0x20, 0x44, 0x53, 0x4e, 0x0d, 0x0a - }; - uint32_t reply1_len = sizeof(reply1); - - /* STARTTLS<CR><LF> */ - uint8_t request2[] = { - 0x53, 0x54, 0x41, 0x52, 0x54, 0x54, 0x4c, 0x53, - 0x0d, 0x0a - }; - uint32_t request2_len = sizeof(request2); - /* 502 5.5.2 Error: command not recognized<CR><LF> */ - uint8_t reply2[] = { - 0x35, 0x30, 0x32, 0x20, 0x35, 0x2e, 0x35, 0x2e, - 0x32, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, - 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x63, - 0x6f, 0x67, 0x6e, 0x69, 0x7a, 0x65, 0x64, 0x0d, - 0x0a - }; - uint32_t reply2_len = sizeof(reply2); - - /* QUIT<CR><LF> */ - uint8_t request3[] = { - 0x51, 0x55, 0x49, 0x54, 0x0d, 0x0a - - }; - uint32_t request3_len = sizeof(request3); - /* 221 2.0.0 Bye<CR><LF> */ - uint8_t reply3[] = { - 0x32, 0x32, 0x31, 0x20, 0x32, 0x2e, 0x30, 0x2e, - 0x30, 0x20, 0x42, 0x79, 0x65, 0x0d, 0x0a - }; - uint32_t reply3_len = sizeof(reply3); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply1, reply1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_STARTTLS || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply2, reply2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - if ((f.flags & FLOW_NOPAYLOAD_INSPECTION) || - (ssn.flags & STREAMTCP_FLAG_APP_LAYER_DISABLED) || - (((TcpSession *)f.protoctx)->server.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY) || - (((TcpSession *)f.protoctx)->client.flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) { - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request3, request3_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply3, reply3_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -/** - * \test Test multiple DATA commands(full mail transactions). - */ -int SMTPParserTest06(void) -{ - int result = 0; - Flow f; - int r = 0; - - uint8_t welcome_reply[] = { - 0x32, 0x32, 0x30, 0x20, 0x62, 0x61, 0x79, 0x30, - 0x2d, 0x6d, 0x63, 0x36, 0x2d, 0x66, 0x31, 0x30, - 0x2e, 0x62, 0x61, 0x79, 0x30, 0x2e, 0x68, 0x6f, - 0x74, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, - 0x6d, 0x20, 0x53, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x20, 0x75, 0x6e, 0x73, 0x6f, 0x6c, 0x69, - 0x63, 0x69, 0x74, 0x65, 0x64, 0x20, 0x63, 0x6f, - 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6c, - 0x20, 0x6f, 0x72, 0x20, 0x62, 0x75, 0x6c, 0x6b, - 0x20, 0x65, 0x2d, 0x6d, 0x61, 0x69, 0x6c, 0x20, - 0x74, 0x6f, 0x20, 0x4d, 0x69, 0x63, 0x72, 0x6f, - 0x73, 0x6f, 0x66, 0x74, 0x27, 0x73, 0x20, 0x63, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x20, - 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, - 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x68, 0x69, - 0x62, 0x69, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x4f, - 0x74, 0x68, 0x65, 0x72, 0x20, 0x72, 0x65, 0x73, - 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x66, 0x6f, - 0x75, 0x6e, 0x64, 0x20, 0x61, 0x74, 0x20, 0x68, - 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x72, - 0x69, 0x76, 0x61, 0x63, 0x79, 0x2e, 0x6d, 0x73, - 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x6e, - 0x74, 0x69, 0x2d, 0x73, 0x70, 0x61, 0x6d, 0x2f, - 0x2e, 0x20, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x6c, - 0x6c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x20, 0x69, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x20, - 0x6f, 0x66, 0x20, 0x65, 0x71, 0x75, 0x69, 0x70, - 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, - 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, - 0x69, 0x61, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, - 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x73, 0x2e, 0x20, 0x46, 0x72, 0x69, - 0x2c, 0x20, 0x31, 0x36, 0x20, 0x46, 0x65, 0x62, - 0x20, 0x32, 0x30, 0x30, 0x37, 0x20, 0x30, 0x35, - 0x3a, 0x30, 0x33, 0x3a, 0x32, 0x33, 0x20, 0x2d, - 0x30, 0x38, 0x30, 0x30, 0x20, 0x0d, 0x0a - }; - uint32_t welcome_reply_len = sizeof(welcome_reply); - - uint8_t request1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x45, 0x58, 0x43, - 0x48, 0x41, 0x4e, 0x47, 0x45, 0x32, 0x2e, 0x63, - 0x67, 0x63, 0x65, 0x6e, 0x74, 0x2e, 0x6d, 0x69, - 0x61, 0x6d, 0x69, 0x2e, 0x65, 0x64, 0x75, 0x0d, - 0x0a - }; - uint32_t request1_len = sizeof(request1); - - uint8_t reply1[] = { - 0x32, 0x35, 0x30, 0x2d, 0x62, 0x61, 0x79, 0x30, - 0x2d, 0x6d, 0x63, 0x36, 0x2d, 0x66, 0x31, 0x30, - 0x2e, 0x62, 0x61, 0x79, 0x30, 0x2e, 0x68, 0x6f, - 0x74, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, - 0x6d, 0x20, 0x28, 0x33, 0x2e, 0x33, 0x2e, 0x31, - 0x2e, 0x34, 0x29, 0x20, 0x48, 0x65, 0x6c, 0x6c, - 0x6f, 0x20, 0x5b, 0x31, 0x32, 0x39, 0x2e, 0x31, - 0x37, 0x31, 0x2e, 0x33, 0x32, 0x2e, 0x35, 0x39, - 0x5d, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x53, - 0x49, 0x5a, 0x45, 0x20, 0x32, 0x39, 0x36, 0x39, - 0x36, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x32, 0x35, - 0x30, 0x2d, 0x50, 0x49, 0x50, 0x45, 0x4c, 0x49, - 0x4e, 0x49, 0x4e, 0x47, 0x0d, 0x0a, 0x32, 0x35, - 0x30, 0x2d, 0x38, 0x62, 0x69, 0x74, 0x6d, 0x69, - 0x6d, 0x65, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, - 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x4d, 0x49, - 0x4d, 0x45, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, - 0x43, 0x48, 0x55, 0x4e, 0x4b, 0x49, 0x4e, 0x47, - 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x41, 0x55, - 0x54, 0x48, 0x20, 0x4c, 0x4f, 0x47, 0x49, 0x4e, - 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x41, 0x55, - 0x54, 0x48, 0x3d, 0x4c, 0x4f, 0x47, 0x49, 0x4e, - 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x20, 0x4f, 0x4b, - 0x0d, 0x0a - }; - uint32_t reply1_len = sizeof(reply1); - - /* MAIL FROM:asdff@asdf.com<CR><LF> */ - uint8_t request2[] = { - 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, - 0x4d, 0x3a, 0x61, 0x73, 0x64, 0x66, 0x66, 0x40, - 0x61, 0x73, 0x64, 0x66, 0x2e, 0x63, 0x6f, 0x6d, - 0x0d, 0x0a - }; - uint32_t request2_len = sizeof(request2); - /* 250 2.1.0 Ok<CR><LF> */ - uint8_t reply2[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, - 0x30, 0x20, 0x4f, 0x6b, 0x0d, 0x0a - }; - uint32_t reply2_len = sizeof(reply2); - - /* RCPT TO:bimbs@gmail.com<CR><LF> */ - uint8_t request3[] = { - 0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a, - 0x62, 0x69, 0x6d, 0x62, 0x73, 0x40, 0x67, 0x6d, - 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x0d, - 0x0a - }; - uint32_t request3_len = sizeof(request3); - /* 250 2.1.5 Ok<CR><LF> */ - uint8_t reply3[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, - 0x35, 0x20, 0x4f, 0x6b, 0x0d, 0x0a - }; - uint32_t reply3_len = sizeof(reply3); - - /* BDAT 51<CR><LF> */ - uint8_t request4[] = { - 0x42, 0x44, 0x41, 0x54, 0x20, 0x35, 0x31, 0x0d, - 0x0a, - }; - uint32_t request4_len = sizeof(request4); - - uint8_t request5[] = { - 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x61, 0x73, 0x64, - 0x66, 0x66, 0x40, 0x61, 0x73, 0x64, 0x66, 0x2e, - 0x66, 0x66, 0x40, 0x61, 0x73, 0x64, 0x66, 0x2e, - 0x66, 0x66, 0x40, 0x61, 0x73, 0x64, 0x0d, 0x0a, - }; - uint32_t request5_len = sizeof(request5); - - uint8_t request6[] = { - 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x61, 0x73, 0x64, - 0x66, 0x66, 0x40, 0x61, 0x73, 0x64, 0x66, 0x2e, - 0x66, 0x0d, 0x0a, - }; - uint32_t request6_len = sizeof(request6); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply1, reply1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply2, reply2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request3, request3_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply3, reply3_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request4, request4_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_BDAT || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE) || - smtp_state->bdat_chunk_len != 51 || - smtp_state->bdat_chunk_idx != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request5, request5_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE) || - smtp_state->bdat_chunk_len != 51 || - smtp_state->bdat_chunk_idx != 32) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request6, request6_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN || - smtp_state->bdat_chunk_len != 51 || - smtp_state->bdat_chunk_idx != 51) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -/* - * \test Test retrieving lines when frag'ed. - */ -int SMTPParserTest07(void) -{ - int result = 0; - Flow f; - int r = 0; - - const char *request1_str = "EHLO boo.com"; - /* EHLO boo.com<CR> */ - uint8_t request1_1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, - }; - int32_t request1_1_len = sizeof(request1_1); - - /* <LF> */ - uint8_t request1_2[] = { - 0x0a - }; - int32_t request1_2_len = sizeof(request1_2); - - /* EHLO boo.com<CR><LF> */ - uint8_t request2[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a, - }; - int32_t request2_len = sizeof(request2); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1_1, request1_1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->current_line != NULL || - smtp_state->current_line_len != 0 || - smtp_state->ts_current_line_db != 1 || - smtp_state->ts_db == NULL || - smtp_state->ts_db_len != request1_1_len || - memcmp(smtp_state->ts_db, request1_1, request1_1_len) != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1_2, request1_2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->ts_current_line_db != 1 || - smtp_state->ts_db == NULL || - smtp_state->ts_db_len != (int32_t)strlen(request1_str) || - memcmp(smtp_state->ts_db, request1_str, strlen(request1_str)) != 0 || - smtp_state->current_line != smtp_state->ts_db || - smtp_state->current_line_len != smtp_state->ts_db_len) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->ts_current_line_db != 0 || - smtp_state->ts_db != NULL || - smtp_state->ts_db_len != 0 || - smtp_state->current_line == NULL || - smtp_state->current_line_len != (int32_t)strlen(request1_str) || - memcmp(smtp_state->current_line, request1_str, strlen(request1_str)) != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -/* - * \test Test retrieving lines when frag'ed. - */ -int SMTPParserTest08(void) -{ - int result = 0; - Flow f; - int r = 0; - - const char *request1_str = "EHLO boo.com"; - /* EHLO boo.com */ - uint8_t request1_1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, - }; - int32_t request1_1_len = sizeof(request1_1); - - /* <CR><LF> */ - uint8_t request1_2[] = { - 0x0d, 0x0a - }; - int32_t request1_2_len = sizeof(request1_2); - - /* EHLO boo.com<CR><LF> */ - uint8_t request2[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a, - }; - int32_t request2_len = sizeof(request2); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1_1, request1_1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->current_line != NULL || - smtp_state->current_line_len != 0 || - smtp_state->ts_current_line_db != 1 || - smtp_state->ts_db == NULL || - smtp_state->ts_db_len != request1_1_len || - memcmp(smtp_state->ts_db, request1_1, request1_1_len) != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1_2, request1_2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->ts_current_line_db != 1 || - smtp_state->ts_db == NULL || - smtp_state->ts_db_len != (int32_t)strlen(request1_str) || - memcmp(smtp_state->ts_db, request1_str, strlen(request1_str)) != 0 || - smtp_state->current_line != smtp_state->ts_db || - smtp_state->current_line_len != smtp_state->ts_db_len) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->ts_current_line_db != 0 || - smtp_state->ts_db != NULL || - smtp_state->ts_db_len != 0 || - smtp_state->current_line == NULL || - smtp_state->current_line_len != (int32_t)strlen(request1_str) || - memcmp(smtp_state->current_line, request1_str, strlen(request1_str)) != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -/* - * \test Test retrieving lines when frag'ed. - */ -int SMTPParserTest09(void) -{ - int result = 0; - Flow f; - int r = 0; - - const char *request1_str = "EHLO boo.com"; - /* EHLO boo. */ - uint8_t request1_1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, - }; - int32_t request1_1_len = sizeof(request1_1); - - /* com<CR><LF> */ - uint8_t request1_2[] = { - 0x63, 0x6f, 0x6d, 0x0d, 0x0a - }; - int32_t request1_2_len = sizeof(request1_2); - - /* EHLO boo.com<CR><LF> */ - uint8_t request2[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a, - }; - int32_t request2_len = sizeof(request2); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1_1, request1_1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->current_line != NULL || - smtp_state->current_line_len != 0 || - smtp_state->ts_current_line_db != 1 || - smtp_state->ts_db == NULL || - smtp_state->ts_db_len != request1_1_len || - memcmp(smtp_state->ts_db, request1_1, request1_1_len) != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1_2, request1_2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->ts_current_line_db != 1 || - smtp_state->ts_db == NULL || - smtp_state->ts_db_len != (int32_t)strlen(request1_str) || - memcmp(smtp_state->ts_db, request1_str, strlen(request1_str)) != 0 || - smtp_state->current_line != smtp_state->ts_db || - smtp_state->current_line_len != smtp_state->ts_db_len) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->ts_current_line_db != 0 || - smtp_state->ts_db != NULL || - smtp_state->ts_db_len != 0 || - smtp_state->current_line == NULL || - smtp_state->current_line_len != (int32_t)strlen(request1_str) || - memcmp(smtp_state->current_line, request1_str, strlen(request1_str)) != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -/* - * \test Test retrieving lines when frag'ed. - */ -int SMTPParserTest10(void) -{ - int result = 0; - Flow f; - int r = 0; - - const char *request1_str = ""; - /* EHLO boo. */ - uint8_t request1_1[] = { - 0x0d, - }; - int32_t request1_1_len = sizeof(request1_1); - - /* com<CR><LF> */ - uint8_t request1_2[] = { - 0x0a, - }; - int32_t request1_2_len = sizeof(request1_2); - - const char *request2_str = "EHLO boo.com"; - /* EHLO boo.com<CR><LF> */ - uint8_t request2[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a, - }; - int32_t request2_len = sizeof(request2); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1_1, request1_1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->current_line != NULL || - smtp_state->current_line_len != 0 || - smtp_state->ts_current_line_db != 1 || - smtp_state->ts_db == NULL || - smtp_state->ts_db_len != request1_1_len || - memcmp(smtp_state->ts_db, request1_1, request1_1_len) != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1_2, request1_2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->ts_current_line_db != 1 || - smtp_state->ts_db == NULL || - smtp_state->ts_db_len != (int32_t)strlen(request1_str) || - memcmp(smtp_state->ts_db, request1_str, strlen(request1_str)) != 0 || - smtp_state->current_line != smtp_state->ts_db || - smtp_state->current_line_len != smtp_state->ts_db_len) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->ts_current_line_db != 0 || - smtp_state->ts_db != NULL || - smtp_state->ts_db_len != 0 || - smtp_state->current_line == NULL || - smtp_state->current_line_len != (int32_t)strlen(request2_str) || - memcmp(smtp_state->current_line, request2_str, strlen(request2_str)) != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -/* - * \test Test retrieving lines when frag'ed. - */ -int SMTPParserTest11(void) -{ - int result = 0; - Flow f; - int r = 0; - - const char *request1_str = ""; - /* EHLO boo. */ - uint8_t request1[] = { - 0x0a, - }; - int32_t request1_len = sizeof(request1); - - const char *request2_str = "EHLO boo.com"; - /* EHLO boo.com<CR><LF> */ - uint8_t request2[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a, - }; - int32_t request2_len = sizeof(request2); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->current_line == NULL || - smtp_state->current_line_len != 0 || - smtp_state->ts_current_line_db == 1 || - smtp_state->ts_db != NULL || - smtp_state->ts_db_len != 0 || - memcmp(smtp_state->current_line, request1_str, strlen(request1_str)) != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->ts_current_line_db != 0 || - smtp_state->ts_db != NULL || - smtp_state->ts_db_len != 0 || - smtp_state->current_line == NULL || - smtp_state->current_line_len != (int32_t)strlen(request2_str) || - memcmp(smtp_state->current_line, request2_str, strlen(request2_str)) != 0) { - printf("smtp parser in inconsistent state\n"); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -int SMTPParserTest12(void) -{ - int result = 0; - Signature *s = NULL; - ThreadVars th_v; - Packet *p = NULL; - Flow f; - TcpSession ssn; - DetectEngineThreadCtx *det_ctx = NULL; - DetectEngineCtx *de_ctx = NULL; - SMTPState *smtp_state = NULL; - int r = 0; - - /* EHLO boo.com<CR><LF> */ - uint8_t request1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a, - }; - int32_t request1_len = sizeof(request1); - - /* 388<CR><LF> - */ - uint8_t reply1[] = { - 0x31, 0x38, 0x38, 0x0d, 0x0a, - }; - uint32_t reply1_len = sizeof(reply1); - - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - p->flow = &f; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - f.alproto = ALPROTO_SMTP; - - StreamTcpInitConfig(TRUE); - - de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) - goto end; - - de_ctx->flags |= DE_QUIET; - - s = DetectEngineAppendSig(de_ctx,"alert tcp any any -> any any " - "(msg:\"SMTP event handling\"; " - "app-layer-event: smtp.invalid_reply; " - "sid:1;)"); - if (s == NULL) - goto end; - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER | STREAM_START, - request1, request1_len); - if (r != 0) { - printf("AppLayerParse for smtp failed. Returned %" PRId32, r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - - smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - - if (PacketAlertCheck(p, 1)) { - printf("sid 1 matched. It shouldn't match: "); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT | STREAM_TOCLIENT, - reply1, reply1_len); - if (r == 0) { - printf("AppLayerParse for smtp failed. Returned %" PRId32, r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - - if (!PacketAlertCheck(p, 1)) { - printf("sid 1 didn't match. Should have matched: "); - goto end; - } - - result = 1; - -end: - SigGroupCleanup(de_ctx); - SigCleanSignatures(de_ctx); - - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - DetectEngineCtxFree(de_ctx); - - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - UTHFreePackets(&p, 1); - return result; -} - -int SMTPParserTest13(void) -{ - int result = 0; - Signature *s = NULL; - ThreadVars th_v; - Packet *p = NULL; - Flow f; - TcpSession ssn; - DetectEngineThreadCtx *det_ctx = NULL; - DetectEngineCtx *de_ctx = NULL; - SMTPState *smtp_state = NULL; - int r = 0; - - /* EHLO boo.com<CR><LF> */ - uint8_t request1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a, - }; - int32_t request1_len = sizeof(request1); - - /* 250<CR><LF> - */ - uint8_t reply1[] = { - 0x32, 0x35, 0x30, 0x0d, 0x0a, - }; - uint32_t reply1_len = sizeof(reply1); - - /* MAIL FROM:pbsf@asdfs.com<CR><LF> - * RCPT TO:pbsf@asdfs.com<CR><LF> - * DATA<CR><LF> - * STARTTLS<CR><LF> - */ - uint8_t request2[] = { - 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, - 0x4d, 0x3a, 0x70, 0x62, 0x73, 0x66, 0x40, 0x61, - 0x73, 0x64, 0x66, 0x73, 0x2e, 0x63, 0x6f, 0x6d, - 0x0d, 0x0a, 0x52, 0x43, 0x50, 0x54, 0x20, 0x54, - 0x4f, 0x3a, 0x70, 0x62, 0x73, 0x66, 0x40, 0x61, - 0x73, 0x64, 0x66, 0x73, 0x2e, 0x63, 0x6f, 0x6d, - 0x0d, 0x0a, 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a, - 0x53, 0x54, 0x41, 0x52, 0x54, 0x54, 0x4c, 0x53, - 0x0d, 0x0a - }; - uint32_t request2_len = sizeof(request2); - - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&th_v, 0, sizeof(th_v)); - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - p = UTHBuildPacket(NULL, 0, IPPROTO_TCP); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - p->flow = &f; - p->flowflags |= FLOW_PKT_TOSERVER; - p->flowflags |= FLOW_PKT_ESTABLISHED; - p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST; - f.alproto = ALPROTO_SMTP; - - StreamTcpInitConfig(TRUE); - - de_ctx = DetectEngineCtxInit(); - if (de_ctx == NULL) - goto end; - - de_ctx->flags |= DE_QUIET; - - s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any " - "(msg:\"SMTP event handling\"; " - "app-layer-event: " - "smtp.invalid_pipelined_sequence; " - "sid:1;)"); - if (s == NULL) - goto end; - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER | STREAM_START, - request1, request1_len); - if (r != 0) { - printf("AppLayerParse for smtp failed. Returned %" PRId32, r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - - smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - - if (PacketAlertCheck(p, 1)) { - printf("sid 1 matched. It shouldn't match: "); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply1, reply1_len); - if (r != 0) { - printf("AppLayerParse for smtp failed. Returned %" PRId32, r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - - if (PacketAlertCheck(p, 1)) { - printf("sid 1 matched. It shouldn't match: "); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("AppLayerParse for smtp failed. Returned %" PRId32, r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - - /* do detect */ - SigMatchSignatures(&th_v, de_ctx, det_ctx, p); - - if (!PacketAlertCheck(p, 1)) { - printf("sid 1 didn't match. Should have matched: "); - goto end; - } - - result = 1; - -end: - SigGroupCleanup(de_ctx); - SigCleanSignatures(de_ctx); - - DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - DetectEngineCtxFree(de_ctx); - - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - UTHFreePackets(&p, 1); - return result; -} - -/** - * \test Test DATA command w/MIME message. - */ -int SMTPParserTest14(void) -{ - int result = 0; - Flow f; - int r = 0; - - /* 220 mx.google.com ESMTP d15sm986283wfl.6<CR><LF> */ - static uint8_t welcome_reply[] = { - 0x32, 0x32, 0x30, 0x20, 0x6d, 0x78, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x20, 0x45, 0x53, 0x4d, 0x54, 0x50, 0x20, - 0x64, 0x31, 0x35, 0x73, 0x6d, 0x39, 0x38, 0x36, - 0x32, 0x38, 0x33, 0x77, 0x66, 0x6c, 0x2e, 0x36, - 0x0d, 0x0a - }; - static uint32_t welcome_reply_len = sizeof(welcome_reply); - - /* EHLO boo.com<CR><LF> */ - static uint8_t request1[] = { - 0x45, 0x48, 0x4c, 0x4f, 0x20, 0x62, 0x6f, 0x6f, - 0x2e, 0x63, 0x6f, 0x6d, 0x0d, 0x0a - }; - static uint32_t request1_len = sizeof(request1); - /* 250-mx.google.com at your service, [117.198.115.50]<CR><LF> - * 250-SIZE 35882577<CR><LF> - * 250-8BITMIME<CR><LF> - * 250-STARTTLS<CR><LF> - * 250 ENHANCEDSTATUSCODES<CR><LF> - */ - static uint8_t reply1[] = { - 0x32, 0x35, 0x30, 0x2d, 0x70, 0x6f, 0x6f, 0x6e, - 0x61, 0x5f, 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x5f, - 0x76, 0x6d, 0x31, 0x2e, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x50, 0x49, 0x50, - 0x45, 0x4c, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x53, 0x49, 0x5a, - 0x45, 0x20, 0x31, 0x30, 0x32, 0x34, 0x30, 0x30, - 0x30, 0x30, 0x0d, 0x0a, 0x32, 0x35, 0x30, 0x2d, - 0x56, 0x52, 0x46, 0x59, 0x0d, 0x0a, 0x32, 0x35, - 0x30, 0x2d, 0x45, 0x54, 0x52, 0x4e, 0x0d, 0x0a, - 0x32, 0x35, 0x30, 0x2d, 0x45, 0x4e, 0x48, 0x41, - 0x4e, 0x43, 0x45, 0x44, 0x53, 0x54, 0x41, 0x54, - 0x55, 0x53, 0x43, 0x4f, 0x44, 0x45, 0x53, 0x0d, - 0x0a, 0x32, 0x35, 0x30, 0x2d, 0x38, 0x42, 0x49, - 0x54, 0x4d, 0x49, 0x4d, 0x45, 0x0d, 0x0a, 0x32, - 0x35, 0x30, 0x20, 0x44, 0x53, 0x4e, 0x0d, 0x0a - }; - static uint32_t reply1_len = sizeof(reply1); - - /* MAIL FROM:asdff@asdf.com<CR><LF> */ - static uint8_t request2[] = { - 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, - 0x4d, 0x3a, 0x61, 0x73, 0x64, 0x66, 0x66, 0x40, - 0x61, 0x73, 0x64, 0x66, 0x2e, 0x63, 0x6f, 0x6d, - 0x0d, 0x0a - }; - static uint32_t request2_len = sizeof(request2); - /* 250 2.1.0 Ok<CR><LF> */ - static uint8_t reply2[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, - 0x30, 0x20, 0x4f, 0x6b, 0x0d, 0x0a - }; - static uint32_t reply2_len = sizeof(reply2); - - /* RCPT TO:bimbs@gmail.com<CR><LF> */ - static uint8_t request3[] = { - 0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a, - 0x62, 0x69, 0x6d, 0x62, 0x73, 0x40, 0x67, 0x6d, - 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x0d, - 0x0a - }; - static uint32_t request3_len = sizeof(request3); - /* 250 2.1.5 Ok<CR><LF> */ - static uint8_t reply3[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x31, 0x2e, - 0x35, 0x20, 0x4f, 0x6b, 0x0d, 0x0a - }; - static uint32_t reply3_len = sizeof(reply3); - - /* DATA<CR><LF> */ - static uint8_t request4[] = { - 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a - }; - static uint32_t request4_len = sizeof(request4); - /* 354 End data with <CR><LF>.<CR><LF>|<CR><LF>| */ - static uint8_t reply4[] = { - 0x33, 0x35, 0x34, 0x20, 0x45, 0x6e, 0x64, 0x20, - 0x64, 0x61, 0x74, 0x61, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x20, 0x3c, 0x43, 0x52, 0x3e, 0x3c, 0x4c, - 0x46, 0x3e, 0x2e, 0x3c, 0x43, 0x52, 0x3e, 0x3c, - 0x4c, 0x46, 0x3e, 0x0d, 0x0a - }; - static uint32_t reply4_len = sizeof(reply4); - - /* MIME_MSG */ - static uint64_t filesize = 133; - static uint8_t request4_msg[] = { - 0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, - 0x30, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, - 0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x3A, - 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x6F, 0x63, 0x74, - 0x65, 0x74, 0x2D, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6D, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, - 0x6E, 0x74, 0x2D, 0x54, 0x72, 0x61, 0x6E, 0x73, - 0x66, 0x65, 0x72, 0x2D, 0x45, 0x6E, 0x63, 0x6F, - 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x61, - 0x73, 0x65, 0x36, 0x34, 0x0D, 0x0A, 0x43, 0x6F, - 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x44, 0x69, - 0x73, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, - 0x6E, 0x3A, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, - 0x68, 0x6D, 0x65, 0x6E, 0x74, 0x3B, 0x20, 0x66, - 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x3D, - 0x22, 0x74, 0x65, 0x73, 0x74, 0x2E, 0x65, 0x78, - 0x65, 0x22, 0x3B, 0x0D, 0x0A, 0x0D, 0x0A, 0x54, - 0x56, 0x6F, 0x41, 0x41, 0x46, 0x42, 0x46, 0x41, - 0x41, 0x42, 0x4D, 0x41, 0x51, 0x45, 0x41, 0x61, - 0x69, 0x70, 0x59, 0x77, 0x77, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, - 0x41, 0x41, 0x44, 0x41, 0x51, 0x73, 0x42, 0x43, - 0x41, 0x41, 0x42, 0x41, 0x41, 0x43, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x48, 0x6B, 0x41, 0x41, - 0x41, 0x41, 0x4D, 0x41, 0x41, 0x41, 0x41, 0x65, - 0x51, 0x41, 0x41, 0x41, 0x41, 0x77, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x45, 0x41, 0x41, 0x42, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x51, 0x41, 0x41, - 0x41, 0x42, 0x30, 0x41, 0x41, 0x41, 0x41, 0x49, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x51, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, - 0x41, 0x45, 0x41, 0x41, 0x49, 0x67, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, - 0x67, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, - 0x41, 0x42, 0x63, 0x58, 0x44, 0x59, 0x32, 0x4C, - 0x6A, 0x6B, 0x7A, 0x4C, 0x6A, 0x59, 0x34, 0x4C, - 0x6A, 0x5A, 0x63, 0x65, 0x67, 0x41, 0x41, 0x4F, - 0x41, 0x3D, 0x3D, 0x0D,0x0A }; - static uint32_t request4_msg_len = sizeof(request4_msg); - - /* DATA COMPLETED */ - static uint8_t request4_end[] = { - 0x0d, 0x0a, 0x2e, 0x0d, 0x0a - }; - static uint32_t request4_end_len = sizeof(request4_end); - /* 250 2.0.0 Ok: queued as 6A1AF20BF2<CR><LF> */ - static uint8_t reply4_end[] = { - 0x32, 0x35, 0x30, 0x20, 0x32, 0x2e, 0x30, 0x2e, - 0x30, 0x20, 0x4f, 0x6b, 0x3a, 0x20, 0x71, 0x75, - 0x65, 0x75, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, - 0x36, 0x41, 0x31, 0x41, 0x46, 0x32, 0x30, 0x42, - 0x46, 0x32, 0x0d, 0x0a - }; - static uint32_t reply4_end_len = sizeof(reply4_end); - - /* QUIT<CR><LF> */ - static uint8_t request5[] = { - 0x51, 0x55, 0x49, 0x54, 0x0d, 0x0a - }; - static uint32_t request5_len = sizeof(request5); - /* 221 2.0.0 Bye<CR><LF> */ - static uint8_t reply5[] = { - 0x32, 0x32, 0x31, 0x20, 0x32, 0x2e, 0x30, 0x2e, - 0x30, 0x20, 0x42, 0x79, 0x65, 0x0d, 0x0a - }; - static uint32_t reply5_len = sizeof(reply5); - - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&f, 0, sizeof(f)); - memset(&ssn, 0, sizeof(ssn)); - - FLOW_INITIALIZE(&f); - f.protoctx = (void *)&ssn; - f.proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f.m); - /* Welcome reply */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - SMTPState *smtp_state = f.alstate; - if (smtp_state == NULL) { - printf("no smtp state: "); - goto end; - } - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - /* EHLO Reply */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply1, reply1_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - 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 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - /* MAIL FROM Request */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request2, request2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - /* MAIL FROM Reply */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply2, reply2_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - 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 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - /* RCPT TO Request */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request3, request3_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - /* RCPT TO Reply */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply3, reply3_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - /* Enable mime decoding */ - smtp_config.decode_mime = 1; - smtp_config.mime_config.decode_base64 = 1; - smtp_config.mime_config.decode_quoted_printable = 1; - MimeDecSetConfig(&smtp_config.mime_config); - - SCMutexLock(&f.m); - /* DATA request */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request4, request4_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_DATA || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - /* Data reply */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply4, reply4_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - /* DATA message */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request4_msg, request4_msg_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->curr_tx->mime_state == NULL || smtp_state->curr_tx->msg_head == NULL || /* MIME data structures */ - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | - SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - /* DATA . request */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request4_end, request4_end_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_DATA_MODE || - smtp_state->curr_tx->mime_state == NULL || smtp_state->curr_tx->msg_head == NULL || /* MIME data structures */ - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SMTPState *state = (SMTPState *) f.alstate; - FileContainer *files = state->files_ts; - if (files != NULL && files->head != NULL) { - File *file = files->head; - - if(strncmp((const char *)file->name, "test.exe", 8) != 0){ - printf("smtp-mime file name is incorrect"); - goto end; - } - if(file->size != filesize){ - printf("smtp-mime file size %"PRIu64" is incorrect", file->size); - goto end; - } - static uint8_t org_binary[] = { - 0x4D, 0x5A, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, - 0x4C, 0x01, 0x01, 0x00, 0x6A, 0x2A, 0x58, 0xC3, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x03, 0x01, 0x0B, 0x01, 0x08, 0x00, - 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x79, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0x79, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x40, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, - 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5C, 0x5C, 0x36, 0x36, - 0x2E, 0x39, 0x33, 0x2E, 0x36, 0x38, 0x2E, 0x36, - 0x5C, 0x7A, 0x00, 0x00, 0x38,}; - uint64_t z; - for (z=0; z < filesize; z++){ - if(org_binary[z] != file->chunks_head->data[z]){ - printf("smtp-mime file data incorrect\n"); - goto end; - } - } - } - - SCMutexLock(&f.m); - /* DATA . reply */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply4_end, reply4_end_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - /* QUIT Request */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request5, request5_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || - smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - SCMutexLock(&f.m); - /* QUIT Reply */ - r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - reply5, reply5_len); - if (r != 0) { - printf("smtp check returned %" PRId32 ", expected 0: ", r); - SCMutexUnlock(&f.m); - goto end; - } - SCMutexUnlock(&f.m); - if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 0 || - smtp_state->cmds_idx != 0 || - smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - printf("smtp parser in inconsistent state l.%d\n", __LINE__); - goto end; - } - - result = 1; -end: - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - StreamTcpFreeConfig(TRUE); - FLOW_DESTROY(&f); - return result; -} - -int SMTPProcessDataChunkTest01(void){ - Flow f; - FLOW_INITIALIZE(&f); - f.flags = FLOW_FILE_NO_STORE_TS; - MimeDecParseState *state = MimeDecInitParser(&f, NULL); - int ret; - ret = SMTPProcessDataChunk(NULL, 0, state); - - return ret; -} - - -int SMTPProcessDataChunkTest02(void){ - char mimemsg[] = {0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, - 0x30, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, - 0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x3A, - 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x6F, 0x63, 0x74, - 0x65, 0x74, 0x2D, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6D, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, - 0x6E, 0x74, 0x2D, 0x54, 0x72, 0x61, 0x6E, 0x73, - 0x66, 0x65, 0x72, 0x2D, 0x45, 0x6E, 0x63, 0x6F, - 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x61, - 0x73, 0x65, 0x36, 0x34, 0x0D, 0x0A, 0x43, 0x6F, - 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x44, 0x69, - 0x73, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, - 0x6E, 0x3A, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, - 0x68, 0x6D, 0x65, 0x6E, 0x74, 0x3B, 0x20, 0x66, - 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x3D, - 0x22, 0x74, 0x65, 0x73, 0x74, 0x2E, 0x65, 0x78, - 0x65, 0x22, 0x3B, 0x0D, 0x0A, 0x0D, 0x0A, 0x54, - 0x56, 0x6F, 0x41, 0x41, 0x46, 0x42, 0x46, 0x41, - 0x41, 0x42, 0x4D, 0x41, 0x51, 0x45, 0x41, 0x61, - 0x69, 0x70, 0x59, 0x77, 0x77, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, - 0x41, 0x41, 0x44, 0x41, 0x51, 0x73, 0x42, 0x43, - 0x41, 0x41, 0x42, 0x41, 0x41, 0x43, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x48, 0x6B, 0x41, 0x41, - 0x41, 0x41, 0x4D, 0x41, 0x41, 0x41, 0x41, 0x65, - 0x51, 0x41, 0x41, 0x41, 0x41, 0x77, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x45, 0x41, 0x41, 0x42, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x51, 0x41, 0x41, - 0x41, 0x42, 0x30, 0x41, 0x41, 0x41, 0x41, 0x49, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x51, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, - 0x41, 0x45, 0x41, 0x41, 0x49, 0x67, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, - 0x67, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, - 0x41, 0x42, 0x63, 0x58, 0x44, 0x59, 0x32, 0x4C, - 0x6A, 0x6B, 0x7A, 0x4C, 0x6A, 0x59, 0x34, 0x4C, - 0x6A, 0x5A, 0x63, 0x65, 0x67, 0x41, 0x41, 0x4F, - 0x41, 0x3D, 0x3D, 0x0D, 0x0A,}; - - Flow f; - FLOW_INITIALIZE(&f); - f.alstate = SMTPStateAlloc(); - MimeDecParseState *state = MimeDecInitParser(&f, NULL); - ((MimeDecEntity *)state->stack->top->data)->ctnt_flags = CTNT_IS_ATTACHMENT; - state->body_begin = 1; - int ret; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state); - - - return ret; -} - - - -int SMTPProcessDataChunkTest03(void){ - char mimemsg[] = {0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72, }; - char mimemsg2[] = {0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, }; - char mimemsg3[] = {0x30, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, }; - char mimemsg4[] = {0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x3A, }; - char mimemsg5[] = {0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, }; - char mimemsg6[] = {0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x6F, 0x63, 0x74, }; - char mimemsg7[] = {0x65, 0x74, 0x2D, 0x73, 0x74, 0x72, 0x65, 0x61, }; - char mimemsg8[] = {0x6D, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, }; - char mimemsg9[] = {0x6E, 0x74, 0x2D, 0x54, 0x72, 0x61, 0x6E, 0x73, }; - char mimemsg10[] = {0x66, 0x65, 0x72, 0x2D, 0x45, 0x6E, 0x63, 0x6F, }; - char mimemsg11[] = {0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x61, }; - char mimemsg12[] = {0x73, 0x65, 0x36, 0x34, 0x0D, 0x0A, 0x43, 0x6F, }; - - Flow f; - FLOW_INITIALIZE(&f); - f.alstate = SMTPStateAlloc(); - MimeDecParseState *state = MimeDecInitParser(&f, NULL); - ((MimeDecEntity *)state->stack->top->data)->ctnt_flags = CTNT_IS_ATTACHMENT; - int ret; - - state->body_begin = 1; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state); - if(ret) goto end; - state->body_begin = 0; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg2, sizeof(mimemsg2), state); - if(ret) goto end; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg3, sizeof(mimemsg3), state); - if(ret) goto end; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg4, sizeof(mimemsg4), state); - if(ret) goto end; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg5, sizeof(mimemsg5), state); - if(ret) goto end; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg6, sizeof(mimemsg6), state); - if(ret) goto end; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg7, sizeof(mimemsg7), state); - if(ret) goto end; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg8, sizeof(mimemsg8), state); - if(ret) goto end; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg9, sizeof(mimemsg9), state); - if(ret) goto end; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg10, sizeof(mimemsg10), state); - if(ret) goto end; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg11, sizeof(mimemsg11), state); - if(ret) goto end; - state->body_end = 1; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg12, sizeof(mimemsg12), state); - if(ret) goto end; - - end: - return ret; -} - - -int SMTPProcessDataChunkTest04(void){ - char mimemsg[] = {0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72, }; - char mimemsg2[] = {0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, }; - char mimemsg3[] = {0x30, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, }; - char mimemsg4[] = {0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x3A, }; - char mimemsg5[] = {0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, }; - char mimemsg6[] = {0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x6F, 0x63, 0x74, }; - char mimemsg7[] = {0x65, 0x74, 0x2D, 0x73, 0x74, 0x72, 0x65, 0x61, }; - char mimemsg8[] = {0x6D, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, }; - char mimemsg9[] = {0x6E, 0x74, 0x2D, 0x54, 0x72, 0x61, 0x6E, 0x73, }; - char mimemsg10[] = {0x66, 0x65, 0x72, 0x2D, 0x45, 0x6E, 0x63, 0x6F, }; - char mimemsg11[] = {0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x61, }; - - Flow f; - FLOW_INITIALIZE(&f); - f.alstate = SMTPStateAlloc(); - MimeDecParseState *state = MimeDecInitParser(&f, NULL); - ((MimeDecEntity *)state->stack->top->data)->ctnt_flags = CTNT_IS_ATTACHMENT; - int ret = MIME_DEC_OK; - - state->body_begin = 1; - if(SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state) != 0) goto end; - if(SMTPProcessDataChunk((uint8_t *)mimemsg2, sizeof(mimemsg2), state) != 0) goto end; - if(SMTPProcessDataChunk((uint8_t *)mimemsg3, sizeof(mimemsg3), state) != 0) goto end; - if(SMTPProcessDataChunk((uint8_t *)mimemsg4, sizeof(mimemsg4), state) != 0) goto end; - if(SMTPProcessDataChunk((uint8_t *)mimemsg5, sizeof(mimemsg5), state) != 0) goto end; - if(SMTPProcessDataChunk((uint8_t *)mimemsg6, sizeof(mimemsg6), state) != 0) goto end; - if(SMTPProcessDataChunk((uint8_t *)mimemsg7, sizeof(mimemsg7), state) != 0) goto end; - state->body_begin = 0; - state->body_end = 1; - if(SMTPProcessDataChunk((uint8_t *)mimemsg8, sizeof(mimemsg8), state) != 0) goto end; - state->body_end = 0; - if(SMTPProcessDataChunk((uint8_t *)mimemsg9, sizeof(mimemsg9), state) != 0) goto end; - if(SMTPProcessDataChunk((uint8_t *)mimemsg10, sizeof(mimemsg10), state) != 0) goto end; - if(SMTPProcessDataChunk((uint8_t *)mimemsg11, sizeof(mimemsg11), state) != 0) goto end; - - end: - return ret; -} - -int SMTPProcessDataChunkTest05(void){ - char mimemsg[] = {0x4D, 0x49, 0x4D, 0x45, 0x2D, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x31, 0x2E, - 0x30, 0x0D, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, - 0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x3A, - 0x6A, 0x6B, 0x7A, 0x4C, 0x6A, 0x59, 0x34, 0x4C, - 0x6A, 0x5A, 0x63, 0x65, 0x67, 0x41, 0x41, 0x4F, - 0x41, 0x3D, 0x3D, 0x0D, 0x0A,}; - - Flow f; - FLOW_INITIALIZE(&f); - f.alstate = SMTPStateAlloc(); - MimeDecParseState *state = MimeDecInitParser(&f, NULL); - ((MimeDecEntity *)state->stack->top->data)->ctnt_flags = CTNT_IS_ATTACHMENT; - state->body_begin = 1; - int ret; - uint64_t file_size = 0; - ret = SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state); - state->body_begin = 0; - if(ret){goto end;} - SMTPState *smtp_state = (SMTPState *)((Flow *)state->data)->alstate; - FileContainer *files = smtp_state->files_ts; - File *file = files->head; - file_size = file->size; - - FileDisableStoring(&f, STREAM_TOSERVER); - FileDisableMagic(&f, STREAM_TOSERVER); - FileDisableMd5(&f, STREAM_TOSERVER); - ret = SMTPProcessDataChunk((uint8_t *)mimemsg, sizeof(mimemsg), state); - if(ret){goto end;} - printf("%u\t%u\n", (uint32_t) file->size, (uint32_t) file_size); - if(file->size == file_size){ - return 0; - }else{ - return 1; - } - - end: - return ret; -} - -#endif /* UNITTESTS */ - -void SMTPParserRegisterTests(void) -{ -#ifdef UNITTESTS - UtRegisterTest("SMTPParserTest01", SMTPParserTest01, 1); - UtRegisterTest("SMTPParserTest02", SMTPParserTest02, 1); - UtRegisterTest("SMTPParserTest03", SMTPParserTest03, 1); - UtRegisterTest("SMTPParserTest04", SMTPParserTest04, 1); - UtRegisterTest("SMTPParserTest05", SMTPParserTest05, 1); - UtRegisterTest("SMTPParserTest06", SMTPParserTest06, 1); - UtRegisterTest("SMTPParserTest07", SMTPParserTest07, 1); - UtRegisterTest("SMTPParserTest08", SMTPParserTest08, 1); - UtRegisterTest("SMTPParserTest09", SMTPParserTest09, 1); - UtRegisterTest("SMTPParserTest10", SMTPParserTest10, 1); - UtRegisterTest("SMTPParserTest11", SMTPParserTest11, 1); - UtRegisterTest("SMTPParserTest12", SMTPParserTest12, 1); - UtRegisterTest("SMTPParserTest13", SMTPParserTest13, 1); - UtRegisterTest("SMTPParserTest14", SMTPParserTest14, 1); - UtRegisterTest("SMTPProcessDataChunkTest01", SMTPProcessDataChunkTest01, 0); - UtRegisterTest("SMTPProcessDataChunkTest02", SMTPProcessDataChunkTest02, 0); - UtRegisterTest("SMTPProcessDataChunkTest03", SMTPProcessDataChunkTest03, 0); - UtRegisterTest("SMTPProcessDataChunkTest04", SMTPProcessDataChunkTest04, 0); - UtRegisterTest("SMTPProcessDataChunkTest05", SMTPProcessDataChunkTest05, 0); -#endif /* UNITTESTS */ - - return; -} |