]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2545 in SNORT/snort3 from ~MMATIRKO/snort3:payload_disco_2 to...
authorMasud Hasan (mashasan) <mashasan@cisco.com>
Mon, 19 Oct 2020 20:34:31 +0000 (20:34 +0000)
committerMasud Hasan (mashasan) <mashasan@cisco.com>
Mon, 19 Oct 2020 20:34:31 +0000 (20:34 +0000)
Squashed commit of the following:

commit 926aadab5dd20e0373a92b425d31fae49a4385e8
Author: Michael Matirko <mmatirko@cisco.com>
Date:   Thu Oct 8 16:26:44 2020 -0400

    rna: change logic for payload discovery, eventing

src/host_tracker/host_tracker.cc
src/host_tracker/host_tracker.h
src/network_inspectors/rna/rna_app_discovery.cc
src/network_inspectors/rna/rna_app_discovery.h
src/protocols/packet.h

index 2180b2b0c052b0a4becea6b12be21c7515e9d16a..1cb306a6829a3e4437fee0bd78ed28778564452f 100644 (file)
@@ -85,9 +85,11 @@ bool HostTracker::add_mac(const uint8_t* mac, uint8_t ttl, uint8_t primary)
     return true;
 }
 
-
-bool HostTracker::add_payload_no_lock(const AppId pld, HostApplication* ha)
+bool HostTracker::add_payload_no_lock(const AppId pld, HostApplication* ha, size_t max_payloads)
 {
+    if ( max_payloads and ha->payloads.size() >= max_payloads )
+        return false;
+
     for ( const auto& app : ha->payloads )
         if ( app == pld )
             return false;
@@ -276,6 +278,31 @@ void HostTracker::clear_service(HostApplication& ha)
     ha.info.clear();
 }
 
+bool HostTracker::add_client_payload(HostClient& hc, AppId payload, size_t max_payloads)
+{
+    std::lock_guard<std::mutex> lck(host_tracker_lock);
+
+    for ( auto& client : clients )
+        if ( client.id == hc.id and client.service == hc.service )
+        {
+            if ( max_payloads and client.payloads.size() >= max_payloads )
+                return false;
+
+            for (const auto& pld : client.payloads)
+            {
+                if ( pld == payload )
+                    return false;
+            }
+
+            client.payloads.emplace_back(payload);
+            hc.payloads = client.payloads;
+            strncpy(hc.version, client.version, INFO_SIZE);
+            return true;
+        }
+
+    return false;
+}
+
 bool HostTracker::add_service(HostApplication& app, bool* added)
 {
     host_tracker_stats.service_adds++;
@@ -348,10 +375,11 @@ bool HostTracker::add_payload(HostApplication& local_ha, Port port, IpProtocol p
 
     auto ha = find_service_no_lock(port, proto, service);
 
-    if (ha and ha->payloads.size() < max_payloads)
+    if (ha)
     {
-        bool success = add_payload_no_lock(payload, ha);
+        bool success = add_payload_no_lock(payload, ha, max_payloads);
         local_ha = *ha;
+        local_ha.payloads = ha->payloads;
         return success;
     }
 
@@ -548,7 +576,8 @@ HostClient::HostClient(AppId clientid, const char *ver, AppId ser) :
     }
 }
 
-HostClient HostTracker::get_client(AppId id, const char* version, AppId service, bool& is_new)
+HostClient HostTracker::find_or_add_client(AppId id, const char* version, AppId service,
+    bool& is_new)
 {
     lock_guard<mutex> lck(host_tracker_lock);
 
@@ -667,6 +696,15 @@ void HostTracker::stringify(string& str)
                 + ", service: " + to_string(c.service);
             if ( c.version[0] != '\0' )
                 str += ", version: " + string(c.version);
+
+            auto total_payloads = c.payloads.size();
+            if ( total_payloads )
+            {
+                str += ", payload";
+                str += (total_payloads > 1) ? "s: " : ": ";
+                for ( const auto& pld : c.payloads )
+                    str += to_string(pld) + (--total_payloads ? ", " : "");
+            }
         }
     }
 
