]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1676 in SNORT/snort3 from ~MASHASAN/snort3:host_discovery to...
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Wed, 24 Jul 2019 20:40:07 +0000 (16:40 -0400)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Wed, 24 Jul 2019 20:40:07 +0000 (16:40 -0400)
Squashed commit of the following:

commit 6ac57a71278abff483a23d296384f3d0d25a13b7
Author: Masud Hasan <mashasan@cisco.com>
Date:   Mon Jul 15 12:13:45 2019 -0400

    rna: Add new hosts with IP-address into host cache

src/hash/lru_cache_shared.h
src/host_tracker/host_cache.cc
src/host_tracker/host_cache.h
src/host_tracker/host_tracker.cc
src/network_inspectors/rna/CMakeLists.txt
src/network_inspectors/rna/rna_event_handler.cc
src/network_inspectors/rna/rna_event_handler.h
src/network_inspectors/rna/rna_inspector.cc
src/network_inspectors/rna/rna_inspector.h
src/network_inspectors/rna/rna_pnd.cc [new file with mode: 0644]
src/network_inspectors/rna/rna_pnd.h [new file with mode: 0644]

index 69535027736fffdb3d95bd21d200a2356b79226a..097855616b774ec364e252e9500c784aa18f3083 100644 (file)
@@ -189,7 +189,7 @@ void LruCacheShared<Key, Data, Hash>::insert(const Key& key, const Data& data)
     }
 
     //  Add key/data pair to front of list.
-    list.push_front(std::make_pair(key, data));
+    list.emplace_front(std::make_pair(key, data));
 
     //  Add list iterator for the new entry to map.
     map[key] = list.begin();
index 17bc8d96dc82b9d264c0e35426cd0542340bf393..450d46eb5cbb7af404fd6b32ae638113c4006958 100644 (file)
 #include "target_based/snort_protocols.h"
 
 using namespace snort;
+using namespace std;
 
 #define LRU_CACHE_INITIAL_SIZE 65535
 
 LruCacheShared<HostIpKey, std::shared_ptr<HostTracker>, HashHostIpKey>
     host_cache(LRU_CACHE_INITIAL_SIZE);
 
