diff --git a/src/detect-engine-threshold.c b/src/detect-engine-threshold.c index 7b0ed1f570..1973dc6be9 100644 --- a/src/detect-engine-threshold.c +++ b/src/detect-engine-threshold.c @@ -532,6 +532,26 @@ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx } break; } + case TYPE_SUPPRESS: + { + DetectAddress *res = NULL; + switch (td->track) { + case TRACK_DST: + res = DetectAddressLookupInHead(&td->addr, &p->dst); + break; + case TRACK_SRC: + res = DetectAddressLookupInHead(&td->addr, &p->src); + break; + case TRACK_RULE: + default: + SCLogError(SC_ERR_INVALID_VALUE, + "track mode %d is not supported", td->track); + break; + } + if (res == NULL) + ret = 1; + break; + } } /* handle timing out entries */ diff --git a/src/detect-threshold.h b/src/detect-threshold.h index 1daa4539a1..a02c0fea0b 100644 --- a/src/detect-threshold.h +++ b/src/detect-threshold.h @@ -33,6 +33,7 @@ #define TYPE_THRESHOLD 3 #define TYPE_DETECTION 4 #define TYPE_RATE 5 +#define TYPE_SUPPRESS 6 #define TRACK_DST 1 #define TRACK_SRC 2 @@ -60,6 +61,9 @@ typedef struct DetectThresholdData_ { uint8_t track; /**< Track type: by_src, by_dst */ uint8_t new_action; /**< new_action alert|drop|pass|log|sdrop|reject */ uint32_t timeout; /**< timeout */ + uint32_t flags; /**< flags used to set option */ + /* TODO take care of free of allocated */ + DetectAddressHead addr; /**< address group used by suppress keyword */ } DetectThresholdData; typedef struct DetectThresholdEntry_ { diff --git a/src/detect.h b/src/detect.h index d5748bf310..b5f40a8c74 100644 --- a/src/detect.h +++ b/src/detect.h @@ -39,7 +39,6 @@ #include "util-error.h" #include "util-radix-tree.h" -#include "detect-threshold.h" #include "detect-mark.h" #define COUNTER_DETECT_ALERTS 1 @@ -161,6 +160,9 @@ typedef struct DetectAddressHead_ { DetectAddress *ipv6_head; } DetectAddressHead; + +#include "detect-threshold.h" + typedef struct DetectMatchAddressIPv4_ { uint32_t ip; /**< address in host order, start of range */ uint32_t ip2; /**< address in host order, end of range */ diff --git a/src/util-threshold-config.c b/src/util-threshold-config.c index 3ff8824412..c6971c0b8d 100644 --- a/src/util-threshold-config.c +++ b/src/util-threshold-config.c @@ -33,6 +33,7 @@ #include "suricata-common.h" #include "detect.h" #include "detect-engine.h" +#include "detect-engine-address.h" #include "detect-threshold.h" #include "detect-parse.h" @@ -46,6 +47,13 @@ #include "util-debug.h" #include "util-fmemopen.h" +typedef enum _rule_type_t { + THRESHOLD_TYPE_EVENT_FILTER, + THRESHOLD_TYPE_THRESHOLD, + THRESHOLD_TYPE_RATE, + THRESHOLD_TYPE_SUPPRESS, +} rule_type_t; + /* File descriptor for unittests */ #define DETECT_THRESHOLD_REGEX "^\\s*(event_filter|threshold)\\s*gen_id\\s*(\\d+)\\s*,\\s*sig_id\\s*(\\d+)\\s*,\\s*type\\s*(limit|both|threshold)\\s*,\\s*track\\s*(by_dst|by_src)\\s*,\\s*count\\s*(\\d+)\\s*,\\s*seconds\\s*(\\d+)\\s*$" @@ -53,6 +61,15 @@ /* TODO: "apply_to" */ #define DETECT_RATE_REGEX "^\\s*(rate_filter)\\s*gen_id\\s*(\\d+)\\s*,\\s*sig_id\\s*(\\d+)\\s*,\\s*track\\s*(by_dst|by_src|by_rule)\\s*,\\s*count\\s*(\\d+)\\s*,\\s*seconds\\s*(\\d+)\\s*,\\s*new_action\\s*(alert|drop|pass|log|sdrop|reject)\\s*,\\s*timeout\\s*(\\d+)\\s*$" +/* + * suppress has two form: + * suppress gen_id 0, sig_id 0, track by_dst, ip 10.88.0.14 + * suppress gen_id 1, sig_id 2000328 +*/ + +#define DETECT_SUPPRESS_REGEX_BASE "^\\s*suppress\\s*gen_id\\s*(\\d+)\\s*,\\s*sig_id\\s*(\\d+)\\s*(.*)\\s*$" +#define DETECT_SUPPRESS_REGEX_EXTEND "^,\\s*track\\s*(by_dst|by_src)\\s*,\\s*ip\\s*([\\d.:/]+)*\\s*$" + /* Default path for the threshold.config file */ #define THRESHOLD_CONF_DEF_CONF_FILEPATH "threshold.config" @@ -62,6 +79,12 @@ static pcre_extra *regex_study = NULL; static pcre *rate_regex = NULL; static pcre_extra *rate_regex_study = NULL; +static pcre *suppress_regex_base = NULL; +static pcre_extra *suppress_regex_base_study = NULL; + +static pcre *suppress_regex_extend = NULL; +static pcre_extra *suppress_regex_extend_study = NULL; + /** * \brief Returns the path for the Threshold Config file. We check if we * can retrieve the path from the yaml conf file. If it is not present, @@ -137,6 +160,30 @@ int SCThresholdConfInitContext(DetectEngineCtx *de_ctx, FILE *utfd) goto error; } + suppress_regex_base = pcre_compile(DETECT_SUPPRESS_REGEX_BASE, opts, &eb, &eo, NULL); + if (regex == NULL) { + SCLogError(SC_ERR_PCRE_COMPILE, "Compile of \"%s\" failed at offset %" PRId32 ": %s",DETECT_SUPPRESS_REGEX_BASE, eo, eb); + goto error; + } + + suppress_regex_base_study = pcre_study(suppress_regex_base, 0, &eb); + if (eb != NULL) { + SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb); + goto error; + } + + suppress_regex_extend = pcre_compile(DETECT_SUPPRESS_REGEX_EXTEND, opts, &eb, &eo, NULL); + if (regex == NULL) { + SCLogError(SC_ERR_PCRE_COMPILE, "Compile of \"%s\" failed at offset %" PRId32 ": %s",DETECT_SUPPRESS_REGEX_EXTEND, eo, eb); + goto error; + } + + suppress_regex_extend_study = pcre_study(suppress_regex_extend, 0, &eb); + if (eb != NULL) { + SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb); + goto error; + } + SCThresholdConfParseFile(de_ctx, fd); SCThresholdConfDeInitContext(de_ctx, fd); @@ -181,6 +228,8 @@ int SCThresholdConfAddThresholdtype(char *rawstr, DetectEngineCtx *de_ctx) const char *th_seconds = NULL; const char *th_new_action= NULL; const char *th_timeout = NULL; + const char *th_ip = NULL; + const char *suppress_extend = NULL; uint8_t parsed_type = 0; uint8_t parsed_track = 0; @@ -198,20 +247,85 @@ int SCThresholdConfAddThresholdtype(char *rawstr, DetectEngineCtx *de_ctx) int ret = 0; int ov[MAX_SUBSTRINGS]; uint32_t id = 0, gid = 0; + int rule_type; if (de_ctx == NULL) return -1; + /* TODO add offset to rawstr if it start with space */ + /* TODO switch to a base regexp for all keyword */ + if (strncasecmp(rawstr,"event_filter",strlen("event_filter")) == 0) { + rule_type = THRESHOLD_TYPE_EVENT_FILTER; + } + if (strncasecmp(rawstr,"threshold",strlen("threshold")) == 0) { + rule_type = THRESHOLD_TYPE_THRESHOLD; + } + if (strncasecmp(rawstr,"rate",strlen("rate")) == 0) { + rule_type = THRESHOLD_TYPE_RATE; + } + if (strncasecmp(rawstr,"suppress",strlen("suppress")) == 0) { + rule_type = THRESHOLD_TYPE_SUPPRESS; + } - ret = pcre_exec(regex, regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); + switch(rule_type) { + case THRESHOLD_TYPE_EVENT_FILTER: + case THRESHOLD_TYPE_THRESHOLD: + ret = pcre_exec(regex, regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); + /* Its a threshold/event_filter rule, Parse it */ + if (ret < 8) { + SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr); + goto error; + } + /* retrieve the classtype name */ + ret = pcre_get_substring((char *)rawstr, ov, 30, 2, &th_gid); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } - if (ret < 8) { - /* Its not threshold/event_filter, so try rate_filter regexp */ - ret = pcre_exec(rate_regex, rate_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); - if (ret < 9) { - SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr); - goto error; - } else { - /* Start rate_filter parsing */ + ret = pcre_get_substring((char *)rawstr, ov, 30, 3, &th_sid); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + + ret = pcre_get_substring((char *)rawstr, ov, 30, 4, &th_type); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + + ret = pcre_get_substring((char *)rawstr, ov, 30, 5, &th_track); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + + ret = pcre_get_substring((char *)rawstr, ov, 30, 6, &th_count); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + + ret = pcre_get_substring((char *)rawstr, ov, 30, 7, &th_seconds); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + + if (strcasecmp(th_type,"limit") == 0) + parsed_type = TYPE_LIMIT; + else if (strcasecmp(th_type,"both") == 0) + parsed_type = TYPE_BOTH; + else if (strcasecmp(th_type,"threshold") == 0) + parsed_type = TYPE_THRESHOLD; + break; + case THRESHOLD_TYPE_RATE: + ret = pcre_exec(rate_regex, rate_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); + if (ret < 9) { + SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr); + goto error; + } + /* Start rate_filter parsing */ /* retrieve the classtype name */ ret = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, &th_gid); if (ret < 0) { @@ -280,70 +394,103 @@ int SCThresholdConfAddThresholdtype(char *rawstr, DetectEngineCtx *de_ctx) } parsed_type = TYPE_RATE; + break; + case THRESHOLD_TYPE_SUPPRESS: + ret = pcre_exec(suppress_regex_base, suppress_regex_base_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); + /* Its a suppress, Parse it */ + if (ret < 3) { + SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr); + goto error; + } + /* retrieve the classtype name */ + ret = pcre_get_substring((char *)rawstr, ov, 30, 1, &th_gid); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } - } /* End rate_filter parsing */ - } else { - /* Its a threshold/event_filter rule, Parse it */ - - /* retrieve the classtype name */ - ret = pcre_get_substring((char *)rawstr, ov, 30, 2, &th_gid); - if (ret < 0) { - SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); - goto error; - } - - ret = pcre_get_substring((char *)rawstr, ov, 30, 3, &th_sid); - if (ret < 0) { - SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); - goto error; - } + ret = pcre_get_substring((char *)rawstr, ov, 30, 2, &th_sid); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } - ret = pcre_get_substring((char *)rawstr, ov, 30, 4, &th_type); - if (ret < 0) { - SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); - goto error; - } + ret = pcre_get_substring((char *)rawstr, ov, 30, 3, &suppress_extend); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + if (strlen(suppress_extend) > 0) { + ret = pcre_exec(suppress_regex_extend, suppress_regex_extend_study, + suppress_extend, strlen(suppress_extend), + 0, 0, ov, MAX_SUBSTRINGS); + /* Its a suppress, Parse it */ + if (ret < 2) { + SCLogError(SC_ERR_PCRE_MATCH, + "pcre_exec parse error, ret %" PRId32 ", string %s", + ret, suppress_extend); + goto error; + } + /* retrieve the track mode */ + ret = pcre_get_substring((char *)suppress_extend, ov, 30, 1, &th_track); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + /* retrieve the IP */ + ret = pcre_get_substring((char *)suppress_extend, ov, 30, 2, &th_ip); + if (ret < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + } else { + parsed_track = TRACK_RULE; + } - ret = pcre_get_substring((char *)rawstr, ov, 30, 5, &th_track); - if (ret < 0) { - SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + parsed_type = TYPE_SUPPRESS; + break; + default: + SCLogError(SC_ERR_PCRE_MATCH, "unable to find rule type for string %s", rawstr); goto error; - } + } - ret = pcre_get_substring((char *)rawstr, ov, 30, 6, &th_count); - if (ret < 0) { - SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); - goto error; - } + switch (rule_type) { + /* This part is common to threshold/event_filter/rate_filter */ + case THRESHOLD_TYPE_EVENT_FILTER: + case THRESHOLD_TYPE_THRESHOLD: + case THRESHOLD_TYPE_RATE: + if (strcasecmp(th_track,"by_dst") == 0) + parsed_track = TRACK_DST; + else if (strcasecmp(th_track,"by_src") == 0) + parsed_track = TRACK_SRC; + else if (strcasecmp(th_track,"by_rule") == 0) + parsed_track = TRACK_RULE; + else { + SCLogError(SC_ERR_INVALID_VALUE, "Invalid track parameter %s in %s", th_track, rawstr); + goto error; + } - ret = pcre_get_substring((char *)rawstr, ov, 30, 7, &th_seconds); - if (ret < 0) { - SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); - goto error; - } + if (ByteExtractStringUint32(&parsed_count, 10, strlen(th_count), th_count) <= 0) { + goto error; + } - if (strcasecmp(th_type,"limit") == 0) - parsed_type = TYPE_LIMIT; - else if (strcasecmp(th_type,"both") == 0) - parsed_type = TYPE_BOTH; - else if (strcasecmp(th_type,"threshold") == 0) - parsed_type = TYPE_THRESHOLD; - } /* End of threshold/event_filter parsing */ - - /* This part is common to threshold/event_filter/rate_filter */ - if (strcasecmp(th_track,"by_dst") == 0) - parsed_track = TRACK_DST; - else if (strcasecmp(th_track,"by_src") == 0) - parsed_track = TRACK_SRC; - else if (strcasecmp(th_track,"by_rule") == 0) - parsed_track = TRACK_RULE; - - if (ByteExtractStringUint32(&parsed_count, 10, strlen(th_count), th_count) <= 0) { - goto error; - } + if (ByteExtractStringUint32(&parsed_seconds, 10, strlen(th_seconds), th_seconds) <= 0) { + goto error; + } - if (ByteExtractStringUint32(&parsed_seconds, 10, strlen(th_seconds), th_seconds) <= 0) { - goto error; + break; + case THRESHOLD_TYPE_SUPPRESS: + /* need to get IP if extension is provided */ + if (strlen(suppress_extend)) { + if (strcasecmp(th_track,"by_dst") == 0) + parsed_track = TRACK_DST; + else if (strcasecmp(th_track,"by_src") == 0) + parsed_track = TRACK_SRC; + else { + SCLogError(SC_ERR_INVALID_VALUE, "Invalid track parameter %s in %s", th_track, suppress_extend); + goto error; + } + } } if (ByteExtractStringUint32(&id, 10, strlen(th_sid), th_sid) <= 0) { @@ -354,10 +501,8 @@ int SCThresholdConfAddThresholdtype(char *rawstr, DetectEngineCtx *de_ctx) goto error; } - /* Install it */ if (id == 0 && gid == 0) { - for (s = de_ctx->sig_list; s != NULL;) { ns = s->next; @@ -385,6 +530,13 @@ int SCThresholdConfAddThresholdtype(char *rawstr, DetectEngineCtx *de_ctx) de->new_action = parsed_new_action; de->timeout = parsed_timeout; + if ((parsed_type == TYPE_SUPPRESS) && (parsed_track != TRACK_RULE)) { + if (DetectAddressParse(&de->addr, (char *)th_ip) < 0) { + SCLogError(SC_ERR_INVALID_IP_NETBLOCK, "Can't add %s to address group", th_ip); + goto error; + } + } + sm = SigMatchAlloc(); if (sm == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "Error allocating SigMatch"); @@ -412,7 +564,6 @@ int SCThresholdConfAddThresholdtype(char *rawstr, DetectEngineCtx *de_ctx) } } else if (id == 0 && gid > 0) { - for (s = de_ctx->sig_list; s != NULL;) { ns = s->next; @@ -442,6 +593,13 @@ int SCThresholdConfAddThresholdtype(char *rawstr, DetectEngineCtx *de_ctx) de->new_action = parsed_new_action; de->timeout = parsed_timeout; + if ((parsed_type == TYPE_SUPPRESS) && (parsed_track != TRACK_RULE)) { + if (DetectAddressParse(&de->addr, (char *)th_ip) < 0) { + SCLogError(SC_ERR_INVALID_IP_NETBLOCK, "Can't add %s to address group", th_ip); + goto error; + } + } + sm = SigMatchAlloc(); if (sm == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "Error allocating SigMatch"); @@ -472,6 +630,10 @@ int SCThresholdConfAddThresholdtype(char *rawstr, DetectEngineCtx *de_ctx) sig = SigFindSignatureBySidGid(de_ctx,id,gid); if(sig != NULL) { + if ((parsed_type == TYPE_SUPPRESS) && (parsed_track == TRACK_RULE)) { + sig->flags |= SIG_FLAG_NOALERT; + goto end; + } m = SigMatchGetLastSM(sig->sm_lists[DETECT_SM_LIST_MATCH], DETECT_THRESHOLD); @@ -496,6 +658,13 @@ int SCThresholdConfAddThresholdtype(char *rawstr, DetectEngineCtx *de_ctx) de->new_action = parsed_new_action; de->timeout = parsed_timeout; + if ((parsed_type == TYPE_SUPPRESS) && (parsed_track != TRACK_RULE)) { + if (DetectAddressParse(&de->addr, (char *)th_ip) < 0) { + SCLogError(SC_ERR_INVALID_IP_NETBLOCK, "Can't add %s to address group", th_ip); + goto error; + } + } + sm = SigMatchAlloc(); if (sm == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "Error allocating SigMatch"); @@ -531,6 +700,8 @@ end: if(th_count != NULL) SCFree((char *)th_count); if(th_seconds != NULL) SCFree((char *)th_seconds); if(th_type != NULL) SCFree((char *)th_type); + if(th_ip != NULL) SCFree((char *)th_ip); + if(suppress_extend != NULL) SCFree((char *)suppress_extend); return 0; @@ -542,6 +713,8 @@ error: if(th_count != NULL) SCFree((char *)th_count); if(th_seconds != NULL) SCFree((char *)th_seconds); if(th_type != NULL) SCFree((char *)th_type); + if(th_ip != NULL) SCFree((char *)th_ip); + if(suppress_extend != NULL) SCFree((char *)suppress_extend); return -1; } @@ -682,6 +855,8 @@ void SCThresholdConfParseFile(DetectEngineCtx *de_ctx, FILE *fd) } } + SCLogInfo("Threshold config parsed: %d rule(s) found", rule_num); + /* Free the last line */ SCFree(line); @@ -891,6 +1066,25 @@ FILE *SCThresholdConfGenerateValidDummyFD10() return fd; } +/** + * \brief Creates a dummy threshold file, with all valid options, for testing purposes. + * + * \retval fd Pointer to file descriptor. + */ +FILE *SCThresholdConfGenerateValidDummyFD11() +{ + FILE *fd = NULL; + const char *buffer = + "suppress gen_id 1, sig_id 10000\n" + "suppress gen_id 1, sig_id 1000, track by_src, ip 192.168.1.1\n"; + + fd = SCFmemopen((void *)buffer, strlen(buffer), "r"); + if (fd == NULL) + SCLogDebug("Error with SCFmemopen() called by Threshold Config test code"); + + return fd; +} + /** * \test Check if the threshold file is loaded and well parsed * @@ -1689,6 +1883,112 @@ end: return result; } +/** + * \test Check if the threshold file is loaded and well parsed + * + * \retval 1 on succces + * \retval 0 on failure + */ +int SCThresholdConfTest13(void) +{ + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + DetectThresholdData *de = NULL; + Signature *sig = NULL; + SigMatch *m = NULL; + int result = 0; + FILE *fd = NULL; + + if (de_ctx == NULL) + return result; + + de_ctx->flags |= DE_QUIET; + + sig = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Threshold limit\"; gid:1; sid:1000;)"); + if (sig == NULL) { + goto end; + } + + fd = SCThresholdConfGenerateValidDummyFD11(); + SCThresholdConfInitContext(de_ctx,fd); + + m = SigMatchGetLastSM(sig->sm_lists[DETECT_SM_LIST_MATCH], DETECT_THRESHOLD); + + if(m != NULL) { + de = (DetectThresholdData *)m->ctx; + if(de != NULL && (de->type == TYPE_SUPPRESS && de->track == TRACK_SRC)) + result = 1; + + } +end: + SigGroupBuild(de_ctx); + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +/** + * \test Check if the suppress rules work + * + * \retval 1 on succces + * \retval 0 on failure + */ +int SCThresholdConfTest14(void) +{ + Signature *sig = NULL; + int result = 0; + FILE *fd = NULL; + + Packet *p = UTHBuildPacketReal((uint8_t*)"lalala", 6, IPPROTO_TCP, "192.168.0.10", + "192.168.0.100", 1234, 24); + Packet *p1 = 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,"alert tcp any any -> any any (msg:\"suppress test\"; gid:1; sid:10000;)"); + sig = sig->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"suppress test 2\"; gid:1; sid:10;)"); + sig = sig->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"suppress test 3\"; 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); + SigMatchSignatures(&th_v, de_ctx, det_ctx, p1); + if ((PacketAlertCheck(p, 10000) == 0) && (PacketAlertCheck(p, 10) == 1) && + (PacketAlertCheck(p, 1000) == 1) && (PacketAlertCheck(p1, 1000) == 0)) + result = 1; + +end: + UTHFreePacket(p); + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); + + return result; +} + #endif /* UNITTESTS */ /** @@ -1709,6 +2009,8 @@ void SCThresholdConfRegisterTests(void) UtRegisterTest("SCThresholdConfTest10 - rate_filter", SCThresholdConfTest10, 1); UtRegisterTest("SCThresholdConfTest11 - event_filter", SCThresholdConfTest11, 1); UtRegisterTest("SCThresholdConfTest12 - event_filter", SCThresholdConfTest12, 1); + UtRegisterTest("SCThresholdConfTest13", SCThresholdConfTest13, 1); + UtRegisterTest("SCThresholdConfTest14 - suppress", SCThresholdConfTest14, 1); #endif /* UNITTESTS */ }