]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2792 in SNORT/snort3 from ~SMINUT/snort3:smbfp to master
authorMasud Hasan (mashasan) <mashasan@cisco.com>
Tue, 23 Mar 2021 16:17:01 +0000 (16:17 +0000)
committerMasud Hasan (mashasan) <mashasan@cisco.com>
Tue, 23 Mar 2021 16:17:01 +0000 (16:17 +0000)
Squashed commit of the following:

commit 727fcef5b3952eb13f895e3ea8fbb0075c4366d8
Author: Silviu Minut <sminut@cisco.com>
Date:   Thu Mar 11 15:43:57 2021 -0500

    appid: smb fingerprinting support

    rna: smb fingerprint support

26 files changed:
src/host_tracker/host_tracker.cc
src/host_tracker/host_tracker.h
src/network_inspectors/appid/appid_session.h
src/network_inspectors/appid/service_plugins/service_netbios.cc
src/network_inspectors/appid/service_plugins/service_netbios.h
src/network_inspectors/appid/service_plugins/test/CMakeLists.txt
src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h
src/network_inspectors/rna/CMakeLists.txt
src/network_inspectors/rna/rna_app_discovery.cc
src/network_inspectors/rna/rna_app_discovery.h
src/network_inspectors/rna/rna_config.h
src/network_inspectors/rna/rna_event_handler.cc
src/network_inspectors/rna/rna_event_handler.h
src/network_inspectors/rna/rna_fingerprint.h
src/network_inspectors/rna/rna_fingerprint_smb.cc [new file with mode: 0644]
src/network_inspectors/rna/rna_fingerprint_smb.h [new file with mode: 0644]
src/network_inspectors/rna/rna_flow.cc
src/network_inspectors/rna/rna_flow.h
src/network_inspectors/rna/rna_inspector.cc
src/network_inspectors/rna/rna_module.cc
src/network_inspectors/rna/rna_module.h
src/network_inspectors/rna/rna_pnd.cc
src/network_inspectors/rna/rna_pnd.h
src/network_inspectors/rna/test/rna_module_mock.h
src/pub_sub/CMakeLists.txt
src/pub_sub/smb_events.h [new file with mode: 0644]

index 2780401acc0a1869dab0c3162daefdaa0256a703..7b3dac42222a0df7b8a37d96063eb176b42f9d32 100644 (file)
@@ -800,6 +800,13 @@ bool HostTracker::set_netbios_name(const char* nb_name)
         return false;
 }
 
+bool HostTracker::add_smb_fingerprint(uint32_t fpid)
+{
+    lock_guard<mutex> lck(host_tracker_lock);
+    auto result = smb_fpids.emplace(fpid);
+    return result.second;
+}
+
 bool HostTracker::set_visibility(bool v)
 {
     // get_valid_id may use its own lock, so get this outside our lock
@@ -1279,6 +1286,14 @@ void HostTracker::stringify(string& str)
             str += to_string(fpid) + (--total ? ", " : "");
     }
 
+    total = smb_fpids.size();
+    if ( total )
+    {
+        str += "\nsmb fingerprint: ";
+        for ( const auto& fpid : smb_fpids )
+            str += to_string(fpid) + (--total ? ", " : "");
+    }
+
     if ( !netbios_name.empty() )
         str += "\nnetbios name: " + netbios_name;
 }
index b1cf2a6dea62e4cf840bdbb9dc5c2367f4f27a6d..72ffb3df42e6ebdbec377199d0b164fab120396d 100644 (file)
@@ -336,6 +336,7 @@ public:
     bool add_ua_fingerprint(uint32_t fpid, uint32_t fp_type, bool jail_broken,
         const char* device_info, uint8_t max_devices);
     bool add_udp_fingerprint(uint32_t fpid);
+    bool add_smb_fingerprint(uint32_t fpid);
 
     //  This should be updated whenever HostTracker data members are changed
     void stringify(std::string& str);
@@ -431,6 +432,7 @@ private:
     std::vector<HostClient, HostClientAllocator> clients;
     std::set<uint32_t, std::less<uint32_t>, HostCacheAllocIp<uint32_t>> tcp_fpids;
     std::set<uint32_t, std::less<uint32_t>, HostCacheAllocIp<uint32_t>> udp_fpids;
+    std::set<uint32_t, std::less<uint32_t>, HostCacheAllocIp<uint32_t>> smb_fpids;
     std::vector<DeviceFingerprint, HostDeviceFpAllocator> ua_fps;
     std::string netbios_name;
 
