From: Masud Hasan (mashasan) Date: Tue, 1 Sep 2020 14:24:21 +0000 (+0000) Subject: Merge pull request #2437 in SNORT/snort3 from ~ARMANDAV/snort3:rna_client_disc to... X-Git-Tag: 3.0.2-6~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a800fab9d9d7ca77071f68f9cf1426f893206076;p=thirdparty%2Fsnort3.git Merge pull request #2437 in SNORT/snort3 from ~ARMANDAV/snort3:rna_client_disc to master Squashed commit of the following: commit c3efbd690571824a3ced29722fae510d055b33df Author: Arun Mandava Date: Fri Aug 28 12:18:56 2020 -0400 rna: Support client discovery from appid event changes --- diff --git a/src/host_tracker/host_tracker.cc b/src/host_tracker/host_tracker.cc index aa7ab58cf..591cb25b1 100644 --- a/src/host_tracker/host_tracker.cc +++ b/src/host_tracker/host_tracker.cc @@ -369,6 +369,31 @@ bool HostTracker::add_tcp_fingerprint(uint32_t fpid) return result.second; } +size_t HostTracker::get_client_count() +{ + lock_guard lck(host_tracker_lock); + return clients.size(); +} + +HostClient HostTracker::get_client(AppId id, const char* version, AppId service, bool& is_new) +{ + lock_guard lck(host_tracker_lock); + + for ( const auto& c : clients ) + { + if (c.id != APP_ID_NONE and c.id == id and c.service == service + and ((c.version[0] == '\0' and !version) or + (version and strncmp(c.version, version, INFO_SIZE) == 0))) + { + return c; + } + } + + is_new = true; + clients.emplace_back(id, version, service); + return clients.back(); +} + static inline string to_time_string(uint32_t p_time) { time_t raw_time = (time_t) p_time; @@ -424,6 +449,18 @@ void HostTracker::stringify(string& str) } } + if ( !clients.empty() ) + { + str += "\nclients size: " + to_string(clients.size()); + for ( const auto& c : clients ) + { + str += "\n id: " + to_string(c.id) + + ", service: " + to_string(c.service); + if ( c.version[0] != '\0' ) + str += ", version: " + string(c.version); + } + } + auto total = network_protos.size(); if ( total ) { diff --git a/src/host_tracker/host_tracker.h b/src/host_tracker/host_tracker.h index b5a1a79d7..e34f5db59 100644 --- a/src/host_tracker/host_tracker.h +++ b/src/host_tracker/host_tracker.h @@ -82,6 +82,24 @@ struct HostApplication char version[INFO_SIZE] = { 0 }; }; +struct HostClient +{ + HostClient() = default; + HostClient(AppId clientid, const char *ver, AppId ser) : + id(clientid), service(ser) + { + if (ver) + { + strncpy(version, ver, INFO_SIZE); + version[INFO_SIZE-1] = '\0'; + } + } + + AppId id; + char version[INFO_SIZE] = { 0 }; + AppId service; +}; + enum HostType { HOST_TYPE_HOST=0, @@ -93,6 +111,7 @@ enum HostType typedef HostCacheAllocIp HostMacAllocator; typedef HostCacheAllocIp HostAppAllocator; +typedef HostCacheAllocIp HostClientAllocator; class SO_PUBLIC HostTracker { @@ -190,6 +209,8 @@ public: bool update_service_info(HostApplication& ha, const char* vendor, const char* version); void remove_inferred_services(); + size_t get_client_count(); + HostClient get_client(AppId id, const char* version, AppId service, bool& is_new); bool add_tcp_fingerprint(uint32_t fpid); // This should be updated whenever HostTracker data members are changed @@ -204,6 +225,7 @@ private: std::vector> network_protos; std::vector> xport_protos; std::vector services; + std::vector clients; std::set, HostCacheAllocIp> tcp_fpids; bool vlan_tag_present = false; diff --git a/src/network_inspectors/rna/rna_app_discovery.cc b/src/network_inspectors/rna/rna_app_discovery.cc index 27949ec09..0ebd1402a 100644 --- a/src/network_inspectors/rna/rna_app_discovery.cc +++ b/src/network_inspectors/rna/rna_app_discovery.cc @@ -72,6 +72,14 @@ void RnaAppDiscovery::process(AppidEvent* appid_event, DiscoveryFilter& filter, if ( appid_change_bits[APPID_SERVICE_BIT] and service > APP_ID_NONE ) discover_service(p, proto, ht, (const struct in6_addr*) src_ip->get_ip6_ptr(), src_mac, conf, logger, service); + + if (appid_change_bits[APPID_CLIENT_BIT] and client > APP_ID_NONE + 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 ( appid_change_bits[APPID_SERVICE_VENDOR_BIT] or appid_change_bits[APPID_VERSION_BIT] ) @@ -141,3 +149,20 @@ void RnaAppDiscovery::update_service_info(const Packet* p, IpProtocol proto, con ha.hits = 0; rt->update_service(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) +{ + if (conf and conf->max_host_client_apps and + conf->max_host_client_apps <= rt->get_client_count()) + return; + + bool is_new = false; + + auto hc = rt->get_client(client, version, service, is_new); + if ( is_new ) + { + logger.log(RNA_EVENT_NEW, NEW_CLIENT_APP, p, &rt, src_ip, src_mac, &hc); + } +} diff --git a/src/network_inspectors/rna/rna_app_discovery.h b/src/network_inspectors/rna/rna_app_discovery.h index 9acd143c1..3717b7679 100644 --- a/src/network_inspectors/rna/rna_app_discovery.h +++ b/src/network_inspectors/rna/rna_app_discovery.h @@ -31,6 +31,9 @@ public: const struct in6_addr* src_ip, const uint8_t* src_mac, RnaConfig* conf, RnaLogger& logger, AppId service = APP_ID_NONE); + static void discover_client(const snort::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); private: static void update_service_info(const snort::Packet* p, IpProtocol proto, const char* vendor, const char* version, RnaTracker& rt, const snort::SfIp* ip, const uint8_t* src_mac, diff --git a/src/network_inspectors/rna/rna_logger.cc b/src/network_inspectors/rna/rna_logger.cc index ceb0e2e14..a4e7a9c16 100644 --- a/src/network_inspectors/rna/rna_logger.cc +++ b/src/network_inspectors/rna/rna_logger.cc @@ -58,6 +58,16 @@ static inline void rna_logger_message(const RnaLoggerEvent& rle) ip.set(rle.ip); // using this instead of packet's ip to support ARP debug_logf(rna_trace, nullptr, "RNA log: type %u, subtype %u, mac %s, ip %s\n", rle.type, rle.subtype, macbuf, ip.ntop(ipbuf)); + if (rle.hc) + { + if (rle.hc->version[0] != '\0') + debug_logf(rna_trace, nullptr, + "RNA client log: client %u, service %u, version %s\n", + rle.hc->id, rle.hc->service, rle.hc->version); + else + debug_logf(rna_trace, nullptr, "RNA client log: client %u, service %u\n", + rle.hc->id, rle.hc->service); + } } else debug_logf(rna_trace, nullptr, "RNA log: type %u, subtype %u, mac %s\n", @@ -69,55 +79,62 @@ void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker const struct in6_addr* src_ip, const uint8_t* src_mac, const HostApplication* ha) { log(type, subtype, src_ip, src_mac, ht, p, 0, 0, - nullptr, ha, nullptr, nullptr); + nullptr, ha, nullptr, nullptr, nullptr); +} + +void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht, + const struct in6_addr* src_ip, const uint8_t* src_mac, const HostClient* hc) +{ + log(type, subtype, src_ip, src_mac, ht, p, 0, 0, + nullptr, nullptr, nullptr, nullptr, hc); } void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht, const struct in6_addr* src_ip, const uint8_t* src_mac, const TcpFingerprint* tfp) { log(type, subtype, src_ip, src_mac, ht, p, 0, 0, - nullptr, nullptr, tfp, nullptr); + nullptr, nullptr, tfp, nullptr, nullptr); } void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht, const struct in6_addr* src_ip, const uint8_t* src_mac, uint32_t event_time) { log(type, subtype, src_ip, src_mac, ht, p, event_time, 0, - nullptr, nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr, nullptr); } void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht, const struct in6_addr* src_ip, const uint8_t* src_mac, const HostMac* hm, uint32_t event_time) { log(type, subtype, src_ip, src_mac, ht, p, event_time, 0, - hm, nullptr, nullptr, nullptr); + hm, nullptr, nullptr, nullptr, nullptr); } void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht, uint16_t proto, const uint8_t* src_mac, const struct in6_addr* src_ip, uint32_t event_time) { log(type, subtype, src_ip, src_mac, ht, p, event_time, proto, - nullptr, nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr, nullptr); } void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, const uint8_t* src_mac, const struct in6_addr* src_ip, RnaTracker* ht, uint32_t event_time, void* cond_var) { log(type, subtype, src_ip, src_mac, ht, p, event_time, 0, - nullptr, nullptr, nullptr, cond_var); + nullptr, nullptr, nullptr, cond_var, nullptr); } bool RnaLogger::log(uint16_t type, uint16_t subtype, const struct in6_addr* src_ip, const uint8_t* src_mac, RnaTracker* ht, const Packet* p, uint32_t event_time, uint16_t proto, const HostMac* hm, const HostApplication* ha, const TcpFingerprint* tfp, - void* cond_var) + void* cond_var, const HostClient* hc) { if ( !enabled ) return false; assert(ht); - RnaLoggerEvent rle(type, subtype, src_mac, ht, hm, proto, cond_var, ha, tfp); + RnaLoggerEvent rle(type, subtype, src_mac, ht, hm, proto, cond_var, ha, tfp, hc); if ( src_ip and (!IN6_IS_ADDR_V4MAPPED(src_ip) or src_ip->s6_addr32[3]) ) rle.ip = src_ip; else diff --git a/src/network_inspectors/rna/rna_logger.h b/src/network_inspectors/rna/rna_logger.h index 381fc12ee..34e9539e4 100644 --- a/src/network_inspectors/rna/rna_logger.h +++ b/src/network_inspectors/rna/rna_logger.h @@ -37,8 +37,8 @@ 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::TcpFingerprint* tf) : type(t), subtype(st), mac(mc), ht(rt), hm(hmp), - proto(pr), cond_var(cv), ha(hap), tfp(tf) { } + const snort::TcpFingerprint* tf, const snort::HostClient* hcp) : type(t), subtype(st), + mac(mc), ht(rt), hm(hmp), proto(pr), cond_var(cv), ha(hap), tfp(tf), hc(hcp) { } uint16_t type; uint16_t subtype; @@ -50,6 +50,7 @@ struct RnaLoggerEvent : public Event void* cond_var; const snort::HostApplication* ha; const snort::TcpFingerprint* tfp; + const snort::HostClient* hc; }; class RnaLogger @@ -61,6 +62,10 @@ public: void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht, const struct in6_addr* src_ip, const uint8_t* src_mac, const snort::HostApplication* ha); + // for host client + void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht, + const struct in6_addr* src_ip, const uint8_t* src_mac, const snort::HostClient* hcp); + // for tcp fingerprint void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht, const struct in6_addr* src_ip, const uint8_t* src_mac, const snort::TcpFingerprint* tfp); @@ -88,7 +93,7 @@ public: const uint8_t* src_mac, RnaTracker* ht, const snort::Packet* p = nullptr, uint32_t event_time = 0, uint16_t proto = 0, const snort::HostMac* hm = nullptr, const snort::HostApplication* ha = nullptr, const snort::TcpFingerprint* tfp = nullptr, - void* cond_var = nullptr); + void* cond_var = nullptr, const snort::HostClient* hc = nullptr); private: const bool enabled; diff --git a/src/network_inspectors/rna/rna_logger_common.h b/src/network_inspectors/rna/rna_logger_common.h index cd25272d7..56174674c 100644 --- a/src/network_inspectors/rna/rna_logger_common.h +++ b/src/network_inspectors/rna/rna_logger_common.h @@ -27,6 +27,7 @@ #define NEW_NET_PROTOCOL 3 #define NEW_XPORT_PROTOCOL 4 #define NEW_UDP_SERVICE 6 + #define NEW_CLIENT_APP 7 #define NEW_OS 8 #define RNA_EVENT_CHANGE 1001