]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2580 in SNORT/snort3 from ~ARMANDAV/snort3:rna_banner to master
authorMasud Hasan (mashasan) <mashasan@cisco.com>
Wed, 28 Oct 2020 00:00:27 +0000 (00:00 +0000)
committerMasud Hasan (mashasan) <mashasan@cisco.com>
Wed, 28 Oct 2020 00:00:27 +0000 (00:00 +0000)
Squashed commit of the following:

commit ce08354fcfaf79ee973c489c1ad439fa34657fe5
Author: Arun Mandava <armandav@cisco.com>
Date:   Thu Oct 15 20:58:37 2020 -0400

    rna: Support banner discovery

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/network_inspectors/rna/rna_logger.cc
src/network_inspectors/rna/rna_logger.h
src/network_inspectors/rna/rna_logger_common.h

index e04707e115e0aef7836a7f2b9a494ae5e50840a4..2e9e9d97a31160ffbf5eb87b114f171fc806704d 100644 (file)
@@ -308,6 +308,7 @@ void HostTracker::clear_service(HostApplication& ha)
     ha.last_seen = 0;
     ha.payloads.clear();
     ha.info.clear();
+    ha.banner_updated = false;
 }
 
 bool HostTracker::add_client_payload(HostClient& hc, AppId payload, size_t max_payloads)
@@ -592,6 +593,24 @@ bool HostTracker::update_service_info(HostApplication& ha, const char* vendor,
     return false;
 }
 
+bool HostTracker::update_service_banner(Port port, IpProtocol proto)
+{
+    host_tracker_stats.service_finds++;
+    lock_guard<mutex> lck(host_tracker_lock);
+    for ( auto& s : services )
+    {
+        if ( s.port == port and s.proto == proto )
+        {
+            if ( !s.visibility or s.banner_updated )
+                return false;
+
+            s.banner_updated = true;
+            return true;
+        }
+    }
+    return false;
+}
+
 bool HostTracker::update_service_user(Port port, IpProtocol proto, const char* user)
 {
     host_tracker_stats.service_finds++;
@@ -718,6 +737,7 @@ bool HostTracker::set_service_visibility(Port port, IpProtocol proto, bool v)
                 for ( auto& info : s.info )
                     info.visibility = false;
                 s.user[0] = '\0';
+                s.banner_updated = false;
             }
             return true;
         }
index 040761fcd1ad233cd127dd06818e38578ffaa59a..819b2bdc8b88c6c286ec6511984be1df1a77f808 100644 (file)
@@ -86,8 +86,9 @@ typedef AppId Payload_t;
 struct HostApplication
 {
     HostApplication() = default;
-    HostApplication(Port pt, IpProtocol pr, AppId ap, bool in, uint32_t ht = 0, uint32_t ls = 0) :
-        port(pt), proto(pr), appid(ap), inferred_appid(in), hits(ht), last_seen(ls) { }
+    HostApplication(Port pt, IpProtocol pr, AppId ap, bool in, uint32_t ht = 0, uint32_t ls = 0,
+        bool banner = false) : port(pt), proto(pr), appid(ap), inferred_appid(in), hits(ht),
+        last_seen(ls), banner_updated(banner) { }
     HostApplication(const HostApplication& ha): port(ha.port), proto(ha.proto), appid(ha.appid),
         inferred_appid(ha.inferred_appid), hits(ha.hits), last_seen(ha.last_seen), info(ha.info),
         payloads(ha.payloads) { }
@@ -102,6 +103,7 @@ struct HostApplication
         info = ha.info;
         payloads = ha.payloads;
         visibility = ha.visibility;
+        banner_updated = ha.banner_updated;
         return *this;
     }
 
@@ -112,6 +114,7 @@ struct HostApplication
     uint32_t hits = 0;
     uint32_t last_seen = 0;
     char user[INFO_SIZE] = { '\0' };
+    bool banner_updated = false;
 
     std::vector<HostApplicationInfo, HostAppInfoAllocator> info;
     std::vector<Payload_t, HostCacheAllocIp<Payload_t>> payloads;
