]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #929 in SNORT/snort3 from ssl_splitter to master
authorTom Peters (thopeter) <thopeter@cisco.com>
Tue, 20 Jun 2017 17:42:51 +0000 (13:42 -0400)
committerTom Peters (thopeter) <thopeter@cisco.com>
Tue, 20 Jun 2017 17:42:51 +0000 (13:42 -0400)
Squashed commit of the following:

commit 79d04e69161c7d6e9c5ae83546e1102ceb746148
Author: Steven Baigal <sbaigal@cisco.com>
Date:   Mon Jun 12 16:32:33 2017 -0400

    add ssl splitter

src/service_inspectors/ssl/CMakeLists.txt
src/service_inspectors/ssl/Makefile.am
src/service_inspectors/ssl/ssl_inspector.cc
src/service_inspectors/ssl/ssl_splitter.cc [new file with mode: 0644]
src/service_inspectors/ssl/ssl_splitter.h [new file with mode: 0644]

index d91614fbfdc2d19deb63bdf9f7e6d87627753fc1..5db4f30deb25373ad07a6100d3fb48baa60561b3 100644 (file)
@@ -1,12 +1,14 @@
 
 set( FILE_LIST
+    ips_ssl_state.cc
+    ips_ssl_version.cc
+    ssl_config.h
     ssl_inspector.cc
     ssl_inspector.h
-    ssl_config.h
     ssl_module.cc
     ssl_module.h
-    ips_ssl_state.cc
-    ips_ssl_version.cc
+    ssl_splitter.cc
+    ssl_splitter.h
 )
 
 # can't be be linked dynamically yet
index 43309288c7fc77897fb6d7efa6012e22e8967c81..b38c5da15cb49e8be0ed3af66f0c7393ba2878f8 100644 (file)
@@ -1,12 +1,14 @@
 
 file_list = \
+ips_ssl_state.cc \
+ips_ssl_version.cc \
 ssl_config.h \
 ssl_inspector.cc \
 ssl_inspector.h \
 ssl_module.cc \
 ssl_module.h \
-ips_ssl_state.cc \
-ips_ssl_version.cc
+ssl_splitter.cc \
+ssl_splitter.h
 
 # can't be linked dynamically yet
 #if STATIC_INSPECTORS
index d340fbf8b00567c8f9ff557071d37169f1163578..4060e3385698088cd902f36119af7282cc8c162f 100644 (file)
@@ -37,6 +37,7 @@
 #include "stream/stream_splitter.h"
 
 #include "ssl_module.h"
+#include "ssl_splitter.h"
 
 THREAD_LOCAL ProfileStats sslPerfStats;
 THREAD_LOCAL SslStats sslstats;
@@ -413,7 +414,7 @@ public:
     void eval(Packet*) override;
 
     StreamSplitter* get_splitter(bool c2s)
-    { return new StopAndWaitSplitter(c2s); }
+    { return new SslSplitter(c2s); }
 
 private:
     SSL_PROTO_CONF* config;
