From: Victor Julien Date: Tue, 30 Oct 2012 11:58:58 +0000 (+0100) Subject: Fix drop (and other actions) not being applied to thresholded packets. Bug #613. X-Git-Tag: suricata-1.4beta3~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80d62b59ec1b517090faf0cd52531232300aef6b;p=thirdparty%2Fsuricata.git Fix drop (and other actions) not being applied to thresholded packets. Bug #613. --- diff --git a/src/detect-detection-filter.c b/src/detect-detection-filter.c index 4b74765f15..9573b44b3b 100644 --- a/src/detect-detection-filter.c +++ b/src/detect-detection-filter.c @@ -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 */ } diff --git a/src/detect-engine-alert.c b/src/detect-engine-alert.c index 0b2f78f426..e1839f7498 100644 --- a/src/detect-engine-alert.c +++ b/src/detect-engine-alert.c @@ -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 diff --git a/src/detect-engine-iponly.c b/src/detect-engine-iponly.c index af3c05030f..563f191903 100644 --- a/src/detect-engine-iponly.c +++ b/src/detect-engine-iponly.c @@ -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; } } } diff --git a/src/detect-engine-threshold.c b/src/detect-engine-threshold.c index 3c69609089..d152d2732b 100644 --- a/src/detect-engine-threshold.c +++ b/src/detect-engine-threshold.c @@ -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 */ diff --git a/src/detect-threshold.c b/src/detect-threshold.c index 8074f37020..a1db7b84b4 100644 --- a/src/detect-threshold.c +++ b/src/detect-threshold.c @@ -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 */ } diff --git a/src/detect.c b/src/detect.c index 692f62fa11..d14824eee7 100644 --- a/src/detect.c +++ b/src/detect.c @@ -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); diff --git a/src/util-threshold-config.c b/src/util-threshold-config.c index 254275f887..d7183ba0f8 100644 --- a/src/util-threshold-config.c +++ b/src/util-threshold-config.c @@ -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 */ }