From: Shravan Rangarajuvenkata (shrarang) Date: Mon, 20 Apr 2020 01:28:21 +0000 (+0000) Subject: Merge pull request #2133 in SNORT/snort3 from ~CLJUDGE/snort3:mark_service_unknown_if... X-Git-Tag: 3.0.1-2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1f1e90c85e5d5d4e05cd00df3f10f369f177fd12;p=thirdparty%2Fsnort3.git Merge pull request #2133 in SNORT/snort3 from ~CLJUDGE/snort3:mark_service_unknown_if_only_client_sends_data to master Squashed commit of the following: commit d28c407da03e2a6e9ad3d6becddae6cbf3140d00 Author: Cliff Judge Date: Tue Apr 14 22:58:44 2020 -0400 appid: setting up packet counters to make sure flows with one-way data don't pend forever --- diff --git a/src/network_inspectors/appid/app_info_table.cc b/src/network_inspectors/appid/app_info_table.cc index 75b21b54f..d07c95d17 100644 --- a/src/network_inspectors/appid/app_info_table.cc +++ b/src/network_inspectors/appid/app_info_table.cc @@ -58,17 +58,17 @@ AppInfoTableEntry::AppInfoTableEntry(AppId id, char* name) app_name_key = AppInfoManager::strdup_to_lower(name); } -AppInfoTableEntry::AppInfoTableEntry(AppId id, char* name, AppId sid, AppId cid, AppId pid) - : appId(id), serviceId(sid), clientId(cid), payloadId(pid), app_name(name) +AppInfoTableEntry::AppInfoTableEntry(AppId id, char* name, AppId sid, AppId cid, AppId pid) : + appId(id), serviceId(sid), clientId(cid), payloadId(pid), app_name(name) { app_name_key = AppInfoManager::strdup_to_lower(name); } AppInfoTableEntry::~AppInfoTableEntry() { - if ( app_name ) + if (app_name) snort_free(app_name); - if ( app_name_key ) + if (app_name_key) snort_free(app_name_key); } @@ -87,27 +87,26 @@ AppInfoTableEntry* AppInfoManager::find_app_info_by_name(const char* app_name) const char* search_name = AppInfoManager::strdup_to_lower(app_name); app = app_info_name_table.find(search_name); - if ( app != app_info_name_table.end() ) + if (app != app_info_name_table.end()) entry = app->second; snort_free((void*)search_name); return entry; } -bool AppInfoManager::add_entry_to_app_info_name_table(const char* app_name, AppInfoTableEntry* entry) +bool AppInfoManager::add_entry_to_app_info_name_table(const char* app_name, + AppInfoTableEntry* entry) { bool added = true; - if ( !is_existing_entry(entry) ) + if (!is_existing_entry(entry)) app_info_name_table[app_name] = entry; else { - WarningMessage( - "App name, \"%s\"is a duplicate entry will be shared by each detector.\n", + WarningMessage("App name, \"%s\" is a duplicate entry will be shared by each detector.\n", app_name); added = false; } - return added; } @@ -115,8 +114,8 @@ AppId AppInfoManager::get_static_app_info_entry(AppId appid) { if (appid > 0 && appid < SF_APPID_BUILDIN_MAX) return appid; - if ( ( appid >= SF_APPID_CSD_MIN ) && - appid < ( SF_APPID_CSD_MIN + ( SF_APPID_MAX - SF_APPID_BUILDIN_MAX ) ) ) + if ((appid >= SF_APPID_CSD_MIN) && + appid < (SF_APPID_CSD_MIN + (SF_APPID_MAX - SF_APPID_BUILDIN_MAX))) return (SF_APPID_BUILDIN_MAX + appid - SF_APPID_CSD_MIN); return 0; } @@ -131,7 +130,6 @@ char* AppInfoManager::strdup_to_lower(const char* source) *lcd = tolower(*lcd); lcd++; } - return dest; } @@ -140,8 +138,8 @@ bool AppInfoManager::configured() return !app_info_table.empty(); } -AppInfoTableEntry* AppInfoManager::get_app_info_entry(AppId appId, const - AppInfoTable& lookup_table) +AppInfoTableEntry* AppInfoManager::get_app_info_entry(AppId appId, + const AppInfoTable& lookup_table) { AppId tmp; AppInfoTable::const_iterator app; @@ -150,16 +148,15 @@ AppInfoTableEntry* AppInfoManager::get_app_info_entry(AppId appId, const if ((tmp = get_static_app_info_entry(appId))) { app = lookup_table.find(tmp); - if ( app != lookup_table.end() ) + if (app != lookup_table.end()) entry = app->second; } else { app = custom_app_info_table.find(appId); - if ( app != custom_app_info_table.end() ) + if (app != custom_app_info_table.end()) entry = app->second; } - return entry; } @@ -182,13 +179,12 @@ AppInfoTableEntry* AppInfoManager::add_dynamic_app_entry(const char* app_name) entry = new AppInfoTableEntry(next_custom_appid++, snort_strdup(app_name)); custom_app_info_table[entry->appId] = entry; - if ( !add_entry_to_app_info_name_table(entry->app_name_key, entry) ) + if (!add_entry_to_app_info_name_table(entry->app_name_key, entry)) { delete entry; return nullptr; } } - return entry; } @@ -325,16 +321,22 @@ void AppInfoManager::load_odp_config(OdpContext& odp_ctxt, const char* path) else if (!(strcasecmp(conf_key, "host_port_app_cache_lookup_interval"))) { int host_port_app_cache_lookup_interval = atoi(conf_val); - if (host_port_app_cache_lookup_interval < MIN_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL - || host_port_app_cache_lookup_interval > MAX_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL ) + if (host_port_app_cache_lookup_interval < + MIN_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL || + host_port_app_cache_lookup_interval > + MAX_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL) { - ParseWarning(WARN_CONF, - "AppId: invalid host_port_app_cache_lookup_interval %d, must be between %d and %d\n.", - host_port_app_cache_lookup_interval, MIN_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL , MAX_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL); + ParseWarning(WARN_CONF, + "AppId: invalid host_port_app_cache_lookup_interval %d, " + "must be between %d and %d\n.", + host_port_app_cache_lookup_interval, + MIN_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL, + MAX_HOST_PORT_APP_CACHE_LOOKUP_INTERVAL); } else { - odp_ctxt.host_port_app_cache_lookup_interval = host_port_app_cache_lookup_interval; + odp_ctxt.host_port_app_cache_lookup_interval = + host_port_app_cache_lookup_interval; } } else if (!(strcasecmp(conf_key, "host_port_app_cache_lookup_range"))) @@ -344,12 +346,14 @@ void AppInfoManager::load_odp_config(OdpContext& odp_ctxt, const char* path) || host_port_app_cache_lookup_range > MAX_HOST_PORT_APP_CACHE_LOOKUP_RANGE) { ParseWarning(WARN_CONF, - "AppId: invalid host_port_app_cache_lookup_range %d, must be between %d and %d\n.", - host_port_app_cache_lookup_range , MIN_HOST_PORT_APP_CACHE_LOOKUP_RANGE, MAX_HOST_PORT_APP_CACHE_LOOKUP_RANGE); + "AppId: invalid host_port_app_cache_lookup_range %d, " + "must be between %d and %d\n.", host_port_app_cache_lookup_range, + MIN_HOST_PORT_APP_CACHE_LOOKUP_RANGE, + MAX_HOST_PORT_APP_CACHE_LOOKUP_RANGE); } else { - odp_ctxt.host_port_app_cache_lookup_range = host_port_app_cache_lookup_range; + odp_ctxt.host_port_app_cache_lookup_range = host_port_app_cache_lookup_range; } } else if (!(strcasecmp(conf_key, "is_host_port_app_cache_runtime"))) @@ -398,7 +402,8 @@ void AppInfoManager::load_odp_config(OdpContext& odp_ctxt, const char* path) set_app_info_flags(APP_ID_BITTORRENT, APPINFO_FLAG_DEFER); set_app_info_flags(APP_ID_BITTORRENT, APPINFO_FLAG_DEFER_PAYLOAD); odp_ctxt.max_tp_flow_depth = 25; - LogMessage("AppId: host_port_app_cache_lookup_interval %d\n", odp_ctxt.host_port_app_cache_lookup_interval); + LogMessage("AppId: host_port_app_cache_lookup_interval %d\n", + odp_ctxt.host_port_app_cache_lookup_interval); LogMessage("AppId: recheck_for_portservice_appid enabled\n"); LogMessage("AppId: defer_to_thirdparty %d\n", APP_ID_BITTORRENT); LogMessage("AppId: defer_payload_to_thirdparty %d\n", APP_ID_BITTORRENT); @@ -503,6 +508,51 @@ void AppInfoManager::load_odp_config(OdpContext& odp_ctxt, const char* path) continue; } } + else if (!(strcasecmp(conf_key, "max_bytes_before_service_fail"))) + { + uint64_t max_bytes_before_service_fail = atoi(conf_val); + if (max_bytes_before_service_fail < MIN_MAX_BYTES_BEFORE_SERVICE_FAIL) + { + ParseWarning(WARN_CONF, "AppId: invalid max_bytes_before_service_fail " + "%" PRIu64 " must be greater than %u.\n", max_bytes_before_service_fail, + MIN_MAX_BYTES_BEFORE_SERVICE_FAIL); + } + else + { + odp_ctxt.max_bytes_before_service_fail = max_bytes_before_service_fail; + } + } + else if (!(strcasecmp(conf_key, "max_packet_before_service_fail"))) + { + uint16_t max_packet_before_service_fail = atoi(conf_val); + if (max_packet_before_service_fail < MIN_MAX_PKTS_BEFORE_SERVICE_FAIL) + { + ParseWarning(WARN_CONF, "AppId: invalid max_packet_before_service_fail " + "%" PRIu16 ", must be greater than %u.\n", max_packet_before_service_fail, + MIN_MAX_PKTS_BEFORE_SERVICE_FAIL); + } + else + { + odp_ctxt.max_packet_before_service_fail = max_packet_before_service_fail; + } + } + else if (!(strcasecmp(conf_key, "max_packet_service_fail_ignore_bytes"))) + { + uint16_t max_packet_service_fail_ignore_bytes = atoi(conf_val); + if (max_packet_service_fail_ignore_bytes < + MIN_MAX_PKT_BEFORE_SERVICE_FAIL_IGNORE_BYTES) + { + ParseWarning(WARN_CONF, "AppId: invalid max_packet_service_fail_ignore_bytes" + "%" PRIu16 ", must be greater than %u.\n", + max_packet_service_fail_ignore_bytes, + MIN_MAX_PKT_BEFORE_SERVICE_FAIL_IGNORE_BYTES); + } + else + { + odp_ctxt.max_packet_service_fail_ignore_bytes = + max_packet_service_fail_ignore_bytes; + } + } /* App Priority bit set*/ else if (!(strcasecmp(conf_key, "app_priority"))) { @@ -602,7 +652,7 @@ SnortProtocolId AppInfoManager::add_appid_protocol_reference(const char* protoco void AppInfoManager::init_appid_info_table(AppIdConfig& config, SnortConfig* sc, OdpContext& odp_ctxt) { - if ( !config.app_detector_dir ) + if (!config.app_detector_dir) { return; // no lua detectors, no rule support, already warned } @@ -613,7 +663,7 @@ void AppInfoManager::init_appid_info_table(AppIdConfig& config, FILE* tableFile = fopen(filepath, "r"); - if ( !tableFile ) + if (!tableFile) { ParseError("appid: could not open %s", filepath); } @@ -694,7 +744,7 @@ void AppInfoManager::init_appid_info_table(AppIdConfig& config, if ((app_id = get_static_app_info_entry(entry->payloadId))) app_info_payload_table[app_id] = entry; - if ( !add_entry_to_app_info_name_table(entry->app_name_key, entry) ) + if (!add_entry_to_app_info_name_table(entry->app_name_key, entry)) delete entry; } fclose(tableFile); diff --git a/src/network_inspectors/appid/appid_config.h b/src/network_inspectors/appid/appid_config.h index 7bce597b0..7f39f9a4f 100644 --- a/src/network_inspectors/appid/appid_config.h +++ b/src/network_inspectors/appid/appid_config.h @@ -40,6 +40,13 @@ #define APP_ID_PORT_ARRAY_SIZE 65536 +#define MIN_MAX_BYTES_BEFORE_SERVICE_FAIL 4096 +#define MIN_MAX_PKTS_BEFORE_SERVICE_FAIL 5 +#define MIN_MAX_PKT_BEFORE_SERVICE_FAIL_IGNORE_BYTES 15 + +extern SnortProtocolId snortId_for_unsynchronized; +extern SnortProtocolId snortId_for_ftp_data; +extern SnortProtocolId snortId_for_http2; class PatternClientDetector; class PatternServiceDetector; @@ -96,6 +103,9 @@ public: bool http_response_version_enabled = false; bool allow_port_wildcard_host_cache = false; bool recheck_for_portservice_appid = false; + 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; OdpContext(AppIdConfig&, snort::SnortConfig*); void initialize(); @@ -120,7 +130,8 @@ public: return host_port_cache.find(ip, port, proto, *this); } - bool host_port_cache_add(const snort::SfIp* ip, uint16_t port, IpProtocol proto, unsigned type, AppId appid) + bool host_port_cache_add(const snort::SfIp* ip, uint16_t port, IpProtocol proto, unsigned type, + AppId appid) { return host_port_cache.add(ip, port, proto, type, appid); } diff --git a/src/network_inspectors/appid/appid_discovery.cc b/src/network_inspectors/appid/appid_discovery.cc index e9fe0f34a..36378e902 100644 --- a/src/network_inspectors/appid/appid_discovery.cc +++ b/src/network_inspectors/appid/appid_discovery.cc @@ -57,7 +57,7 @@ AppIdDiscovery::AppIdDiscovery() AppIdDiscovery::~AppIdDiscovery() { - for (auto pd : pattern_data ) + for (auto pd : pattern_data) delete pd; pattern_data.clear(); @@ -65,10 +65,10 @@ AppIdDiscovery::~AppIdDiscovery() delete tcp_patterns; delete udp_patterns; - for ( auto kv : tcp_detectors ) + for (auto kv : tcp_detectors) delete kv.second; - for ( auto kv : udp_detectors ) + for (auto kv : udp_detectors) delete kv.second; } @@ -76,13 +76,13 @@ void AppIdDiscovery::tterm() { } -void AppIdDiscovery::register_detector(const std::string& name, AppIdDetector* cd, IpProtocol proto) +void AppIdDiscovery::register_detector(const std::string& name, AppIdDetector* cd, IpProtocol proto) { // FIXIT-L - check for dup name? - if ( proto == IpProtocol::TCP ) - tcp_detectors[ name ] = cd; - else if ( proto == IpProtocol::UDP ) - udp_detectors[ name ] = cd; + if (proto == IpProtocol::TCP) + tcp_detectors[name] = cd; + else if (proto == IpProtocol::UDP) + udp_detectors[name] = cd; else ErrorMessage("Detector %s has unsupported protocol %u", name.c_str(), (unsigned)proto); } @@ -122,7 +122,7 @@ void AppIdDiscovery::do_application_discovery(Packet* p, AppIdInspector& inspect AppidSessionDirection direction = APP_ID_FROM_INITIATOR; AppIdSession* asd = (AppIdSession*)p->flow->get_flow_data(AppIdSession::inspector_id); - if ( !do_pre_discovery(p, &asd, inspector, protocol, outer_protocol, direction) ) + if (!do_pre_discovery(p, &asd, inspector, protocol, outer_protocol, direction)) return; AppId service_id = APP_ID_NONE; @@ -179,7 +179,7 @@ static inline unsigned get_ipfuncs_flags(const Packet* p, bool dst) static inline bool is_special_session_monitored(const Packet* p) { - if ( p->is_ip4() ) + if (p->is_ip4()) { if (p->is_udp() && ((p->ptrs.sp == 68 && p->ptrs.dp == 67) || (p->ptrs.sp == 67 && p->ptrs.dp == 68))) @@ -247,7 +247,7 @@ static bool set_network_attributes(AppIdSession* asd, Packet* p, IpProtocol& pro static bool is_packet_ignored(Packet* p) { - if ( p->is_rebuilt() and !p->flow->is_proxied()) + if (p->is_rebuilt() and !p->flow->is_proxied()) { appid_stats.ignored_packets++; return true; @@ -256,7 +256,8 @@ static bool is_packet_ignored(Packet* p) return false; } -static uint64_t is_session_monitored(const AppIdSession& asd, const Packet* p, AppidSessionDirection dir) +static uint64_t is_session_monitored(const AppIdSession& asd, const Packet* p, + AppidSessionDirection dir) { uint64_t flags; uint64_t flow_flags = APPID_SESSION_DISCOVER_APP; @@ -455,26 +456,26 @@ bool AppIdDiscovery::do_pre_discovery(Packet* p, AppIdSession** p_asd, AppIdInsp { AppIdSession* asd = *p_asd; - if ( !set_network_attributes(asd, p, protocol, outer_protocol, direction) ) + if (!set_network_attributes(asd, p, protocol, outer_protocol, direction)) { appid_stats.ignored_packets++; return false; } - if ( appidDebug->is_enabled() ) + if (appidDebug->is_enabled()) appidDebug->activate(p->flow, asd, inspector.get_ctxt().config.log_all_sessions); - if ( is_packet_ignored(p) ) + if (is_packet_ignored(p)) return false; uint64_t flow_flags; - if ( handle_unmonitored_session(asd, p, protocol, direction, inspector, flow_flags) ) + if (handle_unmonitored_session(asd, p, protocol, direction, inspector, flow_flags)) return false; // FIXIT-M - Potential memory leak for TMP sessions. handle_unmonitored_session() already // TMP session and that is not being freed before creating the new one below - if ( !asd || asd->common.flow_type == APPID_FLOW_TYPE_TMP ) + if (!asd || asd->common.flow_type == APPID_FLOW_TYPE_TMP) { *p_asd = asd = AppIdSession::allocate_session(p, protocol, direction, &inspector); if (p->flow->get_session_flags() & SSNFLAG_MIDSTREAM) @@ -494,9 +495,23 @@ bool AppIdDiscovery::do_pre_discovery(Packet* p, AppIdSession** p_asd, AppIdInsp asd->session_packet_count++; if (direction == APP_ID_FROM_INITIATOR) + { asd->stats.initiator_bytes += p->pkth->pktlen; + if (p->dsize) + { + asd->init_pkts_without_reply++; + asd->init_bytes_without_reply += p->dsize; + } + } else + { asd->stats.responder_bytes += p->pkth->pktlen; + if (p->dsize) + { + asd->init_pkts_without_reply = 0; + asd->init_bytes_without_reply = 0; + } + } asd->common.flags = flow_flags; if (!asd->get_session_flags(APPID_SESSION_PAYLOAD_SEEN) and p->dsize) @@ -512,15 +527,16 @@ bool AppIdDiscovery::do_pre_discovery(Packet* p, AppIdSession** p_asd, AppIdInsp publish_appid_event(change_bits, p->flow); asd->set_session_flags(APPID_SESSION_IGNORE_FLOW_IDED); } - if (appidDebug->is_active() && !asd->get_session_flags(APPID_SESSION_IGNORE_FLOW_LOGGED)) { asd->set_session_flags(APPID_SESSION_IGNORE_FLOW_LOGGED); - const char *app_name = asd->ctxt.get_odp_ctxt().get_app_info_mgr().get_app_name(asd->service.get_id()); + const char *app_name = + asd->ctxt.get_odp_ctxt().get_app_info_mgr().get_app_name(asd->service.get_id()); LogMessage("AppIdDbg %s Ignoring connection with service %s (%d)\n", - appidDebug->get_debug_session(), app_name ? app_name : "unknown", asd->service.get_id()); + appidDebug->get_debug_session(), app_name ? app_name : "unknown", + asd->service.get_id()); } return false; @@ -555,7 +571,7 @@ bool AppIdDiscovery::do_pre_discovery(Packet* p, AppIdSession** p_asd, AppIdInsp else { const auto* tcph = p->ptrs.tcph; - if ( tcph->is_rst() && asd->previous_tcp_flags == TH_SYN ) + if (tcph->is_rst() && asd->previous_tcp_flags == TH_SYN) { uint16_t port = 0; const SfIp* ip = nullptr; @@ -571,10 +587,8 @@ bool AppIdDiscovery::do_pre_discovery(Packet* p, AppIdSession** p_asd, AppIdInsp ip = p->ptrs.ip_api.get_src(); port = p->ptrs.sp; } - AppIdServiceState::check_reset(*asd, ip, port); } - asd->previous_tcp_flags = p->ptrs.tcph->th_flags; } } @@ -622,8 +636,8 @@ void AppIdDiscovery::do_port_based_discovery(Packet* p, AppIdSession& asd, IpPro asd.service.set_port_service_id(id); if (appidDebug->is_active()) { - const char *app_name = - asd.ctxt.get_odp_ctxt().get_app_info_mgr().get_app_name(asd.service.get_port_service_id()); + AppId ps_id = asd.service.get_port_service_id(); + const char *app_name = asd.ctxt.get_odp_ctxt().get_app_info_mgr().get_app_name(ps_id); LogMessage("AppIdDbg %s Port service %s (%d) from port\n", appidDebug->get_debug_session(), app_name ? app_name : "unknown", asd.service.get_port_service_id()); @@ -644,9 +658,11 @@ bool AppIdDiscovery::do_host_port_based_discovery(Packet* p, AppIdSession& asd, if (!(asd.scan_flags & SCAN_HOST_PORT_FLAG)) check_static = true; - if ((asd.session_packet_count % asd.ctxt.get_odp_ctxt().host_port_app_cache_lookup_interval == 0) and - (asd.session_packet_count <= asd.ctxt.get_odp_ctxt().host_port_app_cache_lookup_range) and - asd.ctxt.get_odp_ctxt().is_host_port_app_cache_runtime ) + if ((asd.session_packet_count % + asd.ctxt.get_odp_ctxt().host_port_app_cache_lookup_interval == 0) and + (asd.session_packet_count <= + asd.ctxt.get_odp_ctxt().host_port_app_cache_lookup_range) and + asd.ctxt.get_odp_ctxt().is_host_port_app_cache_runtime) check_dynamic = true; if (!(check_static || check_dynamic)) @@ -657,7 +673,7 @@ bool AppIdDiscovery::do_host_port_based_discovery(Packet* p, AppIdSession& asd, AppIdHttpSession* hsession = asd.get_http_session(); const TunnelDest* tun_dest = hsession->get_tun_dest(); - if(tun_dest) + if (tun_dest) { ip = &(tun_dest->ip); port = tun_dest->port; @@ -714,7 +730,8 @@ bool AppIdDiscovery::do_host_port_based_discovery(Packet* p, AppIdSession& asd, auto ht = host_cache.find(*ip); if (ht) { - AppId appid = ht->get_appid(port, protocol, true, asd.ctxt.get_odp_ctxt().allow_port_wildcard_host_cache); + AppId appid = ht->get_appid(port, protocol, true, + asd.ctxt.get_odp_ctxt().allow_port_wildcard_host_cache); if (appid > APP_ID_NONE) { // FIXIT-L: Make this more generic to support service and payload IDs @@ -723,20 +740,23 @@ bool AppIdDiscovery::do_host_port_based_discovery(Packet* p, AppIdSession& asd, asd.set_session_flags(APPID_SESSION_HOST_CACHE_MATCHED); } } - return true; } - return false; } -static inline bool is_check_host_cache_valid(AppIdSession& asd, AppId service_id, AppId client_id, AppId payload_id, AppId misc_id) +static inline bool is_check_host_cache_valid(AppIdSession& asd, AppId service_id, AppId client_id, + AppId payload_id, AppId misc_id) { - bool is_payload_client_misc_none = (payload_id <= APP_ID_NONE and client_id <= APP_ID_NONE and misc_id <= APP_ID_NONE); - bool is_appid_none = is_payload_client_misc_none and (service_id <= APP_ID_NONE or service_id == APP_ID_UNKNOWN_UI or - (asd.ctxt.get_odp_ctxt().recheck_for_portservice_appid and service_id == asd.service.get_port_service_id())); - bool is_ssl_none = asd.ctxt.get_odp_ctxt().check_host_cache_unknown_ssl and asd.get_session_flags(APPID_SESSION_SSL_SESSION) and - (not(asd.tsession and asd.tsession->get_tls_host() and asd.tsession->get_tls_cname())); + bool is_payload_client_misc_none = (payload_id <= APP_ID_NONE and client_id <= APP_ID_NONE and + misc_id <= APP_ID_NONE); + bool is_appid_none = is_payload_client_misc_none and (service_id <= APP_ID_NONE or + service_id == APP_ID_UNKNOWN_UI or + (asd.ctxt.get_odp_ctxt().recheck_for_portservice_appid and + service_id == asd.service.get_port_service_id())); + bool is_ssl_none = asd.ctxt.get_odp_ctxt().check_host_cache_unknown_ssl and + asd.get_session_flags(APPID_SESSION_SSL_SESSION) and + (not(asd.tsession and asd.tsession->get_tls_host() and asd.tsession->get_tls_cname())); if (is_appid_none or is_ssl_none or asd.ctxt.get_odp_ctxt().check_host_port_app_cache) return true; return false; @@ -759,10 +779,11 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto asd.misc_app_id = misc_id = id; if (appidDebug->is_active()) { - const char *app_name = asd.ctxt.get_odp_ctxt().get_app_info_mgr(). - get_app_name(asd.misc_app_id); + const char *app_name = + asd.ctxt.get_odp_ctxt().get_app_info_mgr().get_app_name(asd.misc_app_id); LogMessage("AppIdDbg %s Outer protocol service %s (%d)\n", - appidDebug->get_debug_session(), app_name ? app_name : "unknown", asd.misc_app_id); + appidDebug->get_debug_session(), app_name ? app_name : "unknown", + asd.misc_app_id); } } } @@ -779,17 +800,19 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto asd.service_disco_state = APPID_DISCO_STATE_FINISHED; if (appidDebug->is_active()) { - const char *app_name = asd.ctxt.get_odp_ctxt().get_app_info_mgr().get_app_name(asd.service.get_port_service_id()); + AppId ps_id = asd.service.get_port_service_id(); + const char *app_name = + asd.ctxt.get_odp_ctxt().get_app_info_mgr().get_app_name(ps_id); LogMessage("AppIdDbg %s Protocol service %s (%d) from protocol\n", - appidDebug->get_debug_session(), app_name ? app_name : "unknown", asd.service.get_port_service_id()); + appidDebug->get_debug_session(), app_name ? app_name : "unknown", ps_id); } } asd.set_session_flags(APPID_SESSION_PORT_SERVICE_DONE); } else { - service_id = asd.pick_service_app_id(); - misc_id = asd.pick_misc_app_id(); + service_id = asd.pick_service_app_id(); + misc_id = asd.pick_misc_app_id(); } return true; } @@ -818,7 +841,8 @@ 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)) { - asd.ctxt.get_odp_ctxt().get_service_disco_mgr().identify_service(asd, p, direction, change_bits); + asd.ctxt.get_odp_ctxt().get_service_disco_mgr().identify_service(asd, p, direction, + change_bits); if (asd.get_session_flags(APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_CONTINUE) == APPID_SESSION_SERVICE_DETECTED) @@ -832,20 +856,22 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto else if (protocol != IpProtocol::TCP || (p->packet_flags & PKT_STREAM_ORDER_OK)) { if (asd.service_disco_state != APPID_DISCO_STATE_FINISHED) - is_discovery_done = asd.ctxt.get_odp_ctxt().get_service_disco_mgr().do_service_discovery( - asd, p, direction, change_bits); + is_discovery_done = + asd.ctxt.get_odp_ctxt().get_service_disco_mgr().do_service_discovery(asd, p, + direction, change_bits); if (asd.client_disco_state != APPID_DISCO_STATE_FINISHED) - is_discovery_done = asd.ctxt.get_odp_ctxt().get_client_disco_mgr().do_client_discovery( - asd, p, direction, change_bits); + is_discovery_done = + asd.ctxt.get_odp_ctxt().get_client_disco_mgr().do_client_discovery(asd, p, + direction, change_bits); asd.set_session_flags(APPID_SESSION_ADDITIONAL_PACKET); } service_id = asd.pick_service_app_id(); // Length-based service detection if no service is found yet - if ( (service_id <= APP_ID_NONE or service_id == APP_ID_UNKNOWN_UI) and (p->dsize > 0) and + if ((service_id <= APP_ID_NONE or service_id == APP_ID_UNKNOWN_UI) and (p->dsize > 0) and (asd.length_sequence.sequence_cnt < LENGTH_SEQUENCE_CNT_MAX) and - !asd.get_session_flags(APPID_SESSION_OOO) ) + !asd.get_session_flags(APPID_SESSION_OOO)) { uint8_t index = asd.length_sequence.sequence_cnt; asd.length_sequence.proto = protocol; @@ -871,15 +897,18 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto client_id = asd.pick_client_app_id(); misc_id = asd.pick_misc_app_id(); - bool is_http_tunnel = ((asd.payload.get_id() == APP_ID_HTTP_TUNNEL) || (asd.payload.get_id() == APP_ID_HTTP_SSL_TUNNEL)) ? true:false; - if (is_check_host_cache_valid(asd, service_id, client_id, payload_id, misc_id) or (is_http_tunnel)) + bool is_http_tunnel = ((asd.payload.get_id() == APP_ID_HTTP_TUNNEL) || + (asd.payload.get_id() == APP_ID_HTTP_SSL_TUNNEL)) ? true:false; + + if (is_check_host_cache_valid(asd, service_id, client_id, payload_id, misc_id) or + (is_http_tunnel)) { - if(is_http_tunnel) + if (is_http_tunnel) { AppIdHttpSession* hsession = asd.get_http_session(); - if(hsession and (asd.scan_flags & SCAN_HTTP_URI_FLAG)) + if (hsession and (asd.scan_flags & SCAN_HTTP_URI_FLAG)) { - if(hsession->get_tun_dest()) + if (hsession->get_tun_dest()) hsession->free_tun_dest(); hsession->set_tun_dest(); asd.scan_flags &= ~SCAN_HTTP_URI_FLAG; @@ -912,16 +941,16 @@ void AppIdDiscovery::do_post_discovery(Packet* p, AppIdSession& asd, asd.set_session_flags(APPID_SESSION_CONTINUE); } - if ( service_id != APP_ID_NONE ) + if (service_id != APP_ID_NONE) { - if ( payload_id != asd.past_indicator and payload_id != APP_ID_NONE) + if (payload_id != asd.past_indicator and payload_id != APP_ID_NONE) { asd.past_indicator = payload_id; check_session_for_AF_indicator(p, direction, (AppId)payload_id); } - if ( asd.past_forecast != service_id and asd.past_forecast != APP_ID_UNKNOWN and - asd.payload.get_id() == APP_ID_NONE ) + if (asd.past_forecast != service_id and asd.past_forecast != APP_ID_UNKNOWN and + asd.payload.get_id() == APP_ID_NONE) { asd.past_forecast = check_session_for_AF_forecast(asd, p, direction, service_id); if (asd.past_forecast != APP_ID_UNKNOWN) diff --git a/src/network_inspectors/appid/appid_session.cc b/src/network_inspectors/appid/appid_session.cc index be44b8d22..29d7c7e8d 100644 --- a/src/network_inspectors/appid/appid_session.cc +++ b/src/network_inspectors/appid/appid_session.cc @@ -298,7 +298,8 @@ void AppIdSession::sync_with_snort_protocol_id(AppId newAppId, Packet* p) break; } - AppInfoTableEntry* entry = ctxt.get_odp_ctxt().get_app_info_mgr().get_app_info_entry(newAppId); + AppInfoTableEntry* entry = + ctxt.get_odp_ctxt().get_app_info_mgr().get_app_info_entry(newAppId); if (entry) { SnortProtocolId tmp_snort_protocol_id = entry->snort_protocol_id; @@ -345,7 +346,8 @@ void AppIdSession::check_app_detection_restart(AppidChangeBits& change_bits) encrypted.referred_id = pick_referred_payload_app_id(); reinit_session_data(change_bits); if (appidDebug->is_active()) - LogMessage("AppIdDbg %s SSL decryption is available, restarting app detection\n", appidDebug->get_debug_session()); + LogMessage("AppIdDbg %s SSL decryption is available, restarting app detection\n", + appidDebug->get_debug_session()); // APPID_SESSION_ENCRYPTED is set upon receiving a command which upgrades the session to // SSL. Next packet after the command will have encrypted traffic. In the case of a @@ -415,8 +417,9 @@ void AppIdSession::examine_ssl_metadata(Packet* p, AppidChangeBits& change_bits) if ((scan_flags & SCAN_SSL_HOST_FLAG) and tls_str) { size_t size = strlen(tls_str); - if ((ret = ctxt.get_odp_ctxt().get_ssl_matchers().scan_hostname((const uint8_t*)tls_str, size, - client_id, payload_id))) + if ((ret = + ctxt.get_odp_ctxt().get_ssl_matchers().scan_hostname((const uint8_t*)tls_str, size, + client_id, payload_id))) { if (client.get_id() == APP_ID_NONE or client.get_id() == APP_ID_SSL_CLIENT) set_client_appid_data(client_id, change_bits); @@ -429,7 +432,7 @@ void AppIdSession::examine_ssl_metadata(Packet* p, AppidChangeBits& change_bits) { size_t size = strlen(tls_str); if ((ret = ctxt.get_odp_ctxt().get_ssl_matchers().scan_cname((const uint8_t*)tls_str, size, - client_id, payload_id))) + client_id, payload_id))) { if (client.get_id() == APP_ID_NONE or client.get_id() == APP_ID_SSL_CLIENT) set_client_appid_data(client_id, change_bits); @@ -442,7 +445,7 @@ void AppIdSession::examine_ssl_metadata(Packet* p, AppidChangeBits& change_bits) { size_t size = strlen(tls_str); if ((ret = ctxt.get_odp_ctxt().get_ssl_matchers().scan_cname((const uint8_t*)tls_str, size, - client_id, payload_id))) + client_id, payload_id))) { set_client_appid_data(client_id, change_bits); set_payload_appid_data(payload_id, change_bits); @@ -454,7 +457,8 @@ void AppIdSession::examine_ssl_metadata(Packet* p, AppidChangeBits& change_bits) payload.get_id() == APP_ID_NONE) { if (appidDebug->is_active()) - LogMessage("AppIdDbg %s End of SSL/TLS handshake detected with no payloadAppId, so setting to unknown\n", appidDebug->get_debug_session()); + LogMessage("AppIdDbg %s End of SSL/TLS handshake detected with no payloadAppId, " + "so setting to unknown\n", appidDebug->get_debug_session()); payload.set_id(APP_ID_UNKNOWN); } } @@ -503,12 +507,11 @@ void AppIdSession::set_client_appid_data(AppId id, AppidChangeBits& change_bits, if (id != cur_id) { if (cur_id) - if (ctxt.get_odp_ctxt().get_app_info_mgr().get_priority(cur_id) > ctxt.get_odp_ctxt().get_app_info_mgr().get_priority(id)) + if (ctxt.get_odp_ctxt().get_app_info_mgr().get_priority(cur_id) > + ctxt.get_odp_ctxt().get_app_info_mgr().get_priority(id)) return; - client.set_id(id); } - client.set_version(version, change_bits); } @@ -529,7 +532,8 @@ void AppIdSession::set_payload_appid_data(AppId id, AppidChangeBits& change_bits if (id <= APP_ID_NONE) return; - if (ctxt.get_odp_ctxt().get_app_info_mgr().get_priority(payload.get_id()) > ctxt.get_odp_ctxt().get_app_info_mgr().get_priority(id)) + if (ctxt.get_odp_ctxt().get_app_info_mgr().get_priority(payload.get_id()) > + ctxt.get_odp_ctxt().get_app_info_mgr().get_priority(id)) return; payload.set_id(id); payload.set_version(version, change_bits); @@ -551,6 +555,13 @@ void AppIdSession::set_service_appid_data(AppId id, AppidChangeBits& change_bits service.update(id, change_bits, version); } +bool AppIdSession::is_svc_taking_too_much_time() +{ + return (init_pkts_without_reply > ctxt.get_odp_ctxt().max_packet_service_fail_ignore_bytes || + (init_pkts_without_reply > ctxt.get_odp_ctxt().max_packet_before_service_fail && + init_bytes_without_reply > ctxt.get_odp_ctxt().max_bytes_before_service_fail)); +} + void AppIdSession::free_tls_session_data() { if (tsession) @@ -616,7 +627,6 @@ void* AppIdSession::remove_flow_data(unsigned id) delete it->second; flow_data.erase(it); } - return data; } @@ -959,12 +969,14 @@ bool AppIdSession::is_tp_appid_available() const return true; } -void AppIdSession::set_tp_app_id(Packet& p, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits) +void AppIdSession::set_tp_app_id(Packet& p, AppidSessionDirection dir, AppId app_id, + AppidChangeBits& change_bits) { if (tp_app_id != app_id) { tp_app_id = app_id; - AppInfoTableEntry* entry = ctxt.get_odp_ctxt().get_app_info_mgr().get_app_info_entry(tp_app_id); + AppInfoTableEntry* entry = + ctxt.get_odp_ctxt().get_app_info_mgr().get_app_info_entry(tp_app_id); if (entry) { tp_app_id_deferred = (entry->flags & APPINFO_FLAG_DEFER) ? true : false; @@ -973,12 +985,14 @@ void AppIdSession::set_tp_app_id(Packet& p, AppidSessionDirection dir, AppId app } } -void AppIdSession::set_tp_payload_app_id(Packet& p, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits) +void AppIdSession::set_tp_payload_app_id(Packet& p, AppidSessionDirection dir, AppId app_id, + AppidChangeBits& change_bits) { if (tp_payload_app_id != app_id) { tp_payload_app_id = app_id; - AppInfoTableEntry* entry = ctxt.get_odp_ctxt().get_app_info_mgr().get_app_info_entry(tp_payload_app_id); + AppInfoTableEntry* entry = + ctxt.get_odp_ctxt().get_app_info_mgr().get_app_info_entry(tp_payload_app_id); if (entry) { tp_payload_app_id_deferred = (entry->flags & APPINFO_FLAG_DEFER_PAYLOAD) ? true : false; diff --git a/src/network_inspectors/appid/appid_session.h b/src/network_inspectors/appid/appid_session.h index dd1c1cd3b..866082e71 100644 --- a/src/network_inspectors/appid/appid_session.h +++ b/src/network_inspectors/appid/appid_session.h @@ -210,6 +210,8 @@ public: std::unordered_map flow_data; CommonAppIdData common; uint16_t session_packet_count = 0; + uint16_t init_pkts_without_reply = 0; + uint64_t init_bytes_without_reply = 0; snort::SfIp service_ip; uint16_t service_port = 0; @@ -285,10 +287,13 @@ public: void clear_session_flags(uint64_t flags) { common.flags &= ~flags; } uint64_t get_session_flags(uint64_t flags) const { return (common.flags & flags); } void set_service_detected() { common.flags |= APPID_SESSION_SERVICE_DETECTED; } - bool is_service_detected() { return ((common.flags & APPID_SESSION_SERVICE_DETECTED) == 0) ? false : true; } + bool is_service_detected() { return ((common.flags & APPID_SESSION_SERVICE_DETECTED) == 0) ? + false : true; } void set_client_detected() { common.flags |= APPID_SESSION_CLIENT_DETECTED; } - bool is_client_detected() { return ((common.flags & APPID_SESSION_CLIENT_DETECTED) == 0) ? false : true; } + bool is_client_detected() { return ((common.flags & APPID_SESSION_CLIENT_DETECTED) == 0) ? + false : true; } bool is_decrypted() { return ((common.flags & APPID_SESSION_DECRYPTED) == 0) ? false : true; } + bool is_svc_taking_too_much_time(); void* get_flow_data(unsigned id); int add_flow_data(void* data, unsigned id, AppIdFreeFCN); @@ -338,8 +343,10 @@ public: bool is_tp_processing_done() const; bool is_tp_appid_available() const; - void set_tp_app_id(snort::Packet& p, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits); - void set_tp_payload_app_id(snort::Packet& p, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits); + void set_tp_app_id(snort::Packet& p, AppidSessionDirection dir, AppId app_id, + AppidChangeBits& change_bits); + void set_tp_payload_app_id(snort::Packet& p, AppidSessionDirection dir, AppId app_id, + AppidChangeBits& change_bits); inline void set_tp_app_id(AppId app_id) { if (tp_app_id != app_id) diff --git a/src/network_inspectors/appid/service_plugins/service_discovery.cc b/src/network_inspectors/appid/service_plugins/service_discovery.cc index c1ef13c03..5471396c2 100644 --- a/src/network_inspectors/appid/service_plugins/service_discovery.cc +++ b/src/network_inspectors/appid/service_plugins/service_discovery.cc @@ -670,6 +670,16 @@ bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p, } } + /* If the session appears to only have the client sending data then + we must mark the service unknown to prevent pending forever. */ + if (asd.service_disco_state == APPID_DISCO_STATE_STATEFUL && + asd.service.get_id() == APP_ID_NONE && asd.is_svc_taking_too_much_time()) + { + asd.stop_service_inspection(p, direction); + asd.service.set_id(APP_ID_UNKNOWN, asd.ctxt.get_odp_ctxt()); + return isTpAppidDiscoveryDone; + } + AppIdDnsSession* dsession = asd.get_dns_session(); if (asd.service.get_id() == APP_ID_DNS && asd.ctxt.get_odp_ctxt().dns_host_reporting && dsession->get_host())