From: Russ Combs (rucombs) Date: Thu, 21 Apr 2022 12:27:01 +0000 (+0000) Subject: Pull request #3373: ips_bag2 X-Git-Tag: 3.1.28.0~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d3570c2b6351fb18348e2444a5c358146170720;p=thirdparty%2Fsnort3.git Pull request #3373: ips_bag2 Merge in SNORT/snort3 from ~RUCOMBS/snort3:ips_bag2 to master Squashed commit of the following: commit faebae4e783ceb1e110663326756a87ba83510fe Author: russ Date: Thu Apr 14 11:26:01 2022 -0400 mms_data: make a fast pattern buffer Also some minor refactoring of related framework code. commit aca6b04e9c610ecff216e28c549176a1f5962aa4 Author: russ Date: Tue Apr 12 13:31:08 2022 -0400 ips_options: eliminate obsolete RULE_OPTION_TYPE_BUFFER_* commit 75469d9cb9528a1952390d961a32199653678a3e Author: russ Date: Mon Apr 11 16:26:00 2022 -0400 conf: add cip and s7commplus to the default snort.lua commit ed2856e6e08ef74187dda09c095177f8fd5fcd18 Author: russ Date: Sun Apr 10 16:03:51 2022 -0400 raw_data: only search pkt_data if no alt buffer or raw_data rules included in group commit f3d69b64eba4a520d2d782f2b4507ddb4f42d7f3 Author: russ Date: Sat Apr 9 22:13:44 2022 -0400 detection: remove now obsolete get buf support The only remaining inspection buffer provided by multiple inspectors is vba_data. pkt_data and file_data are pushed to the detection engine. alt_data is pushed as well but is used where pkt_data is used. All other buffers are provided by solely by individual inspector ips options. (http2 just internally uses http_* buffers.) commit f79e200c64a8de929764cded5dc10f8022fd429b Author: russ Date: Fri Apr 8 18:27:40 2022 -0400 ips: eliminate direct dependence on get_fp_buf of all ibt (by using rule options) commit e54fa287fd110a6d7634ed22d9fcd43297b6490c Author: russ Date: Fri Apr 8 06:08:01 2022 -0400 service inspectors: update fast pattern access commit 9d6477ebb015e2ddfdcf80aece115da3d21867b0 Author: russ Date: Fri Apr 8 02:59:57 2022 -0400 detection: rearrange startup rule counts commit d22ea5aeda36790a229a24226e9a5a5c509fc057 Author: russ Date: Thu Apr 7 15:49:47 2022 -0400 ips: eliminate PM_TYPE_* to make fast pattern buffers generic commit a49cd8f04e54c86228e45e3316c2f06769782fe2 Author: russ Date: Wed Apr 6 16:52:20 2022 -0400 detection: add missing fast pattern buffer translations commit 1ba179ea66d4050f3c57bd1d3fcc884106b08409 Author: russ Date: Tue Apr 5 17:53:12 2022 -0400 inspectors: add / update api buffer lists commit 127236881855c6230d413acdbae95320fbacf80c Author: russ Date: Tue Apr 5 17:52:12 2022 -0400 bufferlen: add missing relative override commit 774a078e38b90fa610d70a3663383a260d8361f9 Author: russ Date: Mon Apr 4 10:09:04 2022 -0400 ips_options: fix cursor action type overrides commit 07fbe66bba3a81f4f8dbe3e8dcb4a351b22344b1 Author: russ Date: Mon Apr 4 08:41:42 2022 -0400 detection: make CursorActionType generic commit c7063241d67718633e5c533ea49ab9defd736f1e Author: russ Date: Mon Apr 4 07:18:46 2022 -0400 detection: map buffers to services commit 0837fc34448a36c6a817491c916cda319e335112 Author: russ Date: Sun Apr 3 07:13:10 2022 -0400 ips: further limit port group rules Rules with buffers that imply services go only in service groups. commit eba1ff1bad596d1222b1dc934235ad29c929445a Author: russ Date: Sun Apr 3 07:10:30 2022 -0400 content: auto no-case non-alpha patterns --- diff --git a/lua/snort.lua b/lua/snort.lua index 24d984370..d8c037eb3 100644 --- a/lua/snort.lua +++ b/lua/snort.lua @@ -52,12 +52,8 @@ stream_file = { } arp_spoof = { } back_orifice = { } -dnp3 = { } dns = { } imap = { } -iec104 = { } -mms = { } -modbus = { } netflow = {} normalizer = { } pop = { } @@ -67,6 +63,13 @@ ssh = { } ssl = { } telnet = { } +cip = { } +dnp3 = { } +iec104 = { } +mms = { } +modbus = { } +s7commplus = { } + dce_smb = { } dce_tcp = { } dce_udp = { } @@ -119,19 +122,23 @@ binder = -- port bindings required for protocols without wizard support { when = { proto = 'udp', ports = '53', role='server' }, use = { type = 'dns' } }, { when = { proto = 'tcp', ports = '53', role='server' }, use = { type = 'dns' } }, + { when = { proto = 'tcp', ports = '102', role = 'server' }, use = { type = 's7commplus' } }, { when = { proto = 'tcp', ports = '111', role='server' }, use = { type = 'rpc_decode' } }, { when = { proto = 'tcp', ports = '502', role='server' }, use = { type = 'modbus' } }, { when = { proto = 'tcp', ports = '2123 2152 3386', role='server' }, use = { type = 'gtp_inspect' } }, { when = { proto = 'tcp', ports = '2404', role='server' }, use = { type = 'iec104' } }, + { when = { proto = 'udp', ports = '22222', role = 'server' }, use = { type = 'cip' } }, + { when = { proto = 'tcp', ports = '44818', role = 'server' }, use = { type = 'cip' } }, - { when = { proto = 'tcp', service = 'dcerpc' }, use = { type = 'dce_tcp' } }, - { when = { proto = 'udp', service = 'dcerpc' }, use = { type = 'dce_udp' } }, + { when = { proto = 'tcp', service = 'dcerpc' }, use = { type = 'dce_tcp' } }, + { when = { proto = 'udp', service = 'dcerpc' }, use = { type = 'dce_udp' } }, { when = { proto = 'udp', service = 'netflow' }, use = { type = 'netflow' } }, { when = { service = 'netbios-ssn' }, use = { type = 'dce_smb' } }, { when = { service = 'dce_http_server' }, use = { type = 'dce_http_server' } }, { when = { service = 'dce_http_proxy' }, use = { type = 'dce_http_proxy' } }, + { when = { service = 'cip' }, use = { type = 'cip' } }, { when = { service = 'dnp3' }, use = { type = 'dnp3' } }, { when = { service = 'dns' }, use = { type = 'dns' } }, { when = { service = 'ftp' }, use = { type = 'ftp_server' } }, @@ -149,6 +156,7 @@ binder = { when = { service = 'smtp' }, use = { type = 'smtp' } }, { when = { service = 'ssl' }, use = { type = 'ssl' } }, { when = { service = 'sunrpc' }, use = { type = 'rpc_decode' } }, + { when = { service = 's7commplus' }, use = { type = 's7commplus' } }, { when = { service = 'telnet' }, use = { type = 'telnet' } }, { use = { type = 'wizard' } } diff --git a/src/detection/detect_trace.cc b/src/detection/detect_trace.cc index 8b6c727e1..55fd00af5 100644 --- a/src/detection/detect_trace.cc +++ b/src/detection/detect_trace.cc @@ -32,6 +32,7 @@ #include "detection_options.h" #include "fp_create.h" +#include "fp_utils.h" #include "ips_context.h" #include "pattern_match_data.h" @@ -86,12 +87,11 @@ void print_pkt_info(Packet* p, const char* task) void print_pattern(const PatternMatchData* pmd, Packet* p) { string hex, txt, opts; + get_pattern_info(pmd, hex, txt, opts); - get_pattern_info(pmd, pmd->pattern_buf, pmd->pattern_size, hex, txt, opts); debug_logf(detection_trace, TRACE_RULE_EVAL, p, "Fast pattern %s[%u] = '%s' |%s| %s\n", - pm_type_strings[pmd->pm_type], pmd->pattern_size, - txt.c_str(), hex.c_str(), opts.c_str()); + pmd->sticky_buf, pmd->pattern_size, txt.c_str(), hex.c_str(), opts.c_str()); } void dump_buffer(const uint8_t* buff, unsigned len, Packet* p) diff --git a/src/detection/detection_options.cc b/src/detection/detection_options.cc index 81a515d60..e6dfa6538 100644 --- a/src/detection/detection_options.cc +++ b/src/detection/detection_options.cc @@ -607,22 +607,27 @@ int detection_option_node_evaluate( continue; } - else if ( node->option_type != RULE_OPTION_TYPE_BUFFER_SET ) + else { - // Check for an unbounded relative search. If this - // failed before, it's going to fail again so don't - // go down this path again - IpsOption* opt = (IpsOption*)child_node->option_data; - PatternMatchData* pmd = opt->get_pattern(0, RULE_WO_DIR); + IpsOption* opt = (IpsOption*)node->option_data; - if ( pmd and pmd->is_literal() and pmd->is_unbounded() ) + if ( !opt->is_buffer_setter() ) { - // Only increment result once. Should hit this - // condition on first loop iteration - if (loop_count == 1) - ++result; - - continue; + // Check for an unbounded relative search. If this + // failed before, it's going to fail again so don't + // go down this path again + opt = (IpsOption*)child_node->option_data; + PatternMatchData* pmd = opt->get_pattern(0, RULE_WO_DIR); + + if ( pmd and pmd->is_literal() and pmd->is_unbounded() ) + { + // Only increment result once. Should hit this + // condition on first loop iteration + if (loop_count == 1) + ++result; + + continue; + } } } } diff --git a/src/detection/fp_create.cc b/src/detection/fp_create.cc index e0bb5d7ed..57c99ff48 100644 --- a/src/detection/fp_create.cc +++ b/src/detection/fp_create.cc @@ -74,8 +74,7 @@ static int fpGetFinalPattern( FastPatternConfig*, PatternMatchData*, const char*& ret_pattern, unsigned& ret_bytes); static void print_nfp_info(const char*, OptTreeNode*); -static void print_fp_info(const char*, const OptTreeNode*, const PatternMatchData*, - const char* pattern, unsigned pattern_length); +static void print_fp_info(const char*, const OptTreeNode*, const PatternMatchData*); static OptTreeNode* fixup_tree( detection_option_tree_node_t* dot, bool branched, unsigned contents) @@ -435,8 +434,8 @@ static int fpFinishRuleGroupRule( pattern_length = pmd->pattern_size; } - if ( fp->get_debug_print_fast_patterns() and !otn->soid ) - print_fp_info(s_group, otn, pmd, pattern, pattern_length); + if (pmd->pattern_size > otn->longestPatternLen) + otn->longestPatternLen = pmd->pattern_size; PMX* pmx = (PMX*)snort_calloc(sizeof(PMX)); pmx->rule_node.rnRuleData = otn; @@ -450,56 +449,22 @@ static int fpFinishRuleGroupRule( return 0; } -static int fpFinishRuleGroup(SnortConfig* sc, RuleGroup* pg, FastPatternConfig* fp) +static int fpFinishRuleGroup(SnortConfig* sc, RuleGroup* pg) { - int rules = 0; + assert(pg); + bool has_rules = false; - if (pg == nullptr) - return -1; - - if (fp == nullptr) + for ( auto& it : pg->pm_list ) { - delete pg; - return -1; - } - - for (int i = PM_TYPE_PKT; i < PM_TYPE_MAX; i++) - { - if (pg->mpsegrp[i] != nullptr) + if ( it->group.normal_mpse ) { - if (pg->mpsegrp[i]->normal_mpse != nullptr) - { - if (pg->mpsegrp[i]->normal_mpse->get_pattern_count() != 0) - { - queue_mpse(pg->mpsegrp[i]->normal_mpse); - rules = 1; - } - else - { - MpseManager::delete_search_engine(pg->mpsegrp[i]->normal_mpse); - pg->mpsegrp[i]->normal_mpse = nullptr; - } - } - if (pg->mpsegrp[i]->offload_mpse != nullptr) - { - if (pg->mpsegrp[i]->offload_mpse->get_pattern_count() != 0) - { - queue_mpse(pg->mpsegrp[i]->offload_mpse); - rules = 1; - } - else - { - MpseManager::delete_search_engine(pg->mpsegrp[i]->offload_mpse); - pg->mpsegrp[i]->offload_mpse = nullptr; - } - } - - if ((pg->mpsegrp[i]->normal_mpse == nullptr) and - (pg->mpsegrp[i]->offload_mpse == nullptr)) - { - delete pg->mpsegrp[i]; - pg->mpsegrp[i] = nullptr; - } + queue_mpse(it->group.normal_mpse); + has_rules = true; + } + if ( it->group.offload_mpse ) + { + queue_mpse(it->group.offload_mpse); + has_rules = true; } } @@ -507,21 +472,20 @@ static int fpFinishRuleGroup(SnortConfig* sc, RuleGroup* pg, FastPatternConfig* { RULE_NODE* ruleNode; - for (ruleNode = pg->nfp_head; ruleNode; ruleNode = ruleNode->rnNext) + for ( ruleNode = pg->nfp_head; ruleNode; ruleNode = ruleNode->rnNext ) { OptTreeNode* otn = (OptTreeNode*)ruleNode->rnRuleData; otn_create_tree(otn, &pg->nfp_tree, Mpse::MPSE_TYPE_NORMAL); } finalize_detection_option_tree(sc, (detection_option_tree_root_t*)pg->nfp_tree); - rules = 1; + has_rules = true; pg->delete_nfp_rules(); } - if (!rules) + if ( !has_rules ) { - /* Nothing in the port group so we can just free it */ delete pg; return -1; } @@ -529,18 +493,11 @@ static int fpFinishRuleGroup(SnortConfig* sc, RuleGroup* pg, FastPatternConfig* return 0; } -static void fpAddAlternatePatterns( - Mpse* mpse, OptTreeNode* otn, PatternMatchData* pmd, FastPatternConfig* fp) -{ - fpFinishRuleGroupRule(mpse, otn, pmd, fp, false); -} - static int fpAddRuleGroupRule( SnortConfig* sc, RuleGroup* pg, OptTreeNode* otn, FastPatternConfig* fp, bool srvc) { const MpseApi* search_api = nullptr; const MpseApi* offload_search_api = nullptr; - OptFpList* ofp = nullptr; bool exclude; // skip builtin rules, continue for text and so rules @@ -553,13 +510,17 @@ static int fpAddRuleGroupRule( search_api = fp->get_search_api(); assert(search_api); + OptFpList* ofp = nullptr; + IpsOption* opt = nullptr; + bool only_literal = !MpseManager::is_regex_capable(search_api); - PatternMatchVector pmv = get_fp_content(otn, ofp, srvc, only_literal, exclude); + PatternMatchVector pmv = get_fp_content(otn, ofp, opt, srvc, only_literal, exclude); if ( !pmv.empty() ) { PatternMatchVector pmv_ol; OptFpList* ofp_ol = nullptr; + IpsOption* opt_ol = nullptr; bool add_to_offload = false; bool cont = true; PatternMatchData* ol_pmd = nullptr; @@ -568,22 +529,22 @@ static int fpAddRuleGroupRule( // Only add rule to the offload search engine if the offload search engine // is different to the normal search engine. - if (offload_search_api and (offload_search_api != search_api)) + if ( offload_search_api and (offload_search_api != search_api) ) { bool exclude_ol; bool only_literal_ol = !MpseManager::is_regex_capable(offload_search_api); - pmv_ol = get_fp_content(otn, ofp_ol, srvc, only_literal_ol, exclude_ol); + pmv_ol = get_fp_content(otn, ofp_ol, opt_ol, srvc, only_literal_ol, exclude_ol); // If we can get a fast_pattern for the normal search engine but not for the // offload search engine then add rule to the non fast pattern list - if (!pmv_ol.empty()) + if ( !pmv_ol.empty() ) add_to_offload = true; else cont = false; } // From here on we will create the mpses that are needed and add the patterns - if (cont) + if ( cont ) { PatternMatchData* main_pmd = pmv.back(); pmv.pop_back(); @@ -594,21 +555,23 @@ static int fpAddRuleGroupRule( fpDeletePMX, free_detection_option_root, neg_list_free }; - if ( !pg->mpsegrp[main_pmd->pm_type] ) - pg->mpsegrp[main_pmd->pm_type] = new MpseGroup; + const char* s = opt ? opt->get_name() : "pkt_data"; + auto pmt = get_pm_type(s); + PatternMatcher* pm = pg->get_pattern_matcher(pmt, s); + MpseGroup* mpg = &pm->group; - if ( !pg->mpsegrp[main_pmd->pm_type]->normal_mpse ) + if ( !mpg->normal_mpse ) { - if (!pg->mpsegrp[main_pmd->pm_type]->create_normal_mpse(sc, &agent)) + if ( !mpg->create_normal_mpse(sc, &agent) ) { - ParseError("Failed to create normal pattern matcher for %d", main_pmd->pm_type); + ParseError("Failed to create normal pattern matcher for %s", pm->name); return -1; } mpse_count++; } - if (add_to_offload) + if ( add_to_offload ) { ol_pmd = pmv_ol.back(); pmv_ol.pop_back(); @@ -620,12 +583,11 @@ static int fpAddRuleGroupRule( }; // Keep the created mpse alongside the same pm type as the main pmd - if ( !pg->mpsegrp[main_pmd->pm_type]->offload_mpse ) + if ( !mpg->offload_mpse ) { - if (!pg->mpsegrp[main_pmd->pm_type]->create_offload_mpse(sc, &agent_offload)) + if ( !mpg->create_offload_mpse(sc, &agent_offload) ) { - ParseError("Failed to create offload pattern matcher for %d", - main_pmd->pm_type); + ParseError("Failed to create offload pattern matcher for %s", pm->name); return -1; } @@ -636,55 +598,73 @@ static int fpAddRuleGroupRule( bool add_rule = false; bool add_nfp_rule = false; - if (pg->mpsegrp[main_pmd->pm_type]->normal_mpse) + if ( mpg->normal_mpse ) { add_rule = true; - if (main_pmd->is_negated()) + if ( main_pmd->is_negated() ) add_nfp_rule = true; // Now add patterns - if (fpFinishRuleGroupRule( - pg->mpsegrp[main_pmd->pm_type]->normal_mpse, otn, main_pmd, fp, true) == 0) + if ( fpFinishRuleGroupRule(mpg->normal_mpse, otn, main_pmd, fp, true) == 0 ) { - if (main_pmd->pattern_size > otn->longestPatternLen) - otn->longestPatternLen = main_pmd->pattern_size; - if ( make_fast_pattern_only(ofp, main_pmd) ) { otn->normal_fp_only = ofp; fp_only++; } + if ( !pm->fp_opt ) + pm->fp_opt = opt; + + main_pmd->sticky_buf = pm->name; + + if ( fp->get_debug_print_fast_patterns() and !otn->soid ) + print_fp_info(s_group, otn, main_pmd); + // Add Alternative patterns - for (auto p : pmv) - fpAddAlternatePatterns( - pg->mpsegrp[main_pmd->pm_type]->normal_mpse, otn, p, fp); + for ( auto alt_pmd : pmv ) + { + fpFinishRuleGroupRule(mpg->normal_mpse, otn, alt_pmd, fp, false); + alt_pmd->sticky_buf = pm->name; + + if ( fp->get_debug_print_fast_patterns() and !otn->soid ) + print_fp_info(s_group, otn, alt_pmd); + } } } - if (ol_pmd and pg->mpsegrp[main_pmd->pm_type]->offload_mpse) + if ( ol_pmd and mpg->offload_mpse ) { add_rule = true; - if (ol_pmd->is_negated()) + if ( ol_pmd->is_negated() ) add_nfp_rule = true; // Now add patterns - if (fpFinishRuleGroupRule( - pg->mpsegrp[main_pmd->pm_type]->offload_mpse, otn, ol_pmd, fp, true) == 0) + if ( fpFinishRuleGroupRule(mpg->offload_mpse, otn, ol_pmd, fp, true) == 0 ) { - if (ol_pmd->pattern_size > otn->longestPatternLen) - otn->longestPatternLen = ol_pmd->pattern_size; - if ( make_fast_pattern_only(ofp_ol, ol_pmd) ) { otn->offload_fp_only = ofp_ol; fp_only++; } + if ( !pm->fp_opt ) + pm->fp_opt = opt_ol; + + main_pmd->sticky_buf = pm->name; + + if ( fp->get_debug_print_fast_patterns() and !otn->soid ) + print_fp_info(s_group, otn, main_pmd); + // Add Alternative patterns - for (auto p : pmv_ol) - fpAddAlternatePatterns( - pg->mpsegrp[main_pmd->pm_type]->offload_mpse, otn, p, fp); + for (auto alt_pmd : pmv_ol) + { + fpFinishRuleGroupRule(mpg->offload_mpse, otn, alt_pmd, fp, false); + alt_pmd->sticky_buf = pm->name; + + if ( fp->get_debug_print_fast_patterns() and !otn->soid ) + print_fp_info(s_group, otn, alt_pmd); + } } } @@ -950,28 +930,18 @@ static int fpGetFinalPattern( static void fpRuleGroupPrintRuleCount(RuleGroup* pg, const char* what) { - int type; - - if (pg == nullptr) - return; - LogMessage("RuleGroup rule summary (%s):\n", what); - for (type = PM_TYPE_PKT; type < PM_TYPE_MAX; type++) + for ( auto& it : pg->pm_list ) { - if (pg->mpsegrp[type]) - { - int count = pg->mpsegrp[type]->normal_mpse ? - pg->mpsegrp[type]->normal_mpse->get_pattern_count() : 0; - int count_ol = pg->mpsegrp[type]->offload_mpse ? - pg->mpsegrp[type]->offload_mpse->get_pattern_count() : 0; + int count = it->group.normal_mpse ? it->group.normal_mpse->get_pattern_count() : 0; + int count_ol = it->group.offload_mpse ? it->group.offload_mpse->get_pattern_count() : 0; - if ( count ) - LogMessage("\tNormal Pattern Matcher %s: %d\n", pm_type_strings[type], count); + if ( count ) + LogMessage("\tNormal Pattern Matcher %s: %d\n", it->name, count); - if ( count_ol ) - LogMessage("\tOffload Pattern Matcher %s: %d\n", pm_type_strings[type], count_ol); - } + if ( count_ol ) + LogMessage("\tOffload Pattern Matcher %s: %d\n", it->name, count_ol); } if ( pg->nfp_rule_count ) @@ -1058,7 +1028,7 @@ static void fpCreatePortObject2RuleGroup(SnortConfig* sc, PortObject2* po, PortO } // This might happen if there was ip proto only rules...Don't return failure - if (fpFinishRuleGroup(sc, pg, fp) != 0) + if (fpFinishRuleGroup(sc, pg) != 0) return; po->group = pg; @@ -1238,7 +1208,7 @@ static void fpBuildServiceRuleGroupByServiceOtnList( fpAddRuleGroupRule(sc, pg, otn, fp, true); } - if (fpFinishRuleGroup(sc, pg, fp) != 0) + if (fpFinishRuleGroup(sc, pg) != 0) return; /* Add the port_group using it's service name */ @@ -1387,18 +1357,19 @@ static void fp_print_service_rules_by_proto(SnortConfig* sc) fp_print_service_rules(sc, sc->srmmTable->to_srv, sc->srmmTable->to_cli); } -static void fp_sum_port_groups(RuleGroup* pg, unsigned c[PM_TYPE_MAX]) +static void fp_sum_port_groups(RuleGroup* pg, unsigned& c) { if ( !pg ) return; - for ( int i = PM_TYPE_PKT; i < PM_TYPE_MAX; ++i ) - if ( pg->mpsegrp[i] and pg->mpsegrp[i]->normal_mpse and - pg->mpsegrp[i]->normal_mpse->get_pattern_count() ) - c[i]++; + for ( const auto& it : pg->pm_list ) + { + if ( it->group.normal_mpse and it->group.normal_mpse->get_pattern_count() ) + c++; + } } -static void fp_sum_service_groups(GHash* h, unsigned c[PM_TYPE_MAX]) +static void fp_sum_service_groups(GHash* h, unsigned& c) { for (GHashNode* node = h->find_first(); node; @@ -1409,31 +1380,22 @@ static void fp_sum_service_groups(GHash* h, unsigned c[PM_TYPE_MAX]) } } -static void fp_print_service_groups(srmm_table_t* srmm) +static void fp_print_service_groups(srmm_table_t* srmm, bool label) { - unsigned to_srv[PM_TYPE_MAX] = { }; - unsigned to_cli[PM_TYPE_MAX] = { }; + unsigned to_srv = 0; + unsigned to_cli = 0; fp_sum_service_groups(srmm->to_srv, to_srv); fp_sum_service_groups(srmm->to_cli, to_cli); - bool label = true; + if ( label and (to_srv or to_cli) ) + LogLabel("fast pattern groups"); - for ( int i = PM_TYPE_PKT; i < PM_TYPE_MAX; ++i ) - { - if ( !to_srv[i] and !to_cli[i] ) - continue; - - if ( label ) - { - LogLabel("fast pattern service groups to-srv to-cli"); - label = false; - } - LogMessage("%25.25s: %8u%8u\n", pm_type_strings[i], to_srv[i], to_cli[i]); - } + LogCount("to_server", to_srv); + LogCount("to_client", to_cli); } -static void fp_sum_port_groups(PortTable* tab, unsigned c[PM_TYPE_MAX]) +static void fp_sum_port_groups(PortTable* tab, unsigned& c) { for (GHashNode* node = tab->pt_mpo_hash->find_first(); node; @@ -1446,11 +1408,11 @@ static void fp_sum_port_groups(PortTable* tab, unsigned c[PM_TYPE_MAX]) PortTableFinalize(tab); } -static void fp_print_port_groups(RulePortTables* port_tables) +static bool fp_print_port_groups(RulePortTables* port_tables) { - unsigned src[PM_TYPE_MAX] = { }; - unsigned dst[PM_TYPE_MAX] = { }; - unsigned any[PM_TYPE_MAX] = { }; + unsigned src = 0; + unsigned dst = 0; + unsigned any = 0; fp_sum_port_groups(port_tables->ip.src, src); fp_sum_port_groups(port_tables->ip.dst, dst); @@ -1480,20 +1442,15 @@ static void fp_print_port_groups(RulePortTables* port_tables) PortObjectFinalize(port_tables->udp.any); PortObjectFinalize(port_tables->udp.nfp); - bool label = true; - - for ( int i = PM_TYPE_PKT; i < PM_TYPE_MAX; ++i ) + if ( src or dst or any ) { - if ( !src[i] and !dst[i] and !any[i] ) - continue; - - if ( label ) - { - LogLabel("fast pattern port groups src dst any"); - label = false; - } - LogMessage("%25.25s: %8u%8u%8u\n", pm_type_strings[i], src[i], dst[i], any[i]); + LogLabel("fast pattern groups"); + LogCount("src", src); + LogCount("dst", dst); + LogCount("any", any); + return true; } + return false; } /* @@ -1607,8 +1564,8 @@ int fpCreateFastPacketDetection(SnortConfig* sc) ParseError("Failed to compile %u search engines", expected - c); } - fp_print_port_groups(port_tables); - fp_print_service_groups(sc->spgmmTable); + bool label = fp_print_port_groups(port_tables); + fp_print_service_groups(sc->spgmmTable, !label); if ( !sc->rule_db_dir.empty() ) mpse_dumped = fp_serialize(sc, sc->rule_db_dir); @@ -1664,16 +1621,15 @@ static void print_nfp_info(const char* group, OptTreeNode* otn) otn->set_warned_fp(); } -void get_pattern_info(const PatternMatchData* pmd, - const char* pattern, int pattern_length, string& hex, string& txt, string& opts) +void get_pattern_info(const PatternMatchData* pmd, string& hex, string& txt, string& opts) { char buf[8]; - for ( int i = 0; i < pattern_length; ++i ) + for ( unsigned i = 0; i < pmd->pattern_size; ++i ) { - snprintf(buf, sizeof(buf), "%2.02X ", (uint8_t)pattern[i]); + snprintf(buf, sizeof(buf), "%2.02X ", (uint8_t)pmd->pattern_buf[i]); hex += buf; - txt += isprint(pattern[i]) ? pattern[i] : '.'; + txt += isprint(pmd->pattern_buf[i]) ? pmd->pattern_buf[i] : '.'; } opts = "("; if ( pmd->is_fast_pattern() ) @@ -1683,15 +1639,13 @@ void get_pattern_info(const PatternMatchData* pmd, opts += " )"; } -static void print_fp_info( - const char* group, const OptTreeNode* otn, const PatternMatchData* pmd, - const char* pattern, unsigned pattern_length) +static void print_fp_info(const char* group, const OptTreeNode* otn, const PatternMatchData* pmd) { std::string hex, txt, opts; - get_pattern_info(pmd, pattern, pattern_length, hex, txt, opts); + get_pattern_info(pmd, hex, txt, opts); LogMessage("FP %s %u:%u:%u %s[%d] = '%s' |%s| %s\n", group, otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, - pm_type_strings[pmd->pm_type], pattern_length, - txt.c_str(), hex.c_str(), opts.c_str()); + pmd->sticky_buf, pmd->pattern_size, txt.c_str(), hex.c_str(), opts.c_str()); } + diff --git a/src/detection/fp_create.h b/src/detection/fp_create.h index f5e76a4ed..2a4c01d43 100644 --- a/src/detection/fp_create.h +++ b/src/detection/fp_create.h @@ -55,9 +55,7 @@ struct NCListNode */ int fpCreateFastPacketDetection(snort::SnortConfig*); void fpDeleteFastPacketDetection(snort::SnortConfig*); -void get_pattern_info(const PatternMatchData* pmd, - const char* pattern, int pattern_length, std::string& hex, std::string& txt, - std::string& opts); +void get_pattern_info(const PatternMatchData* pmd, std::string& hex, std::string& txt, std::string& opts); #endif diff --git a/src/detection/fp_detect.cc b/src/detection/fp_detect.cc index 0cf5fb35d..e356ee8a5 100644 --- a/src/detection/fp_detect.cc +++ b/src/detection/fp_detect.cc @@ -75,6 +75,7 @@ #include "detection_options.h" #include "fp_config.h" #include "fp_create.h" +#include "fp_utils.h" #include "ips_context.h" #include "pattern_match_data.h" #include "pcrm.h" @@ -856,21 +857,21 @@ static int rule_tree_queue( } static inline int batch_search( - MpseGroup* so, Packet* p, const uint8_t* buf, unsigned len, PegCount& cnt) + MpseGroup* mpg, Packet* p, const uint8_t* buf, unsigned len, PegCount& cnt) { - assert(so->get_normal_mpse()->get_pattern_count() > 0); + assert(mpg->get_normal_mpse()->get_pattern_count() > 0); cnt++; // FIXIT-P Batch outer UDP payload searches for teredo set and the outer header // during any signature evaluation if ( p->is_udp_tunneled() ) { - fp_immediate(so, p, buf, len); + fp_immediate(mpg, p, buf, len); } else { MpseBatchKey<> key = MpseBatchKey<>(buf, len); - p->context->searches.items[key].so.push_back(so); + p->context->searches.items[key].so.push_back(mpg); } dump_buffer(buf, len, p); @@ -880,109 +881,83 @@ static inline int batch_search( return 0; } -static inline void search_buffer( - Inspector* gadget, InspectionBuffer& buf, InspectionBuffer::Type ibt, - Packet* p, RuleGroup* pg, PmType pmt, PegCount& cnt) -{ - if ( MpseGroup* so = pg->mpsegrp[pmt] ) - { - if ( gadget->get_fp_buf(ibt, p, buf) ) - { - debug_logf(detection_trace, TRACE_FP_SEARCH, p, - "%" PRIu64 " fp %s.%s[%d]\n", p->context->packet_number, - gadget->get_name(), pm_type_strings[pmt], buf.len); - - batch_search(so, p, buf.data, buf.len, cnt); - } - } -} - static int fp_search(RuleGroup* port_group, Packet* p, bool srvc) { + p->packet_flags |= PKT_FAST_PAT_EVAL; Inspector* gadget = p->flow ? p->flow->gadget : nullptr; - InspectionBuffer buf; debug_log(detection_trace, TRACE_RULE_EVAL, p, "Fast pattern search\n"); - // ports search raw packet only - if ( p->dsize ) + for ( const auto it : port_group->pm_list ) { - assert(p->data); - - if ( MpseGroup* so = port_group->mpsegrp[PM_TYPE_PKT] ) + switch ( it->type ) { - if ( uint16_t pattern_match_size = p->get_detect_limit() ) + case PatternMatcher::PMT_PKT: { - debug_logf(detection_trace, TRACE_FP_SEARCH, p, - "%" PRIu64 " fp %s[%u]\n", p->context->packet_number, - pm_type_strings[PM_TYPE_PKT], pattern_match_size); - - batch_search(so, p, p->data, pattern_match_size, pc.pkt_searches); - p->is_cooked() ? pc.cooked_searches++ : pc.raw_searches++; - } - } - } - - if ( gadget ) - { - // FIXIT-L PM_TYPE_ALT will never be set unless we add - // norm_data keyword or telnet, rpc_decode, smtp keywords - // until then we must use the standard packet mpse - search_buffer(gadget, buf, buf.IBT_ALT, p, port_group, PM_TYPE_PKT, pc.alt_searches); - } - - if ( !srvc ) - return 0; - - // service searches PDU buffers and file - if ( gadget ) - { - search_buffer(gadget, buf, buf.IBT_KEY, p, port_group, PM_TYPE_KEY, pc.key_searches); - - search_buffer(gadget, buf, buf.IBT_HEADER, p, port_group, PM_TYPE_HEADER, pc.header_searches); - - search_buffer(gadget, buf, buf.IBT_BODY, p, port_group, PM_TYPE_BODY, pc.body_searches); - - search_buffer( - gadget, buf, buf.IBT_RAW_KEY, p, port_group, PM_TYPE_RAW_KEY, pc.raw_key_searches); + bool alt_search = false; + if ( gadget ) + { + // need to add a norm_data keyword or telnet, rpc_decode, smtp keywords + // until then we must use the standard packet mpse + const DataBuffer& buf = DetectionEngine::get_alt_buffer(p); - search_buffer( - gadget, buf, buf.IBT_RAW_HEADER, p, port_group, PM_TYPE_RAW_HEADER, pc.raw_header_searches); + if ( buf.len ) + { + debug_logf(detection_trace, TRACE_FP_SEARCH, p, + "%" PRIu64 " fp alt_data[%u]\n", p->context->packet_number, buf.len); - search_buffer( - gadget, buf, buf.IBT_METHOD, p, port_group, PM_TYPE_METHOD, pc.method_searches); + batch_search(&it->group, p, buf.data, buf.len, pc.alt_searches); + alt_search = true; + } + } + if ( p->dsize and (!alt_search or it->raw_data) ) + { + assert(p->data); - search_buffer( - gadget, buf, buf.IBT_STAT_CODE, p, port_group, PM_TYPE_STAT_CODE, pc.stat_code_searches); + if ( uint16_t length = p->get_detect_limit() ) + { + debug_logf(detection_trace, TRACE_FP_SEARCH, p, + "%" PRIu64 " fp pkt_data[%u]\n", p->context->packet_number, length); - search_buffer( - gadget, buf, buf.IBT_STAT_MSG, p, port_group, PM_TYPE_STAT_MSG, pc.stat_msg_searches); + batch_search(&it->group, p, p->data, length, pc.pkt_searches); + p->is_cooked() ? pc.cooked_searches++ : pc.raw_searches++; + } + } + } + break; - search_buffer( - gadget, buf, buf.IBT_COOKIE, p, port_group, PM_TYPE_COOKIE, pc.cookie_searches); + case PatternMatcher::PMT_PDU: + if ( srvc and gadget ) + { + Cursor c; - search_buffer(gadget, buf, buf.IBT_VBA, p, port_group, PM_TYPE_VBA, pc.vba_searches); + if ( it->fp_opt->eval(c, p) == IpsOption::MATCH ) + { + debug_logf(detection_trace, TRACE_FP_SEARCH, p, + "%" PRIu64 " fp %s[%d]\n", p->context->packet_number, c.get_name(), c.size()); - search_buffer(gadget, buf, buf.IBT_JS_DATA, p, port_group, PM_TYPE_JS_DATA, pc.js_data_searches); - } + batch_search(&it->group, p, c.buffer(), c.size(), pc.pdu_searches); + } + } + break; - // file searches file only - if ( MpseGroup* so = port_group->mpsegrp[PM_TYPE_FILE] ) - { - // FIXIT-M file data should be obtained from - // inspector gadget as is done with search_buffer - DataPointer file_data = p->context->file_data; + case PatternMatcher::PMT_FILE: + if ( srvc ) + { + DataPointer file_data = p->context->file_data; - if ( file_data.len ) - { - debug_logf(detection_trace, TRACE_FP_SEARCH, p, - "%" PRIu64 " fp search %s[%d]\n", p->context->packet_number, - pm_type_strings[PM_TYPE_FILE], file_data.len); + if ( file_data.len ) + { + debug_logf(detection_trace, TRACE_FP_SEARCH, p, + "%" PRIu64 " fp search file_data[%d]\n", p->context->packet_number, file_data.len); - batch_search(so, p, file_data.data, file_data.len, pc.file_searches); + batch_search(&it->group, p, file_data.data, file_data.len, pc.file_searches); + } + } + break; } } - + p->packet_flags &= ~PKT_FAST_PAT_EVAL; return 0; } @@ -1367,13 +1342,13 @@ static void fp_immediate(Packet* p) } } -static void fp_immediate(MpseGroup* so, Packet* p, const uint8_t* buf, unsigned len) +static void fp_immediate(MpseGroup* mpg, Packet* p, const uint8_t* buf, unsigned len) { MpseStash* stash = p->context->stash; { Profile mpse_profile(mpsePerfStats); int start_state = 0; - so->get_normal_mpse()->search(buf, len, rule_tree_queue, p->context, &start_state); + mpg->get_normal_mpse()->search(buf, len, rule_tree_queue, p->context, &start_state); } { Profile rule_profile(rulePerfStats); diff --git a/src/detection/fp_utils.cc b/src/detection/fp_utils.cc index e262db522..e60e2ffe5 100644 --- a/src/detection/fp_utils.cc +++ b/src/detection/fp_utils.cc @@ -30,7 +30,9 @@ #include #include #include +#include +#include "framework/inspector.h" #include "framework/mpse.h" #include "framework/mpse_batch.h" #include "hash/ghash.h" @@ -77,78 +79,93 @@ static bool pmd_can_be_fp( return pmd->can_be_fp(); } -PmType get_pm_type(CursorActionType cat) +PatternMatcher::Type get_pm_type(const std::string& buf) { - switch ( cat ) - { - case CAT_SET_RAW: - case CAT_SET_OTHER: - return PM_TYPE_PKT; + if ( buf == "pkt_data" or buf == "raw_data" ) + return PatternMatcher::PMT_PKT; - case CAT_SET_COOKIE: - return PM_TYPE_COOKIE; + if ( buf == "file_data" ) + return PatternMatcher::PMT_FILE; - case CAT_SET_JS_DATA: - return PM_TYPE_JS_DATA; + return PatternMatcher::PMT_PDU; +} - case CAT_SET_STAT_MSG: - return PM_TYPE_STAT_MSG; +static RuleDirection get_dir(OptTreeNode* otn) +{ + if ( otn->to_client() ) + return RULE_FROM_SERVER; - case CAT_SET_STAT_CODE: - return PM_TYPE_STAT_CODE; + if ( otn->to_server() ) + return RULE_FROM_CLIENT; - case CAT_SET_METHOD: - return PM_TYPE_METHOD; + return RULE_WO_DIR; +} - case CAT_SET_RAW_HEADER: - return PM_TYPE_RAW_HEADER; +using SvcList = std::vector; +static std::unordered_map buffer_map; - case CAT_SET_RAW_KEY: - return PM_TYPE_RAW_KEY; +static const char* get_service(const char* buf) +{ + auto it = buffer_map.find(buf); - case CAT_SET_FILE: - return PM_TYPE_FILE; + if ( it == buffer_map.end() ) + return nullptr; - case CAT_SET_BODY: - return PM_TYPE_BODY; + return it->second[0].c_str(); +} - case CAT_SET_HEADER: - return PM_TYPE_HEADER; +static unsigned get_num_services(const char* buf) +{ + auto it = buffer_map.find(buf); - case CAT_SET_KEY: - return PM_TYPE_KEY; + if ( it == buffer_map.end() ) + return 0; - case CAT_SET_VBA: - return PM_TYPE_VBA; + return it->second.size(); +} - default: - break; +void update_buffer_map(const char** bufs, const char* svc) +{ + if ( !bufs ) + return; + + if ( !svc ) + { + assert(svc); + return; + } + + // FIXIT-M update NHI and H2I api.buffers and remove the hard-coded foo below + for ( int i = 0; bufs[i]; ++i ) + { + buffer_map[bufs[i]].push_back(svc); + if ( !strcmp(svc, "http") ) + buffer_map[bufs[i]].push_back("http2"); + } + + if ( !strcmp(svc, "http") ) + { + buffer_map["file_data"].push_back("http"); + buffer_map["file_data"].push_back("http2"); } - assert(false); - return PM_TYPE_MAX; } -static RuleDirection get_dir(OptTreeNode* otn) +void add_default_services(SnortConfig* sc, const std::string& buf, OptTreeNode* otn) { - if ( otn->to_client() ) - return RULE_FROM_SERVER; + SvcList& list = buffer_map[buf]; - if ( otn->to_server() ) - return RULE_FROM_CLIENT; - - return RULE_WO_DIR; + for ( auto& svc : list ) + add_service_to_otn(sc, otn, svc.c_str()); } -// this will be made extensible when fast patterns are extensible -static const char* get_service(const char* opt) +// FIXIT-L this will be removed when ips option api +// is updated to include service +static const char* guess_service(const char* opt) { if ( !strncmp(opt, "http_", 5) ) return "http"; - if ( !strncmp(opt, "js_data", 7) ) - return "http"; - - if ( !strncmp(opt, "cip_", 4) ) // NO FP BUF + if ( !strncmp(opt, "cip_", 4) or !strncmp(opt, "enip_", 5) ) return "cip"; if ( !strncmp(opt, "dce_", 4) ) @@ -157,9 +174,12 @@ static const char* get_service(const char* opt) if ( !strncmp(opt, "dnp3_", 5) ) return "dnp3"; - if ( !strncmp(opt, "gtp_", 4) ) // NO FP BUF + if ( !strncmp(opt, "gtp_", 4) ) return "gtp"; + if ( !strncmp(opt, "mms_", 4) ) + return "mms"; + if ( !strncmp(opt, "modbus_", 7) ) return "modbus"; @@ -169,8 +189,8 @@ static const char* get_service(const char* opt) if ( !strncmp(opt, "sip_", 4) ) return "sip"; - if ( !strncmp(opt, "vba_data", 8) ) - return "file"; + if ( !strncmp(opt, "ssl_", 4) ) + return "ssl"; return nullptr; } @@ -293,20 +313,17 @@ static std::string make_db_name( static bool db_dump(const std::string& path, const char* proto, const char* dir, RuleGroup* g) { - for ( auto i = 0; i < PM_TYPE_MAX; ++i ) + for ( auto it : g->pm_list ) { - if ( !g->mpsegrp[i] ) - continue; - std::string id; - g->mpsegrp[i]->normal_mpse->get_hash(id); + it->group.normal_mpse->get_hash(id); - std::string file = make_db_name(path, proto, dir, pm_type_strings[i], id); + std::string file = make_db_name(path, proto, dir, it->name, id); uint8_t* db = nullptr; size_t len = 0; - if ( g->mpsegrp[i]->normal_mpse->serialize(db, len) and db and len > 0 ) + if ( it->group.normal_mpse->serialize(db, len) and db and len > 0 ) { store(file, db, len); free(db); @@ -323,15 +340,12 @@ static bool db_dump(const std::string& path, const char* proto, const char* dir, static bool db_load(const std::string& path, const char* proto, const char* dir, RuleGroup* g) { - for ( auto i = 0; i < PM_TYPE_MAX; ++i ) + for ( auto it : g->pm_list ) { - if ( !g->mpsegrp[i] ) - continue; - std::string id; - g->mpsegrp[i]->normal_mpse->get_hash(id); + it->group.normal_mpse->get_hash(id); - std::string file = make_db_name(path, proto, dir, pm_type_strings[i], id); + std::string file = make_db_name(path, proto, dir, it->name, id); uint8_t* db = nullptr; size_t len = 0; @@ -341,7 +355,7 @@ static bool db_load(const std::string& path, const char* proto, const char* dir, ParseWarning(WARN_RULES, "Failed to read %s", file.c_str()); return false; } - else if ( !g->mpsegrp[i]->normal_mpse->deserialize(db, len) ) + else if ( !it->group.normal_mpse->deserialize(db, len) ) { ParseWarning(WARN_RULES, "Failed to deserialize %s", file.c_str()); return false; @@ -431,8 +445,8 @@ unsigned fp_deserialize(const SnortConfig* sc, const std::string& dir) void validate_services(SnortConfig* sc, OptTreeNode* otn) { - std::string svc; - bool file = false; + std::string svc, multi_svc_buf; + const char* guess = nullptr; for (OptFpList* ofl = otn->opt_func; ofl; ofl = ofl->next) { @@ -440,24 +454,29 @@ void validate_services(SnortConfig* sc, OptTreeNode* otn) continue; CursorActionType cat = ofl->ips_opt->get_cursor_type(); + const char* s = ofl->ips_opt->get_name(); if ( cat <= CAT_ADJUST ) + { + if ( !guess ) + guess = guess_service(s); + continue; + } - const char* s = ofl->ips_opt->get_name(); + unsigned n = get_num_services(s); + + if ( !n ) + continue; - // special case file_data because it could be any subset of file carving services - if ( !strcmp(s, "file_data") ) + if ( n > 1 ) { - file = true; + multi_svc_buf = s; continue; } s = get_service(s); - if ( !s ) - continue; - if ( !svc.empty() and svc != s ) { ParseWarning(WARN_RULES, "%u:%u:%u has mixed service buffers (%s and %s)", @@ -478,21 +497,35 @@ void validate_services(SnortConfig* sc, OptTreeNode* otn) add_service_to_otn(sc, otn, svc.c_str()); } - if ( otn->sigInfo.services.empty() and file ) + if ( otn->sigInfo.services.empty() and !multi_svc_buf.empty() ) { - ParseWarning(WARN_RULES, "%u:%u:%u has no service with file_data", - otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev); - add_service_to_otn(sc, otn, "file"); + ParseWarning(WARN_RULES, "%u:%u:%u has no service with %s", + otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, multi_svc_buf.c_str()); + + add_default_services(sc, multi_svc_buf, otn); + } + if ( !otn->sigInfo.services.size() and guess ) + { + ParseWarning(WARN_RULES, "%u:%u:%u has no service with %s option", + otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, guess); + + add_service_to_otn(sc, otn, guess); + + if ( !strcmp(guess, "netbios-ssn") ) // :( + add_service_to_otn(sc, otn, "dcerpc"); + + otn->set_service_only(); } } PatternMatchVector get_fp_content( - OptTreeNode* otn, OptFpList*& node, bool srvc, bool only_literals, bool& exclude) + OptTreeNode* otn, OptFpList*& node, IpsOption*& fp_opt, bool srvc, bool only_literals, bool& exclude) { CursorActionType curr_cat = CAT_SET_RAW; FpSelector best; bool content = false; PatternMatchVector pmds; + IpsOption* curr_opt = nullptr, * best_opt = nullptr; for (OptFpList* ofl = otn->opt_func; ofl; ofl = ofl->next) { @@ -502,7 +535,12 @@ PatternMatchVector get_fp_content( CursorActionType cat = ofl->ips_opt->get_cursor_type(); if ( cat > CAT_ADJUST ) + { + if ( cat == CAT_SET_FAST_PATTERN or cat == CAT_SET_RAW ) + curr_opt = ofl->ips_opt; + curr_cat = cat; + } RuleDirection dir = get_dir(otn); PatternMatchData* tmp = ofl->ips_opt->get_pattern(otn->snort_protocol_id, dir); @@ -518,6 +556,7 @@ PatternMatchVector get_fp_content( { best = curr; node = ofl; + best_opt = curr_opt; } } @@ -533,6 +572,7 @@ PatternMatchVector get_fp_content( if (alt_pmd) pmds.emplace_back(alt_pmd); pmds.emplace_back(best.pmd); // add primary pattern last + fp_opt = best_opt; } return pmds; } @@ -638,8 +678,6 @@ unsigned compile_mpses(struct SnortConfig* sc, bool parallel) #ifdef UNIT_TEST static void set_pmd(PatternMatchData& pmd, unsigned flags, const char* s) { - memset(&pmd, 0, sizeof(pmd)); - if ( flags & 0x01 ) pmd.set_negated(); if ( flags & 0x02 ) @@ -657,49 +695,49 @@ static void set_pmd(PatternMatchData& pmd, unsigned flags, const char* s) TEST_CASE("pmd_no_options", "[PatternMatchData]") { - PatternMatchData pmd; + PatternMatchData pmd = { }; set_pmd(pmd, 0x0, "foo"); CHECK(pmd.can_be_fp()); } TEST_CASE("pmd_negated", "[PatternMatchData]") { - PatternMatchData pmd; + PatternMatchData pmd = { }; set_pmd(pmd, 0x1, "foo"); CHECK(!pmd.can_be_fp()); } TEST_CASE("pmd_no_case", "[PatternMatchData]") { - PatternMatchData pmd; + PatternMatchData pmd = { }; set_pmd(pmd, 0x2, "foo"); CHECK(pmd.can_be_fp()); } TEST_CASE("pmd_relative", "[PatternMatchData]") { - PatternMatchData pmd; + PatternMatchData pmd = { }; set_pmd(pmd, 0x4, "foo"); CHECK(pmd.can_be_fp()); } TEST_CASE("pmd_negated_no_case", "[PatternMatchData]") { - PatternMatchData pmd; + PatternMatchData pmd = { }; set_pmd(pmd, 0x3, "foo"); CHECK(pmd.can_be_fp()); } TEST_CASE("pmd_negated_relative", "[PatternMatchData]") { - PatternMatchData pmd; + PatternMatchData pmd = { }; set_pmd(pmd, 0x5, "foo"); CHECK(!pmd.can_be_fp()); } TEST_CASE("pmd_negated_no_case_offset", "[PatternMatchData]") { - PatternMatchData pmd; + PatternMatchData pmd = { }; set_pmd(pmd, 0x1, "foo"); pmd.offset = 3; CHECK(!pmd.can_be_fp()); @@ -707,7 +745,7 @@ TEST_CASE("pmd_negated_no_case_offset", "[PatternMatchData]") TEST_CASE("pmd_negated_no_case_depth", "[PatternMatchData]") { - PatternMatchData pmd; + PatternMatchData pmd = { }; set_pmd(pmd, 0x3, "foo"); pmd.depth = 1; CHECK(!pmd.can_be_fp()); @@ -716,7 +754,7 @@ TEST_CASE("pmd_negated_no_case_depth", "[PatternMatchData]") TEST_CASE("fp_simple", "[FastPatternSelect]") { FpSelector test; - PatternMatchData pmd; + PatternMatchData pmd = { }; set_pmd(pmd, 0x0, "foo"); FpSelector left(CAT_SET_RAW, nullptr, &pmd); CHECK(left.is_better_than(test, false, RULE_WO_DIR)); @@ -727,11 +765,11 @@ TEST_CASE("fp_simple", "[FastPatternSelect]") TEST_CASE("fp_negated", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x0, "foo"); FpSelector s0(CAT_SET_RAW, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x1, "foo"); FpSelector s1(CAT_SET_RAW, nullptr, &p1); @@ -741,26 +779,26 @@ TEST_CASE("fp_negated", "[FastPatternSelect]") TEST_CASE("fp_cat1", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x0, "longer"); - FpSelector s0(CAT_SET_FILE, nullptr, &p0); + FpSelector s0(CAT_SET_FAST_PATTERN, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x0, "short"); - FpSelector s1(CAT_SET_BODY, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(s0.is_better_than(s1, true, RULE_WO_DIR)); } TEST_CASE("fp_cat2", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x0, "foo"); FpSelector s0(CAT_SET_RAW, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x0, "foo"); - FpSelector s1(CAT_SET_FILE, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(!s0.is_better_than(s1, false, RULE_WO_DIR)); CHECK(!s1.is_better_than(s0, false, RULE_WO_DIR)); @@ -768,117 +806,117 @@ TEST_CASE("fp_cat2", "[FastPatternSelect]") TEST_CASE("fp_cat3", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x0, "foo"); FpSelector s0(CAT_SET_RAW, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x0, "foo"); - FpSelector s1(CAT_SET_FILE, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(!s0.is_better_than(s1, true, RULE_WO_DIR)); } TEST_CASE("fp_size", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x0, "longer"); - FpSelector s0(CAT_SET_HEADER, nullptr, &p0); + FpSelector s0(CAT_SET_FAST_PATTERN, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x0, "short"); - FpSelector s1(CAT_SET_HEADER, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(s0.is_better_than(s1, false, RULE_WO_DIR)); } TEST_CASE("fp_pkt_key_port", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x0, "short"); FpSelector s0(CAT_SET_RAW, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x0, "longer"); - FpSelector s1(CAT_SET_KEY, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(!s0.is_better_than(s1, false, RULE_WO_DIR)); } TEST_CASE("fp_pkt_key_port_user", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x10, "short"); - FpSelector s0(CAT_SET_KEY, nullptr, &p0); + FpSelector s0(CAT_SET_FAST_PATTERN, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x0, "longer"); - FpSelector s1(CAT_SET_KEY, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(s0.is_better_than(s1, false, RULE_WO_DIR)); } TEST_CASE("fp_pkt_key_port_user_user", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x10, "longer"); - FpSelector s0(CAT_SET_KEY, nullptr, &p0); + FpSelector s0(CAT_SET_FAST_PATTERN, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x10, "short"); - FpSelector s1(CAT_SET_KEY, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(!s0.is_better_than(s1, false, RULE_WO_DIR)); } TEST_CASE("fp_pkt_key_port_user_user2", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x0, "longer"); - FpSelector s0(CAT_SET_KEY, nullptr, &p0); + FpSelector s0(CAT_SET_FAST_PATTERN, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x10, "short"); - FpSelector s1(CAT_SET_KEY, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(!s0.is_better_than(s1, false, RULE_WO_DIR)); } TEST_CASE("fp_pkt_key_srvc_1", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x0, "short"); FpSelector s0(CAT_SET_RAW, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x0, "longer"); - FpSelector s1(CAT_SET_KEY, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(s1.is_better_than(s0, true, RULE_WO_DIR)); } TEST_CASE("fp_pkt_key_srvc_2", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x0, "longer"); FpSelector s0(CAT_SET_RAW, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x0, "short"); - FpSelector s1(CAT_SET_KEY, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(s0.is_better_than(s1, true, RULE_WO_DIR)); } TEST_CASE("fp_pkt_key_srvc_rsp", "[FastPatternSelect]") { - PatternMatchData p0; + PatternMatchData p0 = { }; set_pmd(p0, 0x0, "short"); FpSelector s0(CAT_SET_RAW, nullptr, &p0); - PatternMatchData p1; + PatternMatchData p1 = { }; set_pmd(p1, 0x0, "longer"); - FpSelector s1(CAT_SET_KEY, nullptr, &p1); + FpSelector s1(CAT_SET_FAST_PATTERN, nullptr, &p1); CHECK(!s0.is_better_than(s1, true, RULE_FROM_SERVER)); CHECK(s1.is_better_than(s0, true, RULE_FROM_SERVER)); diff --git a/src/detection/fp_utils.h b/src/detection/fp_utils.h index 7bc80a2bb..293ca6d65 100644 --- a/src/detection/fp_utils.h +++ b/src/detection/fp_utils.h @@ -38,12 +38,12 @@ struct PatternMatchData* get_pmd(OptFpList*, SnortProtocolId, snort::RuleDirecti bool make_fast_pattern_only(const OptFpList*, const PatternMatchData*); bool is_fast_pattern_only(const OptTreeNode*, const OptFpList*, snort::Mpse::MpseType); -PmType get_pm_type(snort::CursorActionType); +PatternMatcher::Type get_pm_type(const std::string& buf); bool set_fp_content(OptTreeNode*); std::vector get_fp_content( - OptTreeNode*, OptFpList*&, bool srvc, bool only_literals, bool& exclude); + OptTreeNode*, OptFpList*& pat, snort::IpsOption*& buf, bool srvc, bool only_literals, bool& exclude); void queue_mpse(snort::Mpse*); unsigned compile_mpses(struct snort::SnortConfig*, bool parallel = false); @@ -53,5 +53,8 @@ void validate_services(struct snort::SnortConfig*, OptTreeNode*); unsigned fp_serialize(const struct snort::SnortConfig*, const std::string& dir); unsigned fp_deserialize(const struct snort::SnortConfig*, const std::string& dir); +void update_buffer_map(const char** bufs, const char* svc); +void add_default_services(struct snort::SnortConfig*, const std::string&, OptTreeNode*); + #endif diff --git a/src/detection/ips_context.cc b/src/detection/ips_context.cc index 9295f136b..98bb5a391 100644 --- a/src/detection/ips_context.cc +++ b/src/detection/ips_context.cc @@ -140,6 +140,7 @@ void IpsContext::post_detection() callback(this); post_callbacks.clear(); + alt_data.len = 0; } void IpsContext::disable_detection() diff --git a/src/detection/pattern_match_data.h b/src/detection/pattern_match_data.h index dbe49d7f1..8297ea6f0 100644 --- a/src/detection/pattern_match_data.h +++ b/src/detection/pattern_match_data.h @@ -22,6 +22,9 @@ #define PATTERN_MATCH_DATA_H #include + +#include +#include #include #include "framework/ips_option.h" // FIXIT-L not a good dependency @@ -36,8 +39,6 @@ struct PmdLastCheck struct PatternMatchData { - const char* pattern_buf; // app layer pattern to match on - // FIXIT-L wasting some memory here: // - this is not used by content option logic directly // - and only used on current eval (not across packets) @@ -47,7 +48,12 @@ struct PatternMatchData but the rule option specifies a negated content. Only applies to negative contents that are not relative */ PmdLastCheck* last_check; + const char* sticky_buf = nullptr; // provides context to contents + //---------------------------------------------------------------- + // data above this point is for framework use only! + //---------------------------------------------------------------- + const char* pattern_buf; // app layer pattern to match on unsigned pattern_size; // size of app layer pattern int offset; // pattern search start offset @@ -69,9 +75,6 @@ struct PatternMatchData uint16_t fp_offset; uint16_t fp_length; - // not used by ips_content - uint8_t pm_type; - bool is_unbounded() const { return !depth; } @@ -106,6 +109,8 @@ struct PatternMatchData { return (flags & LITERAL) != 0; } bool can_be_fp() const; + + bool has_alpha() const; }; typedef std::vector PatternMatchVector; @@ -137,5 +142,18 @@ inline bool PatternMatchData::can_be_fp() const return true; } +inline bool PatternMatchData::has_alpha() const +{ + unsigned offset = fp_offset ? fp_offset : 0; + unsigned length = fp_length ? fp_length : pattern_size; + + for ( unsigned idx = 0; idx < length; ++idx ) + { + if ( isalpha(pattern_buf[offset + idx]) ) + return true; + } + return false; +} + #endif diff --git a/src/detection/rule_option_types.h b/src/detection/rule_option_types.h index c1dbc2c37..9ac505c28 100644 --- a/src/detection/rule_option_types.h +++ b/src/detection/rule_option_types.h @@ -20,13 +20,10 @@ #ifndef RULE_OPTION_TYPES_H #define RULE_OPTION_TYPES_H -// if you change this, you must also update detection_options.cc::option_type_str[]. enum option_type_t { RULE_OPTION_TYPE_LEAF_NODE, // internal use by rule compiler - RULE_OPTION_TYPE_BUFFER_SET, // sets sticky buffer - RULE_OPTION_TYPE_BUFFER_USE, // uses sticky buffer - RULE_OPTION_TYPE_CONTENT, // ideally would be eliminated (implies _BUFFER_USE) + RULE_OPTION_TYPE_CONTENT, // ideally would be eliminated RULE_OPTION_TYPE_FLOWBIT, // ideally would be eliminated RULE_OPTION_TYPE_OTHER // for all new buffer independent rule options }; diff --git a/src/detection/treenodes.h b/src/detection/treenodes.h index b98c5fcd1..c8fc3339e 100644 --- a/src/detection/treenodes.h +++ b/src/detection/treenodes.h @@ -22,6 +22,8 @@ // rule header (RTN) and body (OTN) nodes +#include + #include "actions/actions.h" #include "detection/signature.h" #include "detection/rule_option_types.h" @@ -173,6 +175,7 @@ struct OptTreeNode static constexpr Flag TO_CLIENT = 0x10; static constexpr Flag TO_SERVER = 0x20; static constexpr Flag BIT_CHECK = 0x40; + static constexpr Flag SVC_ONLY = 0x80; /* metadata about signature */ SigInfo sigInfo; @@ -202,8 +205,6 @@ struct OptTreeNode IpsPolicy::Enable enable; Flag flags = 0; - uint8_t sticky_buf = PM_TYPE_PKT; // parsing only - void set_warned_fp() { flags |= WARNED_FP; } @@ -255,6 +256,12 @@ struct OptTreeNode bool checks_flowbits() const { return (flags & BIT_CHECK) != 0; } + void set_service_only() + { flags |= SVC_ONLY; } + + bool service_only() const + { return (flags & SVC_ONLY) != 0; } + void update_fp(snort::IpsOption*); }; diff --git a/src/flow/flow.cc b/src/flow/flow.cc index 0b945ab83..c772815a9 100644 --- a/src/flow/flow.cc +++ b/src/flow/flow.cc @@ -29,7 +29,6 @@ #include "flow/session.h" #include "framework/data_bus.h" #include "helpers/bitop.h" -#include "ips_options/ips_flowbits.h" #include "memory/memory_cap.h" #include "protocols/packet.h" #include "protocols/tcp.h" diff --git a/src/flow/flow_cache.cc b/src/flow/flow_cache.cc index 850c2ec29..8630ece92 100644 --- a/src/flow/flow_cache.cc +++ b/src/flow/flow_cache.cc @@ -28,7 +28,6 @@ #include "hash/hash_defs.h" #include "hash/zhash.h" #include "helpers/flag_context.h" -#include "ips_options/ips_flowbits.h" #include "main/snort_debug.h" #include "memory/memory_cap.h" #include "packet_io/active.h" diff --git a/src/framework/cursor.cc b/src/framework/cursor.cc index 8fc6e4ca6..f4c32cbaa 100644 --- a/src/framework/cursor.cc +++ b/src/framework/cursor.cc @@ -25,6 +25,7 @@ #include "cursor.h" +#include "detection/detection_engine.h" #include "detection/detection_util.h" #include "protocols/packet.h" @@ -94,16 +95,17 @@ void Cursor::set_data(CursorData* cd) void Cursor::reset(Packet* p) { - InspectionBuffer buf; - - if ( p->flow and p->flow->gadget and - p->flow->gadget->get_buf(buf.IBT_ALT, p, buf) ) - { - set("alt_data", buf.data, buf.len); - } - else + if ( p->flow and p->flow->gadget ) { - set("pkt_data", p->data, p->get_detect_limit()); + const DataBuffer& buf = DetectionEngine::get_alt_buffer(p); + + if ( buf.len ) + { + set("alt_data", buf.data, buf.len); + return; + } } + + set("pkt_data", p->data, p->get_detect_limit()); } diff --git a/src/framework/inspector.h b/src/framework/inspector.h index f598ecaf5..db3b25da4 100644 --- a/src/framework/inspector.h +++ b/src/framework/inspector.h @@ -47,10 +47,16 @@ struct InspectionBuffer { enum Type { - // FIXIT-L file data is tbd - IBT_KEY, IBT_HEADER, IBT_BODY, IBT_FILE, IBT_ALT, - IBT_RAW_KEY, IBT_RAW_HEADER, IBT_METHOD, IBT_STAT_CODE, - IBT_STAT_MSG, IBT_COOKIE, IBT_JS_DATA, IBT_VBA, IBT_MAX + // this is the only generic rule option + IBT_VBA, + + // FIXIT-M all of these should be eliminated after NHI is updated + IBT_KEY, IBT_HEADER, IBT_BODY, + IBT_RAW_KEY, IBT_RAW_HEADER, IBT_METHOD, + IBT_STAT_CODE, IBT_STAT_MSG, IBT_COOKIE, + IBT_JS_DATA, + + IBT_MAX }; const uint8_t* data; unsigned len; diff --git a/src/framework/ips_option.cc b/src/framework/ips_option.cc index b6a900fcd..f3feecd9c 100644 --- a/src/framework/ips_option.cc +++ b/src/framework/ips_option.cc @@ -29,40 +29,25 @@ using namespace snort; -static const char* s_buffer = nullptr; - -void IpsOption::set_buffer(const char* s) -{ s_buffer = s; } - //------------------------------------------------------------------------- IpsOption::IpsOption(const char* s, option_type_t t) { name = s; type = t; - - switch ( t ) - { - case RULE_OPTION_TYPE_BUFFER_SET: buffer = s_buffer = s; break; - case RULE_OPTION_TYPE_CONTENT: - case RULE_OPTION_TYPE_BUFFER_USE: buffer = s_buffer; break; - default: buffer = "n/a"; - } } uint32_t IpsOption::hash() const { uint32_t a = 0, b = 0, c = 0; mix_str(a, b, c, get_name()); - mix_str(a, b, c, get_buffer()); finalize(a, b, c); return c; } bool IpsOption::operator==(const IpsOption& ips) const { - return !strcmp(get_name(), ips.get_name()) and - !strcmp(get_buffer(), ips.get_buffer()); + return !strcmp(get_name(), ips.get_name()); } //------------------------------------------------------------------------- @@ -84,10 +69,16 @@ TEST_CASE("IpsOption test", "[ips_option]") StubIpsOption main_ips("ips_test", option_type_t::RULE_OPTION_TYPE_OTHER); + SECTION("buffer test") + { + REQUIRE(main_ips.get_buffer()); // only until api is updated + } + SECTION("IpsOperator == test") { StubIpsOption case_diff_name("not_hello_world", - option_type_t::RULE_OPTION_TYPE_BUFFER_USE); + option_type_t::RULE_OPTION_TYPE_LEAF_NODE); + REQUIRE((main_ips == case_diff_name) == false); StubIpsOption case_diff_option("hello_world", diff --git a/src/framework/ips_option.h b/src/framework/ips_option.h index e5165374f..cbd935bca 100644 --- a/src/framework/ips_option.h +++ b/src/framework/ips_option.h @@ -52,18 +52,7 @@ enum CursorActionType CAT_ADJUST, CAT_SET_OTHER, CAT_SET_RAW, - CAT_SET_COOKIE, - CAT_SET_STAT_MSG, - CAT_SET_STAT_CODE, - CAT_SET_METHOD, - CAT_SET_RAW_HEADER, - CAT_SET_RAW_KEY, - CAT_SET_FILE, - CAT_SET_BODY, - CAT_SET_HEADER, - CAT_SET_KEY, - CAT_SET_JS_DATA, - CAT_SET_VBA, + CAT_SET_FAST_PATTERN, }; enum RuleDirection @@ -95,10 +84,6 @@ public: enum EvalStatus { NO_MATCH, MATCH, NO_ALERT, FAILED_BIT }; virtual EvalStatus eval(Cursor&, Packet*) { return MATCH; } - option_type_t get_type() const { return type; } - const char* get_name() const { return name; } - const char* get_buffer() const { return buffer; } - virtual CursorActionType get_cursor_type() const { return CAT_NONE; } @@ -109,14 +94,21 @@ public: virtual PatternMatchData* get_alternate_pattern() { return nullptr; } - static void set_buffer(const char*); + option_type_t get_type() const { return type; } + const char* get_name() const { return name; } + + bool is_buffer_setter() const + { return get_cursor_type() > CAT_ADJUST; } + + const char* get_buffer() + { return buffer; } protected: IpsOption(const char* s, option_type_t t = RULE_OPTION_TYPE_OTHER); private: const char* name; - const char* buffer; + const char* buffer = "error"; // FIXIT-API to be deleted; here to avoid an api update option_type_t type; }; diff --git a/src/framework/mpse_batch.h b/src/framework/mpse_batch.h index 7bf5660fd..fd500a98e 100644 --- a/src/framework/mpse_batch.h +++ b/src/framework/mpse_batch.h @@ -130,8 +130,7 @@ struct MpseBatch inline void MpseBatch::search() { - items.begin()->second.so[0]->get_normal_mpse()-> - search(*this, Mpse::MPSE_TYPE_NORMAL); + items.begin()->second.so[0]->get_normal_mpse()->search(*this, Mpse::MPSE_TYPE_NORMAL); } inline Mpse::MpseRespType MpseBatch::receive_responses() diff --git a/src/ips_options/ips_asn1.cc b/src/ips_options/ips_asn1.cc index 426300828..f8c43efe9 100644 --- a/src/ips_options/ips_asn1.cc +++ b/src/ips_options/ips_asn1.cc @@ -86,7 +86,7 @@ static THREAD_LOCAL ProfileStats asn1PerfStats; class Asn1Option : public IpsOption { public: - Asn1Option(const ASN1_CTXT& c) : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_USE) + Asn1Option(const ASN1_CTXT& c) : IpsOption(s_name) { config = c; } uint32_t hash() const override; diff --git a/src/ips_options/ips_base64.cc b/src/ips_options/ips_base64.cc index c78104327..672b871ba 100644 --- a/src/ips_options/ips_base64.cc +++ b/src/ips_options/ips_base64.cc @@ -59,7 +59,7 @@ struct Base64DecodeData class Base64DecodeOption : public IpsOption { public: - Base64DecodeOption(const Base64DecodeData& c) : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_USE) + Base64DecodeOption(const Base64DecodeData& c) : IpsOption(s_name) { config = c; } @@ -274,7 +274,7 @@ static const IpsApi base64_decode_api = class Base64DataOption : public IpsOption { public: - Base64DataOption() : IpsOption(s_data_name, RULE_OPTION_TYPE_BUFFER_SET) { } + Base64DataOption() : IpsOption(s_data_name) { } CursorActionType get_cursor_type() const override { return CAT_SET_OTHER; } diff --git a/src/ips_options/ips_ber_data.cc b/src/ips_options/ips_ber_data.cc index c62b7c2d4..0fd708acd 100644 --- a/src/ips_options/ips_ber_data.cc +++ b/src/ips_options/ips_ber_data.cc @@ -48,6 +48,9 @@ public: EvalStatus eval(Cursor&, Packet*) override; + CursorActionType get_cursor_type() const override + { return CAT_ADJUST; } + private: uint32_t type; }; diff --git a/src/ips_options/ips_ber_skip.cc b/src/ips_options/ips_ber_skip.cc index 0d305ab99..8addd34ef 100644 --- a/src/ips_options/ips_ber_skip.cc +++ b/src/ips_options/ips_ber_skip.cc @@ -48,6 +48,9 @@ public: EvalStatus eval(Cursor&, Packet*) override; + CursorActionType get_cursor_type() const override + { return CAT_ADJUST; } + private: uint32_t type; bool optional; diff --git a/src/ips_options/ips_bufferlen.cc b/src/ips_options/ips_bufferlen.cc index fdb53a49b..cfa68f956 100644 --- a/src/ips_options/ips_bufferlen.cc +++ b/src/ips_options/ips_bufferlen.cc @@ -40,13 +40,15 @@ static THREAD_LOCAL ProfileStats lenCheckPerfStats; class LenOption : public IpsOption { public: - LenOption(const RangeCheck& c, bool r) : - IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_USE) + LenOption(const RangeCheck& c, bool r) : IpsOption(s_name) { config = c; relative = r; } uint32_t hash() const override; bool operator==(const IpsOption&) const override; + bool is_relative() override + { return relative; } + EvalStatus eval(Cursor&, Packet*) override; private: diff --git a/src/ips_options/ips_byte_extract.cc b/src/ips_options/ips_byte_extract.cc index 0e0717540..518fcee1b 100644 --- a/src/ips_options/ips_byte_extract.cc +++ b/src/ips_options/ips_byte_extract.cc @@ -61,7 +61,7 @@ class ByteExtractOption : public IpsOption { public: ByteExtractOption(const ByteExtractData& c) : - IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_USE), config(c) + IpsOption(s_name), config(c) { } ~ByteExtractOption() override @@ -510,22 +510,12 @@ static ByteExtractDataMatcher ByteExtractDataEquals(const ByteExtractData& value return {value}; } -class SetBufferOptionHelper : public IpsOption -{ -public: - SetBufferOptionHelper(const char* value) - : IpsOption(value, RULE_OPTION_TYPE_BUFFER_SET) - { } -}; - //------------------------------------------------------------------------- // option tests //------------------------------------------------------------------------- TEST_CASE("ByteExtractOption::operator== valid", "[ips_byte_extract]") { - SetBufferOptionHelper set_buf("test"); - char* lhs_name = new char[9]; strcpy(lhs_name, "test_lhs"); ByteExtractData data_lhs; @@ -543,19 +533,12 @@ TEST_CASE("ByteExtractOption::operator== valid", "[ips_byte_extract]") TEST_CASE("ByteExtractOption::operator== invalid", "[ips_byte_extract]") { - SetBufferOptionHelper set_buf("test"); - char* lhs_name = new char[5]; strcpy(lhs_name, "test"); ByteExtractData data_lhs; INITIALIZE(data_lhs, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, nullptr); ByteExtractOption lhs(data_lhs); - SECTION("not equal to IpsOption object") - { - CHECK(lhs != set_buf); - delete[] lhs_name; - } SECTION("all fields is different") { ByteExtractData data_rhs; @@ -647,8 +630,6 @@ TEST_CASE("ByteExtractOption::operator== invalid", "[ips_byte_extract]") TEST_CASE("ByteExtractOption::hash", "[ips_byte_extract]") { - SetBufferOptionHelper set_buf("test"); - ByteExtractData data_lhs; INITIALIZE(data_lhs, 0, 0, 0, 0, 0, 0, 8, 1, 0, 0, nullptr); ByteExtractOption lhs(data_lhs); diff --git a/src/ips_options/ips_byte_jump.cc b/src/ips_options/ips_byte_jump.cc index 6931e426d..11a73e5aa 100644 --- a/src/ips_options/ips_byte_jump.cc +++ b/src/ips_options/ips_byte_jump.cc @@ -109,9 +109,7 @@ struct ByteJumpData : public ByteData class ByteJumpOption : public IpsOption { public: - ByteJumpOption(const ByteJumpData& c) : IpsOption(s_name, - RULE_OPTION_TYPE_BUFFER_USE), config(c) - { } + ByteJumpOption(const ByteJumpData& c) : IpsOption(s_name), config(c) { } uint32_t hash() const override; bool operator==(const IpsOption&) const override; @@ -597,14 +595,6 @@ static void SetByteJumpMaxValue(ByteJumpData &byte_jump) byte_jump.post_offset_var = SCHAR_MAX; } -class StubIpsOption : public IpsOption -{ -public: - StubIpsOption(const char* name, option_type_t option_type) : - IpsOption(name, option_type) - { } -}; - class StubEndianness : public Endianness { public: @@ -617,7 +607,6 @@ TEST_CASE("ByteJumpOption test", "[ips_byte_jump]") { ByteJumpData byte_jump; SetByteJumpData(byte_jump, 1); - snort::IpsOption::set_buffer("hello_world"); SECTION("method hash") { @@ -663,13 +652,6 @@ TEST_CASE("ByteJumpOption test", "[ips_byte_jump]") { ByteJumpOption jump(byte_jump); - SECTION("Compare IpsOptions with different names") - { - StubIpsOption case_diff_name("not_hello_world", - option_type_t::RULE_OPTION_TYPE_BUFFER_USE); - REQUIRE(jump != case_diff_name); - } - ByteJumpData byte_jump2; SetByteJumpData(byte_jump2, 1); diff --git a/src/ips_options/ips_byte_math.cc b/src/ips_options/ips_byte_math.cc index 02aefcd28..3cf4b6efd 100644 --- a/src/ips_options/ips_byte_math.cc +++ b/src/ips_options/ips_byte_math.cc @@ -75,7 +75,7 @@ class ByteMathOption : public IpsOption { public: ByteMathOption(const ByteMathData& c) : - IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_USE), config(c) + IpsOption(s_name), config(c) { } ~ByteMathOption() override @@ -84,9 +84,6 @@ public: uint32_t hash() const override; bool operator==(const IpsOption&) const override; - CursorActionType get_cursor_type() const override - { return CAT_ADJUST; } - bool is_relative() override { return config.relative_flag; } @@ -619,22 +616,12 @@ static ByteMathDataMatcher ByteMathDataEquals(const ByteMathData& value) return {value}; } -class SetBufferOptionHelper : public IpsOption -{ -public: - SetBufferOptionHelper(const char* value) - : IpsOption(value, RULE_OPTION_TYPE_BUFFER_SET) - { } -}; - //------------------------------------------------------------------------- // option tests //------------------------------------------------------------------------- TEST_CASE("ByteMathOption::operator== valid", "[ips_byte_math]") { - SetBufferOptionHelper set_buf("test"); - char* lhs_name = new char[9]; strcpy(lhs_name, "test_lhs"); ByteMathData data_lhs; @@ -654,8 +641,6 @@ TEST_CASE("ByteMathOption::operator== valid", "[ips_byte_math]") TEST_CASE("ByteMathOption::operator== invalid", "[ips_byte_math]") { - SetBufferOptionHelper set_buf("test"); - char* lhs_name = new char[5]; strcpy(lhs_name, "test"); ByteMathData data_lhs; @@ -666,11 +651,6 @@ TEST_CASE("ByteMathOption::operator== invalid", "[ips_byte_math]") char* rhs_name = new char[5]; strcpy(rhs_name, "test"); - SECTION("not equal to IpsOption object") - { - CHECK(lhs != set_buf); - delete[] rhs_name; - } SECTION("all fields is different") { delete[] rhs_name; @@ -793,8 +773,6 @@ TEST_CASE("ByteMathOption::operator== invalid", "[ips_byte_math]") TEST_CASE("ByteMathOption::hash", "[ips_byte_math]") { - SetBufferOptionHelper set_buf("test"); - char* lhs_name = new char[5]; strcpy(lhs_name, "test"); ByteMathData data_lhs; diff --git a/src/ips_options/ips_byte_test.cc b/src/ips_options/ips_byte_test.cc index 0a25f4181..a3daed4b0 100644 --- a/src/ips_options/ips_byte_test.cc +++ b/src/ips_options/ips_byte_test.cc @@ -188,9 +188,7 @@ static inline bool byte_test_check(ByteTestOper op, uint32_t val, uint32_t cmp, class ByteTestOption : public IpsOption { public: - ByteTestOption(const ByteTestData& c) : IpsOption(s_name, - RULE_OPTION_TYPE_BUFFER_USE), config(c) - { } + ByteTestOption(const ByteTestData& c) : IpsOption(s_name), config(c) { } uint32_t hash() const override; bool operator==(const IpsOption&) const override; @@ -656,14 +654,6 @@ static void SetByteTestDataMax(ByteTestData& byte_test) byte_test.offset_var = CHAR_MAX; } -class StubIpsOption : public IpsOption -{ -public: - StubIpsOption(const char* name, option_type_t option_type) : - IpsOption(name, option_type) - { } -}; - class StubEndianness : public Endianness { public: @@ -731,7 +721,6 @@ TEST_CASE("ByteTestOption test", "[ips_byte_test]") { ByteTestData byte_test; SetByteTestData(byte_test, 1); - snort::IpsOption::set_buffer("hello_world"); SECTION("method hash") { @@ -777,13 +766,6 @@ TEST_CASE("ByteTestOption test", "[ips_byte_test]") { ByteTestOption test(byte_test); - SECTION("Compare IpsOptions with different names") - { - StubIpsOption case_diff_name("not_hello_world", - option_type_t::RULE_OPTION_TYPE_BUFFER_USE); - REQUIRE(test != case_diff_name); - } - SECTION("Compare between equals objects") { ByteTestOption test_1(byte_test); diff --git a/src/ips_options/ips_content.cc b/src/ips_options/ips_content.cc index 29877d810..3fe853233 100644 --- a/src/ips_options/ips_content.cc +++ b/src/ips_options/ips_content.cc @@ -192,7 +192,6 @@ uint32_t ContentOption::hash() const mix(a,b,c); - a += config->pmd.pm_type; b += IpsOption::hash(); mix(a, b, c); @@ -255,7 +254,6 @@ bool ContentOption::operator==(const IpsOption& ips) const (left.pmd.depth == right.pmd.depth) and (left.pmd.fp_offset == right.pmd.fp_offset) and (left.pmd.fp_length == right.pmd.fp_length) and - (left.pmd.pm_type == right.pmd.pm_type) and (left.match_delta == right.match_delta) and (left.offset_var == right.offset_var) and (left.depth_var == right.depth_var) ) @@ -681,6 +679,9 @@ bool ContentModule::end(const char*, int, SnortConfig*) } cd->setup_bm(); + if ( !cd->pmd.has_alpha() ) + cd->pmd.set_no_case(); + if ( cd->pmd.is_negated() ) { cd->pmd.last_check = (PmdLastCheck*)snort_calloc( @@ -740,11 +741,10 @@ static void mod_dtor(Module* m) delete m; } -static IpsOption* content_ctor(Module* p, OptTreeNode* otn) +static IpsOption* content_ctor(Module* p, OptTreeNode*) { ContentModule* m = (ContentModule*)p; ContentData* cd = m->get_data(); - cd->pmd.pm_type = otn->sticky_buf; return new ContentOption(cd); } diff --git a/src/ips_options/ips_file_data.cc b/src/ips_options/ips_file_data.cc index ecdf3e9c6..d69ca1072 100644 --- a/src/ips_options/ips_file_data.cc +++ b/src/ips_options/ips_file_data.cc @@ -37,10 +37,10 @@ static THREAD_LOCAL ProfileStats fileDataPerfStats; class FileDataOption : public IpsOption { public: - FileDataOption() : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) { } + FileDataOption() : IpsOption(s_name) { } CursorActionType get_cursor_type() const override - { return CAT_SET_FILE; } + { return CAT_SET_FAST_PATTERN; } EvalStatus eval(Cursor&, Packet*) override; }; diff --git a/src/ips_options/ips_file_type.cc b/src/ips_options/ips_file_type.cc index 80bb4031e..856b13541 100644 --- a/src/ips_options/ips_file_type.cc +++ b/src/ips_options/ips_file_type.cc @@ -45,9 +45,6 @@ public: uint32_t hash() const override; bool operator==(const IpsOption& ips) const override; - CursorActionType get_cursor_type() const override - { return CAT_NONE; } - EvalStatus eval(Cursor&, Packet*) override; FileTypeBitSet types; diff --git a/src/ips_options/ips_flowbits.cc b/src/ips_options/ips_flowbits.cc index e3f7638b6..658dbe61a 100644 --- a/src/ips_options/ips_flowbits.cc +++ b/src/ips_options/ips_flowbits.cc @@ -331,6 +331,29 @@ void get_flowbits_dependencies(void* option_data, bool& set, std::vectorget_dependencies(set, bits); } +void flowbits_counts(unsigned& total, unsigned& unchecked, unsigned& unset) +{ + unchecked = unset = 0; + + for ( const auto& it : bit_map ) + { + if ((it.second.sets > 0) and (it.second.checks == 0)) + { + ParseWarning(WARN_FLOWBITS, "%s key '%s' is set but not checked.", + s_name, it.first.c_str()); + unchecked++; + } + else if ((it.second.checks > 0) and (it.second.sets == 0)) + { + ParseWarning(WARN_FLOWBITS, "%s key '%s' is checked but not set.", + s_name, it.first.c_str()); + unset++; + } + } + + total = bit_map.size(); +} + //------------------------------------------------------------------------- // parsing methods //------------------------------------------------------------------------- @@ -401,35 +424,6 @@ static bool parse_flowbits(const char* flowbits_names, FlowBitCheck* check) return true; } -static void flowbits_verify() -{ - unsigned unchecked = 0, unset = 0; - - for ( const auto& it : bit_map ) - { - if ((it.second.sets > 0) and (it.second.checks == 0)) - { - ParseWarning(WARN_FLOWBITS, "%s key '%s' is set but not checked.", - s_name, it.first.c_str()); - unchecked++; - } - else if ((it.second.checks > 0) and (it.second.sets == 0)) - { - ParseWarning(WARN_FLOWBITS, "%s key '%s' is checked but not set.", - s_name, it.first.c_str()); - unset++; - } - } - - if ( !bit_map.size() ) - return; - - LogLabel(s_name); - LogCount("defined", bit_map.size()); - LogCount("not checked", unchecked); - LogCount("not set", unset); -} - //------------------------------------------------------------------------- // module //------------------------------------------------------------------------- @@ -541,11 +535,6 @@ static void flowbits_dtor(IpsOption* p) delete p; } -static void flowbits_verify(const SnortConfig*) -{ - flowbits_verify(); -} - static const IpsApi flowbits_api = { { @@ -568,7 +557,7 @@ static const IpsApi flowbits_api = nullptr, flowbits_ctor, flowbits_dtor, - flowbits_verify + nullptr }; const BaseApi* ips_flowbits = &flowbits_api.base; diff --git a/src/ips_options/ips_flowbits.h b/src/ips_options/ips_flowbits.h index caaee5766..db5c6fdb8 100644 --- a/src/ips_options/ips_flowbits.h +++ b/src/ips_options/ips_flowbits.h @@ -24,6 +24,7 @@ bool flowbits_setter(void*); void get_flowbits_dependencies(void*, bool& set, std::vector& bits); +void flowbits_counts(unsigned& total, unsigned& unchecked, unsigned& unset); #endif diff --git a/src/ips_options/ips_hash.cc b/src/ips_options/ips_hash.cc index e2003f9e9..4cb6fdfa2 100644 --- a/src/ips_options/ips_hash.cc +++ b/src/ips_options/ips_hash.cc @@ -68,7 +68,7 @@ class HashOption : public IpsOption { public: HashOption(const char* s, HashPsIdx hpi, HashMatchData* c, HashFunc f, unsigned n) : - IpsOption(s, RULE_OPTION_TYPE_BUFFER_USE) + IpsOption(s) { config = c; hashf = f; size = n; idx = hpi; assert(n <= MAX_HASH_SIZE); } ~HashOption() override { delete config; } diff --git a/src/ips_options/ips_luajit.cc b/src/ips_options/ips_luajit.cc index b1a1cd174..7cdfef35d 100644 --- a/src/ips_options/ips_luajit.cc +++ b/src/ips_options/ips_luajit.cc @@ -134,7 +134,7 @@ private: LuaJitOption::LuaJitOption( const char* name, std::string& chunk, LuaJitModule* mod) - : IpsOption((my_name = snort_strdup(name)), RULE_OPTION_TYPE_BUFFER_USE) + : IpsOption((my_name = snort_strdup(name))) { // create an args table with any rule options config = "args = { "; diff --git a/src/ips_options/ips_pkt_data.cc b/src/ips_options/ips_pkt_data.cc index ff87c0542..c53f6d9ff 100644 --- a/src/ips_options/ips_pkt_data.cc +++ b/src/ips_options/ips_pkt_data.cc @@ -36,7 +36,7 @@ static THREAD_LOCAL ProfileStats pktDataPerfStats; class PktDataOption : public IpsOption { public: - PktDataOption() : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) { } + PktDataOption() : IpsOption(s_name) { } CursorActionType get_cursor_type() const override { return CAT_SET_RAW; } diff --git a/src/ips_options/ips_raw_data.cc b/src/ips_options/ips_raw_data.cc index b2976d0e2..edb040c43 100644 --- a/src/ips_options/ips_raw_data.cc +++ b/src/ips_options/ips_raw_data.cc @@ -36,7 +36,7 @@ static THREAD_LOCAL ProfileStats rawDataPerfStats; class RawDataOption : public IpsOption { public: - RawDataOption() : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) { } + RawDataOption() : IpsOption(s_name) { } CursorActionType get_cursor_type() const override { return CAT_SET_RAW; } diff --git a/src/ips_options/ips_regex.cc b/src/ips_options/ips_regex.cc index 21617a4f3..8dae412b3 100644 --- a/src/ips_options/ips_regex.cc +++ b/src/ips_options/ips_regex.cc @@ -50,7 +50,7 @@ struct RegexConfig { hs_database_t* db; std::string re; - PatternMatchData pmd; + PatternMatchData pmd = { }; bool pcre_upgrade; RegexConfig() @@ -58,7 +58,6 @@ struct RegexConfig void reset() { - memset(&pmd, 0, sizeof(pmd)); re.clear(); db = nullptr; pcre_upgrade = false; @@ -123,12 +122,11 @@ uint32_t RegexOption::hash() const { uint32_t a = config.pmd.flags; uint32_t b = config.pmd.mpse_flags; - uint32_t c = config.pmd.pm_type; + uint32_t c = IpsOption::hash(); mix(a, b, c); - a += IpsOption::hash(); - mix_str(a, b, c, config.re.c_str()); + finalize(a, b, c); return c; @@ -142,7 +140,6 @@ bool RegexOption::operator==(const IpsOption& ips) const const RegexOption& rhs = (const RegexOption&)ips; if ( config.re == rhs.config.re and - config.pmd.pm_type == rhs.config.pmd.pm_type and config.pmd.flags == rhs.config.pmd.flags and config.pmd.mpse_flags == rhs.config.pmd.mpse_flags ) return true; @@ -409,12 +406,11 @@ static Module* mod_ctor() static void mod_dtor(Module* p) { delete p; } -static IpsOption* regex_ctor(Module* m, OptTreeNode* otn) +static IpsOption* regex_ctor(Module* m, OptTreeNode*) { RegexModule* mod = (RegexModule*)m; RegexConfig c; mod->get_data(c); - c.pmd.pm_type = otn->sticky_buf; return new RegexOption(c); } diff --git a/src/ips_options/ips_sd_pattern.cc b/src/ips_options/ips_sd_pattern.cc index d5000bdd7..c44c4e543 100644 --- a/src/ips_options/ips_sd_pattern.cc +++ b/src/ips_options/ips_sd_pattern.cc @@ -72,7 +72,7 @@ static THREAD_LOCAL SdStats s_stats; struct SdPatternConfig { - PatternMatchData pmd; + PatternMatchData pmd = { }; hs_database_t* db; std::string pii; @@ -93,7 +93,6 @@ struct SdPatternConfig void reset() { - memset(&pmd, 0, sizeof(pmd)); pii.clear(); threshold = 1; obfuscate_pii = false; @@ -128,7 +127,7 @@ private: }; SdPatternOption::SdPatternOption(const SdPatternConfig& c) : - IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_USE), config(c) + IpsOption(s_name), config(c) { if ( !scratcher->allocate(config.db) ) ParseError("can't allocate scratch for sd_pattern '%s'", config.pii.c_str()); @@ -148,13 +147,14 @@ SdPatternOption::~SdPatternOption() uint32_t SdPatternOption::hash() const { uint32_t a = config.pmd.pattern_size; - uint32_t b = config.pmd.pm_type; + uint32_t b = IpsOption::hash(); uint32_t c = config.threshold; mix(a, b, c); - a += IpsOption::hash(); mix_str(a, b, c, config.pii.c_str()); + //mix_str(a, b, c, config.pmd.sticky_buf.c_str()); + finalize(a, b, c); return c; @@ -402,12 +402,11 @@ static void mod_dtor(Module* p) delete p; } -static IpsOption* sd_pattern_ctor(Module* m, OptTreeNode* otn) +static IpsOption* sd_pattern_ctor(Module* m, OptTreeNode*) { SdPatternModule* mod = (SdPatternModule*)m; SdPatternConfig c; mod->get_data(c); - c.pmd.pm_type = otn->sticky_buf; return new SdPatternOption(c); } diff --git a/src/ips_options/ips_vba_data.cc b/src/ips_options/ips_vba_data.cc index 1a049507c..671eaaa11 100644 --- a/src/ips_options/ips_vba_data.cc +++ b/src/ips_options/ips_vba_data.cc @@ -33,7 +33,7 @@ LiteralSearch::Handle* search_handle = nullptr; const LiteralSearch* searcher = nullptr; CursorActionType VbaDataOption::get_cursor_type() const -{ return CAT_SET_VBA; } +{ return CAT_SET_FAST_PATTERN; } IpsOption::EvalStatus VbaDataOption::eval(Cursor& c, Packet* p) { diff --git a/src/ips_options/ips_vba_data.h b/src/ips_options/ips_vba_data.h index ead07a3b5..2ab31ff99 100644 --- a/src/ips_options/ips_vba_data.h +++ b/src/ips_options/ips_vba_data.h @@ -39,7 +39,7 @@ extern const snort::LiteralSearch* searcher ; class VbaDataOption : public snort::IpsOption { public: - VbaDataOption() : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) { } + VbaDataOption() : IpsOption(s_name) { } snort::CursorActionType get_cursor_type() const override; diff --git a/src/ips_options/test/ips_regex_test.cc b/src/ips_options/test/ips_regex_test.cc index 6f18b8128..3559143de 100644 --- a/src/ips_options/test/ips_regex_test.cc +++ b/src/ips_options/test/ips_regex_test.cc @@ -144,11 +144,9 @@ static IpsOption* get_option(Module* mod, const char* pat) mod->end(ips_regex->name, 0, nullptr); OptTreeNode otn; - otn.sticky_buf = 0; const IpsApi* api = (const IpsApi*) ips_regex; IpsOption* opt = api->ctor(mod, &otn); - IpsOption::set_buffer("pkt_data"); return opt; } diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index ce4d2c7b0..8d5fc9df6 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -318,7 +318,6 @@ void SnortConfig::setup() } ParseRulesFinish(this); - ShowPolicyStats(this); /* Need to do this after dynamic detection stuff is initialized, too */ IpsManager::verify(this); diff --git a/src/managers/inspector_manager.cc b/src/managers/inspector_manager.cc index 7f440f446..220a0a769 100644 --- a/src/managers/inspector_manager.cc +++ b/src/managers/inspector_manager.cc @@ -30,6 +30,7 @@ #include "binder/bind_module.h" #include "detection/detect.h" #include "detection/detection_engine.h" +#include "detection/fp_utils.h" #include "flow/flow.h" #include "flow/session.h" #include "log/messages.h" @@ -862,6 +863,7 @@ void InspectorManager::add_plugin(const InspectApi* api) { PHObject* g = new PHObject(*api); s_handlers.emplace_back(g); + update_buffer_map(api->buffers, api->service); } static const InspectApi* get_plugin(const char* keyword) diff --git a/src/managers/ips_manager.cc b/src/managers/ips_manager.cc index 22753c8b5..fca81c886 100644 --- a/src/managers/ips_manager.cc +++ b/src/managers/ips_manager.cc @@ -349,9 +349,6 @@ void IpsManager::reset_options() { for ( auto& p : s_options ) p.second->count = 0; - - // this is the default when we start parsing a rule body - IpsOption::set_buffer("pkt_data"); } void IpsManager::setup_options(const SnortConfig* sc) diff --git a/src/managers/test/get_inspector_stubs.h b/src/managers/test/get_inspector_stubs.h index 832c91a1d..5d81ab2fe 100644 --- a/src/managers/test/get_inspector_stubs.h +++ b/src/managers/test/get_inspector_stubs.h @@ -38,6 +38,7 @@ void BinderModule::add(const char*, const char*) { } void BinderModule::add(unsigned, const char*) { } void set_default_policy(const snort::SnortConfig*) { } +void update_buffer_map(const char**, const char*) { } namespace snort { diff --git a/src/network_inspectors/appid/test/appid_discovery_test.cc b/src/network_inspectors/appid/test/appid_discovery_test.cc index 0bd3a3b2e..7589d037e 100644 --- a/src/network_inspectors/appid/test/appid_discovery_test.cc +++ b/src/network_inspectors/appid/test/appid_discovery_test.cc @@ -66,7 +66,7 @@ Inspector::Inspector() } Inspector::~Inspector() = default; bool Inspector::likes(Packet*) { return true; } -bool Inspector::get_buf(const char*, Packet*, InspectionBuffer&) { return true; } +bool Inspector::get_buf(const char*, Packet*, InspectionBuffer&) { return false; } class StreamSplitter* Inspector::get_splitter(bool) { return nullptr; } // Stubs for module diff --git a/src/parser/parse_conf.cc b/src/parser/parse_conf.cc index c86756578..e5e95f647 100644 --- a/src/parser/parse_conf.cc +++ b/src/parser/parse_conf.cc @@ -33,6 +33,7 @@ #include #include +#include "detection/fp_utils.h" #include "log/messages.h" #include "main/snort_config.h" #include "managers/module_manager.h" @@ -244,12 +245,8 @@ void add_service_to_otn(SnortConfig* sc, OptTreeNode* otn, const char* svc_name) { // well-known services supporting file_data // applies to both alert file and service:file rules - add_service_to_otn(sc, otn, "ftp-data"); - add_service_to_otn(sc, otn, "netbios-ssn"); - add_service_to_otn(sc, otn, "http"); - add_service_to_otn(sc, otn, "pop3"); - add_service_to_otn(sc, otn, "imap"); - add_service_to_otn(sc, otn, "smtp"); + std::string buf = "file_data"; + add_default_services(sc, buf, otn); add_service_to_otn(sc, otn, "file"); return; } diff --git a/src/parser/parse_rule.cc b/src/parser/parse_rule.cc index 5d5cfb389..f648f57fb 100644 --- a/src/parser/parse_rule.cc +++ b/src/parser/parse_rule.cc @@ -699,7 +699,7 @@ void parse_rule_init() void parse_rule_term() { } -void parse_rule_print() +void parse_rule_print(unsigned fb_total, unsigned fb_unchk, unsigned fb_unset) { if ( !rule_count and !skip_count ) return; @@ -713,6 +713,9 @@ void parse_rule_print() LogCount("so rules", so_rule_count); LogCount("option chains", otn_count); LogCount("chain headers", head_count); + LogCount("flowbits", fb_total); + LogCount("flowbits not checked", fb_unchk); + LogCount("flowbits not set", fb_unset); unsigned ip = ipCnt.src + ipCnt.dst + ipCnt.any + ipCnt.both; unsigned icmp = icmpCnt.src + icmpCnt.dst + icmpCnt.any + icmpCnt.both; @@ -975,7 +978,10 @@ void parse_rule_opt_end(SnortConfig* sc, const char* key, OptTreeNode* otn) CursorActionType cat = ips ? ips->get_cursor_type() : CAT_NONE; if ( cat > CAT_ADJUST ) - otn->sticky_buf = get_pm_type(cat); + { + if ( cat != CAT_SET_RAW ) + otn->set_service_only(); + } if ( type != OPT_TYPE_META ) otn->num_detection_opts++; diff --git a/src/parser/parse_rule.h b/src/parser/parse_rule.h index ca281a02b..a9d78fd89 100644 --- a/src/parser/parse_rule.h +++ b/src/parser/parse_rule.h @@ -34,7 +34,7 @@ struct RuleTreeNode; void parse_rule_init(); void parse_rule_term(); -void parse_rule_print(); +void parse_rule_print(unsigned fb_total, unsigned fb_unchk, unsigned fb_unset); int get_policy_loaded_rule_count(); int get_policy_shared_rule_count(); diff --git a/src/parser/parser.cc b/src/parser/parser.cc index a7e9bf95d..84620e28e 100644 --- a/src/parser/parser.cc +++ b/src/parser/parser.cc @@ -41,6 +41,7 @@ #include "hash/hash_key_operations.h" #include "hash/xhash.h" #include "helpers/directory.h" +#include "ips_options/ips_flowbits.h" #include "log/messages.h" #include "main/modules.h" #include "main/shell.h" @@ -512,7 +513,8 @@ static void reduce_rtns(SnortConfig* sc) for ( auto node = sc->otn_map->find_first(); node; node = sc->otn_map->find_next() ) { OptTreeNode* otn = (OptTreeNode*)node->data; - if ( !otn ) + + if ( !otn or otn->service_only() ) continue; for ( auto pid = 0; pid < otn->proto_node_num; ++pid ) @@ -528,19 +530,7 @@ static void reduce_rtns(SnortConfig* sc) } } -void ParseRulesFinish(SnortConfig* sc) -{ - if ( !sc->dump_rule_info() ) - reduce_rtns(sc); - - set_ips_policy(sc, 0); - - /* Compile/Finish and Print the PortList Tables */ - PortTablesFinish(sc->port_tables, sc->fast_pattern_config); - parse_rule_print(); -} - -void ShowPolicyStats(const SnortConfig* sc) +static void ShowPolicyStats(const SnortConfig* sc) { std::unordered_map stats; std::multimap sorted_stats; @@ -600,6 +590,23 @@ void ShowPolicyStats(const SnortConfig* sc) s.second.enabled, " ", s.second.file); } +void ParseRulesFinish(SnortConfig* sc) +{ + ShowPolicyStats(sc); + + if ( !sc->dump_rule_info() ) + reduce_rtns(sc); + + set_ips_policy(sc, 0); + + /* Compile/Finish and Print the PortList Tables */ + PortTablesFinish(sc->port_tables, sc->fast_pattern_config); + + unsigned total, unchk, unset; + flowbits_counts(total, unchk, unset); + parse_rule_print(total, unchk, unset); +} + /**************************************************************************** * * Function: CreateRuleType diff --git a/src/parser/parser.h b/src/parser/parser.h index fa1beb7fb..3311259c3 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -45,7 +45,6 @@ void inc_parse_position(); snort::SnortConfig* ParseSnortConf(const snort::SnortConfig*, const char* fname = nullptr); void ParseRules(snort::SnortConfig*); void ParseRulesFinish(snort::SnortConfig*); -void ShowPolicyStats(const snort::SnortConfig*); char* ProcessFileOption(snort::SnortConfig*, const char*); void SetRuleStates(snort::SnortConfig*); diff --git a/src/payload_injector/test/payload_injector_test.cc b/src/payload_injector/test/payload_injector_test.cc index 6ba1df06a..6adfc7c6b 100644 --- a/src/payload_injector/test/payload_injector_test.cc +++ b/src/payload_injector/test/payload_injector_test.cc @@ -96,7 +96,7 @@ Inspector::Inspector() Inspector::~Inspector() = default; bool Inspector::likes(Packet*) { return true; } -bool Inspector::get_buf(const char*, Packet*, InspectionBuffer&) { return true; } +bool Inspector::get_buf(const char*, Packet*, InspectionBuffer&) { return false; } class StreamSplitter* Inspector::get_splitter(bool) { return nullptr; } } diff --git a/src/ports/port_group.cc b/src/ports/port_group.cc index 1ece7a326..f39b7b924 100644 --- a/src/ports/port_group.cc +++ b/src/ports/port_group.cc @@ -24,8 +24,8 @@ #include "port_group.h" #include "detection/detection_options.h" +#include "framework/ips_option.h" #include "framework/mpse.h" -#include "framework/mpse_batch.h" #include "utils/util.h" void RuleGroup::add_rule() @@ -35,11 +35,10 @@ void RuleGroup::add_rule() RuleGroup::~RuleGroup() { - delete_nfp_rules(); - - for (int i = PM_TYPE_PKT; i < PM_TYPE_MAX; i++) - delete mpsegrp[i]; + for ( auto* it : pm_list ) + delete it; + delete_nfp_rules(); free_detection_option_root(&nfp_tree); } @@ -80,3 +79,24 @@ void RuleGroup::delete_nfp_rules() nfp_head = nullptr; } +PatternMatcher* RuleGroup::get_pattern_matcher(PatternMatcher::Type t, const char* s) +{ + bool raw = false; + + if ( !strcmp(s, "raw_data") ) + { + s = "pkt_data"; + raw = true; + } + for ( auto& it : pm_list ) + { + if ( it->type == t and !strcmp(it->name, s) ) + { + it->raw_data = raw; + return it; + } + } + pm_list.push_back(new PatternMatcher(t, s, raw)); + return pm_list.back(); +} + diff --git a/src/ports/port_group.h b/src/ports/port_group.h index 1d44e33cf..c66a52b84 100644 --- a/src/ports/port_group.h +++ b/src/ports/port_group.h @@ -25,10 +25,10 @@ #ifndef PORT_GROUP_H #define PORT_GROUP_H -namespace snort -{ - class MpseGroup; -} +#include +#include + +#include "framework/mpse_batch.h" // RuleGroup contains a set of fast patterns in the form of an MPSE and a // set of non-fast-pattern (nfp) rules. when a RuleGroup is selected, the @@ -36,30 +36,10 @@ namespace snort // patterns. it will always run nfp rules since there is no way to filter // them out. -enum PmType -{ - PM_TYPE_PKT = 0, - PM_TYPE_ALT, - PM_TYPE_KEY, - PM_TYPE_HEADER, - PM_TYPE_BODY, - PM_TYPE_FILE, - PM_TYPE_RAW_KEY, - PM_TYPE_RAW_HEADER, - PM_TYPE_METHOD, - PM_TYPE_STAT_CODE, - PM_TYPE_STAT_MSG, - PM_TYPE_COOKIE, - PM_TYPE_JS_DATA, - PM_TYPE_VBA, - PM_TYPE_MAX -}; - -const char* const pm_type_strings[PM_TYPE_MAX] = +namespace snort { - "packet", "alt", "key", "header", "body", "file", "raw_key", "raw_header", - "method", "stat_code", "stat_msg", "cookie", "js_data", "vba" -}; + class IpsOption; +} struct RULE_NODE { @@ -68,6 +48,21 @@ struct RULE_NODE int iRuleNodeID; }; +struct PatternMatcher +{ + enum Type { PMT_PKT, PMT_FILE, PMT_PDU }; + + PatternMatcher(Type t, const char* s, bool r = false) + { type = t; name = s; raw_data = r; } + + Type type; + const char* name; + bool raw_data; + + snort::MpseGroup group; + snort::IpsOption* fp_opt = nullptr; +}; + struct RuleGroup { RuleGroup() = default; @@ -78,7 +73,8 @@ struct RuleGroup RULE_NODE* nfp_tail = nullptr; // pattern matchers - snort::MpseGroup* mpsegrp[PM_TYPE_MAX] = { }; + using PmList = std::vector; + PmList pm_list; // detection option tree void* nfp_tree = nullptr; @@ -89,6 +85,8 @@ struct RuleGroup void add_rule(); bool add_nfp_rule(void*); void delete_nfp_rules(); + + PatternMatcher* get_pattern_matcher(PatternMatcher::Type, const char*); }; #endif diff --git a/src/protocols/packet.h b/src/protocols/packet.h index f5f1949a1..60481652b 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -40,56 +40,54 @@ class IpsContext; class Obfuscator; class SFDAQInstance; -/* packet status flags */ -#define PKT_REBUILT_FRAG 0x00000001 /* is a rebuilt fragment */ -#define PKT_REBUILT_STREAM 0x00000002 /* is a rebuilt stream */ -#define PKT_STREAM_UNEST_UNI 0x00000004 /* is from an unestablished stream and - * we've only seen traffic in one direction */ -#define PKT_STREAM_EST 0x00000008 /* is from an established stream */ - -#define PKT_STREAM_INSERT 0x00000010 /* this packet has been queued for stream reassembly */ -#define PKT_STREAM_TWH 0x00000020 /* packet completes the 3-way handshake */ -#define PKT_FROM_SERVER 0x00000040 /* this packet came from the server - side of a connection (TCP) */ -#define PKT_FROM_CLIENT 0x00000080 /* this packet came from the client - side of a connection (TCP) */ - -#define PKT_PDU_HEAD 0x00000100 /* start of PDU */ -#define PKT_PDU_TAIL 0x00000200 /* end of PDU */ -#define PKT_DETECT_LIMIT 0x00000400 /* alt_dsize is valid */ - -#define PKT_ALLOW_MULTIPLE_DETECT 0x00000800 /* packet has multiple PDUs */ +#define PKT_REBUILT_FRAG 0x00000001 // is a rebuilt fragment +#define PKT_REBUILT_STREAM 0x00000002 // is a rebuilt stream +#define PKT_STREAM_UNEST_UNI 0x00000004 // is from an unestablished stream and + // we've only seen traffic in one direction +#define PKT_STREAM_EST 0x00000008 // is from an established stream + +#define PKT_STREAM_INSERT 0x00000010 // this packet has been queued for stream reassembly +#define PKT_STREAM_TWH 0x00000020 // packet completes the 3-way handshake +#define PKT_FROM_SERVER 0x00000040 // this packet came from the server side of a connection (TCP) +#define PKT_FROM_CLIENT 0x00000080 // this packet came from the client side of a connection (TCP) + +#define PKT_PDU_HEAD 0x00000100 // start of PDU +#define PKT_PDU_TAIL 0x00000200 // end of PDU +#define PKT_DETECT_LIMIT 0x00000400 // alt_dsize is valid + +#define PKT_ALLOW_MULTIPLE_DETECT 0x00000800 // packet has multiple PDUs #define PKT_PAYLOAD_OBFUSCATE 0x00001000 -#define PKT_STATELESS 0x00002000 /* Packet has matched a stateless rule */ -#define PKT_PASS_RULE 0x00004000 /* this packet has matched a pass rule */ -#define PKT_IP_RULE 0x00008000 /* this packet is being evaluated against an IP rule */ -#define PKT_IP_RULE_2ND 0x00010000 /* this packet is being evaluated against an IP rule */ +#define PKT_STATELESS 0x00002000 // Packet has matched a stateless rule +#define PKT_PASS_RULE 0x00004000 // this packet has matched a pass rule +#define PKT_IP_RULE 0x00008000 // this packet is being evaluated against an IP rule +#define PKT_IP_RULE_2ND 0x00010000 // this packet is being evaluated against an IP rule -#define PKT_PSEUDO 0x00020000 /* is a pseudo packet */ -#define PKT_MODIFIED 0x00040000 /* packet had normalizations, etc. */ -#define PKT_RESIZED 0x00080000 /* packet has new size */ +#define PKT_PSEUDO 0x00020000 // is a pseudo packet +#define PKT_MODIFIED 0x00040000 // packet had normalizations, etc. +#define PKT_RESIZED 0x00080000 // packet has new size // neither of these flags will be set for (full) retransmissions or non-data segments // a partial overlap results in out of sequence condition // out of sequence condition is sticky -#define PKT_STREAM_ORDER_OK 0x00100000 /* this segment is in order, w/o gaps */ -#define PKT_STREAM_ORDER_BAD 0x00200000 /* this stream had at least one gap */ +#define PKT_STREAM_ORDER_OK 0x00100000 // this segment is in order, w/o gaps +#define PKT_STREAM_ORDER_BAD 0x00200000 // this stream had at least one gap -#define PKT_FILE_EVENT_SET 0x00400000 -#define PKT_IGNORE 0x00800000 /* this packet should be ignored, based on port */ -#define PKT_RETRANSMIT 0x01000000 // packet is a re-transmitted pkt. -#define PKT_RETRY 0x02000000 /* this packet is being re-evaluated from the internal retry queue */ -#define PKT_USE_DIRECT_INJECT 0x04000000 /* Use ioctl when injecting. */ -#define PKT_HAS_PARENT 0x08000000 /* derived pseudo packet from current wire packet */ +#define PKT_FILE_EVENT_SET 0x00400000 +#define PKT_IGNORE 0x00800000 // this packet should be ignored, based on port +#define PKT_RETRANSMIT 0x01000000 // packet is a re-transmitted pkt. +#define PKT_RETRY 0x02000000 // this packet is being re-evaluated from the internal retry queue +#define PKT_USE_DIRECT_INJECT 0x04000000 // Use ioctl when injecting. +#define PKT_HAS_PARENT 0x08000000 // derived pseudo packet from current wire packet -#define PKT_WAS_SET 0x10000000 /* derived pseudo packet (PDU) from current wire packet */ +#define PKT_WAS_SET 0x10000000 // derived pseudo packet (PDU) from current wire packet -#define PKT_MORE_TO_FLUSH 0x20000000 /* when more data is available to StreamSplitter::scan */ +#define PKT_MORE_TO_FLUSH 0x20000000 // when more data is available to StreamSplitter::scan +#define PKT_FAST_PAT_EVAL 0x40000000 // temporary until IpsOption api updated -#define PKT_UNUSED_FLAGS 0xC0000000 +#define PKT_UNUSED_FLAGS 0x80000000 -#define PKT_TS_OFFLOADED 0x01 +#define TS_PKT_OFFLOADED 0x01 #define PKT_PDU_FULL (PKT_PDU_HEAD | PKT_PDU_TAIL) @@ -319,13 +317,13 @@ struct SO_PUBLIC Packet { return (packet_flags & PKT_RETRY) != 0; } bool is_offloaded() const - { return (ts_packet_flags & PKT_TS_OFFLOADED) != 0; } + { return (ts_packet_flags & TS_PKT_OFFLOADED) != 0; } void set_offloaded() - { ts_packet_flags |= PKT_TS_OFFLOADED; } + { ts_packet_flags |= TS_PKT_OFFLOADED; } void clear_offloaded() - { ts_packet_flags &= (~PKT_TS_OFFLOADED); } + { ts_packet_flags &= (~TS_PKT_OFFLOADED); } bool has_parent() const { return (packet_flags & PKT_HAS_PARENT) != 0; } diff --git a/src/service_inspectors/dce_rpc/dce_smb_inspector.cc b/src/service_inspectors/dce_rpc/dce_smb_inspector.cc index 0a9fc2983..1d75de9ea 100644 --- a/src/service_inspectors/dce_rpc/dce_smb_inspector.cc +++ b/src/service_inspectors/dce_rpc/dce_smb_inspector.cc @@ -152,6 +152,14 @@ static void dce2_smb_dtor(Inspector* p) delete p; } +static const char* dce2_bufs[] = +{ + "dce_iface", + "dce_stub_data", + "file_data", + nullptr +}; + const InspectApi dce2_smb_api = { { @@ -168,7 +176,7 @@ const InspectApi dce2_smb_api = }, IT_SERVICE, PROTO_BIT__PDU, - nullptr, // buffers + dce2_bufs, DCE_SMB_PROTOCOL_ID, dce2_smb_init, nullptr, diff --git a/src/service_inspectors/dce_rpc/dce_tcp.cc b/src/service_inspectors/dce_rpc/dce_tcp.cc index f581fe43d..c04be5ef5 100644 --- a/src/service_inspectors/dce_rpc/dce_tcp.cc +++ b/src/service_inspectors/dce_rpc/dce_tcp.cc @@ -198,6 +198,14 @@ static void dce2_tcp_init() DceContextData::init(DCE2_TRANS_TYPE__TCP); } +static const char* dce2_tcp_bufs[] = +{ + "dce_iface", + "dce_stub_data", + "file_data", + nullptr +}; + const InspectApi dce2_tcp_api = { { @@ -214,7 +222,7 @@ const InspectApi dce2_tcp_api = }, IT_SERVICE, PROTO_BIT__PDU, - nullptr, // buffers + dce2_tcp_bufs, DCE_RPC_SERVICE_NAME, dce2_tcp_init, nullptr, // pterm diff --git a/src/service_inspectors/dce_rpc/dce_udp.cc b/src/service_inspectors/dce_rpc/dce_udp.cc index 24425e6a4..94a409630 100644 --- a/src/service_inspectors/dce_rpc/dce_udp.cc +++ b/src/service_inspectors/dce_rpc/dce_udp.cc @@ -197,6 +197,14 @@ static void dce2_udp_init() DceContextData::init(DCE2_TRANS_TYPE__UDP); } +static const char* dce2_udp_bufs[] = +{ + "dce_iface", + "dce_stub_data", + "file_data", + nullptr +}; + const InspectApi dce2_udp_api = { { @@ -213,7 +221,7 @@ const InspectApi dce2_udp_api = }, IT_SERVICE, PROTO_BIT__UDP, - nullptr, // buffers + dce2_udp_bufs, DCE_RPC_SERVICE_NAME, dce2_udp_init, nullptr, // pterm diff --git a/src/service_inspectors/dce_rpc/ips_dce_iface.cc b/src/service_inspectors/dce_rpc/ips_dce_iface.cc index 8d256dd3f..47e25fcca 100644 --- a/src/service_inspectors/dce_rpc/ips_dce_iface.cc +++ b/src/service_inspectors/dce_rpc/ips_dce_iface.cc @@ -26,6 +26,7 @@ #include #include "detection/pattern_match_data.h" +#include "framework/cursor.h" #include "framework/module.h" #include "framework/ips_option.h" #include "framework/range.h" @@ -219,6 +220,9 @@ public: PatternMatchData* get_alternate_pattern() override; ~Dce2IfaceOption() override; + CursorActionType get_cursor_type() const override + { return CAT_SET_FAST_PATTERN; } + private: const RangeCheck version; const bool any_frag; @@ -363,7 +367,7 @@ bool Dce2IfaceOption::operator==(const IpsOption& ips) const return this == &ips; } -IpsOption::EvalStatus Dce2IfaceOption::eval(Cursor&, Packet* p) +IpsOption::EvalStatus Dce2IfaceOption::eval(Cursor& c, Packet* p) { RuleProfile profile(dce2_iface_perf_stats); @@ -392,6 +396,12 @@ IpsOption::EvalStatus Dce2IfaceOption::eval(Cursor&, Packet* p) return NO_MATCH; } + if (p->packet_flags & PKT_FAST_PAT_EVAL) + { + c.set("pkt_data", p->data, p->dsize); + return MATCH; + } + if (DCE2_UuidCompare((void*)&ropts->iface, &uuid) != 0) { return NO_MATCH; diff --git a/src/service_inspectors/dce_rpc/ips_dce_stub_data.cc b/src/service_inspectors/dce_rpc/ips_dce_stub_data.cc index ccf0b571c..d6e1bd7ae 100644 --- a/src/service_inspectors/dce_rpc/ips_dce_stub_data.cc +++ b/src/service_inspectors/dce_rpc/ips_dce_stub_data.cc @@ -46,12 +46,15 @@ static THREAD_LOCAL ProfileStats dce2_stub_data_perf_stats; class Dce2StubDataOption : public IpsOption { public: - Dce2StubDataOption() : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) { } + Dce2StubDataOption() : IpsOption(s_name) { } uint32_t hash() const override; bool operator==(const IpsOption&) const override; EvalStatus eval(Cursor&, Packet*) override; + + CursorActionType get_cursor_type() const override + { return CAT_SET_FAST_PATTERN; } }; uint32_t Dce2StubDataOption::hash() const diff --git a/src/service_inspectors/dnp3/dnp3.cc b/src/service_inspectors/dnp3/dnp3.cc index e23efaa29..f4bba511a 100644 --- a/src/service_inspectors/dnp3/dnp3.cc +++ b/src/service_inspectors/dnp3/dnp3.cc @@ -66,30 +66,6 @@ static dnp3_session_data_t* set_new_dnp3_session(Packet* p) return(&fd->dnp3_session); } -static const uint8_t* dnp3_get_alt_buffer(Packet* p, unsigned& len) -{ - dnp3_session_data_t* dnp3_sess = get_session_data(p->flow); - len = 0; - - if (dnp3_sess) - { - dnp3_reassembly_data_t* rdata; - /* rdata->buffer will be the alt decode buffer. - This will be returned via the get_buf inspector API*/ - - if (dnp3_sess->direction == DNP3_CLIENT) - rdata = &(dnp3_sess->client_rdata); - else - rdata = &(dnp3_sess->server_rdata); - if (rdata->state == DNP3_REASSEMBLY_STATE__DONE) - { - len = rdata->buflen; - return (const uint8_t*)rdata->buffer; - } - } - return nullptr; -} - static void dnp3_reset_alt_buffer(const Packet* p) { dnp3_session_data_t* dnp3_sess = get_session_data(p->flow); @@ -220,13 +196,10 @@ public: void show(const SnortConfig*) const override; void eval(Packet*) override; - bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override; void clear(Packet*) override; StreamSplitter* get_splitter(bool c2s) override - { - return new Dnp3Splitter(c2s); - } + { return new Dnp3Splitter(c2s); } private: dnp3ProtoConf config; @@ -255,17 +228,6 @@ void Dnp3::eval(Packet* p) process_dnp3(config, p); } -bool Dnp3::get_buf( - InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b) -{ - if ( ibt != InspectionBuffer::IBT_ALT ) - return false; - - b.data = dnp3_get_alt_buffer(p,b.len); - - return (b.data != nullptr); -} - void Dnp3::clear(Packet* p) { dnp3_reset_alt_buffer(p); @@ -303,6 +265,12 @@ static void dnp3_dtor(Inspector* p) delete p; } +static const char* dnp3_bufs[] = +{ + "dnp3_data", + nullptr +}; + const InspectApi dnp3_api = { { @@ -319,7 +287,7 @@ const InspectApi dnp3_api = }, IT_SERVICE, PROTO_BIT__UDP | PROTO_BIT__PDU, - nullptr, // buffers + dnp3_bufs, "dnp3", dnp3_init, nullptr, // pterm diff --git a/src/service_inspectors/dnp3/ips_dnp3_data.cc b/src/service_inspectors/dnp3/ips_dnp3_data.cc index 8ce9b0533..5e4903453 100644 --- a/src/service_inspectors/dnp3/ips_dnp3_data.cc +++ b/src/service_inspectors/dnp3/ips_dnp3_data.cc @@ -47,12 +47,15 @@ static THREAD_LOCAL ProfileStats dnp3_data_perf_stats; class Dnp3DataOption : public IpsOption { public: - Dnp3DataOption() : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) { } + Dnp3DataOption() : IpsOption(s_name) { } uint32_t hash() const override; bool operator==(const IpsOption&) const override; EvalStatus eval(Cursor&, Packet*) override; + + CursorActionType get_cursor_type() const override + { return CAT_SET_FAST_PATTERN; } }; uint32_t Dnp3DataOption::hash() const diff --git a/src/service_inspectors/ftp_telnet/ftp_data.cc b/src/service_inspectors/ftp_telnet/ftp_data.cc index f8a530172..b87c257e3 100644 --- a/src/service_inspectors/ftp_telnet/ftp_data.cc +++ b/src/service_inspectors/ftp_telnet/ftp_data.cc @@ -348,6 +348,12 @@ static void fd_dtor(Inspector* p) delete p; } +static const char* fd_bufs[] = +{ + "file_data", + nullptr +}; + // exported in ftp.cc const InspectApi fd_api = { @@ -365,7 +371,7 @@ const InspectApi fd_api = }, IT_SERVICE, PROTO_BIT__PDU, - nullptr, // buffers + fd_bufs, fd_svc_name, fd_init, nullptr, // pterm diff --git a/src/service_inspectors/ftp_telnet/telnet.cc b/src/service_inspectors/ftp_telnet/telnet.cc index 8fb2b473b..9d0049abb 100644 --- a/src/service_inspectors/ftp_telnet/telnet.cc +++ b/src/service_inspectors/ftp_telnet/telnet.cc @@ -186,9 +186,8 @@ public: bool configure(SnortConfig*) override; void show(const SnortConfig*) const override; - void eval(Packet*) override; - bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override; + void eval(Packet*) override; void clear(Packet*) override; private: @@ -231,17 +230,6 @@ void Telnet::eval(Packet* p) snort_telnet(config, p); } -bool Telnet::get_buf( - InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b) -{ - if ( ibt != InspectionBuffer::IBT_ALT ) - return false; - - b.data = get_telnet_buffer(p, b.len); - - return (b.data != nullptr); -} - void Telnet::clear(Packet* p) { reset_telnet_buffer(p); diff --git a/src/service_inspectors/gtp/gtp_inspect.cc b/src/service_inspectors/gtp/gtp_inspect.cc index 7b28c21c4..bfd0e4093 100644 --- a/src/service_inspectors/gtp/gtp_inspect.cc +++ b/src/service_inspectors/gtp/gtp_inspect.cc @@ -220,6 +220,12 @@ static void gtp_dtor(Inspector* p) //------------------------------------------------------------------------- +static const char* gtp_bufs[] = +{ + "gtp_info", + nullptr +}; + static const InspectApi gtp_api = { { @@ -236,7 +242,7 @@ static const InspectApi gtp_api = }, IT_SERVICE, PROTO_BIT__UDP, - nullptr, + gtp_bufs, "gtp", gtp_init, gtp_term, diff --git a/src/service_inspectors/gtp/ips_gtp_info.cc b/src/service_inspectors/gtp/ips_gtp_info.cc index 752097d5c..bb6785adf 100644 --- a/src/service_inspectors/gtp/ips_gtp_info.cc +++ b/src/service_inspectors/gtp/ips_gtp_info.cc @@ -49,12 +49,12 @@ class GtpInfoOption : public IpsOption public: GtpInfoOption(const uint8_t*); - CursorActionType get_cursor_type() const override - { return CAT_SET_OTHER; } - uint32_t hash() const override; bool operator==(const IpsOption&) const override; + CursorActionType get_cursor_type() const override + { return CAT_SET_OTHER; } + EvalStatus eval(Cursor&, Packet*) override; public: @@ -63,7 +63,7 @@ public: uint8_t types[MAX_GTP_VERSION_CODE + 1]; }; -GtpInfoOption::GtpInfoOption(const uint8_t* t) : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) +GtpInfoOption::GtpInfoOption(const uint8_t* t) : IpsOption(s_name) { for ( int v = 0; v <= MAX_GTP_VERSION_CODE; ++v ) types[v] = t[v]; diff --git a/src/service_inspectors/gtp/ips_gtp_type.cc b/src/service_inspectors/gtp/ips_gtp_type.cc index a358bc894..4c27b25d0 100644 --- a/src/service_inspectors/gtp/ips_gtp_type.cc +++ b/src/service_inspectors/gtp/ips_gtp_type.cc @@ -48,9 +48,6 @@ class GtpTypeOption : public IpsOption public: GtpTypeOption(ByteBitSet*); - CursorActionType get_cursor_type() const override - { return CAT_SET_OTHER; } - uint32_t hash() const override; bool operator==(const IpsOption&) const override; diff --git a/src/service_inspectors/http2_inspect/ips_http2.h b/src/service_inspectors/http2_inspect/ips_http2.h index 1853acb11..7f7bd8a01 100644 --- a/src/service_inspectors/http2_inspect/ips_http2.h +++ b/src/service_inspectors/http2_inspect/ips_http2.h @@ -67,7 +67,7 @@ class Http2IpsOption : public snort::IpsOption { public: Http2IpsOption(const Http2CursorModule* cm) : - snort::IpsOption(cm->key, RULE_OPTION_TYPE_BUFFER_SET), key(cm->key), + snort::IpsOption(cm->key), key(cm->key), buffer_index(cm->buffer_index), cat(cm->cat), psi(cm->psi) {} snort::CursorActionType get_cursor_type() const override { return cat; } EvalStatus eval(Cursor&, snort::Packet*) override; diff --git a/src/service_inspectors/http_inspect/ips_http.cc b/src/service_inspectors/http_inspect/ips_http.cc index 7408ad05e..a0e14a0f8 100644 --- a/src/service_inspectors/http_inspect/ips_http.cc +++ b/src/service_inspectors/http_inspect/ips_http.cc @@ -137,6 +137,7 @@ HttpInspect const* HttpIpsOption::eval_helper(Packet* p) return nullptr; const bool section_match = + (p->packet_flags & PKT_FAST_PAT_EVAL) || (HttpInspect::get_latest_is(p) == inspect_section) || ((HttpInspect::get_latest_is(p) == IS_HEADER) && (inspect_section == IS_FLEX_HEADER)) || ((HttpInspect::get_latest_is(p) == IS_FIRST_BODY) && (inspect_section == IS_BODY)) || diff --git a/src/service_inspectors/http_inspect/ips_http.h b/src/service_inspectors/http_inspect/ips_http.h index 50b025d89..898113236 100644 --- a/src/service_inspectors/http_inspect/ips_http.h +++ b/src/service_inspectors/http_inspect/ips_http.h @@ -82,8 +82,8 @@ private: class HttpIpsOption : public snort::IpsOption { public: - HttpIpsOption(const HttpRuleOptModule* cm, option_type_t type) : - snort::IpsOption(cm->key, type), + HttpIpsOption(const HttpRuleOptModule* cm) : + snort::IpsOption(cm->key), buffer_info(cm->rule_opt_index, cm->sub_id, cm->form), cat(cm->cat), inspect_section(cm->inspect_section) {} snort::CursorActionType get_cursor_type() const override { return cat; } diff --git a/src/service_inspectors/http_inspect/ips_http_buffer.cc b/src/service_inspectors/http_inspect/ips_http_buffer.cc index 9326dfde3..15f0e0718 100644 --- a/src/service_inspectors/http_inspect/ips_http_buffer.cc +++ b/src/service_inspectors/http_inspect/ips_http_buffer.cc @@ -133,15 +133,60 @@ bool HttpBufferRuleOptModule::end(const char*, int, SnortConfig*) return HttpRuleOptModule::end(nullptr, 0, nullptr); } +static InspectionBuffer::Type buf_map[] = +{ +#if 0 + BUFFER_PSI_CLIENT_BODY, BUFFER_PSI_COOKIE, BUFFER_PSI_HEADER, BUFFER_PSI_METHOD, + BUFFER_PSI_RAW_BODY, BUFFER_PSI_RAW_COOKIE, BUFFER_PSI_RAW_HEADER, BUFFER_PSI_RAW_REQUEST, + BUFFER_PSI_RAW_STATUS, BUFFER_PSI_RAW_TRAILER, BUFFER_PSI_RAW_URI, BUFFER_PSI_STAT_CODE, + BUFFER_PSI_STAT_MSG, BUFFER_PSI_TRAILER, BUFFER_PSI_TRUE_IP, BUFFER_PSI_URI, BUFFER_PSI_VERSION, + BUFFER_PSI_JS_DATA, BUFFER_PSI_VBA_DATA, BUFFER_PSI_MAX +#endif + InspectionBuffer::IBT_BODY, + InspectionBuffer::IBT_COOKIE, + InspectionBuffer::IBT_HEADER, + InspectionBuffer::IBT_METHOD, + InspectionBuffer::IBT_MAX, + InspectionBuffer::IBT_MAX, + InspectionBuffer::IBT_RAW_HEADER, + InspectionBuffer::IBT_MAX, + InspectionBuffer::IBT_MAX, + InspectionBuffer::IBT_RAW_HEADER, + InspectionBuffer::IBT_RAW_KEY, + InspectionBuffer::IBT_STAT_CODE, + InspectionBuffer::IBT_STAT_MSG, + InspectionBuffer::IBT_HEADER, + InspectionBuffer::IBT_MAX, + InspectionBuffer::IBT_KEY, + InspectionBuffer::IBT_MAX, + InspectionBuffer::IBT_JS_DATA, + InspectionBuffer::IBT_VBA, + InspectionBuffer::IBT_MAX +}; IpsOption::EvalStatus HttpBufferIpsOption::eval(Cursor& c, Packet* p) { RuleProfile profile(HttpBufferRuleOptModule::http_buffer_ps[idx]); - const HttpInspect* const hi = eval_helper(p); + HttpInspect* hi = const_cast(eval_helper(p)); if (hi == nullptr) return NO_MATCH; - + + if (p->packet_flags & PKT_FAST_PAT_EVAL) + { + InspectionBuffer buf; + InspectionBuffer::Type ibt = buf_map[idx]; + + if (ibt == InspectionBuffer::IBT_MAX) + return NO_MATCH; + + if (!hi->get_fp_buf(ibt, p, buf)) + return NO_MATCH; + + c.set(key, buf.data, buf.len); + return MATCH; + } + const Field& http_buffer = hi->http_get_buf(p, buffer_info); if (http_buffer.length() <= 0) return NO_MATCH; @@ -163,7 +208,7 @@ IpsOption::EvalStatus HttpBufferIpsOption::eval(Cursor& c, Packet* p) static Module* client_body_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_CLIENT_BODY, CAT_SET_BODY, + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_CLIENT_BODY, CAT_SET_FAST_PATTERN, BUFFER_PSI_CLIENT_BODY); } @@ -216,8 +261,8 @@ static const Parameter http_cookie_params[] = static Module* cookie_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_COOKIE, CAT_SET_COOKIE, BUFFER_PSI_COOKIE, - http_cookie_params); + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_COOKIE, CAT_SET_FAST_PATTERN, + BUFFER_PSI_COOKIE, http_cookie_params); } static const IpsApi cookie_api = @@ -277,7 +322,7 @@ static const Parameter http_header_params[] = static Module* header_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_HEADER, CAT_SET_HEADER, + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_HEADER, CAT_SET_FAST_PATTERN, BUFFER_PSI_HEADER, http_header_params); } @@ -328,8 +373,8 @@ static const Parameter http_method_params[] = static Module* method_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_METHOD, CAT_SET_METHOD, BUFFER_PSI_METHOD, - http_method_params); + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_METHOD, CAT_SET_FAST_PATTERN, + BUFFER_PSI_METHOD, http_method_params); } static const IpsApi method_api = @@ -476,7 +521,7 @@ static const Parameter http_raw_header_params[] = static Module* raw_header_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_HEADER, CAT_SET_RAW_HEADER, + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_HEADER, CAT_SET_FAST_PATTERN, BUFFER_PSI_RAW_HEADER, http_raw_header_params); } @@ -630,7 +675,7 @@ static const Parameter http_raw_trailer_params[] = static Module* raw_trailer_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_TRAILER, CAT_SET_RAW_HEADER, + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_TRAILER, CAT_SET_FAST_PATTERN, BUFFER_PSI_RAW_TRAILER, http_raw_trailer_params); } @@ -693,7 +738,7 @@ static const Parameter http_raw_uri_params[] = static Module* raw_uri_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_URI, CAT_SET_RAW_KEY, + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_URI, CAT_SET_FAST_PATTERN, BUFFER_PSI_RAW_URI, http_raw_uri_params); } @@ -742,7 +787,7 @@ static const Parameter http_stat_code_params[] = static Module* stat_code_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_CODE, CAT_SET_STAT_CODE, + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_CODE, CAT_SET_FAST_PATTERN, BUFFER_PSI_STAT_CODE, http_stat_code_params); } @@ -791,7 +836,7 @@ static const Parameter http_stat_msg_params[] = static Module* stat_msg_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_MSG, CAT_SET_STAT_MSG, + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_MSG, CAT_SET_FAST_PATTERN, BUFFER_PSI_STAT_MSG, http_stat_msg_params); } @@ -844,7 +889,7 @@ static const Parameter http_trailer_params[] = static Module* trailer_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRAILER, CAT_SET_HEADER, + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRAILER, CAT_SET_FAST_PATTERN, BUFFER_PSI_TRAILER, http_trailer_params); } @@ -958,8 +1003,8 @@ static const Parameter http_uri_params[] = static Module* uri_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_URI, CAT_SET_KEY, BUFFER_PSI_URI, - http_uri_params); + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_URI, CAT_SET_FAST_PATTERN, + BUFFER_PSI_URI, http_uri_params); } static const IpsApi uri_api = @@ -1051,7 +1096,7 @@ static const IpsApi version_api = #define IPS_HELP "rule option to set detection cursor to normalized JavaScript data" static Module* js_data_mod_ctor() { - return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, BUFFER_JS_DATA, CAT_SET_JS_DATA, + return new HttpBufferRuleOptModule(IPS_OPT, IPS_HELP, BUFFER_JS_DATA, CAT_SET_FAST_PATTERN, BUFFER_PSI_JS_DATA); } diff --git a/src/service_inspectors/http_inspect/ips_http_buffer.h b/src/service_inspectors/http_inspect/ips_http_buffer.h index cd568db32..8af7d0c7f 100644 --- a/src/service_inspectors/http_inspect/ips_http_buffer.h +++ b/src/service_inspectors/http_inspect/ips_http_buffer.h @@ -69,7 +69,7 @@ class HttpBufferIpsOption : public HttpIpsOption { public: HttpBufferIpsOption(const HttpBufferRuleOptModule* cm) : - HttpIpsOption(cm, RULE_OPTION_TYPE_BUFFER_SET), idx(cm->idx), + HttpIpsOption(cm), idx(cm->idx), key(cm->key) {} EvalStatus eval(Cursor&, snort::Packet*) override; diff --git a/src/service_inspectors/http_inspect/ips_http_num_hdrs.cc b/src/service_inspectors/http_inspect/ips_http_num_hdrs.cc index c3c4d5d0d..7a11aba2e 100644 --- a/src/service_inspectors/http_inspect/ips_http_num_hdrs.cc +++ b/src/service_inspectors/http_inspect/ips_http_num_hdrs.cc @@ -126,7 +126,7 @@ static const Parameter http_num_hdrs_params[] = static Module* num_hdrs_mod_ctor() { - return new HttpNumHdrsRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_HDRS, CAT_SET_OTHER, + return new HttpNumHdrsRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_HDRS, CAT_NONE, NUM_HDRS_PSI_HDRS, http_num_hdrs_params); } @@ -165,7 +165,7 @@ static const IpsApi num_headers_api = static Module* num_trailers_mod_ctor() { - return new HttpNumHdrsRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_TRAILERS, CAT_SET_OTHER, + return new HttpNumHdrsRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_TRAILERS, CAT_NONE, NUM_HDRS_PSI_TRAILERS, http_num_hdrs_params); } diff --git a/src/service_inspectors/http_inspect/ips_http_num_hdrs.h b/src/service_inspectors/http_inspect/ips_http_num_hdrs.h index 54a8da205..ccb3f8306 100644 --- a/src/service_inspectors/http_inspect/ips_http_num_hdrs.h +++ b/src/service_inspectors/http_inspect/ips_http_num_hdrs.h @@ -58,7 +58,7 @@ class HttpNumHdrsIpsOption : public HttpIpsOption { public: HttpNumHdrsIpsOption(const HttpNumHdrsRuleOptModule* cm) : - HttpIpsOption(cm, RULE_OPTION_TYPE_OTHER), idx(cm->idx), range(cm->range) {} + HttpIpsOption(cm), idx(cm->idx), range(cm->range) {} EvalStatus eval(Cursor&, snort::Packet*) override; uint32_t hash() const override; bool operator==(const snort::IpsOption& ips) const override; diff --git a/src/service_inspectors/http_inspect/ips_http_param.h b/src/service_inspectors/http_inspect/ips_http_param.h index 40cf593a2..9557363c5 100644 --- a/src/service_inspectors/http_inspect/ips_http_param.h +++ b/src/service_inspectors/http_inspect/ips_http_param.h @@ -53,7 +53,7 @@ class HttpParamIpsOption : public HttpIpsOption { public: HttpParamIpsOption(const HttpParamRuleOptModule* cm) : - HttpIpsOption(cm, RULE_OPTION_TYPE_BUFFER_SET), + HttpIpsOption(cm), key(cm->key), http_param(cm->param, cm->nocase) {} EvalStatus eval(Cursor&, snort::Packet*) override; uint32_t hash() const override; diff --git a/src/service_inspectors/http_inspect/ips_http_test.cc b/src/service_inspectors/http_inspect/ips_http_test.cc index 835054a73..d78d2eae0 100644 --- a/src/service_inspectors/http_inspect/ips_http_test.cc +++ b/src/service_inspectors/http_inspect/ips_http_test.cc @@ -206,7 +206,7 @@ static const Parameter hdr_test_params[] = static Module* http_header_test_mod_ctor() { - return new HttpTestRuleOptModule(IPS_OPT, IPS_HELP, HTTP_HEADER_TEST, CAT_SET_OTHER, + return new HttpTestRuleOptModule(IPS_OPT, IPS_HELP, HTTP_HEADER_TEST, CAT_NONE, TEST_PSI_HEADER_TEST, hdr_test_params); } @@ -265,7 +265,7 @@ check whether it is a number, or check if the field is absent" static Module* http_trailer_test_mod_ctor() { - return new HttpTestRuleOptModule(IPS_OPT, IPS_HELP, HTTP_TRAILER_TEST, CAT_SET_OTHER, + return new HttpTestRuleOptModule(IPS_OPT, IPS_HELP, HTTP_TRAILER_TEST, CAT_NONE, TEST_PSI_TRAILER_TEST, trailer_test_params); } diff --git a/src/service_inspectors/http_inspect/ips_http_test.h b/src/service_inspectors/http_inspect/ips_http_test.h index 681e47a15..b98f75347 100644 --- a/src/service_inspectors/http_inspect/ips_http_test.h +++ b/src/service_inspectors/http_inspect/ips_http_test.h @@ -63,7 +63,7 @@ class HttpTestIpsOption : public HttpIpsOption { public: HttpTestIpsOption(const HttpTestRuleOptModule* cm) : - HttpIpsOption(cm, RULE_OPTION_TYPE_OTHER), idx(cm->idx), check(cm->check), + HttpIpsOption(cm), idx(cm->idx), check(cm->check), numeric(cm->numeric), absent(cm->absent) {} EvalStatus eval(Cursor&, snort::Packet*) override; uint32_t hash() const override; diff --git a/src/service_inspectors/http_inspect/ips_http_version.cc b/src/service_inspectors/http_inspect/ips_http_version.cc index 90b2e3ffb..23c9980f5 100644 --- a/src/service_inspectors/http_inspect/ips_http_version.cc +++ b/src/service_inspectors/http_inspect/ips_http_version.cc @@ -153,7 +153,7 @@ static const Parameter version_match_params[] = static Module* version_match_mod_ctor() { - return new HttpVersionRuleOptModule(IPS_OPT, IPS_HELP, HTTP_VERSION_MATCH, CAT_SET_OTHER, + return new HttpVersionRuleOptModule(IPS_OPT, IPS_HELP, HTTP_VERSION_MATCH, CAT_NONE, version_match_params); } diff --git a/src/service_inspectors/http_inspect/ips_http_version.h b/src/service_inspectors/http_inspect/ips_http_version.h index 2a89c6203..873309be0 100644 --- a/src/service_inspectors/http_inspect/ips_http_version.h +++ b/src/service_inspectors/http_inspect/ips_http_version.h @@ -53,7 +53,7 @@ class HttpVersionIpsOption : public HttpIpsOption { public: HttpVersionIpsOption(const HttpVersionRuleOptModule* cm) : - HttpIpsOption(cm, RULE_OPTION_TYPE_OTHER), version_flags(cm->version_flags) {} + HttpIpsOption(cm), version_flags(cm->version_flags) {} EvalStatus eval(Cursor&, snort::Packet*) override; uint32_t hash() const override; bool operator==(const snort::IpsOption& ips) const override; diff --git a/src/service_inspectors/imap/imap.cc b/src/service_inspectors/imap/imap.cc index 9277e3278..afb6a8055 100644 --- a/src/service_inspectors/imap/imap.cc +++ b/src/service_inspectors/imap/imap.cc @@ -839,6 +839,13 @@ static void imap_dtor(Inspector* p) delete p; } +static const char* imap_bufs[] = +{ + "file_data", + "vba_data", + nullptr +}; + const InspectApi imap_api = { { @@ -855,7 +862,7 @@ const InspectApi imap_api = }, IT_SERVICE, PROTO_BIT__PDU, - nullptr, // buffers + imap_bufs, "imap", imap_init, imap_term, // pterm diff --git a/src/service_inspectors/mms/ips_mms_data.cc b/src/service_inspectors/mms/ips_mms_data.cc index dc50af24d..08e02747b 100644 --- a/src/service_inspectors/mms/ips_mms_data.cc +++ b/src/service_inspectors/mms/ips_mms_data.cc @@ -45,10 +45,10 @@ static THREAD_LOCAL ProfileStats mms_data_prof; class MmsDataOption : public IpsOption { public: - MmsDataOption() : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) { } + MmsDataOption() : IpsOption(s_name) { } CursorActionType get_cursor_type() const override - { return CAT_SET_OTHER; } + { return CAT_SET_FAST_PATTERN; } EvalStatus eval(Cursor&, Packet*) override; }; diff --git a/src/service_inspectors/mms/mms.cc b/src/service_inspectors/mms/mms.cc index 3b6008d3a..98620dcc0 100644 --- a/src/service_inspectors/mms/mms.cc +++ b/src/service_inspectors/mms/mms.cc @@ -149,6 +149,12 @@ static void mms_dtor(Inspector* p) //------------------------------------------------------------------------- +static const char* mms_bufs[] = +{ + "mms_data", + nullptr +}; + static const InspectApi mms_api = { { @@ -165,7 +171,7 @@ static const InspectApi mms_api = }, IT_SERVICE, PROTO_BIT__PDU, - nullptr, + mms_bufs, "mms", mms_init, nullptr, diff --git a/src/service_inspectors/modbus/ips_modbus_data.cc b/src/service_inspectors/modbus/ips_modbus_data.cc index 651c0de85..a323cb370 100644 --- a/src/service_inspectors/modbus/ips_modbus_data.cc +++ b/src/service_inspectors/modbus/ips_modbus_data.cc @@ -45,12 +45,15 @@ static THREAD_LOCAL ProfileStats modbus_data_prof; class ModbusDataOption : public IpsOption { public: - ModbusDataOption() : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) { } + ModbusDataOption() : IpsOption(s_name) { } uint32_t hash() const override; bool operator==(const IpsOption&) const override; EvalStatus eval(Cursor&, Packet*) override; + + CursorActionType get_cursor_type() const override + { return CAT_SET_FAST_PATTERN; } }; uint32_t ModbusDataOption::hash() const diff --git a/src/service_inspectors/modbus/modbus.cc b/src/service_inspectors/modbus/modbus.cc index beed02e22..e4b9e7472 100644 --- a/src/service_inspectors/modbus/modbus.cc +++ b/src/service_inspectors/modbus/modbus.cc @@ -71,6 +71,7 @@ class Modbus : public Inspector public: // default ctor / dtor void eval(Packet*) override; + bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override; int get_message_type(int version, const char* name); int get_info_type(int version, const char* name); @@ -118,6 +119,16 @@ void Modbus::eval(Packet* p) mfd->reset(); } +bool Modbus::get_buf(InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b) +{ + if ( ibt != InspectionBuffer::IBT_BODY or p->dsize <= MODBUS_MIN_LEN ) + return false; + + b.data = p->data + MODBUS_MIN_LEN; + b.len = p->dsize - MODBUS_MIN_LEN; + return true; +} + //------------------------------------------------------------------------- // plugin stuff //------------------------------------------------------------------------- @@ -145,6 +156,12 @@ static void modbus_dtor(Inspector* p) //------------------------------------------------------------------------- +static const char* modbus_bufs[] = +{ + "modbus_data", + nullptr +}; + static const InspectApi modbus_api = { { @@ -161,7 +178,7 @@ static const InspectApi modbus_api = }, IT_SERVICE, PROTO_BIT__PDU, - nullptr, + modbus_bufs, "modbus", modbus_init, nullptr, diff --git a/src/service_inspectors/pop/pop.cc b/src/service_inspectors/pop/pop.cc index 0f4ff54bb..8c9e67634 100644 --- a/src/service_inspectors/pop/pop.cc +++ b/src/service_inspectors/pop/pop.cc @@ -778,6 +778,13 @@ static void pop_dtor(Inspector* p) delete p; } +static const char* pop_bufs[] = +{ + "file_data", + "vba_data", + nullptr +}; + const InspectApi pop_api = { { @@ -794,7 +801,7 @@ const InspectApi pop_api = }, IT_SERVICE, PROTO_BIT__PDU, - nullptr, // buffers + pop_bufs, "pop3", pop_init, pop_term, // pterm diff --git a/src/service_inspectors/rpc_decode/rpc_decode.cc b/src/service_inspectors/rpc_decode/rpc_decode.cc index d20b2c75b..5b5d530c4 100644 --- a/src/service_inspectors/rpc_decode/rpc_decode.cc +++ b/src/service_inspectors/rpc_decode/rpc_decode.cc @@ -763,8 +763,6 @@ public: void eval(Packet*) override; void clear(Packet*) override; - bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override; - StreamSplitter* get_splitter(bool c2s) override { return c2s ? new LogSplitter(c2s) : nullptr; } }; @@ -823,18 +821,6 @@ void RpcDecode::eval(Packet* p) RpcPreprocEvent(rsdata, ConvertRPC(rsdata, p)); } -bool RpcDecode::get_buf(InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b) -{ - if ( ibt != InspectionBuffer::IBT_ALT ) - return false; - - const DataBuffer& buf = DetectionEngine::get_alt_buffer(p); - b.len = buf.len; - b.data = (b.len > 0) ? buf.data : nullptr; - - return (b.data != nullptr); -} - void RpcDecode::clear(Packet* p) { DataBuffer& buf = DetectionEngine::get_alt_buffer(p); diff --git a/src/service_inspectors/s7commplus/ips_s7comm_content.cc b/src/service_inspectors/s7commplus/ips_s7comm_content.cc index ba58dcf75..034d2b454 100644 --- a/src/service_inspectors/s7commplus/ips_s7comm_content.cc +++ b/src/service_inspectors/s7commplus/ips_s7comm_content.cc @@ -45,12 +45,15 @@ static THREAD_LOCAL ProfileStats s7commplus_content_prof; class S7commplusContentOption : public IpsOption { public: - S7commplusContentOption() : IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_SET) { } + S7commplusContentOption() : IpsOption(s_name) { } uint32_t hash() const override; bool operator==(const IpsOption&) const override; EvalStatus eval(Cursor&, Packet*) override; + + CursorActionType get_cursor_type() const override + { return CAT_SET_FAST_PATTERN; } }; uint32_t S7commplusContentOption::hash() const diff --git a/src/service_inspectors/s7commplus/s7comm.cc b/src/service_inspectors/s7commplus/s7comm.cc index cc27d101b..d63ea36df 100644 --- a/src/service_inspectors/s7commplus/s7comm.cc +++ b/src/service_inspectors/s7commplus/s7comm.cc @@ -145,6 +145,12 @@ static void s7commplus_dtor(Inspector* p) //------------------------------------------------------------------------- +static const char* s7commplus_bufs[] = +{ + "s7commplus_content", + nullptr +}; + static const InspectApi s7commplus_api = { { @@ -161,7 +167,7 @@ static const InspectApi s7commplus_api = }, IT_SERVICE, PROTO_BIT__PDU, - nullptr, + s7commplus_bufs, "s7commplus", s7commplus_init, nullptr, diff --git a/src/service_inspectors/sip/ips_sip.cc b/src/service_inspectors/sip/ips_sip.cc index 981888155..525ad4fdf 100644 --- a/src/service_inspectors/sip/ips_sip.cc +++ b/src/service_inspectors/sip/ips_sip.cc @@ -82,9 +82,7 @@ static void opt_dtor(IpsOption* p) class SipIpsOption : public IpsOption { public: - SipIpsOption( - const char* s, SipIdx psi, CursorActionType c) : - IpsOption(s, RULE_OPTION_TYPE_BUFFER_SET) + SipIpsOption(const char* s, SipIdx psi, CursorActionType c) : IpsOption(s) { key = s; cat = c; idx = psi; } CursorActionType get_cursor_type() const override @@ -155,7 +153,7 @@ static Module* header_mod_ctor() static IpsOption* header_opt_ctor(Module*, OptTreeNode*) { - return new SipIpsOption(IPS_OPT, SIP_HEADER, CAT_SET_HEADER); + return new SipIpsOption(IPS_OPT, SIP_HEADER, CAT_SET_FAST_PATTERN); } static const IpsApi header_api = @@ -200,7 +198,7 @@ static Module* body_mod_ctor() static IpsOption* body_opt_ctor(Module*, OptTreeNode*) { - return new SipIpsOption(IPS_OPT, SIP_BODY, CAT_SET_BODY); + return new SipIpsOption(IPS_OPT, SIP_BODY, CAT_SET_FAST_PATTERN); } static const IpsApi body_api = diff --git a/src/service_inspectors/sip/sip.cc b/src/service_inspectors/sip/sip.cc index 9fe05f878..e66902118 100644 --- a/src/service_inspectors/sip/sip.cc +++ b/src/service_inspectors/sip/sip.cc @@ -187,7 +187,6 @@ public: void show(const SnortConfig*) const override; void eval(Packet*) override; - bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override; class StreamSplitter* get_splitter(bool to_server) override { return new SipSplitter(to_server); } @@ -243,47 +242,6 @@ void Sip::eval(Packet* p) snort_sip(config, p); } -bool Sip::get_buf( - InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b) -{ - SIPData* sd; - SIP_Roptions* ropts; - const uint8_t* data = nullptr; - unsigned len = 0; - - sd = get_sip_session_data(p->flow); - if (!sd) - return false; - - ropts = &sd->ropts; - - switch ( ibt ) - { - case InspectionBuffer::IBT_HEADER: - data = ropts->header_data; - len = ropts->header_len; - break; - - case InspectionBuffer::IBT_BODY: - data = ropts->body_data; - len = ropts->body_len; - break; - - default: - break; - } - - if (!len) - return false; - - assert(data); - - b.data = data; - b.len = len; - - return true; -} - //------------------------------------------------------------------------- // api stuff //------------------------------------------------------------------------- @@ -310,6 +268,13 @@ static void sip_dtor(Inspector* p) delete p; } +static const char* sip_bufs[] = +{ + "sip_header", + "sip_body", + nullptr +}; + const InspectApi sip_api = { { @@ -326,7 +291,7 @@ const InspectApi sip_api = }, IT_SERVICE, PROTO_BIT__UDP | PROTO_BIT__PDU, - nullptr, // buffers + sip_bufs, "sip", sip_init, nullptr, // pterm diff --git a/src/service_inspectors/smtp/smtp.cc b/src/service_inspectors/smtp/smtp.cc index c27691e05..92e77602c 100644 --- a/src/service_inspectors/smtp/smtp.cc +++ b/src/service_inspectors/smtp/smtp.cc @@ -1446,8 +1446,8 @@ public: bool configure(SnortConfig*) override; void show(const SnortConfig*) const override; + void eval(Packet*) override; - bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override; void clear(Packet*) override; StreamSplitter* get_splitter(bool c2s) override @@ -1461,8 +1461,7 @@ public: void ProcessSmtpCmdsList(const SmtpCmd*); - bool get_fp_buf(snort::InspectionBuffer::Type ibt, snort::Packet* p, - snort::InspectionBuffer& b) override; + bool get_fp_buf(snort::InspectionBuffer::Type, snort::Packet*, snort::InspectionBuffer&) override; private: SmtpProtoConf* config; @@ -1516,40 +1515,6 @@ void Smtp::eval(Packet* p) snort_smtp(config, p); } -bool Smtp::get_buf(InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b) -{ - // Fast pattern buffers only supplied at specific times - switch (ibt) - { - case InspectionBuffer::IBT_ALT: - b.data = SMTP_GetAltBuffer(p, b.len); - return (b.data != nullptr); - - case InspectionBuffer::IBT_VBA: - { - SMTPData* smtp_ssn = get_session_data(p->flow); - - if (!smtp_ssn) - return false; - - const BufferData& vba_buf = smtp_ssn->mime_ssn->get_vba_inspect_buf(); - - if (vba_buf.data_ptr() && vba_buf.length()) - { - b.data = vba_buf.data_ptr(); - b.len = vba_buf.length(); - return true; - } - else - return false; - } - default: - break; - } - return false; - -} - void Smtp::clear(Packet* p) { SMTP_ResetAltBuffer(p); @@ -1590,7 +1555,23 @@ void Smtp::ProcessSmtpCmdsList(const SmtpCmd* sc) bool Smtp::get_fp_buf(InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b) { - return get_buf(ibt, p, b); + if ( ibt != InspectionBuffer::IBT_VBA ) + return false; + + SMTPData* smtp_ssn = get_session_data(p->flow); + + if (!smtp_ssn) + return false; + + const BufferData& vba_buf = smtp_ssn->mime_ssn->get_vba_inspect_buf(); + + if ( vba_buf.data_ptr() && vba_buf.length() ) + { + b.data = vba_buf.data_ptr(); + b.len = vba_buf.length(); + return true; + } + return false; } //------------------------------------------------------------------------- @@ -1633,6 +1614,13 @@ static void smtp_dtor(Inspector* p) delete p; } +static const char* smtp_bufs[] = +{ + "file_data", + "vba_data", + nullptr +}; + const InspectApi smtp_api = { { @@ -1649,7 +1637,7 @@ const InspectApi smtp_api = }, IT_SERVICE, PROTO_BIT__PDU, - nullptr, // buffers + smtp_bufs, "smtp", smtp_init, smtp_term, diff --git a/src/utils/stats.cc b/src/utils/stats.cc index f1e11e6a9..f8f052c3c 100644 --- a/src/utils/stats.cc +++ b/src/utils/stats.cc @@ -192,18 +192,8 @@ const PegInfo pc_names[] = { CountType::SUM, "cooked_searches", "fast pattern searches in cooked packet data" }, { CountType::SUM, "pkt_searches", "fast pattern searches in packet data" }, { CountType::SUM, "alt_searches", "alt fast pattern searches in packet data" }, - { CountType::SUM, "key_searches", "fast pattern searches in key buffer" }, - { CountType::SUM, "header_searches", "fast pattern searches in header buffer" }, - { CountType::SUM, "body_searches", "fast pattern searches in body buffer" }, + { CountType::SUM, "pdu_searches", "fast pattern searches in service buffers" }, { CountType::SUM, "file_searches", "fast pattern searches in file buffer" }, - { CountType::SUM, "raw_key_searches", "fast pattern searches in raw key buffer" }, - { CountType::SUM, "raw_header_searches", "fast pattern searches in raw header buffer" }, - { CountType::SUM, "method_searches", "fast pattern searches in method buffer" }, - { CountType::SUM, "stat_code_searches", "fast pattern searches in status code buffer" }, - { CountType::SUM, "stat_msg_searches", "fast pattern searches in status message buffer" }, - { CountType::SUM, "cookie_searches", "fast pattern searches in cookie buffer" }, - { CountType::SUM, "js_data_searches", "fast pattern searches in js_data buffer" }, - { CountType::SUM, "vba_searches", "fast pattern searches in MS Office Visual Basic for Applications buffer" }, { CountType::SUM, "offloads", "fast pattern searches that were offloaded" }, { CountType::SUM, "alerts", "alerts not including IP reputation" }, { CountType::SUM, "total_alerts", "alerts including IP reputation" }, diff --git a/src/utils/stats.h b/src/utils/stats.h index c215eeea2..8e548b062 100644 --- a/src/utils/stats.h +++ b/src/utils/stats.h @@ -42,18 +42,8 @@ struct PacketCount PegCount cooked_searches; PegCount pkt_searches; PegCount alt_searches; - PegCount key_searches; - PegCount header_searches; - PegCount body_searches; + PegCount pdu_searches; PegCount file_searches; - PegCount raw_key_searches; - PegCount raw_header_searches; - PegCount method_searches; - PegCount stat_code_searches; - PegCount stat_msg_searches; - PegCount cookie_searches; - PegCount js_data_searches; - PegCount vba_searches; PegCount offloads; PegCount alert_pkts; PegCount total_alert_pkts;