]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smtp: enforce line limit even when LF is found 8721/head
authorShivani Bhardwaj <shivani@oisf.net>
Tue, 4 Apr 2023 06:28:42 +0000 (11:58 +0530)
committerVictor Julien <vjulien@oisf.net>
Thu, 13 Apr 2023 05:34:49 +0000 (07:34 +0200)
Before:
If LF character was found, so far, we won't enforce the line limit on
the line. We only enforced limits in case of LF character missing in a
long line.

After this patch:
Line limit is enforced on the line if it is bigger than 4096 Bytes
irrespective of whether LF was found or not.

Redmine Bug: 5819

(cherry picked from commit 5f52b199ff0a49628fa00103d86bd72c5792a6b0)

src/app-layer-smtp.c

index 1a94ba085b1a63574d3001b91e8468850c377afc..ed9626fd4d9ce0abe4e0d0901adf7e1dbfe60b0d 100644 (file)
@@ -567,11 +567,24 @@ static AppLayerResult SMTPGetLine(SMTPState *state)
         }
         SCReturnStruct(APP_LAYER_INCOMPLETE(state->consumed, state->input_len + 1));
     } else {
+        /* There could be one chunk of command data that has LF but post the line limit
+         * e.g. input_len = 5077
+         *      lf_idx = 5010
+         *      max_line_len = 4096 */
         uint32_t o_consumed = state->consumed;
         state->consumed = lf_idx - state->input + 1;
         state->current_line_len = state->consumed - o_consumed;
+        DEBUG_VALIDATE_BUG_ON(state->current_line_len < 0);
+        if (state->current_line_len < 0)
+            SCReturnStruct(APP_LAYER_ERROR);
         state->input_len -= state->current_line_len;
         DEBUG_VALIDATE_BUG_ON((state->consumed + state->input_len) != state->orig_input_len);
+        state->current_line = state->input + o_consumed;
+        if (state->current_line_len >= SMTP_LINE_BUFFER_LIMIT) {
+            state->current_line_len = SMTP_LINE_BUFFER_LIMIT;
+            state->current_line_delimiter_len = 0;
+            SCReturnStruct(APP_LAYER_OK);
+        }
         if (state->discard_till_lf) {
             // Whatever came in with first LF should also get discarded
             state->discard_till_lf = false;
@@ -579,7 +592,6 @@ static AppLayerResult SMTPGetLine(SMTPState *state)
             state->current_line_delimiter_len = 0;
             SCReturnStruct(APP_LAYER_OK);
         }
-        state->current_line = state->input + o_consumed;
         if (state->consumed >= 2 && state->input[state->consumed - 2] == 0x0D) {
             state->current_line_delimiter_len = 2;
             state->current_line_len -= 2;
@@ -1199,6 +1211,8 @@ static int SMTPProcessRequest(SMTPState *state, Flow *f,
 static int SMTPPreProcessCommands(SMTPState *state, Flow *f, AppLayerParserState *pstate)
 {
     DEBUG_VALIDATE_BUG_ON((state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE) == 0);
+    DEBUG_VALIDATE_BUG_ON(state->current_line_len != 0);
+    DEBUG_VALIDATE_BUG_ON(state->current_line_delimiter_len != 0);
 
     /* fall back to strict line parsing for mime header parsing */
     if (state->curr_tx && state->curr_tx->mime_state &&
@@ -1236,6 +1250,7 @@ static int SMTPPreProcessCommands(SMTPState *state, Flow *f, AppLayerParserState
             int32_t current_line_consumed = total_consumed - state->consumed;
             state->current_line = state->input + state->consumed;
             state->current_line_len = current_line_consumed - state->current_line_delimiter_len;
+            DEBUG_VALIDATE_BUG_ON(state->current_line_len < 0);
             state->consumed = total_consumed;
             state->input_len -= current_line_consumed;
             DEBUG_VALIDATE_BUG_ON(state->consumed + state->input_len != state->orig_input_len);
@@ -1290,40 +1305,33 @@ static AppLayerResult SMTPParse(int direction, Flow *f, SMTPState *state,
     /* toserver */
     if (direction == 0) {
         while (res.status == 0) {
-            DEBUG_VALIDATE_BUG_ON(state->discard_till_lf);
-            if (!state->discard_till_lf) {
-                if ((state->current_line_delimiter_len > 0) &&
-                        (SMTPProcessRequest(state, f, pstate) == -1))
-                    SCReturnStruct(APP_LAYER_ERROR);
-                if (state->current_line_delimiter_len == 0 &&
-                        state->current_line_len == SMTP_LINE_BUFFER_LIMIT) {
-                    state->discard_till_lf = true;
-                    state->consumed = state->input_len + 1; // For the newly found LF
-                    SMTPSetEvent(state, SMTP_DECODER_EVENT_TRUNCATED_LINE);
-                    break;
-                }
-                res = SMTPGetLine(state);
+            int retval = SMTPProcessRequest(state, f, pstate);
+            if (retval != 0)
+                SCReturnStruct(APP_LAYER_ERROR);
+            if (state->current_line_delimiter_len == 0 &&
+                    state->current_line_len == SMTP_LINE_BUFFER_LIMIT) {
+                state->discard_till_lf = true;
+                state->consumed = state->input_len + 1; // For the newly found LF
+                SMTPSetEvent(state, SMTP_DECODER_EVENT_TRUNCATED_LINE);
+                break;
             }
+            res = SMTPGetLine(state);
         }
         if (res.status == 1)
             return res;
         /* toclient */
     } else {
         while (res.status == 0) {
-            DEBUG_VALIDATE_BUG_ON(state->discard_till_lf);
-            if (!state->discard_till_lf) {
-                if ((state->current_line_delimiter_len > 0) &&
-                        (SMTPProcessReply(state, f, pstate, thread_data) == -1))
-                    SCReturnStruct(APP_LAYER_ERROR);
-                if (state->current_line_delimiter_len == 0 &&
-                        state->current_line_len == SMTP_LINE_BUFFER_LIMIT) {
-                    state->discard_till_lf = true;
-                    state->consumed = state->input_len + 1; // For the newly found LF
-                    SMTPSetEvent(state, SMTP_DECODER_EVENT_TRUNCATED_LINE);
-                    break;
-                }
-                res = SMTPGetLine(state);
+            if (SMTPProcessReply(state, f, pstate, thread_data) != 0)
+                SCReturnStruct(APP_LAYER_ERROR);
+            if (state->current_line_delimiter_len == 0 &&
+                    state->current_line_len == SMTP_LINE_BUFFER_LIMIT) {
+                state->discard_till_lf = true;
+                state->consumed = state->input_len + 1; // For the newly found LF
+                SMTPSetEvent(state, SMTP_DECODER_EVENT_TRUNCATED_LINE);
+                break;
             }
+            res = SMTPGetLine(state);
         }
         if (res.status == 1)
             return res;