#define INSPECTION_KEY ".inspection"
#define IPS_KEY ".ips"
+unsigned int BinderModule::module_id = 0;
+
THREAD_LOCAL BindStats bstats;
static const PegInfo bind_pegs[] =
"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 }
};
policy_type.clear();
}
+ if (!module_id)
+ module_id = FlowData::create_flow_data_id();
+
return true;
}
// 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") )
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;
#include "config.h"
#endif
+
+#include "appid/appid_session_api.h"
#include "detection/detection_engine.h"
#include "flow/flow.h"
#include "framework/pig_pen.h"
#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"
}
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))
{
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);
}
};
+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
{
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());
bstats.verdicts[stuff.action]++;
}
+void Binder::handle_appid_service_change(DataEvent& event, Flow& flow)
+{
+ AppidEvent& appid_event = static_cast<AppidEvent&>(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<Packet*>(appid_event.get_packet());
+ p->active->block_session(p, true);
+ }
+ }
+}
+
void Binder::handle_flow_service_change(Flow& flow)
{
bstats.service_changes++;
if (stuff.action != BindUse::BA_INSPECT)
{
stuff.apply_action(flow);
+ flow.disable_inspection();
return;
}
#define BINDING_H
#include <string>
+#include <sstream>
#include "main/policy.h"
#include "sfip/sf_ipvar.h"
unsigned ips_id_user;
unsigned protos;
Role role;
- std::string svc;
sfip_var_t* src_nets;
sfip_var_t* dst_nets;
PortBitSet src_ports;
PortBitSet dst_ports;
+ std::unordered_set<std::string> svc_list;
+
std::unordered_set<int32_t> src_intfs;
std::unordered_set<int32_t> dst_intfs;
{ 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