From: Mike Stepanek (mstepane) Date: Wed, 24 Jul 2019 20:40:07 +0000 (-0400) Subject: Merge pull request #1676 in SNORT/snort3 from ~MASHASAN/snort3:host_discovery to... X-Git-Tag: 3.0.0-259~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f53957e5517227d1873a4eb2761a2dca0efda257;p=thirdparty%2Fsnort3.git Merge pull request #1676 in SNORT/snort3 from ~MASHASAN/snort3:host_discovery to master Squashed commit of the following: commit 6ac57a71278abff483a23d296384f3d0d25a13b7 Author: Masud Hasan Date: Mon Jul 15 12:13:45 2019 -0400 rna: Add new hosts with IP-address into host cache --- diff --git a/src/hash/lru_cache_shared.h b/src/hash/lru_cache_shared.h index 695350277..097855616 100644 --- a/src/hash/lru_cache_shared.h +++ b/src/hash/lru_cache_shared.h @@ -189,7 +189,7 @@ void LruCacheShared::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(); diff --git a/src/host_tracker/host_cache.cc b/src/host_tracker/host_cache.cc index 17bc8d96d..450d46eb5 100644 --- a/src/host_tracker/host_cache.cc +++ b/src/host_tracker/host_cache.cc @@ -28,31 +28,31 @@ #include "target_based/snort_protocols.h" using namespace snort; +using namespace std; #define LRU_CACHE_INITIAL_SIZE 65535 LruCacheShared, HashHostIpKey> host_cache(LRU_CACHE_INITIAL_SIZE); +namespace snort +{ + void host_cache_add_host_tracker(HostTracker* ht) { std::shared_ptr 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 ht; if (!host_cache.find(ipkey, ht)) { // This host hasn't been seen. Add it. - ht = std::make_shared(); + ht = std::make_shared(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()); diff --git a/src/host_tracker/host_cache.h b/src/host_tracker/host_cache.h index 9b96038fa..d73290645 100644 --- a/src/host_tracker/host_cache.h +++ b/src/host_tracker/host_cache.h @@ -64,12 +64,14 @@ struct HashHostIpKey extern LruCacheShared, 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 ); } diff --git a/src/host_tracker/host_tracker.cc b/src/host_tracker/host_tracker.cc index f9eea4417..c117563fa 100644 --- a/src/host_tracker/host_tracker.cc +++ b/src/host_tracker/host_tracker.cc @@ -70,7 +70,7 @@ void HostTracker::add_app_mapping(Port port, Protocol proto, AppId appid) std::lock_guard 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) diff --git a/src/network_inspectors/rna/CMakeLists.txt b/src/network_inspectors/rna/CMakeLists.txt index 440a6c8bf..109169731 100644 --- a/src/network_inspectors/rna/CMakeLists.txt +++ b/src/network_inspectors/rna/CMakeLists.txt @@ -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) diff --git a/src/network_inspectors/rna/rna_event_handler.cc b/src/network_inspectors/rna/rna_event_handler.cc index d1c317ab6..8607c5e8d 100644 --- a/src/network_inspectors/rna/rna_event_handler.cc +++ b/src/network_inspectors/rna/rna_event_handler.cc @@ -26,44 +26,44 @@ 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()); } diff --git a/src/network_inspectors/rna/rna_event_handler.h b/src/network_inspectors/rna/rna_event_handler.h index 8a0f8ef8e..2b4752a5a 100644 --- a/src/network_inspectors/rna/rna_event_handler.h +++ b/src/network_inspectors/rna/rna_event_handler.h @@ -24,47 +24,60 @@ #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 diff --git a/src/network_inspectors/rna/rna_inspector.cc b/src/network_inspectors/rna/rna_inspector.cc index b3e18e23c..1b3629e76 100644 --- a/src/network_inspectors/rna/rna_inspector.cc +++ b/src/network_inspectors/rna/rna_inspector.cc @@ -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*) diff --git a/src/network_inspectors/rna/rna_inspector.h b/src/network_inspectors/rna/rna_inspector.h index 41b4e9154..7e2c43540 100644 --- a/src/network_inspectors/rna/rna_inspector.h +++ b/src/network_inspectors/rna/rna_inspector.h @@ -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 index 000000000..3708456c8 --- /dev/null +++ b/src/network_inspectors/rna/rna_pnd.cc @@ -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 +// Masud Hasan + +#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 index 000000000..b19beb408 --- /dev/null +++ b/src/network_inspectors/rna/rna_pnd.h @@ -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