@@ -292,6 +295,7 @@ public:
     void update_service(const HostApplication&);
     bool update_service_info(HostApplication&, const char* vendor, const char* version,
         uint16_t max_info);
+    bool update_service_banner(Port, IpProtocol);
     bool update_service_user(Port, IpProtocol, const char* username);
     void remove_inferred_services();
 
index c83995aa1f70d22b9b16ac12952b6f172ff1a632..785c949bdc5371a4b1b05a9de59d87708413f8f5 100644 (file)
@@ -64,7 +64,8 @@ void RnaAppDiscovery::process(AppidEvent* appid_event, DiscoveryFilter& filter,
     const auto& appid_session_api = appid_event->get_appid_session_api();
 
     if ( appid_change_bits[APPID_SERVICE_BIT] or appid_change_bits[APPID_CLIENT_BIT] or
-        appid_change_bits[APPID_PAYLOAD_BIT] )
+        appid_change_bits[APPID_PAYLOAD_BIT] or appid_change_bits[APPID_SERVICE_VENDOR_BIT] or
+        appid_change_bits[APPID_VERSION_BIT] )
     {
         AppId service, client, payload;
         appid_session_api.get_app_id(&service, &client, &payload, nullptr, nullptr);
@@ -96,25 +97,24 @@ void RnaAppDiscovery::process(AppidEvent* appid_event, DiscoveryFilter& filter,
                     src_mac, conf, logger, version, client, service);
         }
 
-        if ( appid_change_bits[APPID_PAYLOAD_BIT] and payload > APP_ID_NONE and
-            service > APP_ID_NONE)
+        if ( appid_change_bits[APPID_SERVICE_VENDOR_BIT] or appid_change_bits[APPID_VERSION_BIT] )
         {
-             discover_payload(p, proto, ht, (const struct in6_addr*) src_ip->get_ip6_ptr(),
-                 src_mac, conf, logger, service, payload, client);
+            const char* vendor;
+            const char* version;
+            const AppIdServiceSubtype* subtype;
+            appid_session_api.get_service_info(vendor, version, subtype);
+            update_service_info(p, proto, vendor, version, ht, src_ip, src_mac, logger, conf,
+                service);
         }
-    }
-
-    if ( appid_change_bits[APPID_SERVICE_VENDOR_BIT] or appid_change_bits[APPID_VERSION_BIT] )
-    {
-        const char* vendor;
-        const char* version;
-        const AppIdServiceSubtype* subtype;
-        AppId service, client, payload;
 
-        appid_session_api.get_app_id(&service, &client, &payload, nullptr, nullptr);
-        appid_session_api.get_service_info(vendor, version, subtype);
-        update_service_info(p, proto, vendor, version, ht, src_ip, src_mac, logger, conf,
-            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, client);
+            if ( conf->enable_banner_grab )
+                discover_banner(p, proto, ht, &p->flow->server_ip, src_mac, logger, service);
+        }
     }
 
     // Appid supports only login success event. Change checks once login failure and
@@ -250,6 +250,33 @@ void RnaAppDiscovery::update_service_info(const Packet* p, IpProtocol proto, con
     rt->update_service(ha);
 }
 
+void RnaAppDiscovery::discover_banner(const Packet* p, IpProtocol proto, RnaTracker& rt,
+    const snort::SfIp* ip, const uint8_t* mac, RnaLogger& logger, AppId service)
+{
+    auto srt = rt;
+    const uint8_t* service_mac = mac;
+
+    HostApplication ha(p->flow->server_port, proto, service, false);
+    if ( p->is_from_client() )
+    {
+        srt = host_cache.find(p->flow->server_ip);
+        if ( !srt )
+            return;
+
+        if ( layer::get_eth_layer(p) )
+            service_mac = layer::get_eth_layer(p)->ether_dst;
+        else
+            service_mac = srt->get_last_seen_mac();
+    }
+
+    if ( !srt->update_service_banner(p->flow->server_port, proto) )
+        return;
+
+    ha.last_seen = (uint32_t) packet_time();
+    logger.log(RNA_EVENT_CHANGE, CHANGE_BANNER_UPDATE, p, &srt,
+        (const struct in6_addr*) ip->get_ip6_ptr(), service_mac, &ha);
+}
+
 void RnaAppDiscovery::discover_client(const Packet* p, RnaTracker& rt,
     const struct in6_addr* src_ip, const uint8_t* src_mac, RnaConfig* conf,
     RnaLogger& logger, const char* version, AppId client, AppId service)
