};
static int compareMlmpPatterns(const void* p1, const void* p2);
-static int createTreesRecusively(tMlmpTree* root);
+static int createTreesRecursively(tMlmpTree* root);
static void destroyTreesRecursively(tMlmpTree* root);
static int addPatternRecursively(tMlmpTree* root, const tMlmpPattern* inputPatternList,
void* metaData, uint32_t level);
{
int rvalue;
- rvalue = createTreesRecusively(root);
+ rvalue = createTreesRecursively(root);
if (rvalue)
destroyTreesRecursively(root);
return rvalue;
/*pattern trees are not freed on error because in case of error, caller should call
detroyTreesRecursively. */
-static int createTreesRecusively(tMlmpTree* rootNode)
+static int createTreesRecursively(tMlmpTree* rootNode)
{
SearchTool* patternMatcher;
tPatternPrimaryNode* primaryPatternNode;
/*recursion into next lower level */
if (primaryPatternNode->nextLevelMatcher)
{
- if (createTreesRecusively(primaryPatternNode->nextLevelMatcher))
+ if (createTreesRecursively(primaryPatternNode->nextLevelMatcher))
return -1;
}
ddPatternNode = ddPatternNode->nextPattern)
{
patternMatcher->add(ddPatternNode->pattern.pattern,
- ddPatternNode->pattern.patternSize, ddPatternNode, true);
+ ddPatternNode->pattern.patternSize, ddPatternNode, true, ddPatternNode->pattern.is_literal);
}
}
tmpList;
tmpList = tmpList->next)
{
- if (tmpList->patternNode->patternId != patternId)
+ const tPatternNode& node = *tmpList->patternNode;
+ if (node.patternId != patternId)
{
/*first pattern */
/*skip incomplete pattern */
- if (tmpList->patternNode->partNum != 1)
+ if (node.partNum != 1)
continue;
/*new pattern started */
- patternId = tmpList->patternNode->patternId;
+ patternId = node.patternId;
currentPrimaryNode = tmpList->patternNode;
partNum = 0;
patternSize = 0;
}
- if (tmpList->patternNode->partNum == (partNum+1))
+ if (node.partNum == (partNum+1))
{
partNum++;
- patternSize += tmpList->patternNode->pattern.patternSize;
+ patternSize += node.pattern.patternSize;
}
- if (tmpList->patternNode->partTotal != partNum)
+ if (node.partTotal != partNum)
continue;
/*backward compatibility */
- if ((tmpList->patternNode->partTotal == 1)
+ if (node.pattern.is_literal && (node.partTotal == 1)
&& domain && !match_is_domain_pattern(tmpList, payload))
continue;
tmpPrimaryNode->patternNode.pattern.pattern = patterns->pattern;
tmpPrimaryNode->patternNode.pattern.patternSize = patterns->patternSize;
tmpPrimaryNode->patternNode.pattern.level = patterns->level;
+ tmpPrimaryNode->patternNode.pattern.is_literal = patterns->is_literal;
tmpPrimaryNode->patternNode.partNum = 1;
tmpPrimaryNode->patternNode.partTotal = partTotal;
tmpPrimaryNode->patternNode.patternId = patternId;
newNode->pattern.pattern = patterns->pattern;
newNode->pattern.patternSize = patterns->patternSize;
newNode->pattern.level = patterns->level;
+ newNode->pattern.is_literal = patterns->is_literal;
newNode->partNum = partNum;
newNode->partTotal = partTotal;
newNode->patternId = patternId;
/**level of pattern. It should start from 0.*/
uint32_t level;
+ bool is_literal;
};
struct tMlmpTree;
tMlmpPattern patterns[PATTERN_PART_MAX];
int num_patterns = parse_multiple_http_patterns((const char*)pattern.pattern, patterns,
- PATTERN_PART_MAX, 0);
+ PATTERN_PART_MAX, 0, true);
patterns[num_patterns].pattern = nullptr;
return mlmpAddPattern(matcher, patterns, detector);
}
tMlmpPattern patterns[PATTERN_PART_MAX];
int num_patterns = parse_multiple_http_patterns((const char*)pattern.patterns.host.pattern,
- patterns, PATTERN_PART_MAX, 0);
+ patterns, PATTERN_PART_MAX, 0, pattern.is_literal);
if (pattern.patterns.path.pattern)
num_patterns += parse_multiple_http_patterns((const char*)pattern.patterns.path.pattern,
- patterns + num_patterns, PATTERN_PART_MAX - num_patterns, 1);
+ patterns + num_patterns, PATTERN_PART_MAX - num_patterns, 1, pattern.is_literal);
patterns[num_patterns].pattern = nullptr;
return mlmpAddPattern(matcher, patterns, detector);
}
uint32_t HttpPatternMatchers::parse_multiple_http_patterns(const char* pattern,
- tMlmpPattern* parts, uint32_t numPartLimit, int level)
+ tMlmpPattern* parts, uint32_t numPartLimit, int level, bool is_literal)
{
uint32_t partNum = 0;
tmp = nullptr;
}
parts[partNum].level = level;
+ parts[partNum].is_literal = is_literal;
if ( !parts[partNum].pattern )
{
} patterns;
UrlUserData userData;
+ bool is_literal;
};
// These values are used in Lua code as raw numbers. Do NOT reassign new values.
void get_server_vendor_version(const char*, int, char**, char**, AppIdServiceSubtype**);
void identify_user_agent(const char*, int, AppId&, AppId&, char**);
uint32_t parse_multiple_http_patterns(const char* pattern, tMlmpPattern*,
- uint32_t numPartLimit, int level);
+ uint32_t numPartLimit, int level, bool is_literal);
private:
DetectorHTTPPatterns client_agent_patterns;
{
pattern_count++;
num_patterns = odp_ctxt.get_http_matchers().parse_multiple_http_patterns(
- (const char*)pattern_node->pattern.pattern, patterns, PATTERN_PART_MAX, 0);
+ (const char*)pattern_node->pattern.pattern, patterns, PATTERN_PART_MAX, 0, true);
patterns[num_patterns].pattern = nullptr;
mlmpAddPattern(sip_ua_matcher, patterns, pattern_node);
{
pattern_count++;
num_patterns = odp_ctxt.get_http_matchers().parse_multiple_http_patterns(
- (const char*)pattern_node->pattern.pattern, patterns, PATTERN_PART_MAX, 0);
+ (const char*)pattern_node->pattern.pattern, patterns, PATTERN_PART_MAX, 0, true);
patterns[num_patterns].pattern = nullptr;
mlmpAddPattern(sip_server_matcher, patterns, pattern_node);
private:
static const int PATTERN_PART_MAX = 10;
- tMlmpPattern patterns[PATTERN_PART_MAX] = { { nullptr, 0, 0 } };
+ tMlmpPattern patterns[PATTERN_PART_MAX] = { { nullptr, 0, 0, true } };
tMlmpTree* sip_ua_matcher = nullptr;
DetectorAppSipPattern* sip_ua_list = nullptr;
tMlmpTree* sip_server_matcher = nullptr;
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);
+
+ return 0;
+}
+
+static int detector_add_url_application_regex(lua_State* L)
+{
+ // 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;
+
+ const FastPatternConfig* const fp = SnortConfig::get_conf()->fast_pattern_config;
+ if (!MpseManager::is_regex_capable(fp->get_search_api())){
+ appid_log(nullptr, TRACE_WARNING_LEVEL, "WARNING: appid: Regex patterns require usage of "
+ "regex capable search engine like hyperscan in %s\n", ud->get_detector()->get_name().c_str());
+ return 0;
+ }
+
+
+ int index = 1;
+
+ uint32_t service_id = lua_tointeger(L, ++index);
+ uint32_t client_id = lua_tointeger(L, ++index);
+ lua_tointeger(L, ++index); //client_id_type
+ uint32_t payload_id = lua_tointeger(L, ++index);
+ lua_tointeger(L, ++index); // payload_type
+
+ /* Verify that host pattern is a valid string */
+ size_t host_pattern_size = 0;
+ uint8_t* host_pattern = nullptr;
+ 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; "
+ "client_id %u; payload_id %u.\n", service_id, client_id, payload_id);
+ return 0;
+ }
+ else
+ host_pattern = (uint8_t*)snort_strdup(tmp_string);
+
+ /* Verify that path pattern is a valid string */
+ 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)
+ {
+ 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);
+
+ /* Verify that query pattern is a valid string */
+ size_t query_pattern_size;
+ uint8_t* query_pattern = nullptr;
+ tmp_string = lua_tolstring(L, ++index, &query_pattern_size);
+ if (tmp_string and 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);
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_rtmp_url_pattern(pattern);
AppInfoManager& app_info_manager = ud->get_odp_ctxt().get_app_info_mgr();
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_app_url_pattern(pattern);
AppInfoManager& app_info_manager = ud->get_odp_ctxt().get_app_info_mgr();
{ "cLog", detector_log_snort_message},
{ "addHttpPattern", detector_add_http_pattern },
{ "addAppUrl", detector_add_url_application },
+ { "addAppUrlRegex", detector_add_url_application_regex },
{ "addRTMPUrl", detector_add_rtmp_url },
{ "addContentTypePattern", detector_add_content_type_pattern },
{ "addSSLCertPattern", detector_add_ssl_cert_pattern },