]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: set implied flow direction based on keywords
authorVictor Julien <victor@inliniac.net>
Fri, 3 Nov 2017 11:29:49 +0000 (12:29 +0100)
committerVictor Julien <victor@inliniac.net>
Wed, 14 Feb 2018 13:25:46 +0000 (14:25 +0100)
src/detect-flow.c
src/detect-flow.h
src/detect-parse.c

index 06992d48a472aa5d4970adc3aaf44d3d0f692920..88490285ae44369ae7496ac941e29570f16a929f 100644 (file)
@@ -316,6 +316,37 @@ error:
 
 }
 
+int DetectFlowSetupImplicit(Signature *s, uint32_t flags)
+{
+#define SIG_FLAG_BOTH (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)
+    BUG_ON(flags == 0);
+    BUG_ON(flags & ~SIG_FLAG_BOTH);
+    BUG_ON((flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH);
+
+    SCLogDebug("want %08x", flags & SIG_FLAG_BOTH);
+    SCLogDebug("have %08x", s->flags & SIG_FLAG_BOTH);
+
+    if (flags & SIG_FLAG_TOSERVER) {
+        if ((s->flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH) {
+            /* both is set if we just have 'flow:established' */
+            s->flags &= ~SIG_FLAG_TOCLIENT;
+        } else if (s->flags & SIG_FLAG_TOCLIENT) {
+            return -1;
+        }
+        s->flags |= SIG_FLAG_TOSERVER;
+    } else {
+        if ((s->flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH) {
+            /* both is set if we just have 'flow:established' */
+            s->flags &= ~SIG_FLAG_TOSERVER;
+        } else if (s->flags & SIG_FLAG_TOSERVER) {
+            return -1;
+        }
+        s->flags |= SIG_FLAG_TOCLIENT;
+    }
+    return 0;
+#undef SIG_FLAG_BOTH
+}
+
 /**
  * \brief this function is used to add the parsed flowdata into the current signature
  *
index dc050b40d9a01e6fb547448746513880b79c0b85..0fee4bf8c17a491ae281640f4f34775901256754 100644 (file)
@@ -39,6 +39,8 @@ typedef struct DetectFlowData_ {
     uint8_t match_cnt;  /* number of matches we need */
 } DetectFlowData;
 
+int DetectFlowSetupImplicit(Signature *s, uint32_t flags);
+
 /* prototypes */
 void DetectFlowRegister (void);
 
index 5b3cd3243b6759dec1035d8736bf9ba84b545d04..bd7fd1e2d4c68418bdf4498cb6c4b243b042797c 100644 (file)
@@ -1553,15 +1553,65 @@ static int SigValidate(DetectEngineCtx *de_ctx, Signature *s)
             SCReturnInt(0);
     }
 
+    struct BufferVsDir {
+        int ts;
+        int tc;
+    } bufdir[nlists];
+    memset(&bufdir, 0, nlists * sizeof(struct BufferVsDir));
+
     int x;
     for (x = 0; x < nlists; x++) {
         if (s->init_data->smlists[x]) {
+            const DetectEngineAppInspectionEngine *app = de_ctx->app_inspect_engines;
+            for ( ; app != NULL; app = app->next) {
+                if (app->sm_list == x && s->alproto == app->alproto) {
+                    SCLogDebug("engine %s dir %d alproto %d",
+                            DetectBufferTypeGetNameById(de_ctx, app->sm_list),
+                            app->dir, app->alproto);
+
+                    bufdir[x].ts += (app->dir == 0);
+                    bufdir[x].tc += (app->dir == 1);
+                }
+            }
+
             if (DetectBufferRunValidateCallback(de_ctx, x, s, &de_ctx->sigerror) == FALSE) {
                 SCReturnInt(0);
             }
         }
     }
 
+    int ts_excl = 0;
+    int tc_excl = 0;
+    int dir_amb = 0;
+    for (x = 0; x < nlists; x++) {
+        if (bufdir[x].ts == 0 && bufdir[x].tc == 0)
+            continue;
+        ts_excl += (bufdir[x].ts > 0 && bufdir[x].tc == 0);
+        tc_excl += (bufdir[x].ts == 0 && bufdir[x].tc > 0);
+        dir_amb += (bufdir[x].ts > 0 && bufdir[x].tc > 0);
+
+        SCLogDebug("%s/%d: %d/%d", DetectBufferTypeGetNameById(de_ctx, x),
+                x, bufdir[x].ts, bufdir[x].tc);
+    }
+    if (ts_excl && tc_excl) {
+        SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
+        SCReturnInt(0);
+    } else if (ts_excl) {
+        SCLogDebug("%u: implied rule direction is toserver", s->id);
+        if (DetectFlowSetupImplicit(s, SIG_FLAG_TOSERVER) < 0) {
+            SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
+            SCReturnInt(0);
+        }
+    } else if (tc_excl) {
+        SCLogDebug("%u: implied rule direction is toclient", s->id);
+        if (DetectFlowSetupImplicit(s, SIG_FLAG_TOCLIENT) < 0) {
+            SCLogError(SC_ERR_INVALID_SIGNATURE, "rule %u mixes keywords with conflicting directions", s->id);
+            SCReturnInt(0);
+        }
+    } else if (dir_amb) {
+        SCLogDebug("%u: rule direction cannot be deduced from keywords", s->id);
+    }
+
     if ((s->flags & SIG_FLAG_REQUIRE_PACKET) &&
         (s->flags & SIG_FLAG_REQUIRE_STREAM)) {
         SCLogError(SC_ERR_INVALID_SIGNATURE, "can't mix packet keywords with "