for ( auto& ahm : macs )
if ( !memcmp(mac, ahm.mac, MAC_SIZE) )
{
- if (!ahm.visibility)
+ if ( !ahm.visibility )
return false;
hm = static_cast<HostMac>(ahm);
for ( const auto& hm : macs )
if ( !max_hm or max_hm->last_seen < hm.last_seen )
- if (hm.visibility)
+ if ( hm.visibility )
max_hm = &hm;
if ( max_hm )
for ( auto& hm : macs )
if ( !memcmp(mac, hm.mac, MAC_SIZE) )
{
- if (hm.ttl < new_ttl and hm.visibility)
+ if ( hm.ttl < new_ttl and hm.visibility )
{
hm.ttl = new_ttl;
return true;
{
s.appid = appid;
s.inferred_appid = inferred_appid;
- if (added)
+ if ( added )
*added = true;
}
services.emplace_back(port, proto, appid, inferred_appid);
num_visible_services++;
- if (added)
+ if ( added )
*added = true;
return true;
{
s.appid = app.appid;
s.inferred_appid = app.inferred_appid;
- if (added)
+ if ( added )
*added = true;
}
if ( s.visibility == false )
{
- if (added)
+ if ( added )
*added = true;
s.visibility = true;
num_visible_services++;
{
if ( s.port == port and s.proto == proto )
{
- if (s.visibility == false)
+ if ( s.visibility == false )
return nullptr;
if ( appid != APP_ID_NONE and s.appid == appid )
return &s;
lock_guard<mutex> lck(host_tracker_lock);
for ( auto s = services.begin(); s != services.end(); )
{
- if (s->inferred_appid)
+ if ( s->inferred_appid )
s = services.erase(s);
else
s++;
return result.second;
}
+bool HostTracker::set_netbios_name(const char* nb_name)
+{
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+ if ( nb_name && netbios_name != nb_name )
+ {
+ netbios_name = nb_name;
+ return true;
+ }
+ else
+ return false;
+}
+
bool HostTracker::set_visibility(bool v)
{
// get_valid_id may use its own lock, so get this outside our lock
visibility = v ? container_id : HostCacheIp::invalid_id;
- if (visibility == HostCacheIp::invalid_id)
+ if ( visibility == HostCacheIp::invalid_id )
{
- for (auto& proto : network_protos)
+ for ( auto& proto : network_protos )
proto.second = false;
- for (auto& proto : xport_protos)
+ for ( auto& proto : xport_protos )
proto.second = false;
- for (auto& mac_t : macs)
+ for ( auto& mac_t : macs )
mac_t.visibility = false;
num_visible_macs = 0;
- for (auto& s : services)
+ for ( auto& s : services )
{
s.visibility = false;
- for (auto& info : s.info)
+ for ( auto& info : s.info )
info.visibility = false;
s.user[0] = '\0';
set_payload_visibility_no_lock(s.payloads, false, s.num_visible_payloads);
// to avoid the deadlock from the first case, but we SHOULD lock on
// a different mutex to protect the HT::flows set.
lock_guard<mutex> lck(flows_lock);
- for (auto& rna_flow : flows)
+ for ( auto& rna_flow : flows )
{
rna_flow->clear_ht(*this);
}
for ( const auto& s : services )
{
- if (s.visibility == false)
+ if ( s.visibility == false )
continue;
str += "\n port: " + to_string(s.port)
if ( !s.info.empty() )
for ( const auto& i : s.info )
{
- if (i.visibility == false)
+ if ( i.visibility == false )
continue;
if ( i.vendor[0] != '\0' )
for ( const auto& fpid : udp_fpids )
str += to_string(fpid) + (--total ? ", " : "");
}
+
+ if ( !netbios_name.empty() )
+ str += "\nnetbios name: " + netbios_name;
}
return ++nat_count;
}
+ bool set_netbios_name(const char*);
+
bool set_visibility(bool v = true);
bool is_visible() const;
std::set<uint32_t, std::less<uint32_t>, HostCacheAllocIp<uint32_t>> tcp_fpids;
std::set<uint32_t, std::less<uint32_t>, HostCacheAllocIp<uint32_t>> udp_fpids;
std::vector<DeviceFingerprint, HostDeviceFpAllocator> ua_fps;
+ std::string netbios_name;
// flows that we belong to
std::unordered_set<RNAFlow*> flows;
api.client.reset();
api.payload.reset();
- snort_free(netbios_name);
snort_free(netbios_domain);
if (tsession)
void AppIdSession::reset_session_data(AppidChangeBits& change_bits)
{
delete_session_data();
- netbios_name = nullptr;
netbios_domain = nullptr;
api.hsessions.clear();
std::map<std::string, ClientDetector*> client_candidates;
bool tried_reverse_service = false;
- // FIXIT-RC netbios_name is never set to a valid value; set when netbios_domain is set?
- char* netbios_name = nullptr;
char* netbios_domain = nullptr;
TlsSession* tsession = nullptr;
api.set_tls_host(tls_host);
}
+ void set_netbios_name(AppidChangeBits& change_bits, const char *name)
+ {
+ api.set_netbios_name(change_bits, name);
+ }
+
OdpContext& get_odp_ctxt() const
{
return odp_ctxt;
(asd->service_disco_state!= APPID_DISCO_STATE_FINISHED)));
}
+const char* AppIdSessionApi::get_netbios_name() const
+{
+ return netbios_name;
+}
+
+void AppIdSessionApi::set_netbios_name(AppidChangeBits& change_bits, const char* name)
+{
+ if (netbios_name)
+ {
+ if (strcmp(netbios_name, name) == 0)
+ return;
+ snort_free(netbios_name);
+ }
+ netbios_name = snort_strdup(name);
+ change_bits.set(APPID_NETBIOS_NAME_BIT);
+}
+
void AppIdSessionApi::set_ss_application_ids(AppId service_id, AppId client_id,
AppId payload_id, AppId misc_id, AppId referred_id, AppidChangeBits& change_bits, Flow& flow)
{
const AppIdHttpSession* get_http_session(uint32_t stream_index = 0) const;
const char* get_tls_host() const;
bool is_http_inspection_done() const;
+ const char* get_netbios_name() const;
// For protocols such as HTTP2 which can have multiple streams within a single flow,
// get_first_stream_* methods return the appids in the first stream seen in a packet.
snort::SfIp initiator_ip;
ServiceAppDescriptor service;
char* tls_host = nullptr;
+ char* netbios_name = nullptr;
std::string session_id;
bool user_logged_in = false;
AppId referred, AppidChangeBits& change_bits, Flow& flow);
void set_ss_application_ids(AppId client, AppId payload, AppidChangeBits& change_bits, Flow& flow);
void set_application_ids_service(AppId service_id, AppidChangeBits& change_bits, Flow& flow);
+ void set_netbios_name(AppidChangeBits& change_bits, const char* name);
AppIdHttpSession* get_hsession(uint32_t stream_index = 0) const;
{
delete_all_http_sessions();
snort_free(tls_host);
+ snort_free(netbios_name);
delete dsession;
}
int incompatible_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir);
int fail_service(AppIdSession&, const snort::Packet*, AppidSessionDirection dir);
- void add_host_info(AppIdSession&, SERVICE_HOST_INFO_CODE, const void*)
- {
- // FIXIT-L - this function is called but does nothing... what if anything should it do...
- }
-
void add_miscellaneous_info(AppIdSession& asd, AppId miscId)
{
asd.misc_app_id = miscId;
#define STATE_ID_NEEDED_DUPE_DETRACT_COUNT 3
#define STATE_ID_MAX_VALID_COUNT 5
-enum SERVICE_HOST_INFO_CODE
-{
- SERVICE_HOST_INFO_NETBIOS_NAME = 1
-};
-
/* Service state stored per flow, which acts based on global ServiceState
* at the beginning of the flow, then independently do service discovery, and
* synchronize findings at the end of service discovery by the flow.
return 0;
}
-static int netbios_validate_label(const uint8_t** data,
- const uint8_t* const end)
+static int netbios_validate_label(const uint8_t** data, const uint8_t* const end)
{
const NBNSLabel* lbl;
uint16_t tmp;
}
not_mailslot:
if (source_name[0])
- add_host_info(args.asd, SERVICE_HOST_INFO_NETBIOS_NAME, source_name);
+ args.asd.set_netbios_name(args.change_bits, (const char *)source_name);
args.asd.set_session_flags(APPID_SESSION_CONTINUE);
goto success;
case NBDGM_TYPE_ERROR:
{
snort_free(sd);
}
-
ServiceDetector*, ServiceDiscoveryState*) { return 0; }
int ServiceDiscovery::add_service_port(AppIdDetector*,
const ServiceDetectorPort&) { return APPID_EINVALID; }
+void AppIdSessionApi::set_netbios_name(AppidChangeBits&, const char*) {}
TEST_GROUP(service_netbios_test){};
}
return 0;
}
+
int dcerpc_validate(const uint8_t*, int){return 0; }
AppIdDiscovery::~AppIdDiscovery() { }
void show_stats(PegCount*, const PegInfo*, unsigned, const char*) { }
CHECK_EQUAL(service, APPID_UT_ID);
CHECK_EQUAL(client, APPID_UT_ID);
CHECK_EQUAL(payload, APPID_UT_ID);
- STRCMP_EQUAL("Published change_bits == 00000000000000000", test_log);
+ STRCMP_EQUAL("Published change_bits == 000000000000000000", test_log);
service = APP_ID_NONE;
client = APP_ID_NONE;
STRCMP_EQUAL(mock_session->tsession->get_tls_host(), APPID_UT_TLS_HOST);
STRCMP_EQUAL(mock_session->tsession->get_tls_first_alt_name(), APPID_UT_TLS_HOST);
STRCMP_EQUAL(mock_session->tsession->get_tls_cname(), APPID_UT_TLS_HOST);
- STRCMP_EQUAL("Published change_bits == 00000000100011000", test_log);
+ STRCMP_EQUAL("Published change_bits == 000000000100011000", test_log);
mock_session->tsession->set_tls_host("www.cisco.com", 13, change_bits);
mock_session->tsession->set_tls_cname("www.cisco.com", 13, change_bits);
STRCMP_EQUAL(mock_session->tsession->get_tls_host(), APPID_UT_TLS_HOST);
STRCMP_EQUAL(mock_session->tsession->get_tls_cname(), APPID_UT_TLS_HOST);
STRCMP_EQUAL(mock_session->tsession->get_tls_org_unit(), "Cisco");
- STRCMP_EQUAL("Published change_bits == 00000000100011000", test_log);
+ STRCMP_EQUAL("Published change_bits == 000000000100011000", test_log);
string host = "";
val = appid_api.ssl_app_group_id_lookup(flow, (const char*)(host.c_str()), nullptr,
STRCMP_EQUAL(mock_session->tsession->get_tls_host(), APPID_UT_TLS_HOST);
STRCMP_EQUAL(mock_session->tsession->get_tls_cname(), APPID_UT_TLS_HOST);
STRCMP_EQUAL(mock_session->tsession->get_tls_org_unit(), "Google");
- STRCMP_EQUAL("Published change_bits == 00000000100000000", test_log);
+ STRCMP_EQUAL("Published change_bits == 000000000100000000", test_log);
mock().checkExpectations();
}
// Detect changes in service, client, payload, and misc appid
mock().checkExpectations();
- STRCMP_EQUAL("Published change_bits == 00000000001111100", test_log);
+ STRCMP_EQUAL("Published change_bits == 000000000001111100", test_log);
delete &asd->get_api();
delete asd;
// Detect changes in service, client, payload, and misc appid
mock().checkExpectations();
- STRCMP_EQUAL("Published change_bits == 00000000001111100", test_log);
+ STRCMP_EQUAL("Published change_bits == 000000000001111100", test_log);
delete &asd->get_api();
delete asd;
delete flow;
change_bits_to_string(change_bits, str);
STRCMP_EQUAL(str.c_str(), "created, reset, service, client, payload, misc, referred, host,"
" tls-host, url, user-agent, response, referrer, dns-host, service-info, client-info,"
- " user-info");
+ " user-info, netbios-name");
// Failure of this test is a reminder that enum is changed, hence translator needs update
- CHECK_EQUAL(APPID_MAX_BIT, 17);
+ CHECK_EQUAL(APPID_MAX_BIT, 18);
}
int main(int argc, char** argv)
char const* APPID_UT_SERVICE_IP_ADDR = "192.168.0.2";
char const* APPID_UT_INITIATOR_IP_ADDR = "192.168.0.3";
-char const* APPID_UT_NETBIOS_NAME = "I AM NETBIOS!";
-
char const* APPID_ID_UT_DNS_HOST = "delphi.opendns.com";
#define APPID_UT_DNS_HOST_OFFSET 22
#define APPID_UT_DNS_PATTERN_CNAME_REC 5
set_service_ip(svc_ip);
api.initiator_ip.pton(AF_INET, APPID_UT_INITIATOR_IP_ADDR);
- netbios_name = snort_strdup(APPID_UT_NETBIOS_NAME);
-
api.dsession = new MockAppIdDnsSession;
tp_app_id = APPID_UT_ID;
set_service_id(APPID_UT_ID + 1, odp_ctxt);
AppIdSession::~AppIdSession()
{
delete tsession;
- if (netbios_name)
- snort_free(netbios_name);
}
void* AppIdSession::get_flow_data(unsigned) const
}
}
}
+
+ if ( appid_change_bits[APPID_NETBIOS_NAME_BIT] )
+ {
+ const char* netbios_name = appid_session_api.get_netbios_name();
+ discover_netbios_name(p, filter, rna_flow, logger, netbios_name);
+ }
}
bool RnaAppDiscovery::discover_service(const Packet* p, DiscoveryFilter& filter, RNAFlow* rna_flow,
RnaTracker htp;
SfIp ip = p->flow->server_ip;
- if (!is_client)
+ if ( !is_client )
{
if ( !filter.is_host_monitored(p, nullptr, nullptr, FlowCheckDirection::DF_SERVER) )
return false;
HostClient hc(client, nullptr, service);
new_client_payload = crt->add_client_payload(hc, payload, max_payloads);
- if (new_client_payload)
+ if ( new_client_payload )
logger.log(RNA_EVENT_CHANGE, CHANGE_CLIENT_APP_UPDATE, p, &crt,
(const struct in6_addr*) p->flow->client_ip.get_ip6_ptr(),
crt->get_last_seen_mac(), &hc);
{
RnaTracker htp;
SfIp ip = p->flow->server_ip;
- if (!is_client)
+ if ( !is_client )
{
if ( !filter.is_host_monitored(p, nullptr, nullptr, FlowCheckDirection::DF_SERVER) )
return;
}
}
+void RnaAppDiscovery::discover_netbios_name(const snort::Packet* p, DiscoveryFilter& filter,
+ RNAFlow* rna_flow, RnaLogger& logger, const char* nb_name)
+{
+ RnaTracker rt;
+ if ( p->is_from_server() )
+ {
+ if ( !filter.is_host_monitored(p, nullptr, nullptr, FlowCheckDirection::DF_SERVER) )
+ return;
+ rt = get_server_rna_tracker(p, rna_flow);
+ }
+ else
+ {
+ if ( !filter.is_host_monitored(p, nullptr, nullptr, FlowCheckDirection::DF_CLIENT) )
+ return;
+ rt = get_client_rna_tracker(p, rna_flow);
+ }
+
+ if ( !rt or !rt->is_visible() )
+ return;
+ rt->update_last_seen();
+
+ if ( rt->set_netbios_name(nb_name) )
+ {
+ const auto& src_ip = p->ptrs.ip_api.get_src();
+ const auto& src_ip_ptr = (const struct in6_addr*) src_ip->get_ip6_ptr();
+ const auto& src_mac = layer::get_eth_layer(p)->ether_src;
+
+ logger.log(RNA_EVENT_CHANGE, CHANGE_NETBIOS_NAME, src_ip_ptr, src_mac,
+ &rt, p, (uint32_t) packet_time(), 0, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, APP_ID_NONE, nullptr, false, 0, 0, nullptr, nb_name);
+ }
+}
+
void RnaAppDiscovery::analyze_user_agent_fingerprint(const Packet* p, DiscoveryFilter& filter,
RNAFlow* rna_flow, const char* host, const char* uagent, RnaLogger& logger,
UaFpProcessor& processor)
static void discover_banner(const snort::Packet*, DiscoveryFilter&, RNAFlow*, IpProtocol,
RnaLogger&, AppId);
+
+ static void discover_netbios_name(const snort::Packet*, DiscoveryFilter&,
+ RNAFlow*, RnaLogger&, const char*);
+
private:
static void update_service_info(const snort::Packet*, DiscoveryFilter&, RNAFlow*, IpProtocol,
uint16_t, const char* vendor, const char* version, RnaLogger&, RnaConfig*, AppId service,
uint16_t proto, const HostMac* hm, const HostApplication* ha,
const FpFingerprint* fp, void* cond_var, const HostClient* hc,
const char* user, AppId appid, const char* di, bool jb, uint32_t lease,
- uint32_t netmask, const struct in6_addr* router)
+ uint32_t netmask, const struct in6_addr* router, const char* nb_name)
{
if ( !enabled )
return false;
assert(ht);
RnaLoggerEvent rle(type, subtype, src_mac, ht, hm, proto, cond_var,
- ha, fp, hc, user, appid, di, jb, lease, netmask, router, p);
+ ha, fp, hc, user, appid, di, jb, lease, netmask, router, p, nb_name);
if ( src_ip and (!IN6_IS_ADDR_V4MAPPED(src_ip) or src_ip->s6_addr32[3]) )
rle.ip = src_ip;
else
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, uint32_t ls, uint32_t nm,
- const struct in6_addr* rtr, const snort::Packet* p) : type(t), subtype(st),
+ const struct in6_addr* rtr, const snort::Packet* p, const char* nb_name) : 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), lease(ls), netmask(nm),
- router(rtr), pkt(p) { }
+ router(rtr), pkt(p), netbios_name(nb_name) { }
uint32_t event_time = 0;
uint16_t type;
uint32_t netmask;
const struct in6_addr* router;
const snort::Packet* pkt;
+ const char* netbios_name = nullptr;
};
class RnaLogger
void* cond_var = nullptr, const snort::HostClient* hc = nullptr,
const char* user = nullptr, AppId appid = APP_ID_NONE, const char* device_info = nullptr,
bool jail_broken = false, uint32_t lease = 0, uint32_t netmask = 0,
- const struct in6_addr* router = nullptr);
+ const struct in6_addr* router = nullptr, const char* nb_name = nullptr);
private:
const bool enabled;
#define CHANGE_HOST_UPDATE 15
#define CHANGE_HOST_TYPE 16
#define CHANGE_VLAN_TAG 18
+ #define CHANGE_NETBIOS_NAME 21
#define CHANGE_BANNER_UPDATE 24
#define CHANGE_CLIENT_APP_UPDATE 32
#define CHANGE_FULL_DHCP_INFO 33
APPID_SERVICE_INFO_BIT,
APPID_CLIENT_INFO_BIT,
APPID_USER_INFO_BIT,
+ APPID_NETBIOS_NAME_BIT,
APPID_MAX_BIT
};
--n? str.append("client-info, ") : str.append("client-info");
if (change_bits.test(APPID_USER_INFO_BIT))
--n? str.append("user-info, ") : str.append("user-info");
+ if (change_bits.test(APPID_NETBIOS_NAME_BIT))
+ --n? str.append("netbios-name, ") : str.append("netbios-name");
if (n != 0) // make sure all bits from AppidChangeBit enum get translated
str.append("change_bits_to_string error!");
}