From: Philippe Antoine Date: Wed, 5 Dec 2018 08:31:56 +0000 (+0100) Subject: smtp: improve pipelining support X-Git-Tag: suricata-4.1.2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=447c1042f476cb01d1020da47de4a33db113ebcb;p=thirdparty%2Fsuricata.git smtp: improve pipelining support Fixes #1863 --- diff --git a/src/app-layer-smtp.c b/src/app-layer-smtp.c index fc2bb29ffe..d5f7bf74b9 100644 --- a/src/app-layer-smtp.c +++ b/src/app-layer-smtp.c @@ -81,6 +81,8 @@ #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 +/* Used to indicate that the server supports pipelining */ +#define SMTP_PARSER_STATE_PIPELINING_SERVER 0x10 /* Various SMTP commands * We currently have var-ified just STARTTLS and DATA, since we need to them @@ -1000,6 +1002,12 @@ static int SMTPProcessReply(SMTPState *state, Flow *f, * line of the multiline reply, following which we increment the index */ if (!(state->parser_state & SMTP_PARSER_STATE_PARSING_MULTILINE_REPLY)) { state->cmds_idx++; + } else if (state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { + /* we check if the server is indicating pipelining support */ + if (reply_code == SMTP_REPLY_250 && state->current_line_len == 14 && + SCMemcmpLowercase("pipelining", state->current_line+4, 10) == 0) { + state->parser_state |= SMTP_PARSER_STATE_PIPELINING_SERVER; + } } /* if we have matched all the buffered commands, reset the cnt and index */ @@ -1189,7 +1197,10 @@ static int SMTPProcessRequest(SMTPState *state, Flow *f, tx->msg_tail = tx->mime_state->msg; } } - + /* Enter immediately data mode without waiting for server reply */ + if (state->parser_state & SMTP_PARSER_STATE_PIPELINING_SERVER) { + state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE; + } } else if (state->current_line_len >= 4 && SCMemcmpLowercase("bdat", state->current_line, 4) == 0) { r = SMTPParseCommandBDAT(state); @@ -2787,6 +2798,7 @@ static int SMTPParserTest03(void) /* MAIL FROM:pbsf@asdfs.com * RCPT TO:pbsf@asdfs.com * DATA + * Immediate data */ uint8_t request2[] = { 0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, @@ -2795,7 +2807,9 @@ static int SMTPParserTest03(void) 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 + 0x0d, 0x0a, 0x44, 0x41, 0x54, 0x41, 0x0d, 0x0a, + 0x49, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, + 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0d, 0x0a, }; uint32_t request2_len = sizeof(request2); /* 250 2.1.0 Ok @@ -2881,7 +2895,8 @@ static int SMTPParserTest03(void) 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_state->parser_state != ( SMTP_PARSER_STATE_FIRST_REPLY_SEEN | + SMTP_PARSER_STATE_PIPELINING_SERVER)) { printf("smtp parser in inconsistent state\n"); goto end; } @@ -2901,7 +2916,9 @@ static int SMTPParserTest03(void) 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)) { + smtp_state->parser_state != (SMTP_PARSER_STATE_FIRST_REPLY_SEEN | + SMTP_PARSER_STATE_COMMAND_DATA_MODE | + SMTP_PARSER_STATE_PIPELINING_SERVER)) { printf("smtp parser in inconsistent state\n"); goto end; } @@ -2919,7 +2936,8 @@ static int SMTPParserTest03(void) 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)) { + SMTP_PARSER_STATE_COMMAND_DATA_MODE | + SMTP_PARSER_STATE_PIPELINING_SERVER)) { printf("smtp parser in inconsistent state\n"); goto end; }