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;
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++;
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;
}
}
}
-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);
+ ", 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 ? ", " : "");
+ }
}
}
AppId id;
char version[INFO_SIZE] = { 0 };
AppId service;
+ std::vector<AppId, HostCacheAllocIp<AppId>> payloads;
};
struct DeviceFingerprint
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);
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);
// 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.
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);
}
}
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;
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,
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,
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*,
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;
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();
{
if (is_inter_group_flow())
return pkth->ingress_group;
-
+
return DAQ_PKTHDR_UNKNOWN;
}
{
if (is_inter_group_flow())
return pkth->egress_group;
-
+
return DAQ_PKTHDR_UNKNOWN;
}