diff --git a/src/service_inspectors/ssl/ssl_splitter.cc b/src/service_inspectors/ssl/ssl_splitter.cc
new file mode 100644 (file)
index 0000000..0da15dc
--- /dev/null
@@ -0,0 +1,142 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2017-2017 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// ssl_splitter.cc author Steven Baigal <sbaigal@cisco.com>
+
+#include "ssl_splitter.h"
+
+#include <arpa/inet.h>
+
+#include "protocols/ssl.h"
+
+SslSplitter::SslSplitter(bool c2s) : StreamSplitter(c2s)
+{
+    paf_state = SSL_PAF_STATES_START;
+    remain_len = 0;
+    len_bytes[0] = len_bytes[1] = 0;
+    is_sslv2 = false;
+}
+
+StreamSplitter::Status SslSplitter::scan(
+    Flow*, const uint8_t* data, uint32_t len,
+    uint32_t, uint32_t* fp)
+{
+    uint32_t n = 0;
+    uint32_t skip_len = 0;
+    uint32_t last_fp = 0;
+
+    while (n < len)
+    {
+        switch (paf_state)
+        {
+        case SSL_PAF_STATES_START:
+            if (data[n] >= SSL_CHANGE_CIPHER_REC and data[n] <= SSL_HEARTBEAT_REC)
+            {
+                is_sslv2 = false;
+                paf_state = SSL_PAF_STATES_VER_MJR;
+            }
+            else if ((data[n] & 0x80) or is_sslv2)
+            {
+                len_bytes[0] = data[n];
+                is_sslv2 = true;
+                paf_state = SSL_PAF_STATES_LEN2_V2;
+            }
+            else 
+            {
+                // unknown
+                if (last_fp > 0)
+                {
+                    // stop here and flush out the good records
+                    // it will come to ABORT on subsequent scan
+                    n = len;
+                }
+                else
+                {
+                    return StreamSplitter::ABORT;
+                }
+            }
+            break;
+        case SSL_PAF_STATES_VER_MJR:
+            paf_state = SSL_PAF_STATES_VER_MNR;
+            break;
+        case SSL_PAF_STATES_VER_MNR:
+            paf_state = SSL_PAF_STATES_LEN1;
+            break;
+        case SSL_PAF_STATES_LEN1:
+            len_bytes[0] = data[n];
+            paf_state = SSL_PAF_STATES_LEN2;
+            break;
+        case SSL_PAF_STATES_LEN2:
+            len_bytes[1] = data[n];
+            remain_len = (len_bytes[0] << 8) + len_bytes[1];
+            if (remain_len == 0)
+            {
+                last_fp = n;
+                paf_state = SSL_PAF_STATES_START;
+            }
+            else
+            {
+                paf_state = SSL_PAF_STATES_DATA;
+            }
+            break;
+        case SSL_PAF_STATES_DATA:
+            skip_len = ((len-n) > remain_len) ? remain_len : (len - n);
+            remain_len -= skip_len;
+            n += skip_len;
+            if (remain_len == 0)
+            {
+                last_fp = n;
+                paf_state = SSL_PAF_STATES_START;
+            }
+            n--;
+            break;
+        case SSL_PAF_STATES_LEN2_V2:
+            len_bytes[1] = data[n];
+            if (len_bytes[0] & 0x80)
+            {
+                // sslv2 using 2-byte length
+                len_bytes[0] = len_bytes[0] & 0x7F;
+                paf_state = SSL_PAF_STATES_DATA;
+            }
+            else
+            {
+                // sslv2 using 3-byte length
+                len_bytes[0] = len_bytes[0] & 0x3F;
+                paf_state = SSL_PAF_STATES_PAD_V2;
+            }
+            remain_len = (len_bytes[0] << 8) + len_bytes[1];
+            break;
+        case SSL_PAF_STATES_PAD_V2:
+            paf_state = SSL_PAF_STATES_DATA;
+            break;
+        }
+
+        n++;
+    }
+    // if a flush point was found, flush from there
+    if (last_fp > 0)
+    {
+        *fp = last_fp;
+        remain_len = 0;
+        paf_state = SSL_PAF_STATES_START;
+        return StreamSplitter::FLUSH;
+    }
+
+    return StreamSplitter::SEARCH;
+}
+
diff --git a/src/service_inspectors/ssl/ssl_splitter.h b/src/service_inspectors/ssl/ssl_splitter.h
new file mode 100644 (file)
index 0000000..0ceaaf9
--- /dev/null
@@ -0,0 +1,67 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2017-2017 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// ssl_splitter.h author Steven Baigal <sbaigal@cisco.com>
+
+#ifndef SSL_SPLITTER_H
+#define SSL_SPLITTER_H
+
+// Protocol aware flushing for SSL
+// TLSPlaintext records are flushed when end-of-record meets end-of segment
+// The splitter supports both sslv2 and sslv3 record format, 
+// it starts by checking the first byte, if it is a valid sslv3 content type, 
+// mark the session as sslv3; else if the MSB bit was set, marks it as sslv2,
+// if this bit is not set, yet the session was marked sslv2 from prior detection,
+// continue as sslv2
+
+#include "stream/stream_splitter.h"
+
+// Enumerations for PAF states
+enum SslPafStates
+{
+    SSL_PAF_STATES_START = 0, //start, detect the ssl version, sslv3 type or sslv2 byte-0
+    SSL_PAF_STATES_VER_MJR, // version major
+    SSL_PAF_STATES_VER_MNR, // version minor
+    SSL_PAF_STATES_LEN1,    // length byte-0
+    SSL_PAF_STATES_LEN2,    // length byte-1
+    SSL_PAF_STATES_DATA,    // fragment
+    SSL_PAF_STATES_LEN2_V2, // sslv2, length byte-1
+    SSL_PAF_STATES_PAD_V2,  // sslv2, padding byte if needed 
+};
+
+class SslSplitter : public StreamSplitter
+{
+public:
+    SslSplitter(bool c2s);
+
+    Status scan(Flow*, const uint8_t* data, uint32_t len,
+        uint32_t flags, uint32_t* fp) override;
+
+    bool is_paf() override
+    {
+        return true;
+    }
+
+private:
+    SslPafStates paf_state;
+    uint16_t remain_len;
+    uint8_t len_bytes[2]; // temporary buffer to hold 2-byte length field
+    bool is_sslv2;
+};
+
+#endif