index b62ad024c2b191693135af4ff09dc969199a2e65..a2ae5e59255b61086bd6ca4c11034e6ba2a1d8f9 100644 (file)
@@ -65,7 +65,6 @@ const uint8_t* service_strstr(const uint8_t* haystack, unsigned haystack_len,
 #define MAX_SFTP_PACKET_COUNT   55
 
 #define APPID_SESSION_DATA_NONE                  0
-#define APPID_SESSION_DATA_SMB_DATA              4
 #define APPID_SESSION_DATA_SERVICE_MODSTATE_BIT  0x20000000
 #define APPID_SESSION_DATA_CLIENT_MODSTATE_BIT   0x40000000
 #define APPID_SESSION_DATA_DETECTOR_MODSTATE_BIT 0x80000000
index 1acd066932fd0c016aef303c24b7ce8a1c4f3941..d8cf9a3031e2360fb4d70635f682449d6a5dc501 100644 (file)
@@ -25,7 +25,9 @@
 
 #include "service_netbios.h"
 
+#include "detection/detection_engine.h"
 #include "protocols/packet.h"
+#include "pub_sub/smb_events.h"
 #include "utils/endian.h"
 
 #include "app_info_table.h"
@@ -1165,27 +1167,12 @@ inprocess:
 void NbdgmServiceDetector::add_smb_info(AppIdSession& asd, unsigned major, unsigned minor,
     uint32_t flags)
 {
-    FpSMBData* sd;
-
     if ( flags & FINGERPRINT_UDP_FLAGS_XENIX )
         return;
     if ( asd.get_session_flags(APPID_SESSION_HAS_SMB_INFO) )
         return;
-    sd = (FpSMBData*)snort_calloc(sizeof(FpSMBData));
-
-    if ( asd.add_flow_data(sd, APPID_SESSION_DATA_SMB_DATA, (AppIdFreeFCN)AppIdFreeSMBData) )
-    {
-        AppIdFreeSMBData(sd);
-        return;
-    }
-
     asd.set_session_flags(APPID_SESSION_HAS_SMB_INFO);
-    sd->major = major;
-    sd->minor = minor;
-    sd->flags = flags & FINGERPRINT_UDP_FLAGS_MASK;
-}
-
-void NbdgmServiceDetector::AppIdFreeSMBData(FpSMBData* sd)
-{
-    snort_free(sd);
+    Packet* p = DetectionEngine::get_current_packet();
+    FpSMBDataEvent event(p, major, minor, (flags & FINGERPRINT_UDP_FLAGS_MASK));
+    DataBus::publish(FP_SMB_DATA_EVENT, event, p->flow);
 }
index 96a1b6b0019ebfe16eba066f55f49f6ca5589e2e..e3fe95280ae601061ab2bdbb225c5d46de1f0b92 100644 (file)
 class AppIdSession;
 class ServiceDiscovery;
 
-struct FpSMBData
-{
-    FpSMBData* next;
-    unsigned major;
-    unsigned minor;
-    uint32_t flags;
-};
-
 class NbssServiceDetector : public ServiceDetector
 {
 public:
@@ -58,8 +50,6 @@ public:
 
     int validate(AppIdDiscoveryArgs&) override;
 
-    static void AppIdFreeSMBData(FpSMBData*);
-
 private:
     void add_smb_info(AppIdSession&, unsigned major, unsigned minor, uint32_t flags);
 };
index 85ef7522f441602214d9f55d03760585cbb5043b..d221dfda36fa2e1ac06799902aed674b878ec245 100644 (file)
@@ -2,5 +2,4 @@
 include_directories ( appid PRIVATE ${APPID_INCLUDE_DIR} )
 
 add_cpputest( service_rsync_test )
-add_cpputest( service_netbios_test )
 
index 8141c59f81d2e6593d6ca90c9eabd3438e588aa9..13f8cdac78c261d09538a2defdc68af5572a99ae 100644 (file)
@@ -80,10 +80,10 @@ AppIdSessionApi::AppIdSessionApi(const AppIdSession*, const SfIp&) :
     StashGenericObject(STASH_GENERIC_OBJECT_APPID) {}
 }
 
-SslPatternMatchers::~SslPatternMatchers() = default;
-SipPatternMatchers::~SipPatternMatchers() = default;
-HttpPatternMatchers::~HttpPatternMatchers() = default;
-DnsPatternMatchers::~DnsPatternMatchers() = default;
+SslPatternMatchers::~SslPatternMatchers() { }
+SipPatternMatchers::~SipPatternMatchers() { }
+HttpPatternMatchers::~HttpPatternMatchers() { }
+DnsPatternMatchers::~DnsPatternMatchers() { }
 void ClientDiscovery::initialize(AppIdInspector&) {}
 void ClientDiscovery::reload() {}
 FpSMBData* smb_data = nullptr;
@@ -110,18 +110,9 @@ void AppIdDiscovery::register_udp_pattern(AppIdDetector*, const uint8_t* const,
     int, unsigned){}
 int AppIdDiscovery::add_service_port(AppIdDetector*, const ServiceDetectorPort&){return 0;}
 void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&){}
-int AppIdSession::add_flow_data(void* data, unsigned type, AppIdFreeFCN)
-{
-    if ( type == APPID_SESSION_DATA_SMB_DATA )
-    {
-        smb_data = (FpSMBData*)data;
-        set_session_flags(APPID_SESSION_HAS_SMB_INFO);
-    }
-    return 0;
-}
-
+int AppIdSession::add_flow_data(void*, unsigned, AppIdFreeFCN) { return 0; }
 int dcerpc_validate(const uint8_t*, int){return 0; }
