// return verification status
virtual bool configure(SnortConfig*) { return true; }
virtual void show(SnortConfig*) { }
- virtual void update(SnortConfig*, const char*) { }
+
+ // Specific to Binders to notify them of an inspector being removed from the policy
+ // FIXIT-L Probably shouldn't be part of the base Inspector class
+ virtual void remove_inspector_binding(SnortConfig*, const char*) { }
// packet thread functions
// tinit, tterm called on default policy instance only
p->decoder_drop = v.get_bool();
else if ( v.is("id") )
+ {
p->user_policy_id = v.get_long();
+ sc->policy_map->set_user_network(p);
+ }
else if ( v.is("min_ttl") )
p->min_ttl = (uint8_t)v.get_long();
#define ips_help \
"configure IPS rule processing"
-THREAD_LOCAL IpsModuleStats snort::ips_module_stats;
-
-const PegInfo ips_module_pegs[] =
-{
- { CountType::SUM, "invalid_policy_ids", "Number of times an invalid policy ID was provided" },
- { CountType::END, nullptr, nullptr }
-};
-
class IpsModule : public Module
{
public:
IpsModule() : Module("ips", ips_help, ips_params) { }
bool set(const char*, Value&, SnortConfig*) override;
- const PegInfo* get_pegs() const override
- { return ips_module_pegs; }
-
- PegCount* get_counts() const override
- { return (PegCount*) &ips_module_stats; }
-
Usage get_usage() const override
{ return DETECT; }
};
extern Trace TRACE_NAME(detection); // FIXIT-L refactor detection module out
-struct IpsModuleStats
-{
- PegCount invalid_policy_ids;
-};
-
-namespace snort
-{
-SO_PUBLIC extern THREAD_LOCAL IpsModuleStats ips_module_stats;
-}
-
#endif
InspectionPolicy* get_default_inspection_policy(SnortConfig* sc)
{ return sc->policy_map->get_inspection_policy(0); }
-void set_user_ips_policy(unsigned policy_id)
+void set_ips_policy(IpsPolicy* p)
+{ s_detection_policy = p; }
+
+void set_network_policy(NetworkPolicy* p)
+{ s_traffic_policy = p; }
+
+IpsPolicy* get_user_ips_policy(SnortConfig* sc, unsigned policy_id)
{
- IpsPolicy *p = SnortConfig::get_conf()->policy_map->get_user_ips(policy_id);
- if(!p)
- {
- snort::ips_module_stats.invalid_policy_ids++;
- return;
- }
+ return sc->policy_map->get_user_ips(policy_id);
+}
- s_detection_policy = p;
+NetworkPolicy* get_user_network_policy(SnortConfig* sc, unsigned policy_id)
+{
+ return sc->policy_map->get_user_network(policy_id);
}
} // namespace snort
-void set_network_policy(NetworkPolicy* p)
-{ s_traffic_policy = p; }
-
void set_network_policy(SnortConfig* sc, unsigned i)
{
PolicyMap* pm = sc->policy_map;
set_inspection_policy(pm->get_inspection_policy(i));
}
-void set_ips_policy(IpsPolicy* p)
-{ s_detection_policy = p; }
-
void set_ips_policy(SnortConfig* sc, unsigned i)
{
PolicyMap* pm = sc->policy_map;
void set_user_ips(IpsPolicy* p)
{ user_ips[p->user_policy_id] = p; }
+ void set_user_network(NetworkPolicy* p)
+ { user_network[p->user_policy_id] = p; }
+
IpsPolicy* get_user_ips(unsigned user_id)
{ return user_ips[user_id]; }
+ NetworkPolicy* get_user_network(unsigned user_id)
+ { return user_network[user_id]; }
+
InspectionPolicy* get_inspection_policy(unsigned i = 0)
{ return i < inspection_policy.size() ? inspection_policy[i] : nullptr; }
std::unordered_map<Shell*, std::shared_ptr<PolicyTuple>> shell_map;
std::unordered_map<unsigned, InspectionPolicy*> user_inspection;
std::unordered_map<unsigned, IpsPolicy*> user_ips;
+ std::unordered_map<unsigned, NetworkPolicy*> user_network;
bool cloned = false;
SO_PUBLIC InspectionPolicy* get_inspection_policy();
SO_PUBLIC IpsPolicy* get_ips_policy();
SO_PUBLIC InspectionPolicy* get_default_inspection_policy(snort::SnortConfig*);
-SO_PUBLIC void set_user_ips_policy(unsigned policy_id);
+SO_PUBLIC void set_ips_policy(IpsPolicy* p);
+SO_PUBLIC void set_network_policy(NetworkPolicy* p);
+SO_PUBLIC IpsPolicy* get_user_ips_policy(snort::SnortConfig* sc, unsigned policy_id);
+SO_PUBLIC NetworkPolicy* get_user_network_policy(snort::SnortConfig* sc, unsigned policy_id);
}
-void set_network_policy(NetworkPolicy*);
void set_network_policy(snort::SnortConfig*, unsigned = 0);
void set_inspection_policy(InspectionPolicy*);
void set_inspection_policy(snort::SnortConfig*, unsigned = 0);
-void set_ips_policy(IpsPolicy*);
void set_ips_policy(snort::SnortConfig*, unsigned = 0);
void set_policies(snort::SnortConfig*, Shell*);
if (PacketTracer::is_active())
{
- PacketTracer::log("NAP id %u, IPS id %u, Verdict %s\n",
- get_network_policy()->policy_id, get_ips_policy()->policy_id,
- SFDAQ::verdict_to_string(verdict));
+ PacketTracer::log("Policies: Network %u, Inspection %u, Detection %u\n",
+ get_network_policy()->user_policy_id, get_inspection_policy()->user_policy_id,
+ get_ips_policy()->user_policy_id);
+ PacketTracer::log("Verdict: %s\n", SFDAQ::verdict_to_string(verdict));
PacketTracer::dump(pkthdr);
}
std::vector<PHInstance*>::iterator bind_it;
if ( get_instance(fp, "binder", false, bind_it) )
{
- (*bind_it)->handler->update(sc, iname);
+ (*bind_it)->handler->remove_inspector_binding(sc, iname);
}
}
if ( (tp_module->api_version() != THIRD_PARTY_APP_ID_API_VERSION)
|| (tp_module->module_name().empty()) )
{
- ErrorMessage("Ignoring incomplete 3rd party AppID module (%s, %d, %s)!\n",
+ ErrorMessage("Ignoring incomplete 3rd party AppID module (%s, %u, %s)!\n",
path, tp_module->api_version(),
tp_module->module_name().empty() ? "empty" : tp_module->module_name().c_str());
void show(SnortConfig*) override
{ LogMessage("Binder\n"); }
- void update(SnortConfig*, const char*) override;
+ void remove_inspector_binding(SnortConfig*, const char*) override;
bool configure(SnortConfig*) override;
return true;
}
-void Binder::update(SnortConfig*, const char* name)
+void Binder::remove_inspector_binding(SnortConfig*, const char* name)
{
vector<Binding*>::iterator it;
for ( it = bindings.begin(); it != bindings.end(); ++it )
// down. performance should be the focus of the next iteration.
void Binder::get_bindings(Flow* flow, Stuff& stuff, Packet* p)
{
- Binding* pb;
- unsigned i, sz = bindings.size();
+ unsigned sz = bindings.size();
- for ( i = 0; i < sz; i++ )
+ // Evaluate policy ID bindings first
+ // FIXIT-P The way these are being used, the policy bindings should be a separate list if not a
+ // separate table entirely
+ // FIXIT-L This will select the first policy ID of each type that it finds and ignore the rest.
+ // It gets potentially hairy if people start specifying overlapping policy types in
+ // overlapping rules.
+ bool inspection_set = false, ips_set = false, network_set = false;
+ for ( unsigned i = 0; i < sz; i++ )
{
- pb = bindings[i];
+ Binding* pb = bindings[i];
- if ( !pb->check_all(flow, p) )
+ // Skip any rules that don't contain an ID for a policy type we haven't set yet.
+ if ( (!pb->use.inspection_index or inspection_set) and
+ (!pb->use.ips_index or ips_set) and
+ (!pb->use.network_index or network_set) )
continue;
- if ( !pb->use.ips_index and !pb->use.inspection_index and !pb->use.network_index )
- {
- if ( stuff.update(pb) )
- return;
- else
- continue;
- }
+ if ( !pb->check_all(flow, p) )
+ continue;
- if ( pb->use.inspection_index )
+ if ( pb->use.inspection_index and !inspection_set )
{
set_inspection_policy(SnortConfig::get_conf(), pb->use.inspection_index - 1);
flow->inspection_policy_id = pb->use.inspection_index - 1;
+ inspection_set = true;
}
- if ( pb->use.ips_index )
+ if ( pb->use.ips_index and !ips_set )
{
set_ips_policy(SnortConfig::get_conf(), pb->use.ips_index - 1);
flow->ips_policy_id = pb->use.ips_index - 1;
+ ips_set = true;
}
- if ( pb->use.network_index )
+ if ( pb->use.network_index and !network_set )
{
set_network_policy(SnortConfig::get_conf(), pb->use.network_index - 1);
flow->network_policy_id = pb->use.network_index - 1;
+ network_set = true;
}
+ }
+
+ Binder* sub = (Binder*)InspectorManager::get_binder();
- Binder* sub = (Binder*)InspectorManager::get_binder();
+ // If policy selection produced a new binder to use, use that instead.
+ if ( sub && sub != this )
+ {
+ sub->get_bindings(flow, stuff, p);
+ return;
+ }
+
+ // If we got here, that means that a sub-policy with a binder was not invoked.
+ // Continue using this binder for the rest of processing.
+ for ( unsigned i = 0; i < sz; i++ )
+ {
+ Binding* pb = bindings[i];
- // If selected sub-policy is IPS, inspection policy wont
- // change and get_binder() will return this binder. Keep
- // checking rules in case a new inspection policy is specified
- // after.
- if ( sub == this )
+ if ( pb->use.ips_index or pb->use.inspection_index or pb->use.network_index )
continue;
- if ( sub )
- {
- sub->get_bindings(flow, stuff, p);
+ if ( !pb->check_all(flow, p) )
+ continue;
+
+ if ( stuff.update(pb) )
return;
- }
}
}
int max_depth)
{
auto& entries = cur.children;
+ unsigned num_entries;
if ( !count || count > entries.size() )
- count = entries.size();
+ num_entries = entries.size();
+ else
+ num_entries = count;
if ( sort )
- std::partial_sort(entries.begin(), entries.begin() + count, entries.end(), sort);
+ std::partial_sort(entries.begin(), entries.begin() + num_entries, entries.end(), sort);
- for ( unsigned i = 0; i < count; ++i )
+ for ( unsigned i = 0; i < num_entries; ++i )
{
auto& entry = entries[i];