arp_spoof = { }
back_orifice = { }
-dnp3 = { }
dns = { }
imap = { }
-iec104 = { }
-mms = { }
-modbus = { }
netflow = {}
normalizer = { }
pop = { }
ssl = { }
telnet = { }
+cip = { }
+dnp3 = { }
+iec104 = { }
+mms = { }
+modbus = { }
+s7commplus = { }
+
dce_smb = { }
dce_tcp = { }
dce_udp = { }
-- 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' } },
{ 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' } }
#include "detection_options.h"
#include "fp_create.h"
+#include "fp_utils.h"
#include "ips_context.h"
#include "pattern_match_data.h"
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)
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;
+ }
}
}
}
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)
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;
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;
}
}
{
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;
}
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
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;
// 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();
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();
};
// 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;
}
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);
+ }
}
}
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 )
}
// 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;
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 */
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;
}
}
-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;
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);
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;
}
/*
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);
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() )
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());
}
+
*/
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
#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"
}
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);
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;
}
}
}
-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);
#include <mutex>
#include <sstream>
#include <thread>
+#include <unordered_map>
+#include "framework/inspector.h"
#include "framework/mpse.h"
#include "framework/mpse_batch.h"
#include "hash/ghash.h"
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<std::string>;
+static std::unordered_map<std::string, SvcList> 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) )
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";
if ( !strncmp(opt, "sip_", 4) )
return "sip";
- if ( !strncmp(opt, "vba_data", 8) )
- return "file";
+ if ( !strncmp(opt, "ssl_", 4) )
+ return "ssl";
return nullptr;
}
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);
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;
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;
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)
{
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)",
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)
{
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);
{
best = curr;
node = ofl;
+ best_opt = curr_opt;
}
}
if (alt_pmd)
pmds.emplace_back(alt_pmd);
pmds.emplace_back(best.pmd); // add primary pattern last
+ fp_opt = best_opt;
}
return pmds;
}
#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 )
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());
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());
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));
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);
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));
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));
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 <PatternMatchData*> 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);
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
callback(this);
post_callbacks.clear();
+ alt_data.len = 0;
}
void IpsContext::disable_detection()
#define PATTERN_MATCH_DATA_H
#include <sys/time.h>
+
+#include <cctype>
+#include <string>
#include <vector>
#include "framework/ips_option.h" // FIXIT-L not a good dependency
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)
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
uint16_t fp_offset;
uint16_t fp_length;
- // not used by ips_content
- uint8_t pm_type;
-
bool is_unbounded() const
{ return !depth; }
{ return (flags & LITERAL) != 0; }
bool can_be_fp() const;
+
+ bool has_alpha() const;
};
typedef std::vector<PatternMatchData*> PatternMatchVector;
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
#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
};
// rule header (RTN) and body (OTN) nodes
+#include <string>
+
#include "actions/actions.h"
#include "detection/signature.h"
#include "detection/rule_option_types.h"
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;
IpsPolicy::Enable enable;
Flag flags = 0;
- uint8_t sticky_buf = PM_TYPE_PKT; // parsing only
-
void set_warned_fp()
{ flags |= WARNED_FP; }
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*);
};
#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"
#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"
#include "cursor.h"
+#include "detection/detection_engine.h"
#include "detection/detection_util.h"
#include "protocols/packet.h"
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());
}
{
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;
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());
}
//-------------------------------------------------------------------------
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",
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
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; }
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;
};
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()
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;
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; }
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; }
EvalStatus eval(Cursor&, Packet*) override;
+ CursorActionType get_cursor_type() const override
+ { return CAT_ADJUST; }
+
private:
uint32_t type;
};
EvalStatus eval(Cursor&, Packet*) override;
+ CursorActionType get_cursor_type() const override
+ { return CAT_ADJUST; }
+
private:
uint32_t type;
bool optional;
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:
{
public:
ByteExtractOption(const ByteExtractData& c) :
- IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_USE), config(c)
+ IpsOption(s_name), config(c)
{ }
~ByteExtractOption() override
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;
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;
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);
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;
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:
{
ByteJumpData byte_jump;
SetByteJumpData(byte_jump, 1);
- snort::IpsOption::set_buffer("hello_world");
SECTION("method hash")
{
{
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);
{
public:
ByteMathOption(const ByteMathData& c) :
- IpsOption(s_name, RULE_OPTION_TYPE_BUFFER_USE), config(c)
+ IpsOption(s_name), config(c)
{ }
~ByteMathOption() override
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; }
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;
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;
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;
TEST_CASE("ByteMathOption::hash", "[ips_byte_math]")
{
- SetBufferOptionHelper set_buf("test");
-
char* lhs_name = new char[5];
strcpy(lhs_name, "test");
ByteMathData data_lhs;
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;
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:
{
ByteTestData byte_test;
SetByteTestData(byte_test, 1);
- snort::IpsOption::set_buffer("hello_world");
SECTION("method hash")
{
{
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);
mix(a,b,c);
- a += config->pmd.pm_type;
b += IpsOption::hash();
mix(a, b, c);
(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) )
}
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(
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);
}
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;
};
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;
p->get_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
//-------------------------------------------------------------------------
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
//-------------------------------------------------------------------------
delete p;
}
-static void flowbits_verify(const SnortConfig*)
-{
- flowbits_verify();
-}
-
static const IpsApi flowbits_api =
{
{
nullptr,
flowbits_ctor,
flowbits_dtor,
- flowbits_verify
+ nullptr
};
const BaseApi* ips_flowbits = &flowbits_api.base;
bool flowbits_setter(void*);
void get_flowbits_dependencies(void*, bool& set, std::vector<std::string>& bits);
+void flowbits_counts(unsigned& total, unsigned& unchecked, unsigned& unset);
#endif
{
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; }
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 = { ";
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; }
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; }
{
hs_database_t* db;
std::string re;
- PatternMatchData pmd;
+ PatternMatchData pmd = { };
bool pcre_upgrade;
RegexConfig()
void reset()
{
- memset(&pmd, 0, sizeof(pmd));
re.clear();
db = nullptr;
pcre_upgrade = false;
{
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;
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;
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);
}
struct SdPatternConfig
{
- PatternMatchData pmd;
+ PatternMatchData pmd = { };
hs_database_t* db;
std::string pii;
void reset()
{
- memset(&pmd, 0, sizeof(pmd));
pii.clear();
threshold = 1;
obfuscate_pii = false;
};
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());
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;
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);
}
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)
{
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;
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;
}
}
ParseRulesFinish(this);
- ShowPolicyStats(this);
/* Need to do this after dynamic detection stuff is initialized, too */
IpsManager::verify(this);
#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"
{
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)
{
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)
void BinderModule::add(unsigned, const char*) { }
void set_default_policy(const snort::SnortConfig*) { }
+void update_buffer_map(const char**, const char*) { }
namespace snort
{
}
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
#include <fstream>
#include <stack>
+#include "detection/fp_utils.h"
#include "log/messages.h"
#include "main/snort_config.h"
#include "managers/module_manager.h"
{
// 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;
}
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;
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;
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++;
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();
#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"
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 )
}
}
-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<PolicyId, int> stats;
std::multimap<PolicyId, PolicyRuleStats> sorted_stats;
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
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*);
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; }
}
#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()
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);
}
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();
+}
+
#ifndef PORT_GROUP_H
#define PORT_GROUP_H
-namespace snort
-{
- class MpseGroup;
-}
+#include <cassert>
+#include <vector>
+
+#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
// 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
{
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;
RULE_NODE* nfp_tail = nullptr;
// pattern matchers
- snort::MpseGroup* mpsegrp[PM_TYPE_MAX] = { };
+ using PmList = std::vector<PatternMatcher*>;
+ PmList pm_list;
// detection option tree
void* nfp_tree = nullptr;
void add_rule();
bool add_nfp_rule(void*);
void delete_nfp_rules();
+
+ PatternMatcher* get_pattern_matcher(PatternMatcher::Type, const char*);
};
#endif
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)
{ 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; }
delete p;
}
+static const char* dce2_bufs[] =
+{
+ "dce_iface",
+ "dce_stub_data",
+ "file_data",
+ nullptr
+};
+
const InspectApi dce2_smb_api =
{
{
},
IT_SERVICE,
PROTO_BIT__PDU,
- nullptr, // buffers
+ dce2_bufs,
DCE_SMB_PROTOCOL_ID,
dce2_smb_init,
nullptr,
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 =
{
{
},
IT_SERVICE,
PROTO_BIT__PDU,
- nullptr, // buffers
+ dce2_tcp_bufs,
DCE_RPC_SERVICE_NAME,
dce2_tcp_init,
nullptr, // pterm
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 =
{
{
},
IT_SERVICE,
PROTO_BIT__UDP,
- nullptr, // buffers
+ dce2_udp_bufs,
DCE_RPC_SERVICE_NAME,
dce2_udp_init,
nullptr, // pterm
#include <cerrno>
#include "detection/pattern_match_data.h"
+#include "framework/cursor.h"
#include "framework/module.h"
#include "framework/ips_option.h"
#include "framework/range.h"
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;
return this == &ips;
}
-IpsOption::EvalStatus Dce2IfaceOption::eval(Cursor&, Packet* p)
+IpsOption::EvalStatus Dce2IfaceOption::eval(Cursor& c, Packet* p)
{
RuleProfile profile(dce2_iface_perf_stats);
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;
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
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);
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;
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);
delete p;
}
+static const char* dnp3_bufs[] =
+{
+ "dnp3_data",
+ nullptr
+};
+
const InspectApi dnp3_api =
{
{
},
IT_SERVICE,
PROTO_BIT__UDP | PROTO_BIT__PDU,
- nullptr, // buffers
+ dnp3_bufs,
"dnp3",
dnp3_init,
nullptr, // pterm
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
delete p;
}
+static const char* fd_bufs[] =
+{
+ "file_data",
+ nullptr
+};
+
// exported in ftp.cc
const InspectApi fd_api =
{
},
IT_SERVICE,
PROTO_BIT__PDU,
- nullptr, // buffers
+ fd_bufs,
fd_svc_name,
fd_init,
nullptr, // pterm
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:
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);
//-------------------------------------------------------------------------
+static const char* gtp_bufs[] =
+{
+ "gtp_info",
+ nullptr
+};
+
static const InspectApi gtp_api =
{
{
},
IT_SERVICE,
PROTO_BIT__UDP,
- nullptr,
+ gtp_bufs,
"gtp",
gtp_init,
gtp_term,
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:
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];
public:
GtpTypeOption(ByteBitSet*);
- CursorActionType get_cursor_type() const override
- { return CAT_SET_OTHER; }
-
uint32_t hash() const override;
bool operator==(const IpsOption&) const override;
{
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;
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)) ||
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; }
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<HttpInspect*>(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;
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);
}
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 =
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);
}
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 =
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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 =
#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);
}
{
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;
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);
}
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);
}
{
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;
{
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;
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);
}
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);
}
{
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;
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);
}
{
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;
delete p;
}
+static const char* imap_bufs[] =
+{
+ "file_data",
+ "vba_data",
+ nullptr
+};
+
const InspectApi imap_api =
{
{
},
IT_SERVICE,
PROTO_BIT__PDU,
- nullptr, // buffers
+ imap_bufs,
"imap",
imap_init,
imap_term, // pterm
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;
};
//-------------------------------------------------------------------------
+static const char* mms_bufs[] =
+{
+ "mms_data",
+ nullptr
+};
+
static const InspectApi mms_api =
{
{
},
IT_SERVICE,
PROTO_BIT__PDU,
- nullptr,
+ mms_bufs,
"mms",
mms_init,
nullptr,
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
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);
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
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
+static const char* modbus_bufs[] =
+{
+ "modbus_data",
+ nullptr
+};
+
static const InspectApi modbus_api =
{
{
},
IT_SERVICE,
PROTO_BIT__PDU,
- nullptr,
+ modbus_bufs,
"modbus",
modbus_init,
nullptr,
delete p;
}
+static const char* pop_bufs[] =
+{
+ "file_data",
+ "vba_data",
+ nullptr
+};
+
const InspectApi pop_api =
{
{
},
IT_SERVICE,
PROTO_BIT__PDU,
- nullptr, // buffers
+ pop_bufs,
"pop3",
pop_init,
pop_term, // pterm
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; }
};
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);
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
//-------------------------------------------------------------------------
+static const char* s7commplus_bufs[] =
+{
+ "s7commplus_content",
+ nullptr
+};
+
static const InspectApi s7commplus_api =
{
{
},
IT_SERVICE,
PROTO_BIT__PDU,
- nullptr,
+ s7commplus_bufs,
"s7commplus",
s7commplus_init,
nullptr,
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
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 =
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 =
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); }
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
//-------------------------------------------------------------------------
delete p;
}
+static const char* sip_bufs[] =
+{
+ "sip_header",
+ "sip_body",
+ nullptr
+};
+
const InspectApi sip_api =
{
{
},
IT_SERVICE,
PROTO_BIT__UDP | PROTO_BIT__PDU,
- nullptr, // buffers
+ sip_bufs,
"sip",
sip_init,
nullptr, // pterm
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
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;
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);
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;
}
//-------------------------------------------------------------------------
delete p;
}
+static const char* smtp_bufs[] =
+{
+ "file_data",
+ "vba_data",
+ nullptr
+};
+
const InspectApi smtp_api =
{
{
},
IT_SERVICE,
PROTO_BIT__PDU,
- nullptr, // buffers
+ smtp_bufs,
"smtp",
smtp_init,
smtp_term,
{ 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" },
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;