-AppIdDiscovery::~AppIdDiscovery() = default;
+AppIdDiscovery::~AppIdDiscovery() { }
 void show_stats(PegCount*, const PegInfo*, unsigned, const char*) { }
 void show_stats(PegCount*, const PegInfo*, const IndexVec&, const char*, FILE*) { }
 AppIdConfig config;
index 54854381404a12773f60f9429d6cded63415b079..df05ffaef592abbcb9487be331416532410726a1 100644 (file)
@@ -1,5 +1,6 @@
 set (RNA_INCLUDES
     rna_fingerprint.h
+    rna_fingerprint_smb.h
     rna_fingerprint_tcp.h
     rna_fingerprint_ua.h
     rna_fingerprint_udp.h
@@ -18,6 +19,7 @@ set ( RNA_SOURCES
     rna_event_handler.cc
     rna_event_handler.h
     rna_fingerprint.cc
+    rna_fingerprint_smb.cc
     rna_fingerprint_tcp.cc
     rna_fingerprint_ua.cc
     rna_fingerprint_udp.cc
index cb73033e7d21884a793045650852aeafd25423fb..a41ccb47265cbe6cf167f046c8a476c74d91d18a 100644 (file)
@@ -383,23 +383,10 @@ void RnaAppDiscovery::discover_user(const Packet* p, DiscoveryFilter& filter, RN
     RnaLogger& logger, const char* username, AppId service, IpProtocol proto, RnaConfig* conf,
     bool login_success)
 {
-    RnaTracker rt;
-    if ( p->is_from_server() )
-    {
-        if ( !filter.is_host_monitored(p, nullptr, nullptr, FlowCheckDirection::DF_SERVER) )
-            return;
-        rt = get_server_rna_tracker(p, rna_flow);
-    }
-    else
-    {
-        if ( !filter.is_host_monitored(p, nullptr, nullptr, FlowCheckDirection::DF_CLIENT) )
-            return;
-        rt = get_client_rna_tracker(p, rna_flow);
-    }
-
+    assert(rna_flow);
+    RnaTracker rt = rna_flow->get_tracker(p, filter);
     if ( !rt or !rt->is_visible() )
         return;
-    rt->update_last_seen();
 
     if ( rt->update_service_user(p->flow->server_port, proto, username,
         (uint32_t) packet_time(), conf ? conf->max_host_services : 0, login_success) )
@@ -413,23 +400,9 @@ void RnaAppDiscovery::discover_user(const Packet* p, DiscoveryFilter& filter, RN
 void RnaAppDiscovery::discover_netbios_name(const snort::Packet* p, DiscoveryFilter& filter,
     RNAFlow* rna_flow, RnaLogger& logger, const char* nb_name)
 {
-    RnaTracker rt;
-    if ( p->is_from_server() )
-    {
-        if ( !filter.is_host_monitored(p, nullptr, nullptr, FlowCheckDirection::DF_SERVER) )
-            return;
-        rt = get_server_rna_tracker(p, rna_flow);
-    }
-    else
-    {
-        if ( !filter.is_host_monitored(p, nullptr, nullptr, FlowCheckDirection::DF_CLIENT) )
-            return;
-        rt = get_client_rna_tracker(p, rna_flow);
-    }
-
-    if ( !rt or !rt->is_visible() )
+    RnaTracker rt = rna_flow->get_tracker(p, filter);
+    if ( !rt or !rt->is_visible())
         return;
-    rt->update_last_seen();
 
     if ( rt->set_netbios_name(nb_name) )
     {
index 67731ac30e7353ef883eda64036b02081d7210bb..70c39e68696a46998bb5bf75bf580b6bed97004c 100644 (file)
@@ -46,6 +46,9 @@ public:
     static void discover_netbios_name(const snort::Packet*, DiscoveryFilter&,
         RNAFlow*, RnaLogger&, const char*);
 
+    static RnaTracker get_server_rna_tracker(const snort::Packet*, RNAFlow*);
+    static RnaTracker get_client_rna_tracker(const snort::Packet*, RNAFlow*);
+
 private:
     static void update_service_info(const snort::Packet*, DiscoveryFilter&, RNAFlow*, IpProtocol,
         uint16_t, const char* vendor, const char* version, RnaLogger&, RnaConfig*, AppId service,
@@ -54,8 +57,6 @@ private:
     static void analyze_user_agent_fingerprint(const snort::Packet*, DiscoveryFilter&, RNAFlow*,
         const char* host, const char* uagent, RnaLogger&, snort::UaFpProcessor&);
 
-    static RnaTracker get_server_rna_tracker(const snort::Packet*, RNAFlow*);
-    static RnaTracker get_client_rna_tracker(const snort::Packet*, RNAFlow*);
 };
 
 #endif
index 98729c125930bb28c5b90c8a30eab5d45838784e..d8e86c8db23b009ebf280241030d1a5ea078bbbc 100644 (file)
@@ -26,6 +26,7 @@ namespace snort
 class TcpFpProcessor;
 class UaFpProcessor;
 class UdpFpProcessor;
+class SmbFpProcessor;
 }
 
 struct RnaModuleConfig
@@ -36,6 +37,7 @@ struct RnaModuleConfig
     snort::TcpFpProcessor* tcp_processor = nullptr;
     snort::UaFpProcessor* ua_processor = nullptr;
     snort::UdpFpProcessor* udp_processor = nullptr;
+    snort::SmbFpProcessor* smb_processor = nullptr;
 };
 
 // Give default values so that RNA can work even if rna_conf_path is not provided
index 3eb818406d96be57adfd1995f691d72bca401058..2167ee54b4d109bce0f1bb1996b8bdd7a4b3a057 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "rna_event_handler.h"
 #include "pub_sub/dhcp_events.h"
+#include "pub_sub/smb_events.h"
 
 using namespace snort;
 
@@ -118,3 +119,10 @@ void RnaDHCPDataEventHandler::handle(DataEvent& event, Flow*)
     ++rna_stats.dhcp_data;
     pnd.analyze_dhcp_fingerprint(event);
 }
+
+void RnaFpSMBEventHandler::handle(DataEvent& event, Flow*)
+{
+    Profile profile(rna_perf_stats);
+    ++rna_stats.smb;
+    pnd.analyze_smb_fingerprint(event);
+}
index 8bfb59600d4663d915f46b6f61b14bd1b5f51f4a..e85f4ce90310a2297f5a03ceac6564c583f2beb1 100644 (file)
@@ -144,4 +144,13 @@ private:
     RnaPnd& pnd;
 };
 
+class RnaFpSMBEventHandler : public snort::DataHandler
+{
+public:
+    RnaFpSMBEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
+    void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
+};
+
 #endif
index 2dc37f153cd394b1473d64f54635a64d59d5f4f2..93961223bc720239631c4d2a98dd332062c8c804 100644 (file)
@@ -147,6 +147,10 @@ public:
     std::string dhcp55;
     std::string dhcp60;
 
+    int16_t smb_major;
+    int16_t smb_minor;
+    uint32_t smb_flags;
+
     void clear()
     {
         fpid = 0;
@@ -165,6 +169,9 @@ public:
         device.clear();
         dhcp55.clear();
         dhcp60.clear();
+        smb_major = 0;
+        smb_minor = 0;
+        smb_flags=0;
     }
 };
 
diff --git a/src/network_inspectors/rna/rna_fingerprint_smb.cc b/src/network_inspectors/rna/rna_fingerprint_smb.cc
new file mode 100644 (file)
index 0000000..3f25c79
--- /dev/null
@@ -0,0 +1,124 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 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.
+//--------------------------------------------------------------------------
+
+// rna_fingerprint_smb.cc author Silviu Minut <sminut@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rna_fingerprint_smb.h"
+
+#include <sstream>
+
+#ifdef UNIT_TEST
+#include "catch/snort_catch.h"
+#endif
+
+#include "log/messages.h"
+
+using namespace snort;
+using namespace std;
+
+static THREAD_LOCAL SmbFpProcessor* smb_fp_processor = nullptr;
+
+SmbFpProcessor* get_smb_fp_processor()
+{
+    return smb_fp_processor;
+}
+
+void set_smb_fp_processor(SmbFpProcessor* processor)
+{
+    smb_fp_processor = processor;
+}
+
+namespace snort
+{
+
+SmbFingerprint::SmbFingerprint(unsigned maj, unsigned min, uint32_t f)
+    : major(maj), minor(min), flags(f) { }
+
+SmbFingerprint::SmbFingerprint(const RawFingerprint& rfp)
+{
+    fpid = rfp.fpid;
+    fp_type = rfp.fp_type;
+    fpuuid = rfp.fpuuid;
+    ttl = rfp.ttl;
+
+    major = rfp.smb_major;
+    minor = rfp.smb_minor;
+    flags = rfp.smb_flags;
+}
+
+bool SmbFingerprint::operator==(const SmbFingerprint& y) const
+{
+    return ((fpid == y.fpid) &&
+        (fp_type == y.fp_type) &&
+        (fpuuid == y.fpuuid) &&
+        (ttl == y.ttl) &&
+        (major == y.major) &&
+        (minor == y.minor) &&
+        (flags == y.flags) );
+}
+
+bool SmbFpProcessor::push(const SmbFingerprint& sfp)
+{
+    auto result = smb_fps.emplace(sfp);
+    if (!result.second)
+        WarningMessage("SmbFpProcessor: ignoring previously seen fingerprint id: %d\n", sfp.fpid);
+    return result.second;
+}
+
+const SmbFingerprint* SmbFpProcessor::find(const SmbFingerprint& key) const
+{
+    const auto& it = smb_fps.find(key);
+    return it != smb_fps.end() ? &(*it) : nullptr;
+}
+
+}
+
+#ifdef UNIT_TEST
+
+TEST_CASE("get_smb_fp_processor", "[rna_fingerprint_smb]")
+{
+    SmbFpProcessor smb_processor;
+    set_smb_fp_processor(&smb_processor);
+
+    SmbFpProcessor* processor = get_smb_fp_processor();
+    CHECK(processor == &smb_processor);
+
+    unsigned major = 6;
+    unsigned minor = 4;
+    uint32_t flags = 4096;
+    SmbFingerprint fp(major, minor, flags);
+    processor->push(fp);
+
+    // positive test:
+    const SmbFingerprint* fpptr = processor->find({major, minor, flags});
+    CHECK(fpptr != nullptr);
+    CHECK(*fpptr == fp);
+
+    // negative test:
+    fpptr = processor->find({0, 0, 0});
+    CHECK(fpptr == nullptr);
+
+    set_smb_fp_processor(nullptr);
+    CHECK(smb_fp_processor == nullptr);
+}
+
+#endif
diff --git a/src/network_inspectors/rna/rna_fingerprint_smb.h b/src/network_inspectors/rna/rna_fingerprint_smb.h
new file mode 100644 (file)
index 0000000..6b325f5
--- /dev/null
@@ -0,0 +1,93 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 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.
+//--------------------------------------------------------------------------
+
+// rna_fingerprint_smb.h author Silviu Minut <sminut@cisco.com>
+
+#ifndef RNA_FINGERPRINT_SMB_H
+#define RNA_FINGERPRINT_SMB_H
+
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+#include "main/snort_types.h"
+#include "protocols/packet.h"
+#include "protocols/tcp.h"
+#include "sfip/sf_ip.h"
+
+#include "rna_fingerprint.h"
+
+class RNAFlow;
+
+namespace snort
+{
+
+class SO_PUBLIC SmbFingerprint : public FpFingerprint
+{
+public:
+
+    SmbFingerprint(unsigned maj = 0, unsigned min = 0, uint32_t f = 0);
+    SmbFingerprint(const RawFingerprint& rfp);
+
+    unsigned major;
+    unsigned minor;
+    uint32_t flags;
+
+    bool operator==(const SmbFingerprint& y) const;
+};
+
+class SO_PUBLIC SmbFpProcessor
+{
+public:
+
+    struct SmbFpHash
+    {
+        size_t operator()(const SmbFingerprint & key) const noexcept
+        {
+            std::hash<decltype(SmbFingerprint::major)> hm;
+            std::hash<decltype(SmbFingerprint::flags)> hf;
+            auto const h = hm(key.major) ^ (hm(key.minor) << 1) ^ (hf(key.flags) << 2);
+            return h;
+        }
+    };
+
+    struct SmbEqTo
+    {
+        bool operator() (const SmbFingerprint& x, const SmbFingerprint& y) const
+        {
+            return x.major == y.major && x.minor == y.minor && x.flags == y.flags;
+        }
+    };
+
+    typedef std::unordered_set<SmbFingerprint, SmbFpHash, SmbEqTo> SmbFpContainer;
+    typedef SmbFpContainer::const_iterator SmbFpIter;
+
+    bool push(const SmbFingerprint&);
+    const SmbFingerprint* find(const SmbFingerprint& ) const;
+
+private:
+
+    SmbFpContainer smb_fps;
+};
+
+}
+
+snort::SmbFpProcessor* get_smb_fp_processor();
+SO_PUBLIC void set_smb_fp_processor(snort::SmbFpProcessor*);
+
+#endif
index f155f298dd02ac3e1134b80e05b9bf2c6ec8c233..95d97167c90c30f4598b9ea331afab366b8284fd 100644 (file)
 
 #include "rna_flow.h"
 
+#include "helpers/discovery_filter.h"
 #include "host_tracker/host_cache.h"
+#include "protocols/packet.h"
+
+#ifdef UNIT_TEST
+#include "catch/snort_catch.h"
+#endif
 
 using namespace snort;
 using namespace std;
@@ -80,6 +86,19 @@ RnaTracker RNAFlow::get_client(const SfIp& ip)
     return loc_ht;
 }
 
