]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3615: Reputation
authorRon Dempster (rdempste) <rdempste@cisco.com>
Mon, 10 Oct 2022 15:07:25 +0000 (15:07 +0000)
committerRon Dempster (rdempste) <rdempste@cisco.com>
Mon, 10 Oct 2022 15:07:25 +0000 (15:07 +0000)
Merge in SNORT/snort3 from ~RDEMPSTE/snort3:reputation to master

Squashed commit of the following:

commit 8570cbe9d6a889c4393efd885ee0365d5820fc24
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Mon Sep 12 14:29:20 2022 -0400

    reputation: added profiling to the event handlers

commit 6641fdf35ecadf53d9f7114fd54ef9e04c5f3712
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Fri Aug 19 16:21:26 2022 -0400

    flow, reputation, protocols: remove reputation information from packet and flow

commit 67b9574c7c955cd4022a94f592c326295e9e03f0
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Thu Aug 18 16:45:49 2022 -0400

    reputation: refactor event generation for matches

src/flow/flow.h
src/network_inspectors/reputation/reputation_inspect.cc
src/protocols/packet.cc
src/protocols/packet.h
src/pub_sub/reputation_events.h

index d4343be5951db82c80bc0b873878ddcc46791b05..f057c27ee45011d69aa42a99be37f222c5c4abac 100644 (file)
@@ -456,8 +456,6 @@ public:  // FIXIT-M privatize if possible
     unsigned ips_policy_id;
     unsigned reload_id;
 
-    uint32_t iplist_monitor_id;
-
     uint32_t tenant;
 
     uint32_t default_session_timeout;
@@ -487,10 +485,6 @@ public:  // FIXIT-M privatize if possible
                                     // currently considered to be the client
         bool app_direction_swapped : 1; // Packet direction swapped from application perspective
         bool disable_inspect : 1;
-        bool reputation_src_dest : 1;
-        bool reputation_blocklist : 1;
-        bool reputation_monitor : 1;
-        bool reputation_allowlist : 1;
         bool trigger_detained_packet_event : 1;
         bool trigger_finalize_event : 1;
         bool use_direct_inject : 1;
index 9f8d1de4be40c2f5fe2f3465ae4230fabcfb0a38..2f1a38c92a3c9ed75e28c02a3b91682810d4a7e8 100644 (file)
@@ -75,7 +75,7 @@ static inline IPrepInfo* reputation_lookup(const ReputationConfig& config,
 }
 
 static inline IPdecision get_reputation(const ReputationConfig& config, ReputationData& data,
-    IPrepInfo* rep_info, uint32_t* listid, uint32_t ingress_intf, uint32_t egress_intf)
+    IPrepInfo* rep_info, uint32_t& listid, uint32_t ingress_intf, uint32_t egress_intf)
 {
     IPdecision decision = DECISION_NULL;
 
@@ -100,13 +100,13 @@ static inline IPdecision get_reputation(const ReputationConfig& config, Reputati
                     return DECISION_NULL;
                 if (config.priority == (IPdecision)list_info[list_index]->list_type )
                 {
-                    *listid = list_info[list_index]->list_id;
+                    listid = list_info[list_index]->list_id;
                     return  ((IPdecision)list_info[list_index]->list_type);
                 }
                 else if ( decision < list_info[list_index]->list_type)
                 {
                     decision = (IPdecision)list_info[list_index]->list_type;
-                    *listid = list_info[list_index]->list_id;
+                    listid = list_info[list_index]->list_id;
                 }
             }
         }