index c647404c77f4fdc1d7c2cffcf41b207be6d22cc5..1a9856b758ae55262c9b2f41149b8ba6966afb0c 100644 (file)
@@ -43,6 +43,8 @@ public:
     static void discover_user(const snort::Packet*, RnaTracker&, const struct in6_addr*,
         RnaLogger&, const char* username, AppId, IpProtocol);
 
+    static void discover_banner(const snort::Packet*, IpProtocol, RnaTracker&,
+        const snort::SfIp*, const uint8_t* mac, RnaLogger&, AppId);
 private:
     static void update_service_info(const snort::Packet*, IpProtocol, const char* vendor,
         const char* version, RnaTracker&, const snort::SfIp*, const uint8_t*,
index acabff94ed5d48b013566e278a13292a40d99d94..21479ba790e2eae252bcf12e8502d5d1e70e6950 100644 (file)
@@ -91,6 +91,8 @@ static inline void rna_logger_message(const RnaLoggerEvent& rle)
                     debug_logf(rna_trace, nullptr, "RNA Service Info log: version: %s\n",
                         s.version);
             }
+            if ( rle.type == RNA_EVENT_CHANGE and rle.subtype == CHANGE_BANNER_UPDATE )
+                debug_logf(rna_trace, nullptr, "RNA Banner log: true\n");
         }
 
         if ( rle.user )
@@ -172,7 +174,7 @@ bool RnaLogger::log(uint16_t type, uint16_t subtype, const struct in6_addr* src_
     assert(ht);
 
     RnaLoggerEvent rle(type, subtype, src_mac, ht, hm, proto, cond_var,
-        ha, fp, hc, user, appid, di, jb);
+        ha, fp, hc, user, appid, di, jb, p);
     if ( src_ip and (!IN6_IS_ADDR_V4MAPPED(src_ip) or src_ip->s6_addr32[3]) )
         rle.ip = src_ip;
     else
index 76d2eed93b247502fcbe9e1f2e82670818391211..5521ce47b0471d8c2057fe11ec834224bdf41fbb 100644 (file)
@@ -38,9 +38,9 @@ struct RnaLoggerEvent : public Event
     RnaLoggerEvent (uint16_t t, uint16_t st, const uint8_t* mc, const RnaTracker* rt,
         const snort::HostMac* hmp, uint16_t pr, void* cv, const snort::HostApplication* hap,
         const snort::FpFingerprint* fpr, const snort::HostClient* hcp, const char* u,
-        int32_t app, const char* di, bool jb) : type(t), subtype(st), mac(mc), ht(rt), hm(hmp),
-        proto(pr), cond_var(cv), ha(hap), fp(fpr), hc(hcp), user(u), appid(app),
-        device_info(di), jail_broken(jb) { }
+        int32_t app, const char* di, bool jb, const snort::Packet* p) : type(t), subtype(st),
+        mac(mc), ht(rt), hm(hmp), proto(pr), cond_var(cv), ha(hap), fp(fpr), hc(hcp),
+        user(u), appid(app), device_info(di), jail_broken(jb), pkt(p) { }
 
     uint32_t event_time = 0;
     uint16_t type;
@@ -58,6 +58,7 @@ struct RnaLoggerEvent : public Event
     AppId appid;
     const char* device_info;
     bool jail_broken;
+    const snort::Packet* pkt;
 };
 
 class RnaLogger
index 87e45248b8d64b6702b298dd217945dece8aed73..38bdfbfd5010fa1e372a6bbc452504e5cf98c44b 100644 (file)
@@ -39,6 +39,7 @@
     #define CHANGE_HOST_UPDATE         15
     #define CHANGE_HOST_TYPE           16
     #define CHANGE_VLAN_TAG            18
+    #define CHANGE_BANNER_UPDATE       24
     #define CHANGE_CLIENT_APP_UPDATE   32
 
 #define RUA_EVENT         1004