+RnaTracker RNAFlow::get_tracker(const Packet* p, DiscoveryFilter& filter)
+{
+    RnaTracker rt;
+    if ( p->is_from_server() && filter.is_host_monitored(p, nullptr, nullptr, FlowCheckDirection::DF_SERVER) )
+        rt = get_server(p->flow->server_ip);
+    else if (p->is_from_client() && filter.is_host_monitored(p, nullptr, nullptr, FlowCheckDirection::DF_CLIENT) )
+        rt = get_client(p->flow->server_ip);
+
+    if ( rt && rt->is_visible() )
+        rt->update_last_seen();
+    return rt;
+}
+
 void RNAFlow::set_server(RnaTracker& ht)
 {
     rna_mutex.lock();
@@ -93,3 +112,48 @@ void RNAFlow::set_client(RnaTracker& ht)
     clientht = ht;
     rna_mutex.unlock();
 }
+
+
+#ifdef UNIT_TEST
+
+TEST_CASE("RNA Flow", "[get_tracker]")
+{
+    timeval curr_time;
+    Packet p;
+    Flow flow;
+    p.flow=&flow;
+
+    DiscoveryFilter filter("");
+    RnaTracker ht(new HostTracker);
+
+    RNAFlow::init();
+    RNAFlow* rna_flow = new RNAFlow();
+    p.flow->set_flow_data(rna_flow);
+
+    RnaTracker rt;
+    uint32_t last_seen;
+
+    // test the server path
+    curr_time.tv_sec = 12345678;
+    packet_time_update(&curr_time);
+    p.packet_flags = PKT_FROM_SERVER;
+    rna_flow->set_server(ht);
+    rt = rna_flow->get_tracker(&p, filter);
+    CHECK(rt == ht);
+    last_seen = ht->get_last_seen();
+    CHECK(last_seen == curr_time.tv_sec);
+
+    // and the client path
+    curr_time.tv_sec = 23456789;
+    packet_time_update(&curr_time);
+    p.packet_flags = PKT_FROM_CLIENT;
+    rna_flow->set_client(ht);
+    rt = rna_flow->get_tracker(&p, filter);
+    CHECK(rt == ht);
+    last_seen = ht->get_last_seen();
+    CHECK(last_seen == curr_time.tv_sec);
+
+    flow.free_flow_data();
+}
+
+#endif
index 4bfd0373fef40a1afaed674187e6bc226d5c9986..8af1e8d8a0803afe80f9d0d51716fdbd1cc91801 100644 (file)
 
 #include "rna_fingerprint_tcp.h"
 