@@ -120,14 +120,14 @@ static inline IPdecision get_reputation(const ReputationConfig& config, Reputati
 }
 
 static bool decision_per_layer(const ReputationConfig& config, ReputationData& data,
-    Packet* p, uint32_t ingress_intf, uint32_t egress_intf, const ip::IpApi& ip_api,
+    uint32_t& iplist_id, uint32_t ingress_intf, uint32_t egress_intf, const ip::IpApi& ip_api,
     IPdecision* decision_final)
 {
     const SfIp* ip = ip_api.get_src();
     IPrepInfo* result = reputation_lookup(config, data, ip);
     if (result)
     {
-        IPdecision decision = get_reputation(config, data, result, &p->iplist_id, ingress_intf,
+        IPdecision decision = get_reputation(config, data, result, iplist_id, ingress_intf,
             egress_intf);
 
         if (decision == BLOCKED)
@@ -147,7 +147,7 @@ static bool decision_per_layer(const ReputationConfig& config, ReputationData& d
     result = reputation_lookup(config, data, ip);
     if (result)
     {
-        IPdecision decision = get_reputation(config, data, result, &p->iplist_id, ingress_intf,
+        IPdecision decision = get_reputation(config, data, result, iplist_id, ingress_intf,
             egress_intf);
 
         if (decision == BLOCKED)
@@ -167,7 +167,7 @@ static bool decision_per_layer(const ReputationConfig& config, ReputationData& d
 }
 
 static IPdecision reputation_decision(const ReputationConfig& config, ReputationData& data,
-    Packet* p)
+    Packet* p, uint32_t& iplist_id)
 {
     IPdecision decision_final = DECISION_NULL;
     uint32_t ingress_intf = 0;
@@ -184,7 +184,7 @@ static IPdecision reputation_decision(const ReputationConfig& config, Reputation
 
     if (config.nested_ip == INNER)
     {
-        decision_per_layer(config, data, p, ingress_intf, egress_intf, p->ptrs.ip_api, &decision_final);
+        decision_per_layer(config, data, iplist_id, ingress_intf, egress_intf, p->ptrs.ip_api, &decision_final);
         return decision_final;
     }
 
@@ -197,7 +197,7 @@ static IPdecision reputation_decision(const ReputationConfig& config, Reputation
     if (config.nested_ip == OUTER)
     {
         layer::set_outer_ip_api(p, p->ptrs.ip_api, p->ip_proto_next, num_layer);
-        decision_per_layer(config, data, p, ingress_intf, egress_intf, p->ptrs.ip_api, &decision_final);
+        decision_per_layer(config, data, iplist_id, ingress_intf, egress_intf, p->ptrs.ip_api, &decision_final);
     }
     else if (config.nested_ip == ALL)
     {
@@ -206,7 +206,7 @@ static IPdecision reputation_decision(const ReputationConfig& config, Reputation
 
         while (!done and layer::set_outer_ip_api(p, p->ptrs.ip_api, p->ip_proto_next, num_layer))
         {
-            done = decision_per_layer(config, data, p, ingress_intf, egress_intf, p->ptrs.ip_api,
+            done = decision_per_layer(config, data, iplist_id, ingress_intf, egress_intf, p->ptrs.ip_api,
                 &decision_current);
             if (decision_current != DECISION_NULL)
             {
@@ -252,19 +252,18 @@ static IPdecision snort_reputation_aux_ip(const ReputationConfig& config, Reputa
     IPrepInfo* result = reputation_lookup(config, data, ip);
     if (result)
     {
-        decision = get_reputation(config, data, result, &p->iplist_id, ingress_intf,
+        uint32_t iplist_id;
+        decision = get_reputation(config, data, result, iplist_id, ingress_intf,
             egress_intf);
 
         if (decision == BLOCKED)
         {
-            if (p->flow)
-                p->flow->flags.reputation_blocklist = true;
-
             // Prior to IPRep logging, IPS policy must be set to the default policy,
             set_ips_policy(get_default_ips_policy(SnortConfig::get_conf()));
 
             DetectionEngine::queue_event(GID_REPUTATION, REPUTATION_EVENT_BLOCKLIST_DST);
-            DataBus::publish(REPUTATION_MATCHED_EVENT, p);
+            ReputationVerdictEvent event(p, REP_VERDICT_BLOCKED, iplist_id, false);
+            DataBus::publish(REPUTATION_MATCHED_EVENT, event);
             p->active->drop_packet(p, true);
 
             // disable all preproc analysis and detection for this packet
@@ -282,23 +281,16 @@ static IPdecision snort_reputation_aux_ip(const ReputationConfig& config, Reputa
         }
         else if (decision == MONITORED)
         {
-            if (p->flow)
-            {
-                p->flow->flags.reputation_monitor = true;
-                p->flow->iplist_monitor_id = p->iplist_id;
-            }
-
             DetectionEngine::queue_event(GID_REPUTATION, REPUTATION_EVENT_MONITOR_DST);
-            DataBus::publish(REPUTATION_MATCHED_EVENT, p);
+            ReputationVerdictEvent event(p, REP_VERDICT_MONITORED, iplist_id, false);
+            DataBus::publish(REPUTATION_MATCHED_EVENT, event);
             reputationstats.aux_ip_monitored++;
         }
         else if (decision == TRUSTED)
         {
-            if (p->flow)
-                p->flow->flags.reputation_allowlist = true;
-
             DetectionEngine::queue_event(GID_REPUTATION, REPUTATION_EVENT_ALLOWLIST_DST);
-            DataBus::publish(REPUTATION_MATCHED_EVENT, p);
+            ReputationVerdictEvent event(p, REP_VERDICT_TRUSTED, iplist_id, false);
+            DataBus::publish(REPUTATION_MATCHED_EVENT, event);
             p->active->trust_session(p, true);
             reputationstats.aux_ip_trusted++;
         }
@@ -337,7 +329,7 @@ static const char* to_string(IPdecision ipd)
     }
 }
 
-static void populate_trace_data(IPdecision& decision, Packet* p)
+static void populate_trace_data(IPdecision& decision, Packet* p, uint32_t iplist_id)
 {
     char addr[INET6_ADDRSTRLEN];
     const SfIp* ip = nullptr;
@@ -356,7 +348,7 @@ static void populate_trace_data(IPdecision& decision, Packet* p)
     PacketTracer::daq_log("SI-IP+%" PRId64"+%s list id %u+Matched ip %s, action %s$",
         TO_NSECS(pt_timer->get()),
         (TRUSTED_SRC == decision or TRUSTED_DST == decision)?"Do_not_block":"Block",
-        p->iplist_id, addr, to_string(decision));
+        iplist_id, addr, to_string(decision));
 }
 
 static void snort_reputation(const ReputationConfig& config, ReputationData& data, Packet* p)
@@ -366,7 +358,8 @@ static void snort_reputation(const ReputationConfig& config, ReputationData& dat
     if (!data.ip_list)
         return;
 
-    decision = reputation_decision(config, data, p);
+    uint32_t iplist_id;
+    decision = reputation_decision(config, data, p, iplist_id);
     Active* act = p->active;
 
     if (BLOCKED_SRC == decision or BLOCKED_DST == decision)
@@ -374,26 +367,23 @@ static void snort_reputation(const ReputationConfig& config, ReputationData& dat
         unsigned blocklist_event = (BLOCKED_SRC == decision) ?
             REPUTATION_EVENT_BLOCKLIST_SRC : REPUTATION_EVENT_BLOCKLIST_DST;
 
-        if (p->flow)
-        {
-            p->flow->flags.reputation_blocklist = true;
-            p->flow->flags.reputation_src_dest = (BLOCKED_SRC == decision);
-        }
-
         DetectionEngine::queue_event(GID_REPUTATION, blocklist_event);
-        DataBus::publish(REPUTATION_MATCHED_EVENT, p);
+        ReputationVerdictEvent event(p, REP_VERDICT_BLOCKED, iplist_id, BLOCKED_SRC == decision);
+        DataBus::publish(REPUTATION_MATCHED_EVENT, event);
         act->drop_packet(p, true);
 
         // disable all preproc analysis and detection for this packet
         DetectionEngine::disable_all(p);
         act->block_session(p, true);
+        if (p->flow)
+            p->flow->set_state(Flow::FlowState::BLOCK);
         act->set_drop_reason("reputation");
         reputationstats.blocked++;
         if (PacketTracer::is_active())
             PacketTracer::log("Reputation: packet blocked, drop\n");
 
         if (PacketTracer::is_daq_activated())
-            populate_trace_data(decision, p);
+            populate_trace_data(decision, p, iplist_id);
 
         return;
     }
@@ -418,14 +408,9 @@ static void snort_reputation(const ReputationConfig& config, ReputationData& dat
         unsigned monitor_event = (MONITORED_SRC == decision) ?
             REPUTATION_EVENT_MONITOR_SRC : REPUTATION_EVENT_MONITOR_DST;
 
-        if (p->flow)
-        {
-            p->flow->flags.reputation_monitor = true;
-            p->flow->flags.reputation_src_dest = (MONITORED_SRC == decision);
-        }
-
         DetectionEngine::queue_event(GID_REPUTATION, monitor_event);
-        DataBus::publish(REPUTATION_MATCHED_EVENT, p);
+        ReputationVerdictEvent event(p, REP_VERDICT_MONITORED, iplist_id, MONITORED_SRC == decision);
+        DataBus::publish(REPUTATION_MATCHED_EVENT, event);
         reputationstats.monitored++;
     }
 
@@ -434,20 +419,15 @@ static void snort_reputation(const ReputationConfig& config, ReputationData& dat
         unsigned allowlist_event = (TRUSTED_SRC == decision) ?
             REPUTATION_EVENT_ALLOWLIST_SRC : REPUTATION_EVENT_ALLOWLIST_DST;
 
-        if (p->flow)
-        {
-            p->flow->flags.reputation_allowlist = true;
-            p->flow->flags.reputation_src_dest = (TRUSTED_SRC == decision);
-        }
-
         DetectionEngine::queue_event(GID_REPUTATION, allowlist_event);
-        DataBus::publish(REPUTATION_MATCHED_EVENT, p);
+        ReputationVerdictEvent event(p, REP_VERDICT_TRUSTED, iplist_id, TRUSTED_SRC == decision);
+        DataBus::publish(REPUTATION_MATCHED_EVENT, event);
         act->trust_session(p, true);
         reputationstats.trusted++;
     }
 
     if (PacketTracer::is_daq_activated())
-        populate_trace_data(decision, p);
+        populate_trace_data(decision, p, iplist_id);
 }
 
 static const char* to_string(NestedIP nip)
@@ -483,7 +463,7 @@ class IpRepHandler : public DataHandler
 public:
     explicit IpRepHandler(Reputation& inspector)
         : DataHandler(REPUTATION_NAME), inspector(inspector)
-    { }
+    { order = 5; }
     void handle(DataEvent&, Flow*) override;
 
 private:
@@ -492,13 +472,12 @@ private:
 
 void IpRepHandler::handle(DataEvent& event, Flow*)
 {
+    Profile profile(reputation_perf_stats);
     Packet* p = const_cast<Packet*>(event.get_packet());
     assert(p);
     if (!p->has_ip())
         return;
 
-    Profile profile(reputation_perf_stats);
-
     if (PacketTracer::is_daq_activated())
         PacketTracer::pt_timer_start();
 
index e2fb3e2f242cb74861054d6d423d15236da475f4..f3022aeb8b7578db21c25a233b7517b11f8ce31b 100644 (file)
@@ -88,7 +88,6 @@ void Packet::reset()
     release_helpers();
     ptrs.reset();
 
-    iplist_id = 0;
     user_inspection_policy_id = 0;
     user_ips_policy_id = 0;
     user_network_policy_id = 0;
index 60481652bdd52eeeb63344e20366862e627b9893..c605741da349d7fe33be9a75c1fe3b1a02bdc728 100644 (file)
@@ -159,7 +159,6 @@ struct SO_PUBLIC Packet
     Layer* layers;    /* decoded encapsulations */
 
     PseudoPacketType pseudo_type;    // valid only when PKT_PSEUDO is set
-    uint32_t iplist_id;
 
     uint32_t user_inspection_policy_id;
     uint32_t user_ips_policy_id;
index 8f2ab9ef5993b3f30d12bbdacb8a61ebc79e2a5b..52bac8a5476d1ad244bc68d802ac04ce76baf12e 100644 (file)
 #ifndef REPUTATION_EVENTS_H
 #define REPUTATION_EVENTS_H
 
+#include "framework/data_bus.h"
+
 #define REPUTATION_MATCHED_EVENT "rep.matched"
 
+namespace snort
+{
+
+enum ReputationVerdict
+{
+    REP_VERDICT_BLOCKED,
+    REP_VERDICT_TRUSTED,
+    REP_VERDICT_MONITORED
+};
+
+class ReputationVerdictEvent : public DataEvent
+{
+public:
+    ReputationVerdictEvent(const Packet* packet, ReputationVerdict verdict, uint32_t list_id, bool source_matched)
+        : packet(packet), verdict(verdict), list_id(list_id), source_matched(source_matched)
+    { }
+
+    const Packet* get_packet() const override
+    { return packet; }
+
+    ReputationVerdict get_verdict() const
+    { return verdict; }
+
+    uint32_t get_list_id() const
+    { return list_id; }
+
+    bool get_source_matched() const
+    { return source_matched; }
+
+private:
+    const Packet* packet;
+    ReputationVerdict verdict;
+    uint32_t list_id;
+    bool source_matched;
+};
+
+}
+
 #endif