diff --git a/src/Makefile.am b/src/Makefile.am index bb37b63c8a..bc6ab0c314 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -40,6 +40,7 @@ host.c host.h \ reputation.c reputation.h \ detect.c detect.h \ detect-engine-sigorder.c detect-engine-sigorder.h \ +detect-engine-alert.c detect-engine-alert.h \ detect-engine.c detect-engine.h \ detect-rpc.c detect-rpc.h \ detect-isdataat.c detect-isdataat.h \ diff --git a/src/detect-engine-alert.c b/src/detect-engine-alert.c new file mode 100644 index 0000000000..7a6872e266 --- /dev/null +++ b/src/detect-engine-alert.c @@ -0,0 +1,108 @@ +#include "detect-engine-alert.h" +#include "suricata-common.h" +#include "detect.h" +#include "decode.h" + +/** + * \brief Check if a certain sid alerted, this is used in the test functions + * + * \param p Packet on which we want to check if the signature alerted or not + * \param sid Signature id of the signature that thas to be checked for a match + * + * \retval match A value > 0 on a match; 0 on no match + */ +int PacketAlertCheck(Packet *p, uint32_t sid) +{ + uint16_t i = 0; + int match = 0; + + for (i = 0; i < p->alerts.cnt; i++) { + if (p->alerts.alerts[i].sid == sid) + match++; + } + + return match; +} + +/** + * \brief Remove alert from the p->alerts.alerts array at pos + * \param p Pointer to the Packet + * \param pos Position in the array + * \retval 0 if the number of alerts is less than pos + * 1 if all goes well + */ +int PacketAlertRemove(Packet *p, uint16_t pos) +{ + uint16_t i = 0; + int match = 0; + if (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)); + } + + // Update it, since we removed 1 + p->alerts.cnt--; + + return match; +} + +int PacketAlertAppend(DetectEngineThreadCtx *det_ctx, Signature *s, Packet *p) +{ + int i = 0; + + if (p->alerts.cnt == PACKET_ALERT_MAX) + return 0; + + SCLogDebug("sid %"PRIu32"", s->id); + + /* It should be usually the last, so check it before iterating */ + if (p->alerts.cnt == 0 || (p->alerts.cnt > 0 && + p->alerts.alerts[p->alerts.cnt - 1].num < s->num)) { + /* We just add it */ + if (s->gid > 1) + p->alerts.alerts[p->alerts.cnt].gid = s->gid; + else + p->alerts.alerts[p->alerts.cnt].gid = 1; + + p->alerts.alerts[p->alerts.cnt].num= s->num; + p->alerts.alerts[p->alerts.cnt].action = s->action; + p->alerts.alerts[p->alerts.cnt].sid = s->id; + p->alerts.alerts[p->alerts.cnt].rev = s->rev; + p->alerts.alerts[p->alerts.cnt].prio = s->prio; + p->alerts.alerts[p->alerts.cnt].msg = s->msg; + p->alerts.alerts[p->alerts.cnt].class_msg = s->class_msg; + p->alerts.alerts[p->alerts.cnt].references = s->references; + } else { + /* We need to make room for this s->num + (a bit ugly with mamcpy but we are planning changes here)*/ + for (i = p->alerts.cnt - 1; i >= 0 && p->alerts.alerts[i].num > s->num; i--) { + memcpy(&p->alerts.alerts[i + 1], &p->alerts.alerts[i], sizeof(PacketAlert)); + } + + i++; /* The right place to store the alert */ + + if (s->gid > 1) + p->alerts.alerts[i].gid = s->gid; + else + p->alerts.alerts[i].gid = 1; + + p->alerts.alerts[i].num= s->num; + p->alerts.alerts[i].action = s->action; + p->alerts.alerts[i].sid = s->id; + p->alerts.alerts[i].rev = s->rev; + p->alerts.alerts[i].prio = s->prio; + p->alerts.alerts[i].msg = s->msg; + p->alerts.alerts[i].class_msg = s->class_msg; + p->alerts.alerts[i].references = s->references; + } + + /* Update the count */ + p->alerts.cnt++; + + SCPerfCounterIncr(det_ctx->counter_alerts, det_ctx->tv->sc_perf_pca); + + return 0; +} + diff --git a/src/detect-engine-alert.h b/src/detect-engine-alert.h new file mode 100644 index 0000000000..8718e12b88 --- /dev/null +++ b/src/detect-engine-alert.h @@ -0,0 +1,11 @@ +#ifndef __DETECT_ENGINE_ALERT_H__ +#define __DETECT_ENGINE_ALERT_H__ +#include "suricata-common.h" +#include "decode.h" +#include "detect.h" + +int PacketAlertAppend(DetectEngineThreadCtx *, Signature *, Packet *); +int PacketAlertCheck(Packet *, uint32_t); +int PacketAlertRemove(Packet *, uint16_t); + +#endif /* __DETECT_ENGINE_ALERT_H__ */ diff --git a/src/detect-engine-iponly.c b/src/detect-engine-iponly.c index 84a19ffd81..e8f1c38278 100644 --- a/src/detect-engine-iponly.c +++ b/src/detect-engine-iponly.c @@ -977,7 +977,7 @@ void IPOnlyMatchPacket(DetectEngineCtx *de_ctx, p->flow->flags |= FLOW_ACTION_PASS; } p->action |= ACTION_PASS; - PacketAlertHandle(de_ctx, det_ctx, s, p); + PacketAlertAppend(det_ctx, s, p); } } } diff --git a/src/detect-engine-threshold.c b/src/detect-engine-threshold.c index 42984045c2..499167f8ad 100644 --- a/src/detect-engine-threshold.c +++ b/src/detect-engine-threshold.c @@ -60,10 +60,11 @@ * \param p Packet structure * */ -void PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, - Signature *s, Packet *p) +int PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, + Signature *s, Packet *p, uint16_t pos) { SCEnter(); + int ret = 0; /* retrieve the sig match data */ DetectThresholdData *td = SigGetThresholdType(s,p); @@ -72,12 +73,18 @@ void PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, /* if have none just alert, otherwise handle thresholding */ if (td == NULL) { - PacketAlertAppend(det_ctx, s, p); - } else { - PacketAlertThreshold(de_ctx, det_ctx, td, p, s); + //PacketAlertAppend(det_ctx, s, p); + /* Already inserted so get out */ + ret = 1; + } else { + ret = PacketAlertThreshold(de_ctx, det_ctx, td, p, s); + if (ret == 0) { + /* It doesn't match threshold, remove it */ + PacketAlertRemove(p, pos); + } } - SCReturn; + SCReturnInt(ret); } /** @@ -243,23 +250,24 @@ void ThresholdHashAdd(DetectEngineCtx *de_ctx, DetectThresholdEntry *tsh_ptr, Pa * \param s Signature structure * */ -void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, +int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, DetectThresholdData *td, Packet *p, Signature *s) { SCEnter(); + int ret = 0; struct timeval ts; DetectThresholdEntry *lookup_tsh = NULL; DetectThresholdEntry *ste = NULL; if (td == NULL) - SCReturn; + SCReturnInt(ret); /* setup the Entry we use to search our hash with */ ste = SCMalloc(sizeof(DetectThresholdEntry)); if (ste == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "SCMalloc failed: %s", strerror(errno)); - SCReturn; + SCReturnInt(ret); } memset(ste, 0x00, sizeof(ste)); @@ -297,20 +305,20 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ct if (lookup_tsh != NULL) { if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { if (lookup_tsh->current_count < td->count) { - PacketAlertAppend(det_ctx, s, p); + ret = 1; } lookup_tsh->current_count++; } else { lookup_tsh->tv_sec1 = ts.tv_sec; lookup_tsh->current_count = 1; - PacketAlertAppend(det_ctx, s, p); + ret = 1; } } else { ste->tv_sec1 = ts.tv_sec; ste->current_count = 1; - PacketAlertAppend(det_ctx, s, p); + ret = 1; ThresholdHashAdd(de_ctx, ste, p); ste = NULL; @@ -327,7 +335,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ct lookup_tsh->current_count++; if (lookup_tsh->current_count >= td->count) { - PacketAlertAppend(det_ctx, s, p); + ret = 1; lookup_tsh->current_count = 0; } } else { @@ -339,7 +347,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ct ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(det_ctx, s, p); + ret = 1; ste->current_count = 0; } else { ThresholdHashAdd(de_ctx,ste,p); @@ -357,7 +365,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ct if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { lookup_tsh->current_count++; if (lookup_tsh->current_count == td->count) { - PacketAlertAppend(det_ctx, s, p); + ret = 1; } } else { lookup_tsh->tv_sec1 = ts.tv_sec; @@ -368,7 +376,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ct ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(det_ctx, s, p); + ret = 1; ste->current_count = 0; } else { ThresholdHashAdd(de_ctx,ste,p); @@ -387,7 +395,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ct if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { lookup_tsh->current_count++; if (lookup_tsh->current_count >= td->count) { - PacketAlertAppend(det_ctx, s, p); + ret = 1; } } else { lookup_tsh->tv_sec1 = ts.tv_sec; @@ -398,7 +406,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ct ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(det_ctx, s, p); + ret = 1; } ThresholdHashAdd(de_ctx, ste, p); ste = NULL; @@ -412,7 +420,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ct SCFree(ste); ThresholdTimeoutRemove(de_ctx); - SCReturn; + SCReturnInt(ret); } void ThresholdFreeFunc(void *data) diff --git a/src/detect-engine-threshold.h b/src/detect-engine-threshold.h index 61c77461c2..53de369cf0 100644 --- a/src/detect-engine-threshold.h +++ b/src/detect-engine-threshold.h @@ -29,10 +29,10 @@ #define THRESHOLD_HASH_SIZE 0xffff -void PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *, - Signature *sig, Packet *p); +int PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *, + Signature *sig, Packet *p, uint16_t); DetectThresholdData *SigGetThresholdType(Signature *, Packet *); -void PacketAlertThreshold(DetectEngineCtx *, DetectEngineThreadCtx *, +int PacketAlertThreshold(DetectEngineCtx *, DetectEngineThreadCtx *, DetectThresholdData *, Packet *, Signature *); void ThresholdFreeFunc(void *data); char ThresholdCompareFunc(void *data1, uint16_t len1, void *data2,uint16_t len2); diff --git a/src/detect.c b/src/detect.c index 57e44e988b..25bc78e02f 100644 --- a/src/detect.c +++ b/src/detect.c @@ -33,6 +33,7 @@ #include "detect-parse.h" #include "detect-engine.h" +#include "detect-engine-alert.h" #include "detect-engine-siggroup.h" #include "detect-engine-address.h" #include "detect-engine-proto.h" @@ -139,6 +140,7 @@ #include "util-cuda.h" #include "util-privs.h" + SigMatch *SigMatchAlloc(void); void DetectExitPrintStats(ThreadVars *tv, void *data); @@ -404,85 +406,6 @@ int SigLoadSignatures (DetectEngineCtx *de_ctx, char *sig_file) SCReturnInt(0); } -/** - * \brief Check if a certain sid alerted, this is used in the test functions - * - * \param p Packet on which we want to check if the signature alerted or not - * \param sid Signature id of the signature that thas to be checked for a match - * - * \retval match A value > 0 on a match; 0 on no match - */ -int PacketAlertCheck(Packet *p, uint32_t sid) -{ - uint16_t i = 0; - int match = 0; - - for (i = 0; i < p->alerts.cnt; i++) { - if (p->alerts.alerts[i].sid == sid) - match++; - } - - return match; -} - -int PacketAlertAppend(DetectEngineThreadCtx *det_ctx, Signature *s, Packet *p) -{ - int i = 0; - - if (p->alerts.cnt == PACKET_ALERT_MAX) - return 0; - - SCLogDebug("sid %"PRIu32"", s->id); - - /* It should be usually the last, so check it before iterating */ - if (p->alerts.cnt == 0 || (p->alerts.cnt > 0 && - p->alerts.alerts[p->alerts.cnt - 1].num < s->num)) { - /* We just add it */ - if (s->gid > 1) - p->alerts.alerts[p->alerts.cnt].gid = s->gid; - else - p->alerts.alerts[p->alerts.cnt].gid = 1; - - p->alerts.alerts[p->alerts.cnt].num= s->num; - p->alerts.alerts[p->alerts.cnt].action = s->action; - p->alerts.alerts[p->alerts.cnt].sid = s->id; - p->alerts.alerts[p->alerts.cnt].rev = s->rev; - p->alerts.alerts[p->alerts.cnt].prio = s->prio; - p->alerts.alerts[p->alerts.cnt].msg = s->msg; - p->alerts.alerts[p->alerts.cnt].class_msg = s->class_msg; - p->alerts.alerts[p->alerts.cnt].references = s->references; - } else { - /* We need to make room for this s->num - (a bit ugly with mamcpy but we are planning changes here)*/ - for (i = p->alerts.cnt - 1; i >= 0 && p->alerts.alerts[i].num > s->num; i--) { - memcpy(&p->alerts.alerts[i + 1], &p->alerts.alerts[i], sizeof(PacketAlert)); - } - - i++; /* The right place to store the alert */ - - if (s->gid > 1) - p->alerts.alerts[i].gid = s->gid; - else - p->alerts.alerts[i].gid = 1; - - p->alerts.alerts[i].num= s->num; - p->alerts.alerts[i].action = s->action; - p->alerts.alerts[i].sid = s->id; - p->alerts.alerts[i].rev = s->rev; - p->alerts.alerts[i].prio = s->prio; - p->alerts.alerts[i].msg = s->msg; - p->alerts.alerts[i].class_msg = s->class_msg; - p->alerts.alerts[i].references = s->references; - } - - /* Update the count */ - p->alerts.cnt++; - - SCPerfCounterIncr(det_ctx->counter_alerts, det_ctx->tv->sc_perf_pca); - - return 0; -} - SigGroupHead *SigMatchSignaturesGetSgh(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p) { SCEnter(); @@ -552,7 +475,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh void *alstate = NULL; uint8_t flags = 0; uint32_t cnt = 0; - uint16_t i = 0; + int i = 0; SCEnter(); @@ -759,7 +682,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (!(s->flags & SIG_FLAG_NOALERT)) { /* set verdict on packet */ p->action |= s->action; - PacketAlertHandle(de_ctx, det_ctx, s, p); + PacketAlertAppend(det_ctx, s, p); } } else { /* reset offset */ @@ -798,7 +721,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh /* set verdict on packet */ p->action |= s->action; - PacketAlertHandle(de_ctx, det_ctx, s, p); + PacketAlertAppend(det_ctx, s, p); } } rmatch = fmatch = 1; @@ -845,7 +768,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh /* set verdict on packet */ p->action |= s->action; - PacketAlertHandle(de_ctx, det_ctx, s, p); + PacketAlertAppend(det_ctx, s, p); } } } else { @@ -863,9 +786,14 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh * matched (if any) */ end: SCLogDebug("(p->action & ation pass)) = %"PRIu8, (p->action & ACTION_PASS)); - if (p->action & ACTION_PASS) { - for (; i < p->alerts.cnt; i++) { - SCLogDebug("Sig->num: %"PRIu16, p->alerts.alerts[i].num); + for (i = 0; i < p->alerts.cnt; i++) { + 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 (p->alerts.alerts[i].action & ACTION_PASS) { /* Ok, reset the alert cnt to end in the previous of pass * so we ignore the rest with less prio */ @@ -873,6 +801,9 @@ end: break; } } + /* 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) */ } /* cleanup pkt specific part of the patternmatcher */ diff --git a/src/detect.h b/src/detect.h index 8d915d0b4a..388a81b90b 100644 --- a/src/detect.h +++ b/src/detect.h @@ -690,17 +690,11 @@ int SigGroupBuild(DetectEngineCtx *); int SigGroupCleanup(); void SigAddressPrepareBidirectionals (DetectEngineCtx *); -int PacketAlertAppend(DetectEngineThreadCtx *, Signature *s, Packet *); - int SigLoadSignatures (DetectEngineCtx *, char *); void SigTableSetup(void); -int PacketAlertCheck(Packet *p, uint32_t sid); int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p); -int PacketAlertCheck(Packet *p, uint32_t sid); -int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, - DetectEngineThreadCtx *det_ctx, Packet *p); int SignatureIsIPOnly(DetectEngineCtx *de_ctx, Signature *s); #endif /* __DETECT_H__ */ diff --git a/src/suricata-common.h b/src/suricata-common.h index 29b8309acf..6e8cbebe61 100644 --- a/src/suricata-common.h +++ b/src/suricata-common.h @@ -121,13 +121,6 @@ #include #define BUG_ON(x) assert(!(x)) -#include -#include "threads.h" -#include "util-debug.h" -#include "util-error.h" -#include "util-mem.h" - - /** type for the internal signature id. Since it's used in the matching engine * extensively keeping this as small as possible reduces the overall memory * footprint of the engine. Set to uint32_t if the engine needs to support @@ -135,6 +128,14 @@ #define SigIntId uint16_t //#define SigIntId uint32_t + +#include +#include "threads.h" +#include "util-debug.h" +#include "util-error.h" +#include "util-mem.h" +#include "detect-engine-alert.h" + size_t strlcat(char *, const char *src, size_t siz); size_t strlcpy(char *dst, const char *src, size_t siz); diff --git a/src/util-mpm.h b/src/util-mpm.h index f3a866b7c4..54f5bf7207 100644 --- a/src/util-mpm.h +++ b/src/util-mpm.h @@ -23,6 +23,7 @@ #ifndef __UTIL_MPM_H__ #define __UTIL_MPM_H__ +#include "suricata-common.h" #define MPM_ENDMATCH_SINGLE 0x01 /**< A single match is sufficient. No depth, offset, etc settings. */