From: Oleksandr Stepanov -X (ostepano - SOFTSERVE INC at Cisco) Date: Mon, 26 Aug 2024 14:35:54 +0000 (+0000) Subject: Pull request #4369: appid: Notify binder on service change X-Git-Tag: 3.3.4.0~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b52974331cbc3386dd248a714b2c2dc0088c9b5;p=thirdparty%2Fsnort3.git Pull request #4369: appid: Notify binder on service change Merge in SNORT/snort3 from ~OSTEPANO/snort3:appid_binder to master Squashed commit of the following: commit b95ee6c0632260fe1a295f7eba7b90ae7be4424d Author: Oleksandr Stepanov Date: Mon Jul 1 09:00:35 2024 -0400 appid: Notify binder on service change --- diff --git a/src/flow/flow.h b/src/flow/flow.h index 9f1e46452..6e4bb03a6 100644 --- a/src/flow/flow.h +++ b/src/flow/flow.h @@ -521,6 +521,8 @@ public: // FIXIT-M privatize if possible bool ips_block_event_suppressed : 1; // Set if event filters have suppressed a block ips event bool ips_wblock_event_suppressed : 1; // set if event filters have suppressed a would block/drop ips event bool ips_pblock_event_suppressed : 1; // set if event filters have suppressed a partial block ips event + bool binder_action_allow : 1; + bool binder_action_block : 1; } flags = {}; FlowState flow_state = FlowState::SETUP; diff --git a/src/network_inspectors/binder/bind_module.cc b/src/network_inspectors/binder/bind_module.cc index 6d034702c..1f8c095be 100644 --- a/src/network_inspectors/binder/bind_module.cc +++ b/src/network_inspectors/binder/bind_module.cc @@ -40,6 +40,8 @@ using namespace std; #define INSPECTION_KEY ".inspection" #define IPS_KEY ".ips" +unsigned int BinderModule::module_id = 0; + THREAD_LOCAL BindStats bstats; static const PegInfo bind_pegs[] = @@ -122,7 +124,7 @@ static const Parameter binder_when_params[] = "use the given configuration on one or any end of a session" }, { "service", Parameter::PT_STRING, nullptr, nullptr, - "override default configuration" }, + "space separated list of services" }, { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; @@ -232,6 +234,9 @@ bool BinderModule::begin(const char* fqn, int idx, SnortConfig*) policy_type.clear(); } + if (!module_id) + module_id = FlowData::create_flow_data_id(); + return true; } @@ -240,7 +245,7 @@ bool BinderModule::set(const char* fqn, Value& v, SnortConfig*) // both if ( !strcmp(fqn, "binder.when.service") ) { - binding.when.svc = v.get_string(); + binding.when.parse_service(v.get_string()); binding.when.add_criteria(BindWhen::Criteria::BWC_SVC); } else if ( !strcmp(fqn, "binder.use.service") ) @@ -483,7 +488,7 @@ bool BinderModule::end(const char* fqn, int idx, SnortConfig* sc) void BinderModule::add(const char* svc, const char* type) { binding.clear(); - binding.when.svc = svc; + binding.when.parse_service(svc); binding.when.add_criteria(BindWhen::Criteria::BWC_SVC); binding.use.type = type; binding.use.name = type; diff --git a/src/network_inspectors/binder/bind_module.h b/src/network_inspectors/binder/bind_module.h index 2fda481b6..5cfd3a6c3 100644 --- a/src/network_inspectors/binder/bind_module.h +++ b/src/network_inspectors/binder/bind_module.h @@ -68,6 +68,8 @@ public: Usage get_usage() const override { return INSPECT; } + static unsigned int module_id; + private: Binding binding; std::vector bindings; diff --git a/src/network_inspectors/binder/binder.cc b/src/network_inspectors/binder/binder.cc index ccef0efb1..cab438ebc 100644 --- a/src/network_inspectors/binder/binder.cc +++ b/src/network_inspectors/binder/binder.cc @@ -21,6 +21,8 @@ #include "config.h" #endif + +#include "appid/appid_session_api.h" #include "detection/detection_engine.h" #include "flow/flow.h" #include "framework/pig_pen.h" @@ -30,6 +32,7 @@ #include "packet_io/active.h" #include "profiler/profiler.h" #include "protocols/packet.h" +#include "pub_sub/appid_events.h" #include "pub_sub/assistant_gadget_event.h" #include "pub_sub/intrinsic_event_ids.h" #include "pub_sub/stream_event_ids.h" @@ -198,7 +201,7 @@ static std::string to_string(const BindWhen& bw) } if (bw.has_criteria(BindWhen::Criteria::BWC_SVC)) - when += " service = " + bw.svc + ","; + when += " service = " + bw.get_service_list() + ","; if (bw.has_criteria(BindWhen::Criteria::BWC_SPLIT_NETS)) { @@ -489,6 +492,7 @@ public: void handle_flow_service_change(Flow&); void handle_assistant_gadget(const char* service, Flow&); void handle_flow_after_reload(Flow&); + void handle_appid_service_change(DataEvent&,Flow&); private: void get_policy_bindings(Flow&, const char* service); @@ -533,6 +537,19 @@ public: } }; +class AppIDServiceChangeHandler : public DataHandler +{ + public: + AppIDServiceChangeHandler() : DataHandler(BIND_NAME) { } + + void handle(DataEvent& event, Flow* flow) override + { + Binder* binder = (Binder*)InspectorManager::get_binder(); + if (binder && flow) + binder->handle_appid_service_change(event, *flow); + } +}; + // When a flow's service changes, re-evaluate service to inspector mapping. class FlowServiceChangeHandler : public DataHandler { @@ -636,6 +653,7 @@ bool Binder::configure(SnortConfig* sc) DataBus::subscribe(intrinsic_pub_key, IntrinsicEventIds::FLOW_SERVICE_CHANGE, new FlowServiceChangeHandler()); DataBus::subscribe(intrinsic_pub_key, IntrinsicEventIds::FLOW_ASSISTANT_GADGET, new AssistantGadgetHandler()); DataBus::subscribe(intrinsic_pub_key, IntrinsicEventIds::FLOW_STATE_RELOADED, new RebindFlow()); + DataBus::subscribe(appid_pub_key, AppIdEventIds::ANY_CHANGE, new AppIDServiceChangeHandler()); DataBus::subscribe(stream_pub_key, StreamEventIds::HA_NEW_FLOW, new StreamHANewFlowHandler()); @@ -752,6 +770,49 @@ void Binder::handle_flow_setup(Flow& flow, bool standby) bstats.verdicts[stuff.action]++; } +void Binder::handle_appid_service_change(DataEvent& event, Flow& flow) +{ + AppidEvent& appid_event = static_cast(event); + + if(appid_event.get_change_bitset().test(APPID_SERVICE_BIT)) + { + if ((appid_event.get_appid_session_api().get_service_app_id() <= 0) + or (flow.ssn_state.snort_protocol_id == 0)) + return; + + Stuff stuff; + const SnortConfig* sc = SnortConfig::get_conf(); + const char* service = sc->proto_ref->get_name(flow.ssn_state.snort_protocol_id); + get_bindings(flow, stuff, service); + + if(stuff.action == BindUse::BA_ALLOW) + { + flow.set_deferred_trust(BinderModule::module_id, true); + flow.flags.binder_action_allow = true; + } + else if (stuff.action == BindUse::BA_BLOCK) + { + flow.flags.binder_action_block = true; + } + } + + if(appid_event.get_change_bitset().test(APPID_DISCOVERY_FINISHED_BIT)) + { + //apply action for delay + if(flow.flags.binder_action_allow) + { + flow.try_trust(); + flow.set_deferred_trust(BinderModule::module_id, false); + } + else if(flow.flags.binder_action_block) + { + flow.block(); + auto p = const_cast(appid_event.get_packet()); + p->active->block_session(p, true); + } + } +} + void Binder::handle_flow_service_change(Flow& flow) { bstats.service_changes++; @@ -763,6 +824,7 @@ void Binder::handle_flow_service_change(Flow& flow) if (stuff.action != BindUse::BA_INSPECT) { stuff.apply_action(flow); + flow.disable_inspection(); return; } diff --git a/src/network_inspectors/binder/binding.cc b/src/network_inspectors/binder/binding.cc index bac7f5a0f..9519343e4 100644 --- a/src/network_inspectors/binder/binding.cc +++ b/src/network_inspectors/binder/binding.cc @@ -45,7 +45,7 @@ void Binding::clear() when.ips_id_user = 0; when.protos = PROTO_BIT__ANY_TYPE; when.role = BindWhen::BR_EITHER; - when.svc.clear(); + when.svc_list.clear(); if (when.src_nets) { @@ -587,7 +587,7 @@ inline bool Binding::check_service(const Flow& flow) const if (!flow.service) return false; - return when.svc == flow.service; + return when.svc_list.find(flow.service) != when.svc_list.end(); } inline bool Binding::check_service(const char* service) const @@ -597,7 +597,7 @@ inline bool Binding::check_service(const char* service) const if (!when.has_criteria(BindWhen::Criteria::BWC_SVC)) return false; - return when.svc == service; + return when.svc_list.find(service) != when.svc_list.end(); } inline bool Binding::check_service() const diff --git a/src/network_inspectors/binder/binding.h b/src/network_inspectors/binder/binding.h index bc27133fb..d96d4bd70 100644 --- a/src/network_inspectors/binder/binding.h +++ b/src/network_inspectors/binder/binding.h @@ -21,6 +21,7 @@ #define BINDING_H #include +#include #include "main/policy.h" #include "sfip/sf_ipvar.h" @@ -42,7 +43,6 @@ struct BindWhen unsigned ips_id_user; unsigned protos; Role role; - std::string svc; sfip_var_t* src_nets; sfip_var_t* dst_nets; @@ -52,6 +52,8 @@ struct BindWhen PortBitSet src_ports; PortBitSet dst_ports; + std::unordered_set svc_list; + std::unordered_set src_intfs; std::unordered_set dst_intfs; @@ -85,6 +87,28 @@ struct BindWhen { criteria_flags |= flags; } bool has_criteria(uint16_t flags) const { return (criteria_flags & flags) == flags; } + + void parse_service(const std::string& service) + { + if (service.find(" ") == std::string::npos) + { + svc_list.emplace(service); + return; + } + + std::string buf; + std::stringstream ss(service); + while(getline(ss, buf, ' ')) + svc_list.emplace(buf); + } + + std::string get_service_list() const + { + std::string res; + for(const auto& entry : svc_list) + res += entry; + return res; + } }; struct BindUse