]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: explicit action scopes
authorVictor Julien <vjulien@oisf.net>
Thu, 3 Apr 2025 14:03:13 +0000 (16:03 +0200)
committerVictor Julien <victor@inliniac.net>
Mon, 7 Apr 2025 20:04:13 +0000 (22:04 +0200)
For drop and pass allow setting the scope explicitly:

        drop:flow
        drop:packet

        pass:flow
        pass:packet

Ticket: #7481.

src/action-globals.h
src/detect-engine-alert.c
src/detect-engine-analyzer.c
src/detect-parse.c
src/detect.h

index edf3d9fc2ff1c626e202b69eb3fa8bdd05bb03af..d6509e98be633fbc95497e05d104707f8393f493 100644 (file)
 
 #define ACTION_DROP_REJECT (ACTION_REJECT_ANY | ACTION_DROP)
 
+enum ActionScope {
+    ACTION_SCOPE_AUTO = 0,
+    ACTION_SCOPE_PACKET, /**< apply action to packet */
+    ACTION_SCOPE_FLOW,   /**< apply drop/pass/accept action to flow */
+};
+
 #endif /* SURICATA_ACTION_GLOBALS_H */
index 51f1896800cdde62cca80c20631c5ebec0f5c9ff..1ec4790f520c9497c6e787dc5ea5a6d54690406f 100644 (file)
@@ -341,12 +341,17 @@ static inline void FlowApplySignatureActions(
         DEBUG_VALIDATE_BUG_ON(s->type == SIG_TYPE_NOT_SET);
         DEBUG_VALIDATE_BUG_ON(s->type == SIG_TYPE_MAX);
 
-        enum SignaturePropertyFlowAction flow_action = signature_properties[s->type].flow_action;
-        if (flow_action == SIG_PROP_FLOW_ACTION_FLOW) {
+        if (s->action_scope == ACTION_SCOPE_FLOW) {
             pa->flags |= PACKET_ALERT_FLAG_APPLY_ACTION_TO_FLOW;
-        } else if (flow_action == SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL) {
-            if (pa->flags & (PACKET_ALERT_FLAG_STATE_MATCH | PACKET_ALERT_FLAG_STREAM_MATCH)) {
+        } else if (s->action_scope == ACTION_SCOPE_AUTO) {
+            enum SignaturePropertyFlowAction flow_action =
+                    signature_properties[s->type].flow_action;
+            if (flow_action == SIG_PROP_FLOW_ACTION_FLOW) {
                 pa->flags |= PACKET_ALERT_FLAG_APPLY_ACTION_TO_FLOW;
+            } else if (flow_action == SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL) {
+                if (pa->flags & (PACKET_ALERT_FLAG_STATE_MATCH | PACKET_ALERT_FLAG_STREAM_MATCH)) {
+                    pa->flags |= PACKET_ALERT_FLAG_APPLY_ACTION_TO_FLOW;
+                }
             }
         }
 
index 3fb0ee219a75e4e791b5f75b8af332cca7cc1d49..e362a6ad8ae3f14c9d72d199e6ea4c2174dfc8b1 100644 (file)
@@ -1035,17 +1035,32 @@ void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
         SCJbAppendString(ctx.js, "pass");
     }
     SCJbClose(ctx.js);
-    enum SignaturePropertyFlowAction flow_action = signature_properties[s->type].flow_action;
-    switch (flow_action) {
-        case SIG_PROP_FLOW_ACTION_PACKET:
-            SCJbSetString(ctx.js, "scope", "packet");
-            break;
-        case SIG_PROP_FLOW_ACTION_FLOW:
-            SCJbSetString(ctx.js, "scope", "flow");
-            break;
-        case SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL:
-            SCJbSetString(ctx.js, "scope", "flow_if_stateful");
-            break;
+
+    if (s->action_scope == ACTION_SCOPE_AUTO) {
+        enum SignaturePropertyFlowAction flow_action = signature_properties[s->type].flow_action;
+        switch (flow_action) {
+            case SIG_PROP_FLOW_ACTION_PACKET:
+                SCJbSetString(ctx.js, "scope", "packet");
+                break;
+            case SIG_PROP_FLOW_ACTION_FLOW:
+                SCJbSetString(ctx.js, "scope", "flow");
+                break;
+            case SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL:
+                SCJbSetString(ctx.js, "scope", "flow_if_stateful");
+                break;
+        }
+    } else {
+        enum ActionScope as = s->action_scope;
+        switch (as) {
+            case ACTION_SCOPE_PACKET:
+                SCJbSetString(ctx.js, "scope", "packet");
+                break;
+            case ACTION_SCOPE_FLOW:
+                SCJbSetString(ctx.js, "scope", "flow");
+                break;
+            case ACTION_SCOPE_AUTO: /* should be unreachable */
+                break;
+        }
     }
     SCJbClose(ctx.js);
 
index 59d980618038f0ab0544303f7591aac61ce4d3fc..15b2cc3677d1043bbd7d1117173e98ac1d0e8197 100644 (file)
@@ -1268,7 +1268,7 @@ static int SigParseProtoHookApp(Signature *s, const char *proto_hook, const char
     }
     s->init_data->hook.sm_list = list;
 
-    SCLogNotice("protocol:%s hook:%s: type:%s alproto:%u hook:%d", p, h,
+    SCLogDebug("protocol:%s hook:%s: type:%s alproto:%u hook:%d", p, h,
             SignatureHookTypeToString(s->init_data->hook.type), s->init_data->hook.t.app.alproto,
             s->init_data->hook.t.app.app_progress);
     return 0;
@@ -1453,12 +1453,52 @@ static uint8_t ActionStringToFlags(const char *action)
  *            Signature.
  * \retval -1 On failure.
  */
-static int SigParseAction(Signature *s, const char *action)
+static int SigParseAction(Signature *s, const char *action_in)
 {
-    uint8_t flags = ActionStringToFlags(action);
+    char action[32];
+    strlcpy(action, action_in, sizeof(action));
+    const char *a = action;
+    const char *o = NULL;
+
+    bool has_scope = strchr(action, ':') != NULL;
+    if (has_scope) {
+        char *xsaveptr = NULL;
+        a = strtok_r(action, ":", &xsaveptr);
+        o = strtok_r(NULL, ":", &xsaveptr);
+        SCLogDebug("a: '%s' o: '%s'", a, o);
+    }
+    if (a == NULL) {
+        SCLogError("invalid protocol specification '%s'", action_in);
+        return -1;
+    }
+
+    uint8_t flags = ActionStringToFlags(a);
     if (flags == 0)
         return -1;
 
+    /* parse scope, if any */
+    if (o) {
+        uint8_t scope_flags = 0;
+        if (flags & (ACTION_DROP | ACTION_PASS)) {
+            if (strcmp(o, "packet") == 0) {
+                scope_flags = (uint8_t)ACTION_SCOPE_PACKET;
+            } else if (strcmp(o, "flow") == 0) {
+                scope_flags = (uint8_t)ACTION_SCOPE_FLOW;
+            } else {
+                SCLogError("invalid action scope '%s' in action '%s': only 'packet' and 'flow' "
+                           "allowed",
+                        o, action_in);
+                return -1;
+            }
+            s->action_scope = scope_flags;
+        } else {
+            SCLogError("invalid action scope '%s' in action '%s': scope only supported for actions "
+                       "'drop', 'pass' and 'reject'",
+                    o, action_in);
+            return -1;
+        }
+    }
+
     s->action = flags;
     return 0;
 }
index b519dcd10ae9b340594713506bfde164391c445a..8eb1d94af6c4965e92b7e42f7053658d5a394654 100644 (file)
@@ -667,6 +667,9 @@ typedef struct Signature_ {
     /** addresses, ports and proto this sig matches on */
     DetectProto proto;
 
+    /* scope setting for the action: enum ActionScope */
+    uint8_t action_scope;
+
     /** ipv4 match arrays */
     uint16_t addr_dst_match4_cnt;
     uint16_t addr_src_match4_cnt;