]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: tables support per keyword
authorVictor Julien <vjulien@oisf.net>
Thu, 29 May 2025 12:56:02 +0000 (14:56 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 10 Jun 2025 06:36:36 +0000 (08:36 +0200)
Allow keywords to specify in which detect table they can function.

E.g. the pre_flow table will not support flow keywords, as no flow is
availble at this time.

src/detect-engine.c
src/detect-engine.h
src/detect-flow.c
src/detect-flowbits.c
src/detect-parse.c
src/detect-tcp-wscale.c
src/detect.h

index c89c83053dbe4adf0daba55813b65fff4808c7a3..999c96c002c17cd000eefa921886fb4a842d5600 100644 (file)
@@ -126,6 +126,28 @@ const struct SignatureProperties signature_properties[SIG_TYPE_MAX] = {
 // rule types documentation tag end: SignatureProperties
 // clang-format on
 
+const char *DetectTableToString(enum FirewallTable table)
+{
+    switch (table) {
+        case FIREWALL_TABLE_NOT_SET:
+            return "not_set";
+        case FIREWALL_TABLE_PACKET_PRE_FLOW:
+            return "pre_flow";
+        case FIREWALL_TABLE_PACKET_PRE_STREAM:
+            return "pre_stream";
+        case FIREWALL_TABLE_PACKET_FILTER:
+            return "packet_filter";
+        case FIREWALL_TABLE_PACKET_TD:
+            return "packet_td";
+        case FIREWALL_TABLE_APP_FILTER:
+            return "app_filter";
+        case FIREWALL_TABLE_APP_TD:
+            return "app_td";
+        default:
+            return "unknown";
+    }
+}
+
 /** \brief register inspect engine at start up time
  *
  *  \note errors are fatal */
index 557009fcfda7716f776f0fc2d871e0c5ed7c7148..4d22b8075b412acaf12bb8c038f75a906b57ff9c 100644 (file)
@@ -27,6 +27,8 @@
 #include "detect.h"
 #include "suricata.h"
 
+const char *DetectTableToString(enum FirewallTable table);
+
 /* start up registry funcs */
 
 int DetectBufferTypeRegister(const char *name);
index 2a0ef1c9c2fe33c4de73654e98d80b9e085fd344..6ed54152eb9d6b36930446ba44570b33fab1ce47 100644 (file)
@@ -76,6 +76,10 @@ void DetectFlowRegister (void)
 #endif
     sigmatch_table[DETECT_FLOW].SupportsPrefilter = PrefilterFlowIsPrefilterable;
     sigmatch_table[DETECT_FLOW].SetupPrefilter = PrefilterSetupFlow;
+    /* all but pre_flow */
+    sigmatch_table[DETECT_FLOW].tables =
+            DETECT_TABLE_PACKET_PRE_STREAM_FLAG | DETECT_TABLE_PACKET_FILTER_FLAG |
+            DETECT_TABLE_PACKET_TD_FLAG | DETECT_TABLE_APP_FILTER_FLAG | DETECT_TABLE_APP_TD_FLAG;
 
     DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
 }
index 49b7d13735299db8ce0bc0b1508c9b3ecb9d2bfb..2d810112c279427b1b7ca6f3551fcb303fa814fb 100644 (file)
@@ -83,6 +83,10 @@ void DetectFlowbitsRegister (void)
 
     sigmatch_table[DETECT_FLOWBITS].SupportsPrefilter = PrefilterFlowbitIsPrefilterable;
     sigmatch_table[DETECT_FLOWBITS].SetupPrefilter = PrefilterSetupFlowbits;
+    /* all but pre_flow */
+    sigmatch_table[DETECT_FLOWBITS].tables =
+            DETECT_TABLE_PACKET_PRE_STREAM_FLAG | DETECT_TABLE_PACKET_FILTER_FLAG |
+            DETECT_TABLE_PACKET_TD_FLAG | DETECT_TABLE_APP_FILTER_FLAG | DETECT_TABLE_APP_TD_FLAG;
     DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
 }
 
index d526d582194e9ec112a4dcd33f598f1fc7f3ea28..6d8bec8d69acb4c057420500815295e9c8f623f0 100644 (file)
@@ -2446,6 +2446,27 @@ static void SigSetupPrefilter(DetectEngineCtx *de_ctx, Signature *s)
     SCReturn;
 }
 