+namespace snort
+{
+struct Packet;
+}
+
+class DiscoveryFilter;
+
 using RnaTracker = std::shared_ptr<snort::HostTracker>;
 
 class RNAFlow : public snort::FlowData
@@ -53,6 +60,7 @@ public:
 
     RnaTracker get_server(const snort::SfIp&);
     RnaTracker get_client(const snort::SfIp&);
+    RnaTracker get_tracker(const snort::Packet*, DiscoveryFilter&);
 
     void set_server(RnaTracker& ht);
     void set_client(RnaTracker& ht);
index 2c64ca8de983d6468d49a4ea8bc38da3583b62c3..02f986d9ec8d7347464ddcdec632dd64e0402cc2 100644 (file)
 #include "managers/inspector_manager.h"
 #include "protocols/packet.h"
 #include "pub_sub/dhcp_events.h"
+#include "pub_sub/smb_events.h"
 
 #include "rna_event_handler.h"
+#include "rna_fingerprint_smb.h"
 #include "rna_fingerprint_tcp.h"
 #include "rna_fingerprint_ua.h"
 #include "rna_fingerprint_udp.h"
@@ -79,6 +81,7 @@ RnaInspector::~RnaInspector()
         delete mod_conf->tcp_processor;
         delete mod_conf->ua_processor;
         delete mod_conf->udp_processor;
