From f49fbbef259d841e46a7eef8b8f6f4d017419e7e Mon Sep 17 00:00:00 2001 From: "Masud Hasan (mashasan)" Date: Tue, 23 Mar 2021 16:17:01 +0000 Subject: [PATCH] Merge pull request #2792 in SNORT/snort3 from ~SMINUT/snort3:smbfp to master Squashed commit of the following: commit 727fcef5b3952eb13f895e3ea8fbb0075c4366d8 Author: Silviu Minut Date: Thu Mar 11 15:43:57 2021 -0500 appid: smb fingerprinting support rna: smb fingerprint support --- src/host_tracker/host_tracker.cc | 15 +++ src/host_tracker/host_tracker.h | 2 + src/network_inspectors/appid/appid_session.h | 1 - .../appid/service_plugins/service_netbios.cc | 23 +--- .../appid/service_plugins/service_netbios.h | 10 -- .../appid/service_plugins/test/CMakeLists.txt | 1 - .../test/service_plugin_mock.h | 21 +-- src/network_inspectors/rna/CMakeLists.txt | 2 + .../rna/rna_app_discovery.cc | 35 +---- .../rna/rna_app_discovery.h | 5 +- src/network_inspectors/rna/rna_config.h | 2 + .../rna/rna_event_handler.cc | 8 ++ .../rna/rna_event_handler.h | 9 ++ src/network_inspectors/rna/rna_fingerprint.h | 7 + .../rna/rna_fingerprint_smb.cc | 124 ++++++++++++++++++ .../rna/rna_fingerprint_smb.h | 93 +++++++++++++ src/network_inspectors/rna/rna_flow.cc | 64 +++++++++ src/network_inspectors/rna/rna_flow.h | 8 ++ src/network_inspectors/rna/rna_inspector.cc | 5 + src/network_inspectors/rna/rna_module.cc | 37 +++++- src/network_inspectors/rna/rna_module.h | 1 + src/network_inspectors/rna/rna_pnd.cc | 34 +++++ src/network_inspectors/rna/rna_pnd.h | 2 + .../rna/test/rna_module_mock.h | 4 + src/pub_sub/CMakeLists.txt | 1 + src/pub_sub/smb_events.h | 57 ++++++++ 26 files changed, 491 insertions(+), 80 deletions(-) create mode 100644 src/network_inspectors/rna/rna_fingerprint_smb.cc create mode 100644 src/network_inspectors/rna/rna_fingerprint_smb.h create mode 100644 src/pub_sub/smb_events.h diff --git a/src/host_tracker/host_tracker.cc b/src/host_tracker/host_tracker.cc index 2780401ac..7b3dac422 100644 --- a/src/host_tracker/host_tracker.cc +++ b/src/host_tracker/host_tracker.cc @@ -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 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; } diff --git a/src/host_tracker/host_tracker.h b/src/host_tracker/host_tracker.h index b1cf2a6de..72ffb3df4 100644 --- a/src/host_tracker/host_tracker.h +++ b/src/host_tracker/host_tracker.h @@ -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 clients; std::set, HostCacheAllocIp> tcp_fpids; std::set, HostCacheAllocIp> udp_fpids; + std::set, HostCacheAllocIp> smb_fpids; std::vector ua_fps; std::string netbios_name; diff --git a/src/network_inspectors/appid/appid_session.h b/src/network_inspectors/appid/appid_session.h index b62ad024c..a2ae5e592 100644 --- a/src/network_inspectors/appid/appid_session.h +++ b/src/network_inspectors/appid/appid_session.h @@ -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 diff --git a/src/network_inspectors/appid/service_plugins/service_netbios.cc b/src/network_inspectors/appid/service_plugins/service_netbios.cc index 1acd06693..d8cf9a303 100644 --- a/src/network_inspectors/appid/service_plugins/service_netbios.cc +++ b/src/network_inspectors/appid/service_plugins/service_netbios.cc @@ -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); } diff --git a/src/network_inspectors/appid/service_plugins/service_netbios.h b/src/network_inspectors/appid/service_plugins/service_netbios.h index 96a1b6b00..e3fe95280 100644 --- a/src/network_inspectors/appid/service_plugins/service_netbios.h +++ b/src/network_inspectors/appid/service_plugins/service_netbios.h @@ -27,14 +27,6 @@ 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); }; diff --git a/src/network_inspectors/appid/service_plugins/test/CMakeLists.txt b/src/network_inspectors/appid/service_plugins/test/CMakeLists.txt index 85ef7522f..d221dfda3 100644 --- a/src/network_inspectors/appid/service_plugins/test/CMakeLists.txt +++ b/src/network_inspectors/appid/service_plugins/test/CMakeLists.txt @@ -2,5 +2,4 @@ include_directories ( appid PRIVATE ${APPID_INCLUDE_DIR} ) add_cpputest( service_rsync_test ) -add_cpputest( service_netbios_test ) diff --git a/src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h b/src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h index 8141c59f8..13f8cdac7 100644 --- a/src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h +++ b/src/network_inspectors/appid/service_plugins/test/service_plugin_mock.h @@ -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; diff --git a/src/network_inspectors/rna/CMakeLists.txt b/src/network_inspectors/rna/CMakeLists.txt index 548543814..df05ffaef 100644 --- a/src/network_inspectors/rna/CMakeLists.txt +++ b/src/network_inspectors/rna/CMakeLists.txt @@ -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 diff --git a/src/network_inspectors/rna/rna_app_discovery.cc b/src/network_inspectors/rna/rna_app_discovery.cc index cb73033e7..a41ccb472 100644 --- a/src/network_inspectors/rna/rna_app_discovery.cc +++ b/src/network_inspectors/rna/rna_app_discovery.cc @@ -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) ) { diff --git a/src/network_inspectors/rna/rna_app_discovery.h b/src/network_inspectors/rna/rna_app_discovery.h index 67731ac30..70c39e686 100644 --- a/src/network_inspectors/rna/rna_app_discovery.h +++ b/src/network_inspectors/rna/rna_app_discovery.h @@ -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 diff --git a/src/network_inspectors/rna/rna_config.h b/src/network_inspectors/rna/rna_config.h index 98729c125..d8e86c8db 100644 --- a/src/network_inspectors/rna/rna_config.h +++ b/src/network_inspectors/rna/rna_config.h @@ -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 diff --git a/src/network_inspectors/rna/rna_event_handler.cc b/src/network_inspectors/rna/rna_event_handler.cc index 3eb818406..2167ee54b 100644 --- a/src/network_inspectors/rna/rna_event_handler.cc +++ b/src/network_inspectors/rna/rna_event_handler.cc @@ -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); +} diff --git a/src/network_inspectors/rna/rna_event_handler.h b/src/network_inspectors/rna/rna_event_handler.h index 8bfb59600..e85f4ce90 100644 --- a/src/network_inspectors/rna/rna_event_handler.h +++ b/src/network_inspectors/rna/rna_event_handler.h @@ -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 diff --git a/src/network_inspectors/rna/rna_fingerprint.h b/src/network_inspectors/rna/rna_fingerprint.h index 2dc37f153..93961223b 100644 --- a/src/network_inspectors/rna/rna_fingerprint.h +++ b/src/network_inspectors/rna/rna_fingerprint.h @@ -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 index 000000000..3f25c7942 --- /dev/null +++ b/src/network_inspectors/rna/rna_fingerprint_smb.cc @@ -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 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "rna_fingerprint_smb.h" + +#include + +#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 index 000000000..6b325f559 --- /dev/null +++ b/src/network_inspectors/rna/rna_fingerprint_smb.h @@ -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 + +#ifndef RNA_FINGERPRINT_SMB_H +#define RNA_FINGERPRINT_SMB_H + +#include +#include +#include + +#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 hm; + std::hash 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 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 diff --git a/src/network_inspectors/rna/rna_flow.cc b/src/network_inspectors/rna/rna_flow.cc index f155f298d..95d97167c 100644 --- a/src/network_inspectors/rna/rna_flow.cc +++ b/src/network_inspectors/rna/rna_flow.cc @@ -24,7 +24,13 @@ #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 diff --git a/src/network_inspectors/rna/rna_flow.h b/src/network_inspectors/rna/rna_flow.h index 4bfd0373f..8af1e8d8a 100644 --- a/src/network_inspectors/rna/rna_flow.h +++ b/src/network_inspectors/rna/rna_flow.h @@ -30,6 +30,13 @@ #include "rna_fingerprint_tcp.h" +namespace snort +{ +struct Packet; +} + +class DiscoveryFilter; + using RnaTracker = std::shared_ptr; 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); diff --git a/src/network_inspectors/rna/rna_inspector.cc b/src/network_inspectors/rna/rna_inspector.cc index 2c64ca8de..02f986d9e 100644 --- a/src/network_inspectors/rna/rna_inspector.cc +++ b/src/network_inspectors/rna/rna_inspector.cc @@ -34,8 +34,10 @@ #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); } diff --git a/src/network_inspectors/rna/rna_module.cc b/src/network_inspectors/rna/rna_module.cc index a0affe312..3775f4e12 100644 --- a/src/network_inspectors/rna/rna_module.cc +++ b/src/network_inspectors/rna/rna_module.cc @@ -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"); } diff --git a/src/network_inspectors/rna/rna_module.h b/src/network_inspectors/rna/rna_module.h index 09a0e00d9..3aa935dea 100644 --- a/src/network_inspectors/rna/rna_module.h +++ b/src/network_inspectors/rna/rna_module.h @@ -47,6 +47,7 @@ struct RnaStats PegCount change_host_update; PegCount dhcp_data; PegCount dhcp_info; + PegCount smb; }; extern THREAD_LOCAL RnaStats rna_stats; diff --git a/src/network_inspectors/rna/rna_pnd.cc b/src/network_inspectors/rna/rna_pnd.cc index 62585b4fb..286dc8399 100644 --- a/src/network_inspectors/rna/rna_pnd.cc +++ b/src/network_inspectors/rna/rna_pnd.cc @@ -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(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 diff --git a/src/network_inspectors/rna/rna_pnd.h b/src/network_inspectors/rna/rna_pnd.h index af76e6e01..326051124 100644 --- a/src/network_inspectors/rna/rna_pnd.h +++ b/src/network_inspectors/rna/rna_pnd.h @@ -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(); diff --git a/src/network_inspectors/rna/test/rna_module_mock.h b/src/network_inspectors/rna/test/rna_module_mock.h index 46cf49b2d..4a93af7c3 100644 --- a/src/network_inspectors/rna/test/rna_module_mock.h +++ b/src/network_inspectors/rna/test/rna_module_mock.h @@ -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 { diff --git a/src/pub_sub/CMakeLists.txt b/src/pub_sub/CMakeLists.txt index f319a71e8..04ebfddb1 100644 --- a/src/pub_sub/CMakeLists.txt +++ b/src/pub_sub/CMakeLists.txt @@ -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 index 000000000..68d6008ac --- /dev/null +++ b/src/pub_sub/smb_events.h @@ -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 + +#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 -- 2.47.3