From: Masud Hasan (mashasan) Date: Mon, 19 Oct 2020 20:34:31 +0000 (+0000) Subject: Merge pull request #2545 in SNORT/snort3 from ~MMATIRKO/snort3:payload_disco_2 to... X-Git-Tag: 3.0.3-3~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e972c74648ec45418fa37443c17eabb447af701;p=thirdparty%2Fsnort3.git Merge pull request #2545 in SNORT/snort3 from ~MMATIRKO/snort3:payload_disco_2 to master Squashed commit of the following: commit 926aadab5dd20e0373a92b425d31fae49a4385e8 Author: Michael Matirko Date: Thu Oct 8 16:26:44 2020 -0400 rna: change logic for payload discovery, eventing --- diff --git a/src/host_tracker/host_tracker.cc b/src/host_tracker/host_tracker.cc index 2180b2b0c..1cb306a68 100644 --- a/src/host_tracker/host_tracker.cc +++ b/src/host_tracker/host_tracker.cc @@ -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 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 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 ? ", " : ""); + } } } diff --git a/src/host_tracker/host_tracker.h b/src/host_tracker/host_tracker.h index b72ac1282..34961f514 100644 --- a/src/host_tracker/host_tracker.h +++ b/src/host_tracker/host_tracker.h @@ -119,6 +119,7 @@ struct HostClient AppId id; char version[INFO_SIZE] = { 0 }; AppId service; + std::vector> 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. diff --git a/src/network_inspectors/rna/rna_app_discovery.cc b/src/network_inspectors/rna/rna_app_discovery.cc index cf7ba5322..f7cf148e8 100644 --- a/src/network_inspectors/rna/rna_app_discovery.cc +++ b/src/network_inspectors/rna/rna_app_discovery.cc @@ -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, diff --git a/src/network_inspectors/rna/rna_app_discovery.h b/src/network_inspectors/rna/rna_app_discovery.h index e7c468be9..c647404c7 100644 --- a/src/network_inspectors/rna/rna_app_discovery.h +++ b/src/network_inspectors/rna/rna_app_discovery.h @@ -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*, diff --git a/src/protocols/packet.h b/src/protocols/packet.h index 345c47d90..5f42bdddf 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -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; }