]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
Fix drop (and other actions) not being applied to thresholded packets. Bug #613.
authorVictor Julien <victor@inliniac.net>
Tue, 30 Oct 2012 11:58:58 +0000 (12:58 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 30 Oct 2012 15:19:15 +0000 (16:19 +0100)
src/detect-detection-filter.c
src/detect-engine-alert.c
src/detect-engine-iponly.c
src/detect-engine-threshold.c
src/detect-threshold.c
src/detect.c
src/util-threshold-config.c

index 4b74765f15115d0043e340d7a232458738e56344..9573b44b3b5e65dffc37a482f9350d6fe719200d 100644 (file)
@@ -536,7 +536,102 @@ end:
     return result;
 }
 
+/**
+ *  \test drops
+ */
+static int DetectDetectionFilterTestSig3(void) {
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx;
+    int result = 0;
+    int alerts = 0;
+    int drops = 0;
+    struct timeval ts;
+
+    HostInitConfig(HOST_QUIET);
+
+    memset (&ts, 0, sizeof(struct timeval));
+    TimeGet(&ts);
+
+    memset(&th_v, 0, sizeof(th_v));
+
+    p = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
 
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (msg:\"detection_filter Test 2\"; detection_filter: track by_dst, count 2, seconds 60; sid:10;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    TimeGet(&p->ts);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts = PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    TimeSetIncrementTime(200);
+    TimeGet(&p->ts);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    if (alerts == 3 && drops == 3)
+        result = 1;
+    else {
+        if (alerts != 3)
+            printf("alerts: %d != 3: ", alerts);
+        if (drops != 3)
+            printf("drops: %d != 3: ", drops);
+    }
+
+    SigGroupCleanup(de_ctx);
+    SigCleanSignatures(de_ctx);
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+end:
+    UTHFreePackets(&p, 1);
+    HostShutdown();
+    return result;
+}
 #endif /* UNITTESTS */
 
 void DetectDetectionFilterRegisterTests(void) {
@@ -549,6 +644,7 @@ void DetectDetectionFilterRegisterTests(void) {
     UtRegisterTest("DetectDetectionFilterTestParse06", DetectDetectionFilterTestParse06, 0);
     UtRegisterTest("DetectDetectionFilterTestSig1", DetectDetectionFilterTestSig1, 1);
     UtRegisterTest("DetectDetectionFilterTestSig2", DetectDetectionFilterTestSig2, 1);
+    UtRegisterTest("DetectDetectionFilterTestSig3", DetectDetectionFilterTestSig3, 1);
 #endif /* UNITTESTS */
 }
 
index 0b2f78f42650a2239d320e416adaa8c8091f2c1f..e1839f7498af72f7bb4dcba0ef447ff0bf3cff95 100644 (file)
@@ -54,6 +54,7 @@ PacketAlert *PacketAlertGetTag(void) {
 
 /**
  * \brief Handle a packet and check if needs a threshold logic
+ *        Also apply rule action if necessary.
  *
  * \param de_ctx Detection Context
  * \param sig Signature pointer
@@ -78,16 +79,18 @@ static int PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det
         td = SigGetThresholdTypeIter(s, p, &sm);
         if (td != NULL) {
             SCLogDebug("td %p", td);
+
+            /* PacketAlertThreshold returns 2 if the alert is suppressed but
+             * we do need to apply rule actions to the packet. */
             ret = PacketAlertThreshold(de_ctx, det_ctx, td, p, s);
-            if (ret == 0) {
+            if (ret == 0 || ret == 2) {
                 /* It doesn't match threshold, remove it */
-                PacketAlertRemove(p, pos);
-                break;
+                SCReturnInt(ret);
             }
         }
     } while (sm != NULL);
 
-    SCReturnInt(ret);
+    SCReturnInt(1);
 }
 
 
@@ -126,8 +129,11 @@ int PacketAlertRemove(Packet *p, uint16_t pos)
 {
     uint16_t i = 0;
     int match = 0;
-    if (pos > p->alerts.cnt)
+
+    if (pos > p->alerts.cnt) {
+        SCLogDebug("removing %u failed, pos > cnt %u", pos, p->alerts.cnt);
         return 0;
+    }
 
     for (i = pos; i <= p->alerts.cnt - 1; i++) {
         memcpy(&p->alerts.alerts[i], &p->alerts.alerts[i + 1], sizeof(PacketAlert));
@@ -198,20 +204,16 @@ int PacketAlertAppend(DetectEngineThreadCtx *det_ctx, Signature *s, Packet *p, u
  */
 void PacketAlertFinalize(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p) {
     SCEnter();
-
     int i = 0;
     Signature *s = NULL;
     SigMatch *sm = NULL;
 
-    for (i = 0; i < p->alerts.cnt; i++) {
+    while (i < p->alerts.cnt) {
         SCLogDebug("Sig->num: %"PRIu16, p->alerts.alerts[i].num);
         s = de_ctx->sig_array[p->alerts.alerts[i].num];
 
         int res = PacketAlertHandle(de_ctx, det_ctx, s, p, i);
-        /* Thresholding might remove one alert */
-        if (res == 0) {
-            i--;
-        } else {
+        if (res > 0) {
             /* Now, if we have an alert, we have to check if we want
              * to tag this session or src/dst host */
             sm = s->sm_lists[DETECT_SM_LIST_TMATCH];
@@ -267,9 +269,16 @@ void PacketAlertFinalize(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx
                 FLOWLOCK_UNLOCK(p->flow);
             }
         }
-        /* Because we removed the alert from the array, we should
-         * have compacted the array and decreased cnt by one, so
-         * process again the same position (with different alert now) */
+
+        /* Thresholding removes this alert */
+        if (res == 0 || res == 2) {
+            PacketAlertRemove(p, i);
+
+            if (p->alerts.cnt == 0)
+                break;
+        } else {
+            i++;
+        }
     }
 
     /* At this point, we should have all the new alerts. Now check the tag
index af3c05030fa7d7fd6f65d64f7ccfed570fa843ef..563f1919032d92fed057de63d3ea6ce363d714e0 100644 (file)
@@ -1074,11 +1074,14 @@ void IPOnlyMatchPacket(ThreadVars *tv,
                             (void)sigmatch_table[sm->type].Match(tv, det_ctx, p, s, sm);
                         }
                     }
-                    if ( !(s->flags & SIG_FLAG_NOALERT)) {
+                    if (!(s->flags & SIG_FLAG_NOALERT)) {
                         if (s->action & ACTION_DROP)
                             PacketAlertAppend(det_ctx, s, p, PACKET_ALERT_FLAG_DROP_FLOW);
                         else
                             PacketAlertAppend(det_ctx, s, p, 0);
+                    } else {
+                        /* apply actions for noalert/rule suppressed as well */
+                        p->action |= s->action;
                     }
                 }
             }
index 3c69609089759f5dc057c6099dcd7d32ec39d634..d152d2732bb688396a619c215b64cab3a361efd3 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2010 Open Information Security Foundation
+/* Copyright (C) 2007-2012 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -201,6 +201,11 @@ static DetectThresholdEntry *ThresholdHostLookupEntry(Host *h, uint32_t sid, uin
     return e;
 }
 
+/**
+ *  \retval 2 silent match (no alert but apply actions)
+ *  \retval 1 normal match
+ *  \retval 0 no match
+ */
 int ThresholdHandlePacketHost(Host *h, Packet *p, DetectThresholdData *td, uint32_t sid, uint32_t gid) {
     int ret = 0;
 
@@ -218,6 +223,8 @@ int ThresholdHandlePacketHost(Host *h, Packet *p, DetectThresholdData *td, uint3
 
                     if (lookup_tsh->current_count <= td->count) {
                         ret = 1;
+                    } else {
+                        ret = 2;
                     }
                 } else    {
                     lookup_tsh->tv_sec1 = p->ts.tv_sec;
@@ -286,6 +293,9 @@ int ThresholdHandlePacketHost(Host *h, Packet *p, DetectThresholdData *td, uint3
                     lookup_tsh->current_count++;
                     if (lookup_tsh->current_count == td->count) {
                         ret = 1;
+                    } else if (lookup_tsh->current_count > td->count) {
+                        /* silent match */
+                        ret = 2;
                     }
                 } else {
                     /* expired, so reset */
@@ -462,6 +472,8 @@ int ThresholdHandlePacketHost(Host *h, Packet *p, DetectThresholdData *td, uint3
             }
             if (res == 0)
                 ret = 1;
+            else
+                ret = 2; /* suppressed but still need actions */
             break;
         }
         default:
@@ -564,6 +576,7 @@ static int ThresholdHandlePacketRule(DetectEngineCtx *de_ctx, Packet *p, DetectT
  * \param p Packet structure
  * \param s Signature structure
  *
+ * \retval 2 silent match (no alert but apply actions)
  * \retval 1 alert on this event
  * \retval 0 do not alert on this event
  */
index 8074f3702035b1bf104e8b8c79eadad58a390e50..a1db7b84b4b4aeecd0c5fb702e454fb30e5d9368 100644 (file)
@@ -817,8 +817,10 @@ static int DetectThresholdTestSig5(void) {
 
     if(alerts == 10)
         result = 1;
-    else
+    else {
+        printf("alerts %d != 10: ", alerts);
         goto cleanup;
+    }
 
 cleanup:
     SigGroupCleanup(de_ctx);
@@ -914,6 +916,565 @@ end:
     HostShutdown();
     return result;
 }
+
+/**
+ * \test Test drop action being set even if thresholded
+ */
+static int DetectThresholdTestSig7(void) {
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx;
+    int result = 0;
+    int alerts = 0;
+    int drops = 0;
+    struct timeval ts;
+
+    HostInitConfig(HOST_QUIET);
+
+    memset (&ts, 0, sizeof(struct timeval));
+    TimeGet(&ts);
+
+    memset(&th_v, 0, sizeof(th_v));
+
+    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type limit, track by_src, count 1, seconds 300; sid:10;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    TimeGet(&p->ts);
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts = PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    TimeSetIncrementTime(200);
+    TimeGet(&p->ts);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    if (alerts == 1 && drops == 6)
+        result = 1;
+    else {
+        if (alerts != 1)
+            printf("alerts: %d != 1: ", alerts);
+        if (drops != 6)
+            printf("drops: %d != 6: ", drops);
+        goto cleanup;
+    }
+
+cleanup:
+    SigGroupCleanup(de_ctx);
+    SigCleanSignatures(de_ctx);
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+end:
+    UTHFreePackets(&p, 1);
+    HostShutdown();
+    return result;
+}
+
+/**
+ * \test Test drop action being set even if thresholded
+ */
+static int DetectThresholdTestSig8(void) {
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx;
+    int result = 0;
+    int alerts = 0;
+    int drops = 0;
+    struct timeval ts;
+
+    HostInitConfig(HOST_QUIET);
+
+    memset (&ts, 0, sizeof(struct timeval));
+    TimeGet(&ts);
+
+    memset(&th_v, 0, sizeof(th_v));
+
+    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type limit, track by_src, count 2, seconds 300; sid:10;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    TimeGet(&p->ts);
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts = PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    TimeSetIncrementTime(200);
+    TimeGet(&p->ts);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    if (alerts == 2 && drops == 6)
+        result = 1;
+    else {
+        if (alerts != 1)
+            printf("alerts: %d != 1: ", alerts);
+        if (drops != 6)
+            printf("drops: %d != 6: ", drops);
+        goto cleanup;
+    }
+
+cleanup:
+    SigGroupCleanup(de_ctx);
+    SigCleanSignatures(de_ctx);
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+end:
+    UTHFreePackets(&p, 1);
+    HostShutdown();
+    return result;
+}
+
+/**
+ * \test Test drop action being set even if thresholded
+ */
+static int DetectThresholdTestSig9(void) {
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx;
+    int result = 0;
+    int alerts = 0;
+    int drops = 0;
+    struct timeval ts;
+
+    HostInitConfig(HOST_QUIET);
+
+    memset (&ts, 0, sizeof(struct timeval));
+    TimeGet(&ts);
+
+    memset(&th_v, 0, sizeof(th_v));
+
+    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type threshold, track by_src, count 3, seconds 100; sid:10;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    TimeGet(&p->ts);
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts = PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    TimeSetIncrementTime(200);
+    TimeGet(&p->ts);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    if (alerts == 2 && drops == 2)
+        result = 1;
+    else {
+        if (alerts != 2)
+            printf("alerts: %d != 2: ", alerts);
+        if (drops != 2)
+            printf("drops: %d != 2: ", drops);
+        goto cleanup;
+    }
+
+cleanup:
+    SigGroupCleanup(de_ctx);
+    SigCleanSignatures(de_ctx);
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+end:
+    UTHFreePackets(&p, 1);
+    HostShutdown();
+    return result;
+}
+
+/**
+ * \test Test drop action being set even if thresholded
+ */
+static int DetectThresholdTestSig10(void) {
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx;
+    int result = 0;
+    int alerts = 0;
+    int drops = 0;
+    struct timeval ts;
+
+    HostInitConfig(HOST_QUIET);
+
+    memset (&ts, 0, sizeof(struct timeval));
+    TimeGet(&ts);
+
+    memset(&th_v, 0, sizeof(th_v));
+
+    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type threshold, track by_src, count 5, seconds 300; sid:10;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    TimeGet(&p->ts);
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts = PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    TimeSetIncrementTime(200);
+    TimeGet(&p->ts);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    if (alerts == 1 && drops == 1)
+        result = 1;
+    else {
+        if (alerts != 1)
+            printf("alerts: %d != 1: ", alerts);
+        if (drops != 1)
+            printf("drops: %d != 1: ", drops);
+        goto cleanup;
+    }
+
+cleanup:
+    SigGroupCleanup(de_ctx);
+    SigCleanSignatures(de_ctx);
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+end:
+    UTHFreePackets(&p, 1);
+    HostShutdown();
+    return result;
+}
+
+/**
+ * \test Test drop action being set even if thresholded
+ */
+static int DetectThresholdTestSig11(void) {
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx;
+    int result = 0;
+    int alerts = 0;
+    int drops = 0;
+    struct timeval ts;
+
+    HostInitConfig(HOST_QUIET);
+
+    memset (&ts, 0, sizeof(struct timeval));
+    TimeGet(&ts);
+
+    memset(&th_v, 0, sizeof(th_v));
+
+    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type both, track by_src, count 3, seconds 300; sid:10;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    TimeGet(&p->ts);
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts = PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    TimeSetIncrementTime(200);
+    TimeGet(&p->ts);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    if (alerts == 1 && drops == 4)
+        result = 1;
+    else {
+        if (alerts != 1)
+            printf("alerts: %d != 1: ", alerts);
+        if (drops != 4)
+            printf("drops: %d != 4: ", drops);
+        goto cleanup;
+    }
+
+cleanup:
+    SigGroupCleanup(de_ctx);
+    SigCleanSignatures(de_ctx);
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+end:
+    UTHFreePackets(&p, 1);
+    HostShutdown();
+    return result;
+}
+
+/**
+ * \test Test drop action being set even if thresholded
+ */
+static int DetectThresholdTestSig12(void) {
+    Packet *p = NULL;
+    Signature *s = NULL;
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx;
+    int result = 0;
+    int alerts = 0;
+    int drops = 0;
+    struct timeval ts;
+
+    HostInitConfig(HOST_QUIET);
+
+    memset (&ts, 0, sizeof(struct timeval));
+    TimeGet(&ts);
+
+    memset(&th_v, 0, sizeof(th_v));
+
+    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL) {
+        goto end;
+    }
+
+    de_ctx->flags |= DE_QUIET;
+
+    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type both, track by_src, count 5, seconds 300; sid:10;)");
+    if (s == NULL) {
+        goto end;
+    }
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    TimeGet(&p->ts);
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts = PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    TimeSetIncrementTime(200);
+    TimeGet(&p->ts);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+    alerts += PacketAlertCheck(p, 10);
+    drops += ((p->action & ACTION_DROP)?1:0);
+    p->action = 0;
+
+    if (alerts == 1 && drops == 2)
+        result = 1;
+    else {
+        if (alerts != 1)
+            printf("alerts: %d != 1: ", alerts);
+        if (drops != 2)
+            printf("drops: %d != 2: ", drops);
+        goto cleanup;
+    }
+
+cleanup:
+    SigGroupCleanup(de_ctx);
+    SigCleanSignatures(de_ctx);
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+end:
+    UTHFreePackets(&p, 1);
+    HostShutdown();
+    return result;
+}
+
 #endif /* UNITTESTS */
 
 void ThresholdRegisterTests(void) {
@@ -929,6 +1490,12 @@ void ThresholdRegisterTests(void) {
     UtRegisterTest("DetectThresholdTestSig4", DetectThresholdTestSig4, 1);
     UtRegisterTest("DetectThresholdTestSig5", DetectThresholdTestSig5, 1);
     UtRegisterTest("DetectThresholdTestSig6Ticks", DetectThresholdTestSig6Ticks, 1);
+    UtRegisterTest("DetectThresholdTestSig7", DetectThresholdTestSig7, 1);
+    UtRegisterTest("DetectThresholdTestSig8", DetectThresholdTestSig8, 1);
+    UtRegisterTest("DetectThresholdTestSig9", DetectThresholdTestSig9, 1);
+    UtRegisterTest("DetectThresholdTestSig10", DetectThresholdTestSig10, 1);
+    UtRegisterTest("DetectThresholdTestSig11", DetectThresholdTestSig11, 1);
+    UtRegisterTest("DetectThresholdTestSig12", DetectThresholdTestSig12, 1);
 #endif /* UNITTESTS */
 }
 
index 692f62fa11a8de269724c13764d964ebe7f977a5..d14824eee73f9a02c51a29084b32fa0f53960f3c 100644 (file)
@@ -1858,6 +1858,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
 
         if (!(s->flags & SIG_FLAG_NOALERT)) {
             PacketAlertAppend(det_ctx, s, p, alert_flags);
+        } else {
+            /* apply actions even if not alerting */
+            p->action |= s->action;
         }
 next:
         DetectReplaceFree(det_ctx->replist);
index 254275f88771741baed35d9581e86e21f23d5ab1..d7183ba0f81b4cf218e3873dfce8a0ed7f5180e7 100644 (file)
@@ -2169,6 +2169,213 @@ end:
     return result;
 }
 
+/**
+ * \test Check if the suppress rules work
+ *
+ *  \retval 1 on succces
+ *  \retval 0 on failure
+ */
+static int SCThresholdConfTest15(void)
+{
+    Signature *sig = NULL;
+    int result = 0;
+    FILE *fd = NULL;
+
+    HostInitConfig(HOST_QUIET);
+
+    Packet *p = UTHBuildPacketReal((uint8_t*)"lalala", 6, IPPROTO_TCP, "192.168.0.10",
+                                    "192.168.0.100", 1234, 24);
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx = NULL;
+
+    memset(&th_v, 0, sizeof(th_v));
+
+    struct timeval ts;
+
+    memset (&ts, 0, sizeof(struct timeval));
+    TimeGet(&ts);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL || p == NULL)
+        return result;
+
+    de_ctx->flags |= DE_QUIET;
+
+    sig = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any any (msg:\"suppress test\"; content:\"lalala\"; gid:1; sid:10000;)");
+    if (sig == NULL) {
+        goto end;
+    }
+
+    fd = SCThresholdConfGenerateValidDummyFD11();
+    SCThresholdConfInitContext(de_ctx,fd);
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+    /* 10000 shouldn't match */
+    if (PacketAlertCheck(p, 10000) != 0) {
+        printf("sid 10000 should not have alerted: ");
+        goto end;
+    }
+    /* however, it should have set the drop flag */
+    if (!(p->action & ACTION_DROP)) {
+        printf("sid 10000 should have set DROP flag even if suppressed: ");
+        goto end;
+    }
+
+    result = 1;
+end:
+    UTHFreePacket(p);
+    SigGroupCleanup(de_ctx);
+    SigCleanSignatures(de_ctx);
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+
+    HostShutdown();
+    return result;
+}
+
+/**
+ * \test Check if the suppress rules work
+ *
+ *  \retval 1 on succces
+ *  \retval 0 on failure
+ */
+static int SCThresholdConfTest16(void)
+{
+    Signature *sig = NULL;
+    int result = 0;
+    FILE *fd = NULL;
+
+    HostInitConfig(HOST_QUIET);
+
+    Packet *p = UTHBuildPacketReal((uint8_t*)"lalala", 6, IPPROTO_TCP, "192.168.1.1",
+                                    "192.168.0.100", 1234, 24);
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx = NULL;
+
+    memset(&th_v, 0, sizeof(th_v));
+
+    struct timeval ts;
+
+    memset (&ts, 0, sizeof(struct timeval));
+    TimeGet(&ts);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL || p == NULL)
+        return result;
+
+    de_ctx->flags |= DE_QUIET;
+
+    sig = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any any (msg:\"suppress test\"; gid:1; sid:1000;)");
+    if (sig == NULL) {
+        goto end;
+    }
+
+    fd = SCThresholdConfGenerateValidDummyFD11();
+    SCThresholdConfInitContext(de_ctx,fd);
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+    /* 10000 shouldn't match */
+    if (PacketAlertCheck(p, 1000) != 0) {
+        printf("sid 1000 should not have alerted: ");
+        goto end;
+    }
+    /* however, it should have set the drop flag */
+    if (!(p->action & ACTION_DROP)) {
+        printf("sid 1000 should have set DROP flag even if suppressed: ");
+        goto end;
+    }
+
+    result = 1;
+end:
+    UTHFreePacket(p);
+    SigGroupCleanup(de_ctx);
+    SigCleanSignatures(de_ctx);
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+
+    HostShutdown();
+    return result;
+}
+
+/**
+ * \test Check if the suppress rules work - ip only rule
+ *
+ *  \retval 1 on succces
+ *  \retval 0 on failure
+ */
+static int SCThresholdConfTest17(void)
+{
+    Signature *sig = NULL;
+    int result = 0;
+    FILE *fd = NULL;
+
+    HostInitConfig(HOST_QUIET);
+
+    Packet *p = UTHBuildPacketReal((uint8_t*)"lalala", 6, IPPROTO_TCP, "192.168.0.10",
+                                    "192.168.0.100", 1234, 24);
+    ThreadVars th_v;
+    DetectEngineThreadCtx *det_ctx = NULL;
+
+    memset(&th_v, 0, sizeof(th_v));
+
+    struct timeval ts;
+
+    memset (&ts, 0, sizeof(struct timeval));
+    TimeGet(&ts);
+
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    if (de_ctx == NULL || p == NULL)
+        return result;
+
+    de_ctx->flags |= DE_QUIET;
+
+    sig = de_ctx->sig_list = SigInit(de_ctx,"drop tcp 192.168.0.10 any -> 192.168.0.100 any (msg:\"suppress test\"; gid:1; sid:10000;)");
+    if (sig == NULL) {
+        goto end;
+    }
+
+    fd = SCThresholdConfGenerateValidDummyFD11();
+    SCThresholdConfInitContext(de_ctx,fd);
+
+    SigGroupBuild(de_ctx);
+    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
+
+    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
+
+    /* 10000 shouldn't match */
+    if (PacketAlertCheck(p, 10000) != 0) {
+        printf("sid 10000 should not have alerted: ");
+        goto end;
+    }
+    /* however, it should have set the drop flag */
+    if (!(p->action & ACTION_DROP)) {
+        printf("sid 10000 should have set DROP flag even if suppressed: ");
+        goto end;
+    }
+
+    result = 1;
+end:
+    UTHFreePacket(p);
+    SigGroupCleanup(de_ctx);
+    SigCleanSignatures(de_ctx);
+
+    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
+    DetectEngineCtxFree(de_ctx);
+
+    HostShutdown();
+    return result;
+}
+
 #endif /* UNITTESTS */
 
 /**
@@ -2191,6 +2398,9 @@ void SCThresholdConfRegisterTests(void)
     UtRegisterTest("SCThresholdConfTest12 - event_filter", SCThresholdConfTest12, 1);
     UtRegisterTest("SCThresholdConfTest13", SCThresholdConfTest13, 1);
     UtRegisterTest("SCThresholdConfTest14 - suppress", SCThresholdConfTest14, 1);
+    UtRegisterTest("SCThresholdConfTest15 - suppress drop", SCThresholdConfTest15, 1);
+    UtRegisterTest("SCThresholdConfTest16 - suppress drop", SCThresholdConfTest16, 1);
+    UtRegisterTest("SCThresholdConfTest17 - suppress drop", SCThresholdConfTest17, 1);
 #endif /* UNITTESTS */
 }