index b72ac1282f8cd1c575ccd819769468b9a5025114..34961f514277c74f5014e883164d82a34464a623 100644 (file)
@@ -119,6 +119,7 @@ struct HostClient
     AppId id;
     char version[INFO_SIZE] = { 0 };
     AppId service;
+    std::vector<AppId, HostCacheAllocIp<AppId>> payloads;
 };
 
 struct DeviceFingerprint
@@ -206,6 +207,8 @@ public:
         hops = h;
     }
 
+    bool add_client_payload(HostClient&, AppId, size_t);
+
     // Returns true if a new mac entry is added, false otherwise
     bool add_mac(const uint8_t* mac, uint8_t ttl, uint8_t primary);
 
@@ -261,7 +264,8 @@ public:
     void remove_inferred_services();
 
     size_t get_client_count();
-    HostClient get_client(AppId id, const char* version, AppId service, bool& is_new);
+    HostClient find_or_add_client(AppId id, const char* version, AppId service,
+        bool& is_new);
     bool add_tcp_fingerprint(uint32_t fpid);
     bool add_ua_fingerprint(uint32_t fpid, uint32_t fp_type, bool jail_broken,
         const char* device_info, uint8_t max_devices);
@@ -347,7 +351,7 @@ private:
     // These two do not lock independently; they are used by payload discovery and called
     // from add_payload(HostApplication&, Port, IpProtocol, AppId, AppId, size_t); where the
     // lock is actually obtained
-    bool add_payload_no_lock(const AppId, HostApplication*);
+    bool add_payload_no_lock(const AppId, HostApplication*, size_t);
     HostApplication* find_service_no_lock(Port, IpProtocol, AppId);
 
     // ... and some unit tests. See Utest.h and UtestMacros.h in cpputest.
index cf7ba5322d88271a5fdcad4987ea749fde00fcb1..f7cf148e8b1a4b797bbec38630e0d3733d1d009f 100644 (file)
@@ -83,15 +83,24 @@ void RnaAppDiscovery::process(AppidEvent* appid_event, DiscoveryFilter& filter,
             and service > APP_ID_NONE )
         {
             const char* version = appid_session_api.get_client_version();
-            discover_client(p, ht, (const struct in6_addr*) src_ip->get_ip6_ptr(), src_mac,
-                conf, logger, version, client, service);
+            if ( p->packet_flags & PKT_FROM_SERVER )
+            {
+                auto cht = host_cache.find(p->flow->client_ip);
+                if (cht)
+                    discover_client(p, cht, (const struct in6_addr*) &p->flow->client_ip,
+                        layer::get_eth_layer(p)->ether_dst, conf, logger, version, client,
+                        service);
+            }
+            else
+                discover_client(p, ht, (const struct in6_addr*) &p->flow->client_ip,
+                    src_mac, conf, logger, version, client, service);
         }
 
         if ( appid_change_bits[APPID_PAYLOAD_BIT] and payload > APP_ID_NONE and
             service > APP_ID_NONE)
         {
              discover_payload(p, proto, ht, (const struct in6_addr*) src_ip->get_ip6_ptr(),
-                 src_mac, conf, logger, service, payload);
+                 src_mac, conf, logger, service, payload, client);
         }
     }
 
