]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smtp: improve pipelining support
authorPhilippe Antoine <contact@catenacyber.fr>
Wed, 5 Dec 2018 08:31:56 +0000 (09:31 +0100)
committerVictor Julien <victor@inliniac.net>
Sat, 16 Feb 2019 13:58:18 +0000 (14:58 +0100)
Fixes #1863

src/app-layer-smtp.c

index cc6d9ea2adae50f6733c6ee13c10a070748bb6d6..29a91c709bc5292fb0b0d995307e5f3cecba4a2c 100644 (file)
@@ -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);
@@ -2769,6 +2780,7 @@ static int SMTPParserTest03(void)
     /* MAIL FROM:pbsf@asdfs.com<CR><LF>
      * RCPT TO:pbsf@asdfs.com<CR><LF>
      * DATA<CR><LF>
+     * Immediate data
      */
     uint8_t request2[] = {
         0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f,
@@ -2777,7 +2789,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<CR><LF>
@@ -2863,7 +2877,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;
     }
@@ -2883,7 +2898,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;
     }
@@ -2901,7 +2918,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;
     }