odp_ctxt.recheck_for_portservice_appid = true;
}
}
- else if (!(strcasecmp(conf_key, "mdns_deviceinfo")))
+ else if (!(strcasecmp(conf_key, "detector_deviceinfo")))
{
if (!(strcasecmp(conf_val, "enabled")))
{
- odp_ctxt.mdns_deviceinfo = true;
+ odp_ctxt.detector_deviceinfo = true;
}
else if (!(strcasecmp(conf_val, "disabled")))
{
- odp_ctxt.mdns_deviceinfo = false;
+ odp_ctxt.detector_deviceinfo = false;
}
}
else if (!(strcasecmp(conf_key, "bittorrent_aggressiveness")))
bool dns_host_reporting = true;
bool referred_appId_disabled = false;
bool mdns_user_reporting = true;
- bool mdns_deviceinfo = true;
+ bool detector_deviceinfo = true;
bool chp_userid_disabled = false;
bool is_host_port_app_cache_runtime = false;
bool check_host_port_app_cache = false;
#include "service_plugins/service_discovery.h"
#include "service_plugins/service_ssl.h"
+#include "pub_sub/deviceinfo_events.h"
+
using namespace snort;
using namespace std;
}
#endif
+static int detector_publish_device_info(lua_State* L)
+{
+ auto& ud = *UserData<LuaObject>::check(L, DETECTOR, 1);
+ LuaStateDescriptor* lsd = ud->validate_lua_state(true);
+ if (!lsd)
+ return 0;
+ if (!lua_istable(L, 2))
+ return 0;
+ if (!ud->get_odp_ctxt().detector_deviceinfo)
+ return 0;
+
+ DeviceInfoEvent::KeyValueVector kv_pairs;
+ std::string service_type = DEVINFO_SERVICE_NULL;
+ std::string device_name;
+
+ lua_pushnil(L);
+ while (lua_next(L, 2) != 0)
+ {
+ if (lua_type(L, -2) != LUA_TSTRING)
+ {
+ lua_pop(L, 1);
+ continue;
+ }
+ const char* key = lua_tostring(L, -2);
+ const char* value = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1) : nullptr;
+ if (!key || !value)
+ {
+ lua_pop(L, 1);
+ continue;
+ }
+ if (strcmp(key, DEVINFO_META_SERVICE_TYPE) == 0)
+ service_type = value;
+ else
+ {
+ kv_pairs.emplace_back(key, value);
+ if (strcmp(key, DEVINFO_KEY_DEVICENAME) == 0)
+ device_name = value;
+ }
+ lua_pop(L, 1);
+ }
+
+ if (kv_pairs.empty())
+ return 0;
+
+ const Packet* pkt = lsd->ldp.pkt;
+ if (!pkt)
+ return 0;
+
+ DeviceInfoEvent event(pkt, service_type, device_name, kv_pairs);
+ DataBus::publish(DataBus::get_id(deviceinfo_pub_key), DeviceInfoEventIds::DEVICEINFO, event);
+
+ return 0;
+}
+
static const luaL_Reg detector_methods[] =
{
/* Obsolete API names. No longer use these! They are here for backward
{"addCipService", detector_add_cip_service},
{"addEnipCommand", detector_add_enip_command},
+ {"publishDeviceInfo", detector_publish_device_info},
+
#ifdef REG_TEST
{"luaRemoveRegistryTableTest", lua_remove_registry_table_test},
#endif
#define MDNS_PATTERN1 "\x00\x00\x84\x00\x00\x00"
#define MDNS_PATTERN2 "\x00\x00\x08\x00\x00\x00"
#define MDNS_PATTERN3 "\x00\x00\x04\x00\x00\x00"
-#define MDNS_PATTERN4 "\x00\x00\x00\x00"
#define SRV_RECORD "\x00\x21"
#define SRV_RECORD_OFFSET 6
#define LENGTH_OFFSET 8
MatchedPatterns* next;
};
+struct MdnsKeyNormEntry
+{
+ const char* raw_key;
+ unsigned raw_key_len;
+ const char* normalized;
+};
+
+static MdnsKeyNormEntry key_norm_entries[] =
+{
+ { "md", 2, "model" },
+ { "mdl", 3, "model" },
+ { "MDL", 3, "model" },
+ { "usb_MDL", 7, "model" },
+ { "ModelName", 9, "model" },
+ { "modelid", 7, "model" },
+ { "mn", 2, "model" },
+ { "am", 2, "model" },
+ { "rpMd", 4, "model" },
+ { "mfg", 3, "manufacturer" },
+ { "MFG", 3, "manufacturer" },
+ { "usb_MFG", 7, "manufacturer" },
+ { "integrator", 10, "manufacturer" },
+ { "osxvers", 7, "osxvers" },
+ { "osvers", 6, "osxvers" },
+};
+
+struct KeyNormResult
+{
+ const char* normalized;
+ unsigned key_len;
+};
+
+static int key_norm_match(void* id, void*, int match_end_pos, void* data, void*)
+{
+ MdnsKeyNormEntry* entry = (MdnsKeyNormEntry*)id;
+ KeyNormResult* result = (KeyNormResult*)data;
+ if ((unsigned)(match_end_pos - entry->raw_key_len) == 0 && (unsigned)match_end_pos == result->key_len)
+ {
+ result->normalized = entry->normalized;
+ return 1;
+ }
+ return 0;
+}
+
static MdnsPattern patterns[] =
{
{ (const uint8_t*)PATTERN_STR_LOCAL_1, sizeof(PATTERN_STR_LOCAL_1) - 1 },
matcher.add((const char*)patterns[i].pattern, patterns[i].length, &patterns[i]);
matcher.prep();
+ for (unsigned i = 0; i < sizeof(key_norm_entries) / sizeof(*key_norm_entries); i++)
+ key_normalizer.add((const uint8_t*)key_norm_entries[i].raw_key, key_norm_entries[i].raw_key_len, &key_norm_entries[i], false);
+ key_normalizer.prep();
+
handler->register_detector(name, this, proto);
}
void MdnsServiceDetector::do_custom_reload()
{
matcher.reload();
+ key_normalizer.reload();
}
int MdnsServiceDetector::validate(AppIdDiscoveryArgs& args)
ret_val = 1;
else if (memcmp(data,MDNS_PATTERN3, sizeof(MDNS_PATTERN3)-1) == 0)
ret_val = 1;
- else if (memcmp(data,MDNS_PATTERN4, sizeof(MDNS_PATTERN4)-1) == 0)
- ret_val = 1;
else
ret_val = 0;
void MdnsServiceDetector::process_txt_record(const snort::Packet* pkt, const char* srv_original,
const char* rdata_start, uint16_t data_len, const char* packet_end,
- std::string& protocol_type, std::string& device_name,
+ std::string& service_type, std::string& device_name,
std::vector<std::pair<std::string, std::string>>& kv_pairs)
{
const char* dns_name_start = srv_original;
size_t dot_pos = device_name.find('.');
if (dot_pos != std::string::npos and dot_pos > 0)
{
- protocol_type = device_name.substr(dot_pos + DNS_LABEL_LENGTH_SKIP);
+ service_type = device_name.substr(dot_pos + DNS_LABEL_LENGTH_SKIP);
device_name = device_name.substr(0, dot_pos);
}
}
else
{
- if (!protocol_type.empty())
- protocol_type += ".";
- protocol_type += label;
+ if (!service_type.empty())
+ service_type += ".";
+ service_type += label;
}
name_parser += label_len;
{
key = clean_mdns_string(key);
value = clean_mdns_string(value);
- kv_pairs.emplace_back(key, value);
+ KeyNormResult result = { nullptr, (unsigned)key.size() };
+ key_normalizer.find_all(key.c_str(), key.size(), key_norm_match, false, &result);
+ if (result.normalized)
+ kv_pairs.emplace_back(result.normalized, value);
+ else
+ kv_pairs.emplace_back(key, value);
}
}
else
if (rdata_start + data_len > packet_end)
return -1;
- if (record_type == TXT_RECORD_TYPE and data_len > 0 and asd.get_odp_ctxt().mdns_deviceinfo)
+ if (record_type == TXT_RECORD_TYPE and data_len > 0 and asd.get_odp_ctxt().detector_deviceinfo)
{
- std::string protocol_type, device_name;
+ std::string service_type, device_name;
std::vector<std::pair<std::string, std::string>> kv_pairs;
const char* dns_name_ptr = srv_original;
process_txt_record(pkt, dns_name_ptr, rdata_start, data_len, packet_end,
- protocol_type, device_name, kv_pairs);
- if (!protocol_type.empty() || !device_name.empty())
+ service_type, device_name, kv_pairs);
+ if (!service_type.empty() || !device_name.empty())
{
- auto device_key = std::make_pair(protocol_type, device_name);
+ auto device_key = std::make_pair(service_type, device_name);
device_info_map[device_key] = std::move(kv_pairs);
}
}
else
return 0;
- if (!device_info_map.empty() and asd.get_odp_ctxt().mdns_deviceinfo)
+ if (!device_info_map.empty() and asd.get_odp_ctxt().detector_deviceinfo)
{
DeviceInfoEvent event(pkt, device_info_map);
DataBus::publish(DataBus::get_id(deviceinfo_pub_key), DeviceInfoEventIds::DEVICEINFO, event);
int reference_pointer(const char* start_ptr, const char* end_pkt, const char** resp_endptr, int* start_index,
uint16_t data_size, uint8_t* user_name_len, unsigned size, MatchedPatterns*& pattern_list);
void process_txt_record(const snort::Packet* pkt, const char* srv_original, const char* rdata_start,
- uint16_t data_len, const char* packet_end, std::string& protocol_type, std::string& device_name,
+ uint16_t data_len, const char* packet_end, std::string& service_type, std::string& device_name,
std::vector<std::pair<std::string, std::string>>& kv_pairs);
snort::SearchTool matcher;
+ snort::SearchTool key_normalizer;
};
#endif
DeviceInfoFpProcessor::~DeviceInfoFpProcessor()
{
- delete protocol_type_mpse;
+ delete service_type_mpse;
}
void DeviceInfoFpProcessor::make_mpse(bool priority)
{
if (priority)
{
- delete protocol_type_mpse;
- protocol_type_mpse = nullptr;
+ delete service_type_mpse;
+ service_type_mpse = nullptr;
}
- if (protocol_type_mpse or protocol_type_fps.empty())
+ if (service_type_mpse or service_type_fps.empty())
return;
- protocol_type_mpse = new SearchTool;
- for (std::pair<const std::string, DeviceInfoProtoFingerprint>& kv : protocol_type_fps)
- protocol_type_mpse->add(kv.second.protocol_type.c_str(), kv.second.protocol_type.size(), &kv.second);
- protocol_type_mpse->prep();
+ service_type_mpse = new SearchTool;
+ for (std::pair<const std::string, DeviceInfoProtoFingerprint>& kv : service_type_fps)
+ service_type_mpse->add(kv.second.service_type.c_str(), kv.second.service_type.size(), &kv.second);
+ service_type_mpse->prep();
}
static int collect_rows(void* id, void*, int, void* data, void*)
return 0;
}
-void DeviceInfoFpProcessor::get_rows(const char* protocol,
+void DeviceInfoFpProcessor::get_rows(const char* service,
std::vector<const DeviceInfoRowFingerprint*>& rows)
{
rows.clear();
- if (!protocol_type_mpse)
+ if (!service_type_mpse)
return;
- protocol_type_mpse->find_all(protocol, strlen(protocol), collect_rows, false, &rows);
+ service_type_mpse->find_all(service, strlen(service), collect_rows, false, &rows);
}
void DeviceInfoFpProcessor::push(const DeviceInfoRawFingerprint& raw_fp)
{
- DeviceInfoProtoFingerprint& proto_fp = protocol_type_fps[raw_fp.protocol_type];
- proto_fp.protocol_type = raw_fp.protocol_type;
+ DeviceInfoProtoFingerprint& proto_fp = service_type_fps[raw_fp.service_type];
+ proto_fp.service_type = raw_fp.service_type;
DeviceInfoRowFingerprint row;
row.fpid = raw_fp.fpid;
for (const std::pair<const std::pair<std::string, std::string>, std::vector<std::pair<std::string, std::string>>>& entry : device_info_map)
{
- const std::string& protocol_type = entry.first.first;
+ const std::string& service_type = entry.first.first;
const std::string& device_name = entry.first.second;
const std::vector<std::pair<std::string, std::string>>& txt_kv_pairs = entry.second;
- if (device_name.empty() || protocol_type.empty())
+ if (device_name.empty() || service_type.empty())
continue;
if (!is_printable_string(device_name.c_str()))
continue;
+ std::string clean_device_name = clean_field_value(device_name);
+ if (is_printable_string(clean_device_name.c_str()))
+ {
+ if (rt->set_device_name(clean_device_name.c_str()))
+ {
+ debug_logf(rna_trace, pkt, "DeviceInfo: logging CHANGE_DEVICE_NAME event, name='%s'\n",
+ clean_device_name.c_str());
+ logger.log(RNA_EVENT_CHANGE, CHANGE_DEVICE_NAME, pkt, rt,
+ reinterpret_cast<const struct in6_addr*>(pkt->flow->client_ip.get_ip6_ptr()),
+ rt->get_last_seen_mac(mac_addr), nullptr, packet_time(),
+ nullptr, clean_device_name.c_str());
+ }
+ }
+
std::vector<const DeviceInfoRowFingerprint*> rows;
- processor->get_rows(protocol_type.c_str(), rows);
+ processor->get_rows(service_type.c_str(), rows);
if (rows.empty())
{
- debug_logf(rna_trace, pkt, "DeviceInfo: no fingerprint rows found for protocol %s\n", protocol_type.c_str());
+ debug_logf(rna_trace, pkt, "DeviceInfo: no fingerprint rows found for service %s\n", service_type.c_str());
continue;
}
- std::string global_hardware_info;
+ std::vector<MatchedRowInfo> matched_rows;
+ const MatchedRowInfo* best_hardware_row = nullptr;
for (const DeviceInfoRowFingerprint* row : rows)
{
if (!rt->add_deviceinfo_fingerprint(row->fpid))
continue;
- std::string field_values[DEVICEINFO_FIELD_MAX];
+ MatchedRowInfo info;
+ info.row = row;
for (uint8_t i = 0; i < DEVICEINFO_FIELD_MAX; i++)
- field_values[i] = clean_field_value(extracted_values[i]);
-
- field_values[DEVICEINFO_FIELD_DEVICENAME] = clean_field_value(device_name);
+ info.field_values[i] = clean_field_value(extracted_values[i]);
+ info.field_values[DEVICEINFO_FIELD_DEVICENAME] = clean_field_value(device_name);
- uint8_t mask = row->field_mask;
- std::string hardware_info = field_values[DEVICEINFO_FIELD_MANUFACTURER] +
- (field_values[DEVICEINFO_FIELD_MANUFACTURER].empty() || field_values[DEVICEINFO_FIELD_MODEL].empty() ? "" : " ") +
- field_values[DEVICEINFO_FIELD_MODEL];
+ info.hardware_info = info.field_values[DEVICEINFO_FIELD_MANUFACTURER] +
+ (info.field_values[DEVICEINFO_FIELD_MANUFACTURER].empty() || info.field_values[DEVICEINFO_FIELD_MODEL].empty() ? "" : " ") +
+ info.field_values[DEVICEINFO_FIELD_MODEL];
- if (global_hardware_info.empty() && !hardware_info.empty())
- global_hardware_info = hardware_info;
+ info.has_predefined_model = (row->field_mask & DEVICEINFO_MASK_MODEL) && !row->values[DEVICEINFO_FIELD_MODEL].empty();
+ info.has_hardware = (row->field_mask & (DEVICEINFO_MASK_MODEL | DEVICEINFO_MASK_MANUFACTURER)) &&
+ !info.hardware_info.empty() && is_printable_string(info.hardware_info.c_str());
- if (is_printable_string(field_values[DEVICEINFO_FIELD_DEVICENAME].c_str()))
- {
- debug_logf(rna_trace, pkt, "DeviceInfo: logging CHANGE_DEVICE_NAME event for fingerprint %u, name='%s'\n",
- row->fpid, field_values[DEVICEINFO_FIELD_DEVICENAME].c_str());
- logger.log(RNA_EVENT_CHANGE, CHANGE_DEVICE_NAME, pkt, rt,
- reinterpret_cast<const struct in6_addr*>(pkt->flow->client_ip.get_ip6_ptr()),
- rt->get_last_seen_mac(mac_addr), row, packet_time(),
- hardware_info.c_str(), field_values[DEVICEINFO_FIELD_DEVICENAME].c_str());
-
- rt->set_device_name(field_values[DEVICEINFO_FIELD_DEVICENAME].c_str());
- }
+ if (row->field_mask & DEVICEINFO_MASK_OS)
+ info.os_cpe = row->os_prefix + info.field_values[DEVICEINFO_FIELD_OS] + row->os_postfix;
- const std::string& hw_for_os = hardware_info.empty() ? global_hardware_info : hardware_info;
- if ((mask & DEVICEINFO_MASK_OS) && is_printable_string(hw_for_os.c_str()))
- {
- std::string os_cpe = row->os_prefix + field_values[DEVICEINFO_FIELD_OS] + row->os_postfix;
- debug_logf(rna_trace, pkt, "DeviceInfo: logging NEW_OS event for fingerprint %u, os_cpe='%s'\n",
- row->fpid, os_cpe.c_str());
- std::vector<const char*> cpes;
- cpes.push_back(os_cpe.c_str());
- FpFingerprint fp;
- fp.fpid = row->fpid;
- fp.fpuuid = row->fpuuid;
- fp.fp_type = FpFingerprint::FpType::FP_TYPE_DEVICEINFO;
-
- logger.log(RNA_EVENT_NEW, NEW_OS, pkt, rt,
- reinterpret_cast<const struct in6_addr*>(pkt->flow->client_ip.get_ip6_ptr()),
- rt->get_last_seen_mac(mac_addr), &fp, &cpes, packet_time(), hw_for_os.c_str());
- }
+ matched_rows.push_back(std::move(info));
+ }
+
+ if (matched_rows.empty())
+ continue;
+
+ for (const MatchedRowInfo& info : matched_rows)
+ {
+ if (!info.has_hardware)
+ continue;
+ if (!best_hardware_row)
+ best_hardware_row = &info;
+ else if (info.has_predefined_model && !best_hardware_row->has_predefined_model)
+ best_hardware_row = &info;
+ }
+
+ const std::string& preferred_hardware_info = best_hardware_row ? best_hardware_row->hardware_info : "";
- if ((mask & (DEVICEINFO_MASK_MODEL | DEVICEINFO_MASK_MANUFACTURER)) && is_printable_string(hardware_info.c_str()))
+ bool os_logged = false;
+ for (const MatchedRowInfo& info : matched_rows)
+ {
+ if (!os_logged && (info.row->field_mask & DEVICEINFO_MASK_OS) && !info.os_cpe.empty())
{
- bool is_high_priority = (mask & DEVICEINFO_MASK_MODEL) && !row->values[DEVICEINFO_FIELD_MODEL].empty();
- if (rt->set_deviceinfo_hardware(hardware_info, is_high_priority))
+ const std::string& hw_for_os = info.hardware_info.empty() ? preferred_hardware_info : info.hardware_info;
+ if (is_printable_string(hw_for_os.c_str()))
{
- debug_logf(rna_trace, pkt, "DeviceInfo: logging NEW_OS hardware event for fingerprint %u, hardware='%s'\n",
- row->fpid, hardware_info.c_str());
+ debug_logf(rna_trace, pkt, "DeviceInfo: logging NEW_OS event for fingerprint %u, os_cpe='%s'\n",
+ info.row->fpid, info.os_cpe.c_str());
+ std::vector<const char*> cpes;
+ cpes.push_back(info.os_cpe.c_str());
+ FpFingerprint fp;
+ fp.fpid = info.row->fpid;
+ fp.fpuuid = info.row->fpuuid;
+ fp.fp_type = FpFingerprint::FpType::FP_TYPE_DEVICEINFO;
+
logger.log(RNA_EVENT_NEW, NEW_OS, pkt, rt,
reinterpret_cast<const struct in6_addr*>(pkt->flow->client_ip.get_ip6_ptr()),
- rt->get_last_seen_mac(mac_addr), row, packet_time(),
- hardware_info.c_str(), nullptr);
+ rt->get_last_seen_mac(mac_addr), &fp, &cpes, packet_time(), hw_for_os.c_str());
+ os_logged = true;
}
}
}
+
+ if (best_hardware_row && rt->set_deviceinfo_hardware(best_hardware_row->hardware_info, best_hardware_row->has_predefined_model))
+ {
+ debug_logf(rna_trace, pkt, "DeviceInfo: logging NEW_OS hardware event for fingerprint %u, hardware='%s'\n",
+ best_hardware_row->row->fpid, best_hardware_row->hardware_info.c_str());
+ logger.log(RNA_EVENT_NEW, NEW_OS, pkt, rt,
+ reinterpret_cast<const struct in6_addr*>(pkt->flow->client_ip.get_ip6_ptr()),
+ rt->get_last_seen_mac(mac_addr), best_hardware_row->row, packet_time(),
+ best_hardware_row->hardware_info.c_str(), nullptr);
+ }
}
}
rawfp.fpid = 100606;
rawfp.fp_type = 15;
rawfp.fpuuid = "680f888c-8f20-4fed-ad9b-c9875d206fcb";
- rawfp.protocol_type = "_airplay._tcp.local";
+ rawfp.service_type = "_airplay._tcp.local";
rawfp.manufacturer_pattern = "manufacturer=";
rawfp.model_pattern = "model=";
processor->push(rawfp);
rawfp.fpid = 100604;
rawfp.fp_type = 15;
rawfp.fpuuid = "6a23f14f-e02a-46bd-95d3-e18853083dc3";
- rawfp.protocol_type = "_printer._tcp.local";
+ rawfp.service_type = "_printer._tcp.local";
rawfp.manufacturer_pattern = "usb_MFG=";
rawfp.manufacturer = "HP";
rawfp.model_pattern = "usb_MDL=";
fp1.fpid = 100601;
fp1.fp_type = 15;
fp1.fpuuid = "ecd3e238-44e1-4cb3-8383-49d83f4f8d5b";
- fp1.protocol_type = "_mediaremotetv._tcp.local";
+ fp1.service_type = "_mediaremotetv._tcp.local";
fp1.model_pattern = "model=";
processor.push(fp1);
fp2.fpid = 100602;
fp2.fp_type = 15;
fp2.fpuuid = "cefa3bb2-eb5f-447e-aa7d-64bda5a49ae5";
- fp2.protocol_type = "_mediaremotetv._tcp.local";
+ fp2.service_type = "_mediaremotetv._tcp.local";
fp2.model_pattern = "model=";
fp2.manufacturer_pattern = "mfg=";
processor.push(fp2);
rawfp.fpid = 100611;
rawfp.fp_type = 15;
rawfp.fpuuid = "google-cast-uuid";
- rawfp.protocol_type = "_googlecast._tcp.local";
+ rawfp.service_type = "_googlecast._tcp.local";
rawfp.model_pattern = "md=";
rawfp.model = "Chromecast";
rawfp.manufacturer_pattern = "fn=";
rawfp.fpid = 100600;
rawfp.fp_type = 15;
rawfp.fpuuid = "d827d911-e50e-404f-9f5d-5aa56b580b35";
- rawfp.protocol_type = "_hap._tcp.local";
+ rawfp.service_type = "_hap._tcp.local";
rawfp.manufacturer_pattern = "md=";
rawfp.manufacturer = "Apple";
rawfp.mac_addr = "A4:83:E7";
rawfp.fpid = 100700;
rawfp.fp_type = 15;
rawfp.fpuuid = "field-mask-test-uuid";
- rawfp.protocol_type = "_test._tcp.local";
+ rawfp.service_type = "_test._tcp.local";
rawfp.manufacturer_pattern = "mfg=";
rawfp.model_pattern = "mdl=";
rawfp.os_pattern = "os=";
class SO_PUBLIC DeviceInfoProtoFingerprint
{
public:
- std::string protocol_type;
+ std::string service_type;
std::vector<DeviceInfoRowFingerprint> rows;
};
class SO_PUBLIC DeviceInfoRawFingerprint : public FpFingerprint
{
public:
- std::string protocol_type;
+ std::string service_type;
std::string manufacturer_pattern;
std::string manufacturer;
std::string model_pattern;
void make_mpse(bool priority = false);
void push(const DeviceInfoRawFingerprint&);
- void get_rows(const char* protocol, std::vector<const DeviceInfoRowFingerprint*>& rows);
+ void get_rows(const char* service, std::vector<const DeviceInfoRowFingerprint*>& rows);
- bool has_pattern() const { return protocol_type_mpse != nullptr; }
+ bool has_pattern() const { return service_type_mpse != nullptr; }
private:
- std::unordered_map<std::string, DeviceInfoProtoFingerprint> protocol_type_fps;
- snort::SearchTool* protocol_type_mpse = nullptr;
+ std::unordered_map<std::string, DeviceInfoProtoFingerprint> service_type_fps;
+ snort::SearchTool* service_type_mpse = nullptr;
};
}
+struct MatchedRowInfo
+{
+ const snort::DeviceInfoRowFingerprint* row = nullptr;
+ std::string field_values[snort::DEVICEINFO_FIELD_MAX];
+ std::string hardware_info;
+ std::string os_cpe;
+ bool has_predefined_model = false;
+ bool has_hardware = false;
+};
+
class RnaDeviceDiscovery
{
public:
{ "flags", Parameter::PT_INT, "0:max32", nullptr,
"smb flags" },
- { "protocol_type", Parameter::PT_STRING, nullptr, nullptr,
- "deviceinfo protocol type" },
+ { "service_type", Parameter::PT_STRING, nullptr, nullptr,
+ "deviceinfo service type" },
{ "manufacturer_pattern", Parameter::PT_STRING, nullptr, nullptr,
"deviceinfo manufacturer pattern" },
deviceinfo_fingerprint.fpid = 0;
deviceinfo_fingerprint.fp_type = 0;
deviceinfo_fingerprint.fpuuid.clear();
- deviceinfo_fingerprint.protocol_type.clear();
+ deviceinfo_fingerprint.service_type.clear();
deviceinfo_fingerprint.manufacturer_pattern.clear();
deviceinfo_fingerprint.manufacturer.clear();
deviceinfo_fingerprint.model_pattern.clear();
fingerprint.smb_minor = v.get_uint32();
else if (v.is("flags"))
fingerprint.smb_flags = v.get_uint32();
- else if (v.is("protocol_type"))
- deviceinfo_fingerprint.protocol_type = v.get_string();
+ else if (v.is("service_type"))
+ deviceinfo_fingerprint.service_type = v.get_string();
else if (v.is("manufacturer_pattern"))
deviceinfo_fingerprint.manufacturer_pattern = v.get_string();
else if (v.is("manufacturer"))
const PubKey deviceinfo_pub_key { "deviceinfo", DeviceInfoEventIds::num_ids };
+constexpr const char* DEVINFO_SERVICE_NULL = "*";
+constexpr const char* DEVINFO_META_SERVICE_TYPE = "service_type";
+constexpr const char* DEVINFO_KEY_DEVICENAME = "devicename";
+
// DataEvent that contains device identification data including protocol type, device name, and attributes
class DeviceInfoEvent : public DataEvent
{
public:
// Composite key for unique device identification consisting of protocol type and device name
- // The protocol type identifies the network protocol (e.g., "_airplay._tcp.local", "_http._tcp.local")
+ // The service type identifies the service advertised in service discovery protocols ( e.g. mDNS/DNS-SD service )
+ // wherever applicable or it should be a wildcard
// The device name identifies the specific device instance (e.g., "John's iPhone", "Office Printer")
using DeviceKey = std::pair<std::string, std::string>;
// Maps device identifiers to their corresponding attribute collections
// Allows multiple devices to be tracked within a single event, each with their own attributes
- // Key: (protocol_type, device_name), Value: vector of device attribute key-value pairs
+ // Key: (service_type, device_name), Value: vector of device attribute key-value pairs
using DeviceInfoMap = std::map<DeviceKey, KeyValueVector>;
// Constructor for creating an event containing multiple devices with their attributes
// Constructor for creating an event containing a single device with its attributes
// Used when network protocol analysis identifies a specific device and its characteristics
- // The device is uniquely identified by protocol type and device name combination
- DeviceInfoEvent(const snort::Packet* p, const std::string& protocol_type,
+ // The device is uniquely identified by service type and device name combination
+ DeviceInfoEvent(const snort::Packet* p, const std::string& service_type,
const std::string& device_name, const KeyValueVector& kv_pairs)
: pkt(p)
{
- device_info_map[std::make_pair(protocol_type, device_name)] = kv_pairs;
+ device_info_map[std::make_pair(service_type, device_name)] = kv_pairs;
}
const Packet* get_packet() const override
const DeviceInfoMap& get_device_info_map() const
{ return device_info_map; }
- // Retrieve device attributes for a specific device identified by protocol type and device name
+ // Retrieve device attributes for a specific device identified by service type and device name
// Returns nullptr if the specified device is not found in this event
// Used by subscribers to extract specific device information from the event
- const KeyValueVector* get_key_value_pairs(const std::string& protocol_type,
+ const KeyValueVector* get_key_value_pairs(const std::string& service_type,
const std::string& device_name) const
{
- auto it = device_info_map.find(std::make_pair(protocol_type, device_name));
+ auto it = device_info_map.find(std::make_pair(service_type, device_name));
return (it != device_info_map.end()) ? &it->second : nullptr;
}