From: Russ Combs (rucombs) Date: Thu, 3 Oct 2019 18:20:27 +0000 (-0400) Subject: Merge pull request #1755 in SNORT/snort3 from ~RUCOMBS/snort3:rule_mode to master X-Git-Tag: 3.0.0-262~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e6ff22a7ec772af73a81c058665d308f47b2f651;p=thirdparty%2Fsnort3.git Merge pull request #1755 in SNORT/snort3 from ~RUCOMBS/snort3:rule_mode to master Squashed commit of the following: commit ea9b22df4fe34ec6b5443de7ad700676cd7ece65 Author: russ Date: Wed Oct 2 15:07:43 2019 -0400 detection: map file rules to services alert file and service:file rules will be loaded as if written: alert * ( service:ftp-data, netbios-ssn, http, pop3, imap, smtp, user ) This only applies to rules w/o services. With file rules folded into service groups, we can avoid a separate, and usually extra, file_data search. The 'user' service is required for stream_file support. commit 4fc36a4a5813b0e862fd9059c8f409bfe7bd9fee Author: russ Date: Thu Sep 26 13:59:46 2019 -0400 detection: update trace to indicate eval task commit bab6812cb2fa5596c6cbe3c970c89d599c9814b2 Author: russ Date: Sun Sep 22 10:45:09 2019 -0400 detection: non-service rules must match on rule header proto commit 70c9e81d2a87fe01e40e13a400c5a8c6dae29847 Author: russ Date: Sat Sep 21 19:43:07 2019 -0400 detection: consistently prefer service rules over port rules commit 2d6092ffce0913a81440dbac11a0aab2c53527c6 Author: russ Date: Fri Sep 20 15:31:56 2019 -0400 detection: do not split service groups by ip proto to avoid extra searches commit 5e35f65a17de82034d5e48a2810abd4edd6d2a68 Author: russ Date: Wed Sep 18 21:19:30 2019 -0400 detection: support alert file rules w/o optional services commit 27d3cf25ecc4727468143df5a3c1a7d881982a27 Author: russ Date: Wed Sep 18 14:36:08 2019 -0400 detection: use reference for signature eval data commit 6cb9fffea37f2f521365927d5098a2ae2f2b8c8c Author: russ Date: Wed Sep 18 14:29:04 2019 -0400 detection: remove unnecessary match data from eval context commit 763aa8a73cd15869b8e6f9de0a7908e28404e65c Author: russ Date: Wed Sep 18 14:12:20 2019 -0400 detection: remove the inappropriate match tracker from mpse batch setup commit e1342b186cf4bb026c1137fce73f7bdebb525291 Author: russ Date: Wed Sep 18 13:43:30 2019 -0400 detection: remove more cruft from match tracker This breaks alert file rules rules which do not contain services but fixes the case where alert tcp and alert file coexist in the same FP FSM and the service match should override port checks. The new breakage must be fixed differently. commit 62e271f85b925b7f6eb3b29d68c3459533bf7bfe Author: russ Date: Wed Sep 18 12:36:05 2019 -0400 detection: remove cruft from match accumulator --- diff --git a/src/detection/detect_trace.cc b/src/detection/detect_trace.cc index 2d85b1ed4..99fa1ff41 100644 --- a/src/detection/detect_trace.cc +++ b/src/detection/detect_trace.cc @@ -58,7 +58,7 @@ void clear_trace_cursor_info() cursor_pos = -1; } -void print_pkt_info(Packet* p) +void print_pkt_info(Packet* p, const char* task) { const char* dir; SfIpString src_addr, dst_addr; @@ -83,8 +83,8 @@ void print_pkt_info(Packet* p) dst_port = p->ptrs.dp; } - trace_logf(detection, TRACE_RULE_EVAL,"packet %" PRIu64 " %s %s:%u %s:%u\n", - p->context->packet_number, dir, src_addr, src_port, dst_addr, dst_port); + trace_logf(detection, TRACE_RULE_EVAL,"packet %" PRIu64 " %s %s:%u %s:%u (%s)\n", + p->context->packet_number, dir, src_addr, src_port, dst_addr, dst_port, task); } void print_pattern(const PatternMatchData* pmd) @@ -151,7 +151,7 @@ void clear_trace_cursor_info() { } -void print_pkt_info(Packet*) +void print_pkt_info(Packet*, const char*) { } diff --git a/src/detection/detect_trace.h b/src/detection/detect_trace.h index 1e089ea04..a00c5c268 100644 --- a/src/detection/detect_trace.h +++ b/src/detection/detect_trace.h @@ -48,7 +48,7 @@ enum }; void clear_trace_cursor_info(); -void print_pkt_info(snort::Packet* p); +void print_pkt_info(snort::Packet* p, const char*); void print_pattern(const PatternMatchData* pmd); void dump_buffer(const uint8_t* buff, unsigned len, snort::Packet*); void node_eval_trace(const detection_option_tree_node_t* node, const Cursor& cursor, snort::Packet*); diff --git a/src/detection/detection_options.cc b/src/detection/detection_options.cc index 2f8222483..883aa8dbe 100644 --- a/src/detection/detection_options.cc +++ b/src/detection/detection_options.cc @@ -342,12 +342,10 @@ void* add_detection_option_tree(SnortConfig* sc, detection_option_tree_node_t* o } int detection_option_node_evaluate( - detection_option_tree_node_t* node, detection_option_eval_data_t* eval_data, + detection_option_tree_node_t* node, detection_option_eval_data_t& eval_data, const Cursor& orig_cursor) { - // need node->state to do perf profiling - if ( !node ) - return 0; + assert(node and eval_data.p); auto& state = node->state[get_instance_id()]; RuleContext profile(state); @@ -360,16 +358,11 @@ int detection_option_node_evaluate( char flowbits_setoperation = 0; int loop_count = 0; uint32_t tmp_byte_extract_vars[NUM_IPS_OPTIONS_VARS]; + uint64_t cur_eval_context_num = eval_data.p->context->context_num; - if ( !eval_data || !eval_data->p || !eval_data->pomd ) - return 0; - - uint64_t cur_eval_context_num = eval_data->p->context->context_num; + node_eval_trace(node, cursor, eval_data.p); - node_eval_trace(node, cursor, eval_data->p); - - auto p = eval_data->p; - auto pomd = eval_data->pomd; + auto p = eval_data.p; // see if evaluated it before ... if ( !node->is_relative ) @@ -393,7 +386,7 @@ int detection_option_node_evaluate( } } - state.last_check.ts = eval_data->p->pkth->ts; + state.last_check.ts = eval_data.p->pkth->ts; state.last_check.run_num = get_run_num(); state.last_check.context_num = cur_eval_context_num; state.last_check.flowbit_failed = 0; @@ -423,7 +416,7 @@ int detection_option_node_evaluate( SnortProtocolId snort_protocol_id = p->get_snort_protocol_id(); int check_ports = 1; - if ( snort_protocol_id != UNKNOWN_PROTOCOL_ID and ((OtnxMatchData*)(pomd))->check_ports != 2 ) + if ( snort_protocol_id != UNKNOWN_PROTOCOL_ID ) { auto sig_info = otn->sigInfo; @@ -436,7 +429,7 @@ int detection_option_node_evaluate( } } - if (sig_info.num_services && check_ports) + if ( sig_info.num_services and check_ports ) { // none of the services match trace_logf(detection, TRACE_RULE_EVAL, @@ -471,17 +464,14 @@ int detection_option_node_evaluate( { otn->state[get_instance_id()].matches++; - if ( !eval_data->flowbit_noalert ) + if ( !eval_data.flowbit_noalert ) { - PatternMatchData* pmd = (PatternMatchData*)eval_data->pmd; - int pattern_size = pmd ? pmd->pattern_size : 0; #ifdef DEBUG_MSGS const SigInfo& si = otn->sigInfo; trace_logf(detection, TRACE_RULE_EVAL, "Matched rule gid:sid:rev %u:%u:%u\n", si.gid, si.sid, si.rev); #endif - - fpAddMatch((OtnxMatchData*)pomd, pattern_size, otn); + fpAddMatch(p->context->otnx, otn); } result = rval = (int)IpsOption::MATCH; } @@ -528,7 +518,7 @@ int detection_option_node_evaluate( rval = (int)IpsOption::MATCH; else - rval = node->evaluate(node->option_data, cursor, eval_data->p); + rval = node->evaluate(node->option_data, cursor, eval_data.p); } break; @@ -547,7 +537,7 @@ int detection_option_node_evaluate( else if ( rval == (int)IpsOption::FAILED_BIT ) { trace_log(detection, TRACE_RULE_EVAL, "failed bit\n"); - eval_data->flowbit_failed = 1; + eval_data.flowbit_failed = 1; // clear the timestamp so failed flowbit gets eval'd again state.last_check.flowbit_failed = 1; state.last_check.result = result; @@ -557,8 +547,8 @@ int detection_option_node_evaluate( { // Cache the current flowbit_noalert flag, and set it // so nodes below this don't alert. - tmp_noalert_flag = eval_data->flowbit_noalert; - eval_data->flowbit_noalert = 1; + tmp_noalert_flag = eval_data.flowbit_noalert; + eval_data.flowbit_noalert = 1; trace_log(detection, TRACE_RULE_EVAL, "flowbit no alert\n"); } @@ -679,7 +669,7 @@ int detection_option_node_evaluate( if ( rval == (int)IpsOption::NO_ALERT ) { // Reset the flowbit_noalert flag in eval data - eval_data->flowbit_noalert = tmp_noalert_flag; + eval_data.flowbit_noalert = tmp_noalert_flag; } if ( continue_loop && rval == (int)IpsOption::MATCH && node->relative_children ) @@ -708,7 +698,7 @@ int detection_option_node_evaluate( result = rval; } - if ( eval_data->flowbit_failed ) + if ( eval_data.flowbit_failed ) { // something deeper in the tree failed a flowbit test, we may need to // reeval this node diff --git a/src/detection/detection_options.h b/src/detection/detection_options.h index dc742751d..5f5f760a5 100644 --- a/src/detection/detection_options.h +++ b/src/detection/detection_options.h @@ -110,7 +110,6 @@ struct detection_option_tree_root_t struct detection_option_eval_data_t { - void* pomd; void* pmd; snort::Packet* p; char flowbit_failed; @@ -122,7 +121,7 @@ void* add_detection_option(struct snort::SnortConfig*, option_type_t, void*); void* add_detection_option_tree(struct snort::SnortConfig*, detection_option_tree_node_t*); int detection_option_node_evaluate( - detection_option_tree_node_t*, detection_option_eval_data_t*, const class Cursor&); + detection_option_tree_node_t*, detection_option_eval_data_t&, const class Cursor&); void DetectionHashTableFree(snort::XHash*); void DetectionTreeHashTableFree(snort::XHash*); diff --git a/src/detection/fp_create.cc b/src/detection/fp_create.cc index 4e34f3b9d..4cdc7f558 100644 --- a/src/detection/fp_create.cc +++ b/src/detection/fp_create.cc @@ -1420,15 +1420,11 @@ static void fpCreateServiceMapPortGroups(SnortConfig* sc) sc->spgmmTable = ServicePortGroupMapNew(); sc->sopgTable = new sopg_table_t(sc->proto_ref->get_count()); - for ( int i = SNORT_PROTO_IP; i < SNORT_PROTO_MAX; i++ ) - { - fpBuildServicePortGroups(sc, sc->spgmmTable->to_srv[i], - sc->sopgTable->to_srv[i], sc->srmmTable->to_srv[i], fp); + fpBuildServicePortGroups(sc, sc->spgmmTable->to_srv, + sc->sopgTable->to_srv, sc->srmmTable->to_srv, fp); - fpBuildServicePortGroups(sc, sc->spgmmTable->to_cli[i], - sc->sopgTable->to_cli[i], sc->srmmTable->to_cli[i], fp); - } - sc->sopgTable->set_user_mode(); + fpBuildServicePortGroups(sc, sc->spgmmTable->to_cli, + sc->sopgTable->to_cli, sc->srmmTable->to_cli, fp); } /* @@ -1447,7 +1443,7 @@ static void fpPrintRuleList(SF_LIST* list) } } -static void fpPrintServiceRuleMapTable(GHash* p, const char* proto, const char* dir) +static void fpPrintServiceRuleMapTable(GHash* p, const char* dir) { GHashNode* n; @@ -1455,8 +1451,6 @@ static void fpPrintServiceRuleMapTable(GHash* p, const char* proto, const char* return; std::string label = "service rule counts - "; - label += proto; - label += " "; label += dir; LogLabel(label.c_str()); @@ -1481,23 +1475,16 @@ static void fpPrintServiceRuleMapTable(GHash* p, const char* proto, const char* static void fpPrintServiceRuleMaps(SnortConfig* sc) { - for ( int i = SNORT_PROTO_IP; i < SNORT_PROTO_MAX; ++i ) - { - const char* s = sc->proto_ref->get_name(i); - fpPrintServiceRuleMapTable(sc->srmmTable->to_srv[i], s, "to server"); - fpPrintServiceRuleMapTable(sc->srmmTable->to_cli[i], s, "to client"); - } + fpPrintServiceRuleMapTable(sc->srmmTable->to_srv, "to server"); + fpPrintServiceRuleMapTable(sc->srmmTable->to_cli, "to client"); } -static void fp_print_service_rules(SnortConfig* sc, GHash* cli, GHash* srv, const char* msg) +static void fp_print_service_rules(SnortConfig* sc, GHash* cli, GHash* srv) { if ( !cli->count and !srv->count ) return; - std::string label = "service rule counts - "; - label += msg; - label += " to-srv to-cli"; - LogLabel(label.c_str()); + LogLabel("service rule counts to-srv to-cli"); uint16_t idx = 0; unsigned ctot = 0, stot = 0; @@ -1524,8 +1511,7 @@ static void fp_print_service_rules(SnortConfig* sc, GHash* cli, GHash* srv, cons static void fp_print_service_rules_by_proto(SnortConfig* sc) { - for ( int i = SNORT_PROTO_IP; i < SNORT_PROTO_MAX; ++i ) - fp_print_service_rules(sc, sc->srmmTable->to_srv[i], sc->srmmTable->to_cli[i], sc->proto_ref->get_name(i)); + fp_print_service_rules(sc, sc->srmmTable->to_srv, sc->srmmTable->to_cli); } static void fp_sum_port_groups(PortGroup* pg, unsigned c[PM_TYPE_MAX]) @@ -1554,11 +1540,8 @@ static void fp_print_service_groups(srmm_table_t* srmm) unsigned to_srv[PM_TYPE_MAX] = { 0 }; unsigned to_cli[PM_TYPE_MAX] = { 0 }; - for ( int i = SNORT_PROTO_IP; i < SNORT_PROTO_MAX; ++i ) - { - fp_sum_service_groups(srmm->to_srv[i], to_srv); - fp_sum_service_groups(srmm->to_cli[i], to_cli); - } + fp_sum_service_groups(srmm->to_srv, to_srv); + fp_sum_service_groups(srmm->to_cli, to_cli); bool label = true; diff --git a/src/detection/fp_detect.cc b/src/detection/fp_detect.cc index e2c8a716c..de460dcb3 100644 --- a/src/detection/fp_detect.cc +++ b/src/detection/fp_detect.cc @@ -91,18 +91,14 @@ THREAD_LOCAL ProfileStats mpsePerfStats; THREAD_LOCAL ProfileStats rulePerfStats; static void fp_immediate(Packet*); -static void fp_immediate(MpseGroup*, OtnxMatchData*, const uint8_t*, unsigned); +static void fp_immediate(MpseGroup*, Packet*, const uint8_t*, unsigned); -// Initialize the OtnxMatchData structure. We do this for -// every packet so this only sets the necessary counters to -// zero which saves us time. - -static inline void init_match_info(OtnxMatchData* o) +static inline void init_match_info(OtnxMatchData* omd) { for ( int i = 0; i < SnortConfig::get_conf()->num_rule_types; i++ ) - o->matchInfo[i].iMatchCount = 0; + omd->matchInfo[i].iMatchCount = 0; - o->have_match = false; + omd->have_match = false; } // called by fpLogEvent(), which does the filtering etc. @@ -247,14 +243,13 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p) ** ** FORMAL INPUTS ** OtnxMatchData * - the omd to add the event to. -** int pLen - length of pattern that matched, 0 for no content ** OptTreeNode * - the otn to add. ** ** FORMAL OUTPUTS ** int - 1 max_events variable hit, 0 successful. ** */ -int fpAddMatch(OtnxMatchData* omd_local, int /*pLen*/, const OptTreeNode* otn) +int fpAddMatch(OtnxMatchData* omd, const OptTreeNode* otn) { RuleTreeNode* rtn = getRuntimeRtnFromOtn(otn); int evalIndex = rtn->listhead->ruleListNode->evalIndex; @@ -265,7 +260,7 @@ int fpAddMatch(OtnxMatchData* omd_local, int /*pLen*/, const OptTreeNode* otn) pc.match_limit++; return 1; } - MatchInfo* pmi = &omd_local->matchInfo[evalIndex]; + MatchInfo* pmi = &omd->matchInfo[evalIndex]; /* ** If we hit the max number of unique events for any rule type alert, @@ -289,7 +284,7 @@ int fpAddMatch(OtnxMatchData* omd_local, int /*pLen*/, const OptTreeNode* otn) pmi->MatchArray[ pmi->iMatchCount ] = otn; pmi->iMatchCount++; - omd_local->have_match = true; + omd->have_match = true; return 0; } @@ -311,7 +306,8 @@ int fpEvalRTN(RuleTreeNode* rtn, Packet* p, int check_ports) if ( !rtn ) return 0; - // FIXIT-L maybe add a port test here ... + if ( rtn->user_mode() ) + check_ports = 1; if (!rtn->rule_func->RuleHeadFunc(p, rtn, rtn->rule_func, check_ports)) { @@ -332,17 +328,17 @@ int fp_eval_option(void* v, Cursor& c, Packet* p) } static int detection_option_tree_evaluate(detection_option_tree_root_t* root, - detection_option_eval_data_t* eval_data) + detection_option_eval_data_t& eval_data) { if ( !root ) return 0; - RuleLatency::Context rule_latency_ctx(root, eval_data->p); + RuleLatency::Context rule_latency_ctx(root, eval_data.p); if ( RuleLatency::suspended() ) return 0; - Cursor c(eval_data->p); + Cursor c(eval_data.p); int rval = 0; trace_log(detection, TRACE_RULE_EVAL, "Starting tree eval\n"); @@ -361,14 +357,12 @@ static int rule_tree_match( void* user, void* tree, int index, void* context, void* neg_list) { PMX* pmx = (PMX*)user; - OtnxMatchData* pomd = ((IpsContext*)context)->otnx; detection_option_tree_root_t* root = (detection_option_tree_root_t*)tree; detection_option_eval_data_t eval_data; NCListNode* ncl; - eval_data.pomd = pomd; - eval_data.p = pomd->p; + eval_data.p = ((IpsContext*)context)->packet; eval_data.pmd = pmx->pmd; eval_data.flowbit_failed = 0; eval_data.flowbit_noalert = 0; @@ -396,7 +390,7 @@ static int rule_tree_match( last_check->rebuild_flag = (eval_data.p->packet_flags & PKT_REBUILT_STREAM); } - int ret = detection_option_tree_evaluate(root, &eval_data); + int ret = detection_option_tree_evaluate(root, eval_data); if ( ret ) pmqs.qualified_events++; @@ -435,9 +429,7 @@ static int rule_tree_match( rule_tree_match(user, tree, index, context, nullptr); } while (layer::set_inner_ip_api(eval_data.p, - eval_data.p->ptrs.ip_api, - curr_layer) && - (eval_data.p->ptrs.ip_api != tmp_api)); + eval_data.p->ptrs.ip_api, curr_layer) && (eval_data.p->ptrs.ip_api != tmp_api)); /* cleanup restore original data & dsize */ eval_data.p->packet_flags &= ~PKT_IP_RULE_2ND; @@ -620,9 +612,9 @@ static inline int fpSessionAlerted(Packet* p, const OptTreeNode* otn) ** FORMAL OUTPUT ** int - return 0 if no match, 1 if match. */ -static inline int fpFinalSelectEvent(OtnxMatchData* o, Packet* p) +static inline int fpFinalSelectEvent(OtnxMatchData* omd, Packet* p) { - if ( !o->have_match ) + if ( !omd->have_match ) return 0; int i; @@ -640,7 +632,7 @@ static inline int fpFinalSelectEvent(OtnxMatchData* o, Packet* p) if (!SnortConfig::process_all_events() && (tcnt > 0)) return 1; - if (o->matchInfo[i].iMatchCount) + if (omd->matchInfo[i].iMatchCount) { /* * We must always sort so if we que 8 and log 3 and they are @@ -656,12 +648,12 @@ static inline int fpFinalSelectEvent(OtnxMatchData* o, Packet* p) /* Sort the rules in this action group */ if (eq->order == SNORT_EVENTQ_PRIORITY) { - qsort(o->matchInfo[i].MatchArray, o->matchInfo[i].iMatchCount, + qsort(omd->matchInfo[i].MatchArray, omd->matchInfo[i].iMatchCount, sizeof(void*), sortOrderByPriority); } else if (eq->order == SNORT_EVENTQ_CONTENT_LEN) { - qsort(o->matchInfo[i].MatchArray, o->matchInfo[i].iMatchCount, + qsort(omd->matchInfo[i].MatchArray, omd->matchInfo[i].iMatchCount, sizeof(void*), sortOrderByContentLength); } else @@ -670,9 +662,9 @@ static inline int fpFinalSelectEvent(OtnxMatchData* o, Packet* p) } /* Process each event in the action (alert,drop,log,...) groups */ - for (j=0; j < o->matchInfo[i].iMatchCount; j++) + for (j=0; j < omd->matchInfo[i].iMatchCount; j++) { - otn = o->matchInfo[i].MatchArray[j]; + otn = omd->matchInfo[i].MatchArray[j]; rtn = getRtnFromOtn(otn); if (otn && rtn && Actions::is_pass(rtn->action)) @@ -685,7 +677,7 @@ static inline int fpFinalSelectEvent(OtnxMatchData* o, Packet* p) // Loop here so we don't log the same event multiple times. for (k = 0; k < j; k++) { - if (o->matchInfo[i].MatchArray[k] == otn) + if (omd->matchInfo[i].MatchArray[k] == otn) { otn = nullptr; break; @@ -854,8 +846,7 @@ void fp_clear_context(IpsContext& c) static int rule_tree_queue( void* user, void* tree, int index, void* context, void* list) { - OtnxMatchData* pomd = ((IpsContext*)context)->otnx; - MpseStash* stash = pomd->p->context->stash; + MpseStash* stash = ((IpsContext*)context)->stash; if ( stash->push(user, tree, index, list) ) { @@ -866,24 +857,24 @@ static int rule_tree_queue( } static inline int batch_search( - MpseGroup* so, OtnxMatchData* omd, const uint8_t* buf, unsigned len, PegCount& cnt) + MpseGroup* so, Packet* p, const uint8_t* buf, unsigned len, PegCount& cnt) { assert(so->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 ( omd->p->ptrs.udph && (omd->p->proto_bits & (PROTO_BIT__TEREDO | PROTO_BIT__GTP)) ) + if ( p->ptrs.udph && (p->proto_bits & (PROTO_BIT__TEREDO | PROTO_BIT__GTP)) ) { - fp_immediate(so, omd, buf, len); + fp_immediate(so, p, buf, len); } else { MpseBatchKey<> key = MpseBatchKey<>(buf, len); - omd->p->context->searches.items[key].so.push_back(so); + p->context->searches.items[key].so.push_back(so); } - dump_buffer(buf, len, omd->p); + dump_buffer(buf, len, p); if ( PacketLatency::fastpath() ) return 1; @@ -891,39 +882,32 @@ static inline int batch_search( } static inline int search_buffer( - Inspector* gadget, OtnxMatchData* omd, InspectionBuffer& buf, - InspectionBuffer::Type ibt, PmType pmt, PegCount& cnt) + Inspector* gadget, InspectionBuffer& buf, InspectionBuffer::Type ibt, + Packet* p, PortGroup* pg, PmType pmt, PegCount& cnt) { - if ( gadget->get_fp_buf(ibt, omd->p, buf) ) + if ( gadget->get_fp_buf(ibt, p, buf) ) { // Depending on where we are searching we call the appropriate mpse - if ( MpseGroup* so = omd->pg->mpsegrp[pmt] ) + if ( MpseGroup* so = pg->mpsegrp[pmt] ) { // FIXIT-H DELETE ME done - get the context packet number trace_logf(detection, TRACE_FP_SEARCH, "%" PRIu64 " fp %s.%s[%d]\n", - omd->p->context->packet_number, gadget->get_name(), pm_type_strings[pmt], buf.len); + p->context->packet_number, gadget->get_name(), pm_type_strings[pmt], buf.len); - batch_search(so, omd, buf.data, buf.len, cnt); + batch_search(so, p, buf.data, buf.len, cnt); } } return 0; } -static int fp_search( - PortGroup* port_group, Packet* p, int check_ports, int type, OtnxMatchData* omd) +static int fp_search(PortGroup* port_group, Packet* p) { Inspector* gadget = p->flow ? p->flow->gadget : nullptr; InspectionBuffer buf; - omd->pg = port_group; - omd->p = p; - omd->check_ports = check_ports; - - bool user_mode = SnortConfig::get_conf()->sopgTable->user_mode; - trace_log(detection, TRACE_RULE_EVAL, "Fast pattern search\n"); - if ( (!user_mode or type < 2) and p->data and p->dsize ) + if ( p->data and p->dsize ) { // ports search raw packet only if ( MpseGroup* so = port_group->mpsegrp[PM_TYPE_PKT] ) @@ -933,32 +917,31 @@ static int fp_search( trace_logf(detection, TRACE_FP_SEARCH, "%" PRIu64 " fp %s[%u]\n", p->context->packet_number, pm_type_strings[PM_TYPE_PKT], pattern_match_size); - batch_search(so, omd, p->data, pattern_match_size, pc.pkt_searches); + batch_search(so, p, p->data, pattern_match_size, pc.pkt_searches); p->is_cooked() ? pc.cooked_searches++ : pc.raw_searches++; } } } - if ( (!user_mode or type == 1) and gadget ) + if ( gadget ) { // service searches PDU buffers and file - if ( search_buffer(gadget, omd, buf, buf.IBT_KEY, PM_TYPE_KEY, pc.key_searches) ) + if ( search_buffer(gadget, buf, buf.IBT_KEY, p, port_group, PM_TYPE_KEY, pc.key_searches) ) return 1; - if ( search_buffer(gadget, omd, buf, buf.IBT_HEADER, PM_TYPE_HEADER, pc.header_searches) ) + if ( search_buffer(gadget, buf, buf.IBT_HEADER, p, port_group, PM_TYPE_HEADER, pc.header_searches) ) return 1; - if ( search_buffer(gadget, omd, buf, buf.IBT_BODY, PM_TYPE_BODY, pc.body_searches) ) + if ( search_buffer(gadget, buf, buf.IBT_BODY, p, port_group, PM_TYPE_BODY, pc.body_searches) ) return 1; // 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 - if ( search_buffer(gadget, omd, buf, buf.IBT_ALT, PM_TYPE_PKT, pc.alt_searches) ) + if ( search_buffer(gadget, buf, buf.IBT_ALT, p, port_group, PM_TYPE_PKT, pc.alt_searches) ) return 1; } - if ( !user_mode or type > 0 ) { // file searches file only if ( MpseGroup* so = port_group->mpsegrp[PM_TYPE_FILE] ) @@ -972,7 +955,7 @@ static int fp_search( trace_logf(detection, TRACE_FP_SEARCH, "%" PRIu64 " fp search %s[%d]\n", p->context->packet_number, pm_type_strings[PM_TYPE_FILE], file_data.len); - batch_search(so, omd, file_data.data, file_data.len, pc.file_searches); + batch_search(so, p, file_data.data, file_data.len, pc.file_searches); } } } @@ -980,8 +963,7 @@ static int fp_search( } static inline void eval_fp( - PortGroup* port_group, Packet* p, OtnxMatchData* omd, char ip_rule, - int check_ports, int type) + PortGroup* port_group, Packet* p, char ip_rule) { const uint8_t* tmp_payload = nullptr; uint16_t tmp_dsize = 0; @@ -1009,7 +991,7 @@ static inline void eval_fp( FastPatternConfig* fp = SnortConfig::get_conf()->fast_pattern_config; if ( fp->get_stream_insert() || !(p->packet_flags & PKT_STREAM_INSERT) ) - if ( fp_search(port_group, p, check_ports, type, omd) ) + if ( fp_search(port_group, p) ) return; } if ( ip_rule ) @@ -1020,7 +1002,7 @@ static inline void eval_fp( } static inline void eval_nfp( - PortGroup* port_group, Packet* p, OtnxMatchData* omd, char ip_rule) + PortGroup* port_group, Packet* p, char ip_rule) { bool repeat = false; int8_t curr_ip_layer = 0; @@ -1053,7 +1035,6 @@ static inline void eval_nfp( detection_option_eval_data_t eval_data; - eval_data.pomd = omd; eval_data.p = p; eval_data.pmd = nullptr; eval_data.flowbit_failed = 0; @@ -1063,7 +1044,7 @@ static inline void eval_nfp( { trace_log(detection, TRACE_RULE_EVAL, "Testing non-content rules\n"); rval = detection_option_tree_evaluate( - (detection_option_tree_root_t*)port_group->nfp_tree, &eval_data); + (detection_option_tree_root_t*)port_group->nfp_tree, eval_data); } if (rval) @@ -1101,24 +1082,21 @@ static inline void eval_nfp( // for non-content. The otn list search will eventually be redone for // for performance purposes. -static inline int fpEvalHeaderSW(PortGroup* port_group, Packet* p, - int check_ports, char ip_rule, int type, OtnxMatchData* omd, FPTask task) +static inline int fpEvalHeaderSW(PortGroup* port_group, Packet* p, char ip_rule, FPTask task) { if ( !p->is_detection_enabled(p->packet_flags & PKT_FROM_CLIENT) ) return 0; - print_pkt_info(p); - if ( task & FPTask::FP ) - eval_fp(port_group, p, omd, ip_rule, check_ports, type); + eval_fp(port_group, p, ip_rule); if ( task & FPTask::NON_FP ) - eval_nfp(port_group, p, omd, ip_rule); + eval_nfp(port_group, p, ip_rule); return 0; } -static inline void fpEvalHeaderIp(Packet* p, OtnxMatchData* omd, FPTask task) +static inline void fpEvalHeaderIp(Packet* p, FPTask task) { PortGroup* any = nullptr, * ip_group = nullptr; @@ -1129,13 +1107,13 @@ static inline void fpEvalHeaderIp(Packet* p, OtnxMatchData* omd, FPTask task) LogMessage("fpEvalHeaderIp: ip_group=%p, any=%p\n", (void*)ip_group, (void*)any); if ( ip_group ) - fpEvalHeaderSW(ip_group, p, 0, 1, 0, omd, task); + fpEvalHeaderSW(ip_group, p, 1, task); if ( any ) - fpEvalHeaderSW(any, p, 0, 1, 0, omd, task); + fpEvalHeaderSW(any, p, 1, task); } -static inline void fpEvalHeaderIcmp(Packet* p, OtnxMatchData* omd, FPTask task) +static inline void fpEvalHeaderIcmp(Packet* p, FPTask task) { PortGroup* any = nullptr, * type = nullptr; @@ -1143,13 +1121,13 @@ static inline void fpEvalHeaderIcmp(Packet* p, OtnxMatchData* omd, FPTask task) return; if ( type ) - fpEvalHeaderSW(type, p, 0, 0, 0, omd, task); + fpEvalHeaderSW(type, p, 0, task); if ( any ) - fpEvalHeaderSW(any, p, 0, 0, 0, omd, task); + fpEvalHeaderSW(any, p, 0, task); } -static inline void fpEvalHeaderTcp(Packet* p, OtnxMatchData* omd, FPTask task) +static inline void fpEvalHeaderTcp(Packet* p, FPTask task) { PortGroup* src = nullptr, * dst = nullptr, * any = nullptr; @@ -1157,16 +1135,16 @@ static inline void fpEvalHeaderTcp(Packet* p, OtnxMatchData* omd, FPTask task) return; if ( dst ) - fpEvalHeaderSW(dst, p, 1, 0, 0, omd, task); + fpEvalHeaderSW(dst, p, 0, task); if ( src ) - fpEvalHeaderSW(src, p, 1, 0, 0, omd, task); + fpEvalHeaderSW(src, p, 0, task); if ( any ) - fpEvalHeaderSW(any, p, 1, 0, 0, omd, task); + fpEvalHeaderSW(any, p, 0, task); } -static inline void fpEvalHeaderUdp(Packet* p, OtnxMatchData* omd, FPTask task) +static inline void fpEvalHeaderUdp(Packet* p, FPTask task) { PortGroup* src = nullptr, * dst = nullptr, * any = nullptr; @@ -1174,49 +1152,37 @@ static inline void fpEvalHeaderUdp(Packet* p, OtnxMatchData* omd, FPTask task) return; if ( dst ) - fpEvalHeaderSW(dst, p, 1, 0, 0, omd, task); + fpEvalHeaderSW(dst, p, 0, task); if ( src ) - fpEvalHeaderSW(src, p, 1, 0, 0, omd, task); + fpEvalHeaderSW(src, p, 0, task); if ( any ) - fpEvalHeaderSW(any, p, 1, 0, 0, omd, task); + fpEvalHeaderSW(any, p, 0, task); } -static inline bool fpEvalHeaderSvc(Packet* p, OtnxMatchData* omd, SnortProtocolId proto_id, FPTask task) +static inline bool fpEvalHeaderSvc(Packet* p, FPTask task) { - PortGroup* svc = nullptr, * file = nullptr; + PortGroup* svc = nullptr; SnortProtocolId snort_protocol_id = p->get_snort_protocol_id(); if (snort_protocol_id != UNKNOWN_PROTOCOL_ID and snort_protocol_id != INVALID_PROTOCOL_ID) { if (p->is_from_server()) /* to cli */ - { - svc = SnortConfig::get_conf()->sopgTable->get_port_group(proto_id, false, snort_protocol_id); - file = SnortConfig::get_conf()->sopgTable->get_port_group(proto_id, false, SNORT_PROTO_FILE); - } + svc = SnortConfig::get_conf()->sopgTable->get_port_group(false, snort_protocol_id); if (p->is_from_client()) /* to srv */ - { - svc = SnortConfig::get_conf()->sopgTable->get_port_group(proto_id, true, snort_protocol_id); - file = SnortConfig::get_conf()->sopgTable->get_port_group(proto_id, true, SNORT_PROTO_FILE); - } + svc = SnortConfig::get_conf()->sopgTable->get_port_group(true, snort_protocol_id); } - // FIXIT-P put alert service rules with file data fp in alert file group and - // verify ports and service during rule eval to avoid searching file data 2x. - int check_ports = (proto_id == SNORT_PROTO_USER) ? 2 : 1; - - if ( file ) - fpEvalHeaderSW(file, p, check_ports, 0, 2, omd, task); if ( svc ) - fpEvalHeaderSW(svc, p, check_ports, 0, 1, omd, task); + fpEvalHeaderSW(svc, p, 0, task); return svc != nullptr; } -static void fpEvalPacketUdp(Packet* p, OtnxMatchData* omd, FPTask task) +static void fpEvalPacketUdp(Packet* p, FPTask task) { uint16_t tmp_sp = p->ptrs.sp; uint16_t tmp_dp = p->ptrs.dp; @@ -1243,7 +1209,7 @@ static void fpEvalPacketUdp(Packet* p, OtnxMatchData* omd, FPTask task) if ( p->dsize ) DetectionEngine::enable_content(p); - fpEvalHeaderUdp(p, omd, task); + fpEvalHeaderUdp(p, task); // FIXIT-P Batch outer UDP payload searches for teredo set and the outer header // during any signature evaluation @@ -1272,54 +1238,38 @@ static void fpEvalPacketUdp(Packet* p, OtnxMatchData* omd, FPTask task) */ static void fpEvalPacket(Packet* p, FPTask task) { - OtnxMatchData* omd = p->context->otnx; - /* Run UDP rules against the UDP header of Teredo packets */ // FIXIT-L udph is always inner; need to check for outer if ( p->ptrs.udph && (p->proto_bits & (PROTO_BIT__TEREDO | PROTO_BIT__GTP)) ) - fpEvalPacketUdp(p, omd, task); + fpEvalPacketUdp(p, task); + + if ( p->get_snort_protocol_id() != UNKNOWN_PROTOCOL_ID and fpEvalHeaderSvc(p, task) ) + return; switch (p->type()) { case PktType::IP: - fpEvalHeaderIp(p, omd, task); - fpEvalHeaderSvc(p, omd, SNORT_PROTO_IP, task); + fpEvalHeaderIp(p, task); break; case PktType::ICMP: - fpEvalHeaderIcmp(p, omd, task); - fpEvalHeaderSvc(p, omd, SNORT_PROTO_ICMP, task); + fpEvalHeaderIcmp(p, task); break; case PktType::TCP: - fpEvalHeaderTcp(p, omd, task); - fpEvalHeaderSvc(p, omd, SNORT_PROTO_TCP, task); + fpEvalHeaderTcp(p, task); break; case PktType::UDP: - fpEvalHeaderUdp(p, omd, task); - fpEvalHeaderSvc(p, omd, SNORT_PROTO_UDP, task); + fpEvalHeaderUdp(p, task); break; case PktType::PDU: if ( p->proto_bits & PROTO_BIT__TCP ) - { - if ( p->get_snort_protocol_id() == UNKNOWN_PROTOCOL_ID or !fpEvalHeaderSvc(p, omd, SNORT_PROTO_TCP, task) ) - fpEvalHeaderTcp(p, omd, task); - } - else if ( p->proto_bits & PROTO_BIT__UDP ) - { - if ( p->get_snort_protocol_id() == UNKNOWN_PROTOCOL_ID or !fpEvalHeaderSvc(p, omd, SNORT_PROTO_UDP, task) ) - fpEvalHeaderUdp(p, omd, task); - } - - if ( SnortConfig::get_conf()->sopgTable->user_mode ) - fpEvalHeaderSvc(p, omd, SNORT_PROTO_USER, task); + fpEvalHeaderTcp(p, task); - break; - - case PktType::FILE: - fpEvalHeaderSvc(p, omd, SNORT_PROTO_USER, task); + else if ( p->proto_bits & PROTO_BIT__UDP ) + fpEvalHeaderUdp(p, task); break; default: @@ -1339,6 +1289,7 @@ void fp_partial(Packet* p) c->searches.mf = rule_tree_queue; c->searches.context = c; assert(!c->searches.items.size()); + print_pkt_info(p, "fast-patterns"); fpEvalPacket(p, FPTask::FP); } @@ -1356,6 +1307,7 @@ void fp_complete(Packet* p, bool search) { Profile rule_profile(rulePerfStats); stash->process(rule_tree_match, c); + print_pkt_info(p, "non-fast-patterns"); fpEvalPacket(p, FPTask::NON_FP); fpFinalSelectEvent(c->otnx, p); c->searches.items.clear(); @@ -1384,18 +1336,18 @@ static void fp_immediate(Packet* p) } } -static void fp_immediate(MpseGroup* so, OtnxMatchData* omd, const uint8_t* buf, unsigned len) +static void fp_immediate(MpseGroup* so, Packet* p, const uint8_t* buf, unsigned len) { - MpseStash* stash = omd->p->context->stash; + MpseStash* stash = p->context->stash; { Profile mpse_profile(mpsePerfStats); int start_state = 0; stash->init(); - so->get_normal_mpse()->search(buf, len, rule_tree_queue, omd->p->context, &start_state); + so->get_normal_mpse()->search(buf, len, rule_tree_queue, p->context, &start_state); } { Profile rule_profile(rulePerfStats); - stash->process(rule_tree_match, omd->p->context); + stash->process(rule_tree_match, p->context); } } diff --git a/src/detection/fp_detect.h b/src/detection/fp_detect.h index a85c68236..8c2f3d9d9 100644 --- a/src/detection/fp_detect.h +++ b/src/detection/fp_detect.h @@ -85,16 +85,11 @@ struct MatchInfo */ struct OtnxMatchData { - PortGroup* pg; - snort::Packet* p; MatchInfo* matchInfo; - - int check_ports; bool have_match; - bool do_fp; }; -int fpAddMatch(OtnxMatchData*, int pLen, const OptTreeNode*); +int fpAddMatch(OtnxMatchData*, const OptTreeNode*); void fp_set_context(snort::IpsContext&); void fp_clear_context(snort::IpsContext&); diff --git a/src/detection/fp_utils.cc b/src/detection/fp_utils.cc index c9cf278df..59f661fd7 100644 --- a/src/detection/fp_utils.cc +++ b/src/detection/fp_utils.cc @@ -358,13 +358,6 @@ PatternMatchVector get_fp_content( else exclude = false; - if ( best.pmd and otn->snort_protocol_id == SNORT_PROTO_FILE and best.cat != CAT_SET_FILE ) - { - ParseWarning(WARN_RULES, "file rule %u:%u does not have file_data fast pattern", - otn->sigInfo.gid, otn->sigInfo.sid); - pmds.clear(); - } - if ( content && !best.pmd) ParseWarning(WARN_RULES, "content based rule %u:%u has no eligible fast pattern", otn->sigInfo.gid, otn->sigInfo.sid); diff --git a/src/detection/rtn_checks.cc b/src/detection/rtn_checks.cc index ca9c54bc2..75745c5a2 100644 --- a/src/detection/rtn_checks.cc +++ b/src/detection/rtn_checks.cc @@ -237,6 +237,22 @@ int CheckDstPortNotEq(Packet* p, RuleTreeNode* rtn_idx, return 0; } +int CheckProto(Packet* p, RuleTreeNode* rtn_idx, RuleFpList*, int) +{ + assert(rtn_idx->snort_protocol_id < SNORT_PROTO_MAX); + + const int proto_bits[SNORT_PROTO_MAX] = // SNORT_PROTO_ to PROTO_BIT__* + { + /* n/a */ PROTO_BIT__NONE, + /* ip */ PROTO_BIT__IP | PROTO_BIT__TCP | PROTO_BIT__UDP, // legacy + /* icmp */ PROTO_BIT__ICMP, + /* tcp */ PROTO_BIT__TCP | PROTO_BIT__PDU, + /* udp */ PROTO_BIT__UDP, + /* user */ PROTO_BIT__PDU + }; + return proto_bits[rtn_idx->snort_protocol_id] & p->proto_bits; +} + int RuleListEnd(Packet*, RuleTreeNode*, RuleFpList*, int) { return 1; diff --git a/src/detection/rtn_checks.h b/src/detection/rtn_checks.h index 870a888e5..7e4c5d642 100644 --- a/src/detection/rtn_checks.h +++ b/src/detection/rtn_checks.h @@ -34,8 +34,11 @@ int OptListEnd(void* option_data, class Cursor&, snort::Packet*); // detection int CheckBidirectional(snort::Packet*, RuleTreeNode*, RuleFpList*, int); + +int CheckProto(snort::Packet*, RuleTreeNode*, RuleFpList*, int); int CheckSrcIP(snort::Packet*, RuleTreeNode*, RuleFpList*, int); int CheckDstIP(snort::Packet*, RuleTreeNode*, RuleFpList*, int); + int CheckSrcPortEqual(snort::Packet*, RuleTreeNode*, RuleFpList*, int); int CheckDstPortEqual(snort::Packet*, RuleTreeNode*, RuleFpList*, int); int CheckSrcPortNotEq(snort::Packet*, RuleTreeNode*, RuleFpList*, int); diff --git a/src/detection/service_map.cc b/src/detection/service_map.cc index 5795b70b3..474aa08cf 100644 --- a/src/detection/service_map.cc +++ b/src/detection/service_map.cc @@ -71,11 +71,8 @@ srmm_table_t* ServiceMapNew() { srmm_table_t* table = (srmm_table_t*)snort_calloc(sizeof(srmm_table_t)); - for ( int i = SNORT_PROTO_IP; i < SNORT_PROTO_MAX; i++ ) - { - table->to_srv[i] = alloc_srvmap(); - table->to_cli[i] = alloc_srvmap(); - } + table->to_srv = alloc_srvmap(); + table->to_cli = alloc_srvmap(); return table; } @@ -85,14 +82,8 @@ void ServiceMapFree(srmm_table_t* table) if ( !table ) return; - for ( int i = SNORT_PROTO_IP; i < SNORT_PROTO_MAX; i++ ) - { - if ( table->to_srv[i] ) - free_srvmap(table->to_srv[i]); - - if ( table->to_cli[i] ) - free_srvmap(table->to_cli[i]); - } + free_srvmap(table->to_srv); + free_srvmap(table->to_cli); snort_free(table); } @@ -123,11 +114,8 @@ srmm_table_t* ServicePortGroupMapNew() { srmm_table_t* table = (srmm_table_t*)snort_calloc(sizeof(srmm_table_t)); - for ( int i = SNORT_PROTO_IP; i < SNORT_PROTO_MAX; i++ ) - { - table->to_srv[i] = alloc_spgmm(); - table->to_cli[i] = alloc_spgmm(); - } + table->to_srv = alloc_spgmm(); + table->to_cli = alloc_spgmm(); return table; } @@ -137,14 +125,8 @@ void ServicePortGroupMapFree(srmm_table_t* table) if ( !table ) return; - for ( int i = SNORT_PROTO_IP; i < SNORT_PROTO_MAX; i++ ) - { - if ( table->to_srv[i] ) - free_spgmm(table->to_srv[i]); - - if ( table->to_cli[i] ) - free_spgmm(table->to_cli[i]); - } + free_spgmm(table->to_srv); + free_spgmm(table->to_cli); snort_free(table); } @@ -163,25 +145,14 @@ void ServicePortGroupMapFree(srmm_table_t* table) */ static void ServiceMapAddOtnRaw(GHash* table, const char* servicename, OptTreeNode* otn) { - SF_LIST* list; - - list = (SF_LIST*)ghash_find(table, servicename); + SF_LIST* list = (SF_LIST*)ghash_find(table, servicename); if ( !list ) { - /* create the list */ list = sflist_new(); - if ( !list ) - FatalError("service_rule_map: could not create a service rule-list\n"); - - /* add the service list to the table */ - if ( ghash_add(table, servicename, list) != GHASH_OK ) - { - FatalError("service_rule_map: could not add a rule to the rule-service-map\n"); - } + ghash_add(table, servicename, list); } - /* add the rule */ sflist_add_tail(list, otn); } @@ -191,21 +162,15 @@ static void ServiceMapAddOtnRaw(GHash* table, const char* servicename, OptTreeNo * service name. */ static int ServiceMapAddOtn( - srmm_table_t* srmm, SnortProtocolId proto_id, const char* servicename, OptTreeNode* otn) + srmm_table_t* srmm, SnortProtocolId, const char* servicename, OptTreeNode* otn) { assert(servicename and otn); - if ( proto_id > SNORT_PROTO_USER ) - proto_id = SNORT_PROTO_USER; - - GHash* to_srv = srmm->to_srv[proto_id]; - GHash* to_cli = srmm->to_cli[proto_id]; - if ( !OtnFlowFromClient(otn) ) - ServiceMapAddOtnRaw(to_cli, servicename, otn); + ServiceMapAddOtnRaw(srmm->to_cli, servicename, otn); if ( !OtnFlowFromServer(otn) ) - ServiceMapAddOtnRaw(to_srv, servicename, otn); + ServiceMapAddOtnRaw(srmm->to_srv, servicename, otn); return 0; } @@ -216,14 +181,11 @@ void fpPrintServicePortGroupSummary(SnortConfig* sc) LogMessage("| Service-PortGroup Table Summary \n"); LogMessage("---------------------------------\n"); - for ( int i = SNORT_PROTO_IP; i < SNORT_PROTO_MAX; i++ ) - { - if ( unsigned n = sc->spgmmTable->to_srv[i]->count ) - LogMessage("| %s to server : %d services\n", sc->proto_ref->get_name(i), n); + if ( unsigned n = sc->spgmmTable->to_srv->count ) + LogMessage("| server : %d services\n", n); - if ( unsigned n = sc->spgmmTable->to_cli[i]->count ) - LogMessage("| %s to client : %d services\n", sc->proto_ref->get_name(i), n); - } + if ( unsigned n = sc->spgmmTable->to_cli->count ) + LogMessage("| client : %d services\n", n); LogMessage("---------------------------------\n"); } @@ -280,23 +242,16 @@ int fpCreateServiceMaps(SnortConfig* sc) sopg_table_t::sopg_table_t(unsigned n) { - for ( int i = SNORT_PROTO_IP; i < SNORT_PROTO_MAX; ++i ) - { - if ( to_srv[i].size() < n ) - to_srv[i].resize(n, nullptr); + if ( to_srv.size() < n ) + to_srv.resize(n, nullptr); - if ( to_cli[i].size() < n ) - to_cli[i].resize(n, nullptr); - } - user_mode = false; + if ( to_cli.size() < n ) + to_cli.resize(n, nullptr); } -PortGroup* sopg_table_t::get_port_group( - SnortProtocolId proto_id, bool c2s, SnortProtocolId snort_protocol_id) +PortGroup* sopg_table_t::get_port_group(bool c2s, SnortProtocolId snort_protocol_id) { - assert(proto_id < SNORT_PROTO_MAX); - - PortGroupVector& v = c2s ? to_srv[proto_id] : to_cli[proto_id]; + PortGroupVector& v = c2s ? to_srv : to_cli; if ( snort_protocol_id >= v.size() ) return nullptr; @@ -304,25 +259,3 @@ PortGroup* sopg_table_t::get_port_group( return v[snort_protocol_id]; } -bool sopg_table_t::set_user_mode() -{ - for ( auto* p : to_srv[SNORT_PROTO_USER] ) - { - if ( p ) - { - user_mode = true; - return true; - } - } - - for ( auto* p : to_cli[SNORT_PROTO_USER] ) - { - if ( p ) - { - user_mode = true; - break; - } - } - return user_mode; -} - diff --git a/src/detection/service_map.h b/src/detection/service_map.h index 6ab53a094..6304d61d9 100644 --- a/src/detection/service_map.h +++ b/src/detection/service_map.h @@ -42,8 +42,8 @@ struct PortGroup; // Service Rule Map Master Table struct srmm_table_t { - snort::GHash* to_srv[SNORT_PROTO_MAX]; - snort::GHash* to_cli[SNORT_PROTO_MAX]; + snort::GHash* to_srv; + snort::GHash* to_cli; }; srmm_table_t* ServiceMapNew(); @@ -61,13 +61,10 @@ typedef std::vector PortGroupVector; struct sopg_table_t { sopg_table_t(unsigned size); - bool set_user_mode(); - PortGroup* get_port_group(SnortProtocolId proto_id, bool c2s, SnortProtocolId snort_protocol_id); + PortGroup* get_port_group(bool c2s, SnortProtocolId svc); - PortGroupVector to_srv[SNORT_PROTO_MAX]; - PortGroupVector to_cli[SNORT_PROTO_MAX]; - - bool user_mode; + PortGroupVector to_srv; + PortGroupVector to_cli; }; diff --git a/src/detection/treenodes.h b/src/detection/treenodes.h index 26ae256af..c582f1be9 100644 --- a/src/detection/treenodes.h +++ b/src/detection/treenodes.h @@ -99,6 +99,7 @@ struct RuleTreeNode static constexpr Flag BIDIRECTIONAL = 0x10; static constexpr Flag ANY_SRC_IP = 0x20; static constexpr Flag ANY_DST_IP = 0x40; + static constexpr Flag USER_MODE = 0x80; RuleFpList* rule_func = nullptr; /* match functions.. (Bidirectional etc.. ) */ @@ -127,7 +128,10 @@ struct RuleTreeNode { flags &= (~ENABLED); } bool enabled() const - { return flags & ENABLED; } + { return (flags & ENABLED) != 0; } + + bool user_mode() + { return (flags & USER_MODE) != 0; } }; // one of these for each rule diff --git a/src/parser/parse_conf.cc b/src/parser/parse_conf.cc index 6410ba3e1..2fcdb49f5 100644 --- a/src/parser/parse_conf.cc +++ b/src/parser/parse_conf.cc @@ -237,6 +237,20 @@ void ParseIpVar(SnortConfig* sc, const char* var, const char* val) void add_service_to_otn(SnortConfig* sc, OptTreeNode* otn, const char* svc_name) { + if ( !strcmp(svc_name, "file") and !otn->sigInfo.num_services ) + { + // 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"); + add_service_to_otn(sc, otn, "user"); + return; + } + if (otn->sigInfo.num_services >= sc->max_metadata_services) { ParseError("too many service's specified for rule, can't add %s", svc_name); diff --git a/src/parser/parse_rule.cc b/src/parser/parse_rule.cc index 11aed2470..11da6a321 100644 --- a/src/parser/parse_rule.cc +++ b/src/parser/parse_rule.cc @@ -567,7 +567,7 @@ static int ParsePortList( PortObject* portobject; /* src or dst */ /* Get the protocol specific port object */ - if ( rule_proto & (PROTO_BIT__TCP | PROTO_BIT__UDP) ) + if ( rule_proto & (PROTO_BIT__TCP | PROTO_BIT__UDP | PROTO_BIT__PDU) ) { portobject = ParsePortListTcpUdpPort(pvt, noname, port_str); } @@ -789,9 +789,8 @@ static void PortToFunc(RuleTreeNode* rtn, int any_flag, int except_flag, int mod static void SetupRTNFuncList(RuleTreeNode* rtn) { if (rtn->flags & RuleTreeNode::BIDIRECTIONAL) - { AddRuleFuncToList(CheckBidirectional, rtn); - } + else { PortToFunc(rtn, (rtn->flags & RuleTreeNode::ANY_DST_PORT) ? 1 : 0, 0, DST); @@ -801,6 +800,9 @@ static void SetupRTNFuncList(RuleTreeNode* rtn) AddrToFunc(rtn, DST); } + if ( rtn->snort_protocol_id < SNORT_PROTO_MAX ) + AddRuleFuncToList(CheckProto, rtn); + AddRuleFuncToList(RuleListEnd, rtn); } @@ -1019,7 +1021,7 @@ void parse_rule_proto(SnortConfig* sc, const char* s, RuleTreeNode& rtn) else // this will allow other protocols like http to have ports - rule_proto = PROTO_BIT__TCP; + rule_proto = PROTO_BIT__PDU; rtn.snort_protocol_id = sc->proto_ref->add(s); diff --git a/src/target_based/snort_protocols.cc b/src/target_based/snort_protocols.cc index d48b33e78..98102b524 100644 --- a/src/target_based/snort_protocols.cc +++ b/src/target_based/snort_protocols.cc @@ -113,7 +113,6 @@ void ProtocolReference::init(ProtocolReference* old_proto_ref) ok = ( add("tcp") == SNORT_PROTO_TCP ) and ok; ok = ( add("udp") == SNORT_PROTO_UDP ) and ok; ok = ( add("user") == SNORT_PROTO_USER ) and ok; - ok = ( add("file") == SNORT_PROTO_FILE ) and ok; assert(ok); } else diff --git a/src/target_based/snort_protocols.h b/src/target_based/snort_protocols.h index 66f3cab30..232a8c823 100644 --- a/src/target_based/snort_protocols.h +++ b/src/target_based/snort_protocols.h @@ -41,7 +41,6 @@ enum SnortProtocols : SnortProtocolId SNORT_PROTO_TCP, SNORT_PROTO_UDP, SNORT_PROTO_USER, - SNORT_PROTO_FILE, SNORT_PROTO_MAX }; diff --git a/src/target_based/test/proto_ref_test.cc b/src/target_based/test/proto_ref_test.cc index 2bc480356..7e9a3e46c 100644 --- a/src/target_based/test/proto_ref_test.cc +++ b/src/target_based/test/proto_ref_test.cc @@ -78,7 +78,7 @@ TEST(protocol_reference, service_protocols) CHECK( is_service_protocol(t3) ); } -// Builtin Protocols (ip, icmp, tcp, udp, user and file) +// Builtin Protocols (ip, icmp, tcp, udp, user) // // Verify normal behaviour of the builtin protocols. // 1. Check the builtin protocols match the hardcoded ID's @@ -125,12 +125,6 @@ TEST(protocol_reference, builtin_protocols) CHECK( !is_network_protocol(user) ); CHECK( is_builtin_protocol(user) ); CHECK( is_service_protocol(user) ); - - SnortProtocolId file = refs.add("file"); - CHECK( file == SNORT_PROTO_FILE ); - CHECK( !is_network_protocol(file) ); - CHECK( is_builtin_protocol(file) ); - CHECK( is_service_protocol(file) ); } // Find none