@@ -168,7 +177,7 @@ void RnaAppDiscovery::discover_service(const Packet* p, IpProtocol proto, RnaTra
 
 void RnaAppDiscovery::discover_payload(const Packet* p, IpProtocol proto, RnaTracker& rt,
     const struct in6_addr* src_ip, const uint8_t* src_mac, RnaConfig* conf,
-    RnaLogger& logger, AppId service, AppId payload)
+    RnaLogger& logger, AppId service, AppId payload, AppId client)
 {
     uint16_t lookup_port;
     size_t max_payloads = 0;
@@ -181,13 +190,39 @@ void RnaAppDiscovery::discover_payload(const Packet* p, IpProtocol proto, RnaTra
     if ( conf and conf->max_payloads )
         max_payloads = conf->max_payloads;
 
-    HostApplication local_ha;
-    bool new_pld = rt->add_payload(local_ha, lookup_port, proto, payload, service, max_payloads);
-
-    if ( new_pld )
+    // Add server payload
+    if ( p->is_from_server() )
     {
-        logger.log(RNA_EVENT_CHANGE, CHANGE_CLIENT_APP_UPDATE, p, &rt, src_ip, src_mac, &local_ha);
+        HostApplication local_ha;
+        bool new_pld = rt->add_payload(local_ha, lookup_port, proto, payload, service,
+            max_payloads);
+
+        if ( new_pld )
+        {
+               if ( proto == IpProtocol::TCP )
+                   logger.log(RNA_EVENT_CHANGE, CHANGE_TCP_SERVICE_INFO, p, &rt,
+                       (const struct in6_addr*) src_ip, src_mac, &local_ha);
+               else
+                   logger.log(RNA_EVENT_CHANGE, CHANGE_UDP_SERVICE_INFO, p, &rt,
+                       (const struct in6_addr*) src_ip, src_mac, &local_ha);
+        }
     }
+
+    // Add client payloads
+    bool new_client_payload = false;
+    auto client_ht = host_cache.find(p->flow->client_ip);
+
+    if (!client_ht)
+        return;
+
+    HostClient hc(client, nullptr, service);
+    auto client_ip = (const struct in6_addr*) p->flow->client_ip.get_ip6_ptr();
+
+    new_client_payload = client_ht->add_client_payload(hc, payload, max_payloads);
+
+    if (new_client_payload)
+        logger.log(RNA_EVENT_CHANGE, CHANGE_CLIENT_APP_UPDATE, p, &client_ht, client_ip,
+            client_ht->get_last_seen_mac(), &hc);
 }
 
 void RnaAppDiscovery::update_service_info(const Packet* p, IpProtocol proto, const char* vendor,
@@ -225,11 +260,9 @@ void RnaAppDiscovery::discover_client(const Packet* p, RnaTracker& rt,
 
     bool is_new = false;
 
-    auto hc = rt->get_client(client, version, service, is_new);
+    auto hc = rt->find_or_add_client(client, version, service, is_new);
     if ( is_new )
-    {
         logger.log(RNA_EVENT_NEW, NEW_CLIENT_APP, p, &rt, src_ip, src_mac, &hc);
-    }
 }
 
 void RnaAppDiscovery::discover_user(const Packet* p, RnaTracker& rt,
index e7c468be9e696774ff84a80469b6838c4eec2c18..c647404c77f4fdc1d7c2cffcf41b207be6d22cc5 100644 (file)
@@ -33,7 +33,8 @@ public:
 
     static void discover_payload(const snort::Packet*, IpProtocol, RnaTracker&,
         const struct in6_addr*, const uint8_t*, RnaConfig*, RnaLogger&,
-        AppId service, AppId payload);
+        AppId service, AppId payload, AppId client);
+
 
     static void discover_client(const snort::Packet*, RnaTracker&,
         const struct in6_addr*, const uint8_t*, RnaConfig*,
index 345c47d904ec0a7270f3f5ee20607e1a4c7fa7ff..5f42bdddf002fca772876f75666fbb7d7436c826 100644 (file)
@@ -284,7 +284,7 @@ struct SO_PUBLIC Packet
 
     bool is_from_server_originally() const
     { return (!flow || flow->flags.client_initiated) ? is_from_server() : is_from_client(); }
-    
+
     bool is_from_application_client() const;
 
     bool is_from_application_server() const;
@@ -317,7 +317,7 @@ struct SO_PUBLIC Packet
 
     bool is_inter_group_flow() const
     { return (pkth->flags & DAQ_PKT_FLAG_SIGNIFICANT_GROUPS) != 0; }
-    
+
     bool test_session_flags(uint32_t);
 
     SnortProtocolId get_snort_protocol_id();
@@ -336,7 +336,7 @@ struct SO_PUBLIC Packet
     {
         if (is_inter_group_flow())
             return pkth->ingress_group;
-        
+
         return DAQ_PKTHDR_UNKNOWN;
     }
 
@@ -344,7 +344,7 @@ struct SO_PUBLIC Packet
     {
         if (is_inter_group_flow())
             return pkth->egress_group;
-        
+
         return DAQ_PKTHDR_UNKNOWN;
     }