detector_plugins/sip_patterns.h
detector_plugins/ssh_patterns.cc
detector_plugins/ssh_patterns.h
- detector_plugins/ssl_patterns.cc
- detector_plugins/ssl_patterns.h
+ detector_plugins/host_patterns.cc
+ detector_plugins/host_patterns.h
)
set ( UTIL_APPID_SOURCES
return false;
AppidChangeBits change_bits;
- SslPatternMatchers& ssl_matchers = asd->get_odp_ctxt().get_ssl_matchers();
+ HostPatternMatchers& host_matchers = asd->get_odp_ctxt().get_host_matchers();
if (!asd->tsession)
asd->tsession = new TlsSession();
else if (sni_mismatch)
asd->tsession->set_tls_org_unit(org_unit, strlen(org_unit));
if (client_id == APP_ID_NONE and payload_id == APP_ID_NONE)
{
- ssl_matchers.scan_cname((const uint8_t*)org_unit, strlen(org_unit),
+ host_matchers.scan_cname((const uint8_t*)org_unit, strlen(org_unit),
client_id, payload_id);
if (client_id != APP_ID_NONE or payload_id != APP_ID_NONE)
asd->tsession->set_matched_tls_type(MatchedTlsType::MATCHED_TLS_ORG_UNIT);
if (server_name and !sni_mismatch)
{
asd->tsession->set_tls_host(server_name, strlen(server_name), change_bits);
- ssl_matchers.scan_hostname((const uint8_t*)server_name, strlen(server_name),
+ host_matchers.scan_hostname((const uint8_t*)server_name, strlen(server_name),
client_id, payload_id);
if (client_id != APP_ID_NONE or payload_id != APP_ID_NONE)
asd->tsession->set_matched_tls_type(MatchedTlsType::MATCHED_TLS_HOST);
asd->tsession->set_tls_first_alt_name(first_alt_name, strlen(first_alt_name), change_bits);
if (client_id == APP_ID_NONE and payload_id == APP_ID_NONE)
{
- ssl_matchers.scan_hostname((const uint8_t*)first_alt_name, strlen(first_alt_name),
+ host_matchers.scan_hostname((const uint8_t*)first_alt_name, strlen(first_alt_name),
client_id, payload_id);
if (client_id != APP_ID_NONE or payload_id != APP_ID_NONE)
asd->tsession->set_matched_tls_type(MatchedTlsType::MATCHED_TLS_FIRST_SAN);
asd->tsession->set_tls_cname(common_name, strlen(common_name), change_bits);
if (client_id == APP_ID_NONE and payload_id == APP_ID_NONE)
{
- ssl_matchers.scan_cname((const uint8_t*)common_name, strlen(common_name),
+ host_matchers.scan_cname((const uint8_t*)common_name, strlen(common_name),
client_id, payload_id);
if (client_id != APP_ID_NONE or payload_id != APP_ID_NONE)
asd->tsession->set_matched_tls_type(MatchedTlsType::MATCHED_TLS_CNAME);
}
else
{
- SslPatternMatchers& ssl_matchers = pkt_thread_odp_ctxt->get_ssl_matchers();
+ HostPatternMatchers& host_matchers = pkt_thread_odp_ctxt->get_host_matchers();
if (server_name and !sni_mismatch)
- ssl_matchers.scan_hostname((const uint8_t*)server_name, strlen(server_name),
+ host_matchers.scan_hostname((const uint8_t*)server_name, strlen(server_name),
client_id, payload_id);
if (first_alt_name and client_id == APP_ID_NONE and payload_id == APP_ID_NONE)
- ssl_matchers.scan_hostname((const uint8_t*)first_alt_name, strlen(first_alt_name),
+ host_matchers.scan_hostname((const uint8_t*)first_alt_name, strlen(first_alt_name),
client_id, payload_id);
if (common_name and client_id == APP_ID_NONE and payload_id == APP_ID_NONE)
- ssl_matchers.scan_cname((const uint8_t*)common_name, strlen(common_name), client_id,
+ host_matchers.scan_cname((const uint8_t*)common_name, strlen(common_name), client_id,
payload_id);
if (org_unit and client_id == APP_ID_NONE and payload_id == APP_ID_NONE)
- ssl_matchers.scan_cname((const uint8_t*)org_unit, strlen(org_unit), client_id,
+ host_matchers.scan_cname((const uint8_t*)org_unit, strlen(org_unit), client_id,
payload_id);
}
eve_ca_matchers.get_pattern_count() +
alpn_matchers.get_pattern_count() +
sip_matchers.get_pattern_count() +
- ssl_matchers.get_pattern_count() +
+ host_matchers.get_pattern_count() +
ssh_matchers.get_pattern_count() +
dns_matchers.get_pattern_count();
}
client_pattern_detector->finalize_client_port_patterns(inspector);
service_disco_mgr.finalize_service_patterns();
client_disco_mgr.finalize_client_patterns();
- http_matchers.finalize_patterns();
+ http_matchers.finalize_patterns(*this);
eve_ca_matchers.finalize_patterns();
alpn_matchers.finalize_patterns();
// sip patterns need to be finalized after http patterns because they
// are dependent on http patterns
sip_matchers.finalize_patterns(*this);
- ssl_matchers.finalize_patterns();
+ host_matchers.finalize_patterns();
dns_matchers.finalize_patterns();
}
eve_ca_matchers.reload_patterns();
http_matchers.reload_patterns();
sip_matchers.reload_patterns();
- ssl_matchers.reload_patterns();
+ host_matchers.reload_patterns();
dns_matchers.reload_patterns();
alpn_matchers.reload_patterns();
}
#include "detector_plugins/dns_patterns.h"
#include "detector_plugins/http_url_patterns.h"
#include "detector_plugins/sip_patterns.h"
-#include "detector_plugins/ssl_patterns.h"
+#include "detector_plugins/host_patterns.h"
#include "host_port_app_cache.h"
#include "length_app_cache.h"
#include "lua_detector_flow_api.h"
return sip_matchers;
}
- SslPatternMatchers& get_ssl_matchers()
+ HostPatternMatchers& get_host_matchers()
{
- return ssl_matchers;
+ return host_matchers;
}
SshPatternMatchers& get_ssh_matchers()
EveCaPatternMatchers eve_ca_matchers;
ServiceDiscovery service_disco_mgr;
SipPatternMatchers sip_matchers;
- SslPatternMatchers ssl_matchers;
+ HostPatternMatchers host_matchers;
SshPatternMatchers ssh_matchers;
PatternClientDetector* client_pattern_detector;
PatternServiceDetector* service_pattern_detector;
asd->tsession->set_tls_host(server_name.c_str(), server_name.length());
asd->set_tls_host();
- odp_ctxt.get_ssl_matchers().scan_hostname(reinterpret_cast<const uint8_t*>(server_name.c_str()),
+ odp_ctxt.get_host_matchers().scan_hostname(reinterpret_cast<const uint8_t*>(server_name.c_str()),
server_name.length(), tmp_client_id, tmp_payload_id);
asd->set_payload_id(tmp_payload_id);
}
if (tls_str)
{
size_t size = strlen(tls_str);
- if (odp_ctxt.get_ssl_matchers().scan_cname((const uint8_t*)tls_str, size,
+ if (odp_ctxt.get_host_matchers().scan_cname((const uint8_t*)tls_str, size,
client_id, payload_id))
{
set_client_appid_data(client_id, change_bits);
if ((scan_flags & SCAN_SSL_HOST_FLAG) and (tls_str = tsession->get_tls_host()))
{
size_t size = strlen(tls_str);
- if (odp_ctxt.get_ssl_matchers().scan_hostname((const uint8_t*)tls_str, size,
+ if (odp_ctxt.get_host_matchers().scan_hostname((const uint8_t*)tls_str, size,
client_id, payload_id))
{
if (api.client.get_id() == APP_ID_NONE or api.client.get_id() == APP_ID_SSL_CLIENT)
if ((scan_flags & SCAN_SSL_CERTIFICATE_FLAG) and (tls_str = tsession->get_tls_cname()))
{
size_t size = strlen(tls_str);
- if (odp_ctxt.get_ssl_matchers().scan_cname((const uint8_t*)tls_str, size,
+ if (odp_ctxt.get_host_matchers().scan_cname((const uint8_t*)tls_str, size,
client_id, payload_id))
{
if (api.client.get_id() == APP_ID_NONE or api.client.get_id() == APP_ID_SSL_CLIENT)
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2025 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.
+//--------------------------------------------------------------------------
+
+// host_patterns.cc author Shravan Rangaraju <shrarang@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cassert>
+
+#include "host_patterns.h"
+
+#include "utils/util.h"
+
+using namespace snort;
+
+#define HOST_PATTERN_CERT_TYPE_MASK 6 // HostPatternType::HOST_PATTERN_TYPE_SNI | HostPatternType::HOST_PATTERN_TYPE_CNAME
+
+int cert_pattern_match(void* id, void*, int match_end_pos, void* data, void*);
+int cname_pattern_match(void* id, void*, int match_end_pos, void* data, void*);
+int url_pattern_match(void* id, void*, int match_end_pos, void* data, void*);
+
+static void create_matcher(SearchTool& matcher, HostPatternList* list, unsigned& pattern_count)
+{
+ size_t* pattern_index;
+ size_t size = 0;
+ HostPatternList* element = nullptr;
+
+ pattern_index = &size;
+
+ for (element = list; element; element = element->next)
+ {
+ matcher.add(element->dpattern->pattern,
+ element->dpattern->pattern_size, element->dpattern, true, element->dpattern->is_literal);
+ (*pattern_index)++;
+ }
+ pattern_count = size;
+ matcher.prep();
+}
+
+int cert_pattern_match(void* id, void*, int match_end_pos, void* data, void*)
+{
+ HostPattern* target = (HostPattern*)id;
+
+ if ( target->pattern_type & HOST_PATTERN_CERT_TYPE_MASK )
+ {
+ MatchedHostPatterns* cm;
+ MatchedHostPatterns** matches = (MatchedHostPatterns**)data;
+
+ cm = (MatchedHostPatterns*)snort_alloc(sizeof(MatchedHostPatterns));
+ cm->mpattern = target;
+ cm->match_start_pos = match_end_pos - target->pattern_size;
+ cm->next = *matches;
+ *matches = cm;
+ }
+ return 0;
+}
+
+int cname_pattern_match(void* id, void*, int match_end_pos, void* data, void*)
+{
+ HostPattern* target = (HostPattern*)id;
+
+ if ( target->pattern_type & HostPatternType::HOST_PATTERN_TYPE_CNAME )
+ {
+ MatchedHostPatterns* cm;
+ MatchedHostPatterns** matches = (MatchedHostPatterns**)data;
+
+ cm = (MatchedHostPatterns*)snort_alloc(sizeof(MatchedHostPatterns));
+ cm->mpattern = target;
+ cm->match_start_pos = match_end_pos - target->pattern_size;
+ cm->next = *matches;
+ *matches = cm;
+ }
+ return 0;
+}
+
+int url_pattern_match(void* id, void*, int match_end_pos, void* data, void*)
+{
+ HostPattern* target = (HostPattern*)id;
+
+ if ( target->pattern_type & HostPatternType::HOST_PATTERN_TYPE_URL )
+ {
+ MatchedHostPatterns* cm;
+ MatchedHostPatterns** matches = (MatchedHostPatterns**)data;
+
+ cm = (MatchedHostPatterns*)snort_alloc(sizeof(MatchedHostPatterns));
+ cm->mpattern = target;
+ cm->match_start_pos = match_end_pos - target->pattern_size;
+ cm->next = *matches;
+ *matches = cm;
+ }
+ return 0;
+}
+/*
+Only patterns that match end of the payload AND
+(match the start of the payload
+or match after '.'
+or patterns starting with '.')
+are considered a match. */
+inline bool host_pattern_validate_match(const MatchedHostPatterns * const mp, const uint8_t* data, const size_t& data_size)
+{
+ return mp->match_start_pos + mp->mpattern->pattern_size == data_size and
+ (mp->match_start_pos == 0 or
+ data[mp->match_start_pos-1] == '.' or
+ *mp->mpattern->pattern == '.');
+}
+
+inline bool host_pattern_validate_url_match(const MatchedHostPatterns * const mp, const uint8_t* data)
+{
+ return mp->match_start_pos == 0 or
+ data[mp->match_start_pos-1] == '.';
+}
+
+inline bool is_perfect_literal_match(const MatchedHostPatterns * const mp, const size_t& data_size)
+{
+ return mp->mpattern->is_literal and mp->match_start_pos == 0 and
+ (mp->match_start_pos + mp->mpattern->pattern_size == data_size);
+
+}
+
+template<HostPatternType T>
+bool scan_patterns(SearchTool& matcher, const uint8_t* data, size_t size,
+ AppId& client_id, AppId& payload_id, bool* is_referred_appid = nullptr)
+{
+ MatchedHostPatterns* mp = nullptr;
+ HostPattern* best_match = nullptr;
+
+ matcher.find_all((const char*)data, size,
+ T == HostPatternType::HOST_PATTERN_TYPE_CNAME ? cname_pattern_match :
+ T == HostPatternType::HOST_PATTERN_TYPE_URL ? url_pattern_match :
+ cert_pattern_match, false, &mp);
+
+ if ( !mp )
+ return false;
+
+ MatchedHostPatterns* tmp = mp;
+
+ while ( tmp )
+ {
+ auto match = tmp->mpattern;
+ if ( !match->is_literal or ( T == HostPatternType::HOST_PATTERN_TYPE_URL ? host_pattern_validate_url_match(tmp, data) : host_pattern_validate_match(tmp, data, size) ))
+ {
+ if ( T != HostPatternType::HOST_PATTERN_TYPE_URL)
+ {
+ if ( is_perfect_literal_match(tmp, size) )
+ {
+ best_match = match;
+ break;
+ }
+ }
+
+ if ( !best_match or match->pattern_size > best_match->pattern_size )
+ {
+ best_match = match;
+ }
+ }
+ tmp = tmp->next;
+ }
+
+ while ( mp )
+ {
+ MatchedHostPatterns* tmpMp = mp;
+ mp = mp->next;
+ snort_free(tmpMp);
+ }
+
+ if ( !best_match )
+ return false;
+
+ if ( T == HostPatternType::HOST_PATTERN_TYPE_URL )
+ {
+ client_id = best_match->client_id;
+ payload_id = best_match->payload_id;
+ if(is_referred_appid)
+ {
+ *is_referred_appid = best_match->is_referred;
+ }
+ }
+ else
+ {
+ if (best_match->type)
+ {
+ client_id = best_match->client_id;
+ payload_id = 0;
+ }
+ else
+ {
+ client_id = APP_ID_SSL_CLIENT;
+ payload_id = best_match->payload_id;
+ }
+ }
+
+ return true;
+}
+
+static void free_patterns(HostPatternList*& list)
+{
+ HostPatternList* tmp_pattern;
+
+ while ( (tmp_pattern = list) )
+ {
+ list = tmp_pattern->next;
+ if ( tmp_pattern->dpattern )
+ {
+ if ( tmp_pattern->dpattern->pattern )
+ snort_free(tmp_pattern->dpattern->pattern);
+ snort_free(tmp_pattern->dpattern);
+ }
+ snort_free(tmp_pattern);
+ }
+}
+
+static void add_pattern(HostPatternList*& list, const uint8_t* pattern_str, size_t
+ pattern_size, uint8_t type, AppId client_id, AppId payload_id, HostPatternType pattern_type, bool is_literal, bool is_referred, HostTmpCache& set)
+{
+
+ HostTmpCacheKey key { pattern_str, pattern_size, client_id, payload_id };
+ auto tmp_lookup_it = set.find(key);
+ if ( tmp_lookup_it != set.end() )
+ {
+ auto cached_list_entry = tmp_lookup_it->second;
+
+ cached_list_entry->pattern_type |= pattern_type;
+ cached_list_entry->is_referred |= is_referred;
+ return;
+ }
+
+ HostPatternList* new_host_pattern;
+
+ new_host_pattern = (HostPatternList*)snort_calloc(sizeof(HostPatternList));
+ new_host_pattern->dpattern = (HostPattern*)snort_calloc(sizeof(HostPattern));
+ new_host_pattern->dpattern->type = type;
+ new_host_pattern->dpattern->client_id = client_id;
+ new_host_pattern->dpattern->payload_id = payload_id;
+ new_host_pattern->dpattern->pattern_size = pattern_size;
+ new_host_pattern->dpattern->pattern_type = pattern_type;
+ new_host_pattern->dpattern->is_literal = is_literal;
+ new_host_pattern->dpattern->is_referred = is_referred;
+ new_host_pattern->dpattern->pattern = (uint8_t*)snort_alloc(pattern_size);
+ memcpy(new_host_pattern->dpattern->pattern, pattern_str, pattern_size);
+
+ new_host_pattern->next = list;
+ list = new_host_pattern;
+
+ key.pattern = new_host_pattern->dpattern->pattern;
+ set[key] = new_host_pattern->dpattern;
+}
+
+HostPatternMatchers::~HostPatternMatchers()
+{
+ free_patterns(host_pattern_list);
+}
+
+void HostPatternMatchers::add_host_pattern(const uint8_t* pattern_str, size_t pattern_size, uint8_t type, AppId client_id, AppId payload_id, HostPatternType pattern_type, bool is_literal, bool is_referred)
+{
+ add_pattern(host_pattern_list, pattern_str, pattern_size, type, client_id, payload_id, pattern_type, is_literal, is_referred, host_pattern_set);
+}
+
+void HostPatternMatchers::finalize_patterns()
+{
+ create_matcher(host_matcher, host_pattern_list, pattern_count);
+ host_pattern_set.clear();
+}
+
+void HostPatternMatchers::reload_patterns()
+{
+ host_matcher.reload();
+}
+
+unsigned HostPatternMatchers::get_pattern_count()
+{
+ return pattern_count;
+}
+
+bool HostPatternMatchers::scan_url(const uint8_t *url, size_t size, AppId &client_id, AppId &payload_id, bool* is_referred_appid)
+{
+ return scan_patterns<HostPatternType::HOST_PATTERN_TYPE_URL>(host_matcher, url, size, client_id, payload_id, is_referred_appid);
+}
+
+bool HostPatternMatchers::scan_hostname(const uint8_t* hostname, size_t size, AppId& client_id, AppId& payload_id)
+{
+ return scan_patterns<HostPatternType::HOST_PATTERN_TYPE_SNI>(host_matcher, hostname, size, client_id, payload_id);
+}
+
+bool HostPatternMatchers::scan_cname(const uint8_t* common_name, size_t size, AppId& client_id, AppId& payload_id)
+{
+ return scan_patterns<HostPatternType::HOST_PATTERN_TYPE_CNAME>(host_matcher, common_name, size, client_id, payload_id);
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2025 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.
+//--------------------------------------------------------------------------
+
+// host_patterns.h author Shravan Rangaraju <shrarang@cisco.com>
+
+#ifndef HOST_PATTERNS_H
+#define HOST_PATTERNS_H
+
+#include <cstring>
+#include <unordered_map>
+#include "search_engines/search_tool.h"
+#include "application_ids.h"
+
+enum HostPatternType : uint8_t
+{
+ HOST_PATTERN_TYPE_UNDEFINED = 0,
+ HOST_PATTERN_TYPE_SNI = (1 << 1),
+ HOST_PATTERN_TYPE_CNAME = (1 << 2),
+ HOST_PATTERN_TYPE_URL = (1 << 3)
+};
+
+struct HostPattern
+{
+ uint8_t type;
+ AppId client_id;
+ AppId payload_id;
+ uint8_t* pattern;
+ uint32_t pattern_size;
+ uint8_t pattern_type;
+ bool is_literal; // is not regex pattern
+ bool is_referred;
+
+ bool operator==(const HostPattern& v) const
+ {
+ return this->type == v.type and pattern_size == v.pattern_size and this->pattern_type == v.pattern_type
+ and (memcmp(pattern, v.pattern, (size_t)pattern_size) == 0);
+ }
+};
+
+struct HostTmpCacheKey
+{
+ const uint8_t* pattern;
+ size_t pattern_len;
+ AppId cl_id;
+ AppId pl_id;
+
+ inline bool operator==(const HostTmpCacheKey& rhs) const
+ {
+ return (this->pattern_len == rhs.pattern_len) and (this->cl_id == rhs.cl_id) and
+ (this->pl_id == rhs.pl_id) and
+ (memcmp(this->pattern, rhs.pattern, this->pattern_len) == 0);
+ }
+};
+
+struct HostTmpCacheKeyHasher
+{
+ size_t operator()(const HostTmpCacheKey& key) const
+ {
+ return std::hash<std::string>()(std::string((const char*)key.pattern, key.pattern_len)) ^ std::hash<AppId>()(key.cl_id) ^ std::hash<AppId>()(key.pl_id);
+ }
+};
+
+typedef std::unordered_map<HostTmpCacheKey, HostPattern*, HostTmpCacheKeyHasher> HostTmpCache;
+
+struct MatchedHostPatterns
+{
+ HostPattern* mpattern;
+ uint32_t match_start_pos;
+ struct MatchedHostPatterns* next;
+};
+
+struct HostPatternList
+{
+ HostPattern* dpattern;
+ HostPatternList* next;
+};
+
+class HostPatternMatchers
+{
+public:
+ ~HostPatternMatchers();
+ void add_host_pattern(const uint8_t*, size_t, uint8_t, AppId, AppId, HostPatternType, bool = true, bool = false);
+ void finalize_patterns();
+ void reload_patterns();
+ unsigned get_pattern_count();
+ bool scan_hostname(const uint8_t*, size_t, AppId&, AppId&);
+ bool scan_cname(const uint8_t*, size_t, AppId&, AppId&);
+ bool scan_url(const uint8_t*, size_t, AppId&, AppId&, bool* = nullptr);
+
+private:
+ HostPatternList* host_pattern_list = nullptr;
+ HostTmpCache host_pattern_set;
+ snort::SearchTool host_matcher = snort::SearchTool();
+ unsigned pattern_count = 0;
+};
+
+#endif
HttpPatternMatchers::insert_url_pattern(pattern);
}
-int HttpPatternMatchers::add_mlmp_pattern(tMlmpTree* matcher, DetectorHTTPPattern& pattern)
+int HttpPatternMatchers::add_mlmp_pattern(tMlmpTree* matcher, DetectorHTTPPattern& pattern, OdpContext& odp_ctxt)
{
assert(pattern.pattern);
else
detector->appId = pattern.service_id;
+ detector->is_referred = odp_ctxt.get_app_info_mgr().get_app_info_flags(detector->payload_id, APPINFO_FLAG_REFERRED);
+
tMlmpPattern patterns[PATTERN_PART_MAX];
int num_patterns = parse_multiple_http_patterns((const char*)pattern.pattern, patterns,
PATTERN_PART_MAX, 0, true);
return mlmpAddPattern(matcher, patterns, detector);
}
-int HttpPatternMatchers::add_mlmp_pattern(tMlmpTree* matcher, DetectorAppUrlPattern& pattern)
+int HttpPatternMatchers::add_mlmp_pattern(tMlmpTree* matcher, DetectorAppUrlPattern& pattern, OdpContext& odp_ctxt)
{
assert(pattern.patterns.host.pattern);
detector->service_id = pattern.userData.service_id;
detector->client_id = pattern.userData.client_id;
detector->seq = SINGLE;
+ detector->is_referred = odp_ctxt.get_app_info_mgr().get_app_info_flags(detector->payload_id, APPINFO_FLAG_REFERRED);
if (pattern.userData.appId > APP_ID_NONE)
detector->appId = pattern.userData.appId;
else if (pattern.userData.payload_id > APP_ID_NONE)
return mlmpAddPattern(matcher, patterns, detector);
}
-int HttpPatternMatchers::process_mlmp_patterns()
+int HttpPatternMatchers::process_mlmp_patterns(OdpContext& ctxt)
{
for (auto& pattern: host_payload_patterns)
- if ( add_mlmp_pattern(host_url_matcher, pattern) < 0 )
+ if ( add_mlmp_pattern(host_url_matcher, pattern, ctxt) < 0 )
return -1;
if (std::any_of(rtmp_url_patterns.begin(), rtmp_url_patterns.end(),
- [this](DetectorAppUrlPattern* pattern){ return add_mlmp_pattern(rtmp_host_url_matcher, *pattern) < 0; }))
+ [this, &ctxt](DetectorAppUrlPattern* pattern) mutable { return add_mlmp_pattern(rtmp_host_url_matcher, *pattern, ctxt) < 0; }))
return -1;
if (std::any_of(app_url_patterns.begin(), app_url_patterns.end(),
- [this](DetectorAppUrlPattern* pattern){ return add_mlmp_pattern(host_url_matcher, *pattern) < 0; }))
+ [this, &ctxt](DetectorAppUrlPattern* pattern) mutable { return add_mlmp_pattern(host_url_matcher, *pattern, ctxt) < 0; }))
return -1;
return 0;
return 0;
}
-int HttpPatternMatchers::process_host_patterns(DetectorHTTPPatterns& patterns)
+int HttpPatternMatchers::process_host_patterns(const DetectorHTTPPatterns& patterns, OdpContext& ctxt)
{
if (!host_url_matcher)
host_url_matcher = mlmpCreate();
if (!rtmp_host_url_matcher)
rtmp_host_url_matcher = mlmpCreate();
- for (auto& pat : patterns)
+ for (const auto& pat : patterns)
{
- if ( add_mlmp_pattern(host_url_matcher, pat) < 0 )
- return -1;
+ ctxt.get_host_matchers().add_host_pattern(pat.pattern, pat.pattern_size, 0,
+ pat.client_id, pat.payload_id, HostPatternType::HOST_PATTERN_TYPE_URL, true,
+ ctxt.get_app_info_mgr().get_app_info_flags(pat.payload_id, APPINFO_FLAG_REFERRED));
}
- if ( HttpPatternMatchers::process_mlmp_patterns() < 0 )
+ if ( HttpPatternMatchers::process_mlmp_patterns(ctxt) < 0 )
return -1;
mlmpProcessPatterns(host_url_matcher);
matcher.prep();
}
-int HttpPatternMatchers::finalize_patterns()
+int HttpPatternMatchers::finalize_patterns(OdpContext& ctxt)
{
process_patterns(via_matcher, static_via_http_detector_patterns);
process_patterns(url_matcher, url_patterns);
process_patterns(client_agent_matcher, static_client_agent_patterns, false);
process_patterns(client_agent_matcher, client_agent_patterns);
- if (process_host_patterns(static_http_host_payload_patterns) < 0)
+ if (process_host_patterns(static_http_host_payload_patterns, ctxt) < 0)
return -1;
process_patterns(content_type_matcher, static_content_type_patterns, false);
const char* referer, AppId* ClientAppId, AppId* serviceAppId, AppId* payloadAppId,
AppId* referredPayloadAppId, bool from_rtmp, OdpContext& odp_ctxt)
{
- char* temp_host = nullptr;
+ if (!host && !url)
+ return false;
+
tMlmpPattern patterns[3];
bool payload_found = false;
tMlmpTree* matcher = from_rtmp ? rtmp_host_url_matcher : host_url_matcher;
-
- if (!host && !url)
- return false;
+ auto& host_matcher = odp_ctxt.get_host_matchers();
+ bool is_referred_appid = false;
int url_len = 0;
if (url)
{
- size_t scheme_len = strlen(url);
- if (scheme_len > URL_SCHEME_MAX_LEN)
- scheme_len = URL_SCHEME_MAX_LEN; // only search the first few bytes for scheme
- const char* url_offset = (const char*)service_strstr((const uint8_t*)url, scheme_len,
- (const uint8_t*)URL_SCHEME_END_PATTERN, sizeof(URL_SCHEME_END_PATTERN)-1);
+ const char* url_offset = strstr(url, URL_SCHEME_END_PATTERN);
if (url_offset)
- url_offset += sizeof(URL_SCHEME_END_PATTERN)-1;
+ url = url_offset + sizeof(URL_SCHEME_END_PATTERN)-1;
else
return false;
- url = url_offset;
url_len = strlen(url);
}
int host_len;
if (!host)
{
- host = strchr(url, '/');
- if (host != nullptr)
- host_len = host - url;
+ host = url;
+ auto path_offset = strchr(url, '/');
+ if (path_offset != nullptr)
+ host_len = path_offset - url;
else
host_len = url_len;
- if (host_len > 0)
- {
- temp_host = snort_strndup(url, host_len);
- if (!temp_host)
- {
- host_len = 0;
- host = nullptr;
- }
- else
- host = temp_host;
- }
}
else
host_len = strlen(host);
{
if (url_len < host_len)
{
- snort_free(temp_host);
return false;
}
path = strchr(url, '/');
if (path)
+ {
path_len = url + url_len - path;
+ if(path_len == 1)
+ path_len = 0;
+ }
+
}
- if (!path_len)
+ if (!path_len and !from_rtmp)
{
- path = "/";
- path_len = 1;
+ payload_found = host_matcher.scan_url((const uint8_t*)host, host_len, *ClientAppId , *payloadAppId);
}
+ else
+ {
+ if (!path_len)
+ {
+ path = "/";
+ path_len = 1;
+ }
- patterns[0].pattern = (const uint8_t*)host;
- patterns[0].patternSize = host_len;
- patterns[1].pattern = (const uint8_t*)path;
- patterns[1].patternSize = path_len;
- patterns[2].pattern = nullptr;
+ patterns[0].pattern = (const uint8_t*)host;
+ patterns[0].patternSize = host_len;
+ patterns[1].pattern = (const uint8_t*)path;
+ patterns[1].patternSize = path_len;
+ patterns[2].pattern = nullptr;
- HostUrlDetectorPattern* data = (HostUrlDetectorPattern*)mlmpMatchPatternUrl(matcher, patterns);
- if ( data )
- {
- payload_found = true;
- if ( url )
+ HostUrlDetectorPattern* data = (HostUrlDetectorPattern*)mlmpMatchPatternUrl(matcher, patterns);
+ if ( data )
{
- const char* q = strchr(url, '?');
- if ( q != nullptr )
+ if ( url )
{
- tMlpPattern query;
- char temp_ver[MAX_VERSION_SIZE];
- temp_ver[0] = 0;
- query.pattern = (const uint8_t*)++q;
- query.patternSize = strlen(q);
+ const char* q = strchr(url, '?');
+ if ( q != nullptr )
+ {
+ tMlpPattern query;
+ char temp_ver[MAX_VERSION_SIZE];
+ temp_ver[0] = 0;
+ query.pattern = (const uint8_t*)++q;
+ query.patternSize = strlen(q);
- match_query_elements(&query, &data->query, temp_ver, MAX_VERSION_SIZE);
+ match_query_elements(&query, &data->query, temp_ver, MAX_VERSION_SIZE);
- if (temp_ver[0] != 0)
- replace_optional_string(version, temp_ver);
+ if (temp_ver[0] != 0)
+ replace_optional_string(version, temp_ver);
+ }
}
+
+ *ClientAppId = data->client_id;
+ *serviceAppId = data->service_id;
+ *payloadAppId = data->payload_id;
+ payload_found = data->payload_id;
+ is_referred_appid = data->is_referred;
}
- *ClientAppId = data->client_id;
- *serviceAppId = data->service_id;
- *payloadAppId = data->payload_id;
+ if (!payload_found and !from_rtmp)
+ {
+ payload_found = host_matcher.scan_url((const uint8_t*)host, host_len, *ClientAppId, *payloadAppId, &is_referred_appid);
+ }
}
- snort_free(temp_host);
-
/* if referred_id feature id disabled, referer will be null */
- if ( referer and (referer[0] != '\0') and (!payload_found or
- odp_ctxt.get_app_info_mgr().get_app_info_flags(data->payload_id,
- APPINFO_FLAG_REFERRED)) )
+ if ( (!payload_found or is_referred_appid)
+ and ( referer and (referer[0] != '\0') ) )
{
const char* referer_start = referer;
- size_t ref_len = strlen(referer);
- const char* referer_offset = (const char*)service_strstr((const uint8_t*)referer_start, ref_len,
- (const uint8_t*)URL_SCHEME_END_PATTERN, sizeof(URL_SCHEME_END_PATTERN)-1);
+ const char* referer_offset = strstr(referer_start, URL_SCHEME_END_PATTERN);
if ( !referer_offset )
return payload_found;
- referer_offset += sizeof(URL_SCHEME_END_PATTERN)-1;
- referer_start = referer_offset;
+ referer_start = referer_offset + sizeof(URL_SCHEME_END_PATTERN)-1;
int referer_len = strlen(referer_start);
const char* referer_path = strchr(referer_start, '/');
- int referer_path_len = 0;
+ bool referer_found = false;
- if ( referer_path )
- {
- referer_path_len = strlen(referer_path);
- referer_len -= referer_path_len;
- }
- else
+ if ( referer_path or from_rtmp)
{
- referer_path = "/";
- referer_path_len = 1;
+ int referer_path_len = 0;
+
+ if(!referer_path)
+ {
+ referer_path = "/";
+ referer_path_len = 1;
+ }
+ else
+ {
+ referer_path_len = strlen(referer_path);
+ referer_len -= referer_path_len;
+ }
+
+ if ( referer_len > 0 )
+ {
+ patterns[0].pattern = (const uint8_t*)referer_start;
+ patterns[0].patternSize = referer_len;
+ patterns[1].pattern = (const uint8_t*)referer_path;
+ patterns[1].patternSize = referer_path_len;
+ patterns[2].pattern = nullptr;
+ HostUrlDetectorPattern* url_pattern_data = (HostUrlDetectorPattern*)mlmpMatchPatternUrl(matcher,
+ patterns);
+ if ( url_pattern_data != nullptr )
+ {
+ referer_found = true;
+ if ( payload_found )
+ *referredPayloadAppId = *payloadAppId;
+ else
+ payload_found = true;
+ *payloadAppId = url_pattern_data->payload_id;
+ }
+ }
}
- if ( referer_len > 0 )
+ if ( !referer_found and !from_rtmp)
{
- patterns[0].pattern = (const uint8_t*)referer_start;
- patterns[0].patternSize = referer_len;
- patterns[1].pattern = (const uint8_t*)referer_path;
- patterns[1].patternSize = referer_path_len;
- patterns[2].pattern = nullptr;
- HostUrlDetectorPattern* url_pattern_data = (HostUrlDetectorPattern*)mlmpMatchPatternUrl(matcher,
- patterns);
- if ( url_pattern_data != nullptr )
+ AppId cl_id = 0;
+ AppId pl_id = 0;
+
+ host_matcher.scan_url((const uint8_t*)referer_start, referer_len, cl_id, pl_id);
+
+ if ( pl_id )
{
if ( payload_found )
+ {
*referredPayloadAppId = *payloadAppId;
+ }
else
+ {
payload_found = true;
- *payloadAppId = url_pattern_data->payload_id;
+ }
+
+ *payloadAppId = pl_id;
}
}
}
uint32_t client_id = APP_ID_NONE;
AppId appId = APP_ID_NONE;
DHPSequence seq = SINGLE;
+ bool is_referred = false;
};
class HttpPatternMatchers
{ }
~HttpPatternMatchers();
- int finalize_patterns();
+ int finalize_patterns(OdpContext&);
void reload_patterns();
unsigned get_pattern_count();
void insert_chp_pattern(CHPListElement*);
void insert_rtmp_url_pattern(DetectorAppUrlPattern*);
void insert_app_url_pattern(DetectorAppUrlPattern*);
int process_chp_list(CHPListElement*);
- int process_host_patterns(DetectorHTTPPatterns&);
- int process_mlmp_patterns();
+ int process_host_patterns(const DetectorHTTPPatterns&, OdpContext&);
+ int process_mlmp_patterns(OdpContext&);
void process_http_field_patterns(FieldPattern*, size_t);
void scan_key_chp(ChpMatchDescriptor&);
unsigned chp_pattern_count = 0;
void free_chp_app_elements();
- int add_mlmp_pattern(tMlmpTree* matcher, DetectorHTTPPattern& pattern );
- int add_mlmp_pattern(tMlmpTree* matcher, DetectorAppUrlPattern& pattern);
+ int add_mlmp_pattern(tMlmpTree* matcher, DetectorHTTPPattern& pattern, OdpContext& odp_ctxt);
+ int add_mlmp_pattern(tMlmpTree* matcher, DetectorAppUrlPattern& pattern, OdpContext& odp_ctxt);
};
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2025 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.
-//--------------------------------------------------------------------------
-
-// ssl_patterns.cc author Shravan Rangaraju <shrarang@cisco.com>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ssl_patterns.h"
-
-#include "utils/util.h"
-
-using namespace snort;
-
-static void create_matcher(SearchTool& matcher, SslPatternList* list, CnameCache& set, unsigned& pattern_count)
-{
- size_t* pattern_index;
- size_t size = 0;
- SslPatternList* element = nullptr;
-
- pattern_index = &size;
-
- for (element = list; element; element = element->next)
- {
- if (!element->dpattern->is_cname and set.count(*(element->dpattern)))
- continue;
-
- matcher.add(element->dpattern->pattern,
- element->dpattern->pattern_size, element->dpattern, true, element->dpattern->is_literal);
- (*pattern_index)++;
- }
- pattern_count = size;
- matcher.prep();
-}
-
-static int cert_pattern_match(void* id, void*, int match_end_pos, void* data, void*)
-{
- MatchedSslPatterns* cm;
- MatchedSslPatterns** matches = (MatchedSslPatterns**)data;
- SslPattern* target = (SslPattern*)id;
-
- cm = (MatchedSslPatterns*)snort_alloc(sizeof(MatchedSslPatterns));
- cm->mpattern = target;
- cm->match_start_pos = match_end_pos - target->pattern_size;
- cm->next = *matches;
- *matches = cm;
-
- return 0;
-}
-
-static int cname_pattern_match(void* id, void*, int match_end_pos, void* data, void*)
-{
- MatchedSslPatterns* cm;
- MatchedSslPatterns** matches = (MatchedSslPatterns**)data;
- SslPattern* target = (SslPattern*)id;
-
- /* Only collect the match if it is a cname pattern. */
- if (target->is_cname)
- {
- cm = (MatchedSslPatterns*)snort_alloc(sizeof(MatchedSslPatterns));
- cm->mpattern = target;
- cm->match_start_pos = match_end_pos - target->pattern_size;
- cm->next = *matches;
- *matches = cm;
- }
- return 0;
-}
-/*
-Only patterns that match end of the payload AND
-(match the start of the payload
-or match after '.'
-or patterns starting with '.')
-are considered a match. */
-inline static bool ssl_pattern_validate_match(const MatchedSslPatterns * const mp, const uint8_t* data, int data_size)
-{
- return mp->match_start_pos + mp->mpattern->pattern_size == data_size and
- (mp->match_start_pos == 0 or
- data[mp->match_start_pos-1] == '.' or
- *mp->mpattern->pattern == '.');
-}
-
-inline static bool is_perfect_literal_match(const MatchedSslPatterns * const mp, int data_size)
-{
- return mp->mpattern->is_literal and
- (mp->match_start_pos + mp->mpattern->pattern_size == data_size) and
- mp->match_start_pos == 0;
-
-}
-
-static bool scan_patterns(SearchTool& matcher, const uint8_t* data, size_t size,
- AppId& client_id, AppId& payload_id, bool is_cname_search)
-{
- MatchedSslPatterns* mp = nullptr;
- SslPattern* best_match = nullptr;
-
- if (is_cname_search)
- matcher.find_all((const char*)data, size, cname_pattern_match, false, &mp);
- else
- matcher.find_all((const char*)data, size, cert_pattern_match, false, &mp);
-
- if (!mp)
- return false;
-
- MatchedSslPatterns* tmp = mp;
-
- while (tmp)
- {
- if (!tmp->mpattern->is_literal or ssl_pattern_validate_match(tmp, data, (int)size))
- {
- if(is_perfect_literal_match(tmp, (int)size))
- {
- best_match = tmp->mpattern;
- break;
- }
-
- if (!best_match or
- tmp->mpattern->pattern_size > best_match->pattern_size)
- {
- best_match = tmp->mpattern;
- }
- }
- tmp = tmp->next;
- }
-
- while (mp)
- {
- MatchedSslPatterns* tmpMp = mp;
- mp = mp->next;
- snort_free(tmpMp);
- }
- if (!best_match)
- return false;
-
- switch (best_match->type)
- {
- /* type 0 means WEB APP */
- case 0:
- client_id = APP_ID_SSL_CLIENT;
- payload_id = best_match->app_id;
- break;
- /* type 1 means CLIENT */
- case 1:
- client_id = best_match->app_id;
- payload_id = 0;
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-static void free_patterns(SslPatternList*& list)
-{
- SslPatternList* tmp_pattern;
-
- while ((tmp_pattern = list))
- {
- list = tmp_pattern->next;
- if (tmp_pattern->dpattern)
- {
- if (tmp_pattern->dpattern->pattern)
- snort_free(tmp_pattern->dpattern->pattern);
- snort_free(tmp_pattern->dpattern);
- }
- snort_free(tmp_pattern);
- }
-}
-
-static void add_pattern(SslPatternList*& list, uint8_t* pattern_str, size_t
- pattern_size, uint8_t type, AppId app_id, bool is_cname, bool is_literal, CnameCache& set)
-{
- SslPatternList* new_ssl_pattern;
-
- new_ssl_pattern = (SslPatternList*)snort_calloc(sizeof(SslPatternList));
- new_ssl_pattern->dpattern = (SslPattern*)snort_calloc(sizeof(SslPattern));
- new_ssl_pattern->dpattern->type = type;
- new_ssl_pattern->dpattern->app_id = app_id;
- new_ssl_pattern->dpattern->pattern = pattern_str;
- new_ssl_pattern->dpattern->pattern_size = pattern_size;
- new_ssl_pattern->dpattern->is_cname = is_cname;
- new_ssl_pattern->dpattern->is_literal = is_literal;
-
- new_ssl_pattern->next = list;
- list = new_ssl_pattern;
-
- if (is_cname)
- set.emplace(*(new_ssl_pattern->dpattern));
-}
-
-SslPatternMatchers::~SslPatternMatchers()
-{
- free_patterns(cert_pattern_list);
-}
-
-void SslPatternMatchers::add_cert_pattern(uint8_t* pattern_str, size_t pattern_size, uint8_t type, AppId app_id, bool is_cname, bool is_literal)
-{
- add_pattern(cert_pattern_list, pattern_str, pattern_size, type, app_id, is_cname, is_literal, cert_pattern_set);
-}
-
-void SslPatternMatchers::finalize_patterns()
-{
- create_matcher(ssl_host_matcher, cert_pattern_list, cert_pattern_set, pattern_count);
- cert_pattern_set.clear();
-}
-
-void SslPatternMatchers::reload_patterns()
-{
- ssl_host_matcher.reload();
-}
-
-unsigned SslPatternMatchers::get_pattern_count()
-{
- return pattern_count;
-}
-
-bool SslPatternMatchers::scan_hostname(const uint8_t* hostname, size_t size, AppId& client_id, AppId& payload_id)
-{
- return scan_patterns(ssl_host_matcher, hostname, size, client_id, payload_id, false);
-}
-
-bool SslPatternMatchers::scan_cname(const uint8_t* common_name, size_t size, AppId& client_id, AppId& payload_id)
-{
- return scan_patterns(ssl_host_matcher, common_name, size, client_id, payload_id, true);
-}
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2020-2025 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.
-//--------------------------------------------------------------------------
-
-// ssl_patterns.h author Shravan Rangaraju <shrarang@cisco.com>
-
-#ifndef SSL_PATTERNS_H
-#define SSL_PATTERNS_H
-
-#include <cstring>
-#include <unordered_set>
-#include "search_engines/search_tool.h"
-#include "application_ids.h"
-
-struct SslPattern
-{
- uint8_t type;
- AppId app_id;
- uint8_t* pattern;
- int pattern_size;
- bool is_cname;
- bool is_literal; // is not regex pattern
-
- bool operator==(const SslPattern& v) const
- {
- return this->type == v.type and pattern_size == v.pattern_size
- and (memcmp(pattern, v.pattern, (size_t)pattern_size) == 0);
- }
-};
-
-struct SslCacheKeyHasher
-{
- size_t operator()(const SslPattern& key) const
- {
- return std::hash<std::string>{}(std::string((char*)key.pattern, key.pattern_size));
- }
-};
-
-typedef std::unordered_set<SslPattern, SslCacheKeyHasher> CnameCache;
-
-struct MatchedSslPatterns
-{
- SslPattern* mpattern;
- int match_start_pos;
- struct MatchedSslPatterns* next;
-};
-
-struct SslPatternList
-{
- SslPattern* dpattern;
- SslPatternList* next;
-};
-
-class SslPatternMatchers
-{
-public:
- ~SslPatternMatchers();
- void add_cert_pattern(uint8_t*, size_t, uint8_t, AppId, bool, bool = true);
- void finalize_patterns();
- void reload_patterns();
- unsigned get_pattern_count();
- bool scan_hostname(const uint8_t*, size_t, AppId&, AppId&);
- bool scan_cname(const uint8_t*, size_t, AppId&, AppId&);
-
-private:
- SslPatternList* cert_pattern_list = nullptr;
- CnameCache cert_pattern_set;
- snort::SearchTool ssl_host_matcher = snort::SearchTool();
- unsigned pattern_count = 0;
-};
-
-#endif
DnsPatternMatchers::~DnsPatternMatchers() = default;
EveCaPatternMatchers::~EveCaPatternMatchers() = default;
-SslPatternMatchers::~SslPatternMatchers() = default;
+HostPatternMatchers::~HostPatternMatchers() = default;
HttpPatternMatchers::~HttpPatternMatchers() = default;
AlpnPatternMatchers::~AlpnPatternMatchers() = default;
CipPatternMatchers::~CipPatternMatchers() = default;
DnsPatternMatchers::~DnsPatternMatchers() = default;
EveCaPatternMatchers::~EveCaPatternMatchers() = default;
SipPatternMatchers::~SipPatternMatchers() = default;
-SslPatternMatchers::~SslPatternMatchers() = default;
+HostPatternMatchers::~HostPatternMatchers() = default;
AlpnPatternMatchers::~AlpnPatternMatchers() = default;
UserDataMap::~UserDataMap() = default;
CipPatternMatchers::~CipPatternMatchers() = default;
+bool HostPatternMatchers::scan_url(const uint8_t*, size_t, AppId&, AppId&, bool*){ return true; }
void AppIdModule::reset_stats() {}
bool AppIdInspector::configure(snort::SnortConfig*) { return true; }
void appid_log(const snort::Packet*, unsigned char, char const*, ...) { }
+void HostPatternMatchers::add_host_pattern(unsigned char const*, unsigned long, unsigned char, int, int, HostPatternType, bool, bool) {}
TEST_GROUP(http_url_patterns_tests)
{
}
uint32_t app_id = lua_tointeger(L, ++index);
- DetectorHTTPPattern pattern;
- if (pattern.init(pattern_str, pattern_size, seq, service_id, client_id,
- payload_id, app_id))
+ if (pat_type != HTTP_USER_AGENT)
{
- ud->get_odp_ctxt().get_http_matchers().insert_http_pattern(pat_type, pattern);
- aim.set_app_info_active(service_id);
- aim.set_app_info_active(client_id);
- aim.set_app_info_active(payload_id);
- aim.set_app_info_active(app_id);
+ ud->get_odp_ctxt().get_host_matchers().add_host_pattern(pattern_str, pattern_size, 0, client_id,
+ payload_id, HostPatternType::HOST_PATTERN_TYPE_URL, true, ud->get_odp_ctxt().get_app_info_mgr().get_app_info_flags(payload_id, APPINFO_FLAG_REFERRED));
+ }
+ else
+ {
+ DetectorHTTPPattern pattern;
+ if (pattern.init(pattern_str, pattern_size, seq, service_id, client_id,
+ payload_id, app_id))
+ {
+ ud->get_odp_ctxt().get_http_matchers().insert_http_pattern(pat_type, pattern);
+ aim.set_app_info_active(service_id);
+ aim.set_app_info_active(client_id);
+ aim.set_app_info_active(payload_id);
+ aim.set_app_info_active(app_id);
+ }
}
return 0;
return 0;
}
- uint8_t* pattern_str = (uint8_t*)snort_strdup(tmp_string);
- ud->get_odp_ctxt().get_ssl_matchers().add_cert_pattern(pattern_str, pattern_size, type, app_id,
- false);
+ ud->get_odp_ctxt().get_host_matchers().add_host_pattern((const uint8_t*)tmp_string, pattern_size, type, type ? app_id : 0, !type ? app_id : 0,
+ HostPatternType::HOST_PATTERN_TYPE_SNI);
ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(app_id);
return 0;
return 0;
}
- uint8_t* pattern_str = (uint8_t*)snort_strdup(tmp_string);
- ud->get_odp_ctxt().get_ssl_matchers().add_cert_pattern(pattern_str, pattern_size, type, app_id,
- false, false);
+ ud->get_odp_ctxt().get_host_matchers().add_host_pattern((const uint8_t*)tmp_string, pattern_size, type, type ? app_id : 0, !type ? app_id : 0,
+ HostPatternType::HOST_PATTERN_TYPE_SNI, false);
ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(app_id);
return 0;
return 0;
}
- uint8_t* pattern_str = (uint8_t*)snort_strdup(tmp_string);
- ud->get_odp_ctxt().get_ssl_matchers().add_cert_pattern(pattern_str, pattern_size, type, app_id,
- true);
+ ud->get_odp_ctxt().get_host_matchers().add_host_pattern((const uint8_t*)tmp_string, pattern_size, type, type ? app_id : 0, !type ? app_id : 0,
+ HostPatternType::HOST_PATTERN_TYPE_CNAME);
ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(app_id);
return 0;
return 0;
}
- uint8_t* pattern_str = (uint8_t*)snort_strdup(tmp_string);
- ud->get_odp_ctxt().get_ssl_matchers().add_cert_pattern(pattern_str, pattern_size, type, app_id,
- true, false);
+ ud->get_odp_ctxt().get_host_matchers().add_host_pattern((const uint8_t*)tmp_string, pattern_size, type, type ? app_id : 0, !type ? app_id : 0,
+ HostPatternType::HOST_PATTERN_TYPE_CNAME, false);
ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(app_id);
return 0;
size_t path_pattern_size = 0;
uint8_t* path_pattern = nullptr;
tmp_string = lua_tolstring(L, ++index, &path_pattern_size);
- if (!tmp_string or !path_pattern_size)
+ if (tmp_string and path_pattern_size)
{
- APPID_LOG(nullptr, TRACE_ERROR_LEVEL, "appid: Invalid path pattern string: service_id %u; "
- "client_id %u; payload %u.\n", service_id, client_id, payload_id);
- snort_free(host_pattern);
- return 0;
- }
- else
path_pattern = (uint8_t*)snort_strdup(tmp_string);
-
- /* Verify that scheme pattern is a valid string */
- size_t schemePatternSize;
- uint8_t* schemePattern = nullptr;
- tmp_string = lua_tolstring(L, ++index, &schemePatternSize);
- if (!tmp_string or !schemePatternSize)
- {
- APPID_LOG(nullptr, TRACE_ERROR_LEVEL, "appid: Invalid scheme pattern string: service_id %u; "
- "client_id %u; payload %u.\n", service_id, client_id, payload_id);
- snort_free(path_pattern);
- snort_free(host_pattern);
- return 0;
}
- else
- schemePattern = (uint8_t*)snort_strdup(tmp_string);
+
+ ++index;
/* Verify that query pattern is a valid string */
size_t query_pattern_size;
uint32_t appId = lua_tointeger(L, ++index);
AppInfoManager& app_info_manager = ud->get_odp_ctxt().get_app_info_mgr();
- DetectorAppUrlPattern* pattern =
- (DetectorAppUrlPattern*)snort_calloc(sizeof(DetectorAppUrlPattern));
- pattern->userData.service_id = app_info_manager.get_appid_by_service_id(service_id);
- pattern->userData.client_id = app_info_manager.get_appid_by_client_id(client_id);
- pattern->userData.payload_id = app_info_manager.get_appid_by_payload_id(payload_id);
- pattern->userData.appId = appId;
- pattern->userData.query.pattern = query_pattern;
- pattern->userData.query.patternSize = query_pattern_size;
- pattern->patterns.host.pattern = host_pattern;
- pattern->patterns.host.patternSize = (int)host_pattern_size;
- pattern->patterns.path.pattern = path_pattern;
- pattern->patterns.path.patternSize = (int)path_pattern_size;
- pattern->patterns.scheme.pattern = schemePattern;
- pattern->patterns.scheme.patternSize = (int)schemePatternSize;
- pattern->is_literal = true;
- ud->get_odp_ctxt().get_http_matchers().insert_url_pattern(pattern);
- app_info_manager.set_app_info_active(pattern->userData.service_id);
- app_info_manager.set_app_info_active(pattern->userData.client_id);
- app_info_manager.set_app_info_active(pattern->userData.payload_id);
- app_info_manager.set_app_info_active(appId);
+ if ( query_pattern or ( path_pattern and ( path_pattern_size > 1 )) )
+ {
+ DetectorAppUrlPattern* pattern =
+ (DetectorAppUrlPattern*)snort_calloc(sizeof(DetectorAppUrlPattern));
+ pattern->userData.service_id = app_info_manager.get_appid_by_service_id(service_id);
+ pattern->userData.client_id = app_info_manager.get_appid_by_client_id(client_id);
+ pattern->userData.payload_id = app_info_manager.get_appid_by_payload_id(payload_id);
+ pattern->userData.appId = appId;
+ pattern->userData.query.pattern = query_pattern;
+ pattern->userData.query.patternSize = query_pattern_size;
+ pattern->patterns.host.pattern = host_pattern;
+ pattern->patterns.host.patternSize = (int)host_pattern_size;
+ pattern->patterns.path.pattern = path_pattern;
+ pattern->patterns.path.patternSize = (int)path_pattern_size;
+ pattern->is_literal = true;
+ ud->get_odp_ctxt().get_http_matchers().insert_url_pattern(pattern);
+ }
+ else
+ {
+ AppId linked_payload_id = app_info_manager.get_appid_by_payload_id(payload_id);
+ ud->get_odp_ctxt().get_host_matchers().add_host_pattern((const uint8_t*)host_pattern, host_pattern_size, 0,
+ app_info_manager.get_appid_by_client_id(client_id), linked_payload_id, HostPatternType::HOST_PATTERN_TYPE_URL, true,
+ ud->get_odp_ctxt().get_app_info_mgr().get_app_info_flags(linked_payload_id, APPINFO_FLAG_REFERRED));
+ snort_free(host_pattern);
+ snort_free(path_pattern);
+ snort_free(query_pattern);
+ }
+
+ ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(appId);
return 0;
}
static int detector_add_url_application_regex(lua_State* L)
{
- // Verify detector user data and that we are NOT in packet context
+ // Verify detector user data and that we are NOT in packet context
auto& ud = *UserData<LuaObject>::check(L, DETECTOR, 1);
ud->validate_lua_state(false);
if (!init(L))
return 0;
}
-
int index = 1;
uint32_t service_id = lua_tointeger(L, ++index);
const char* tmp_string = lua_tolstring(L, ++index, &host_pattern_size);
if (!tmp_string or !host_pattern_size)
{
- APPID_LOG(nullptr, TRACE_ERROR_LEVEL, "appid: Invalid host regex pattern string: service_id %u; "
+ APPID_LOG(nullptr, TRACE_ERROR_LEVEL, "appid: Invalid host pattern string: service_id %u; "
"client_id %u; payload_id %u.\n", service_id, client_id, payload_id);
return 0;
}
size_t path_pattern_size = 0;
uint8_t* path_pattern = nullptr;
tmp_string = lua_tolstring(L, ++index, &path_pattern_size);
- if (!tmp_string or !path_pattern_size)
+ if (tmp_string and path_pattern_size)
{
- APPID_LOG(nullptr, TRACE_ERROR_LEVEL, "appid: Invalid path regex pattern string: service_id %u; "
- "client_id %u; payload %u.\n", service_id, client_id, payload_id);
- snort_free(host_pattern);
- return 0;
- }
- else
path_pattern = (uint8_t*)snort_strdup(tmp_string);
-
- /* Verify that scheme pattern is a valid string */
- size_t schemePatternSize;
- uint8_t* schemePattern = nullptr;
- tmp_string = lua_tolstring(L, ++index, &schemePatternSize);
- if (!tmp_string or !schemePatternSize)
- {
- APPID_LOG(nullptr, TRACE_ERROR_LEVEL, "appid: Invalid scheme regex pattern string: service_id %u; "
- "client_id %u; payload %u.\n", service_id, client_id, payload_id);
- snort_free(path_pattern);
- snort_free(host_pattern);
- return 0;
}
- else
- schemePattern = (uint8_t*)snort_strdup(tmp_string);
+
+ ++index;
/* Verify that query pattern is a valid string */
size_t query_pattern_size;
query_pattern = (uint8_t*)snort_strdup(tmp_string);
uint32_t appId = lua_tointeger(L, ++index);
+
AppInfoManager& app_info_manager = ud->get_odp_ctxt().get_app_info_mgr();
- DetectorAppUrlPattern* pattern =
- (DetectorAppUrlPattern*)snort_calloc(sizeof(DetectorAppUrlPattern));
- pattern->userData.service_id = app_info_manager.get_appid_by_service_id(service_id);
- pattern->userData.client_id = app_info_manager.get_appid_by_client_id(client_id);
- pattern->userData.payload_id = app_info_manager.get_appid_by_payload_id(payload_id);
- pattern->userData.appId = appId;
- pattern->userData.query.pattern = query_pattern;
- pattern->userData.query.patternSize = query_pattern_size;
- pattern->patterns.host.pattern = host_pattern;
- pattern->patterns.host.patternSize = (int)host_pattern_size;
- pattern->patterns.path.pattern = path_pattern;
- pattern->patterns.path.patternSize = (int)path_pattern_size;
- pattern->patterns.scheme.pattern = schemePattern;
- pattern->patterns.scheme.patternSize = (int)schemePatternSize;
- pattern->is_literal = false;
- ud->get_odp_ctxt().get_http_matchers().insert_url_pattern(pattern);
- app_info_manager.set_app_info_active(pattern->userData.service_id);
- app_info_manager.set_app_info_active(pattern->userData.client_id);
- app_info_manager.set_app_info_active(pattern->userData.payload_id);
- app_info_manager.set_app_info_active(appId);
+ if ( query_pattern or ( path_pattern and ( path_pattern_size > 1 )) )
+ {
+ DetectorAppUrlPattern* pattern =
+ (DetectorAppUrlPattern*)snort_calloc(sizeof(DetectorAppUrlPattern));
+ pattern->userData.service_id = app_info_manager.get_appid_by_service_id(service_id);
+ pattern->userData.client_id = app_info_manager.get_appid_by_client_id(client_id);
+ pattern->userData.payload_id = app_info_manager.get_appid_by_payload_id(payload_id);
+ pattern->userData.appId = appId;
+ pattern->userData.query.pattern = query_pattern;
+ pattern->userData.query.patternSize = query_pattern_size;
+ pattern->patterns.host.pattern = host_pattern;
+ pattern->patterns.host.patternSize = (int)host_pattern_size;
+ pattern->patterns.path.pattern = path_pattern;
+ pattern->patterns.path.patternSize = (int)path_pattern_size;
+ pattern->is_literal = false;
+ ud->get_odp_ctxt().get_http_matchers().insert_url_pattern(pattern);
+ }
+ else
+ {
+ AppId linked_payload_id = app_info_manager.get_appid_by_payload_id(payload_id);
+ ud->get_odp_ctxt().get_host_matchers().add_host_pattern((const uint8_t*)host_pattern, host_pattern_size, 0,
+ app_info_manager.get_appid_by_client_id(client_id), linked_payload_id, HostPatternType::HOST_PATTERN_TYPE_URL, false,
+ ud->get_odp_ctxt().get_app_info_mgr().get_app_info_flags(linked_payload_id, APPINFO_FLAG_REFERRED));
+ snort_free(host_pattern);
+ snort_free(path_pattern);
+ snort_free(query_pattern);
+ }
+
+ ud->get_odp_ctxt().get_app_info_mgr().set_app_info_active(appId);
return 0;
}
AlpnPatternMatchers::~AlpnPatternMatchers() {}
EveCaPatternMatchers::~EveCaPatternMatchers() { }
-SslPatternMatchers::~SslPatternMatchers() { }
+HostPatternMatchers::~HostPatternMatchers() { }
SipPatternMatchers::~SipPatternMatchers() { }
HttpPatternMatchers::~HttpPatternMatchers() { }
DnsPatternMatchers::~DnsPatternMatchers() { }
DataBus::publish(0, AppIdEventIds::ANY_CHANGE, app_event, p.flow);
}
-bool SslPatternMatchers::scan_hostname(const uint8_t* server_name, size_t, AppId& client_id, AppId& payload_id)
+bool HostPatternMatchers::scan_hostname(const uint8_t* server_name, size_t, AppId& client_id, AppId& payload_id)
{
if (((const char*)server_name) == APPID_UT_TLS_HOST)
{
return true;
}
-bool SslPatternMatchers::scan_cname(const uint8_t* cname, size_t, AppId& client_id, AppId& payload_id)
+bool HostPatternMatchers::scan_cname(const uint8_t* cname, size_t, AppId& client_id, AppId& payload_id)
{
if (((const char*)cname) == APPID_UT_TLS_HOST)
{
EveCaPatternMatchers::~EveCaPatternMatchers() = default;
HttpPatternMatchers::~HttpPatternMatchers() = default;
SipPatternMatchers::~SipPatternMatchers() = default;
-SslPatternMatchers::~SslPatternMatchers() = default;
+HostPatternMatchers::~HostPatternMatchers() = default;
AlpnPatternMatchers::~AlpnPatternMatchers() = default;
CipPatternMatchers::~CipPatternMatchers() = default;
UserDataMap::~UserDataMap() = default;
return;
}
-bool SslPatternMatchers::scan_hostname(const uint8_t*, size_t, AppId&, AppId& payload)
+bool HostPatternMatchers::scan_hostname(const uint8_t*, size_t, AppId&, AppId& payload)
{
payload = APPID_UT_ID + 1;
return true;
EveCaPatternMatchers::~EveCaPatternMatchers() = default;
HttpPatternMatchers::~HttpPatternMatchers() = default;
SipPatternMatchers::~SipPatternMatchers() = default;
-SslPatternMatchers::~SslPatternMatchers() = default;
+HostPatternMatchers::~HostPatternMatchers() = default;
AlpnPatternMatchers::~AlpnPatternMatchers() = default;
CipPatternMatchers::~CipPatternMatchers() = default;
UserDataMap::~UserDataMap() = default;
EveCaPatternMatchers::~EveCaPatternMatchers() = default;
HttpPatternMatchers::~HttpPatternMatchers() = default;
SipPatternMatchers::~SipPatternMatchers() = default;
-SslPatternMatchers::~SslPatternMatchers() = default;
+HostPatternMatchers::~HostPatternMatchers() = default;
AlpnPatternMatchers::~AlpnPatternMatchers() = default;
CipPatternMatchers::~CipPatternMatchers() = default;
UserDataMap::~UserDataMap() = default;
EveCaPatternMatchers::~EveCaPatternMatchers() = default;
HttpPatternMatchers::~HttpPatternMatchers() = default;
SipPatternMatchers::~SipPatternMatchers() = default;
-SslPatternMatchers::~SslPatternMatchers() = default;
+HostPatternMatchers::~HostPatternMatchers() = default;
AlpnPatternMatchers::~AlpnPatternMatchers() = default;
CipPatternMatchers::~CipPatternMatchers() = default;
UserDataMap::~UserDataMap() = default;