+namespace snort
+{
+
 void host_cache_add_host_tracker(HostTracker* ht)
 {
     std::shared_ptr<HostTracker> sptr(ht);
     host_cache.insert((const uint8_t*) ht->get_ip_addr().get_ip6_ptr(), sptr);
 }
 
-namespace snort
-{
-bool host_cache_add_service(const SfIp& ipaddr, Protocol ipproto, Port port, const char* service)
+bool host_cache_add_service(const SfIp& ipaddr, Protocol ipproto, Port port, SnortProtocolId id)
 {
     HostIpKey ipkey((const uint8_t*) ipaddr.get_ip6_ptr());
-    SnortProtocolId proto_id = SnortConfig::get_conf()->proto_ref->find(service);
-    HostApplicationEntry app_entry(ipproto, port, proto_id);
     std::shared_ptr<HostTracker> ht;
 
     if (!host_cache.find(ipkey, ht))
     {
         //  This host hasn't been seen.  Add it.
-        ht = std::make_shared<HostTracker>();
+        ht = std::make_shared<HostTracker>(ipaddr);
 
         if (ht == nullptr)
         {
@@ -62,9 +62,16 @@ bool host_cache_add_service(const SfIp& ipaddr, Protocol ipproto, Port port, con
         host_cache.insert(ipkey, ht);
     }
 
+    HostApplicationEntry app_entry(ipproto, port, id);
     return ht->add_service(app_entry);
 }
 
+bool host_cache_add_service(const SfIp& ipaddr, Protocol ipproto, Port port, const char* service)
+{
+    return host_cache_add_service(ipaddr, ipproto, port,
+        SnortConfig::get_conf()->proto_ref->find(service));
+}
+
 bool host_cache_add_app_mapping(const SfIp& ipaddr, Port port, Protocol proto, AppId appId)
 {
     HostIpKey ipkey((const uint8_t*) ipaddr.get_ip6_ptr());
index 9b96038fa8dd293ce8b6b414e35c0d3478e4c0b1..d73290645b06c14d81b3291a8b726259e9646f89 100644 (file)
@@ -64,12 +64,14 @@ struct HashHostIpKey
 
 extern LruCacheShared<HostIpKey, std::shared_ptr<HostTracker>, HashHostIpKey> host_cache;
 
-void host_cache_add_host_tracker(HostTracker*);
-
 namespace snort
 {
+void host_cache_add_host_tracker(HostTracker*);
+
 //  Insert a new service into host cache if it doesn't already exist.
-SO_PUBLIC bool host_cache_add_service(const SfIp&, Protocol, Port, const char* service);
+SO_PUBLIC bool host_cache_add_service(const SfIp&, Protocol, Port, SnortProtocolId);
+SO_PUBLIC bool host_cache_add_service(const SfIp&, Protocol, Port, const char*);
+
 bool host_cache_add_app_mapping(const SfIp&, Port, Protocol, AppId);
 AppId host_cache_find_app_mapping(const SfIp* , Port, Protocol );
 }
index f9eea4417bd4b6d112a1dfc48a601749d5e48bf7..c117563faeeabd516791e0d1e8267ed6cee13834 100644 (file)
@@ -70,7 +70,7 @@ void HostTracker::add_app_mapping(Port port, Protocol proto, AppId appid)
     std::lock_guard<std::mutex> lck(host_tracker_lock);
     AppMapping app_map = {port, proto, appid};
 
-    app_mappings.push_back(app_map);
+    app_mappings.emplace_back(app_map);
 }
 
 AppId HostTracker::find_app_mapping(Port port, Protocol proto)
@@ -98,7 +98,7 @@ bool HostTracker::find_else_add_app_mapping(Port port, Protocol proto, AppId app
     }
     AppMapping app_map = {port, proto, appid};
 
-    app_mappings.push_back(app_map);
+    app_mappings.emplace_back(app_map);
     return true;
 }
 
@@ -112,7 +112,7 @@ bool HostTracker::add_service(const HostApplicationEntry& app_entry)
     if (iter != services.end())
         return false;   //  Already exists.
 
-    services.push_front(app_entry);
+    services.emplace_front(app_entry);
     return true;
 }
 
@@ -126,7 +126,7 @@ void HostTracker::add_or_replace_service(const HostApplicationEntry& app_entry)
     if (iter != services.end())
         services.erase(iter);
 
-    services.push_front(app_entry);
+    services.emplace_front(app_entry);
 }
 
 bool HostTracker::find_service(Protocol ipproto, Port port, HostApplicationEntry& app_entry)
index 440a6c8bf122584d1aab1f83e3ab3d45738f40f0..1091697317d6fb3f3c48dd3202e15a2ee3328e1c 100644 (file)
@@ -6,6 +6,8 @@ set ( RNA_SOURCES
     rna_inspector.h
     rna_module.cc
     rna_module.h
+    rna_pnd.cc
+    rna_pnd.h
 )
 
 #if (STATIC_INSPECTORS)
index d1c317ab64499885287858c58fb65bf9f3055ff6..8607c5e8d122a9456ca83c065f9fe8b09264641a 100644 (file)
 
 using namespace snort;
 
-void RnaIcmpEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaIcmpEventHandler::handle(DataEvent& event, Flow*)
 {
     Profile profile(rna_perf_stats);
-
     ++rna_stats.icmp;
+    pnd.analyze_flow_icmp(event.get_packet());
 }
 
-void RnaIpEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaIpEventHandler::handle(DataEvent& event, Flow*)
 {
     Profile profile(rna_perf_stats);
-
     ++rna_stats.ip;
+    pnd.analyze_flow_ip(event.get_packet());
 }
 
-void RnaUdpEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaTcpSynEventHandler::handle(DataEvent& event, Flow*)
 {
     Profile profile(rna_perf_stats);
-
-    ++rna_stats.udp;
+    ++rna_stats.tcp_syn;
+    pnd.analyze_flow_tcp(event.get_packet(), false);
 }
 
-void RnaTcpSynEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaTcpSynAckEventHandler::handle(DataEvent& event, Flow*)
 {
     Profile profile(rna_perf_stats);
-
-    ++rna_stats.tcp_syn;
+    ++rna_stats.tcp_syn_ack;
+    pnd.analyze_flow_tcp(event.get_packet(), false);
 }
 
-void RnaTcpSynAckEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaTcpMidstreamEventHandler::handle(DataEvent& event, Flow*)
 {
     Profile profile(rna_perf_stats);
-
-    ++rna_stats.tcp_syn_ack;
+    ++rna_stats.tcp_midstream;
+    pnd.analyze_flow_tcp(event.get_packet(), true);
 }
 
-void RnaTcpMidstreamEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaUdpEventHandler::handle(DataEvent& event, Flow*)
 {
     Profile profile(rna_perf_stats);
-
-    ++rna_stats.tcp_midstream;
+    ++rna_stats.udp;
+    pnd.analyze_flow_udp(event.get_packet());
 }
index 8a0f8ef8ed706cf4a24ae55826232730aa304297..2b4752a5a151449841217283ff3fa338bfbc69f9 100644 (file)
 #include "framework/data_bus.h"
 
 #include "rna_module.h"
+#include "rna_pnd.h"
 
 class RnaIcmpEventHandler : public snort::DataHandler
 {
 public:
-    RnaIcmpEventHandler() : DataHandler(RNA_NAME) { }
+    RnaIcmpEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
     void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
 };
 
 class RnaIpEventHandler : public snort::DataHandler
 {
 public:
-    RnaIpEventHandler() : DataHandler(RNA_NAME) { }
+    RnaIpEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
     void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
 };
 
-class RnaUdpEventHandler : public snort::DataHandler
+class RnaTcpSynEventHandler : public snort::DataHandler
 {
 public:
-    RnaUdpEventHandler() : DataHandler(RNA_NAME) { }
+    RnaTcpSynEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
     void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
 };
 
-class RnaTcpSynEventHandler : public snort::DataHandler
+class RnaTcpSynAckEventHandler : public snort::DataHandler
 {
 public:
-    RnaTcpSynEventHandler() : DataHandler(RNA_NAME) { }
+    RnaTcpSynAckEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
     void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
 };
 
-class RnaTcpSynAckEventHandler : public snort::DataHandler
+class RnaTcpMidstreamEventHandler : public snort::DataHandler
 {
 public:
-    RnaTcpSynAckEventHandler() : DataHandler(RNA_NAME) { }
+    RnaTcpMidstreamEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
     void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
 };
 
-class RnaTcpMidstreamEventHandler : public snort::DataHandler
+class RnaUdpEventHandler : public snort::DataHandler
 {
 public:
-    RnaTcpMidstreamEventHandler() : DataHandler(RNA_NAME) { }
+    RnaUdpEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
     void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
 };
 
 #endif
index b3e18e23cc174ff3e63ce4f656b895d82892375d..1b3629e769bb7864fc18e1ada782e876362867df 100644 (file)
@@ -64,12 +64,12 @@ RnaInspector::~RnaInspector()
 
 bool RnaInspector::configure(SnortConfig*)
 {
-    DataBus::subscribe( STREAM_ICMP_NEW_FLOW_EVENT, new RnaIcmpEventHandler() );
-    DataBus::subscribe( STREAM_IP_NEW_FLOW_EVENT, new RnaIpEventHandler() );
-    DataBus::subscribe( STREAM_UDP_NEW_FLOW_EVENT, new RnaUdpEventHandler() );
-    DataBus::subscribe( STREAM_TCP_SYN_EVENT, new RnaTcpSynEventHandler() );
-    DataBus::subscribe( STREAM_TCP_SYN_ACK_EVENT, new RnaTcpSynAckEventHandler() );
-    DataBus::subscribe( STREAM_TCP_MIDSTREAM_EVENT, new RnaTcpMidstreamEventHandler() );
+    DataBus::subscribe( STREAM_ICMP_NEW_FLOW_EVENT, new RnaIcmpEventHandler(pnd) );
+    DataBus::subscribe( STREAM_IP_NEW_FLOW_EVENT, new RnaIpEventHandler(pnd) );
+    DataBus::subscribe( STREAM_UDP_NEW_FLOW_EVENT, new RnaUdpEventHandler(pnd) );
+    DataBus::subscribe( STREAM_TCP_SYN_EVENT, new RnaTcpSynEventHandler(pnd) );
+    DataBus::subscribe( STREAM_TCP_SYN_ACK_EVENT, new RnaTcpSynAckEventHandler(pnd) );
+    DataBus::subscribe( STREAM_TCP_MIDSTREAM_EVENT, new RnaTcpMidstreamEventHandler(pnd) );
 
     return true;
 }
@@ -77,16 +77,14 @@ bool RnaInspector::configure(SnortConfig*)
 void RnaInspector::eval(Packet* p)
 {
     Profile profile(rna_perf_stats);
+    ++rna_stats.other_packets;
 
-    // Handling untracked sessions, e.g., non-IP packets
     assert( !p->flow );
     assert( !(BIT((unsigned)p->type()) & PROTO_BIT__ANY_SSN) );
 
-    ++rna_stats.other_packets;
-
-#ifdef NDEBUG
+    // Handling untracked sessions, e.g., non-IP packets
+    // pnd.analyze_flow_non_ip(p);
     UNUSED(p);
-#endif
 }
 
 void RnaInspector::show(SnortConfig*)
index 41b4e9154bfeaa0adcf3c762c519f54e19d62f1f..7e2c435400ba404b8a11a34e7f9e69708f388fce 100644 (file)
@@ -24,6 +24,7 @@
 #include "framework/inspector.h"
 
 #include "rna_module.h"
+#include "rna_pnd.h"
 
 namespace snort
 {
@@ -46,6 +47,7 @@ private:
     bool load_rna_conf();
     const RnaModuleConfig* mod_conf = nullptr;
     RnaConfig* rna_conf = nullptr;
+    RnaPnd pnd;
 };
 
 #endif
diff --git a/src/network_inspectors/rna/rna_pnd.cc b/src/network_inspectors/rna/rna_pnd.cc
new file mode 100644 (file)
index 0000000..3708456
--- /dev/null
@@ -0,0 +1,146 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2019 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2003-2013 Sourcefire, Inc.
+//
+// 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_pnd.cc authors: Martin Roesch <roesch@sourcefire.com>
+//                     Masud Hasan <mashasan@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rna_pnd.h"
+
+#include "host_tracker/host_cache.h"
+
+using namespace snort;
+
+static const uint8_t zeromac[6] = {0, 0, 0, 0, 0, 0};
+
+static inline bool is_eligible_packet(const snort::Packet* p)
+{
+    if ( p->has_ip() or
+        memcmp(snort::layer::get_eth_layer(p)->ether_src, zeromac, sizeof(zeromac)) )
+        return true;
+    return false;
+}
+
+static inline bool is_eligible_ip(const snort::Packet* p)
+{
+    // If payload needs to be inspected ever, allow rebuilt packet when is_proxied
+    if ( !is_eligible_packet(p) or p->is_rebuilt() or !p->flow )
+        return false;
+    return true;
+}
+
+static inline bool is_eligible_tcp(const snort::Packet* p)
+{
+    if ( !is_eligible_ip(p) or p->ptrs.tcph->is_rst() )
+        return false;
+    return true;
+}
+
+static inline bool is_eligible_udp(const snort::Packet* p)
+{
+    if ( !is_eligible_ip(p) )
+        return false;
+    if ( p->is_from_client() )
+    {
+        const snort::SfIp* src = p->ptrs.ip_api.get_src();
+        const snort::SfIp* dst = p->ptrs.ip_api.get_dst();
+        if ( !src->is_set() and IN6_IS_ADDR_MULTICAST(dst->get_ip6_ptr()) and
+            p->ptrs.sp == 68 and p->ptrs.dp == 67 )
+            return false; // skip BOOTP
+    }
+    return true;
+}
+
+void RnaPnd::analyze_flow_icmp(const Packet* p)
+{
+    if ( is_eligible_ip(p) )
+        discover_network_icmp(p);
+}
+
+void RnaPnd::analyze_flow_ip(const Packet* p)
+{
+    if ( is_eligible_ip(p) )
+        discover_network_ip(p);
+}
+
+void RnaPnd::analyze_flow_non_ip(const Packet* p)
+{
+    if ( is_eligible_packet(p) )
+        discover_network_non_ip(p);
+}
+
+void RnaPnd::analyze_flow_tcp(const Packet* p, bool is_midstream)
+{
+    // If and when flow stores rna state, process the flow data here before global cache access
+    if ( is_eligible_tcp(p) )
+        discover_network_tcp(p);
+
+    UNUSED(is_midstream);
+}
+
+void RnaPnd::analyze_flow_udp(const Packet* p)
+{
+    if ( is_eligible_udp(p) )
+        discover_network_udp(p);
+}
+
+void RnaPnd::discover_network_icmp(const Packet* p)
+{
+    if ( !host_cache_add_service(p->flow->client_ip, (uint8_t)p->get_ip_proto_next(),
+        p->flow->client_port, SNORT_PROTO_ICMP) )
+        return;
+    // process rna discovery for icmp
+}
+
+void RnaPnd::discover_network_ip(const Packet* p)
+{
+    if ( !host_cache_add_service(p->flow->client_ip, (uint8_t)p->get_ip_proto_next(),
+        p->flow->client_port, SNORT_PROTO_IP) )
+        return;
+    // process rna discovery for ip
+}
+
+void RnaPnd::discover_network_non_ip(const Packet* p)
+{
+    // process rna discovery for non-ip in mac cache
+    UNUSED(p);
+}
+
+void RnaPnd::discover_network_tcp(const Packet* p)
+{
+    // Track from initiator direction, if not already seen
+    if ( !host_cache_add_service(p->flow->client_ip, (uint8_t)p->get_ip_proto_next(),
+        p->flow->client_port, SNORT_PROTO_TCP) )
+        return;
+
+    // Add mac address to ht list, ttl, last_seen, etc.
+    // Generate new host events
+}
+
+void RnaPnd::discover_network_udp(const Packet* p)
+{
+    if ( !host_cache_add_service(p->flow->client_ip, (uint8_t)p->get_ip_proto_next(),
+        p->flow->client_port, SNORT_PROTO_UDP) )
+        return;
+    // process rna discovery for udp
+}
+
diff --git a/src/network_inspectors/rna/rna_pnd.h b/src/network_inspectors/rna/rna_pnd.h
new file mode 100644 (file)
index 0000000..b19beb4
--- /dev/null
@@ -0,0 +1,50 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2019 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2003-2013 Sourcefire, Inc.
+//
+// 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.
+//--------------------------------------------------------------------------
+
+#ifndef RNA_PND_H
+#define RNA_PND_H
+
+#include "protocols/eth.h"
+#include "protocols/packet.h"
+#include "protocols/tcp.h"
+
+namespace snort
+{
+struct Packet;
+}
+
+class RnaPnd
+{
+public:
+    void analyze_flow_icmp(const snort::Packet* p);
+    void analyze_flow_ip(const snort::Packet* p);
+    void analyze_flow_non_ip(const snort::Packet* p);
+    void analyze_flow_tcp(const snort::Packet* p, bool is_midstream);
+    void analyze_flow_udp(const snort::Packet* p);
+
+private:
+    // General rna utilities not associated with flow
+    void discover_network_icmp(const snort::Packet* p);
+    void discover_network_ip(const snort::Packet* p);
+    void discover_network_non_ip(const snort::Packet* p);
+    void discover_network_tcp(const snort::Packet* p);
+    void discover_network_udp(const snort::Packet* p);
+};
+
+#endif