+        delete mod_conf->smb_processor;
         delete mod_conf;
     }
 }
@@ -88,6 +91,7 @@ bool RnaInspector::configure(SnortConfig* sc)
     DataBus::subscribe_global( APPID_EVENT_ANY_CHANGE, new RnaAppidEventHandler(*pnd), sc );
     DataBus::subscribe_global( DHCP_INFO_EVENT, new RnaDHCPInfoEventHandler(*pnd), sc);
     DataBus::subscribe_global( DHCP_DATA_EVENT, new RnaDHCPDataEventHandler(*pnd), sc);
+    DataBus::subscribe_global( FP_SMB_DATA_EVENT, new RnaFpSMBEventHandler(*pnd), sc);
 
     DataBus::subscribe_global( STREAM_ICMP_NEW_FLOW_EVENT, new RnaIcmpNewFlowEventHandler(*pnd), sc );
     DataBus::subscribe_global( STREAM_ICMP_BIDIRECTIONAL_EVENT, new RnaIcmpBidirectionalEventHandler(*pnd), sc );
@@ -149,6 +153,7 @@ void RnaInspector::tinit()
     set_tcp_fp_processor(mod_conf->tcp_processor);
     set_ua_fp_processor(mod_conf->ua_processor);
     set_udp_fp_processor(mod_conf->udp_processor);
+    set_smb_fp_processor(mod_conf->smb_processor);
     set_host_cache_mac(host_cache_mac_ptr);
 }
 
index a0affe31282454305bae72cf8ee297c9e84a28a2..3775f4e12b7fe4dad531f1b478362470da841e0a 100644 (file)
@@ -41,6 +41,7 @@
 #include "utils/util.h"
 
 #include "data_purge_cmd.h"
+#include "rna_fingerprint_smb.h"
 #include "rna_fingerprint_tcp.h"
 #include "rna_fingerprint_ua.h"
 #include "rna_fingerprint_udp.h"
@@ -326,6 +327,15 @@ static const Parameter rna_fp_params[] =
     { "dhcp60", Parameter::PT_STRING, nullptr, nullptr,
       "dhcp option 60 values" },
 
+    { "major", Parameter::PT_INT, "0:max31", nullptr,
+      "smb major version" },
+
+    { "minor", Parameter::PT_INT, "0:max31", nullptr,
+      "smb minor version" },
+
+    { "flags", Parameter::PT_INT, "0:max32", nullptr,
+      "smb flags" },
+
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
@@ -352,6 +362,9 @@ static const Parameter rna_params[] =
     { "udp_fingerprints", Parameter::PT_LIST, rna_fp_params, nullptr,
       "list of udp fingerprints" },
 