+/** \internal
+ *  \brief check if signature's table requirement is supported by each of the keywords it uses.
+ */
+static bool DetectRuleValidateTable(const Signature *s)
+{
+    if (s->firewall_table == 0)
+        return true;
+
+    const uint8_t table_as_flag = BIT_U8(s->firewall_table);
+
+    for (SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_MATCH]; sm != NULL; sm = sm->next) {
+        const uint8_t kw_tables_supported = sigmatch_table[sm->type].tables;
+        if (kw_tables_supported != 0 && (kw_tables_supported & table_as_flag) == 0) {
+            SCLogError("rule %u uses hook \"%s\", but keyword \"%s\" doesn't support this hook",
+                    s->id, DetectTableToString(s->firewall_table), sigmatch_table[sm->type].name);
+            return false;
+        }
+    }
+    return true;
+}
+
 static bool DetectFirewallRuleValidate(const DetectEngineCtx *de_ctx, const Signature *s)
 {
     if (s->init_data->hook.type == SIGNATURE_HOOK_TYPE_NOT_SET) {
@@ -2907,6 +2928,9 @@ static Signature *SigInitHelper(
     if (de_ctx->flags & DE_HAS_FIREWALL) {
         DetectFirewallRuleSetTable(sig);
     }
+    if (DetectRuleValidateTable(sig) == false) {
+        goto error;
+    }
 
     if (sig->type == SIG_TYPE_IPONLY) {
         /* For IPOnly */
index 747a0412557969b5c2d772084037e2163268e1df..b0785f77ebe8556311e0520d53f4a355339d7a6f 100644 (file)
@@ -55,6 +55,9 @@ void DetectTcpWscaleRegister(void)
     sigmatch_table[DETECT_TCP_WSCALE].SupportsPrefilter = PrefilterTcpWscaleIsPrefilterable;
     sigmatch_table[DETECT_TCP_WSCALE].SetupPrefilter = PrefilterSetupTcpWscale;
     sigmatch_table[DETECT_TCP_WSCALE].flags = SIGMATCH_SUPPORT_FIREWALL;
+    sigmatch_table[DETECT_TCP_WSCALE].tables =
+            (DETECT_TABLE_PACKET_PRE_FLOW_FLAG | DETECT_TABLE_PACKET_PRE_STREAM_FLAG |
+                    DETECT_TABLE_PACKET_FILTER_FLAG | DETECT_TABLE_PACKET_TD_FLAG);
 }
 
 /**
index 477e89f699fd65bc89a6f08858119a7664f33ca3..d6370ca603dc04d969abbd65c216641b7539c66f 100644 (file)
@@ -550,13 +550,22 @@ enum SignatureHookType {
     SIGNATURE_HOOK_TYPE_APP,
 };
 
+// TODO should probably be renamed to DetectTable, similar for values
 enum FirewallTable {
+    FIREWALL_TABLE_NOT_SET = 0,
     FIREWALL_TABLE_PACKET_PRE_FLOW,
     FIREWALL_TABLE_PACKET_PRE_STREAM,
     FIREWALL_TABLE_PACKET_FILTER,
     FIREWALL_TABLE_PACKET_TD,
     FIREWALL_TABLE_APP_FILTER,
     FIREWALL_TABLE_APP_TD,
+
+#define DETECT_TABLE_PACKET_PRE_FLOW_FLAG   BIT_U8(FIREWALL_TABLE_PACKET_PRE_FLOW)
+#define DETECT_TABLE_PACKET_PRE_STREAM_FLAG BIT_U8(FIREWALL_TABLE_PACKET_PRE_STREAM)
+#define DETECT_TABLE_PACKET_FILTER_FLAG     BIT_U8(FIREWALL_TABLE_PACKET_FILTER)
+#define DETECT_TABLE_PACKET_TD_FLAG         BIT_U8(FIREWALL_TABLE_PACKET_TD)
+#define DETECT_TABLE_APP_FILTER_FLAG        BIT_U8(FIREWALL_TABLE_APP_FILTER)
+#define DETECT_TABLE_APP_TD_FLAG            BIT_U8(FIREWALL_TABLE_APP_TD)
 };
 
 // dns:request_complete should add DetectBufferTypeGetByName("dns:request_complete");
@@ -1429,6 +1438,9 @@ typedef struct SigTableElmt_ {
     uint16_t flags;
     /* coccinelle: SigTableElmt:flags:SIGMATCH_ */
 
+    /** bitfield of tables supported by this rule: used by DETECT_TABLE_*_FLAG flags. */
+    uint8_t tables;
+
     /** better keyword to replace the current one */
     uint16_t alternative;