]>
Commit | Line | Data |
---|---|---|
7f6af10f | 1 | /* Copyright (C) 2007-2020 Open Information Security Foundation |
ce019275 WM |
2 | * |
3 | * You can copy, redistribute or modify this Program under the terms of | |
4 | * the GNU General Public License version 2 as published by the Free | |
5 | * Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 | * GNU General Public License for more details. | |
11 | * | |
12 | * You should have received a copy of the GNU General Public License | |
13 | * version 2 along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
15 | * 02110-1301, USA. | |
16 | */ | |
046c813f | 17 | |
ef2ae76c | 18 | /** |
046c813f | 19 | * \file |
ce019275 | 20 | * |
ef2ae76c GIG |
21 | * \author Gerardo Iglesias <iglesiasg@gmail.com> |
22 | * | |
ce019275 | 23 | * Implements the detection_filter keyword |
ef2ae76c GIG |
24 | */ |
25 | ||
26 | #include "suricata-common.h" | |
27 | #include "suricata.h" | |
28 | #include "debug.h" | |
29 | #include "decode.h" | |
30 | #include "detect.h" | |
31 | ||
c0a2cbd4 VJ |
32 | #include "host.h" |
33 | ||
ef2ae76c GIG |
34 | #include "detect-detection-filter.h" |
35 | #include "detect-threshold.h" | |
36 | #include "detect-parse.h" | |
37 | ||
38 | #include "util-byte.h" | |
39 | #include "util-unittest.h" | |
d1ce1c50 | 40 | #include "util-unittest-helper.h" |
ef2ae76c GIG |
41 | #include "util-debug.h" |
42 | ||
4dd01694 VJ |
43 | #define TRACK_DST 1 |
44 | #define TRACK_SRC 2 | |
45 | ||
ef2ae76c GIG |
46 | /** |
47 | *\brief Regex for parsing our detection_filter options | |
48 | */ | |
49 | #define PARSE_REGEX "^\\s*(track|count|seconds)\\s+(by_src|by_dst|\\d+)\\s*,\\s*(track|count|seconds)\\s+(by_src|by_dst|\\d+)\\s*,\\s*(track|count|seconds)\\s+(by_src|by_dst|\\d+)\\s*$" | |
50 | ||
4b0085b0 | 51 | static DetectParseRegex parse_regex; |
ef2ae76c | 52 | |
14896365 | 53 | static int DetectDetectionFilterMatch(DetectEngineThreadCtx *, |
bfd4bc82 | 54 | Packet *, const Signature *, const SigMatchCtx *); |
ab1200fb | 55 | static int DetectDetectionFilterSetup(DetectEngineCtx *, Signature *, const char *); |
6ab323d3 | 56 | #ifdef UNITTESTS |
39613778 | 57 | static void DetectDetectionFilterRegisterTests(void); |
6ab323d3 | 58 | #endif |
d3a65fe1 | 59 | static void DetectDetectionFilterFree(DetectEngineCtx *, void *); |
ef2ae76c GIG |
60 | |
61 | /** | |
62 | * \brief Registration function for detection_filter: keyword | |
63 | */ | |
8f1d7503 KS |
64 | void DetectDetectionFilterRegister (void) |
65 | { | |
ef2ae76c | 66 | sigmatch_table[DETECT_DETECTION_FILTER].name = "detection_filter"; |
68425453 | 67 | sigmatch_table[DETECT_DETECTION_FILTER].desc = "alert on every match after a threshold has been reached"; |
26bcc975 | 68 | sigmatch_table[DETECT_DETECTION_FILTER].url = "/rules/thresholding.html#detection-filter"; |
ef2ae76c GIG |
69 | sigmatch_table[DETECT_DETECTION_FILTER].Match = DetectDetectionFilterMatch; |
70 | sigmatch_table[DETECT_DETECTION_FILTER].Setup = DetectDetectionFilterSetup; | |
71 | sigmatch_table[DETECT_DETECTION_FILTER].Free = DetectDetectionFilterFree; | |
6ab323d3 | 72 | #ifdef UNITTESTS |
ef2ae76c | 73 | sigmatch_table[DETECT_DETECTION_FILTER].RegisterTests = DetectDetectionFilterRegisterTests; |
6ab323d3 | 74 | #endif |
c1a19bcd VJ |
75 | /* this is compatible to ip-only signatures */ |
76 | sigmatch_table[DETECT_DETECTION_FILTER].flags |= SIGMATCH_IPONLY_COMPAT; | |
ef2ae76c | 77 | |
4b0085b0 | 78 | DetectSetupParseRegexes(PARSE_REGEX, &parse_regex); |
ef2ae76c GIG |
79 | } |
80 | ||
14896365 | 81 | static int DetectDetectionFilterMatch (DetectEngineThreadCtx *det_ctx, |
bfd4bc82 | 82 | Packet *p, const Signature *s, const SigMatchCtx *ctx) |
8f1d7503 | 83 | { |
ef2ae76c GIG |
84 | return 1; |
85 | } | |
86 | ||
87 | /** | |
88 | * \internal | |
89 | * \brief This function is used to parse detection_filter options passed via detection_filter: keyword | |
90 | * | |
91 | * \param rawstr Pointer to the user provided detection_filter options | |
92 | * | |
93 | * \retval df pointer to DetectThresholdData on success | |
94 | * \retval NULL on failure | |
95 | */ | |
ab1200fb | 96 | static DetectThresholdData *DetectDetectionFilterParse (const char *rawstr) |
8f1d7503 | 97 | { |
ef2ae76c | 98 | DetectThresholdData *df = NULL; |
ef2ae76c | 99 | int ret = 0, res = 0; |
3de99a21 | 100 | size_t pcre2_len; |
ef2ae76c GIG |
101 | const char *str_ptr = NULL; |
102 | char *args[6] = { NULL, NULL, NULL, NULL, NULL, NULL}; | |
103 | char *copy_str = NULL, *df_opt = NULL; | |
104 | int seconds_found = 0, count_found = 0, track_found = 0; | |
105 | int seconds_pos = 0, count_pos = 0; | |
106 | uint16_t pos = 0; | |
107 | int i = 0; | |
bc2b53f1 | 108 | char *saveptr = NULL; |
ef2ae76c GIG |
109 | |
110 | copy_str = SCStrdup(rawstr); | |
e176be6f | 111 | if (unlikely(copy_str == NULL)) { |
e19f6eba VJ |
112 | goto error; |
113 | } | |
ef2ae76c | 114 | |
bc2b53f1 VJ |
115 | for (pos = 0, df_opt = strtok_r(copy_str,",", &saveptr); |
116 | pos < strlen(copy_str) && df_opt != NULL; | |
117 | pos++, df_opt = strtok_r(NULL,",", &saveptr)) | |
118 | { | |
ef2ae76c GIG |
119 | if(strstr(df_opt,"count")) |
120 | count_found++; | |
121 | if(strstr(df_opt,"second")) | |
122 | seconds_found++; | |
123 | if(strstr(df_opt,"track")) | |
124 | track_found++; | |
125 | } | |
38b6103f VJ |
126 | SCFree(copy_str); |
127 | copy_str = NULL; | |
ef2ae76c | 128 | |
38b6103f | 129 | if (count_found != 1 || seconds_found != 1 || track_found != 1) |
ef2ae76c GIG |
130 | goto error; |
131 | ||
3de99a21 | 132 | ret = DetectParsePcreExec(&parse_regex, rawstr, 0, 0); |
ef2ae76c GIG |
133 | if (ret < 5) { |
134 | SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr); | |
135 | goto error; | |
136 | } | |
137 | ||
4dd01694 | 138 | df = SCMalloc(sizeof(DetectThresholdData)); |
e176be6f | 139 | if (unlikely(df == NULL)) |
ef2ae76c | 140 | goto error; |
9f4fae5b | 141 | |
4dd01694 | 142 | memset(df,0,sizeof(DetectThresholdData)); |
ef2ae76c GIG |
143 | |
144 | df->type = TYPE_DETECTION; | |
145 | ||
146 | for (i = 0; i < (ret - 1); i++) { | |
3de99a21 PA |
147 | res = pcre2_substring_get_bynumber( |
148 | parse_regex.match, i + 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len); | |
ef2ae76c | 149 | if (res < 0) { |
3de99a21 | 150 | SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_get_bynumber failed"); |
ef2ae76c GIG |
151 | goto error; |
152 | } | |
153 | ||
154 | args[i] = (char *)str_ptr; | |
155 | ||
156 | if (strncasecmp(args[i],"by_dst",strlen("by_dst")) == 0) | |
157 | df->track = TRACK_DST; | |
158 | if (strncasecmp(args[i],"by_src",strlen("by_src")) == 0) | |
159 | df->track = TRACK_SRC; | |
160 | if (strncasecmp(args[i],"count",strlen("count")) == 0) | |
161 | count_pos = i+1; | |
162 | if (strncasecmp(args[i],"seconds",strlen("seconds")) == 0) | |
163 | seconds_pos = i+1; | |
164 | } | |
165 | ||
046c813f | 166 | if (args[count_pos] == NULL || args[seconds_pos] == NULL) { |
ef2ae76c GIG |
167 | goto error; |
168 | } | |
169 | ||
0e4f2612 | 170 | if (StringParseUint32(&df->count, 10, strlen(args[count_pos]), |
046c813f VJ |
171 | args[count_pos]) <= 0) { |
172 | goto error; | |
173 | } | |
174 | ||
0e4f2612 | 175 | if (StringParseUint32(&df->seconds, 10, strlen(args[seconds_pos]), |
046c813f | 176 | args[seconds_pos]) <= 0) { |
ef2ae76c GIG |
177 | goto error; |
178 | } | |
179 | ||
180 | if (df->count == 0 || df->seconds == 0) { | |
181 | SCLogError(SC_ERR_INVALID_VALUE, "found an invalid value"); | |
182 | goto error; | |
183 | } | |
184 | ||
e19f6eba VJ |
185 | for (i = 0; i < 6; i++){ |
186 | if (args[i] != NULL) | |
3de99a21 | 187 | pcre2_substring_free((PCRE2_UCHAR *)args[i]); |
ef2ae76c GIG |
188 | } |
189 | return df; | |
190 | ||
191 | error: | |
e19f6eba VJ |
192 | for (i = 0; i < 6; i++){ |
193 | if (args[i] != NULL) | |
3de99a21 | 194 | pcre2_substring_free((PCRE2_UCHAR *)args[i]); |
ef2ae76c | 195 | } |
e19f6eba VJ |
196 | if (df != NULL) |
197 | SCFree(df); | |
ef2ae76c GIG |
198 | return NULL; |
199 | } | |
200 | ||
201 | /** | |
202 | * \internal | |
203 | * \brief this function is used to add the parsed detection_filter into the current signature | |
204 | * | |
205 | * \param de_ctx pointer to the Detection Engine Context | |
206 | * \param s pointer to the Current Signature | |
207 | * \param m pointer to the Current SigMatch | |
208 | * \param rawstr pointer to the user provided detection_filter options | |
209 | * | |
210 | * \retval 0 on Success | |
211 | * \retval -1 on Failure | |
212 | */ | |
ab1200fb | 213 | static int DetectDetectionFilterSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) |
8f1d7503 | 214 | { |
ef2ae76c GIG |
215 | SCEnter(); |
216 | DetectThresholdData *df = NULL; | |
217 | SigMatch *sm = NULL; | |
218 | SigMatch *tmpm = NULL; | |
219 | ||
220 | /* checks if there's a previous instance of threshold */ | |
779d40ce | 221 | tmpm = DetectGetLastSMFromLists(s, DETECT_THRESHOLD, -1); |
ef2ae76c GIG |
222 | if (tmpm != NULL) { |
223 | SCLogError(SC_ERR_INVALID_SIGNATURE, "\"detection_filter\" and \"threshold\" are not allowed in the same rule"); | |
224 | SCReturnInt(-1); | |
225 | } | |
226 | /* checks there's no previous instance of detection_filter */ | |
779d40ce | 227 | tmpm = DetectGetLastSMFromLists(s, DETECT_DETECTION_FILTER, -1); |
ef2ae76c GIG |
228 | if (tmpm != NULL) { |
229 | SCLogError(SC_ERR_INVALID_SIGNATURE, "At most one \"detection_filter\" is allowed per rule"); | |
230 | SCReturnInt(-1); | |
231 | } | |
232 | ||
233 | df = DetectDetectionFilterParse(rawstr); | |
234 | if (df == NULL) | |
235 | goto error; | |
236 | ||
237 | sm = SigMatchAlloc(); | |
238 | if (sm == NULL) | |
239 | goto error; | |
240 | ||
241 | sm->type = DETECT_DETECTION_FILTER; | |
923a77e9 | 242 | sm->ctx = (SigMatchCtx *)df; |
ef2ae76c | 243 | |
eb07c345 | 244 | SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_THRESHOLD); |
ef2ae76c GIG |
245 | |
246 | return 0; | |
247 | ||
248 | error: | |
39613778 VJ |
249 | if (df) |
250 | SCFree(df); | |
251 | if (sm) | |
252 | SCFree(sm); | |
ef2ae76c GIG |
253 | return -1; |
254 | } | |
255 | ||
256 | /** | |
257 | * \internal | |
258 | * \brief this function will free memory associated with DetectThresholdData | |
259 | * | |
260 | * \param df_ptr pointer to DetectDetectionFilterData | |
261 | */ | |
d3a65fe1 | 262 | static void DetectDetectionFilterFree(DetectEngineCtx *de_ctx, void *df_ptr) |
8f1d7503 | 263 | { |
ef2ae76c | 264 | DetectThresholdData *df = (DetectThresholdData *)df_ptr; |
39613778 VJ |
265 | if (df) |
266 | SCFree(df); | |
ef2ae76c GIG |
267 | } |
268 | ||
269 | /* | |
270 | * ONLY TESTS BELOW THIS COMMENT | |
271 | */ | |
272 | #ifdef UNITTESTS | |
ef2ae76c GIG |
273 | #include "detect-engine.h" |
274 | #include "detect-engine-mpm.h" | |
275 | #include "detect-engine-threshold.h" | |
276 | #include "util-time.h" | |
277 | #include "util-hashlist.h" | |
278 | ||
279 | /** | |
280 | * \test DetectDetectionFilterTestParse01 is a test for a valid detection_filter options | |
281 | * | |
282 | * \retval 1 on succces | |
283 | * \retval 0 on failure | |
284 | */ | |
39613778 | 285 | static int DetectDetectionFilterTestParse01 (void) |
8f1d7503 | 286 | { |
ef2ae76c GIG |
287 | DetectThresholdData *df = NULL; |
288 | df = DetectDetectionFilterParse("track by_dst,count 10,seconds 60"); | |
289 | if (df && (df->track == TRACK_DST) && (df->count == 10) && (df->seconds == 60)) { | |
d3a65fe1 | 290 | DetectDetectionFilterFree(NULL, df); |
ef2ae76c GIG |
291 | return 1; |
292 | } | |
293 | ||
294 | return 0; | |
295 | } | |
296 | ||
297 | /** | |
298 | * \test DetectDetectionFilterTestParse02 is a test for a invalid detection_filter options | |
299 | * | |
300 | * \retval 1 on succces | |
301 | * \retval 0 on failure | |
302 | */ | |
39613778 | 303 | static int DetectDetectionFilterTestParse02 (void) |
8f1d7503 | 304 | { |
ef2ae76c GIG |
305 | DetectThresholdData *df = NULL; |
306 | df = DetectDetectionFilterParse("track both,count 10,seconds 60"); | |
307 | if (df && (df->track == TRACK_DST || df->track == TRACK_SRC) && (df->count == 10) && (df->seconds == 60)) { | |
d3a65fe1 | 308 | DetectDetectionFilterFree(NULL, df); |
52983bf3 | 309 | return 0; |
ef2ae76c GIG |
310 | } |
311 | ||
52983bf3 | 312 | return 1; |
ef2ae76c GIG |
313 | } |
314 | ||
315 | /** | |
316 | * \test DetectDetectionfilterTestParse03 is a test for a valid detection_filter options in any order | |
317 | * | |
318 | * \retval 1 on succces | |
319 | * \retval 0 on failure | |
320 | */ | |
39613778 | 321 | static int DetectDetectionFilterTestParse03 (void) |
8f1d7503 | 322 | { |
ef2ae76c GIG |
323 | DetectThresholdData *df = NULL; |
324 | df = DetectDetectionFilterParse("track by_dst, seconds 60, count 10"); | |
325 | if (df && (df->track == TRACK_DST) && (df->count == 10) && (df->seconds == 60)) { | |
d3a65fe1 | 326 | DetectDetectionFilterFree(NULL, df); |
ef2ae76c GIG |
327 | return 1; |
328 | } | |
329 | ||
330 | return 0; | |
331 | } | |
332 | ||
333 | ||
334 | /** | |
335 | * \test DetectDetectionFilterTestParse04 is a test for an invalid detection_filter options in any order | |
336 | * | |
337 | * \retval 1 on succces | |
338 | * \retval 0 on failure | |
339 | */ | |
39613778 | 340 | static int DetectDetectionFilterTestParse04 (void) |
8f1d7503 | 341 | { |
ef2ae76c GIG |
342 | DetectThresholdData *df = NULL; |
343 | df = DetectDetectionFilterParse("count 10, track by_dst, seconds 60, count 10"); | |
344 | if (df && (df->track == TRACK_DST) && (df->count == 10) && (df->seconds == 60)) { | |
d3a65fe1 | 345 | DetectDetectionFilterFree(NULL, df); |
52983bf3 | 346 | return 0; |
ef2ae76c GIG |
347 | } |
348 | ||
52983bf3 | 349 | return 1; |
ef2ae76c GIG |
350 | } |
351 | ||
352 | /** | |
353 | * \test DetectDetectionFilterTestParse05 is a test for a valid detection_filter options in any order | |
354 | * | |
355 | * \retval 1 on succces | |
356 | * \retval 0 on failure | |
357 | */ | |
39613778 | 358 | static int DetectDetectionFilterTestParse05 (void) |
8f1d7503 | 359 | { |
ef2ae76c GIG |
360 | DetectThresholdData *df = NULL; |
361 | df = DetectDetectionFilterParse("count 10, track by_dst, seconds 60"); | |
362 | if (df && (df->track == TRACK_DST) && (df->count == 10) && (df->seconds == 60)) { | |
d3a65fe1 | 363 | DetectDetectionFilterFree(NULL, df); |
ef2ae76c GIG |
364 | return 1; |
365 | } | |
366 | ||
367 | return 0; | |
368 | } | |
369 | ||
370 | /** | |
371 | * \test DetectDetectionFilterTestParse06 is a test for an invalid value in detection_filter | |
372 | * | |
373 | * \retval 1 on succces | |
374 | * \retval 0 on failure | |
375 | */ | |
39613778 | 376 | static int DetectDetectionFilterTestParse06 (void) |
8f1d7503 | 377 | { |
ef2ae76c GIG |
378 | DetectThresholdData *df = NULL; |
379 | df = DetectDetectionFilterParse("count 10, track by_dst, seconds 0"); | |
380 | if (df && (df->track == TRACK_DST) && (df->count == 10) && (df->seconds == 0)) { | |
d3a65fe1 | 381 | DetectDetectionFilterFree(NULL, df); |
52983bf3 | 382 | return 0; |
ef2ae76c GIG |
383 | } |
384 | ||
52983bf3 | 385 | return 1; |
ef2ae76c GIG |
386 | } |
387 | ||
388 | /** | |
389 | * \test DetectDetectionFilterTestSig1 is a test for checking the working of detection_filter keyword | |
390 | * by setting up the signature and later testing its working by matching | |
391 | * the received packet against the sig. | |
392 | * | |
393 | * \retval 1 on succces | |
394 | * \retval 0 on failure | |
395 | */ | |
8f1d7503 KS |
396 | static int DetectDetectionFilterTestSig1(void) |
397 | { | |
1071a532 | 398 | Packet *p = NULL; |
ef2ae76c GIG |
399 | Signature *s = NULL; |
400 | ThreadVars th_v; | |
401 | DetectEngineThreadCtx *det_ctx; | |
402 | int result = 0; | |
403 | int alerts = 0; | |
ef2ae76c | 404 | |
c0a2cbd4 VJ |
405 | HostInitConfig(HOST_QUIET); |
406 | ||
ef2ae76c | 407 | memset(&th_v, 0, sizeof(th_v)); |
1071a532 VJ |
408 | |
409 | p = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); | |
ef2ae76c GIG |
410 | |
411 | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); | |
412 | if (de_ctx == NULL) { | |
413 | goto end; | |
414 | } | |
415 | ||
416 | de_ctx->flags |= DE_QUIET; | |
417 | ||
c1a19bcd | 418 | s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"detection_filter Test\"; detection_filter: track by_dst, count 4, seconds 60; sid:1;)"); |
ef2ae76c GIG |
419 | if (s == NULL) { |
420 | goto end; | |
421 | } | |
422 | ||
423 | SigGroupBuild(de_ctx); | |
424 | DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); | |
425 | ||
1071a532 VJ |
426 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); |
427 | alerts = PacketAlertCheck(p, 1); | |
428 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
429 | alerts += PacketAlertCheck(p, 1); | |
430 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
431 | alerts += PacketAlertCheck(p, 1); | |
432 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
433 | alerts += PacketAlertCheck(p, 1); | |
434 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
435 | alerts += PacketAlertCheck(p, 1); | |
436 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
437 | alerts += PacketAlertCheck(p, 1); | |
438 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
439 | alerts += PacketAlertCheck(p, 1); | |
440 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
441 | alerts += PacketAlertCheck(p, 1); | |
ef2ae76c | 442 | |
8742e51f | 443 | if(alerts == 4) |
ef2ae76c GIG |
444 | result = 1; |
445 | ||
446 | SigGroupCleanup(de_ctx); | |
447 | SigCleanSignatures(de_ctx); | |
448 | ||
449 | DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); | |
450 | DetectEngineCtxFree(de_ctx); | |
451 | ||
452 | end: | |
1071a532 | 453 | UTHFreePackets(&p, 1); |
c0a2cbd4 | 454 | HostShutdown(); |
ef2ae76c GIG |
455 | return result; |
456 | } | |
457 | ||
458 | /** | |
459 | * \test DetectDetectionFilterTestSig2 is a test for checking the working of detection_filter keyword | |
460 | * by setting up the signature and later testing its working by matching | |
461 | * the received packet against the sig. | |
462 | * | |
463 | * \retval 1 on succces | |
464 | * \retval 0 on failure | |
465 | */ | |
466 | ||
8f1d7503 KS |
467 | static int DetectDetectionFilterTestSig2(void) |
468 | { | |
1071a532 | 469 | Packet *p = NULL; |
ef2ae76c GIG |
470 | Signature *s = NULL; |
471 | ThreadVars th_v; | |
472 | DetectEngineThreadCtx *det_ctx; | |
473 | int result = 0; | |
474 | int alerts = 0; | |
ef2ae76c GIG |
475 | struct timeval ts; |
476 | ||
c0a2cbd4 VJ |
477 | HostInitConfig(HOST_QUIET); |
478 | ||
ef2ae76c GIG |
479 | memset (&ts, 0, sizeof(struct timeval)); |
480 | TimeGet(&ts); | |
481 | ||
482 | memset(&th_v, 0, sizeof(th_v)); | |
1071a532 VJ |
483 | |
484 | p = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); | |
ef2ae76c GIG |
485 | |
486 | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); | |
487 | if (de_ctx == NULL) { | |
488 | goto end; | |
489 | } | |
490 | ||
491 | de_ctx->flags |= DE_QUIET; | |
492 | ||
c1a19bcd | 493 | s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"detection_filter Test 2\"; detection_filter: track by_dst, count 4, seconds 60; sid:10;)"); |
ef2ae76c GIG |
494 | if (s == NULL) { |
495 | goto end; | |
496 | } | |
497 | ||
498 | SigGroupBuild(de_ctx); | |
499 | DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); | |
500 | ||
1071a532 | 501 | TimeGet(&p->ts); |
85141328 | 502 | |
1071a532 VJ |
503 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); |
504 | alerts = PacketAlertCheck(p, 10); | |
505 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
506 | alerts += PacketAlertCheck(p, 10); | |
507 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
508 | alerts += PacketAlertCheck(p, 10); | |
ef2ae76c GIG |
509 | |
510 | TimeSetIncrementTime(200); | |
1071a532 | 511 | TimeGet(&p->ts); |
ef2ae76c | 512 | |
1071a532 VJ |
513 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); |
514 | alerts += PacketAlertCheck(p, 10); | |
515 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
516 | alerts += PacketAlertCheck(p, 10); | |
517 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
518 | alerts += PacketAlertCheck(p, 10); | |
519 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
520 | alerts += PacketAlertCheck(p, 10); | |
ef2ae76c | 521 | |
8742e51f | 522 | if (alerts == 0) |
ef2ae76c GIG |
523 | result = 1; |
524 | ||
525 | SigGroupCleanup(de_ctx); | |
526 | SigCleanSignatures(de_ctx); | |
527 | ||
528 | DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); | |
529 | DetectEngineCtxFree(de_ctx); | |
530 | end: | |
1071a532 | 531 | UTHFreePackets(&p, 1); |
c0a2cbd4 | 532 | HostShutdown(); |
ef2ae76c GIG |
533 | return result; |
534 | } | |
535 | ||
80d62b59 VJ |
536 | /** |
537 | * \test drops | |
538 | */ | |
8f1d7503 KS |
539 | static int DetectDetectionFilterTestSig3(void) |
540 | { | |
80d62b59 VJ |
541 | Packet *p = NULL; |
542 | Signature *s = NULL; | |
543 | ThreadVars th_v; | |
544 | DetectEngineThreadCtx *det_ctx; | |
545 | int result = 0; | |
546 | int alerts = 0; | |
547 | int drops = 0; | |
548 | struct timeval ts; | |
549 | ||
550 | HostInitConfig(HOST_QUIET); | |
551 | ||
552 | memset (&ts, 0, sizeof(struct timeval)); | |
553 | TimeGet(&ts); | |
554 | ||
555 | memset(&th_v, 0, sizeof(th_v)); | |
556 | ||
557 | p = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80); | |
ef2ae76c | 558 | |
80d62b59 VJ |
559 | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
560 | if (de_ctx == NULL) { | |
561 | goto end; | |
562 | } | |
563 | ||
564 | de_ctx->flags |= DE_QUIET; | |
565 | ||
566 | 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;)"); | |
567 | if (s == NULL) { | |
568 | goto end; | |
569 | } | |
570 | ||
571 | SigGroupBuild(de_ctx); | |
572 | DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); | |
573 | ||
574 | TimeGet(&p->ts); | |
575 | ||
576 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
577 | alerts = PacketAlertCheck(p, 10); | |
4c7eb644 | 578 | drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0); |
80d62b59 VJ |
579 | p->action = 0; |
580 | ||
581 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
582 | alerts += PacketAlertCheck(p, 10); | |
4c7eb644 | 583 | drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0); |
80d62b59 VJ |
584 | p->action = 0; |
585 | ||
586 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
587 | alerts += PacketAlertCheck(p, 10); | |
4c7eb644 | 588 | drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0); |
80d62b59 VJ |
589 | p->action = 0; |
590 | ||
591 | TimeSetIncrementTime(200); | |
592 | TimeGet(&p->ts); | |
593 | ||
594 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
595 | alerts += PacketAlertCheck(p, 10); | |
4c7eb644 | 596 | drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0); |
80d62b59 VJ |
597 | p->action = 0; |
598 | ||
599 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
600 | alerts += PacketAlertCheck(p, 10); | |
4c7eb644 | 601 | drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0); |
80d62b59 VJ |
602 | p->action = 0; |
603 | ||
604 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
605 | alerts += PacketAlertCheck(p, 10); | |
4c7eb644 | 606 | drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0); |
80d62b59 VJ |
607 | p->action = 0; |
608 | ||
609 | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); | |
610 | alerts += PacketAlertCheck(p, 10); | |
4c7eb644 | 611 | drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0); |
80d62b59 VJ |
612 | p->action = 0; |
613 | ||
614 | if (alerts == 3 && drops == 3) | |
615 | result = 1; | |
616 | else { | |
617 | if (alerts != 3) | |
618 | printf("alerts: %d != 3: ", alerts); | |
619 | if (drops != 3) | |
620 | printf("drops: %d != 3: ", drops); | |
621 | } | |
622 | ||
623 | SigGroupCleanup(de_ctx); | |
624 | SigCleanSignatures(de_ctx); | |
625 | ||
626 | DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); | |
627 | DetectEngineCtxFree(de_ctx); | |
628 | end: | |
629 | UTHFreePackets(&p, 1); | |
630 | HostShutdown(); | |
631 | return result; | |
632 | } | |
ef2ae76c | 633 | |
39613778 | 634 | static void DetectDetectionFilterRegisterTests(void) |
8f1d7503 | 635 | { |
796dd522 JI |
636 | UtRegisterTest("DetectDetectionFilterTestParse01", |
637 | DetectDetectionFilterTestParse01); | |
638 | UtRegisterTest("DetectDetectionFilterTestParse02", | |
639 | DetectDetectionFilterTestParse02); | |
640 | UtRegisterTest("DetectDetectionFilterTestParse03", | |
641 | DetectDetectionFilterTestParse03); | |
642 | UtRegisterTest("DetectDetectionFilterTestParse04", | |
643 | DetectDetectionFilterTestParse04); | |
644 | UtRegisterTest("DetectDetectionFilterTestParse05", | |
645 | DetectDetectionFilterTestParse05); | |
646 | UtRegisterTest("DetectDetectionFilterTestParse06", | |
647 | DetectDetectionFilterTestParse06); | |
648 | UtRegisterTest("DetectDetectionFilterTestSig1", | |
649 | DetectDetectionFilterTestSig1); | |
650 | UtRegisterTest("DetectDetectionFilterTestSig2", | |
651 | DetectDetectionFilterTestSig2); | |
652 | UtRegisterTest("DetectDetectionFilterTestSig3", | |
653 | DetectDetectionFilterTestSig3); | |
ef2ae76c | 654 | } |
6ab323d3 | 655 | #endif /* UNITTESTS */ |