+    { "smb_fingerprints", Parameter::PT_LIST, rna_fp_params, nullptr,
+      "list of smb fingerprints" },
+
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
@@ -371,6 +384,7 @@ static const PegInfo rna_pegs[] =
     { CountType::SUM, "change_host_update", "count number of change host update events" },
     { CountType::SUM, "dhcp_data", "count of DHCP data events received" },
     { CountType::SUM, "dhcp_info", "count of new DHCP lease events received" },
+    { CountType::SUM, "smb", "count of new SMB events received" },
     { CountType::END, nullptr, nullptr},
 };
 
@@ -418,6 +432,12 @@ bool RnaModule::begin(const char* fqn, int, SnortConfig*)
         if (!mod_conf->udp_processor)
             mod_conf->udp_processor = new UdpFpProcessor;
     }
+    else if (!strcmp(fqn, "rna.smb_fingerprints"))
+    {
+        fingerprint.clear();
+        if (!mod_conf->smb_processor)
+            mod_conf->smb_processor = new SmbFpProcessor;
+    }
 
     return true;
 }
@@ -437,7 +457,8 @@ bool RnaModule::set(const char* fqn, Value& v, SnortConfig*)
         dump_file = snort_strdup(v.get_string());
     }
     else if ( fqn and ( strstr(fqn, "rna.tcp_fingerprints") or
-        strstr(fqn, "rna.ua_fingerprints") or strstr(fqn, "rna.udp_fingerprints") ) )
+        strstr(fqn, "rna.ua_fingerprints") or strstr(fqn, "rna.udp_fingerprints")
+        or strstr(fqn, "rna.smb_fingerprints") ) )
     {
         if (v.is("fpid"))
             fingerprint.fpid = v.get_uint32();
@@ -478,6 +499,12 @@ bool RnaModule::set(const char* fqn, Value& v, SnortConfig*)
             fingerprint.dhcp55 = v.get_string();
         else if (v.is("dhcp60"))
             fingerprint.dhcp60 = v.get_string();
+        else if (v.is("major"))
+            fingerprint.smb_major = v.get_int16();
+        else if (v.is("minor"))
+            fingerprint.smb_minor = v.get_int16();
+        else if (v.is("flags"))
+            fingerprint.smb_flags = v.get_uint32();
         else
             return false;
     }
@@ -510,6 +537,7 @@ bool RnaModule::end(const char* fqn, int index, SnortConfig* sc)
 
         if ( mod_conf->ua_processor )
             mod_conf->ua_processor->make_mpse(sc);
+
     }
 
     if ( index > 0 and mod_conf->tcp_processor and !strcmp(fqn, "rna.tcp_fingerprints") )
@@ -529,6 +557,11 @@ bool RnaModule::end(const char* fqn, int index, SnortConfig* sc)
         mod_conf->udp_processor->push(fingerprint);
         fingerprint.clear();
     }
+    else if ( index > 0 and mod_conf->smb_processor and !strcmp(fqn, "rna.smb_fingerprints") )
+    {
+        mod_conf->smb_processor->push(fingerprint);
+        fingerprint.clear();
+    }
 
     return true;
 }
@@ -607,7 +640,7 @@ bool RnaModule::is_valid_fqn(const char* fqn) const
 {
     return !strcmp(fqn, RNA_NAME) or !strcmp(fqn, "rna.tcp_fingerprints") or
         !strcmp(fqn, "rna.ua_fingerprints") or !strcmp(fqn, "rna.ua_fingerprints.user_agent") or
-        !strcmp(fqn, "rna.udp_fingerprints");
+        !strcmp(fqn, "rna.udp_fingerprints") or !strcmp(fqn, "rna.smb_fingerprints");
 }
 
 
index 09a0e00d93ac8cedb0f2bebc90736ac832ad4b8b..3aa935dea467e4cec8156c05afca8ef4f5a400b1 100644 (file)
@@ -47,6 +47,7 @@ struct RnaStats
     PegCount change_host_update;
     PegCount dhcp_data;
     PegCount dhcp_info;
+    PegCount smb;
 };
 
 extern THREAD_LOCAL RnaStats rna_stats;
index 62585b4fbf1d5eedb333b7c00ef2e7e2fe27c40b..286dc8399d21cd0c21e5376a515cfd79fe99745d 100644 (file)
@@ -37,6 +37,7 @@
 #include "protocols/protocol_ids.h"
 
 #include "rna_app_discovery.h"
+#include "rna_fingerprint_smb.h"
 #include "rna_fingerprint_tcp.h"
 #include "rna_fingerprint_udp.h"
 #include "rna_flow.h"
@@ -343,6 +344,38 @@ void RnaPnd::add_dhcp_info(DataEvent& event)
         lease, net_mask, (const struct in6_addr*) router_ip.get_ip6_ptr());
 }
 
