From: Sreeja Athirkandathil Narayanan (sathirka) Date: Wed, 9 Nov 2022 18:00:40 +0000 (+0000) Subject: Pull request #3606: appid: service, client and payload detection by lua detectors... X-Git-Tag: 3.1.47.0~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=561c02e7b9cf458538426b019e185d91f3ace256;p=thirdparty%2Fsnort3.git Pull request #3606: appid: service, client and payload detection by lua detectors and third-party when first packet re-inspection is enabled Merge in SNORT/snort3 from ~UMASHARM/snort3:navl_fix to master Squashed commit of the following: commit 94a51e06a4c12f0732d200e9f26a97e485dfe60c Author: Umang Sharma Date: Wed Sep 28 08:34:11 2022 -0400 appid: service, client and payload detection by lua detectors and third-party when first packet re-inspection is enabled --- diff --git a/src/network_inspectors/appid/appid_config.h b/src/network_inspectors/appid/appid_config.h index b61f596ce..7403db99c 100644 --- a/src/network_inspectors/appid/appid_config.h +++ b/src/network_inspectors/appid/appid_config.h @@ -115,6 +115,9 @@ public: bool ftp_userid_disabled = false; bool chp_body_collection_disabled = false; bool need_reinspection = false; + AppId first_pkt_service_id = 0; + AppId first_pkt_payload_id = 0; + AppId first_pkt_client_id = 0; uint32_t chp_body_collection_max = 0; uint32_t rtmp_max_packets = 15; uint32_t max_tp_flow_depth = 5; @@ -126,6 +129,7 @@ public: uint64_t max_bytes_before_service_fail = MIN_MAX_BYTES_BEFORE_SERVICE_FAIL; uint16_t max_packet_before_service_fail = MIN_MAX_PKTS_BEFORE_SERVICE_FAIL; uint16_t max_packet_service_fail_ignore_bytes = MIN_MAX_PKT_BEFORE_SERVICE_FAIL_IGNORE_BYTES; + FirstPktAppIdDiscovered first_pkt_appid_prefix = NO_APPID_FOUND; OdpContext(const AppIdConfig&, snort::SnortConfig*); void initialize(AppIdInspector& inspector); diff --git a/src/network_inspectors/appid/appid_discovery.cc b/src/network_inspectors/appid/appid_discovery.cc index 247a6ccf8..7b03355b3 100644 --- a/src/network_inspectors/appid/appid_discovery.cc +++ b/src/network_inspectors/appid/appid_discovery.cc @@ -567,70 +567,85 @@ bool AppIdDiscovery::detect_on_first_pkt(Packet* p, AppIdSession& asd, hv = asd.get_odp_ctxt().host_first_pkt_find(ip, port, protocol); if (hv) { - uint32_t appids_found = 0; const char *service_app_name = nullptr, *client_app_name = nullptr, *payload_app_name = nullptr; - FirstPktAppIdDiscovered appid_prefix = NO_APPID_FOUND; + asd.get_odp_ctxt().first_pkt_appid_prefix = NO_APPID_FOUND; if (hv->client_appId) { client_id = hv->client_appId; - asd.set_client_id(client_id); client_app_name = asd.get_odp_ctxt().get_app_info_mgr().get_app_name(client_id); - appids_found++; - appid_prefix = CLIENT_APPID_FOUND; + asd.get_odp_ctxt().first_pkt_client_id = client_id; + asd.get_odp_ctxt().first_pkt_appid_prefix = FIRST_CLIENT_APPID_FOUND; } if (hv->protocol_appId) { service_id = hv->protocol_appId; - asd.set_service_id(service_id, asd.get_odp_ctxt()); - asd.set_session_flags(APPID_SESSION_SERVICE_DETECTED); service_app_name = asd.get_odp_ctxt().get_app_info_mgr().get_app_name(service_id); - appids_found++; - appid_prefix = SERVICE_APPID_FOUND; + asd.get_odp_ctxt().first_pkt_service_id = service_id; + + if (asd.get_odp_ctxt().first_pkt_appid_prefix == FIRST_CLIENT_APPID_FOUND) + { + asd.get_odp_ctxt().first_pkt_appid_prefix = FIRST_SERVICE_CLIENT_APPID_FOUND; + } + else + { + asd.get_odp_ctxt().first_pkt_appid_prefix = FIRST_SERVICE_APPID_FOUND; + } } if (hv->web_appId) { payload_id = hv->web_appId; - asd.set_payload_id(payload_id); payload_app_name = asd.get_odp_ctxt().get_app_info_mgr().get_app_name(payload_id); - appids_found++; - if (appid_prefix == CLIENT_APPID_FOUND) + asd.get_odp_ctxt().first_pkt_payload_id = payload_id; + + if (asd.get_odp_ctxt().first_pkt_appid_prefix == FIRST_CLIENT_APPID_FOUND) { - appid_prefix = CLIENT_PAYLOAD_APPID_FOUND; + asd.get_odp_ctxt().first_pkt_appid_prefix = FIRST_CLIENT_PAYLOAD_APPID_FOUND; } + else if (asd.get_odp_ctxt().first_pkt_appid_prefix == FIRST_SERVICE_APPID_FOUND) + { + asd.get_odp_ctxt().first_pkt_appid_prefix = FIRST_SERVICE_PAYLOAD_APPID_FOUND; + } + else if (asd.get_odp_ctxt().first_pkt_appid_prefix == FIRST_SERVICE_CLIENT_APPID_FOUND) + { + asd.get_odp_ctxt().first_pkt_appid_prefix = FIRST_ALL_APPID_FOUND; + } else { - appid_prefix = PAYLOAD_APPID_FOUND; + asd.get_odp_ctxt().first_pkt_appid_prefix = FIRST_PAYLOAD_APPID_FOUND; } } asd.get_odp_ctxt().need_reinspection = hv->reinspect; - switch (appids_found) + switch (asd.get_odp_ctxt().first_pkt_appid_prefix) { - case FIRST_PKT_CACHE_ONE_APPID_FOUND : - if (appid_prefix == PAYLOAD_APPID_FOUND) - { - service_id = payload_id; - asd.set_service_id(service_id, asd.get_odp_ctxt()); - asd.set_session_flags(APPID_SESSION_SERVICE_DETECTED); - service_app_name = asd.get_odp_ctxt().get_app_info_mgr().get_app_name(service_id); - } - else if (appid_prefix == CLIENT_APPID_FOUND) - { - service_id = client_id; - asd.set_service_id(service_id, asd.get_odp_ctxt()); - asd.set_session_flags(APPID_SESSION_SERVICE_DETECTED); - service_app_name = asd.get_odp_ctxt().get_app_info_mgr().get_app_name(service_id); - } + case FIRST_PAYLOAD_APPID_FOUND : + service_id = payload_id; + service_app_name = asd.get_odp_ctxt().get_app_info_mgr().get_app_name(service_id); + asd.get_odp_ctxt().first_pkt_appid_prefix = FIRST_SERVICE_PAYLOAD_APPID_FOUND; + asd.get_odp_ctxt().first_pkt_service_id = service_id; break; - case FIRST_PKT_CACHE_TWO_APPIDS_FOUND : - if (appid_prefix == CLIENT_PAYLOAD_APPID_FOUND) - { - service_id = client_id; - asd.set_service_id(service_id, asd.get_odp_ctxt()); - asd.set_session_flags(APPID_SESSION_SERVICE_DETECTED); - service_app_name = asd.get_odp_ctxt().get_app_info_mgr().get_app_name(service_id); - } + + case FIRST_CLIENT_APPID_FOUND : + service_id = client_id; + service_app_name = asd.get_odp_ctxt().get_app_info_mgr().get_app_name(service_id); + asd.get_odp_ctxt().first_pkt_appid_prefix = FIRST_SERVICE_CLIENT_APPID_FOUND; + asd.get_odp_ctxt().first_pkt_service_id = service_id; + break; + + case FIRST_CLIENT_PAYLOAD_APPID_FOUND : + service_id = client_id; + service_app_name = asd.get_odp_ctxt().get_app_info_mgr().get_app_name(service_id); + asd.get_odp_ctxt().first_pkt_appid_prefix = FIRST_ALL_APPID_FOUND; + asd.get_odp_ctxt().first_pkt_service_id = service_id; + break; + + case NO_APPID_FOUND : + case FIRST_SERVICE_APPID_FOUND : + case FIRST_SERVICE_PAYLOAD_APPID_FOUND : + case FIRST_SERVICE_CLIENT_APPID_FOUND : + case FIRST_ALL_APPID_FOUND : + default: break; } asd.set_session_flags(APPID_SESSION_FIRST_PKT_CACHE_MATCHED); @@ -662,11 +677,13 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto if (asd.get_session_flags(APPID_SESSION_FIRST_PKT_CACHE_MATCHED) and !asd.get_odp_ctxt().need_reinspection) { is_discovery_done = true; + asd.set_session_flags(APPID_SESSION_SERVICE_DETECTED); + asd.client_disco_state = APPID_DISCO_STATE_FINISHED; + asd.service_disco_state = APPID_DISCO_STATE_FINISHED; service_id = asd.pick_service_app_id(); client_id = asd.pick_ss_client_app_id(); payload_id = asd.pick_ss_payload_app_id(service_id); - asd.client_disco_state = APPID_DISCO_STATE_FINISHED; - asd.service_disco_state = APPID_DISCO_STATE_FINISHED; + return is_discovery_done; } diff --git a/src/network_inspectors/appid/appid_discovery.h b/src/network_inspectors/appid/appid_discovery.h index 7bec32905..016f0eb3c 100644 --- a/src/network_inspectors/appid/appid_discovery.h +++ b/src/network_inspectors/appid/appid_discovery.h @@ -60,17 +60,17 @@ struct Packet; #define SCAN_HTTP_URI_FLAG (1<<9) #define SCAN_CERTVIZ_ENABLED_FLAG (1<<10) #define SCAN_SPOOFED_SNI_FLAG (1<<11) -#define FIRST_PKT_CACHE_ONE_APPID_FOUND 1 -#define FIRST_PKT_CACHE_TWO_APPIDS_FOUND 2 -#define FIRST_PKT_CACHE_ALL_APPIDS_FOUND 3 enum FirstPktAppIdDiscovered { NO_APPID_FOUND = 0, - CLIENT_APPID_FOUND, - SERVICE_APPID_FOUND, - PAYLOAD_APPID_FOUND, - CLIENT_PAYLOAD_APPID_FOUND + FIRST_CLIENT_APPID_FOUND, + FIRST_SERVICE_APPID_FOUND, + FIRST_PAYLOAD_APPID_FOUND, + FIRST_CLIENT_PAYLOAD_APPID_FOUND, + FIRST_SERVICE_PAYLOAD_APPID_FOUND, + FIRST_SERVICE_CLIENT_APPID_FOUND, + FIRST_ALL_APPID_FOUND }; class AppIdPatternMatchNode diff --git a/src/network_inspectors/appid/appid_session.cc b/src/network_inspectors/appid/appid_session.cc index fbe705595..4e52d897a 100644 --- a/src/network_inspectors/appid/appid_session.cc +++ b/src/network_inspectors/appid/appid_session.cc @@ -778,9 +778,13 @@ AppId AppIdSession::pick_service_app_id() const { if ((rval = api.service.get_id()) > APP_ID_NONE) return rval; + else if (odp_ctxt.first_pkt_service_id > APP_ID_NONE) + return odp_ctxt.first_pkt_service_id; else rval = APP_ID_UNKNOWN; } + else if (odp_ctxt.first_pkt_service_id > APP_ID_NONE) + return odp_ctxt.first_pkt_service_id; } else { @@ -790,6 +794,9 @@ AppId AppIdSession::pick_service_app_id() const if (api.service.get_id() > APP_ID_NONE and !deferred) return api.service.get_id(); + if (odp_ctxt.first_pkt_service_id > APP_ID_NONE) + return odp_ctxt.first_pkt_service_id; + if (is_tp_appid_available()) { if (tp_app_id > APP_ID_NONE) @@ -804,7 +811,9 @@ AppId AppIdSession::pick_service_app_id() const } else if (tp_app_id > APP_ID_NONE) return tp_app_id; - } + else if (odp_ctxt.first_pkt_service_id > APP_ID_NONE) + return odp_ctxt.first_pkt_service_id; + } if (client_inferred_service_id > APP_ID_NONE) return client_inferred_service_id; @@ -864,10 +873,29 @@ AppId AppIdSession::pick_ss_client_app_id() const return api.client.get_id(); } + if (odp_ctxt.first_pkt_client_id > APP_ID_NONE) + { + api.client.set_eve_client_app_detect_type(CLIENT_APP_DETECT_APPID); + return odp_ctxt.first_pkt_client_id; + } + api.client.set_eve_client_app_detect_type(CLIENT_APP_DETECT_APPID); return encrypted.client_id; } +AppId AppIdSession::check_first_pkt_tp_payload_app_id() const +{ + if (get_session_flags(APPID_SESSION_FIRST_PKT_CACHE_MATCHED) and + (api.payload.get_id() <= APP_ID_NONE)) + { + if ((odp_ctxt.first_pkt_payload_id > APP_ID_NONE) and (tp_payload_app_id > APP_ID_NONE)) + { + return tp_payload_app_id; + } + } + return APP_ID_NONE; +} + AppId AppIdSession::pick_ss_payload_app_id(AppId service_id) const { if (service_id == APP_ID_HTTP2 or @@ -884,15 +912,24 @@ AppId AppIdSession::pick_ss_payload_app_id(AppId service_id) const { if (tmp_id == APP_ID_HTTP_TUNNEL) { - if (api.payload.get_id() > APP_ID_NONE) + AppId first_pkt_payload_appid = check_first_pkt_tp_payload_app_id(); + if (first_pkt_payload_appid > APP_ID_NONE) + return first_pkt_payload_appid; + else if (api.payload.get_id() > APP_ID_NONE) return api.payload.get_id(); else if (tp_payload_app_id > APP_ID_NONE) return tp_payload_app_id; + else if (odp_ctxt.first_pkt_payload_id > APP_ID_NONE) + return odp_ctxt.first_pkt_payload_id; } else return tmp_id; } + AppId first_pkt_payload_appid = check_first_pkt_tp_payload_app_id(); + if (first_pkt_payload_appid > APP_ID_NONE) + return first_pkt_payload_appid; + if (api.payload.get_id() > APP_ID_NONE) return api.payload.get_id(); @@ -902,6 +939,9 @@ AppId AppIdSession::pick_ss_payload_app_id(AppId service_id) const if (encrypted.payload_id > APP_ID_NONE) return encrypted.payload_id; + if (odp_ctxt.first_pkt_payload_id > APP_ID_NONE) + return odp_ctxt.first_pkt_payload_id; + // APP_ID_UNKNOWN is valid only for HTTP type services if (tmp_id == APP_ID_UNKNOWN) return tmp_id; diff --git a/src/network_inspectors/appid/appid_session.h b/src/network_inspectors/appid/appid_session.h index 6f21da590..b873ac04a 100644 --- a/src/network_inspectors/appid/appid_session.h +++ b/src/network_inspectors/appid/appid_session.h @@ -328,6 +328,7 @@ public: AppId pick_ss_misc_app_id() const; AppId pick_ss_client_app_id() const; AppId pick_ss_payload_app_id() const; + AppId check_first_pkt_tp_payload_app_id() const; AppId pick_ss_payload_app_id(AppId service_id) const; AppId pick_ss_referred_payload_app_id() const; diff --git a/src/network_inspectors/appid/service_plugins/service_discovery.cc b/src/network_inspectors/appid/service_plugins/service_discovery.cc index e3e270077..31d3c3477 100644 --- a/src/network_inspectors/appid/service_plugins/service_discovery.cc +++ b/src/network_inspectors/appid/service_plugins/service_discovery.cc @@ -788,7 +788,7 @@ int ServiceDiscovery::fail_service(AppIdSession& asd, const Packet* pkt, AppidSe /* If we're still working on a port/pattern list of detectors, then ignore * individual fails until we're done looking at everything. */ - if ( !asd.service_detector && !asd.service_candidates.empty() ) + if ((asd.get_odp_ctxt().first_pkt_service_id > APP_ID_NONE) or (!asd.service_detector && !asd.service_candidates.empty())) return APPID_SUCCESS; asd.set_service_id(APP_ID_NONE, asd.get_odp_ctxt());