From: Victor Julien Date: Thu, 3 Apr 2025 14:03:13 +0000 (+0200) Subject: detect: explicit action scopes X-Git-Tag: suricata-8.0.0-beta1~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4071acd659f2f9286f3af24e022892c8358cc1fb;p=thirdparty%2Fsuricata.git detect: explicit action scopes For drop and pass allow setting the scope explicitly: drop:flow drop:packet pass:flow pass:packet Ticket: #7481. --- diff --git a/src/action-globals.h b/src/action-globals.h index edf3d9fc2f..d6509e98be 100644 --- a/src/action-globals.h +++ b/src/action-globals.h @@ -38,4 +38,10 @@ #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 */ diff --git a/src/detect-engine-alert.c b/src/detect-engine-alert.c index 51f1896800..1ec4790f52 100644 --- a/src/detect-engine-alert.c +++ b/src/detect-engine-alert.c @@ -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; + } } } diff --git a/src/detect-engine-analyzer.c b/src/detect-engine-analyzer.c index 3fb0ee219a..e362a6ad8a 100644 --- a/src/detect-engine-analyzer.c +++ b/src/detect-engine-analyzer.c @@ -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); diff --git a/src/detect-parse.c b/src/detect-parse.c index 59d9806180..15b2cc3677 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -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; } diff --git a/src/detect.h b/src/detect.h index b519dcd10a..8eb1d94af6 100644 --- a/src/detect.h +++ b/src/detect.h @@ -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;