]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4517: pop: adding wrong bytes threshold to determine if pop splitter...
authorAndres Avila Segura (aavilase) <aavilase@cisco.com>
Fri, 13 Dec 2024 20:01:54 +0000 (20:01 +0000)
committerChris Sherwin (chsherwi) <chsherwi@cisco.com>
Fri, 13 Dec 2024 20:01:54 +0000 (20:01 +0000)
Merge in SNORT/snort3 from ~AAVILASE/snort3:pop_inspector_fallback_functionality to master

Squashed commit of the following:

commit 38022a1ce200493ee3f61d72674c505c4f0b4687
Author: Andres Avila <aavilase@cisco.com>
Date:   Thu Nov 7 11:51:21 2024 -0500

    pop: adding wrong bytes threshold to determine if pop splitter should fallback

src/service_inspectors/pop/pop_paf.cc
src/service_inspectors/pop/pop_paf.h

index ebffc37673ca675e211d2449ee89423e674228d7..6427e37e30ddcb1c6a3debe67986b17b4db48f3f 100644 (file)
@@ -67,7 +67,7 @@ static bool search_for_command(PopPafData* pfdata, const uint8_t ch)
     }
     else
     {
-        pfdata->cmd_state.status = POP_CMD_FIN;
+        pfdata->cmd_state.status = POP_CMD_INVALID;
     }
 
     return false;
@@ -87,6 +87,21 @@ static bool init_command_search(PopPafData* pfdata, const uint8_t ch)
         pfdata->cmd_state.exp_resp = POP_PAF_MULTI_LINE_STATE;
         pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_CAPA].name[1]);
         break;
+    case 'a':
+    case 'A':
+        pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE;
+        pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_APOP].name[1]);
+        break;
+    case 'd':
+    case 'D':
+        pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE;
+        pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_DELE].name[1]);
+        break;
+    case 'p':
+    case 'P':
+        pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE;
+        pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_PASS].name[1]);
+        break;
     case 'l':
     case 'L':
         pfdata->cmd_state.exp_resp = POP_PAF_HAS_ARG;
@@ -107,8 +122,23 @@ static bool init_command_search(PopPafData* pfdata, const uint8_t ch)
         pfdata->cmd_state.exp_resp = POP_PAF_HAS_ARG;
         pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_UIDL].name[1]);
         break;
+    case 'n':
+    case 'N':
+        pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE;
+        pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_NOOP].name[1]);
+        break;
+    case 'q':
+    case 'Q':
+        pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE;
+        pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_QUIT].name[1]);
+        break;
+    case 's':
+    case 'S':
+        pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE;
+        pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_STAT].name[1]);
+        break;
     default:
-        pfdata->cmd_state.status = POP_CMD_FIN;
+        pfdata->cmd_state.status = POP_CMD_INVALID;
     }
 
     return false;
@@ -153,12 +183,21 @@ static inline void reset_data_states(PopPafData* pfdata)
  *     -ERR.
  *
  *  RETURNS:
- *           true - if the character is a +
+ *           true - if the character is a + or -
  *           false - if the character is anything else
  */
-static inline int valid_response(const uint8_t data)
+static inline bool valid_response(PopPafData* pfdata, const uint8_t data)
 {
-    return (data == '+');
+    if (data == '+')
+    {
+        return true;
+    } else if (data == '-')
+    {
+        //-ERR is always single line
+        pfdata->pop_state = POP_PAF_SINGLE_LINE_STATE;
+        return true;
+    }
+    return false;
 }
 
 /*
@@ -256,8 +295,20 @@ static StreamSplitter::Status pop_paf_server(PopPafData* pfdata,
     uint32_t boundary_start = 0;
 
     // if a negative response was received, it will be a one line response.
-    if (!pfdata->cmd_continued && !valid_response(*data))
-        pfdata->pop_state = POP_PAF_SINGLE_LINE_STATE;
+    if (!pfdata->cmd_continued && !valid_response(pfdata, *data))
+    {
+        pfdata->server_bytes_seen += len;
+        if (pfdata->server_bytes_seen > POP_MAX_OCTETS)
+        {
+            pfdata->server_bytes_seen = 0;
+            reset_data_states(pfdata);
+            return StreamSplitter::ABORT;
+        }
+    }
+    else 
+    {
+        pfdata->server_bytes_seen = 0;
+    }
 
     for (i = 0; i < len; i++)
     {
@@ -336,14 +387,30 @@ static StreamSplitter::Status pop_paf_client(Flow* ssn, PopPafData* pfdata,
             if (find_data_end_single_line(pfdata, ch, true) )
             {
                 // reset command parsing data
+                pfdata->client_bytes_seen = 0;
                 *fp = i + 1;
                 return StreamSplitter::FLUSH;
             }
             break;
 
+        case POP_CMD_INVALID:
+            if (find_data_end_single_line(pfdata, ch, true))
+            {
+                pfdata->client_bytes_seen += len;
+                if(pfdata->client_bytes_seen > POP_MAX_OCTETS)
+                {
+                    pfdata->client_bytes_seen = 0;
+                    reset_client_cmd_info(pfdata);
+                    return StreamSplitter::ABORT;
+                }
+                *fp = i + 1;
+                return StreamSplitter::FLUSH;
+            }
+            break;
         case POP_CMD_ARG:
             if (find_data_end_single_line(pfdata, ch, true))
             {
+                pfdata->client_bytes_seen = 0;
                 set_server_state(ssn, POP_PAF_MULTI_LINE_STATE);
                 *fp = i + 1;
                 return StreamSplitter::FLUSH;
@@ -355,6 +422,13 @@ static StreamSplitter::Status pop_paf_client(Flow* ssn, PopPafData* pfdata,
         }
     }
 
+    pfdata->client_bytes_seen += len;
+    if(pfdata->client_bytes_seen > POP_MAX_OCTETS) 
+    {
+        reset_client_cmd_info(pfdata);
+        return StreamSplitter::ABORT;
+    }
+
     return StreamSplitter::SEARCH;
 }
 
@@ -366,6 +440,7 @@ PopSplitter::PopSplitter(bool c2s) : StreamSplitter(c2s)
 {
     memset(&state, 0, sizeof(state));
     reset_data_states(&state);
+    reset_client_cmd_info(&state);
 }
 
 
index c14660553f3576cb3e92575b6edaa366003f844d..da3ad225ff6c420b17643083d64a9224ac137a86 100644 (file)
@@ -27,6 +27,7 @@
 #include "mime/file_mime_paf.h"
 #include "stream/stream_splitter.h"
 
+#define POP_MAX_OCTETS 5120
 // Structure used to record expected server termination sequence
 enum PopExpectedResp
 {
@@ -40,7 +41,8 @@ enum PopParseCmdState
 {
     POP_CMD_SEARCH,         // Search for Command
     POP_CMD_FIN,            // Found space. Finished parsing Command
-    POP_CMD_ARG             // Parsing command with multi-line response iff arg given
+    POP_CMD_ARG,            // Parsing command with multi-line response iff arg given
+    POP_CMD_INVALID         //Command is not recognized so finish parsing and update threshold counter
 };
 
 // saves data when parsing client commands
@@ -59,6 +61,8 @@ struct PopPafData
     DataEndState end_state;          // Current termination sequence state
     MimeDataPafInfo data_info;       // Mime Information
     bool cmd_continued;              // data continued from previous packet?
+    uint32_t client_bytes_seen;
+    uint32_t server_bytes_seen;
     bool end_of_data;
 };