From: Mike Stepanek (mstepane) Date: Tue, 11 Sep 2018 18:32:28 +0000 (-0400) Subject: Merge pull request #1357 in SNORT/snort3 from firewall_appid_pub_sub to master X-Git-Tag: 3.0.0-248~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6a23d3412a25b315c806ae9a17a9b68d9e188a4b;p=thirdparty%2Fsnort3.git Merge pull request #1357 in SNORT/snort3 from firewall_appid_pub_sub to master Squashed commit of the following: commit 1216e90c23db8393f515bd5892c646a76e1be7c8 Author: Masud Hasan Date: Tue Sep 4 11:12:54 2018 -0400 appid: Supporting pub-sub mechanism for app changes --- diff --git a/src/network_inspectors/appid/appid_api.cc b/src/network_inspectors/appid/appid_api.cc index e00ac9cee..d85467e83 100644 --- a/src/network_inspectors/appid/appid_api.cc +++ b/src/network_inspectors/appid/appid_api.cc @@ -167,8 +167,7 @@ uint32_t AppIdApi::consume_ha_state(Flow& flow, const uint8_t* buf, uint8_t, IpP if( (appHA->flags & APPID_HA_FLAGS_TP_DONE) && asd->tpsession ) { #ifdef ENABLE_APPID_THIRD_PARTY - if( asd->tpsession) - asd->tpsession->set_state(TP_STATE_TERMINATED); + asd->tpsession->set_state(TP_STATE_TERMINATED); #endif asd->set_session_flags(APPID_SESSION_NO_TPI); } diff --git a/src/network_inspectors/appid/appid_app_descriptor.h b/src/network_inspectors/appid/appid_app_descriptor.h index a3023749f..8106bd166 100644 --- a/src/network_inspectors/appid/appid_app_descriptor.h +++ b/src/network_inspectors/appid/appid_app_descriptor.h @@ -47,11 +47,11 @@ public: my_version.clear(); } - virtual void update(AppId id, char* vendor, char* version) + virtual void update(AppId id, char* vendor, char* version, AppidChangeBits& change_bits) { set_id(id); set_vendor(vendor); - set_version(version); + set_version(version, change_bits); } virtual void update_stats(AppId id) = 0; @@ -89,10 +89,13 @@ public: return my_version.empty() ? nullptr : my_version.c_str(); } - void set_version(const char* version) + void set_version(const char* version, AppidChangeBits& change_bits) { if ( version ) + { my_version = version; + change_bits.set(APPID_VERSION_BIT); + } } private: diff --git a/src/network_inspectors/appid/appid_detector.cc b/src/network_inspectors/appid/appid_detector.cc index 9913f36d0..c3cf10158 100644 --- a/src/network_inspectors/appid/appid_detector.cc +++ b/src/network_inspectors/appid/appid_detector.cc @@ -66,12 +66,12 @@ int AppIdDetector::data_add(AppIdSession& asd, void* data, AppIdFreeFCN fcn) return asd.add_flow_data(data, flow_data_index, fcn); } -void AppIdDetector::add_info(AppIdSession& asd, const char* info) +void AppIdDetector::add_info(AppIdSession& asd, const char* info, AppidChangeBits& change_bits) { AppIdHttpSession* hsession = asd.get_http_session(); if ( !hsession->get_field(MISC_URL_FID) ) - hsession->set_field(MISC_URL_FID, new std::string(info)); + hsession->set_field(MISC_URL_FID, new std::string(info), change_bits); } void AppIdDetector::add_user(AppIdSession& asd, const char* username, AppId appId, bool success) @@ -89,10 +89,10 @@ void AppIdDetector::add_payload(AppIdSession& asd, AppId payload_id) } void AppIdDetector::add_app(AppIdSession& asd, AppId service_id, AppId client_id, - const char* version) + const char* version, AppidChangeBits& change_bits) { if ( version ) - asd.client.set_version(version); + asd.client.set_version(version, change_bits); asd.set_client_detected(); asd.client_inferred_service_id = service_id; diff --git a/src/network_inspectors/appid/appid_detector.h b/src/network_inspectors/appid/appid_detector.h index a02737da5..66f4edddb 100644 --- a/src/network_inspectors/appid/appid_detector.h +++ b/src/network_inspectors/appid/appid_detector.h @@ -75,8 +75,9 @@ typedef std::vector ServiceDetectorPorts; class AppIdDiscoveryArgs { public: - AppIdDiscoveryArgs(const uint8_t* data, uint16_t size, AppidSessionDirection dir, AppIdSession& asd, - snort::Packet* p) : data(data), size(size), dir(dir), asd(asd), pkt(p), config(asd.config) + AppIdDiscoveryArgs(const uint8_t* data, uint16_t size, AppidSessionDirection dir, + AppIdSession& asd, snort::Packet* p, AppidChangeBits& cb) : data(data), + size(size), dir(dir), asd(asd), pkt(p), config(asd.config), change_bits(cb) {} const uint8_t* data; @@ -85,6 +86,7 @@ public: AppIdSession& asd; snort::Packet* pkt; const AppIdConfig* config = nullptr; + AppidChangeBits& change_bits; }; // These numbers are what Lua (VDB/ODP) gives us. If these numbers are ever changed, @@ -117,10 +119,10 @@ public: virtual void* data_get(AppIdSession&); virtual int data_add(AppIdSession&, void*, AppIdFreeFCN); - virtual void add_info(AppIdSession&, const char*); + virtual void add_info(AppIdSession&, const char*, AppidChangeBits&); virtual void add_user(AppIdSession&, const char*, AppId, bool); virtual void add_payload(AppIdSession&, AppId); - virtual void add_app(AppIdSession&, AppId, AppId, const char*); + virtual void add_app(AppIdSession&, AppId, AppId, const char*, AppidChangeBits&); virtual void finalize_patterns() {} const char* get_code_string(APPID_STATUS_CODE) const; diff --git a/src/network_inspectors/appid/appid_discovery.cc b/src/network_inspectors/appid/appid_discovery.cc index 51ef5b594..7fe94da7a 100644 --- a/src/network_inspectors/appid/appid_discovery.cc +++ b/src/network_inspectors/appid/appid_discovery.cc @@ -148,9 +148,26 @@ void AppIdDiscovery::do_application_discovery(Packet* p, AppIdInspector& inspect return; AppId service_id; - bool is_discovery_done = do_discovery(p, *asd, protocol, direction, service_id); + AppidChangeBits change_bits; + bool is_discovery_done = do_discovery(p, *asd, protocol, direction, service_id, change_bits); - do_post_discovery(p, *asd, direction, is_discovery_done, service_id); + do_post_discovery(p, *asd, direction, is_discovery_done, service_id, change_bits); +} + +void AppIdDiscovery::publish_appid_event(AppidChangeBits& change_bits, snort::Flow* flow) +{ + if (change_bits.none()) + return; + + AppidEvent app_event(change_bits); + DataBus::publish(APPID_EVENT_ANY_CHANGE, app_event, flow); + if (appidDebug->is_active()) + { + std::string str; + change_bits_to_string(change_bits, str); + LogMessage("AppIdDbg %s Published event for changes: %s\n", + appidDebug->get_debug_session(), str.c_str()); + } } static inline int match_pe_network(const SfIp* pktAddr, const PortExclusion* pe) @@ -741,8 +758,10 @@ bool AppIdDiscovery::do_pre_discovery(Packet* p, AppIdSession** p_asd, AppIdInsp { if (!asd->get_session_flags(APPID_SESSION_IGNORE_FLOW_IDED)) { + AppidChangeBits change_bits; asd->set_application_ids(asd->pick_service_app_id(), asd->pick_client_app_id(), - asd->pick_payload_app_id(), asd->pick_misc_app_id()); + asd->pick_payload_app_id(), asd->pick_misc_app_id(), change_bits); + publish_appid_event(change_bits, p->flow); asd->set_session_flags(APPID_SESSION_IGNORE_FLOW_IDED); } @@ -829,7 +848,7 @@ bool AppIdDiscovery::do_pre_discovery(Packet* p, AppIdSession** p_asd, AppIdInsp } bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol protocol, - AppidSessionDirection direction, AppId& service_id) + AppidSessionDirection direction, AppId& service_id, AppidChangeBits& change_bits) { bool is_discovery_done = false; @@ -837,12 +856,12 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto if ( !(asd.scan_flags & SCAN_HOST_PORT_FLAG) ) lookup_appid_by_host_port(asd, p, protocol, direction); - asd.check_app_detection_restart(); + asd.check_app_detection_restart(change_bits); // Third party detection #ifdef ENABLE_APPID_THIRD_PARTY if ( TPLibHandler::have_tp() ) - is_discovery_done = do_tp_discovery(asd,protocol,p,direction); + is_discovery_done = do_tp_discovery(asd, protocol, p, direction, change_bits); #endif // Port-based service detection @@ -884,7 +903,7 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto // exceptions for rexec and any other service detector that need to see SYN and SYN/ACK if (asd.get_session_flags(APPID_SESSION_REXEC_STDERR)) { - ServiceDiscovery::get_instance().identify_service(asd, p, direction); + ServiceDiscovery::get_instance().identify_service(asd, p, direction, change_bits); AppIdDnsSession* dsession = asd.get_dns_session(); if (asd.service.get_id() == APP_ID_DNS && @@ -893,22 +912,22 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto AppId client_id = APP_ID_NONE, payload_id = APP_ID_NONE; dns_host_scan_hostname((const uint8_t*)dsession->get_host(), dsession->get_host_len(), &client_id, &payload_id); - asd.set_client_appid_data(client_id, nullptr); + asd.set_client_appid_data(client_id, nullptr, change_bits); } else if (asd.service.get_id() == APP_ID_RTMP) - asd.examine_rtmp_metadata(); + asd.examine_rtmp_metadata(change_bits); else if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) && asd.tsession) - asd.examine_ssl_metadata(p); + asd.examine_ssl_metadata(p, change_bits); } // FIXIT-M - snort 2.x has added a check for midstream pickup to this, do we need that? else if (protocol != IpProtocol::TCP || (p->packet_flags & PKT_STREAM_ORDER_OK)) { if (asd.service_disco_state != APPID_DISCO_STATE_FINISHED) - is_discovery_done = - ServiceDiscovery::get_instance().do_service_discovery(asd, p, direction); + is_discovery_done = ServiceDiscovery::get_instance().do_service_discovery(asd, p, + direction, change_bits); if (asd.client_disco_state != APPID_DISCO_STATE_FINISHED) - is_discovery_done = - ClientDiscovery::get_instance().do_client_discovery(asd, p, direction); + is_discovery_done = ClientDiscovery::get_instance().do_client_discovery(asd, p, + direction, change_bits); asd.set_session_flags(APPID_SESSION_ADDITIONAL_PACKET); } @@ -943,7 +962,8 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto } void AppIdDiscovery::do_post_discovery(Packet* p, AppIdSession& asd, - AppidSessionDirection direction, bool is_discovery_done, AppId service_id) + AppidSessionDirection direction, bool is_discovery_done, AppId service_id, + AppidChangeBits& change_bits) { AppId payload_id = asd.pick_payload_app_id(); @@ -965,7 +985,7 @@ void AppIdDiscovery::do_post_discovery(Packet* p, AppIdSession& asd, } asd.set_application_ids(service_id, asd.pick_client_app_id(), payload_id, - asd.pick_misc_app_id()); + asd.pick_misc_app_id(), change_bits); // Set the field that the Firewall queries to see if we have a search engine if (asd.search_support_type == UNKNOWN_SEARCH_ENGINE && payload_id > APP_ID_NONE) @@ -1007,8 +1027,10 @@ void AppIdDiscovery::do_post_discovery(Packet* p, AppIdSession& asd, asd.past_forecast = check_session_for_AF_forecast(asd, p, direction, (AppId)service_id); asd.set_application_ids(service_id, asd.pick_client_app_id(), - asd.pick_payload_app_id(), asd.pick_misc_app_id()); + asd.pick_payload_app_id(), asd.pick_misc_app_id(), change_bits); } } + + publish_appid_event(change_bits, p->flow); } diff --git a/src/network_inspectors/appid/appid_discovery.h b/src/network_inspectors/appid/appid_discovery.h index a889e03f2..46a15e710 100644 --- a/src/network_inspectors/appid/appid_discovery.h +++ b/src/network_inspectors/appid/appid_discovery.h @@ -26,14 +26,15 @@ #include #include -#include "appid_types.h" -#include "application_ids.h" - +#include "flow/flow.h" #include "protocols/protocol_ids.h" +#include "pub_sub/appid_events.h" #include "search_engines/search_tool.h" -#include "flow/flow.h" #include "utils/util.h" +#include "appid_types.h" +#include "application_ids.h" + class AppIdInspector; class AppIdSession; class AppIdDetector; @@ -109,6 +110,7 @@ public: virtual int add_service_port(AppIdDetector*, const ServiceDetectorPort&); static void do_application_discovery(snort::Packet* p, AppIdInspector&); + static void publish_appid_event(AppidChangeBits&, snort::Flow*); AppIdDetectors* get_tcp_detectors() { @@ -137,9 +139,10 @@ private: static bool do_pre_discovery(snort::Packet* p, AppIdSession** p_asd, AppIdInspector& inspector, IpProtocol& protocol, AppidSessionDirection& direction); static bool do_discovery(snort::Packet* p, AppIdSession& asd, IpProtocol protocol, - AppidSessionDirection direction, AppId& service_id); + AppidSessionDirection direction, AppId& service_id, AppidChangeBits& change_bits); static void do_post_discovery(snort::Packet* p, AppIdSession& asd, - AppidSessionDirection direction, bool is_discovery_done, AppId service_id); + AppidSessionDirection direction, bool is_discovery_done, AppId service_id, + AppidChangeBits& change_bits); static bool handle_unmonitored_session(AppIdSession* asd, const snort::Packet* p, IpProtocol protocol, AppidSessionDirection dir, AppIdInspector& inspector, uint64_t& flow_flags); diff --git a/src/network_inspectors/appid/appid_http_event_handler.cc b/src/network_inspectors/appid/appid_http_event_handler.cc index 88e2f7ea3..5a1d59583 100644 --- a/src/network_inspectors/appid/appid_http_event_handler.cc +++ b/src/network_inspectors/appid/appid_http_event_handler.cc @@ -31,6 +31,7 @@ #include "app_info_table.h" #include "appid_debug.h" +#include "appid_discovery.h" #include "appid_http_session.h" #include "appid_session.h" #include "utils/util.h" @@ -39,16 +40,17 @@ using namespace snort; void HttpEventHandler::handle(DataEvent& event, Flow* flow) { - AppidSessionDirection direction; - const uint8_t* header_start; - int32_t header_length; - HttpEvent* http_event = (HttpEvent*)&event; - assert(flow); AppIdSession* asd = appid_api.get_appid_session(*flow); if (!asd) return; + AppidSessionDirection direction; + const uint8_t* header_start; + int32_t header_length; + HttpEvent* http_event = (HttpEvent*)&event; + AppidChangeBits change_bits; + if (appidDebug->is_active()) LogMessage("AppIdDbg %s Processing HTTP metadata from HTTP Inspector\n", appidDebug->get_debug_session()); @@ -62,30 +64,30 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow) header_start = http_event->get_host(header_length); if (header_length > 0) { - hsession->set_field(REQ_HOST_FID, header_start, header_length); + hsession->set_field(REQ_HOST_FID, header_start, header_length, change_bits); asd->scan_flags |= SCAN_HTTP_HOST_URL_FLAG; header_start = http_event->get_uri(header_length); if (header_length > 0) { - hsession->set_field(REQ_URI_FID, header_start, header_length); - hsession->update_url(); + hsession->set_field(REQ_URI_FID, header_start, header_length, change_bits); + hsession->update_url(change_bits); } } header_start = http_event->get_user_agent(header_length); if (header_length > 0) { - hsession->set_field(REQ_AGENT_FID, header_start, header_length); + hsession->set_field(REQ_AGENT_FID, header_start, header_length, change_bits); asd->scan_flags |= SCAN_HTTP_USER_AGENT_FLAG; } header_start = http_event->get_cookie(header_length); - hsession->set_field(REQ_COOKIE_FID, header_start, header_length); + hsession->set_field(REQ_COOKIE_FID, header_start, header_length, change_bits); header_start = http_event->get_referer(header_length); - hsession->set_field(REQ_REFERER_FID, header_start, header_length); + hsession->set_field(REQ_REFERER_FID, header_start, header_length, change_bits); header_start = http_event->get_x_working_with(header_length); - hsession->set_field(MISC_XWW_FID, header_start, header_length); + hsession->set_field(MISC_XWW_FID, header_start, header_length, change_bits); hsession->set_is_webdav(http_event->contains_webdav_method()); // FIXIT-M: Should we get request body (may be expensive to copy)? @@ -95,11 +97,11 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow) else // Response headers. { header_start = http_event->get_content_type(header_length); - hsession->set_field(RSP_CONTENT_TYPE_FID, header_start, header_length); + hsession->set_field(RSP_CONTENT_TYPE_FID, header_start, header_length, change_bits); header_start = http_event->get_location(header_length); - hsession->set_field(RSP_LOCATION_FID, header_start, header_length); + hsession->set_field(RSP_LOCATION_FID, header_start, header_length, change_bits); header_start = http_event->get_server(header_length); - hsession->set_field(MISC_SERVER_FID, header_start, header_length); + hsession->set_field(MISC_SERVER_FID, header_start, header_length, change_bits); int32_t responseCodeNum = http_event->get_response_code(); if (responseCodeNum > 0 && responseCodeNum < 700) @@ -108,7 +110,7 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow) char tmpstr[32]; ret = snprintf(tmpstr, sizeof(tmpstr), "%d", responseCodeNum); if ( ret < sizeof(tmpstr) ) - hsession->set_field(MISC_RESP_CODE_FID, (const uint8_t*)tmpstr, ret); + hsession->set_field(MISC_RESP_CODE_FID, (const uint8_t*)tmpstr, ret, change_bits); } // FIXIT-M: Get Location header data. @@ -121,15 +123,17 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow) header_start = http_event->get_via(header_length); if (header_length > 0) { - hsession->set_field(MISC_VIA_FID, header_start, header_length); + hsession->set_field(MISC_VIA_FID, header_start, header_length, change_bits); asd->scan_flags |= SCAN_HTTP_VIA_FLAG; } - hsession->process_http_packet(direction); + hsession->process_http_packet(direction, change_bits); if (asd->service.get_id() == APP_ID_HTTP) { asd->set_application_ids(asd->pick_service_app_id(), asd->pick_client_app_id(), - asd->pick_payload_app_id(), asd->pick_misc_app_id()); + asd->pick_payload_app_id(), asd->pick_misc_app_id(), change_bits); } + + AppIdDiscovery::publish_appid_event(change_bits, flow); } diff --git a/src/network_inspectors/appid/appid_http_session.cc b/src/network_inspectors/appid/appid_http_session.cc index 1b12f0ece..553ac3203 100644 --- a/src/network_inspectors/appid/appid_http_session.cc +++ b/src/network_inspectors/appid/appid_http_session.cc @@ -81,6 +81,30 @@ void AppIdHttpSession::free_chp_matches(ChpMatchDescriptor& cmd, unsigned num_ma cmd.chp_matches[i].clear(); } +void AppIdHttpSession::set_http_change_bits(AppidChangeBits& change_bits, HttpFieldIds id) +{ + switch (id) + { + case REQ_HOST_FID: + change_bits.set(APPID_HOST_BIT); + break; + case MISC_URL_FID: + change_bits.set(APPID_URL_BIT); + break; + case REQ_AGENT_FID: + change_bits.set(APPID_USERAGENT_BIT); + break; + case MISC_RESP_CODE_FID: + change_bits.set(APPID_RESPONSE_BIT); + break; + case REQ_REFERER_FID: + change_bits.set(APPID_REFERER_BIT); + break; + default: + break; + } +} + int AppIdHttpSession::initial_chp_sweep(ChpMatchDescriptor& cmd) { CHPApp* cah = nullptr; @@ -184,7 +208,7 @@ void AppIdHttpSession::init_chp_match_descriptor(ChpMatchDescriptor& cmd) } } -void AppIdHttpSession::process_chp_buffers() +void AppIdHttpSession::process_chp_buffers(AppidChangeBits& change_bits) { ChpMatchDescriptor cmd; @@ -290,13 +314,13 @@ void AppIdHttpSession::process_chp_buffers() : CHP_APPIDINSTANCE_TO_ID(chp_candidate); if (app_type_flags & APP_TYPE_SERVICE) - asd.set_service_appid_data(chp_final, nullptr, version); + asd.set_service_appid_data(chp_final, nullptr, version, change_bits); if (app_type_flags & APP_TYPE_CLIENT) - asd.set_client_appid_data(chp_final, version); + asd.set_client_appid_data(chp_final, version, change_bits); if ( app_type_flags & APP_TYPE_PAYLOAD ) - asd.set_payload_appid_data((AppId)chp_final, version); + asd.set_payload_appid_data((AppId)chp_final, version, change_bits); if ( version ) { @@ -323,7 +347,7 @@ void AppIdHttpSession::process_chp_buffers() httpFieldName[i], cmd.chp_rewritten[i]); set_field((HttpFieldIds)i, (const uint8_t*)cmd.chp_rewritten[i], - strlen(cmd.chp_rewritten[i])); + strlen(cmd.chp_rewritten[i]), change_bits); delete [] cmd.chp_rewritten[i]; cmd.chp_rewritten[i] = nullptr; } @@ -350,7 +374,8 @@ void AppIdHttpSession::process_chp_buffers() } } -int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) +int AppIdHttpSession::process_http_packet(AppidSessionDirection direction, + AppidChangeBits& change_bits) { snort::Profile http_profile_context(httpPerfStats); AppId service_id = APP_ID_NONE; @@ -412,7 +437,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) } if (!chp_finished || chp_hold_flow) - process_chp_buffers(); + process_chp_buffers(change_bits); if (!skip_simple_detect) // true if processCHP found match { @@ -436,7 +461,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) if (vendor || vendorVersion) { asd.service.set_vendor(vendor); - asd.service.set_version(vendorVersion); + asd.service.set_version(vendorVersion, change_bits); asd.scan_flags &= ~SCAN_HTTP_VENDOR_FLAG; snort_free(vendor); @@ -461,7 +486,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) { if (appidDebug->is_active() and asd.payload.get_id() != APP_ID_WEBDAV) LogMessage("AppIdDbg %s Data is webdav\n", appidDebug->get_debug_session()); - asd.set_payload_appid_data(APP_ID_WEBDAV, nullptr); + asd.set_payload_appid_data(APP_ID_WEBDAV, nullptr, change_bits); } // Scan User-Agent for Browser types or Skype @@ -489,8 +514,8 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) appidDebug->get_debug_session(), app_name ? app_name : "unknown", client_id); } } - asd.set_service_appid_data(service_id, nullptr, nullptr); - asd.set_client_appid_data(client_id, version); + asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits); + asd.set_client_appid_data(client_id, version, change_bits); asd.scan_flags &= ~SCAN_HTTP_USER_AGENT_FLAG; snort_free(version); } @@ -509,7 +534,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) app_name ? app_name : "unknown", payload_id); } - asd.set_payload_appid_data((AppId)payload_id, nullptr); + asd.set_payload_appid_data((AppId)payload_id, nullptr, change_bits); asd.scan_flags &= ~SCAN_HTTP_VIA_FLAG; } } @@ -537,7 +562,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) LogMessage("AppIdDbg %s X is client %s (%d)\n", appidDebug->get_debug_session(), app_name ? app_name : "unknown", appId); } - asd.set_client_appid_data(appId, version); + asd.set_client_appid_data(appId, version, change_bits); } else { @@ -548,7 +573,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) LogMessage("AppIdDbg %s X service %s (%d)\n", appidDebug->get_debug_session(), app_name ? app_name : "unknown", appId); } - asd.set_service_appid_data(appId, nullptr, version); + asd.set_service_appid_data(appId, nullptr, version, change_bits); } asd.scan_flags &= ~SCAN_HTTP_XWORKINGWITH_FLAG; } @@ -575,7 +600,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) app_name ? app_name : "unknown", payload_id); } - asd.set_payload_appid_data((AppId)payload_id, nullptr); + asd.set_payload_appid_data((AppId)payload_id, nullptr, change_bits); asd.scan_flags &= ~SCAN_HTTP_CONTENT_TYPE_FLAG; } @@ -603,7 +628,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) app_name ? app_name : "unknown", client_id); } - asd.set_client_appid_data(client_id, nullptr); + asd.set_client_appid_data(client_id, nullptr, change_bits); } if (asd.service.get_id() <= APP_ID_NONE) @@ -617,7 +642,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) app_name ? app_name : "unknown", service_id); } - asd.set_service_appid_data(service_id, nullptr, nullptr); + asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits); } // DO overwrite a previously-set data @@ -629,8 +654,8 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) app_name ? app_name : "unknown", payload_id); } - asd.set_payload_appid_data((AppId)payload_id, version); - asd.set_referred_payload_app_id_data(referredPayloadAppId); + asd.set_payload_appid_data((AppId)payload_id, version, change_bits); + asd.set_referred_payload_app_id_data(referredPayloadAppId, change_bits); } asd.scan_flags &= ~SCAN_HTTP_HOST_URL_FLAG; @@ -674,11 +699,13 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction) // FIXIT-H - Implement this function when (reconfigurable) XFF is supported. void AppIdHttpSession::update_http_xff_address(struct XffFieldValue* xff_fields, - uint32_t numXffFields) + uint32_t numXffFields, AppidChangeBits& change_bits) { UNUSED(xff_fields); UNUSED(numXffFields); + UNUSED(change_bits); #if 0 + // When this is implemented, do change_bits.set(APPID_XFF_BIT) soon after xff_addr is changed static const char* defaultXffPrecedence[] = { HTTP_XFF_FIELD_X_FORWARDED_FOR, @@ -759,7 +786,7 @@ void AppIdHttpSession::update_http_xff_address(struct XffFieldValue* xff_fields, #endif } -void AppIdHttpSession::update_url() +void AppIdHttpSession::update_url(AppidChangeBits& change_bits) { const std::string* host = meta_data[REQ_HOST_FID]; const std::string* uri = meta_data[REQ_URI_FID]; @@ -768,6 +795,7 @@ void AppIdHttpSession::update_url() if (meta_data[MISC_URL_FID]) delete meta_data[MISC_URL_FID]; meta_data[MISC_URL_FID] = new std::string(std::string("http://") + *host + *uri); + change_bits.set(APPID_URL_BIT); } } diff --git a/src/network_inspectors/appid/appid_http_session.h b/src/network_inspectors/appid/appid_http_session.h index 70b5bb59b..198608fa5 100644 --- a/src/network_inspectors/appid/appid_http_session.h +++ b/src/network_inspectors/appid/appid_http_session.h @@ -26,6 +26,7 @@ #include #include "flow/flow.h" +#include "pub_sub/appid_events.h" #include "sfip/sf_ip.h" #include "appid_types.h" @@ -87,10 +88,10 @@ public: AppIdHttpSession(AppIdSession&); virtual ~AppIdHttpSession(); - int process_http_packet(AppidSessionDirection direction); - void update_http_xff_address(struct XffFieldValue* xff_fields, uint32_t numXffFields); + int process_http_packet(AppidSessionDirection direction, AppidChangeBits& change_bits); + void update_http_xff_address(struct XffFieldValue*, uint32_t, AppidChangeBits&); - void update_url(); + void update_url(AppidChangeBits& change_bits); snort::SfIp* get_xff_addr() { return xff_addr; } @@ -101,16 +102,24 @@ public: const char* get_cfield(HttpFieldIds id) { return meta_data[id] != nullptr ? meta_data[id]->c_str() : nullptr; } - void set_field(HttpFieldIds id, const std::string* str) + void set_field(HttpFieldIds id, const std::string* str, AppidChangeBits& change_bits) { delete meta_data[id]; meta_data[id] = str; + if (str) + set_http_change_bits(change_bits, id); } - void set_field(HttpFieldIds id, const uint8_t* str, int32_t len) + void set_field(HttpFieldIds id, const uint8_t* str, int32_t len, AppidChangeBits& change_bits) { delete meta_data[id]; - meta_data[id] = str and len ? new std::string((const char*)str, len) : nullptr; + if (str and len) + { + meta_data[id] = new std::string((const char*)str, len); + set_http_change_bits(change_bits, id); + } + else + meta_data[id] = nullptr; } bool get_offset(int id, uint16_t& start, uint16_t& end) @@ -184,8 +193,9 @@ protected: void init_chp_match_descriptor(ChpMatchDescriptor& cmd); int initial_chp_sweep(ChpMatchDescriptor&); - void process_chp_buffers(); + void process_chp_buffers(AppidChangeBits&); void free_chp_matches(ChpMatchDescriptor& cmd, unsigned max_matches); + void set_http_change_bits(AppidChangeBits& change_bits, HttpFieldIds id); HttpPatternMatchers* http_matchers = nullptr; diff --git a/src/network_inspectors/appid/appid_session.cc b/src/network_inspectors/appid/appid_session.cc index 455e4b1de..061765dbd 100644 --- a/src/network_inspectors/appid/appid_session.cc +++ b/src/network_inspectors/appid/appid_session.cc @@ -104,7 +104,7 @@ AppIdSession::AppIdSession(IpProtocol proto, const SfIp* ip, uint16_t port, length_sequence.proto = IpProtocol::PROTO_NOT_SET; length_sequence.sequence_cnt = 0; memset(length_sequence.sequence, '\0', sizeof(length_sequence.sequence)); - + memset(application_ids, 0, sizeof(application_ids)); appid_stats.total_sessions++; } @@ -212,7 +212,7 @@ AppIdSession* AppIdSession::create_future_session(const Packet* ctrlPkt, const S return asd; } -void AppIdSession::reinit_session_data() +void AppIdSession::reinit_session_data(AppidChangeBits& change_bits) { misc_app_id = APP_ID_NONE; @@ -223,7 +223,7 @@ void AppIdSession::reinit_session_data() referred_payload_app_id = tp_payload_app_id = APP_ID_NONE; clear_session_flags(APPID_SESSION_CONTINUE); if ( hsession ) - hsession->set_field(MISC_URL_FID, nullptr); + hsession->set_field(MISC_URL_FID, nullptr, change_bits); } //service @@ -316,7 +316,7 @@ void AppIdSession::sync_with_snort_protocol_id(AppId newAppId, Packet* p) } } -void AppIdSession::check_app_detection_restart() +void AppIdSession::check_app_detection_restart(AppidChangeBits& change_bits) { if (get_session_flags(APPID_SESSION_DECRYPTED) || !flow->is_proxied()) return; @@ -336,7 +336,7 @@ void AppIdSession::check_app_detection_restart() encrypted.client_id = pick_client_app_id(); encrypted.misc_id = pick_misc_app_id(); encrypted.referred_id = pick_referred_payload_app_id(); - reinit_session_data(); + reinit_session_data(change_bits); if (appidDebug->is_active()) LogMessage("AppIdDbg %s SSL decryption is available, restarting app detection\n", appidDebug->get_debug_session()); @@ -398,53 +398,52 @@ void AppIdSession::update_encrypted_app_id(AppId service_id) } } -void AppIdSession::examine_ssl_metadata(Packet* p) +void AppIdSession::examine_ssl_metadata(Packet* p, AppidChangeBits& change_bits) { int ret; AppId client_id = 0; AppId payload_id = 0; + const char* tls_str = tsession->get_tls_host(); - if ((scan_flags & SCAN_SSL_HOST_FLAG) && tsession->tls_host) + if ((scan_flags & SCAN_SSL_HOST_FLAG) and tls_str) { - size_t size = strlen(tsession->tls_host); - if ((ret = ssl_scan_hostname((const uint8_t*)tsession->tls_host, size, + size_t size = strlen(tls_str); + if ((ret = ssl_scan_hostname((const uint8_t*)tls_str, size, &client_id, &payload_id))) { - set_client_appid_data(client_id, nullptr); - set_payload_appid_data((AppId)payload_id, nullptr); + set_client_appid_data(client_id, nullptr, change_bits); + set_payload_appid_data((AppId)payload_id, nullptr, change_bits); setSSLSquelch(p, ret, (ret == 1 ? payload_id : client_id), inspector); } scan_flags &= ~SCAN_SSL_HOST_FLAG; } - if (tsession->tls_cname) + if ((tls_str = tsession->get_tls_cname())) { - size_t size = strlen(tsession->tls_cname); - if ((ret = ssl_scan_cname((const uint8_t*)tsession->tls_cname, size, + size_t size = strlen(tls_str); + if ((ret = ssl_scan_cname((const uint8_t*)tls_str, size, &client_id, &payload_id))) { - set_client_appid_data(client_id, nullptr); - set_payload_appid_data((AppId)payload_id, nullptr); + set_client_appid_data(client_id, nullptr, change_bits); + set_payload_appid_data((AppId)payload_id, nullptr, change_bits); setSSLSquelch(p, ret, (ret == 1 ? payload_id : client_id), inspector); } - snort_free(tsession->tls_cname); - tsession->tls_cname = nullptr; + tsession->set_tls_cname(nullptr, 0); } - if (tsession->tls_orgUnit) + if ((tls_str = tsession->get_tls_org_unit())) { - size_t size = strlen(tsession->tls_orgUnit); - if ((ret = ssl_scan_cname((const uint8_t*)tsession->tls_orgUnit, size, + size_t size = strlen(tls_str); + if ((ret = ssl_scan_cname((const uint8_t*)tls_str, size, &client_id, &payload_id))) { - set_client_appid_data(client_id, nullptr); - set_payload_appid_data((AppId)payload_id, nullptr); + set_client_appid_data(client_id, nullptr, change_bits); + set_payload_appid_data((AppId)payload_id, nullptr, change_bits); setSSLSquelch(p, ret, (ret == 1 ? payload_id : client_id), inspector); } - snort_free(tsession->tls_orgUnit); - tsession->tls_orgUnit = nullptr; + tsession->set_tls_org_unit(nullptr, 0); } } -void AppIdSession::examine_rtmp_metadata() +void AppIdSession::examine_rtmp_metadata(AppidChangeBits& change_bits) { AppId service_id = APP_ID_NONE; AppId client_id = APP_ID_NONE; @@ -469,18 +468,18 @@ void AppIdSession::examine_rtmp_metadata() { /* do not overwrite a previously-set client or service */ if (client.get_id() <= APP_ID_NONE) - set_client_appid_data(payload_id, nullptr); + set_client_appid_data(payload_id, nullptr, change_bits); if (service.get_id() <= APP_ID_NONE) - set_service_appid_data(service_id, nullptr, nullptr); + set_service_appid_data(service_id, nullptr, nullptr, change_bits); /* DO overwrite a previously-set data */ - set_payload_appid_data((AppId)payload.get_id(), nullptr); - set_referred_payload_app_id_data(referred_payload_id); + set_payload_appid_data((AppId)payload.get_id(), nullptr, change_bits); + set_referred_payload_app_id_data(referred_payload_id, change_bits); } } } -void AppIdSession::set_client_appid_data(AppId id, char* version) +void AppIdSession::set_client_appid_data(AppId id, char* version, AppidChangeBits& change_bits) { if ( id <= APP_ID_NONE || id == APP_ID_HTTP ) return; @@ -495,19 +494,22 @@ void AppIdSession::set_client_appid_data(AppId id, char* version) client.set_id(id); } - client.set_version(version); + client.set_version(version, change_bits); } -void AppIdSession::set_referred_payload_app_id_data(AppId id) +void AppIdSession::set_referred_payload_app_id_data(AppId id, AppidChangeBits& change_bits) { if (id <= APP_ID_NONE) return; if (referred_payload_app_id != id) + { referred_payload_app_id = id; + change_bits.set(APPID_REFERRED_BIT); + } } -void AppIdSession::set_payload_appid_data(AppId id, char* version) +void AppIdSession::set_payload_appid_data(AppId id, char* version, AppidChangeBits& change_bits) { if ( id <= APP_ID_NONE ) return; @@ -515,10 +517,11 @@ void AppIdSession::set_payload_appid_data(AppId id, char* version) if ( app_info_mgr->get_priority(payload.get_id()) > app_info_mgr->get_priority(id) ) return; payload.set_id(id); - payload.set_version(version); + payload.set_version(version, change_bits); } -void AppIdSession::set_service_appid_data(AppId id, char* vendor, char* version) +void AppIdSession::set_service_appid_data(AppId id, char* vendor, char* version, + AppidChangeBits& change_bits) { if (id <= APP_ID_NONE) return; @@ -531,19 +534,14 @@ void AppIdSession::set_service_appid_data(AppId id, char* vendor, char* version) return; } - service.update(id, vendor, version); + service.update(id, vendor, version, change_bits); } void AppIdSession::free_tls_session_data() { if ( tsession ) { - if (tsession->tls_host) - snort_free(tsession->tls_host); - if (tsession->tls_cname) - snort_free(tsession->tls_cname); - if (tsession->tls_orgUnit) - snort_free(tsession->tls_orgUnit); + tsession->free_data(); snort_free(tsession); tsession = nullptr; } @@ -774,12 +772,28 @@ AppId AppIdSession::pick_referred_payload_app_id() } void AppIdSession::set_application_ids(AppId service_id, AppId client_id, - AppId payload_id, AppId misc_id) + AppId payload_id, AppId misc_id, AppidChangeBits& change_bits) { - application_ids[APP_PROTOID_SERVICE] = service_id; - application_ids[APP_PROTOID_CLIENT] = client_id; - application_ids[APP_PROTOID_PAYLOAD] = payload_id; - application_ids[APP_PROTOID_MISC] = misc_id; + if (application_ids[APP_PROTOID_SERVICE] != service_id) + { + application_ids[APP_PROTOID_SERVICE] = service_id; + change_bits.set(APPID_SERVICE_BIT); + } + if (application_ids[APP_PROTOID_CLIENT] != client_id) + { + application_ids[APP_PROTOID_CLIENT] = client_id; + change_bits.set(APPID_CLIENT_BIT); + } + if (application_ids[APP_PROTOID_PAYLOAD] != payload_id) + { + application_ids[APP_PROTOID_PAYLOAD] = payload_id; + change_bits.set(APPID_PAYLOAD_BIT); + } + if (application_ids[APP_PROTOID_MISC] != misc_id) + { + application_ids[APP_PROTOID_MISC] = misc_id; + change_bits.set(APPID_MISC_BIT); + } } void AppIdSession::get_application_ids(AppId& service_id, AppId& client_id, diff --git a/src/network_inspectors/appid/appid_session.h b/src/network_inspectors/appid/appid_session.h index be446f84b..1b677e4ba 100644 --- a/src/network_inspectors/appid/appid_session.h +++ b/src/network_inspectors/appid/appid_session.h @@ -26,12 +26,14 @@ #include #include -#include "detector_plugins/http_url_patterns.h" +#include "pub_sub/appid_events.h" + #include "app_info_table.h" #include "appid_api.h" #include "appid_app_descriptor.h" #include "appid_types.h" #include "application_ids.h" +#include "detector_plugins/http_url_patterns.h" #include "length_app_cache.h" #include "service_state.h" @@ -127,33 +129,57 @@ struct CommonAppIdData // FIXIT-L: make these const strings struct TlsSession { - char* tls_host = nullptr; - int tls_host_strlen = 0; // FIXIT-M: not rvalue, remove - char* tls_cname = nullptr; - int tls_cname_strlen = 0; // FIXIT-M: not rvalue, remove - char* tls_orgUnit = nullptr; - int tls_orgUnit_strlen = 0; // FIXiT-M: not rvalue, remove + char* get_tls_host() { return tls_host; } + + char* get_tls_cname() { return tls_cname; } - void set_tls_host(const char* new_tls_host, uint32_t len) + char* get_tls_org_unit() { return tls_org_unit; } + + // Duplicate only if len > 0, otherwise simply set (i.e., own the argument) + void set_tls_host(const char* new_tls_host, uint32_t len, AppidChangeBits& change_bits) { - if (tls_host) snort_free(tls_host); - tls_host = snort::snort_strndup(new_tls_host,len); - tls_host_strlen = len; + if (tls_host) + snort_free(tls_host); + if (!new_tls_host) + { + tls_host = nullptr; + return; + } + tls_host = len? snort::snort_strndup(new_tls_host,len) : const_cast(new_tls_host); + change_bits.set(APPID_TLSHOST_BIT); } void set_tls_cname(const char* new_tls_cname, uint32_t len) { - if (tls_cname) snort_free(tls_cname); - tls_cname = snort::snort_strndup(new_tls_cname,len); - tls_cname_strlen = len; + if (tls_cname) + snort_free(tls_cname); + tls_cname = len? snort::snort_strndup(new_tls_cname,len) : + const_cast(new_tls_cname); } void set_tls_org_unit(const char* new_tls_org_unit, uint32_t len) { - if (tls_orgUnit) snort_free(tls_orgUnit); - tls_orgUnit = snort::snort_strndup(new_tls_org_unit,len); - tls_orgUnit_strlen = len; + if (tls_org_unit) + snort_free(tls_org_unit); + tls_org_unit = len? snort::snort_strndup(new_tls_org_unit,len) : + const_cast(new_tls_org_unit); } + + void free_data() + { + if (tls_host) + snort_free(tls_host); + if (tls_cname) + snort_free(tls_cname); + if (tls_org_unit) + snort_free(tls_org_unit); + tls_host = tls_cname = tls_org_unit = nullptr; + } + +private: + char* tls_host = nullptr; + char* tls_cname = nullptr; + char* tls_org_unit = nullptr; }; class AppIdSession : public snort::FlowData @@ -274,7 +300,8 @@ public: AppId pick_client_app_id(); AppId pick_payload_app_id(); AppId pick_referred_payload_app_id(); - void set_application_ids(AppId service, AppId client, AppId payload, AppId misc); + void set_application_ids(AppId service, AppId client, AppId payload, AppId misc, + AppidChangeBits& change_bits); void get_application_ids(AppId& service, AppId& client, AppId& payload, AppId& misc); void get_application_ids(AppId& service, AppId& client, AppId& payload); AppId get_application_ids_service(); @@ -283,14 +310,14 @@ public: AppId get_application_ids_misc(); bool is_ssl_session_decrypted(); - void examine_ssl_metadata(snort::Packet*); - void set_client_appid_data(AppId, char*); - void set_service_appid_data(AppId, char*, char*); - void set_referred_payload_app_id_data(AppId); - void set_payload_appid_data(AppId, char*); - void check_app_detection_restart(); + void examine_ssl_metadata(snort::Packet*, AppidChangeBits& change_bits); + void set_client_appid_data(AppId, char*, AppidChangeBits& change_bits); + void set_service_appid_data(AppId, char*, char*, AppidChangeBits& change_bits); + void set_referred_payload_app_id_data(AppId, AppidChangeBits& change_bits); + void set_payload_appid_data(AppId, char*, AppidChangeBits& change_bits); + void check_app_detection_restart(AppidChangeBits& change_bits); void update_encrypted_app_id(AppId); - void examine_rtmp_metadata(); + void examine_rtmp_metadata(AppidChangeBits& change_bits); void sync_with_snort_protocol_id(AppId, snort::Packet*); void stop_rna_service_inspection(snort::Packet*, AppidSessionDirection); @@ -332,7 +359,7 @@ private: AppIdHttpSession* hsession = nullptr; AppIdDnsSession* dsession = nullptr; - void reinit_session_data(); + void reinit_session_data(AppidChangeBits& change_bits); void delete_session_data(); static THREAD_LOCAL uint32_t appid_flow_data_id; diff --git a/src/network_inspectors/appid/appid_session_api.cc b/src/network_inspectors/appid/appid_session_api.cc index 17b752345..cab58eaa7 100644 --- a/src/network_inspectors/appid/appid_session_api.cc +++ b/src/network_inspectors/appid/appid_session_api.cc @@ -177,7 +177,7 @@ short AppIdSessionApi::get_service_port() char* AppIdSessionApi::get_tls_host() { if (asd->tsession) - return asd->tsession->tls_host; + return asd->tsession->get_tls_host(); return nullptr; } diff --git a/src/network_inspectors/appid/client_plugins/client_app_aim.cc b/src/network_inspectors/appid/client_plugins/client_app_aim.cc index 7e55e741c..a74d2c451 100644 --- a/src/network_inspectors/appid/client_plugins/client_app_aim.cc +++ b/src/network_inspectors/appid/client_plugins/client_app_aim.cc @@ -228,7 +228,7 @@ int AimClientDetector::validate(AppIdDiscoveryArgs& args) snprintf(version, sizeof(version), "%d.%d.%d", major, minor, lesser); add_app(args.asd, APP_ID_AOL_INSTANT_MESSENGER, APP_ID_AOL_INSTANT_MESSENGER, - version); + version, args.change_bits); } } } diff --git a/src/network_inspectors/appid/client_plugins/client_app_bit.cc b/src/network_inspectors/appid/client_plugins/client_app_bit.cc index 52aaee676..540643b22 100644 --- a/src/network_inspectors/appid/client_plugins/client_app_bit.cc +++ b/src/network_inspectors/appid/client_plugins/client_app_bit.cc @@ -154,7 +154,7 @@ inprocess: return APPID_INPROCESS; done: - add_app(args.asd, APP_ID_BITTORRENT, APP_ID_BITTORRENT, nullptr); + add_app(args.asd, APP_ID_BITTORRENT, APP_ID_BITTORRENT, nullptr, args.change_bits); return APPID_SUCCESS; } diff --git a/src/network_inspectors/appid/client_plugins/client_app_bit_tracker.cc b/src/network_inspectors/appid/client_plugins/client_app_bit_tracker.cc index 8e3addced..b2c8af034 100644 --- a/src/network_inspectors/appid/client_plugins/client_app_bit_tracker.cc +++ b/src/network_inspectors/appid/client_plugins/client_app_bit_tracker.cc @@ -200,7 +200,7 @@ inprocess: return APPID_INPROCESS; done: - add_app(args.asd, APP_ID_BITTORRENT, APP_ID_BITTRACKER_CLIENT, nullptr); + add_app(args.asd, APP_ID_BITTORRENT, APP_ID_BITTRACKER_CLIENT, nullptr, args.change_bits); return APPID_SUCCESS; } diff --git a/src/network_inspectors/appid/client_plugins/client_app_msn.cc b/src/network_inspectors/appid/client_plugins/client_app_msn.cc index 8a6f845a8..e3f80ed53 100644 --- a/src/network_inspectors/appid/client_plugins/client_app_msn.cc +++ b/src/network_inspectors/appid/client_plugins/client_app_msn.cc @@ -147,7 +147,7 @@ int MsnClientDetector::validate(AppIdDiscoveryArgs& args) return APPID_INPROCESS; done: - add_app(args.asd, APP_ID_MSN_MESSENGER, product_id, (char*)version); + add_app(args.asd, APP_ID_MSN_MESSENGER, product_id, (char*)version, args.change_bits); return APPID_SUCCESS; } diff --git a/src/network_inspectors/appid/client_plugins/client_app_rtp.cc b/src/network_inspectors/appid/client_plugins/client_app_rtp.cc index 8d8099740..29924b3eb 100644 --- a/src/network_inspectors/appid/client_plugins/client_app_rtp.cc +++ b/src/network_inspectors/appid/client_plugins/client_app_rtp.cc @@ -285,7 +285,7 @@ int RtpClientDetector::validate(AppIdDiscoveryArgs& args) return APPID_INPROCESS; } - add_app(args.asd, APP_ID_RTP, APP_ID_RTP, nullptr); + add_app(args.asd, APP_ID_RTP, APP_ID_RTP, nullptr, args.change_bits); return APPID_SUCCESS; } diff --git a/src/network_inspectors/appid/client_plugins/client_app_ssh.cc b/src/network_inspectors/appid/client_plugins/client_app_ssh.cc index d26539f93..608fd449f 100644 --- a/src/network_inspectors/appid/client_plugins/client_app_ssh.cc +++ b/src/network_inspectors/appid/client_plugins/client_app_ssh.cc @@ -568,7 +568,7 @@ int SshClientDetector::validate(AppIdDiscoveryArgs& args) if (sm_ret != APPID_SUCCESS) return sm_ret; - add_app(args.asd, APP_ID_SSH, fd->client_id, (const char*)fd->version); + add_app(args.asd, APP_ID_SSH, fd->client_id, (const char*)fd->version, args.change_bits); return APPID_SUCCESS; } diff --git a/src/network_inspectors/appid/client_plugins/client_app_timbuktu.cc b/src/network_inspectors/appid/client_plugins/client_app_timbuktu.cc index 237590cf1..3f67ef581 100644 --- a/src/network_inspectors/appid/client_plugins/client_app_timbuktu.cc +++ b/src/network_inspectors/appid/client_plugins/client_app_timbuktu.cc @@ -169,7 +169,7 @@ inprocess: return APPID_INPROCESS; done: - add_app(args.asd, APP_ID_TIMBUKTU, APP_ID_TIMBUKTU, nullptr); + add_app(args.asd, APP_ID_TIMBUKTU, APP_ID_TIMBUKTU, nullptr, args.change_bits); return APPID_SUCCESS; } diff --git a/src/network_inspectors/appid/client_plugins/client_app_tns.cc b/src/network_inspectors/appid/client_plugins/client_app_tns.cc index 612279505..e53ad25a3 100644 --- a/src/network_inspectors/appid/client_plugins/client_app_tns.cc +++ b/src/network_inspectors/appid/client_plugins/client_app_tns.cc @@ -332,7 +332,7 @@ inprocess: return APPID_INPROCESS; done: - add_app(args.asd, APP_ID_ORACLE_TNS, APP_ID_ORACLE_DATABASE, fd->version); + add_app(args.asd, APP_ID_ORACLE_TNS, APP_ID_ORACLE_DATABASE, fd->version, args.change_bits); if (user_start && user_end && ((user_size = user_end - user_start) > 0)) { /* we truncate extra long usernames */ diff --git a/src/network_inspectors/appid/client_plugins/client_app_vnc.cc b/src/network_inspectors/appid/client_plugins/client_app_vnc.cc index 3798eecee..0bf3f09e3 100644 --- a/src/network_inspectors/appid/client_plugins/client_app_vnc.cc +++ b/src/network_inspectors/appid/client_plugins/client_app_vnc.cc @@ -127,7 +127,7 @@ inprocess: return APPID_INPROCESS; done: - add_app(args.asd, APP_ID_VNC_RFB, APP_ID_VNC, (const char*)fd->version); + add_app(args.asd, APP_ID_VNC_RFB, APP_ID_VNC, (const char*)fd->version, args.change_bits); return APPID_SUCCESS; } diff --git a/src/network_inspectors/appid/client_plugins/client_app_ym.cc b/src/network_inspectors/appid/client_plugins/client_app_ym.cc index d55b54542..32d57619c 100644 --- a/src/network_inspectors/appid/client_plugins/client_app_ym.cc +++ b/src/network_inspectors/appid/client_plugins/client_app_ym.cc @@ -148,7 +148,7 @@ int YmDetector::validate(AppIdDiscoveryArgs& args) return APPID_INPROCESS; done: - add_app(args.asd, APP_ID_YAHOO, product_id, (char*)version); + add_app(args.asd, APP_ID_YAHOO, product_id, (char*)version, args.change_bits); return APPID_SUCCESS; } diff --git a/src/network_inspectors/appid/client_plugins/client_discovery.cc b/src/network_inspectors/appid/client_plugins/client_discovery.cc index 2cd57004a..fcd48468b 100644 --- a/src/network_inspectors/appid/client_plugins/client_discovery.cc +++ b/src/network_inspectors/appid/client_plugins/client_discovery.cc @@ -294,13 +294,14 @@ int ClientDiscovery::get_detector_candidates_list(AppIdSession& asd, Packet* p, return APPID_SESSION_SUCCESS; } -int ClientDiscovery::exec_client_detectors(AppIdSession& asd, Packet* p, AppidSessionDirection direction) +int ClientDiscovery::exec_client_detectors(AppIdSession& asd, Packet* p, + AppidSessionDirection direction, AppidChangeBits& change_bits) { int ret = APPID_INPROCESS; if (asd.client_detector != nullptr) { - AppIdDiscoveryArgs disco_args(p->data, p->dsize, direction, asd, p); + AppIdDiscoveryArgs disco_args(p->data, p->dsize, direction, asd, p, change_bits); ret = asd.client_detector->validate(disco_args); if (appidDebug->is_active()) LogMessage("AppIdDbg %s %s client detector returned %s (%d)\n", @@ -311,7 +312,7 @@ int ClientDiscovery::exec_client_detectors(AppIdSession& asd, Packet* p, AppidSe { for ( auto kv = asd.client_candidates.begin(); kv != asd.client_candidates.end(); ) { - AppIdDiscoveryArgs disco_args(p->data, p->dsize, direction, asd, p); + AppIdDiscoveryArgs disco_args(p->data, p->dsize, direction, asd, p, change_bits); int result = kv->second->validate(disco_args); if (appidDebug->is_active()) LogMessage("AppIdDbg %s %s client candidate returned %s (%d)\n", @@ -336,7 +337,8 @@ int ClientDiscovery::exec_client_detectors(AppIdSession& asd, Packet* p, AppidSe return ret; } -bool ClientDiscovery::do_client_discovery(AppIdSession& asd, Packet* p, AppidSessionDirection direction) +bool ClientDiscovery::do_client_discovery(AppIdSession& asd, Packet* p, + AppidSessionDirection direction, AppidChangeBits& change_bits) { bool isTpAppidDiscoveryDone = false; AppInfoTableEntry* entry; @@ -403,12 +405,12 @@ bool ClientDiscovery::do_client_discovery(AppIdSession& asd, Packet* p, AppidSes { /* get out if we've already tried to validate a client app */ if (!asd.is_client_detected() ) - ret = exec_client_detectors(asd, p, direction); + ret = exec_client_detectors(asd, p, direction, change_bits); } else if ( asd.service_disco_state != APPID_DISCO_STATE_STATEFUL && asd.get_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS) ) { - ret = exec_client_detectors(asd, p, direction); + ret = exec_client_detectors(asd, p, direction, change_bits); } switch (ret) @@ -431,11 +433,11 @@ bool ClientDiscovery::do_client_discovery(AppIdSession& asd, Packet* p, AppidSes { /* get out if we've already tried to validate a client app */ if (!asd.is_client_detected()) - ret = exec_client_detectors(asd, p, direction); + ret = exec_client_detectors(asd, p, direction, change_bits); } else if ( asd.service_disco_state != APPID_DISCO_STATE_STATEFUL && asd.get_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS) ) - ret = exec_client_detectors(asd, p, direction); + ret = exec_client_detectors(asd, p, direction, change_bits); if ( ret < 0 ) { diff --git a/src/network_inspectors/appid/client_plugins/client_discovery.h b/src/network_inspectors/appid/client_plugins/client_discovery.h index 4d197063d..83d9eeafb 100644 --- a/src/network_inspectors/appid/client_plugins/client_discovery.h +++ b/src/network_inspectors/appid/client_plugins/client_discovery.h @@ -50,12 +50,14 @@ public: void finalize_client_plugins(); void release_thread_resources(); - bool do_client_discovery(AppIdSession&, snort::Packet*, AppidSessionDirection direction); + bool do_client_discovery(AppIdSession&, snort::Packet*, + AppidSessionDirection direction, AppidChangeBits& change_bits); private: ClientDiscovery(AppIdInspector& ins); void initialize() override; - int exec_client_detectors(AppIdSession&, snort::Packet*, AppidSessionDirection direction); + int exec_client_detectors(AppIdSession&, snort::Packet*, + AppidSessionDirection direction, AppidChangeBits& change_bits); ClientAppMatch* find_detector_candidates(const snort::Packet* pkt, IpProtocol); void create_detector_candidates_list(AppIdSession&, snort::Packet*); int get_detector_candidates_list(AppIdSession&, snort::Packet*, AppidSessionDirection direction); diff --git a/src/network_inspectors/appid/detector_plugins/detector_dns.cc b/src/network_inspectors/appid/detector_plugins/detector_dns.cc index 1dbde4e01..850a0ffe4 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_dns.cc +++ b/src/network_inspectors/appid/detector_plugins/detector_dns.cc @@ -627,7 +627,7 @@ udp_done: case APPID_SUCCESS: success: args.asd.set_session_flags(APPID_SESSION_CONTINUE); - return add_service(args.asd, args.pkt, args.dir, APP_ID_DNS); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_DNS); case APPID_INVALID_CLIENT: invalid: @@ -641,7 +641,7 @@ nomatch: case APPID_INPROCESS: inprocess: - add_app(args.asd, APP_ID_NONE, APP_ID_DNS, nullptr); + add_app(args.asd, APP_ID_NONE, APP_ID_DNS, nullptr, args.change_bits); service_inprocess(args.asd, args.pkt, args.dir); return APPID_INPROCESS; @@ -723,7 +723,7 @@ tcp_done: success: args.asd.set_session_flags(APPID_SESSION_CONTINUE); - return add_service(args.asd, args.pkt, args.dir, APP_ID_DNS); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_DNS); not_compatible: incompatible_data(args.asd, args.pkt, args.dir); @@ -734,7 +734,7 @@ fail: return APPID_NOMATCH; inprocess: - add_app(args.asd, APP_ID_NONE, APP_ID_DNS, nullptr); + add_app(args.asd, APP_ID_NONE, APP_ID_DNS, nullptr, args.change_bits); service_inprocess(args.asd, args.pkt, args.dir); return APPID_INPROCESS; } diff --git a/src/network_inspectors/appid/detector_plugins/detector_http.cc b/src/network_inspectors/appid/detector_plugins/detector_http.cc index 659ce24a6..9afe1dbaf 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_http.cc +++ b/src/network_inspectors/appid/detector_plugins/detector_http.cc @@ -62,9 +62,10 @@ HttpClientDetector::HttpClientDetector(ClientDiscovery* cdm) int HttpClientDetector::validate(AppIdDiscoveryArgs& args) { - add_app(args.asd, APP_ID_HTTP, APP_ID_HTTP + GENERIC_APP_OFFSET, nullptr); + add_app(args.asd, APP_ID_HTTP, APP_ID_HTTP + GENERIC_APP_OFFSET, nullptr, args.change_bits); args.asd.client_disco_state = APPID_DISCO_STATE_FINISHED; - http_service_detector->add_service(args.asd, args.pkt, args.dir, APP_ID_HTTP); + http_service_detector->add_service(args.change_bits, args.asd, args.pkt, + args.dir, APP_ID_HTTP); args.asd.service_disco_state = APPID_DISCO_STATE_FINISHED; args.asd.set_session_flags(APPID_SESSION_CLIENT_DETECTED | APPID_SESSION_SERVICE_DETECTED); args.asd.clear_session_flags(APPID_SESSION_CONTINUE); diff --git a/src/network_inspectors/appid/detector_plugins/detector_imap.cc b/src/network_inspectors/appid/detector_plugins/detector_imap.cc index e71f60351..e21097007 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_imap.cc +++ b/src/network_inspectors/appid/detector_plugins/detector_imap.cc @@ -683,7 +683,7 @@ int ImapClientDetector::validate(AppIdDiscoveryArgs& args) fd->count++; if (fd->count == MIN_CMDS) { - add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr); + add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr, args.change_bits); fd->detected = 1; if (fd->got_user) { @@ -728,7 +728,7 @@ int ImapClientDetector::validate(AppIdDiscoveryArgs& args) fd->count++; if (fd->count == MIN_CMDS) { - add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr); + add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr, args.change_bits); fd->detected = 1; if (fd->got_user) { @@ -777,7 +777,7 @@ int ImapClientDetector::validate(AppIdDiscoveryArgs& args) fd->count++; if (fd->count == MIN_CMDS) { - add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr); + add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr, args.change_bits); fd->detected = 1; if (fd->got_user) { @@ -799,7 +799,7 @@ int ImapClientDetector::validate(AppIdDiscoveryArgs& args) fd->count++; if (fd->count == MIN_CMDS) { - add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr); + add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr, args.change_bits); fd->detected = 1; if (fd->got_user) { @@ -883,10 +883,10 @@ int ImapServiceDetector::validate(AppIdDiscoveryArgs& args) { if ((id->flags & IMAP_FLAG_RESULT_OK) && dd->client.state == IMAP_CLIENT_STATE_STARTTLS_CMD) - return add_service(args.asd, args.pkt, args.dir, APP_ID_IMAPS); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_IMAPS); if (id->count >= IMAP_COUNT_THRESHOLD && !args.asd.is_service_detected()) - return add_service(args.asd, args.pkt, args.dir, APP_ID_IMAP); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_IMAP); } else if (!args.asd.is_service_detected()) { diff --git a/src/network_inspectors/appid/detector_plugins/detector_kerberos.cc b/src/network_inspectors/appid/detector_plugins/detector_kerberos.cc index bc94cff99..acc3b2d3d 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_kerberos.cc +++ b/src/network_inspectors/appid/detector_plugins/detector_kerberos.cc @@ -115,7 +115,8 @@ static KerberosClientDetector* krb_client_detector; static KerberosServiceDetector* krb_service_detector; static int krb_walk_server_packet(KRBState* krbs, const uint8_t* s, const uint8_t* end, - AppIdSession& asd, snort::Packet* pkt, const AppidSessionDirection dir, const char* reqCname) + AppIdSession& asd, snort::Packet* pkt, const AppidSessionDirection dir, + const char* reqCname, AppidChangeBits& change_bits) { static const uint8_t KRB_SERVER_VERSION[] = "\x0a0\x003\x002\x001"; static const uint8_t KRB_SERVER_TYPE[] = "\x0a1\x003\x002\x001"; @@ -410,7 +411,7 @@ static int krb_walk_server_packet(KRBState* krbs, const uint8_t* s, const uint8_ /*end of server response message */ if (krbs->flags & KRB_FLAG_SERVICE_DETECTED) if (!asd.is_service_detected() && pkt) - krb_service_detector->add_service(asd, pkt, dir, APP_ID_KERBEROS, + krb_service_detector->add_service(change_bits, asd, pkt, dir, APP_ID_KERBEROS, nullptr, krbs->ver, nullptr); if (krbs->flags & KRB_FLAG_AUTH_FAILED) @@ -500,8 +501,8 @@ int KerberosServiceDetector::validate(AppIdDiscoveryArgs& args) return APPID_SUCCESS; } - if (krb_walk_server_packet(&fd->svr_state, s, end, args.asd, args.pkt, args.dir, fd->clnt_state.cname) == - KRB_FAILED) + if (krb_walk_server_packet(&fd->svr_state, s, end, args.asd, args.pkt, args.dir, + fd->clnt_state.cname, args.change_bits) == KRB_FAILED) { if (!args.asd.is_service_detected()) { @@ -551,7 +552,7 @@ KerberosClientDetector::KerberosClientDetector(ClientDiscovery* cdm) int KerberosClientDetector::krb_walk_client_packet(KRBState* krbs, const uint8_t* s, - const uint8_t* end, AppIdSession& asd) + const uint8_t* end, AppIdSession& asd, AppidChangeBits& change_bits) { static const uint8_t KRB_CLIENT_VERSION[] = "\x0a1\x003\x002\x001"; static const uint8_t KRB_CLIENT_TYPE[] = "\x0a2\x003\x002\x001"; @@ -660,7 +661,7 @@ int KerberosClientDetector::krb_walk_client_packet(KRBState* krbs, const uint8_t { if (!krbs->added) { - add_app(asd, APP_ID_KERBEROS, APP_ID_KERBEROS, krbs->ver); + add_app(asd, APP_ID_KERBEROS, APP_ID_KERBEROS, krbs->ver, change_bits); krbs->added = 1; } krbs->state = KRB_STATE_APP; @@ -906,7 +907,7 @@ int KerberosClientDetector::validate(AppIdDiscoveryArgs& args) if (args.dir == APP_ID_FROM_INITIATOR) { - if (krb_walk_client_packet(&fd->clnt_state, s, end, args.asd) == KRB_FAILED) + if (krb_walk_client_packet(&fd->clnt_state, s, end, args.asd, args.change_bits) == KRB_FAILED) { args.asd.set_client_detected(); args.asd.clear_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS); @@ -914,7 +915,7 @@ int KerberosClientDetector::validate(AppIdDiscoveryArgs& args) } } else if (krb_walk_server_packet(&fd->svr_state, s, end, args.asd, nullptr, args.dir, - fd->clnt_state.cname) == KRB_FAILED) + fd->clnt_state.cname, args.change_bits) == KRB_FAILED) { args.asd.clear_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS); } diff --git a/src/network_inspectors/appid/detector_plugins/detector_kerberos.h b/src/network_inspectors/appid/detector_plugins/detector_kerberos.h index 7dcbf6a1b..06acf52b5 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_kerberos.h +++ b/src/network_inspectors/appid/detector_plugins/detector_kerberos.h @@ -39,7 +39,8 @@ public: bool failed_login = false; private: - int krb_walk_client_packet(KRBState*, const uint8_t*, const uint8_t*, AppIdSession&); + int krb_walk_client_packet(KRBState*, const uint8_t*, const uint8_t*, + AppIdSession&, AppidChangeBits&); }; class KerberosServiceDetector : public ServiceDetector diff --git a/src/network_inspectors/appid/detector_plugins/detector_pattern.cc b/src/network_inspectors/appid/detector_plugins/detector_pattern.cc index da6c8c087..37fce1d74 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_pattern.cc +++ b/src/network_inspectors/appid/detector_plugins/detector_pattern.cc @@ -490,7 +490,7 @@ int PatternServiceDetector::validate(AppIdDiscoveryArgs& args) return APPID_NOMATCH; } - return add_service(args.asd, args.pkt, args.dir, id); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, id); } PatternClientDetector::PatternClientDetector(ClientDiscovery* cdm) @@ -548,7 +548,7 @@ int PatternClientDetector::validate(AppIdDiscoveryArgs& args) if (!id) return APPID_EINVALID; - add_app(args.asd, id, id, nullptr); + add_app(args.asd, id, id, nullptr, args.change_bits); return APPID_SUCCESS; } diff --git a/src/network_inspectors/appid/detector_plugins/detector_pop3.cc b/src/network_inspectors/appid/detector_plugins/detector_pop3.cc index 1448f20a3..dd724ea3b 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_pop3.cc +++ b/src/network_inspectors/appid/detector_plugins/detector_pop3.cc @@ -283,7 +283,7 @@ static int pop3_check_line(const uint8_t** data, const uint8_t* end) } static int pop3_server_validate(POP3DetectorData* dd, const uint8_t* data, uint16_t size, - AppIdSession& asd, int server) + AppIdSession& asd, int server, AppidChangeBits& change_bits) { ServicePOP3Data* pd = &dd->server; const uint8_t* begin = nullptr; @@ -337,7 +337,7 @@ static int pop3_server_validate(POP3DetectorData* dd, const uint8_t* data, uint1 // we are potentially overriding the APP_ID_POP3 assessment that was made earlier. asd.set_session_flags(APPID_SESSION_ENCRYPTED); asd.clear_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS); - pop3_client_detector->add_app(asd, APP_ID_POP3S, APP_ID_POP3S, nullptr); + pop3_client_detector->add_app(asd, APP_ID_POP3S, APP_ID_POP3S, nullptr, change_bits); } } else if (dd->client.username) // possible only with non-TLS auth, therefore APP_ID_POP3 @@ -572,7 +572,7 @@ int Pop3ClientDetector::validate(AppIdDiscoveryArgs& args) if (args.dir == APP_ID_FROM_RESPONDER) { - if (pop3_server_validate(dd, args.data, args.size, args.asd, 0)) + if (pop3_server_validate(dd, args.data, args.size, args.asd, 0, args.change_bits)) args.asd.clear_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS); return APPID_INPROCESS; } @@ -709,7 +709,7 @@ int Pop3ClientDetector::validate(AppIdDiscoveryArgs& args) if (pattern_index >= PATTERN_POP3_OTHER) { // Still in non-secure mode and received a TRANSACTION-state command: POP3 found - add_app(args.asd, APP_ID_POP3, APP_ID_POP3, nullptr); + add_app(args.asd, APP_ID_POP3, APP_ID_POP3, nullptr, args.change_bits); fd->detected = 1; } else @@ -787,14 +787,14 @@ int Pop3ServiceDetector::validate(AppIdDiscoveryArgs& args) return APPID_SUCCESS; } - if (!pop3_server_validate(dd, args.data, args.size, args.asd, 1)) + if (!pop3_server_validate(dd, args.data, args.size, args.asd, 1, args.change_bits)) { if (pd->count >= POP3_COUNT_THRESHOLD && !args.asd.is_service_detected()) { add_service_consume_subtype(args.asd, args.pkt, args.dir, dd->client.state == POP3_CLIENT_STATE_STLS_CMD ? APP_ID_POP3S : APP_ID_POP3, - pd->vendor, pd->version[0] ? pd->version : nullptr, pd->subtype); + pd->vendor, pd->version[0] ? pd->version : nullptr, pd->subtype, args.change_bits); pd->subtype = nullptr; return APPID_SUCCESS; } diff --git a/src/network_inspectors/appid/detector_plugins/detector_sip.cc b/src/network_inspectors/appid/detector_plugins/detector_sip.cc index 03315f904..1b870d11f 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_sip.cc +++ b/src/network_inspectors/appid/detector_plugins/detector_sip.cc @@ -473,11 +473,14 @@ void SipEventHandler::handle(DataEvent& event, Flow* flow) client->get_handler().get_inspector()); } - client_handler(sip_event, *asd); - service_handler(sip_event, *asd); + AppidChangeBits change_bits; + client_handler(sip_event, *asd, change_bits); + service_handler(sip_event, *asd, change_bits); + AppIdDiscovery::publish_appid_event(change_bits, flow); } -void SipEventHandler::client_handler(SipEvent& sip_event, AppIdSession& asd) +void SipEventHandler::client_handler(SipEvent& sip_event, AppIdSession& asd, + AppidChangeBits& change_bits) { AppId ClientAppId = APP_ID_SIP; char* clientVersion = nullptr; @@ -529,13 +532,14 @@ void SipEventHandler::client_handler(SipEvent& sip_event, AppIdSession& asd) success: if( !asd.is_client_detected() ) - client->add_app(asd, APP_ID_SIP, ClientAppId, clientVersion); + client->add_app(asd, APP_ID_SIP, ClientAppId, clientVersion, change_bits); if ( !fd->user_name.empty() ) client->add_user(asd, fd->user_name.c_str(), APP_ID_SIP, true); } -void SipEventHandler::service_handler(SipEvent& sip_event, AppIdSession& asd) +void SipEventHandler::service_handler(SipEvent& sip_event, AppIdSession& asd, + AppidChangeBits& change_bits) { ServiceSIPData* ss = (ServiceSIPData*)service->data_get(asd); if ( !ss ) @@ -575,7 +579,7 @@ void SipEventHandler::service_handler(SipEvent& sip_event, AppIdSession& asd) if ( !asd.is_service_detected() ) { asd.set_session_flags(APPID_SESSION_CONTINUE); - service->add_service(asd, sip_event.get_packet(), direction, APP_ID_SIP, + service->add_service(change_bits, asd, sip_event.get_packet(), direction, APP_ID_SIP, ss->vendor[0] ? ss->vendor : nullptr); if (appidDebug->is_active()) LogMessage("AppIdDbg %s Sip service detected. Setting APPID_SESSION_CONTINUE flag\n", diff --git a/src/network_inspectors/appid/detector_plugins/detector_sip.h b/src/network_inspectors/appid/detector_plugins/detector_sip.h index 4bd2d740f..0a42bccde 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_sip.h +++ b/src/network_inspectors/appid/detector_plugins/detector_sip.h @@ -106,8 +106,8 @@ public: private: SipEventHandler() = default; - void client_handler(SipEvent&, AppIdSession&); - void service_handler(SipEvent&, AppIdSession&); + void client_handler(SipEvent&, AppIdSession&, AppidChangeBits&); + void service_handler(SipEvent&, AppIdSession&, AppidChangeBits&); static SipUdpClientDetector* client; static SipServiceDetector* service; diff --git a/src/network_inspectors/appid/detector_plugins/detector_smtp.cc b/src/network_inspectors/appid/detector_plugins/detector_smtp.cc index b4a6f4366..bbffdff4f 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_smtp.cc +++ b/src/network_inspectors/appid/detector_plugins/detector_smtp.cc @@ -183,7 +183,7 @@ SmtpClientDetector::SmtpClientDetector(ClientDiscovery* cdm) // FIXIT-M - refactor this to reduce the number of function parameters int SmtpClientDetector::extract_version_and_add_client_app(AppId clientId, const int prefix_len, const uint8_t* product, const uint8_t* product_end, ClientSMTPData* const client_data, - AppIdSession& asd, AppId appId) + AppIdSession& asd, AppId appId, AppidChangeBits& change_bits) { uint8_t* v_end = client_data->version + MAX_VERSION_SIZE - 1; @@ -196,7 +196,7 @@ int SmtpClientDetector::extract_version_and_add_client_app(AppId clientId, const for (v = client_data->version; v < v_end && p < product_end; v++,p++) *v = *p; *v = 0; - add_app(asd, appId, clientId, (char*)client_data->version); + add_app(asd, appId, clientId, (char*)client_data->version, change_bits); return 0; } @@ -206,7 +206,7 @@ int SmtpClientDetector::extract_version_and_add_client_app(AppId clientId, const * Returns 0 if a recognized product is found. Otherwise returns 1. */ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const uint8_t* product, - const uint8_t* data_end, AppIdSession& asd, snort::Packet*) + const uint8_t* data_end, AppIdSession& asd, snort::Packet*, AppidChangeBits& change_bits) { const uint8_t* p; AppId appId = APP_ID_SMTP; @@ -227,7 +227,7 @@ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const if (p >= data_end || *p != ' ') return 1; return extract_version_and_add_client_app(APP_ID_OUTLOOK, - 2, p, data_end, fd, asd, appId); + 2, p, data_end, fd, asd, appId, change_bits); } else if (*p == ' ') { @@ -235,12 +235,12 @@ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const if (data_end-p >= (int)sizeof(EXPRESS) && memcmp(p, EXPRESS, sizeof(EXPRESS)-1) == 0) { return extract_version_and_add_client_app(APP_ID_OUTLOOK_EXPRESS, - sizeof(EXPRESS), p, data_end, fd, asd, appId); + sizeof(EXPRESS), p, data_end, fd, asd, appId, change_bits); } else if (data_end-p >= (int)sizeof(IMO) && memcmp(p, IMO, sizeof(IMO)-1) == 0) { return extract_version_and_add_client_app(APP_ID_OUTLOOK, - sizeof(IMO), p, data_end, fd, asd, appId); + sizeof(IMO), p, data_end, fd, asd, appId, change_bits); } } } @@ -249,13 +249,13 @@ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const sizeof(APP_SMTP_EVOLUTION)-1) == 0) { return extract_version_and_add_client_app(APP_ID_EVOLUTION, - sizeof(APP_SMTP_EVOLUTION), product, data_end, fd, asd, appId); + sizeof(APP_SMTP_EVOLUTION), product, data_end, fd, asd, appId, change_bits); } else if (len >= sizeof(APP_SMTP_LOTUS_NOTES) && memcmp(product, APP_SMTP_LOTUS_NOTES, sizeof(APP_SMTP_LOTUS_NOTES)-1) == 0) { return extract_version_and_add_client_app(APP_ID_LOTUS_NOTES, - sizeof(APP_SMTP_LOTUS_NOTES), product, data_end, fd, asd, appId); + sizeof(APP_SMTP_LOTUS_NOTES), product, data_end, fd, asd, appId, change_bits); } else if (len >= sizeof(APP_SMTP_APPLEMAIL) && memcmp(product, APP_SMTP_APPLEMAIL, sizeof(APP_SMTP_APPLEMAIL)-1) == 0) @@ -271,50 +271,50 @@ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const } *v = 0; - add_app(asd, appId, APP_ID_APPLE_EMAIL, (char*)fd->version); + add_app(asd, appId, APP_ID_APPLE_EMAIL, (char*)fd->version, change_bits); return 0; } else if (len >= sizeof(APP_SMTP_EUDORA) && memcmp(product, APP_SMTP_EUDORA, sizeof(APP_SMTP_EUDORA)-1) == 0) { return extract_version_and_add_client_app(APP_ID_EUDORA, - sizeof(APP_SMTP_EUDORA), product, data_end, fd, asd, appId); + sizeof(APP_SMTP_EUDORA), product, data_end, fd, asd, appId, change_bits); } else if (len >= sizeof(APP_SMTP_EUDORAPRO) && memcmp(product, APP_SMTP_EUDORAPRO, sizeof(APP_SMTP_EUDORAPRO)-1) == 0) { return extract_version_and_add_client_app(APP_ID_EUDORA_PRO, - sizeof(APP_SMTP_EUDORAPRO), product, data_end, fd, asd, appId); + sizeof(APP_SMTP_EUDORAPRO), product, data_end, fd, asd, appId, change_bits); } else if (len >= sizeof(APP_SMTP_AOL) && memcmp(product, APP_SMTP_AOL, sizeof(APP_SMTP_AOL)-1) == 0) { return extract_version_and_add_client_app(APP_ID_AOL_EMAIL, - sizeof(APP_SMTP_AOL), product, data_end, fd, asd, appId); + sizeof(APP_SMTP_AOL), product, data_end, fd, asd, appId, change_bits); } else if (len >= sizeof(APP_SMTP_MUTT) && memcmp(product, APP_SMTP_MUTT, sizeof(APP_SMTP_MUTT)-1) == 0) { return extract_version_and_add_client_app(APP_ID_MUTT, - sizeof(APP_SMTP_MUTT), product, data_end, fd, asd, appId); + sizeof(APP_SMTP_MUTT), product, data_end, fd, asd, appId, change_bits); } else if (len >= sizeof(APP_SMTP_KMAIL) && memcmp(product, APP_SMTP_KMAIL, sizeof(APP_SMTP_KMAIL)-1) == 0) { return extract_version_and_add_client_app(APP_ID_KMAIL, - sizeof(APP_SMTP_KMAIL), product, data_end, fd, asd, appId); + sizeof(APP_SMTP_KMAIL), product, data_end, fd, asd, appId, change_bits); } else if (len >= sizeof(APP_SMTP_THUNDERBIRD) && memcmp(product, APP_SMTP_THUNDERBIRD, sizeof(APP_SMTP_THUNDERBIRD)-1) == 0) { return extract_version_and_add_client_app(APP_ID_THUNDERBIRD, - sizeof(APP_SMTP_THUNDERBIRD), product, data_end, fd, asd, appId); + sizeof(APP_SMTP_THUNDERBIRD), product, data_end, fd, asd, appId, change_bits); } else if (len >= sizeof(APP_SMTP_MTHUNDERBIRD) && memcmp(product, APP_SMTP_MTHUNDERBIRD, sizeof(APP_SMTP_MTHUNDERBIRD)-1) == 0) { return extract_version_and_add_client_app(APP_ID_THUNDERBIRD, - sizeof(APP_SMTP_MTHUNDERBIRD), product, data_end, fd, asd, appId); + sizeof(APP_SMTP_MTHUNDERBIRD), product, data_end, fd, asd, appId, change_bits); } else if (len >= sizeof(APP_SMTP_MOZILLA) && memcmp(product, APP_SMTP_MOZILLA, sizeof(APP_SMTP_MOZILLA)-1) == 0) @@ -329,7 +329,7 @@ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const { return extract_version_and_add_client_app( APP_ID_THUNDERBIRD, sizeof(APP_SMTP_THUNDERBIRD_SHORT), - p, data_end, fd, asd, appId); + p, data_end, fd, asd, appId, change_bits); } } } @@ -387,7 +387,7 @@ int SmtpClientDetector::validate(AppIdDiscoveryArgs& args) /* Because we can't see any further info without decryption we settle for plain APP_ID_SMTPS instead of perhaps finding data that would make calling ExtractVersion() worthwhile, So set the appid and call it good. */ - add_app(args.asd, APP_ID_SMTPS, APP_ID_SMTPS, nullptr); + add_app(args.asd, APP_ID_SMTPS, APP_ID_SMTPS, nullptr, args.change_bits); goto done; } } @@ -517,7 +517,7 @@ int SmtpClientDetector::validate(AppIdDiscoveryArgs& args) (len >= 1 && args.data[1] == '\n') || (len >= 2 && args.data[1] == '\r' && args.data[2] == '\n')) { - add_app(args.asd, APP_ID_SMTP, APP_ID_SMTP, nullptr); + add_app(args.asd, APP_ID_SMTP, APP_ID_SMTP, nullptr, args.change_bits); goto done; } } @@ -545,7 +545,7 @@ int SmtpClientDetector::validate(AppIdDiscoveryArgs& args) { if (fd->headerline && fd->pos) { - identify_client_version(fd, fd->headerline, fd->headerline + fd->pos, args.asd, args.pkt); + identify_client_version(fd, fd->headerline, fd->headerline + fd->pos, args.asd, args.pkt, args.change_bits); snort_free(fd->headerline); fd->headerline = nullptr; fd->pos = 0; @@ -842,7 +842,7 @@ int SmtpServiceDetector::validate(AppIdDiscoveryArgs& args) dd->client.decryption_countdown = 1 #endif - add_service(args.asd, args.pkt, args.dir, APP_ID_SMTPS); + add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_SMTPS); if(dd->need_continue > 0) args.asd.set_session_flags(APPID_SESSION_ENCRYPTED | APPID_SESSION_STICKY_SERVICE | APPID_SESSION_CONTINUE); @@ -869,7 +869,7 @@ success: if (dd->need_continue > 0) args.asd.set_session_flags(APPID_SESSION_CONTINUE); - return add_service(args.asd, args.pkt, args.dir, + return add_service(args.change_bits, args.asd, args.pkt, args.dir, (fd->state == SMTP_SERVICE_STATE_STARTTLS) ? APP_ID_SMTPS : APP_ID_SMTP); fail: diff --git a/src/network_inspectors/appid/detector_plugins/detector_smtp.h b/src/network_inspectors/appid/detector_plugins/detector_smtp.h index a3e972a70..62502dcbf 100644 --- a/src/network_inspectors/appid/detector_plugins/detector_smtp.h +++ b/src/network_inspectors/appid/detector_plugins/detector_smtp.h @@ -40,9 +40,9 @@ public: private: int extract_version_and_add_client_app(AppId, const int prefix_len, const uint8_t* product, const uint8_t* product_end, ClientSMTPData* const, - AppIdSession&, AppId); + AppIdSession&, AppId, AppidChangeBits&); int identify_client_version(ClientSMTPData* const, const uint8_t* product, - const uint8_t* data_end, AppIdSession&, snort::Packet*); + const uint8_t* data_end, AppIdSession&, snort::Packet*, AppidChangeBits&); }; class SmtpServiceDetector : public ServiceDetector diff --git a/src/network_inspectors/appid/lua_detector_api.cc b/src/network_inspectors/appid/lua_detector_api.cc index de4e9b9ed..b724e31f6 100644 --- a/src/network_inspectors/appid/lua_detector_api.cc +++ b/src/network_inspectors/appid/lua_detector_api.cc @@ -518,8 +518,8 @@ static int service_add_service(lua_State* L) /*Phase2 - discuss AppIdServiceSubtype will be maintained on lua side therefore the last parameter on the following call is nullptr. Subtype is not displayed on DC at present. */ - unsigned int retValue = ud->sd->add_service(*lsd->ldp.asd, lsd->ldp.pkt, lsd->ldp.dir, - AppInfoManager::get_instance().get_appid_by_service_id(service_id), + unsigned int retValue = ud->sd->add_service(*lsd->ldp.change_bits, *lsd->ldp.asd, lsd->ldp.pkt, + lsd->ldp.dir, AppInfoManager::get_instance().get_appid_by_service_id(service_id), vendor, version, nullptr); lua_pushnumber(L, retValue); @@ -902,7 +902,7 @@ static int service_add_client(lua_State* L) return 1; } - ud->cd->add_app(*lsd->ldp.asd, service_id, client_id, version); + ud->cd->add_app(*lsd->ldp.asd, service_id, client_id, version, *lsd->ldp.change_bits); lua_pushnumber(L, 0); return 1; } @@ -918,7 +918,8 @@ static int client_add_application(lua_State* L) const char* version = lua_tostring(L, 5); ud->cd->add_app(*lsd->ldp.asd, AppInfoManager::get_instance().get_appid_by_service_id(service_id), - AppInfoManager::get_instance().get_appid_by_client_id(productId), version); + AppInfoManager::get_instance().get_appid_by_client_id(productId), version, + *lsd->ldp.change_bits); lua_pushnumber(L, 0); return 1; @@ -931,7 +932,7 @@ static int client_add_info(lua_State* L) LuaStateDescriptor* lsd = ud->validate_lua_state(true); const char* info = lua_tostring(L, 2); - ud->cd->add_info(*lsd->ldp.asd, info); + ud->cd->add_info(*lsd->ldp.asd, info, *lsd->ldp.change_bits); lua_pushnumber(L, 0); return 1; } @@ -1933,7 +1934,7 @@ static int add_client_application(lua_State* L) unsigned int service_id = lua_tonumber(L, 2); unsigned int client_id = lua_tonumber(L, 3); - ud->cd->add_app(*lsd->ldp.asd, service_id, client_id, ""); + ud->cd->add_app(*lsd->ldp.asd, service_id, client_id, "", *lsd->ldp.change_bits); lua_pushnumber(L, 0); return 1; } @@ -1959,7 +1960,7 @@ static int add_service_application(lua_State* L) /*Phase2 - discuss AppIdServiceSubtype will be maintained on lua side therefore the last parameter on the following call is nullptr. Subtype is not displayed on DC at present. */ - unsigned retValue = ud->sd->add_service(*lsd->ldp.asd, lsd->ldp.pkt, + unsigned retValue = ud->sd->add_service(*lsd->ldp.change_bits, *lsd->ldp.asd, lsd->ldp.pkt, lsd->ldp.dir, service_id); lua_pushnumber(L, retValue); @@ -2502,6 +2503,7 @@ int LuaStateDescriptor::lua_validate(AppIdDiscoveryArgs& args) ldp.size = args.size; ldp.dir = args.dir; ldp.asd = &args.asd; + ldp.change_bits = &args.change_bits; ldp.pkt = args.pkt; const char* validateFn = package_info.validateFunctionName.c_str(); diff --git a/src/network_inspectors/appid/lua_detector_api.h b/src/network_inspectors/appid/lua_detector_api.h index 8b41df110..f93865832 100644 --- a/src/network_inspectors/appid/lua_detector_api.h +++ b/src/network_inspectors/appid/lua_detector_api.h @@ -62,6 +62,7 @@ struct LuaDetectorParameters size = args.size; dir = args.dir; asd = &args.asd; + change_bits = &args.change_bits; pkt = args.pkt; } @@ -69,6 +70,7 @@ struct LuaDetectorParameters uint16_t size = 0; AppidSessionDirection dir = APP_ID_FROM_INITIATOR; AppIdSession* asd; + AppidChangeBits* change_bits = nullptr; snort::Packet* pkt = nullptr; uint8_t macAddress[6] = { 0 }; }; diff --git a/src/network_inspectors/appid/service_plugins/service_battle_field.cc b/src/network_inspectors/appid/service_plugins/service_battle_field.cc index 9720ac272..05fd5dec8 100644 --- a/src/network_inspectors/appid/service_plugins/service_battle_field.cc +++ b/src/network_inspectors/appid/service_plugins/service_battle_field.cc @@ -187,7 +187,7 @@ success: goto inprocess; } - return add_service(args.asd, args.pkt, args.dir, APP_ID_BATTLEFIELD); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_BATTLEFIELD); fail: fail_service(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_bgp.cc b/src/network_inspectors/appid/service_plugins/service_bgp.cc index 6cd04b4a3..74e6f3275 100644 --- a/src/network_inspectors/appid/service_plugins/service_bgp.cc +++ b/src/network_inspectors/appid/service_plugins/service_bgp.cc @@ -219,6 +219,6 @@ fail: return APPID_NOMATCH; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_BGP); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_BGP); } diff --git a/src/network_inspectors/appid/service_plugins/service_bit.cc b/src/network_inspectors/appid/service_plugins/service_bit.cc index cf3f524ed..b24165067 100644 --- a/src/network_inspectors/appid/service_plugins/service_bit.cc +++ b/src/network_inspectors/appid/service_plugins/service_bit.cc @@ -170,7 +170,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_BITTORRENT); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_BITTORRENT); fail: fail_service(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_bootp.cc b/src/network_inspectors/appid/service_plugins/service_bootp.cc index b269dec09..b0fa70e9b 100644 --- a/src/network_inspectors/appid/service_plugins/service_bootp.cc +++ b/src/network_inspectors/appid/service_plugins/service_bootp.cc @@ -296,7 +296,7 @@ success: if (!args.asd.is_service_detected()) { args.asd.set_session_flags(APPID_SESSION_CONTINUE); - add_service(args.asd, args.pkt, args.dir, APP_ID_DHCP); + add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_DHCP); } return APPID_SUCCESS; diff --git a/src/network_inspectors/appid/service_plugins/service_dcerpc.cc b/src/network_inspectors/appid/service_plugins/service_dcerpc.cc index 094880024..676749eba 100644 --- a/src/network_inspectors/appid/service_plugins/service_dcerpc.cc +++ b/src/network_inspectors/appid/service_plugins/service_dcerpc.cc @@ -99,7 +99,7 @@ int DceRpcServiceDetector::tcp_validate(AppIdDiscoveryArgs& args) size -= length; } if (retval == APPID_SUCCESS) - return add_service(args.asd, args.pkt, args.dir, APP_ID_DCE_RPC); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_DCE_RPC); inprocess: service_inprocess(args.asd, args.pkt, args.dir); @@ -142,7 +142,7 @@ int DceRpcServiceDetector::udp_validate(AppIdDiscoveryArgs& args) size -= length; } if (retval == APPID_SUCCESS) - return add_service(args.asd, args.pkt, args.dir, APP_ID_DCE_RPC); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_DCE_RPC); inprocess: service_inprocess(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_detector.cc b/src/network_inspectors/appid/service_plugins/service_detector.cc index 5a4241f4a..bf9f7a844 100644 --- a/src/network_inspectors/appid/service_plugins/service_detector.cc +++ b/src/network_inspectors/appid/service_plugins/service_detector.cc @@ -81,14 +81,14 @@ int ServiceDetector::service_inprocess(AppIdSession& asd, const Packet* pkt, App } int ServiceDetector::update_service_data(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir, AppId appId, - const char* vendor, const char* version) + const char* vendor, const char* version, AppidChangeBits& change_bits) { uint16_t port = 0; const SfIp* ip = nullptr; asd.service_detector = this; asd.service.set_vendor(vendor); - asd.service.set_version(version); + asd.service.set_version(version, change_bits); asd.set_service_detected(); asd.service.set_id(appId); @@ -134,14 +134,15 @@ int ServiceDetector::update_service_data(AppIdSession& asd, const Packet* pkt, A int ServiceDetector::add_service_consume_subtype(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir, AppId appId, const char* vendor, const char* version, - AppIdServiceSubtype* subtype) + AppIdServiceSubtype* subtype, AppidChangeBits& change_bits) { asd.subtype = subtype; - return update_service_data(asd, pkt, dir, appId, vendor, version); + return update_service_data(asd, pkt, dir, appId, vendor, version, change_bits); } -int ServiceDetector::add_service(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir, - AppId appId, const char* vendor, const char* version, const AppIdServiceSubtype* subtype) +int ServiceDetector::add_service(AppidChangeBits& change_bits, AppIdSession& asd, + const Packet* pkt, AppidSessionDirection dir, AppId appId, const char* vendor, + const char* version, const AppIdServiceSubtype* subtype) { AppIdServiceSubtype* new_subtype = nullptr; @@ -162,7 +163,7 @@ int ServiceDetector::add_service(AppIdSession& asd, const Packet* pkt, AppidSess new_subtype = tmp_subtype; } asd.subtype = new_subtype; - return update_service_data(asd, pkt, dir, appId, vendor, version); + return update_service_data(asd, pkt, dir, appId, vendor, version, change_bits); } int ServiceDetector::incompatible_data(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir) diff --git a/src/network_inspectors/appid/service_plugins/service_detector.h b/src/network_inspectors/appid/service_plugins/service_detector.h index 0cb25c776..6b0cd1462 100644 --- a/src/network_inspectors/appid/service_plugins/service_detector.h +++ b/src/network_inspectors/appid/service_plugins/service_detector.h @@ -35,10 +35,12 @@ public: void release_thread_resources() override { } void register_appid(AppId, unsigned extractsInfo) override; int service_inprocess(AppIdSession&, const snort::Packet*, AppidSessionDirection dir); - int add_service(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId, const char* vendor = nullptr, - const char* version = nullptr, const snort::AppIdServiceSubtype* = nullptr); - int add_service_consume_subtype(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId, - const char* vendor, const char* version, snort::AppIdServiceSubtype*); + int add_service(AppidChangeBits&, AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId, + const char* vendor = nullptr, const char* version = nullptr, + const snort::AppIdServiceSubtype* = nullptr); + int add_service_consume_subtype(AppIdSession&, const snort::Packet*, + AppidSessionDirection dir, AppId, const char* vendor, const char* version, + snort::AppIdServiceSubtype*, AppidChangeBits&); int incompatible_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir); int fail_service(AppIdSession&, const snort::Packet*, AppidSessionDirection dir); @@ -55,8 +57,8 @@ public: void initialize_expected_session(AppIdSession&, AppIdSession&, uint64_t flags, AppidSessionDirection dir); private: - int update_service_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId, const char* vendor, - const char* version); + int update_service_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId, + const char* vendor, const char* version, AppidChangeBits& change_bits); }; #endif diff --git a/src/network_inspectors/appid/service_plugins/service_direct_connect.cc b/src/network_inspectors/appid/service_plugins/service_direct_connect.cc index 8ea469bb9..f83eaccc0 100644 --- a/src/network_inspectors/appid/service_plugins/service_direct_connect.cc +++ b/src/network_inspectors/appid/service_plugins/service_direct_connect.cc @@ -111,13 +111,13 @@ int DirectConnectServiceDetector::validate(AppIdDiscoveryArgs& args) } if (args.asd.protocol == IpProtocol::TCP) - return tcp_validate(data, size, args.dir, args.asd, args.pkt, fd); + return tcp_validate(data, size, args.dir, args.asd, args.pkt, fd, args.change_bits); else - return udp_validate(data, size, args.dir, args.asd, args.pkt, fd); + return udp_validate(data, size, args.dir, args.asd, args.pkt, fd, args.change_bits); } int DirectConnectServiceDetector::tcp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir, - AppIdSession& asd, const Packet* pkt, ServiceData* serviceData) + AppIdSession& asd, const Packet* pkt, ServiceData* serviceData, AppidChangeBits& change_bits) { switch (serviceData->state) { @@ -215,7 +215,7 @@ success: goto inprocess; } - return add_service(asd, pkt, dir, APP_ID_DIRECT_CONNECT); + return add_service(change_bits, asd, pkt, dir, APP_ID_DIRECT_CONNECT); fail: fail_service(asd, pkt, dir); @@ -223,7 +223,7 @@ fail: } int DirectConnectServiceDetector::udp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir, - AppIdSession& asd, const Packet* pkt, ServiceData* serviceData) + AppIdSession& asd, const Packet* pkt, ServiceData* serviceData, AppidChangeBits& change_bits) { if (dir == APP_ID_FROM_RESPONDER && serviceData->state == CONN_STATE_SERVICE_DETECTED) { @@ -263,7 +263,7 @@ success: } reportSuccess: - return add_service(asd, pkt, dir, APP_ID_DIRECT_CONNECT); + return add_service(change_bits, asd, pkt, dir, APP_ID_DIRECT_CONNECT); fail: fail_service(asd, pkt, dir); diff --git a/src/network_inspectors/appid/service_plugins/service_direct_connect.h b/src/network_inspectors/appid/service_plugins/service_direct_connect.h index 7befc565e..b8c6634f6 100644 --- a/src/network_inspectors/appid/service_plugins/service_direct_connect.h +++ b/src/network_inspectors/appid/service_plugins/service_direct_connect.h @@ -37,9 +37,9 @@ public: private: int tcp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir, AppIdSession&, - const snort::Packet*, ServiceData*); + const snort::Packet*, ServiceData*, AppidChangeBits&); int udp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir, AppIdSession&, - const snort::Packet*, ServiceData*); + const snort::Packet*, ServiceData*, AppidChangeBits&); }; #endif diff --git a/src/network_inspectors/appid/service_plugins/service_discovery.cc b/src/network_inspectors/appid/service_plugins/service_discovery.cc index 1b27be301..51f812568 100644 --- a/src/network_inspectors/appid/service_plugins/service_discovery.cc +++ b/src/network_inspectors/appid/service_plugins/service_discovery.cc @@ -409,7 +409,8 @@ void ServiceDiscovery::get_next_service(const Packet* p, const AppidSessionDirec } } -int ServiceDiscovery::identify_service(AppIdSession& asd, Packet* p, AppidSessionDirection dir) +int ServiceDiscovery::identify_service(AppIdSession& asd, Packet* p, + AppidSessionDirection dir, AppidChangeBits& change_bits) { ServiceDiscoveryState* sds = nullptr; bool got_brute_force = false; @@ -472,7 +473,7 @@ int ServiceDiscovery::identify_service(AppIdSession& asd, Packet* p, AppidSessio int ret = APPID_NOMATCH; bool got_incompatible_service = false; bool got_fail_service = false; - AppIdDiscoveryArgs args(p->data, p->dsize, dir, asd, p); + AppIdDiscoveryArgs args(p->data, p->dsize, dir, asd, p, change_bits); /* If we already have a service to try, then try it out. */ if ( asd.service_detector ) { @@ -580,7 +581,8 @@ int ServiceDiscovery::add_ftp_service_state(AppIdSession& asd) return asd.add_flow_data_id(21, ftp_service); } -bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p, AppidSessionDirection direction) +bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p, + AppidSessionDirection direction, AppidChangeBits& change_bits) { bool isTpAppidDiscoveryDone = false; @@ -693,7 +695,7 @@ bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p, AppidS if (asd.service_disco_state == APPID_DISCO_STATE_STATEFUL) { - identify_service(asd, p, direction); + identify_service(asd, p, direction, change_bits); isTpAppidDiscoveryDone = true; //to stop executing validator after service has been detected by RNA. if (asd.get_session_flags(APPID_SESSION_SERVICE_DETECTED | @@ -716,12 +718,12 @@ bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p, AppidS AppId payload_id = APP_ID_NONE; dns_host_scan_hostname((const uint8_t*)(dsession->get_host()), dsession->get_host_len(), &client_id, &payload_id); - asd.set_client_appid_data(client_id, nullptr); + asd.set_client_appid_data(client_id, nullptr, change_bits); } else if (asd.service.get_id() == APP_ID_RTMP) - asd.examine_rtmp_metadata(); + asd.examine_rtmp_metadata(change_bits); else if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) && asd.tsession) - asd.examine_ssl_metadata(p); + asd.examine_ssl_metadata(p, change_bits); if (tp_app_id <= APP_ID_NONE && asd.get_session_flags( APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_NOT_A_SERVICE | diff --git a/src/network_inspectors/appid/service_plugins/service_discovery.h b/src/network_inspectors/appid/service_plugins/service_discovery.h index 74844a933..55aa3cc31 100644 --- a/src/network_inspectors/appid/service_plugins/service_discovery.h +++ b/src/network_inspectors/appid/service_plugins/service_discovery.h @@ -78,8 +78,9 @@ public: ServiceDetector* get_next_tcp_detector(AppIdDetectorsIterator&); ServiceDetector* get_next_udp_detector(AppIdDetectorsIterator&); - bool do_service_discovery(AppIdSession&, snort::Packet*, AppidSessionDirection dir); - int identify_service(AppIdSession&, snort::Packet*, AppidSessionDirection dir); + bool do_service_discovery(AppIdSession&, snort::Packet*, AppidSessionDirection dir, + AppidChangeBits& change_bits); + int identify_service(AppIdSession&, snort::Packet*, AppidSessionDirection, AppidChangeBits&); int fail_service(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, ServiceDetector*, ServiceDiscoveryState* sds = nullptr); int incompatible_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, ServiceDetector*); static int add_ftp_service_state(AppIdSession&); diff --git a/src/network_inspectors/appid/service_plugins/service_flap.cc b/src/network_inspectors/appid/service_plugins/service_flap.cc index 567a2bb75..282f3bcc1 100644 --- a/src/network_inspectors/appid/service_plugins/service_flap.cc +++ b/src/network_inspectors/appid/service_plugins/service_flap.cc @@ -202,7 +202,8 @@ fail: return APPID_NOMATCH; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_AOL_INSTANT_MESSENGER); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, + APP_ID_AOL_INSTANT_MESSENGER); inprocess: service_inprocess(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_ftp.cc b/src/network_inspectors/appid/service_plugins/service_ftp.cc index ca8030b16..e48c01caf 100644 --- a/src/network_inspectors/appid/service_plugins/service_ftp.cc +++ b/src/network_inspectors/appid/service_plugins/service_ftp.cc @@ -1228,8 +1228,8 @@ inprocess: | APPID_SESSION_DECRYPTED); // FTPS only when encrypted==1 decrypted==0 - add_service(args.asd, args.pkt, args.dir, flags == APPID_SESSION_ENCRYPTED ? - APP_ID_FTPS : APP_ID_FTP_CONTROL, + add_service(args.change_bits, args.asd, args.pkt, args.dir, + flags == APPID_SESSION_ENCRYPTED ? APP_ID_FTPS : APP_ID_FTP_CONTROL, fd->vendor[0] ? fd->vendor : nullptr, fd->version[0] ? fd->version : nullptr, nullptr); } diff --git a/src/network_inspectors/appid/service_plugins/service_irc.cc b/src/network_inspectors/appid/service_plugins/service_irc.cc index 04f06fd79..337765302 100644 --- a/src/network_inspectors/appid/service_plugins/service_irc.cc +++ b/src/network_inspectors/appid/service_plugins/service_irc.cc @@ -283,7 +283,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_IRCD); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_IRCD); fail: if (args.dir == APP_ID_FROM_RESPONDER) diff --git a/src/network_inspectors/appid/service_plugins/service_lpr.cc b/src/network_inspectors/appid/service_plugins/service_lpr.cc index ed5da28bd..00855987d 100644 --- a/src/network_inspectors/appid/service_plugins/service_lpr.cc +++ b/src/network_inspectors/appid/service_plugins/service_lpr.cc @@ -211,7 +211,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_PRINTSRV); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_PRINTSRV); fail: fail_service(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_mdns.cc b/src/network_inspectors/appid/service_plugins/service_mdns.cc index f52278c44..00d30d0cd 100644 --- a/src/network_inspectors/appid/service_plugins/service_mdns.cc +++ b/src/network_inspectors/appid/service_plugins/service_mdns.cc @@ -165,7 +165,7 @@ int MdnsServiceDetector::validate(AppIdDiscoveryArgs& args) goto fail; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_MDNS); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_MDNS); fail: fail_service(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_mysql.cc b/src/network_inspectors/appid/service_plugins/service_mysql.cc index 3f73772bb..3a26b96b8 100644 --- a/src/network_inspectors/appid/service_plugins/service_mysql.cc +++ b/src/network_inspectors/appid/service_plugins/service_mysql.cc @@ -115,7 +115,8 @@ int MySqlServiceDetector::validate(AppIdDiscoveryArgs& args) data += 6; if (data >= end) goto fail; - return add_service(args.asd, args.pkt, args.dir, APP_ID_MYSQL, nullptr, (const char*)p, nullptr); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_MYSQL, + nullptr, (const char*)p, nullptr); inprocess: service_inprocess(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_netbios.cc b/src/network_inspectors/appid/service_plugins/service_netbios.cc index b75782742..f9b1fefce 100644 --- a/src/network_inspectors/appid/service_plugins/service_netbios.cc +++ b/src/network_inspectors/appid/service_plugins/service_netbios.cc @@ -548,7 +548,7 @@ int NbnsServiceDetector::validate(AppIdDiscoveryArgs& args) } success: - return add_service(args.asd, args.pkt, dir, APP_ID_NETBIOS_NS); + return add_service(args.change_bits, args.asd, args.pkt, dir, APP_ID_NETBIOS_NS); inprocess: service_inprocess(args.asd, args.pkt, dir); @@ -983,7 +983,7 @@ int NbssServiceDetector::validate(AppIdDiscoveryArgs& args) goto inprocess; if ( !args.asd.is_service_detected() ) - if ( add_service(args.asd, args.pkt, dir, nd->serviceAppId) == APPID_SUCCESS ) + if ( add_service(args.change_bits, args.asd, args.pkt, dir, nd->serviceAppId) == APPID_SUCCESS ) add_miscellaneous_info(args.asd, nd->miscAppId); return APPID_SUCCESS; @@ -1166,7 +1166,7 @@ success: { if ( dir == APP_ID_FROM_RESPONDER ) { - if ( add_service(args.asd, args.pkt, dir, serviceAppId) == APPID_SUCCESS ) + if ( add_service(args.change_bits, args.asd, args.pkt, dir, serviceAppId) == APPID_SUCCESS ) add_miscellaneous_info(args.asd, miscAppId); } } diff --git a/src/network_inspectors/appid/service_plugins/service_nntp.cc b/src/network_inspectors/appid/service_plugins/service_nntp.cc index c02deb865..ed1153696 100644 --- a/src/network_inspectors/appid/service_plugins/service_nntp.cc +++ b/src/network_inspectors/appid/service_plugins/service_nntp.cc @@ -345,7 +345,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_NNTP); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_NNTP); fail: fail_service(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_ntp.cc b/src/network_inspectors/appid/service_plugins/service_ntp.cc index 8e91be15f..44182010d 100644 --- a/src/network_inspectors/appid/service_plugins/service_ntp.cc +++ b/src/network_inspectors/appid/service_plugins/service_ntp.cc @@ -127,7 +127,7 @@ int NtpServiceDetector::validate(AppIdDiscoveryArgs& args) goto fail; } - return add_service(args.asd, args.pkt, args.dir, APP_ID_NTP); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_NTP); inprocess: service_inprocess(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_radius.cc b/src/network_inspectors/appid/service_plugins/service_radius.cc index 469a05824..7e3e42047 100644 --- a/src/network_inspectors/appid/service_plugins/service_radius.cc +++ b/src/network_inspectors/appid/service_plugins/service_radius.cc @@ -168,7 +168,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_RADIUS); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_RADIUS); not_compatible: incompatible_data(args.asd, args.pkt, args.dir); @@ -283,7 +283,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_RADIUS_ACCT); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_RADIUS_ACCT); not_compatible: incompatible_data(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_regtest.cc b/src/network_inspectors/appid/service_plugins/service_regtest.cc index 7fe1720bb..fc20718e9 100644 --- a/src/network_inspectors/appid/service_plugins/service_regtest.cc +++ b/src/network_inspectors/appid/service_plugins/service_regtest.cc @@ -80,7 +80,8 @@ int RegTestServiceDetector::validate(AppIdDiscoveryArgs& args) p++; } *v = 0; - return add_service(args.asd, args.pkt, args.dir, APP_ID_REGTEST, nullptr, version, nullptr); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_REGTEST, nullptr, + version, nullptr); inprocess: service_inprocess(args.asd, args.pkt, args.dir); @@ -138,7 +139,8 @@ int RegTestServiceDetector1::validate(AppIdDiscoveryArgs& args) p++; } *v = 0; - return add_service(args.asd, args.pkt, args.dir, APP_ID_REGTEST1, nullptr, version, nullptr); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_REGTEST1, nullptr, + version, nullptr); inprocess: service_inprocess(args.asd, args.pkt, args.dir); @@ -191,7 +193,8 @@ int RegTestServiceDetector2::validate(AppIdDiscoveryArgs& args) p++; } *v = 0; - return add_service(args.asd, args.pkt, args.dir, APP_ID_REGTEST2, nullptr, version, nullptr); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_REGTEST2, nullptr, + version, nullptr); inprocess: service_inprocess(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_rexec.cc b/src/network_inspectors/appid/service_plugins/service_rexec.cc index 50164accc..69264fa0e 100644 --- a/src/network_inspectors/appid/service_plugins/service_rexec.cc +++ b/src/network_inspectors/appid/service_plugins/service_rexec.cc @@ -272,7 +272,7 @@ inprocess: success: if (!args.asd.is_service_detected()) - return add_service(args.asd, args.pkt, args.dir, APP_ID_EXEC); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_EXEC); bail: if (!args.asd.is_service_detected()) diff --git a/src/network_inspectors/appid/service_plugins/service_rfb.cc b/src/network_inspectors/appid/service_plugins/service_rfb.cc index 4a1f04c97..967ff2106 100644 --- a/src/network_inspectors/appid/service_plugins/service_rfb.cc +++ b/src/network_inspectors/appid/service_plugins/service_rfb.cc @@ -97,7 +97,8 @@ int RfbServiceDetector::validate(AppIdDiscoveryArgs& args) p++; } *v = 0; - return add_service(args.asd, args.pkt, args.dir, APP_ID_VNC_RFB, nullptr, version, nullptr); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_VNC_RFB, + nullptr, version, nullptr); inprocess: service_inprocess(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_rlogin.cc b/src/network_inspectors/appid/service_plugins/service_rlogin.cc index aebffa51d..eb9b177e8 100644 --- a/src/network_inspectors/appid/service_plugins/service_rlogin.cc +++ b/src/network_inspectors/appid/service_plugins/service_rlogin.cc @@ -129,7 +129,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_RLOGIN); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_RLOGIN); fail: fail_service(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_rpc.cc b/src/network_inspectors/appid/service_plugins/service_rpc.cc index a6e5d0b2c..6fad6cb75 100644 --- a/src/network_inspectors/appid/service_plugins/service_rpc.cc +++ b/src/network_inspectors/appid/service_plugins/service_rpc.cc @@ -512,7 +512,8 @@ done: else subtype = nullptr; - add_service(args.asd, pkt, dir, APP_ID_SUN_RPC, nullptr, nullptr, subtype); + add_service(args.change_bits, args.asd, pkt, dir, APP_ID_SUN_RPC, + nullptr, nullptr, subtype); } args.asd.set_session_flags(APPID_SESSION_CONTINUE); return APPID_SUCCESS; @@ -857,7 +858,8 @@ inprocess: } else subtype = nullptr; - add_service(args.asd, pkt, dir, APP_ID_SUN_RPC, nullptr, nullptr, subtype); + add_service(args.change_bits, args.asd, pkt, dir, APP_ID_SUN_RPC, + nullptr, nullptr, subtype); } args.asd.set_session_flags(APPID_SESSION_CONTINUE); return APPID_SUCCESS; diff --git a/src/network_inspectors/appid/service_plugins/service_rshell.cc b/src/network_inspectors/appid/service_plugins/service_rshell.cc index 24169ef77..2f5994050 100644 --- a/src/network_inspectors/appid/service_plugins/service_rshell.cc +++ b/src/network_inspectors/appid/service_plugins/service_rshell.cc @@ -283,7 +283,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_SHELL); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_SHELL); bail: incompatible_data(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_rsync.cc b/src/network_inspectors/appid/service_plugins/service_rsync.cc index 70bc2822d..111934cd8 100644 --- a/src/network_inspectors/appid/service_plugins/service_rsync.cc +++ b/src/network_inspectors/appid/service_plugins/service_rsync.cc @@ -121,7 +121,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_RSYNC); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_RSYNC); fail: fail_service(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_rtmp.cc b/src/network_inspectors/appid/service_plugins/service_rtmp.cc index b36a31077..80ae9a8e4 100644 --- a/src/network_inspectors/appid/service_plugins/service_rtmp.cc +++ b/src/network_inspectors/appid/service_plugins/service_rtmp.cc @@ -637,7 +637,7 @@ success: { if ( !hsession->get_field(MISC_URL_FID) ) { - hsession->set_field(MISC_URL_FID, new std::string(ss->swfUrl)); + hsession->set_field(MISC_URL_FID, new std::string(ss->swfUrl), args.change_bits); args.asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG; } @@ -649,12 +649,12 @@ success: { if ( !hsession->get_field(REQ_REFERER_FID) && !args.asd.config->mod_config->referred_appId_disabled ) - hsession->set_field(REQ_REFERER_FID, new std::string(ss->pageUrl)); + hsession->set_field(REQ_REFERER_FID, new std::string(ss->pageUrl), args.change_bits); snort_free(ss->pageUrl); ss->pageUrl = nullptr; } - return add_service(args.asd, args.pkt, args.dir, APP_ID_RTMP); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_RTMP); } diff --git a/src/network_inspectors/appid/service_plugins/service_snmp.cc b/src/network_inspectors/appid/service_plugins/service_snmp.cc index c403a6775..6df490da3 100644 --- a/src/network_inspectors/appid/service_plugins/service_snmp.cc +++ b/src/network_inspectors/appid/service_plugins/service_snmp.cc @@ -572,7 +572,8 @@ success: version_str = nullptr; break; } - return add_service(args.asd, args.pkt, args.dir, APP_ID_SNMP, SNMP_VENDOR_STR, version_str, nullptr); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_SNMP, + SNMP_VENDOR_STR, version_str, nullptr); bail: incompatible_data(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_ssh.cc b/src/network_inspectors/appid/service_plugins/service_ssh.cc index af6d31436..959310105 100644 --- a/src/network_inspectors/appid/service_plugins/service_ssh.cc +++ b/src/network_inspectors/appid/service_plugins/service_ssh.cc @@ -536,7 +536,8 @@ inprocess: return APPID_INPROCESS; case APPID_SUCCESS: - return add_service(args.asd, args.pkt, args.dir, APP_ID_SSH, ss->vendor, ss->version, nullptr); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_SSH, + ss->vendor, ss->version, nullptr); case APPID_NOMATCH: fail: diff --git a/src/network_inspectors/appid/service_plugins/service_ssl.cc b/src/network_inspectors/appid/service_plugins/service_ssl.cc index d5cc59116..96ea2a063 100644 --- a/src/network_inspectors/appid/service_plugins/service_ssl.cc +++ b/src/network_inspectors/appid/service_plugins/service_ssl.cc @@ -876,45 +876,29 @@ success: /* TLS Host */ if (ss->host_name) { - if (args.asd.tsession->tls_host) - snort_free(args.asd.tsession->tls_host); - args.asd.tsession->tls_host = ss->host_name; - args.asd.tsession->tls_host_strlen = ss->host_name_strlen; + args.asd.tsession->set_tls_host(ss->host_name, 0, args.change_bits); args.asd.scan_flags |= SCAN_SSL_HOST_FLAG; } else if (ss->common_name) { // use common name (from server) if we didn't see host name (from client) - char* common_name = snort_strdup(ss->common_name); - - if (args.asd.tsession->tls_host) - snort_free(args.asd.tsession->tls_host); - args.asd.tsession->tls_host = common_name; - args.asd.tsession->tls_host_strlen = ss->common_name_strlen; + args.asd.tsession->set_tls_host(ss->common_name, ss->common_name_strlen, + args.change_bits); args.asd.scan_flags |= SCAN_SSL_HOST_FLAG; } /* TLS Common Name */ if (ss->common_name) - { - if (args.asd.tsession->tls_cname) - snort_free(args.asd.tsession->tls_cname); - args.asd.tsession->tls_cname = ss->common_name; - args.asd.tsession->tls_cname_strlen = ss->common_name_strlen; - } + args.asd.tsession->set_tls_cname(ss->common_name, 0); /* TLS Org Unit */ if (ss->org_name) - { - if (args.asd.tsession->tls_orgUnit) - snort_free(args.asd.tsession->tls_orgUnit); - args.asd.tsession->tls_orgUnit = ss->org_name; - args.asd.tsession->tls_orgUnit_strlen = ss->org_name_strlen; - } + args.asd.tsession->set_tls_org_unit(ss->org_name, 0); ss->host_name = ss->common_name = ss->org_name = nullptr; } - return add_service(args.asd, args.pkt, args.dir, getSslServiceAppId(args.pkt->ptrs.sp)); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, + getSslServiceAppId(args.pkt->ptrs.sp)); } AppId getSslServiceAppId(short srcPort) diff --git a/src/network_inspectors/appid/service_plugins/service_telnet.cc b/src/network_inspectors/appid/service_plugins/service_telnet.cc index e811cac40..7d13f15ff 100644 --- a/src/network_inspectors/appid/service_plugins/service_telnet.cc +++ b/src/network_inspectors/appid/service_plugins/service_telnet.cc @@ -143,7 +143,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_TELNET); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_TELNET); fail: fail_service(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_tftp.cc b/src/network_inspectors/appid/service_plugins/service_tftp.cc index e39e4b976..7448fdb56 100644 --- a/src/network_inspectors/appid/service_plugins/service_tftp.cc +++ b/src/network_inspectors/appid/service_plugins/service_tftp.cc @@ -326,7 +326,7 @@ inprocess: success: if (appidDebug->is_active()) LogMessage("AppIdDbg %s TFTP success\n", appidDebug->get_debug_session()); - return add_service(args.asd, args.pkt, args.dir, APP_ID_TFTP); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_TFTP); bail: incompatible_data(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_timbuktu.cc b/src/network_inspectors/appid/service_plugins/service_timbuktu.cc index 53d962e2c..18b5c054b 100644 --- a/src/network_inspectors/appid/service_plugins/service_timbuktu.cc +++ b/src/network_inspectors/appid/service_plugins/service_timbuktu.cc @@ -154,7 +154,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_TIMBUKTU); + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_TIMBUKTU); fail: fail_service(args.asd, args.pkt, args.dir); diff --git a/src/network_inspectors/appid/service_plugins/service_tns.cc b/src/network_inspectors/appid/service_plugins/service_tns.cc index a87e86e33..6da9570c2 100644 --- a/src/network_inspectors/appid/service_plugins/service_tns.cc +++ b/src/network_inspectors/appid/service_plugins/service_tns.cc @@ -276,7 +276,7 @@ inprocess: return APPID_INPROCESS; success: - return add_service(args.asd, args.pkt, args.dir, APP_ID_ORACLE_TNS, + return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_ORACLE_TNS, nullptr, ss->version ? ss->version : nullptr, nullptr); fail: diff --git a/src/network_inspectors/appid/test/CMakeLists.txt b/src/network_inspectors/appid/test/CMakeLists.txt index f5ab54a37..3fd626d79 100644 --- a/src/network_inspectors/appid/test/CMakeLists.txt +++ b/src/network_inspectors/appid/test/CMakeLists.txt @@ -14,6 +14,10 @@ add_cpputest( appid_detector_test SOURCES $ ) +add_cpputest( appid_discovery_test + SOURCES $ +) + add_cpputest( appid_expected_flags_test SOURCES $ ) diff --git a/src/network_inspectors/appid/test/appid_api_test.cc b/src/network_inspectors/appid/test/appid_api_test.cc index 2b7c16b50..2da4d830f 100644 --- a/src/network_inspectors/appid/test/appid_api_test.cc +++ b/src/network_inspectors/appid/test/appid_api_test.cc @@ -118,7 +118,7 @@ TEST(appid_api, produce_ha_state) mock_flow_data= nullptr; SfIp ip; ip.pton(AF_INET, "192.168.1.222"); - val = appid_api.consume_ha_state(flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066); + appid_api.consume_ha_state(flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066); AppIdSession* session = (AppIdSession*)flow->get_flow_data(AppIdSession::inspector_id); CHECK_TRUE(session); CHECK_TRUE(session->get_tp_app_id() == appHA.appId[0]); @@ -136,7 +136,7 @@ TEST(appid_api, produce_ha_state) // test logic when service app is ftp control appHA.appId[1] = APP_ID_FTP_CONTROL; mock_flow_data= nullptr; - val = appid_api.consume_ha_state(flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066); + appid_api.consume_ha_state(flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066); session = (AppIdSession*)flow->get_flow_data(AppIdSession::inspector_id); CHECK_TRUE(session); uint64_t flags = session->get_session_flags(APPID_SESSION_CLIENT_DETECTED | diff --git a/src/network_inspectors/appid/test/appid_detector_test.cc b/src/network_inspectors/appid/test/appid_detector_test.cc index a423b38a4..463680e1a 100644 --- a/src/network_inspectors/appid/test/appid_detector_test.cc +++ b/src/network_inspectors/appid/test/appid_detector_test.cc @@ -39,6 +39,8 @@ Flow* flow = nullptr; AppIdSession* mock_session = nullptr; +void AppIdHttpSession::set_http_change_bits(AppidChangeBits&, HttpFieldIds) {} + class TestDetector : public AppIdDetector { public: @@ -69,12 +71,13 @@ TEST_GROUP(appid_detector_tests) TEST(appid_detector_tests, add_info) { const char* info_url = "https://tools.ietf.org/html/rfc793"; + AppidChangeBits change_bits; AppIdDetector* ad = new TestDetector; MockAppIdHttpSession* hsession = (MockAppIdHttpSession*)mock_session->get_http_session(); - ad->add_info(*mock_session, info_url); + ad->add_info(*mock_session, info_url, change_bits); STRCMP_EQUAL(hsession->get_cfield(MISC_URL_FID), URL); hsession->reset(); - ad->add_info(*mock_session, info_url); + ad->add_info(*mock_session, info_url, change_bits); STRCMP_EQUAL(mock_session->get_http_session()->get_cfield(MISC_URL_FID), info_url); delete ad; } diff --git a/src/network_inspectors/appid/test/appid_discovery_test.cc b/src/network_inspectors/appid/test/appid_discovery_test.cc new file mode 100644 index 000000000..5455dfaf2 --- /dev/null +++ b/src/network_inspectors/appid/test/appid_discovery_test.cc @@ -0,0 +1,438 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2018-2018 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- +// appid_discovery_test.cc author Masud Hasan + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define APPID_MOCK_INSPECTOR_H // avoiding mocked inspector + +#include "network_inspectors/appid/appid_discovery.cc" + +#include "search_engines/search_tool.h" +#include "utils/sflsq.cc" + +#include "appid_mock_session.h" + +#include +#include + +namespace snort +{ +// Stubs for packet +Packet::Packet(bool) {} +Packet::~Packet() {} + +// Stubs for inspector +Inspector::Inspector() +{ + set_api(nullptr); +} +Inspector::~Inspector() = default; +bool Inspector::likes(Packet*) { return true; } +bool Inspector::get_buf(const char*, Packet*, InspectionBuffer&) { return true; } +class StreamSplitter* Inspector::get_splitter(bool) { return nullptr; } + +// Stubs for module +Module::Module(char const*, char const*) {} +bool Module::set(const char*, Value&, SnortConfig*) { return true; } +void Module::sum_stats(bool) {} +void Module::show_interval_stats(std::vector&, FILE*) {} +void Module::show_stats() {} +void Module::reset_stats() {} +PegCount Module::get_global_count(char const*) const { return 0; } + +// Stubs for logs +void LogMessage(const char*,...) {} +void ErrorMessage(const char*,...) {} +void LogLabel(const char*, FILE*) {} + +// Stubs for utils +char* snort_strdup(const char* str) +{ + assert(str); + size_t n = strlen(str) + 1; + char* p = (char*)snort_alloc(n); + memcpy(p, str, n); + return p; +} +char* snort_strndup(const char* src, size_t) +{ + return snort_strdup(src); +} +time_t packet_time() { return std::time(0); } + +// Stubs for search_tool +SearchTool::SearchTool(const char*, bool) {} +SearchTool::~SearchTool() {} +void SearchTool::add(const char*, unsigned, int, bool) {} +void SearchTool::add(const char*, unsigned, void*, bool) {} +void SearchTool::add(const uint8_t*, unsigned, int, bool) {} +void SearchTool::add(const uint8_t*, unsigned, void*, bool) {} + +// Stubs for ip +namespace ip +{ +void IpApi::set(const SfIp& sip, const SfIp& dip) +{ + type = IAT_DATA; + src.set(sip); + dst.set(dip); + iph = nullptr; +} +} // namespace ip + +} // namespace snort + +// Stubs for publish +static bool databus_publish_called = false; +static char test_log[256]; +void DataBus::publish(const char*, DataEvent& event, Flow*) +{ + databus_publish_called = true; + AppidEvent* appid_event = (AppidEvent*)&event; + snprintf(test_log, 256, "Published change_bits == %s", + appid_event->get_change_bitset().to_string().c_str()); +} + +// Stubs for matchers +static HttpPatternMatchers* http_matchers; +HttpPatternMatchers::~HttpPatternMatchers() {} +void HttpPatternMatchers::get_http_offsets(snort::Packet*, AppIdHttpSession*) {} +HttpPatternMatchers* HttpPatternMatchers::get_instance() +{ + return http_matchers; +} + +// Stubs for AppIdModule +AppIdModule::AppIdModule(): snort::Module("appid_mock", "appid_mock_help") {} +AppIdModule::~AppIdModule() {} +void AppIdModule::sum_stats(bool) {} +void AppIdModule::show_dynamic_stats() {} +bool AppIdModule::begin(char const*, int, snort::SnortConfig*) { return true; } +bool AppIdModule::end(char const*, int, snort::SnortConfig*) { return true; } +bool AppIdModule::set(char const*, snort::Value&, snort::SnortConfig*) { return true; } +const snort::Command* AppIdModule::get_commands() const { return nullptr; } +const PegInfo* AppIdModule::get_pegs() const { return nullptr; } +PegCount* AppIdModule::get_counts() const { return nullptr; } +snort::ProfileStats* AppIdModule::get_profile() const { return nullptr; } + +// Stubs for config +AppIdModuleConfig::~AppIdModuleConfig() {} +AppIdConfig::AppIdConfig(AppIdModuleConfig*) {} +AppIdConfig::~AppIdConfig() {} +static AppIdModuleConfig app_config; +static AppIdConfig my_app_config(&app_config); +AppId AppIdConfig::get_port_service_id(IpProtocol, uint16_t) +{ + return APP_ID_NONE; +} + +// Stubs for AppIdInspector +AppIdInspector::AppIdInspector(AppIdModule&) {} +AppIdInspector::~AppIdInspector() = default; +void AppIdInspector::eval(snort::Packet*) { } +bool AppIdInspector::configure(snort::SnortConfig*) { return true; } +void AppIdInspector::show(snort::SnortConfig*) { } +void AppIdInspector::tinit() { } +void AppIdInspector::tterm() { } +AppIdConfig* AppIdInspector::get_appid_config() +{ + my_app_config.mod_config = &app_config; + return &my_app_config; +} + +// Stubs for AppInfoManager +AppInfoTableEntry* AppInfoManager::get_app_info_entry(AppId) +{ + return nullptr; +} +const char* AppInfoManager::get_app_name(int32_t) +{ + return nullptr; +} + +// Stubs for AppIdSession +void AppIdSession::sync_with_snort_protocol_id(AppId, Packet*) {} +void AppIdSession::check_app_detection_restart(AppidChangeBits&) {} +void AppIdSession::set_client_appid_data(AppId, char*, AppidChangeBits&) {} +void AppIdSession::examine_rtmp_metadata(AppidChangeBits&) {} +void AppIdSession::examine_ssl_metadata(Packet*, AppidChangeBits&) {} +void AppIdSession::update_encrypted_app_id(AppId) {} +AppIdSession* AppIdSession::allocate_session(const Packet*, IpProtocol, + AppidSessionDirection, AppIdInspector&) +{ + return nullptr; +} + +// Stubs for ServiceDiscovery +void ServiceDiscovery::initialize() {} +void ServiceDiscovery::finalize_service_patterns() {} +void ServiceDiscovery::match_by_pattern(AppIdSession&, const Packet*, IpProtocol) {} +void ServiceDiscovery::get_port_based_services(IpProtocol, uint16_t, AppIdSession&) {} +void ServiceDiscovery::get_next_service(const Packet*, const AppidSessionDirection, AppIdSession&) {} +int ServiceDiscovery::identify_service(AppIdSession&, Packet*, AppidSessionDirection, + AppidChangeBits&) { return 0; } +int ServiceDiscovery::add_ftp_service_state(AppIdSession&) { return 0; } +bool ServiceDiscovery::do_service_discovery(AppIdSession&, Packet*, AppidSessionDirection, + AppidChangeBits&) { return 0; } +int ServiceDiscovery::incompatible_data(AppIdSession&, const Packet*,AppidSessionDirection, + ServiceDetector*) { return 0; } +int ServiceDiscovery::fail_service(AppIdSession&, const Packet*, AppidSessionDirection, + ServiceDetector*, ServiceDiscoveryState*) { return 0; } +int ServiceDiscovery::add_service_port(AppIdDetector*, + const ServiceDetectorPort&) { return APPID_EINVALID; } +ServiceDiscovery::ServiceDiscovery(AppIdInspector& ins) + : AppIdDiscovery(ins) {} +void ServiceDiscovery::release_instance() {} +void ServiceDiscovery::release_thread_resources() {} +ServiceDiscovery& ServiceDiscovery::get_instance(AppIdInspector* ins) +{ + static ServiceDiscovery s_discovery_manager(*ins); + return s_discovery_manager; +} + +// Stubs for ClientDiscovery +ClientDiscovery::ClientDiscovery(AppIdInspector& ins) + : AppIdDiscovery(ins) {} +ClientDiscovery::~ClientDiscovery() {} +void ClientDiscovery::initialize() {} +void ClientDiscovery::finalize_client_plugins() {} +void ClientDiscovery::release_instance() {} +void ClientDiscovery::release_thread_resources() {} +ClientDiscovery& ClientDiscovery::get_instance(AppIdInspector* ins) +{ + static ClientDiscovery c_discovery_manager(*ins); + return c_discovery_manager; +} +bool ClientDiscovery::do_client_discovery(AppIdSession&, Packet*, + AppidSessionDirection, AppidChangeBits&) +{ + return false; +} + +// Stubs for misc items +HostPortVal* HostPortCache::find(const SfIp*, uint16_t, IpProtocol) +{ + return nullptr; +} +void AppIdServiceState::check_reset(AppIdSession&, const SfIp*, uint16_t) {} +int dns_host_scan_hostname(const uint8_t*, size_t, AppId*, AppId*) +{ + return 0; +} +bool do_tp_discovery(AppIdSession&, IpProtocol, + Packet*, AppidSessionDirection&, AppidChangeBits&) +{ + return true; +} +TPLibHandler* TPLibHandler::self = nullptr; +THREAD_LOCAL AppIdStats appid_stats; +THREAD_LOCAL AppIdDebug* appidDebug = nullptr; +void AppIdDebug::activate(const Flow*, const AppIdSession*, bool) { active = false; } +AppId find_length_app_cache(const LengthKey&) +{ + return APP_ID_NONE; +} +void check_session_for_AF_indicator(Packet*, AppidSessionDirection, AppId) {} +AppId check_session_for_AF_forecast(AppIdSession&, Packet*, AppidSessionDirection, AppId) +{ + return APP_ID_UNKNOWN; +} + +TEST_GROUP(appid_discovery_tests) +{ + void setup() override + { + appidDebug = new AppIdDebug(); + http_matchers = new HttpPatternMatchers; + AppIdPegCounts::init_pegs(); + } + + void teardown() override + { + delete appidDebug; + delete http_matchers; + AppIdPegCounts::cleanup_pegs(); + AppIdPegCounts::cleanup_peg_info(); + } +}; + +TEST(appid_discovery_tests, event_published_when_ignoring_flow) +{ + // Testing event from do_pre_discovery() path + databus_publish_called = false; + test_log[0] = '\0'; + Packet p; + DAQ_PktHdr_t pkth; + p.pkth = &pkth; + SfIp ip; + p.ptrs.ip_api.set(ip, ip); + AppIdModule app_module; + AppIdInspector ins(app_module); + AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins); + Flow* flow = new Flow; + flow->set_flow_data(asd); + p.flow = flow; + asd->config = &my_app_config; + asd->common.initiator_port = 21; + asd->common.initiator_ip.set("1.2.3.4"); + asd->set_session_flags(APPID_SESSION_IGNORE_FLOW); + + AppIdDiscovery::do_application_discovery(&p, ins); + + // Detect changes in service, client, payload, and misc appid + CHECK_EQUAL(databus_publish_called, true); + STRCMP_EQUAL(test_log, "Published change_bits == 0000000001111"); + delete asd; + delete flow; +} + +TEST(appid_discovery_tests, event_published_when_processing_flow) +{ + // Testing event from do_discovery() path + databus_publish_called = false; + test_log[0] = '\0'; + Packet p; + DAQ_PktHdr_t pkth; + p.pkth = &pkth; + SfIp ip; + p.ptrs.ip_api.set(ip, ip); + AppIdModule app_module; + AppIdInspector ins(app_module); + AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins); + Flow* flow = new Flow; + flow->set_flow_data(asd); + p.flow = flow; + asd->config = &my_app_config; + asd->common.initiator_port = 21; + asd->common.initiator_ip.set("1.2.3.4"); + + AppIdDiscovery::do_application_discovery(&p, ins); + + // Detect changes in service, client, payload, and misc appid + CHECK_EQUAL(databus_publish_called, true); + STRCMP_EQUAL(test_log, "Published change_bits == 0000000001111"); + delete asd; + delete flow; +} + +TEST(appid_discovery_tests, change_bits_for_client_version) +{ + // Testing set_version + AppidChangeBits change_bits; + AppIdModule app_module; + AppIdInspector ins(app_module); + AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins); + const char* version = "3.0"; + asd->client.set_version(version, change_bits); + + // Detect changes in client version + CHECK_EQUAL(change_bits.test(APPID_VERSION_BIT), true); + delete asd; +} + +TEST(appid_discovery_tests, change_bits_for_tls_host) +{ + // Testing set_tls_host + AppidChangeBits change_bits; + const char* host = "www.cisco.com"; + TlsSession tls; + tls.set_tls_host(host, 0, change_bits); + + // Detect changes in tls_host + CHECK_EQUAL(change_bits.test(APPID_TLSHOST_BIT), true); +} + +TEST(appid_discovery_tests, change_bits_for_non_http_appid) +{ + // Testing FTP appid + databus_publish_called = false; + Packet p; + DAQ_PktHdr_t pkth; + p.pkth = &pkth; + SfIp ip; + p.ptrs.ip_api.set(ip, ip); + AppIdModule app_module; + AppIdInspector ins(app_module); + AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins); + Flow* flow = new Flow; + flow->set_flow_data(asd); + p.flow = flow; + asd->config = &my_app_config; + asd->common.initiator_port = 21; + asd->common.initiator_ip.set("1.2.3.4"); + asd->misc_app_id = APP_ID_NONE; + asd->payload.set_id(APP_ID_NONE); + asd->client.set_id(APP_ID_CURL); + asd->service.set_id(APP_ID_FTP); + + AppIdDiscovery::do_application_discovery(&p, ins); + + // Detect event for FTP service and CURL client + CHECK_EQUAL(databus_publish_called, true); + CHECK_EQUAL(asd->client.get_id(), APP_ID_CURL); + CHECK_EQUAL(asd->service.get_id(), APP_ID_FTP); + + // Testing DNS appid + databus_publish_called = false; + asd->misc_app_id = APP_ID_NONE; + asd->payload.set_id(APP_ID_NONE); + asd->client.set_id(APP_ID_NONE); + asd->service.set_id(APP_ID_DNS); + AppIdDiscovery::do_application_discovery(&p, ins); + + // Detect event for DNS service + CHECK_EQUAL(databus_publish_called, true); + CHECK_EQUAL(asd->service.get_id(), APP_ID_DNS); + + delete asd; + delete flow; +} + +TEST(appid_discovery_tests, change_bits_to_string) +{ + // Testing that all bits from AppidChangeBit enum get translated + AppidChangeBits change_bits; + std::string str; + + // Detect empty + change_bits_to_string(change_bits, str); + STRCMP_EQUAL(str.c_str(), ""); + + // Detect all; failure of this test means some bits from enum are missed in translation + change_bits.set(); + change_bits_to_string(change_bits, str); + STRCMP_EQUAL(str.c_str(), "service, client, payload, misc, referred, host," + " tls-host, url, user-agent, response, referrer, xff, client-version"); + + // Detect enum vs translator mismatch actually working + std::bitset change_bits_extra; + change_bits_extra.set(); + str.clear(); + change_bits_to_string(*((AppidChangeBits*) &change_bits_extra), str); + STRCMP_EQUAL(str.c_str(), "service, client, payload, misc, referred, host, tls-host, url," + " user-agent, response, referrer, xff, client-version, change_bits_to_string error!"); +} + +int main(int argc, char** argv) +{ + int rc = CommandLineTestRunner::RunAllTests(argc, argv); + return rc; +} diff --git a/src/network_inspectors/appid/test/appid_expected_flags_test.cc b/src/network_inspectors/appid/test/appid_expected_flags_test.cc index 2566107be..535143485 100644 --- a/src/network_inspectors/appid/test/appid_expected_flags_test.cc +++ b/src/network_inspectors/appid/test/appid_expected_flags_test.cc @@ -28,6 +28,8 @@ #include #include +void AppIdHttpSession::set_http_change_bits(AppidChangeBits&, HttpFieldIds) {} + class MockServiceDetector : public ServiceDetector { public: diff --git a/src/network_inspectors/appid/test/appid_http_event_test.cc b/src/network_inspectors/appid/test/appid_http_event_test.cc index 3fd01a84a..e292138c7 100644 --- a/src/network_inspectors/appid/test/appid_http_event_test.cc +++ b/src/network_inspectors/appid/test/appid_http_event_test.cc @@ -68,6 +68,10 @@ class FakeHttpMsgHeader }; FakeHttpMsgHeader* fake_msg_header = nullptr; +void AppIdDiscovery::publish_appid_event(AppidChangeBits&, snort::Flow*) {} + +void AppIdHttpSession::set_http_change_bits(AppidChangeBits&, HttpFieldIds) {} + const uint8_t* HttpEvent::get_content_type(int32_t& length) { global_field.set(0, nullptr); diff --git a/src/network_inspectors/appid/test/appid_http_session_test.cc b/src/network_inspectors/appid/test/appid_http_session_test.cc index 20bc67d12..2afc0fd9a 100644 --- a/src/network_inspectors/appid/test/appid_http_session_test.cc +++ b/src/network_inspectors/appid/test/appid_http_session_test.cc @@ -91,8 +91,9 @@ AppId HttpPatternMatchers::get_appid_by_content_type(const char*, int) } bool HttpPatternMatchers::get_appid_from_url(char*, const char*, char**, - const char*, AppId*, AppId*, AppId*, AppId*, bool) + const char*, AppId*, AppId*, AppId*, AppId* referredPayloadAppId, bool) { + *referredPayloadAppId = APP_ID_FACEBOOK; return true; } @@ -106,15 +107,15 @@ AppIdSession::~AppIdSession() { } -void AppIdSession::set_client_appid_data(AppId, char*) +void AppIdSession::set_client_appid_data(AppId, char*, AppidChangeBits&) { } -void AppIdSession::set_service_appid_data(AppId, char*, char*) +void AppIdSession::set_service_appid_data(AppId, char*, char*, AppidChangeBits&) { } -void AppIdSession::set_payload_appid_data(AppId, char*) +void AppIdSession::set_payload_appid_data(AppId, char*, AppidChangeBits&) { } @@ -131,8 +132,16 @@ bool AppIdSession::is_payload_appid_set() return true; } -void AppIdSession::set_referred_payload_app_id_data(AppId) +void AppIdSession::set_referred_payload_app_id_data(AppId id, AppidChangeBits& change_bits) { + if (id <= APP_ID_NONE) + return; + + if (referred_payload_app_id != id) + { + referred_payload_app_id = id; + change_bits.set(APPID_REFERRED_BIT); + } } // AppIdDebug mock functions @@ -205,20 +214,22 @@ TEST(appid_http_session, http_field_ids_enum_order) // Set the fields using integers, then get them by HttpFieldIds, // to make sure the order of the HttpFieldIds has not changed // in appid_http_session.h. - hsession.set_field( (HttpFieldIds)0, new std::string("agent") ); - hsession.set_field( (HttpFieldIds)1, new std::string("host") ); - hsession.set_field( (HttpFieldIds)2, new std::string("referer") ); - hsession.set_field( (HttpFieldIds)3, new std::string("uri") ); - hsession.set_field( (HttpFieldIds)4, new std::string("cookie") ); - hsession.set_field( (HttpFieldIds)5, new std::string("req_body") ); - hsession.set_field( (HttpFieldIds)6, new std::string("content_type") ); - hsession.set_field( (HttpFieldIds)7, new std::string("location") ); - hsession.set_field( (HttpFieldIds)8, new std::string("rsp_body") ); - hsession.set_field( (HttpFieldIds)9, new std::string("via") ); - hsession.set_field( (HttpFieldIds)10, new std::string("response_code") ); - hsession.set_field( (HttpFieldIds)11, new std::string("server") ); - hsession.set_field( (HttpFieldIds)12, new std::string("xww") ); - hsession.set_field( (HttpFieldIds)13, new std::string("url") ); + AppidChangeBits change_bits; + + hsession.set_field( (HttpFieldIds)0, new std::string("agent"), change_bits ); + hsession.set_field( (HttpFieldIds)1, new std::string("host"), change_bits ); + hsession.set_field( (HttpFieldIds)2, new std::string("referer"), change_bits ); + hsession.set_field( (HttpFieldIds)3, new std::string("uri"), change_bits ); + hsession.set_field( (HttpFieldIds)4, new std::string("cookie"), change_bits ); + hsession.set_field( (HttpFieldIds)5, new std::string("req_body"), change_bits ); + hsession.set_field( (HttpFieldIds)6, new std::string("content_type"), change_bits ); + hsession.set_field( (HttpFieldIds)7, new std::string("location"), change_bits ); + hsession.set_field( (HttpFieldIds)8, new std::string("rsp_body"), change_bits ); + hsession.set_field( (HttpFieldIds)9, new std::string("via"), change_bits ); + hsession.set_field( (HttpFieldIds)10, new std::string("response_code"), change_bits ); + hsession.set_field( (HttpFieldIds)11, new std::string("server"), change_bits ); + hsession.set_field( (HttpFieldIds)12, new std::string("xww"), change_bits ); + hsession.set_field( (HttpFieldIds)13, new std::string("url"), change_bits ); const std::string* field; field = hsession.get_field(REQ_AGENT_FID); @@ -249,6 +260,29 @@ TEST(appid_http_session, http_field_ids_enum_order) STRCMP_EQUAL(field->c_str(), "xww"); field = hsession.get_field(MISC_URL_FID); STRCMP_EQUAL(field->c_str(), "url"); + + // Detect changes in host, url, user agent, response, and referer fields + // that generate appid event consumed by subscribers + CHECK_EQUAL(change_bits.test(APPID_HOST_BIT), true); + CHECK_EQUAL(change_bits.test(APPID_URL_BIT), true); + CHECK_EQUAL(change_bits.test(APPID_USERAGENT_BIT), true); + CHECK_EQUAL(change_bits.test(APPID_RESPONSE_BIT), true); + CHECK_EQUAL(change_bits.test(APPID_REFERER_BIT), true); +} + +TEST(appid_http_session, change_bits_for_referred_appid) +{ + // Testing set_referred_payload_app_id_data + AppidChangeBits change_bits; + AppIdPegCounts::init_pegs(); + session.service.set_id(APP_ID_HTTP); + session.scan_flags |= SCAN_HTTP_HOST_URL_FLAG; + hsession.set_skip_simple_detect(false); + hsession.set_field( (HttpFieldIds)2, new std::string("referer"), change_bits ); + hsession.process_http_packet(APP_ID_FROM_INITIATOR, change_bits); + + // Detect changes in referred appid + CHECK_EQUAL(change_bits.test(APPID_REFERRED_BIT), true); } int main(int argc, char** argv) diff --git a/src/network_inspectors/appid/test/appid_mock_http_session.h b/src/network_inspectors/appid/test/appid_mock_http_session.h index e29551568..b2410d701 100644 --- a/src/network_inspectors/appid/test/appid_mock_http_session.h +++ b/src/network_inspectors/appid/test/appid_mock_http_session.h @@ -43,7 +43,7 @@ AppIdHttpSession::~AppIdHttpSession() } } -int AppIdHttpSession::process_http_packet(AppidSessionDirection) { return 0; } +int AppIdHttpSession::process_http_packet(AppidSessionDirection, AppidChangeBits&) { return 0; } char const* APPID_UT_XFF_IP_ADDR = "192.168.0.1"; char const* CONTENT_TYPE = "html/text"; @@ -65,7 +65,7 @@ char const* RSP_BODY = "this is the body of the http response"; #define URI_OFFSET 22 #define COOKIE_OFFSET 44 -void AppIdHttpSession::update_url() +void AppIdHttpSession::update_url(AppidChangeBits&) { const std::string* host = meta_data[REQ_HOST_FID]; const std::string* uri = meta_data[REQ_URI_FID]; @@ -108,19 +108,6 @@ public: meta_offset[REQ_COOKIE_FID].second = COOKIE_OFFSET + strlen(NEW_COOKIE); } - void init_hsession_new_fields() - { - set_field(REQ_AGENT_FID, new std::string(USERAGENT)); - set_field(REQ_HOST_FID, new std::string(HOST)); - set_field(REQ_REFERER_FID, new std::string(REFERER)); - set_field(REQ_URI_FID, new std::string(URI)); - set_field(REQ_COOKIE_FID, new std::string(COOKIE)); - set_field(REQ_BODY_FID, new std::string(REQ_BODY)); - set_field(RSP_CONTENT_TYPE_FID, new std::string(CONTENT_TYPE)); - set_field(RSP_LOCATION_FID, new std::string(LOCATION)); - set_field(RSP_BODY_FID, new std::string(RSP_BODY)); - } - void reset() { for ( int i = 0; i < NUM_METADATA_FIELDS; i++) diff --git a/src/network_inspectors/appid/test/appid_mock_session.h b/src/network_inspectors/appid/test/appid_mock_session.h index 2af7082d1..d5cc0f372 100644 --- a/src/network_inspectors/appid/test/appid_mock_session.h +++ b/src/network_inspectors/appid/test/appid_mock_session.h @@ -73,18 +73,18 @@ AppIdSession::AppIdSession(IpProtocol, const SfIp*, uint16_t, AppIdInspector& in { common.flow_type = APPID_FLOW_TYPE_NORMAL; service_port = APPID_UT_SERVICE_PORT; + AppidChangeBits change_bits; client.update_user(APPID_UT_ID, APPID_UT_USERNAME); - client.set_version(APPID_UT_CLIENT_VERSION); + client.set_version(APPID_UT_CLIENT_VERSION, change_bits); service.set_vendor(APPID_UT_SERVICE_VENDOR); - service.set_version(APPID_UT_SERVICE_VERSION); + service.set_version(APPID_UT_SERVICE_VERSION, change_bits); subtype = &APPID_UT_SERVICE_SUBTYPE; search_support_type = UNKNOWN_SEARCH_ENGINE; tsession = new TlsSession; - tsession->tls_host = (char*)APPID_UT_TLS_HOST; service_ip.pton(AF_INET, APPID_UT_SERVICE_IP_ADDR); common.initiator_ip.pton(AF_INET, APPID_UT_INITIATOR_IP_ADDR); @@ -166,26 +166,49 @@ void* AppIdSession::remove_flow_data(unsigned type) return data; } -void AppIdSession::set_application_ids(AppId, AppId, AppId, AppId) { } +void AppIdSession::set_application_ids(AppId service_id, AppId client_id, + AppId payload_id, AppId misc_id, AppidChangeBits& change_bits) +{ + if (application_ids[APP_PROTOID_SERVICE] != service_id) + { + application_ids[APP_PROTOID_SERVICE] = service_id; + change_bits.set(APPID_SERVICE_BIT); + } + if (application_ids[APP_PROTOID_CLIENT] != client_id) + { + application_ids[APP_PROTOID_CLIENT] = client_id; + change_bits.set(APPID_CLIENT_BIT); + } + if (application_ids[APP_PROTOID_PAYLOAD] != payload_id) + { + application_ids[APP_PROTOID_PAYLOAD] = payload_id; + change_bits.set(APPID_PAYLOAD_BIT); + } + if (application_ids[APP_PROTOID_MISC] != misc_id) + { + application_ids[APP_PROTOID_MISC] = misc_id; + change_bits.set(APPID_MISC_BIT); + } +} AppId AppIdSession::pick_service_app_id() { - return APPID_UT_ID; + return service.get_id(); } AppId AppIdSession::pick_misc_app_id() { - return APPID_UT_ID; + return misc_app_id; } AppId AppIdSession::pick_client_app_id() { - return APPID_UT_ID; + return client.get_id(); } AppId AppIdSession::pick_payload_app_id() { - return APPID_UT_ID; + return payload.get_id(); } AppId AppIdSession::pick_referred_payload_app_id() diff --git a/src/network_inspectors/appid/test/appid_session_api_test.cc b/src/network_inspectors/appid/test/appid_session_api_test.cc index 929e6f0e6..11276a148 100644 --- a/src/network_inspectors/appid/test/appid_session_api_test.cc +++ b/src/network_inspectors/appid/test/appid_session_api_test.cc @@ -129,6 +129,8 @@ TEST(appid_session_api, get_http_search) TEST(appid_session_api, get_tls_host) { + AppidChangeBits change_bits; + mock_session->tsession->set_tls_host(APPID_UT_TLS_HOST, 0, change_bits); const char* val = appid_session_api->get_tls_host(); STRCMP_EQUAL(val, APPID_UT_TLS_HOST); } @@ -226,7 +228,7 @@ TEST(appid_session_api, get_user_name) CHECK_TRUE(service == APPID_UT_ID); CHECK_TRUE(!isLoginSuccessful); mock_session->set_session_flags(APPID_SESSION_LOGIN_SUCCEEDED); - val = appid_session_api->get_user_name(&service, &isLoginSuccessful); + appid_session_api->get_user_name(&service, &isLoginSuccessful); CHECK_TRUE(service == APPID_UT_ID); CHECK_TRUE(isLoginSuccessful); } diff --git a/src/network_inspectors/appid/test/service_state_test.cc b/src/network_inspectors/appid/test/service_state_test.cc index 389065c7b..797859f52 100644 --- a/src/network_inspectors/appid/test/service_state_test.cc +++ b/src/network_inspectors/appid/test/service_state_test.cc @@ -88,9 +88,11 @@ void ServiceDiscovery::finalize_service_patterns() {} void ServiceDiscovery::match_by_pattern(AppIdSession&, const Packet*, IpProtocol) {} void ServiceDiscovery::get_port_based_services(IpProtocol, uint16_t, AppIdSession&) {} void ServiceDiscovery::get_next_service(const Packet*, const AppidSessionDirection, AppIdSession&) {} -int ServiceDiscovery::identify_service(AppIdSession&, Packet*, AppidSessionDirection) { return 0; } +int ServiceDiscovery::identify_service(AppIdSession&, Packet*, AppidSessionDirection, + AppidChangeBits&) { return 0; } int ServiceDiscovery::add_ftp_service_state(AppIdSession&) { return 0; } -bool ServiceDiscovery::do_service_discovery(AppIdSession&, Packet*, AppidSessionDirection) { return 0; } +bool ServiceDiscovery::do_service_discovery(AppIdSession&, Packet*, AppidSessionDirection, + AppidChangeBits&) { return 0; } int ServiceDiscovery::incompatible_data(AppIdSession&, const Packet*,AppidSessionDirection, ServiceDetector*) { return 0; } int ServiceDiscovery::fail_service(AppIdSession&, const Packet*, AppidSessionDirection, diff --git a/src/network_inspectors/appid/tp_appid_utils.cc b/src/network_inspectors/appid/tp_appid_utils.cc index b6973e6d9..5a9f64240 100644 --- a/src/network_inspectors/appid/tp_appid_utils.cc +++ b/src/network_inspectors/appid/tp_appid_utils.cc @@ -95,7 +95,7 @@ static inline int check_ssl_appid_for_reinspect(AppId app_id) // Or, register observers with THirdPartyAppIDAttributeData and modify the // set functions to copy the tp buffers directly into the appropriate observer. static inline void process_http_session(AppIdSession& asd, - ThirdPartyAppIDAttributeData& attribute_data) + ThirdPartyAppIDAttributeData& attribute_data, AppidChangeBits& change_bits) { AppIdHttpSession* hsession = asd.get_http_session(); string* field=0; @@ -125,7 +125,7 @@ static inline void process_http_session(AppIdSession& asd, if ( hsession->get_field(MISC_URL_FID) ) hsession->set_chp_finished(false); - hsession->set_field(MISC_URL_FID, url); + hsession->set_field(MISC_URL_FID, url, change_bits); asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG; } @@ -134,7 +134,7 @@ static inline void process_http_session(AppIdSession& asd, if (hsession->get_field(REQ_HOST_FID)) hsession->set_chp_finished(false); - hsession->set_field(REQ_HOST_FID, spdyRequestHost); + hsession->set_field(REQ_HOST_FID, spdyRequestHost, change_bits); hsession->set_offset(REQ_HOST_FID, attribute_data.spdy_request_host_begin(), attribute_data.spdy_request_host_end()); @@ -152,7 +152,7 @@ static inline void process_http_session(AppIdSession& asd, if ( hsession->get_field(REQ_URI_FID) ) hsession->set_chp_finished(false); - hsession->set_field(REQ_URI_FID, spdyRequestPath); + hsession->set_field(REQ_URI_FID, spdyRequestPath, change_bits); hsession->set_offset(REQ_URI_FID, attribute_data.spdy_request_path_begin(), attribute_data.spdy_request_path_end()); @@ -171,7 +171,7 @@ static inline void process_http_session(AppIdSession& asd, if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(REQ_HOST_FID, field); + hsession->set_field(REQ_HOST_FID, field, change_bits); hsession->set_offset(REQ_HOST_FID, attribute_data.http_request_host_begin(), attribute_data.http_request_host_end()); @@ -201,7 +201,7 @@ static inline void process_http_session(AppIdSession& asd, // In all other cases field can be const string*. field->insert(4, 1, 's'); } - hsession->set_field(MISC_URL_FID, field); + hsession->set_field(MISC_URL_FID, field, change_bits); asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG; } @@ -211,7 +211,7 @@ static inline void process_http_session(AppIdSession& asd, if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(REQ_URI_FID, field); + hsession->set_field(REQ_URI_FID, field, change_bits); hsession->set_offset(REQ_URI_FID, attribute_data.http_request_uri_begin(), attribute_data.http_request_uri_end()); @@ -230,7 +230,7 @@ static inline void process_http_session(AppIdSession& asd, if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(MISC_VIA_FID, field); + hsession->set_field(MISC_VIA_FID, field, change_bits); asd.scan_flags |= SCAN_HTTP_VIA_FLAG; } else if ( (field=attribute_data.http_response_via(own)) != nullptr ) @@ -239,7 +239,7 @@ static inline void process_http_session(AppIdSession& asd, if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(MISC_VIA_FID, field); + hsession->set_field(MISC_VIA_FID, field, change_bits); asd.scan_flags |= SCAN_HTTP_VIA_FLAG; } @@ -249,7 +249,7 @@ static inline void process_http_session(AppIdSession& asd, if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(REQ_AGENT_FID, field); + hsession->set_field(REQ_AGENT_FID, field, change_bits); hsession->set_offset(REQ_AGENT_FID, attribute_data.http_request_user_agent_begin(), attribute_data.http_request_user_agent_end()); @@ -286,7 +286,7 @@ static inline void process_http_session(AppIdSession& asd, if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(MISC_RESP_CODE_FID, field); + hsession->set_field(MISC_RESP_CODE_FID, field, change_bits); } // Check to see if we've got an upgrade to HTTP/2 (if enabled). @@ -318,7 +318,7 @@ static inline void process_http_session(AppIdSession& asd, if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(REQ_REFERER_FID, field); + hsession->set_field(REQ_REFERER_FID, field, change_bits); hsession->set_offset(REQ_REFERER_FID, attribute_data.http_request_referer_begin(), attribute_data.http_request_referer_end()); @@ -335,7 +335,7 @@ static inline void process_http_session(AppIdSession& asd, if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(REQ_COOKIE_FID, field); + hsession->set_field(REQ_COOKIE_FID, field, change_bits); hsession->set_offset(REQ_COOKIE_FID, attribute_data.http_request_cookie_begin(), attribute_data.http_request_cookie_end()); @@ -352,7 +352,7 @@ static inline void process_http_session(AppIdSession& asd, if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(RSP_CONTENT_TYPE_FID, field); + hsession->set_field(RSP_CONTENT_TYPE_FID, field, change_bits); asd.scan_flags |= SCAN_HTTP_CONTENT_TYPE_FLAG; } @@ -362,7 +362,7 @@ static inline void process_http_session(AppIdSession& asd, if ( hsession->get_field(RSP_LOCATION_FID) ) if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(RSP_LOCATION_FID, field); + hsession->set_field(RSP_LOCATION_FID, field, change_bits); } if ( (field=attribute_data.http_request_body(own)) != nullptr ) @@ -373,7 +373,7 @@ static inline void process_http_session(AppIdSession& asd, if ( hsession->get_field(REQ_BODY_FID) ) if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(REQ_BODY_FID, field); + hsession->set_field(REQ_BODY_FID, field, change_bits); } if (hsession->get_ptype_scan_count(RSP_BODY_FID) && @@ -382,12 +382,12 @@ static inline void process_http_session(AppIdSession& asd, if (hsession->get_field(RSP_BODY_FID) ) if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)) hsession->set_chp_finished(false); - hsession->set_field(RSP_BODY_FID, field); + hsession->set_field(RSP_BODY_FID, field, change_bits); } if (attribute_data.numXffFields) hsession->update_http_xff_address(attribute_data.xffFieldValue, - attribute_data.numXffFields); + attribute_data.numXffFields, change_bits); if (!hsession->is_chp_finished() || hsession->is_chp_hold_flow()) { @@ -397,19 +397,19 @@ static inline void process_http_session(AppIdSession& asd, if ( (field=attribute_data.http_response_server(own)) != nullptr) { - hsession->set_field(MISC_SERVER_FID, field); + hsession->set_field(MISC_SERVER_FID, field, change_bits); asd.scan_flags |= SCAN_HTTP_VENDOR_FLAG; } if ( (field=attribute_data.http_request_x_working_with(own)) != nullptr ) { - hsession->set_field(MISC_XWW_FID, field); + hsession->set_field(MISC_XWW_FID, field, change_bits); asd.scan_flags |= SCAN_HTTP_XWORKINGWITH_FLAG; } } static inline void process_rtmp(AppIdSession& asd, - ThirdPartyAppIDAttributeData& attribute_data, int confidence) + ThirdPartyAppIDAttributeData& attribute_data, int confidence, AppidChangeBits& change_bits) { AppIdHttpSession* hsession = asd.get_http_session(); AppId service_id = 0; @@ -425,7 +425,7 @@ static inline void process_rtmp(AppIdSession& asd, { if ( ( field=attribute_data.http_request_url(own) ) != nullptr ) { - hsession->set_field(MISC_URL_FID, field); + hsession->set_field(MISC_URL_FID, field, change_bits); asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG; } } @@ -435,7 +435,7 @@ static inline void process_rtmp(AppIdSession& asd, { if ( ( field=attribute_data.http_request_referer(own) ) != nullptr ) { - hsession->set_field(REQ_REFERER_FID, field); + hsession->set_field(REQ_REFERER_FID, field, change_bits); } } @@ -443,7 +443,7 @@ static inline void process_rtmp(AppIdSession& asd, { if ( ( field=attribute_data.http_request_user_agent(own) ) != nullptr ) { - hsession->set_field(REQ_AGENT_FID, field); + hsession->set_field(REQ_AGENT_FID, field, change_bits); hsession->set_offset(REQ_AGENT_FID, attribute_data.http_request_user_agent_begin(), attribute_data.http_request_user_agent_end()); @@ -464,11 +464,11 @@ static inline void process_rtmp(AppIdSession& asd, http_matchers->identify_user_agent(field->c_str(), size, service_id, client_id, &version); - asd.set_client_appid_data(client_id, version); + asd.set_client_appid_data(client_id, version, change_bits); // do not overwrite a previously-set service if ( service_id <= APP_ID_NONE ) - asd.set_service_appid_data(service_id, nullptr, nullptr); + asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits); asd.scan_flags |= ~SCAN_HTTP_USER_AGENT_FLAG; snort_free(version); @@ -492,13 +492,13 @@ static inline void process_rtmp(AppIdSession& asd, { // do not overwrite a previously-set client or service if ( client_id <= APP_ID_NONE ) - asd.set_client_appid_data(client_id, nullptr); + asd.set_client_appid_data(client_id, nullptr, change_bits); if ( service_id <= APP_ID_NONE ) - asd.set_service_appid_data(service_id, nullptr, nullptr); + asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits); // DO overwrite a previously-set data - asd.set_payload_appid_data(payload_id, nullptr); - asd.set_referred_payload_app_id_data(referred_payload_app_id); + asd.set_payload_appid_data(payload_id, nullptr, change_bits); + asd.set_referred_payload_app_id_data(referred_payload_app_id, change_bits); } } @@ -511,7 +511,7 @@ static inline void process_rtmp(AppIdSession& asd, } static inline void process_ssl(AppIdSession& asd, - ThirdPartyAppIDAttributeData& attribute_data) + ThirdPartyAppIDAttributeData& attribute_data, AppidChangeBits& change_bits) { AppId tmpAppId = APP_ID_NONE; int tmpConfidence = 0; @@ -526,11 +526,11 @@ static inline void process_ssl(AppIdSession& asd, asd.tsession = (TlsSession*)snort_calloc(sizeof(TlsSession)); if (!asd.client.get_id()) - asd.set_client_appid_data(APP_ID_SSL_CLIENT, nullptr); + asd.set_client_appid_data(APP_ID_SSL_CLIENT, nullptr, change_bits); if ( (field=attribute_data.tls_host(false)) != nullptr ) { - asd.tsession->set_tls_host(field->c_str(), field->size()); + asd.tsession->set_tls_host(field->c_str(), field->size(), change_bits); if (check_ssl_appid_for_reinspect(tmpAppId)) asd.scan_flags |= SCAN_SSL_HOST_FLAG; } @@ -563,7 +563,8 @@ static inline void process_ftp_control(AppIdSession& asd, } static inline void process_third_party_results(AppIdSession& asd, int confidence, - vector& proto_list, ThirdPartyAppIDAttributeData& attribute_data) + vector& proto_list, ThirdPartyAppIDAttributeData& attribute_data, + AppidChangeBits& change_bits) { if ( asd.payload.get_id() == APP_ID_NONE and contains(proto_list, APP_ID_EXCHANGE) ) asd.payload.set_id(APP_ID_EXCHANGE); @@ -584,14 +585,14 @@ static inline void process_third_party_results(AppIdSession& asd, int confidence } if (asd.get_session_flags(APPID_SESSION_HTTP_SESSION)) - process_http_session(asd, attribute_data); + process_http_session(asd, attribute_data, change_bits); else if (contains(proto_list, APP_ID_RTMP) || contains(proto_list, APP_ID_RTSP) ) - process_rtmp(asd, attribute_data, confidence); + process_rtmp(asd, attribute_data, confidence, change_bits); else if (contains(proto_list, APP_ID_SSL)) - process_ssl(asd, attribute_data); + process_ssl(asd, attribute_data, change_bits); else if (contains(proto_list, APP_ID_FTP_CONTROL)) process_ftp_control(asd, attribute_data); @@ -620,7 +621,7 @@ static inline void check_terminate_tp_module(AppIdSession& asd, uint16_t tpPktCo } bool do_tp_discovery(AppIdSession& asd, IpProtocol protocol, - Packet* p, AppidSessionDirection& direction) + Packet* p, AppidSessionDirection& direction, AppidChangeBits& change_bits) { if ( !TPLibHandler::have_tp() ) return true; @@ -717,7 +718,8 @@ bool do_tp_discovery(AppIdSession& asd, IpProtocol protocol, if ( app_info_flags & APPINFO_FLAG_TP_CLIENT ) asd.client.set_id(tp_app_id); - process_third_party_results(asd, tp_confidence, tp_proto_list, tp_attribute_data); + process_third_party_results(asd, tp_confidence, tp_proto_list, tp_attribute_data, + change_bits); if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) && !(asd.scan_flags & SCAN_SSL_HOST_FLAG)) @@ -776,13 +778,13 @@ bool do_tp_discovery(AppIdSession& asd, IpProtocol protocol, // Handle HTTP tunneling and SSL possibly then being used in that tunnel if (tp_app_id == APP_ID_HTTP_TUNNEL) - asd.set_payload_appid_data(APP_ID_HTTP_TUNNEL, NULL); + asd.set_payload_appid_data(APP_ID_HTTP_TUNNEL, NULL, change_bits); else if ((asd.payload.get_id() == APP_ID_HTTP_TUNNEL) && (tp_app_id == APP_ID_SSL)) - asd.set_payload_appid_data(APP_ID_HTTP_SSL_TUNNEL, NULL); + asd.set_payload_appid_data(APP_ID_HTTP_SSL_TUNNEL, NULL, change_bits); AppIdHttpSession* hsession = asd.get_http_session(); - hsession->process_http_packet(direction); + hsession->process_http_packet(direction, change_bits); // If SSL over HTTP tunnel, make sure Snort knows that it's encrypted. if (asd.payload.get_id() == APP_ID_HTTP_SSL_TUNNEL) @@ -811,7 +813,7 @@ bool do_tp_discovery(AppIdSession& asd, IpProtocol protocol, } else if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) && asd.tsession) { - asd.examine_ssl_metadata(p); + asd.examine_ssl_metadata(p, change_bits); uint16_t serverPort; AppId portAppId; serverPort = (direction == APP_ID_FROM_INITIATOR) ? p->ptrs.dp : p->ptrs.sp; diff --git a/src/network_inspectors/appid/tp_appid_utils.h b/src/network_inspectors/appid/tp_appid_utils.h index d3398f039..089ea1d74 100644 --- a/src/network_inspectors/appid/tp_appid_utils.h +++ b/src/network_inspectors/appid/tp_appid_utils.h @@ -26,6 +26,7 @@ class AppIdSession; -bool do_tp_discovery(AppIdSession&, IpProtocol, snort::Packet*, AppidSessionDirection&); +bool do_tp_discovery(AppIdSession&, IpProtocol, snort::Packet*, AppidSessionDirection&, + AppidChangeBits&); #endif diff --git a/src/pub_sub/CMakeLists.txt b/src/pub_sub/CMakeLists.txt index e3c60d48e..0d32afee1 100644 --- a/src/pub_sub/CMakeLists.txt +++ b/src/pub_sub/CMakeLists.txt @@ -1,4 +1,5 @@ set (PUB_SUB_INCLUDES + appid_events.h expect_events.h http_events.h sip_events.h diff --git a/src/pub_sub/appid_events.h b/src/pub_sub/appid_events.h new file mode 100644 index 000000000..794af103d --- /dev/null +++ b/src/pub_sub/appid_events.h @@ -0,0 +1,105 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2017-2018 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- +// appid_events.h author Masud Hasan + +#ifndef APPID_EVENTS_H +#define APPID_EVENTS_H + +// This event conveys data published by the appid module to be consumed by data bus subscribers + +#include + +#include "framework/data_bus.h" + +#define APPID_EVENT_ANY_CHANGE "appid_event_any_change" + +// Events are added as needed by subscribers +// Any change here should also change change_bits_to_string() +enum AppidChangeBit +{ + // id + APPID_SERVICE_BIT = 0, + APPID_CLIENT_BIT, + APPID_PAYLOAD_BIT, + APPID_MISC_BIT, + APPID_REFERRED_BIT, + + // http + APPID_HOST_BIT, + APPID_TLSHOST_BIT, + APPID_URL_BIT, + APPID_USERAGENT_BIT, + APPID_RESPONSE_BIT, + APPID_REFERER_BIT, + APPID_XFF_BIT, + + // other + APPID_VERSION_BIT, + + APPID_MAX_BIT +}; + +typedef std::bitset AppidChangeBits; + +inline void change_bits_to_string(AppidChangeBits& change_bits, std::string& str) +{ + size_t n = change_bits.count(); + + if (change_bits.test(APPID_SERVICE_BIT)) + --n? str.append("service, ") : str.append("service"); + if (change_bits.test(APPID_CLIENT_BIT)) + --n? str.append("client, ") : str.append("client"); + if (change_bits.test(APPID_PAYLOAD_BIT)) + --n? str.append("payload, ") : str.append("payload"); + if (change_bits.test(APPID_MISC_BIT)) + --n? str.append("misc, ") : str.append("misc"); + if (change_bits.test(APPID_REFERRED_BIT)) + --n? str.append("referred, ") : str.append("referred"); + if (change_bits.test(APPID_HOST_BIT)) + --n? str.append("host, ") : str.append("host"); + if (change_bits.test(APPID_TLSHOST_BIT)) + --n? str.append("tls-host, ") : str.append("tls-host"); + if (change_bits.test(APPID_URL_BIT)) + --n? str.append("url, ") : str.append("url"); + if (change_bits.test(APPID_USERAGENT_BIT)) + --n? str.append("user-agent, ") : str.append("user-agent"); + if (change_bits.test(APPID_RESPONSE_BIT)) + --n? str.append("response, ") : str.append("response"); + if (change_bits.test(APPID_REFERER_BIT)) + --n? str.append("referrer, ") : str.append("referrer"); + if (change_bits.test(APPID_XFF_BIT)) + --n? str.append("xff, ") : str.append("xff"); + if (change_bits.test(APPID_VERSION_BIT)) + --n? str.append("client-version, ") : str.append("client-version"); + if (n != 0) // make sure all bits from AppidChangeBit enum get translated + str.append("change_bits_to_string error!"); +} + +class AppidEvent : public snort::DataEvent +{ +public: + AppidEvent(const AppidChangeBits& ac) : ac_bits(ac) {} + + const AppidChangeBits& get_change_bitset() + { return ac_bits; } + +private: + const AppidChangeBits& ac_bits; +}; + +#endif