]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3363: ftp: splitter and inspector fixes
authorRuss Combs (rucombs) <rucombs@cisco.com>
Tue, 12 Apr 2022 14:59:40 +0000 (14:59 +0000)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Tue, 12 Apr 2022 14:59:40 +0000 (14:59 +0000)
Merge in SNORT/snort3 from ~BRASTULT/snort3:ftp_splitter_fix to master

Squashed commit of the following:

commit 5dae1d6e2ad7c446d8f1ff565de6730e47fb4eab
Author: Brandon Stultz <brastult@cisco.com>
Date:   Tue Apr 5 03:39:36 2022 -0400

    ftp: fix FTP response parsing

commit 08fdc2b94f137b87caca64e66ecae33f2e696329
Author: Brandon Stultz <brastult@cisco.com>
Date:   Tue Apr 5 00:54:37 2022 -0400

    ftp: flush FTP cmds ending in just carriage return

src/service_inspectors/ftp_telnet/ftp_splitter.cc
src/service_inspectors/ftp_telnet/pp_ftp.cc
src/utils/util.cc
src/utils/util.h

index d98c2342aec7af5944cccf31a3dbe4d56559ff8b..137a2f47e5346ed292719b124e8ab231e0c4aa6f 100644 (file)
@@ -24,6 +24,7 @@
 #include "ftp_splitter.h"
 #include "protocols/ssl.h"
 #include "protocols/packet.h"
+#include "utils/util.h"
 
 #include <cstring>
 
@@ -31,34 +32,34 @@ using namespace snort;
 
 FtpSplitter::FtpSplitter(bool c2s) : StreamSplitter(c2s) { }
 
-// flush at last line feed in data
+// flush at last CR or LF in data
 // preproc will deal with any pipelined commands
 StreamSplitter::Status FtpSplitter::scan(
     Packet* p, const uint8_t* data, uint32_t len,
     uint32_t, uint32_t* fp)
 {
-    if(IsSSL(data, len, p->packet_flags))
+    if ( IsSSL(data, len, p->packet_flags) )
     {
         *fp = len;
         return FLUSH;
     }
-#ifdef HAVE_MEMRCHR
-    const uint8_t* lf =  (const uint8_t*)memrchr(data, '\n', len);
-#else
-    uint32_t n = len;
-    const uint8_t* lf = nullptr, * tmp = data;
 
-    while ( (tmp = (const uint8_t*)memchr(tmp, '\n', n)) )
-    {
-        lf = tmp++;
-        n = len - (tmp - data);
-    }
-#endif
+    const uint8_t* cr = snort_memrchr(data, '\r', len);
+    const uint8_t* lf = snort_memrchr(data, '\n', len);
+
+    const uint8_t* ptr = nullptr;
+
+    if ( cr && !lf )
+        ptr = cr;
+    else if ( !cr && lf )
+        ptr = lf;
+    else if ( cr && lf )
+        ptr = ( cr > lf ) ? cr : lf;
 
-    if ( !lf )
+    if ( !ptr )
         return SEARCH;
 
-    *fp = lf - data + 1;
+    *fp = ptr - data + 1;
     return FLUSH;
 }
 
index 550807fb9c7ee27b28728ef19bfe81010c73281e..a703f07edd44214fed35eadedce44d731b6b88c0 100644 (file)
@@ -1596,7 +1596,7 @@ int check_ftp(FTP_SESSION* ftpssn, Packet* p, int iMode)
                     {
                         req->cmd_begin = nullptr;
                         req->cmd_end = nullptr;
-                        if (*read_ptr != SP)
+                        if (*read_ptr != SP && read_ptr != p->data)
                             read_ptr--;
                         state = FTP_RESPONSE_CONT;
                     }
index 6694e037fcfbdf7c503976f384e09f6f133d84d6..8e109303d4c6cad45d482b727f1530a0dc53df21 100644 (file)
@@ -534,6 +534,25 @@ char* snort_strdup(const char* str)
     return p;
 }
 
+const uint8_t* snort_memrchr(const uint8_t* buf, char c, size_t len)
+{
+#ifdef HAVE_MEMRCHR
+    return (const uint8_t*)memrchr(buf, c, len);
+#else
+    size_t n = len;
+    const uint8_t* tmp = buf;
+    const uint8_t* ptr = nullptr;
+
+    while ( n > 0 && (tmp = (const uint8_t*)memchr(tmp, c, n)) )
+    {
+        ptr = tmp++;
+        n = len - (tmp - buf);
+    }
+
+    return ptr;
+#endif
+}
+
 void ts_print(const struct timeval* tvp, char* timebuf, bool yyyymmdd)
 {
     struct timeval tv;
index 31ab353bf010fae91b26ad30eb55484849aadb3a..61f658c14e82e64e9074df01e682d81bc96c05b5 100644 (file)
@@ -108,6 +108,7 @@ SO_PUBLIC extern char** protocol_names;
 SO_PUBLIC const char* get_error(int errnum);
 SO_PUBLIC char* snort_strdup(const char*);
 SO_PUBLIC char* snort_strndup(const char*, size_t);
+SO_PUBLIC const uint8_t* snort_memrchr(const uint8_t*, char, size_t);
 SO_PUBLIC void ts_print(const struct timeval*, char*, bool yyyymmdd = false);
 }