+void RnaPnd::analyze_smb_fingerprint(DataEvent& event)
+{
+    const SmbFpProcessor* processor = get_smb_fp_processor();
+    if (!processor)
+        return;
+
+    const Packet* p = event.get_packet();
+    RNAFlow* rna_flow = (RNAFlow*) p->flow->get_flow_data(RNAFlow::inspector_id);
+    if ( !rna_flow )
+        return;
+
+    RnaTracker rt = rna_flow->get_tracker(p, filter);
+    if ( !rt or !rt->is_visible() )
+        return;
+
+    const FpSMBDataEvent& fp_smb_data_event = static_cast<FpSMBDataEvent&>(event);
+    unsigned major = fp_smb_data_event.get_fp_smb_major();
+    unsigned minor = fp_smb_data_event.get_fp_smb_minor();
+    uint32_t flags = fp_smb_data_event.get_fp_smb_flags();
+
+    const SmbFingerprint* fp = processor->find({major, minor, flags});
+
+    if ( fp && rt->add_smb_fingerprint(fp->fpid) )
+    {
+        const auto& src_ip = p->ptrs.ip_api.get_src();
+        const auto& src_ip_ptr = (const struct in6_addr*) src_ip->get_ip6_ptr();
+        const auto& src_mac = layer::get_eth_layer(p)->ether_src;
+
+        logger.log(RNA_EVENT_NEW, NEW_OS, p, &rt, src_ip_ptr, src_mac, fp, packet_time());
+    }
+}
+
 inline void RnaPnd::update_vlan(const Packet* p, HostTrackerMac& hm)
 {
     if ( !(p->proto_bits & PROTO_BIT__VLAN) )
@@ -956,4 +989,5 @@ TEST_CASE("RNA pnd", "[non-ip]")
         CHECK(is_eligible_packet(&p) == true);
     }
 }
+
 #endif
index af76e6e01965d1be58b1ee42807bc55f49c6e08b..326051124c76064025cfee13f75431b6c295e991 100644 (file)
@@ -31,6 +31,7 @@
 #include "protocols/vlan.h"
 #include "pub_sub/appid_events.h"
 #include "pub_sub/dhcp_events.h"
+#include "pub_sub/smb_events.h"
 #include "sfip/sf_ip.h"
 
 #include "rna_config.h"
@@ -128,6 +129,7 @@ public:
     void analyze_flow_udp(const snort::Packet*);
     void analyze_dhcp_fingerprint(snort::DataEvent&);
     void add_dhcp_info(snort::DataEvent&);
+    void analyze_smb_fingerprint(snort::DataEvent&);
 
     // generate change event for all hosts in the ip cache
     void generate_change_host_update();
index 46cf49b2d7f5833e070690e4ce2c48eb7d6f0166..4a93af7c3ed101d2e9a858936669b683a1fbfa2e 100644 (file)
@@ -76,6 +76,10 @@ void UaFpProcessor::push(RawFingerprint const&) { }
 
 void UdpFpProcessor::push(RawFingerprint const&) { }
 
+SmbFingerprint::SmbFingerprint(const RawFingerprint&) { }
+bool SmbFingerprint::operator==(const SmbFingerprint&) const { return true; }
+bool SmbFpProcessor::push(SmbFingerprint const&) { return true; }
+
 // inspector
 class RnaInspector
 {
index f319a71e817dd18e995edc3ac20692d8a22e3366..04ebfddb1d909ba817b1393b2ef1865477096e19 100644 (file)
@@ -10,6 +10,7 @@ set (PUB_SUB_INCLUDES
     http_events.h
     opportunistic_tls_event.h
     sip_events.h
+    smb_events.h
 )
 
 add_library( pub_sub OBJECT
diff --git a/src/pub_sub/smb_events.h b/src/pub_sub/smb_events.h
new file mode 100644 (file)
index 0000000..68d6008
--- /dev/null
@@ -0,0 +1,57 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 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.
+//--------------------------------------------------------------------------
+// smb_events.h author Sreeja Athirkandathil Narayanan <sathirka@cisco.com>
+
+#ifndef SMB_EVENTS_H
+#define SMB_EVENTS_H
+
+#include "framework/data_bus.h"
+
+#define FP_SMB_DATA_EVENT "fp_smb_data_event"
+
+namespace snort
+{
+
+class FpSMBDataEvent : public snort::DataEvent
+{
+public:
+    FpSMBDataEvent(const snort::Packet* p, unsigned major, unsigned minor,
+        uint32_t flags) : pkt(p), major_version(major), minor_version(minor), flags(flags) { }
+
+    const snort::Packet* get_packet() override
+    { return pkt; }
+
+    unsigned get_fp_smb_major() const
+    { return major_version; }
+
+    unsigned get_fp_smb_minor() const
+    { return minor_version; }
+
+    uint32_t get_fp_smb_flags() const
+    { return flags; }
+
+private:
+    const snort::Packet* pkt;
+    unsigned major_version;
+    unsigned minor_version;
+    uint32_t flags;
+};
+
+}
+
+#endif // SMB_EVENTS_H