1 /* Copyright (C) 2007-2020 Open Information Security Foundation
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 */
17
18 /**
19 * \file
20 *
21 * \author Breno Silva <breno.silva@gmail.com>
22 *
23 * Implements the flags keyword
24 */
25
26 #include "suricata-common.h"
27 #include "suricata.h"
28 #include "decode.h"
29
30 #include "detect.h"
31 #include "detect-parse.h"
32 #include "detect-engine-prefilter.h"
33 #include "detect-engine-prefilter-common.h"
34
35 #include "flow-var.h"
36 #include "decode-events.h"
37
38 #include "detect-tcp-flags.h"
39 #include "util-unittest.h"
40
41 #include "util-debug.h"
42
43 /**
44 * Regex (by Brian Rectanus)
45 * flags: [!+*](SAPRFU120)[,SAPRFU12]
46 */
47 #define PARSE_REGEX "^\\s*(?:([\\+\\*!]))?\\s*([SAPRFU120CE\\+\\*!]+)(?:\\s*,\\s*([SAPRFU12CE]+))?\\s*$"
48
49 /**
50 * Flags args[0] *(3) +(2) !(1)
51 *
52 */
53
54 #define MODIFIER_NOT 1
55 #define MODIFIER_PLUS 2
56 #define MODIFIER_ANY 3
57
58 static DetectParseRegex parse_regex;
59
60 static int DetectFlagsMatch (DetectEngineThreadCtx *, Packet *,
61 const Signature *, const SigMatchCtx *);
62 static int DetectFlagsSetup (DetectEngineCtx *, Signature *, const char *);
63 static void DetectFlagsFree(DetectEngineCtx *, void *);
64
65 static bool PrefilterTcpFlagsIsPrefilterable(const Signature *s);
66 static int PrefilterSetupTcpFlags(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
67 #ifdef UNITTESTS
68 static void FlagsRegisterTests(void);
69 #endif
70
71 /**
72 * \brief Registration function for flags: keyword
73 */
74
DetectFlagsRegister(void)75 void DetectFlagsRegister (void)
76 {
77 sigmatch_table[DETECT_FLAGS].name = "tcp.flags";
78 sigmatch_table[DETECT_FLAGS].alias = "flags";
79 sigmatch_table[DETECT_FLAGS].desc = "detect which flags are set in the TCP header";
80 sigmatch_table[DETECT_FLAGS].url = "/rules/header-keywords.html#tcp-flags";
81 sigmatch_table[DETECT_FLAGS].Match = DetectFlagsMatch;
82 sigmatch_table[DETECT_FLAGS].Setup = DetectFlagsSetup;
83 sigmatch_table[DETECT_FLAGS].Free = DetectFlagsFree;
84 #ifdef UNITTESTS
85 sigmatch_table[DETECT_FLAGS].RegisterTests = FlagsRegisterTests;
86 #endif
87 sigmatch_table[DETECT_FLAGS].SupportsPrefilter = PrefilterTcpFlagsIsPrefilterable;
88 sigmatch_table[DETECT_FLAGS].SetupPrefilter = PrefilterSetupTcpFlags;
89
90 DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
91 }
92
FlagsMatch(const uint8_t pflags,const uint8_t modifier,const uint8_t dflags,const uint8_t iflags)93 static inline int FlagsMatch(const uint8_t pflags, const uint8_t modifier,
94 const uint8_t dflags, const uint8_t iflags)
95 {
96 if (!dflags && pflags) {
97 if(modifier == MODIFIER_NOT) {
98 SCReturnInt(1);
99 }
100
101 SCReturnInt(0);
102 }
103
104 const uint8_t flags = pflags & iflags;
105
106 switch (modifier) {
107 case MODIFIER_ANY:
108 if ((flags & dflags) > 0) {
109 SCReturnInt(1);
110 }
111 SCReturnInt(0);
112
113 case MODIFIER_PLUS:
114 if (((flags & dflags) == dflags)) {
115 SCReturnInt(1);
116 }
117 SCReturnInt(0);
118
119 case MODIFIER_NOT:
120 if ((flags & dflags) != dflags) {
121 SCReturnInt(1);
122 }
123 SCReturnInt(0);
124
125 default:
126 SCLogDebug("flags %"PRIu8" and de->flags %"PRIu8"", flags, dflags);
127 if (flags == dflags) {
128 SCReturnInt(1);
129 }
130 }
131
132 SCReturnInt(0);
133 }
134
135 /**
136 * \internal
137 * \brief This function is used to match flags on a packet with those passed via flags:
138 *
139 * \param t pointer to thread vars
140 * \param det_ctx pointer to the pattern matcher thread
141 * \param p pointer to the current packet
142 * \param s pointer to the Signature
143 * \param m pointer to the sigmatch
144 *
145 * \retval 0 no match
146 * \retval 1 match
147 */
DetectFlagsMatch(DetectEngineThreadCtx * det_ctx,Packet * p,const Signature * s,const SigMatchCtx * ctx)148 static int DetectFlagsMatch (DetectEngineThreadCtx *det_ctx, Packet *p,
149 const Signature *s, const SigMatchCtx *ctx)
150 {
151 SCEnter();
152
153 if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) {
154 SCReturnInt(0);
155 }
156
157 const DetectFlagsData *de = (const DetectFlagsData *)ctx;
158 const uint8_t flags = p->tcph->th_flags;
159
160 return FlagsMatch(flags, de->modifier, de->flags, de->ignored_flags);
161 }
162
163 /**
164 * \internal
165 * \brief This function is used to parse flags options passed via flags: keyword
166 *
167 * \param rawstr Pointer to the user provided flags options
168 *
169 * \retval de pointer to DetectFlagsData on success
170 * \retval NULL on failure
171 */
DetectFlagsParse(const char * rawstr)172 static DetectFlagsData *DetectFlagsParse (const char *rawstr)
173 {
174 SCEnter();
175
176 int ret = 0, found = 0, ignore = 0, res = 0;
177 int ov[MAX_SUBSTRINGS];
178 char *ptr;
179
180 char arg1[16] = "";
181 char arg2[16] = "";
182 char arg3[16] = "";
183
184 ret = DetectParsePcreExec(&parse_regex, rawstr, 0, 0, ov, MAX_SUBSTRINGS);
185 SCLogDebug("input '%s', pcre said %d", rawstr, ret);
186 if (ret < 3) {
187 SCLogError(SC_ERR_PCRE_MATCH, "pcre match failed");
188 SCReturnPtr(NULL, "DetectFlagsData");
189 }
190
191 res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
192 if (res < 0) {
193 SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
194 SCReturnPtr(NULL, "DetectFlagsData");
195 }
196 if (ret >= 2) {
197 res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, arg2, sizeof(arg2));
198 if (res < 0) {
199 SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
200 SCReturnPtr(NULL, "DetectFlagsData");
201 }
202 }
203 if (ret >= 3) {
204 res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 3, arg3, sizeof(arg3));
205 if (res < 0) {
206 SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
207 SCReturnPtr(NULL, "DetectFlagsData");
208 }
209 }
210 SCLogDebug("args '%s', '%s', '%s'", arg1, arg2, arg3);
211
212 if (strlen(arg2) == 0) {
213 SCLogDebug("empty argument");
214 SCReturnPtr(NULL, "DetectFlagsData");
215 }
216
217 DetectFlagsData *de = SCMalloc(sizeof(DetectFlagsData));
218 if (unlikely(de == NULL))
219 goto error;
220 memset(de, 0, sizeof(DetectFlagsData));
221 de->ignored_flags = 0xff;
222
223 /** First parse args1 */
224 ptr = arg1;
225 while (*ptr != '\0') {
226 switch (*ptr) {
227 case 'S':
228 case 's':
229 de->flags |= TH_SYN;
230 found++;
231 break;
232 case 'A':
233 case 'a':
234 de->flags |= TH_ACK;
235 found++;
236 break;
237 case 'F':
238 case 'f':
239 de->flags |= TH_FIN;
240 found++;
241 break;
242 case 'R':
243 case 'r':
244 de->flags |= TH_RST;
245 found++;
246 break;
247 case 'P':
248 case 'p':
249 de->flags |= TH_PUSH;
250 found++;
251 break;
252 case 'U':
253 case 'u':
254 de->flags |= TH_URG;
255 found++;
256 break;
257 case '1':
258 de->flags |= TH_CWR;
259 found++;
260 break;
261 case '2':
262 de->flags |= TH_ECN;
263 found++;
264 break;
265 case 'C':
266 case 'c':
267 de->flags |= TH_CWR;
268 found++;
269 break;
270 case 'E':
271 case 'e':
272 de->flags |= TH_ECN;
273 found++;
274 break;
275 case '0':
276 de->flags = 0;
277 found++;
278 break;
279
280 case '!':
281 de->modifier = MODIFIER_NOT;
282 break;
283 case '+':
284 de->modifier = MODIFIER_PLUS;
285 break;
286 case '*':
287 de->modifier = MODIFIER_ANY;
288 break;
289 }
290 ptr++;
291 }
292
293 /** Second parse first set of flags */
294 if (strlen(arg2) > 0) {
295 ptr = arg2;
296 while (*ptr != '\0') {
297 switch (*ptr) {
298 case 'S':
299 case 's':
300 de->flags |= TH_SYN;
301 found++;
302 break;
303 case 'A':
304 case 'a':
305 de->flags |= TH_ACK;
306 found++;
307 break;
308 case 'F':
309 case 'f':
310 de->flags |= TH_FIN;
311 found++;
312 break;
313 case 'R':
314 case 'r':
315 de->flags |= TH_RST;
316 found++;
317 break;
318 case 'P':
319 case 'p':
320 de->flags |= TH_PUSH;
321 found++;
322 break;
323 case 'U':
324 case 'u':
325 de->flags |= TH_URG;
326 found++;
327 break;
328 case '1':
329 case 'C':
330 case 'c':
331 de->flags |= TH_CWR;
332 found++;
333 break;
334 case '2':
335 case 'E':
336 case 'e':
337 de->flags |= TH_ECN;
338 found++;
339 break;
340 case '0':
341 de->flags = 0;
342 found++;
343 break;
344
345 case '!':
346 if (de->modifier != 0) {
347 SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
348 " one modifier at a time");
349 goto error;
350 }
351 de->modifier = MODIFIER_NOT;
352 SCLogDebug("NOT modifier is set");
353 break;
354 case '+':
355 if (de->modifier != 0) {
356 SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
357 " one modifier at a time");
358 goto error;
359 }
360 de->modifier = MODIFIER_PLUS;
361 SCLogDebug("PLUS modifier is set");
362 break;
363 case '*':
364 if (de->modifier != 0) {
365 SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
366 " one modifier at a time");
367 goto error;
368 }
369 de->modifier = MODIFIER_ANY;
370 SCLogDebug("ANY modifier is set");
371 break;
372 default:
373 break;
374 }
375 ptr++;
376 }
377
378 if (found == 0)
379 goto error;
380 }
381
382 /** Finally parse ignored flags */
383 if (strlen(arg3) > 0) {
384 ptr = arg3;
385
386 while (*ptr != '\0') {
387 switch (*ptr) {
388 case 'S':
389 case 's':
390 de->ignored_flags &= ~TH_SYN;
391 ignore++;
392 break;
393 case 'A':
394 case 'a':
395 de->ignored_flags &= ~TH_ACK;
396 ignore++;
397 break;
398 case 'F':
399 case 'f':
400 de->ignored_flags &= ~TH_FIN;
401 ignore++;
402 break;
403 case 'R':
404 case 'r':
405 de->ignored_flags &= ~TH_RST;
406 ignore++;
407 break;
408 case 'P':
409 case 'p':
410 de->ignored_flags &= ~TH_PUSH;
411 ignore++;
412 break;
413 case 'U':
414 case 'u':
415 de->ignored_flags &= ~TH_URG;
416 ignore++;
417 break;
418 case '1':
419 de->ignored_flags &= ~TH_CWR;
420 ignore++;
421 break;
422 case '2':
423 de->ignored_flags &= ~TH_ECN;
424 ignore++;
425 break;
426 case 'C':
427 case 'c':
428 de->ignored_flags &= ~TH_CWR;
429 ignore++;
430 break;
431 case 'E':
432 case 'e':
433 de->ignored_flags &= ~TH_ECN;
434 ignore++;
435 break;
436 case '0':
437 break;
438 default:
439 break;
440 }
441 ptr++;
442 }
443
444 if (ignore == 0) {
445 SCLogDebug("ignore == 0");
446 goto error;
447 }
448 }
449
450 SCLogDebug("found %"PRId32" ignore %"PRId32"", found, ignore);
451 SCReturnPtr(de, "DetectFlagsData");
452
453 error:
454 if (de) {
455 SCFree(de);
456 }
457 SCReturnPtr(NULL, "DetectFlagsData");
458 }
459
460 /**
461 * \internal
462 * \brief this function is used to add the parsed flags into the current signature
463 *
464 * \param de_ctx pointer to the Detection Engine Context
465 * \param s pointer to the Current Signature
466 * \param m pointer to the Current SigMatch
467 * \param rawstr pointer to the user provided flags options
468 *
469 * \retval 0 on Success
470 * \retval -1 on Failure
471 */
DetectFlagsSetup(DetectEngineCtx * de_ctx,Signature * s,const char * rawstr)472 static int DetectFlagsSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
473 {
474 DetectFlagsData *de = NULL;
475 SigMatch *sm = NULL;
476
477 de = DetectFlagsParse(rawstr);
478 if (de == NULL)
479 goto error;
480
481 sm = SigMatchAlloc();
482 if (sm == NULL)
483 goto error;
484
485 sm->type = DETECT_FLAGS;
486 sm->ctx = (SigMatchCtx *)de;
487
488 SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
489 s->flags |= SIG_FLAG_REQUIRE_PACKET;
490
491 return 0;
492
493 error:
494 if (de) SCFree(de);
495 if (sm) SCFree(sm);
496 return -1;
497 }
498
499 /**
500 * \internal
501 * \brief this function will free memory associated with DetectFlagsData
502 *
503 * \param de pointer to DetectFlagsData
504 */
DetectFlagsFree(DetectEngineCtx * de_ctx,void * de_ptr)505 static void DetectFlagsFree(DetectEngineCtx *de_ctx, void *de_ptr)
506 {
507 DetectFlagsData *de = (DetectFlagsData *)de_ptr;
508 if(de) SCFree(de);
509 }
510
DetectFlagsSignatureNeedsSynPackets(const Signature * s)511 int DetectFlagsSignatureNeedsSynPackets(const Signature *s)
512 {
513 const SigMatch *sm;
514 for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
515 switch (sm->type) {
516 case DETECT_FLAGS:
517 {
518 const DetectFlagsData *fl = (const DetectFlagsData *)sm->ctx;
519
520 if (!(fl->modifier == MODIFIER_NOT) && (fl->flags & TH_SYN)) {
521 return 1;
522 }
523 break;
524 }
525 }
526 }
527 return 0;
528 }
529
DetectFlagsSignatureNeedsSynOnlyPackets(const Signature * s)530 int DetectFlagsSignatureNeedsSynOnlyPackets(const Signature *s)
531 {
532 const SigMatch *sm;
533 for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
534 switch (sm->type) {
535 case DETECT_FLAGS:
536 {
537 const DetectFlagsData *fl = (const DetectFlagsData *)sm->ctx;
538
539 if (!(fl->modifier == MODIFIER_NOT) && (fl->flags == TH_SYN)) {
540 return 1;
541 }
542 break;
543 }
544 }
545 }
546 return 0;
547 }
548
549 static void
PrefilterPacketFlagsMatch(DetectEngineThreadCtx * det_ctx,Packet * p,const void * pectx)550 PrefilterPacketFlagsMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
551 {
552 if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) {
553 SCReturn;
554 }
555
556 const PrefilterPacketHeaderCtx *ctx = pectx;
557 if (PrefilterPacketHeaderExtraMatch(ctx, p) == FALSE)
558 return;
559
560 const uint8_t flags = p->tcph->th_flags;
561 if (FlagsMatch(flags, ctx->v1.u8[0], ctx->v1.u8[1], ctx->v1.u8[2]))
562 {
563 SCLogDebug("packet matches TCP flags %02x", ctx->v1.u8[1]);
564 PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
565 }
566 }
567
568 static void
PrefilterPacketFlagsSet(PrefilterPacketHeaderValue * v,void * smctx)569 PrefilterPacketFlagsSet(PrefilterPacketHeaderValue *v, void *smctx)
570 {
571 const DetectFlagsData *a = smctx;
572 v->u8[0] = a->modifier;
573 v->u8[1] = a->flags;
574 v->u8[2] = a->ignored_flags;
575 SCLogDebug("v->u8[0] = %02x", v->u8[0]);
576 }
577
578 static bool
PrefilterPacketFlagsCompare(PrefilterPacketHeaderValue v,void * smctx)579 PrefilterPacketFlagsCompare(PrefilterPacketHeaderValue v, void *smctx)
580 {
581 const DetectFlagsData *a = smctx;
582 if (v.u8[0] == a->modifier &&
583 v.u8[1] == a->flags &&
584 v.u8[2] == a->ignored_flags)
585 return TRUE;
586 return FALSE;
587 }
588
PrefilterSetupTcpFlags(DetectEngineCtx * de_ctx,SigGroupHead * sgh)589 static int PrefilterSetupTcpFlags(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
590 {
591 return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_FLAGS,
592 PrefilterPacketFlagsSet,
593 PrefilterPacketFlagsCompare,
594 PrefilterPacketFlagsMatch);
595
596 }
597
PrefilterTcpFlagsIsPrefilterable(const Signature * s)598 static bool PrefilterTcpFlagsIsPrefilterable(const Signature *s)
599 {
600 const SigMatch *sm;
601 for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
602 switch (sm->type) {
603 case DETECT_FLAGS:
604 return TRUE;
605 }
606 }
607 return FALSE;
608 }
609
610 /*
611 * ONLY TESTS BELOW THIS COMMENT
612 */
613
614 #ifdef UNITTESTS
615 /**
616 * \test FlagsTestParse01 is a test for a valid flags value
617 *
618 * \retval 1 on succces
619 * \retval 0 on failure
620 */
FlagsTestParse01(void)621 static int FlagsTestParse01 (void)
622 {
623 DetectFlagsData *de = DetectFlagsParse("S");
624 FAIL_IF_NULL(de);
625 FAIL_IF_NOT(de->flags == TH_SYN);
626 DetectFlagsFree(NULL, de);
627 PASS;
628 }
629
630 /**
631 * \test FlagsTestParse02 is a test for an invalid flags value
632 *
633 * \retval 1 on succces
634 * \retval 0 on failure
635 */
FlagsTestParse02(void)636 static int FlagsTestParse02 (void)
637 {
638 DetectFlagsData *de = NULL;
639 de = DetectFlagsParse("G");
640 if (de) {
641 DetectFlagsFree(NULL, de);
642 return 0;
643 }
644
645 return 1;
646 }
647
648 /**
649 * \test FlagsTestParse03 test if ACK and PUSH are set. Must return success
650 *
651 * \retval 1 on success
652 * \retval 0 on failure
653 */
FlagsTestParse03(void)654 static int FlagsTestParse03 (void)
655 {
656 Packet *p = SCMalloc(SIZE_OF_PACKET);
657 if (unlikely(p == NULL))
658 return 0;
659 ThreadVars tv;
660 int ret = 0;
661 DetectFlagsData *de = NULL;
662 SigMatch *sm = NULL;
663 IPV4Hdr ipv4h;
664 TCPHdr tcph;
665
666 memset(&tv, 0, sizeof(ThreadVars));
667 memset(p, 0, SIZE_OF_PACKET);
668 memset(&ipv4h, 0, sizeof(IPV4Hdr));
669 memset(&tcph, 0, sizeof(TCPHdr));
670
671 p->ip4h = &ipv4h;
672 p->tcph = &tcph;
673 p->tcph->th_flags = TH_ACK|TH_PUSH|TH_SYN|TH_RST;
674
675 de = DetectFlagsParse("AP+");
676
677 if (de == NULL || (de->flags != (TH_ACK|TH_PUSH)) )
678 goto error;
679
680 sm = SigMatchAlloc();
681 if (sm == NULL)
682 goto error;
683
684 sm->type = DETECT_FLAGS;
685 sm->ctx = (SigMatchCtx *)de;
686
687 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
688
689 if(ret) {
690 if (de) SCFree(de);
691 if (sm) SCFree(sm);
692 SCFree(p);
693 return 1;
694 }
695
696 error:
697 if (de) SCFree(de);
698 if (sm) SCFree(sm);
699 SCFree(p);
700 return 0;
701 }
702
703 /**
704 * \test FlagsTestParse04 check if ACK bit is set. Must fails.
705 *
706 * \retval 1 on succces
707 * \retval 0 on failure
708 */
FlagsTestParse04(void)709 static int FlagsTestParse04 (void)
710 {
711 Packet *p = SCMalloc(SIZE_OF_PACKET);
712 if (unlikely(p == NULL))
713 return 0;
714 ThreadVars tv;
715 int ret = 0;
716 DetectFlagsData *de = NULL;
717 SigMatch *sm = NULL;
718 IPV4Hdr ipv4h;
719 TCPHdr tcph;
720
721 memset(&tv, 0, sizeof(ThreadVars));
722 memset(p, 0, SIZE_OF_PACKET);
723 memset(&ipv4h, 0, sizeof(IPV4Hdr));
724 memset(&tcph, 0, sizeof(TCPHdr));
725
726 p->ip4h = &ipv4h;
727 p->tcph = &tcph;
728 p->tcph->th_flags = TH_SYN;
729
730 de = DetectFlagsParse("A");
731
732 if (de == NULL || de->flags != TH_ACK)
733 goto error;
734
735 sm = SigMatchAlloc();
736 if (sm == NULL)
737 goto error;
738
739 sm->type = DETECT_FLAGS;
740 sm->ctx = (SigMatchCtx *)de;
741
742 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
743
744 if(ret) {
745 if (de) SCFree(de);
746 if (sm) SCFree(sm);
747 SCFree(p);
748 return 0;
749 }
750
751 /* Error expected. */
752 error:
753 if (de) SCFree(de);
754 if (sm) SCFree(sm);
755 SCFree(p);
756 return 1;
757 }
758
759 /**
760 * \test FlagsTestParse05 test if ACK+PUSH and more flags are set. Ignore SYN and RST bits.
761 * Must fails.
762 * \retval 1 on success
763 * \retval 0 on failure
764 */
FlagsTestParse05(void)765 static int FlagsTestParse05 (void)
766 {
767 Packet *p = SCMalloc(SIZE_OF_PACKET);
768 if (unlikely(p == NULL))
769 return 0;
770 ThreadVars tv;
771 int ret = 0;
772 DetectFlagsData *de = NULL;
773 SigMatch *sm = NULL;
774 IPV4Hdr ipv4h;
775 TCPHdr tcph;
776
777 memset(&tv, 0, sizeof(ThreadVars));
778 memset(p, 0, SIZE_OF_PACKET);
779 memset(&ipv4h, 0, sizeof(IPV4Hdr));
780 memset(&tcph, 0, sizeof(TCPHdr));
781
782 p->ip4h = &ipv4h;
783 p->tcph = &tcph;
784 p->tcph->th_flags = TH_ACK|TH_PUSH|TH_SYN|TH_RST;
785
786 de = DetectFlagsParse("+AP,SR");
787
788 if (de == NULL || (de->modifier != MODIFIER_PLUS) || (de->flags != (TH_ACK|TH_PUSH)) || (de->ignored_flags != (TH_SYN|TH_RST)))
789 goto error;
790
791 sm = SigMatchAlloc();
792 if (sm == NULL)
793 goto error;
794
795 sm->type = DETECT_FLAGS;
796 sm->ctx = (SigMatchCtx *)de;
797
798 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
799
800 if(ret) {
801 if (de) SCFree(de);
802 if (sm) SCFree(sm);
803 SCFree(p);
804 return 0;
805 }
806
807 /* Error expected. */
808 error:
809 if (de) SCFree(de);
810 if (sm) SCFree(sm);
811 SCFree(p);
812 return 1;
813 }
814
815 /**
816 * \test FlagsTestParse06 test if ACK+PUSH and more flags are set. Ignore URG and RST bits.
817 * Must return success.
818 * \retval 1 on success
819 * \retval 0 on failure
820 */
FlagsTestParse06(void)821 static int FlagsTestParse06 (void)
822 {
823 Packet *p = SCMalloc(SIZE_OF_PACKET);
824 if (unlikely(p == NULL))
825 return 0;
826 ThreadVars tv;
827 int ret = 0;
828 DetectFlagsData *de = NULL;
829 SigMatch *sm = NULL;
830 IPV4Hdr ipv4h;
831 TCPHdr tcph;
832
833 memset(&tv, 0, sizeof(ThreadVars));
834 memset(p, 0, SIZE_OF_PACKET);
835 memset(&ipv4h, 0, sizeof(IPV4Hdr));
836 memset(&tcph, 0, sizeof(TCPHdr));
837
838 p->ip4h = &ipv4h;
839 p->tcph = &tcph;
840 p->tcph->th_flags = TH_ACK|TH_PUSH|TH_SYN|TH_RST;
841
842 de = DetectFlagsParse("+AP,UR");
843
844 if (de == NULL || (de->modifier != MODIFIER_PLUS) || (de->flags != (TH_ACK|TH_PUSH)) || ((0xff - de->ignored_flags) != (TH_URG|TH_RST)))
845 goto error;
846
847 sm = SigMatchAlloc();
848 if (sm == NULL)
849 goto error;
850
851 sm->type = DETECT_FLAGS;
852 sm->ctx = (SigMatchCtx *)de;
853
854 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
855
856 if(ret) {
857 if (de) SCFree(de);
858 if (sm) SCFree(sm);
859 SCFree(p);
860 return 1;
861 }
862
863 error:
864 if (de) SCFree(de);
865 if (sm) SCFree(sm);
866 SCFree(p);
867 return 0;
868 }
869
870 /**
871 * \test FlagsTestParse07 test if SYN or RST are set. Must fails.
872 *
873 * \retval 1 on success
874 * \retval 0 on failure
875 */
FlagsTestParse07(void)876 static int FlagsTestParse07 (void)
877 {
878 Packet *p = SCMalloc(SIZE_OF_PACKET);
879 if (unlikely(p == NULL))
880 return 0;
881 ThreadVars tv;
882 int ret = 0;
883 DetectFlagsData *de = NULL;
884 SigMatch *sm = NULL;
885 IPV4Hdr ipv4h;
886 TCPHdr tcph;
887
888 memset(&tv, 0, sizeof(ThreadVars));
889 memset(p, 0, SIZE_OF_PACKET);
890 memset(&ipv4h, 0, sizeof(IPV4Hdr));
891 memset(&tcph, 0, sizeof(TCPHdr));
892
893 p->ip4h = &ipv4h;
894 p->tcph = &tcph;
895 p->tcph->th_flags = TH_SYN|TH_RST;
896
897 de = DetectFlagsParse("*AP");
898
899 if (de == NULL || (de->modifier != MODIFIER_ANY) || (de->flags != (TH_ACK|TH_PUSH)))
900 goto error;
901
902 sm = SigMatchAlloc();
903 if (sm == NULL)
904 goto error;
905
906 sm->type = DETECT_FLAGS;
907 sm->ctx = (SigMatchCtx *)de;
908
909 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
910
911 if(ret) {
912 if (de) SCFree(de);
913 if (sm) SCFree(sm);
914 SCFree(p);
915 return 0;
916 }
917
918 /* Error expected. */
919 error:
920 if (de) SCFree(de);
921 if (sm) SCFree(sm);
922 SCFree(p);
923 return 1;
924 }
925
926 /**
927 * \test FlagsTestParse08 test if SYN or RST are set. Must return success.
928 *
929 * \retval 1 on success
930 * \retval 0 on failure
931 */
FlagsTestParse08(void)932 static int FlagsTestParse08 (void)
933 {
934 Packet *p = SCMalloc(SIZE_OF_PACKET);
935 if (unlikely(p == NULL))
936 return 0;
937 ThreadVars tv;
938 int ret = 0;
939 DetectFlagsData *de = NULL;
940 SigMatch *sm = NULL;
941 IPV4Hdr ipv4h;
942 TCPHdr tcph;
943
944 memset(&tv, 0, sizeof(ThreadVars));
945 memset(p, 0, SIZE_OF_PACKET);
946 memset(&ipv4h, 0, sizeof(IPV4Hdr));
947 memset(&tcph, 0, sizeof(TCPHdr));
948
949 p->ip4h = &ipv4h;
950 p->tcph = &tcph;
951 p->tcph->th_flags = TH_SYN|TH_RST;
952
953 de = DetectFlagsParse("*SA");
954
955 if (de == NULL || (de->modifier != MODIFIER_ANY) || (de->flags != (TH_ACK|TH_SYN)))
956 goto error;
957
958 sm = SigMatchAlloc();
959 if (sm == NULL)
960 goto error;
961
962 sm->type = DETECT_FLAGS;
963 sm->ctx = (SigMatchCtx *)de;
964
965 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
966
967 if(ret) {
968 if (de) SCFree(de);
969 if (sm) SCFree(sm);
970 SCFree(p);
971 return 1;
972 }
973
974 error:
975 if (de) SCFree(de);
976 if (sm) SCFree(sm);
977 SCFree(p);
978 return 0;
979 }
980
981 /**
982 * \test FlagsTestParse09 test if SYN and RST are not set. Must fails.
983 *
984 * \retval 1 on success
985 * \retval 0 on failure
986 */
FlagsTestParse09(void)987 static int FlagsTestParse09 (void)
988 {
989 Packet *p = SCMalloc(SIZE_OF_PACKET);
990 if (unlikely(p == NULL))
991 return 0;
992 ThreadVars tv;
993 int ret = 0;
994 DetectFlagsData *de = NULL;
995 SigMatch *sm = NULL;
996 IPV4Hdr ipv4h;
997 TCPHdr tcph;
998
999 memset(&tv, 0, sizeof(ThreadVars));
1000 memset(p, 0, SIZE_OF_PACKET);
1001 memset(&ipv4h, 0, sizeof(IPV4Hdr));
1002 memset(&tcph, 0, sizeof(TCPHdr));
1003
1004 p->ip4h = &ipv4h;
1005 p->tcph = &tcph;
1006 p->tcph->th_flags = TH_SYN|TH_RST;
1007
1008 de = DetectFlagsParse("!PA");
1009
1010 if (de == NULL || (de->modifier != MODIFIER_NOT) || (de->flags != (TH_ACK|TH_PUSH)))
1011 goto error;
1012
1013 sm = SigMatchAlloc();
1014 if (sm == NULL)
1015 goto error;
1016
1017 sm->type = DETECT_FLAGS;
1018 sm->ctx = (SigMatchCtx *)de;
1019
1020 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1021
1022 if(ret) {
1023 if (de) SCFree(de);
1024 if (sm) SCFree(sm);
1025 SCFree(p);
1026 return 1;
1027 }
1028
1029 error:
1030 if (de) SCFree(de);
1031 if (sm) SCFree(sm);
1032 SCFree(p);
1033 return 0;
1034 }
1035
1036 /**
1037 * \test FlagsTestParse10 test if ACK and PUSH are not set. Must return success.
1038 *
1039 * \retval 1 on success
1040 * \retval 0 on failure
1041 */
FlagsTestParse10(void)1042 static int FlagsTestParse10 (void)
1043 {
1044 Packet *p = SCMalloc(SIZE_OF_PACKET);
1045 if (unlikely(p == NULL))
1046 return 0;
1047 ThreadVars tv;
1048 int ret = 0;
1049 DetectFlagsData *de = NULL;
1050 SigMatch *sm = NULL;
1051 IPV4Hdr ipv4h;
1052 TCPHdr tcph;
1053
1054 memset(&tv, 0, sizeof(ThreadVars));
1055 memset(p, 0, SIZE_OF_PACKET);
1056 memset(&ipv4h, 0, sizeof(IPV4Hdr));
1057 memset(&tcph, 0, sizeof(TCPHdr));
1058
1059 p->ip4h = &ipv4h;
1060 p->tcph = &tcph;
1061 p->tcph->th_flags = TH_SYN|TH_RST;
1062
1063 de = DetectFlagsParse("!AP");
1064
1065 if (de == NULL || (de->modifier != MODIFIER_NOT) || (de->flags != (TH_ACK|TH_PUSH)))
1066 goto error;
1067
1068 sm = SigMatchAlloc();
1069 if (sm == NULL)
1070 goto error;
1071
1072 sm->type = DETECT_FLAGS;
1073 sm->ctx = (SigMatchCtx *)de;
1074
1075 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1076
1077 if(ret) {
1078 if (de) SCFree(de);
1079 if (sm) SCFree(sm);
1080 SCFree(p);
1081 return 1;
1082 }
1083
1084 error:
1085 if (de) SCFree(de);
1086 if (sm) SCFree(sm);
1087 SCFree(p);
1088 return 0;
1089 }
1090
1091 /**
1092 * \test FlagsTestParse11 test if ACK or PUSH are set. Ignore SYN and RST. Must fails.
1093 *
1094 * \retval 1 on success
1095 * \retval 0 on failure
1096 */
FlagsTestParse11(void)1097 static int FlagsTestParse11 (void)
1098 {
1099 Packet *p = SCMalloc(SIZE_OF_PACKET);
1100 if (unlikely(p == NULL))
1101 return 0;
1102 ThreadVars tv;
1103 int ret = 0;
1104 DetectFlagsData *de = NULL;
1105 SigMatch *sm = NULL;
1106 IPV4Hdr ipv4h;
1107 TCPHdr tcph;
1108
1109 memset(&tv, 0, sizeof(ThreadVars));
1110 memset(p, 0, SIZE_OF_PACKET);
1111 memset(&ipv4h, 0, sizeof(IPV4Hdr));
1112 memset(&tcph, 0, sizeof(TCPHdr));
1113
1114 p->ip4h = &ipv4h;
1115 p->tcph = &tcph;
1116 p->tcph->th_flags = TH_SYN|TH_RST|TH_URG;
1117
1118 de = DetectFlagsParse("*AP,SR");
1119
1120 if (de == NULL || (de->modifier != MODIFIER_ANY) || (de->flags != (TH_ACK|TH_PUSH)) || ((0xff - de->ignored_flags) != (TH_SYN|TH_RST)))
1121 goto error;
1122
1123 sm = SigMatchAlloc();
1124 if (sm == NULL)
1125 goto error;
1126
1127 sm->type = DETECT_FLAGS;
1128 sm->ctx = (SigMatchCtx *)de;
1129
1130 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1131
1132 if(ret) {
1133 if (de) SCFree(de);
1134 if (sm) SCFree(sm);
1135 SCFree(p);
1136 return 0;
1137 }
1138
1139 /* Expected. */
1140 error:
1141 if (de) SCFree(de);
1142 if (sm) SCFree(sm);
1143 SCFree(p);
1144 return 1;
1145 }
1146
1147 /**
1148 * \test FlagsTestParse12 check if no flags are set. Must fails.
1149 *
1150 * \retval 1 on succces
1151 * \retval 0 on failure
1152 */
FlagsTestParse12(void)1153 static int FlagsTestParse12 (void)
1154 {
1155 Packet *p = SCMalloc(SIZE_OF_PACKET);
1156 if (unlikely(p == NULL))
1157 return 0;
1158 ThreadVars tv;
1159 int ret = 0;
1160 DetectFlagsData *de = NULL;
1161 SigMatch *sm = NULL;
1162 IPV4Hdr ipv4h;
1163 TCPHdr tcph;
1164
1165 memset(&tv, 0, sizeof(ThreadVars));
1166 memset(p, 0, SIZE_OF_PACKET);
1167 memset(&ipv4h, 0, sizeof(IPV4Hdr));
1168 memset(&tcph, 0, sizeof(TCPHdr));
1169
1170 p->ip4h = &ipv4h;
1171 p->tcph = &tcph;
1172 p->tcph->th_flags = TH_SYN;
1173
1174 de = DetectFlagsParse("0");
1175
1176 if (de == NULL || de->flags != 0) {
1177 printf("de setup: ");
1178 goto error;
1179 }
1180
1181 sm = SigMatchAlloc();
1182 if (sm == NULL)
1183 goto error;
1184
1185 sm->type = DETECT_FLAGS;
1186 sm->ctx = (SigMatchCtx *)de;
1187
1188 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1189
1190 if(ret) {
1191 if (de) SCFree(de);
1192 if (sm) SCFree(sm);
1193 SCFree(p);
1194 return 0;
1195 }
1196
1197 /* Expected. */
1198 error:
1199 if (de) SCFree(de);
1200 if (sm) SCFree(sm);
1201 SCFree(p);
1202 return 1;
1203 }
1204
1205 /**
1206 * \test test for a valid flags value
1207 *
1208 * \retval 1 on succces
1209 * \retval 0 on failure
1210 */
FlagsTestParse13(void)1211 static int FlagsTestParse13 (void)
1212 {
1213 DetectFlagsData *de = NULL;
1214 de = DetectFlagsParse("+S*");
1215 if (de != NULL) {
1216 DetectFlagsFree(NULL, de);
1217 return 0;
1218 }
1219
1220 return 1;
1221 }
1222
1223 /**
1224 * \test Parse 'C' and 'E' flags.
1225 *
1226 * \retval 1 on success.
1227 * \retval 0 on failure.
1228 */
FlagsTestParse14(void)1229 static int FlagsTestParse14(void)
1230 {
1231 DetectFlagsData *de = DetectFlagsParse("CE");
1232 if (de != NULL && (de->flags == (TH_CWR | TH_ECN)) ) {
1233 DetectFlagsFree(NULL, de);
1234 return 1;
1235 }
1236
1237 return 0;
1238 }
1239
FlagsTestParse15(void)1240 static int FlagsTestParse15(void)
1241 {
1242 Packet *p = SCMalloc(SIZE_OF_PACKET);
1243 if (unlikely(p == NULL))
1244 return 0;
1245 ThreadVars tv;
1246 int ret = 0;
1247 DetectFlagsData *de = NULL;
1248 SigMatch *sm = NULL;
1249 IPV4Hdr ipv4h;
1250 TCPHdr tcph;
1251
1252 memset(&tv, 0, sizeof(ThreadVars));
1253 memset(p, 0, SIZE_OF_PACKET);
1254 memset(&ipv4h, 0, sizeof(IPV4Hdr));
1255 memset(&tcph, 0, sizeof(TCPHdr));
1256
1257 p->ip4h = &ipv4h;
1258 p->tcph = &tcph;
1259 p->tcph->th_flags = TH_ECN | TH_CWR | TH_SYN | TH_RST;
1260
1261 de = DetectFlagsParse("EC+");
1262
1263 if (de == NULL || (de->flags != (TH_ECN | TH_CWR)) )
1264 goto error;
1265
1266 sm = SigMatchAlloc();
1267 if (sm == NULL)
1268 goto error;
1269
1270 sm->type = DETECT_FLAGS;
1271 sm->ctx = (SigMatchCtx *)de;
1272
1273 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1274
1275 if (ret) {
1276 if (de)
1277 SCFree(de);
1278 if (sm)
1279 SCFree(sm);
1280 SCFree(p);
1281 return 1;
1282 }
1283
1284 error:
1285 if (de)
1286 SCFree(de);
1287 if (sm)
1288 SCFree(sm);
1289 SCFree(p);
1290 return 0;
1291 }
1292
FlagsTestParse16(void)1293 static int FlagsTestParse16(void)
1294 {
1295 Packet *p = SCMalloc(SIZE_OF_PACKET);
1296 if (unlikely(p == NULL))
1297 return 0;
1298 ThreadVars tv;
1299 int ret = 0;
1300 DetectFlagsData *de = NULL;
1301 SigMatch *sm = NULL;
1302 IPV4Hdr ipv4h;
1303 TCPHdr tcph;
1304
1305 memset(&tv, 0, sizeof(ThreadVars));
1306 memset(p, 0, SIZE_OF_PACKET);
1307 memset(&ipv4h, 0, sizeof(IPV4Hdr));
1308 memset(&tcph, 0, sizeof(TCPHdr));
1309
1310 p->ip4h = &ipv4h;
1311 p->tcph = &tcph;
1312 p->tcph->th_flags = TH_ECN | TH_SYN | TH_RST;
1313
1314 de = DetectFlagsParse("EC*");
1315
1316 if (de == NULL || (de->flags != (TH_ECN | TH_CWR)) )
1317 goto error;
1318
1319 sm = SigMatchAlloc();
1320 if (sm == NULL)
1321 goto error;
1322
1323 sm->type = DETECT_FLAGS;
1324 sm->ctx = (SigMatchCtx *)de;
1325
1326 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1327
1328 if (ret) {
1329 if (de)
1330 SCFree(de);
1331 if (sm)
1332 SCFree(sm);
1333 SCFree(p);
1334 return 1;
1335 }
1336
1337 error:
1338 if (de)
1339 SCFree(de);
1340 if (sm)
1341 SCFree(sm);
1342 SCFree(p);
1343 return 0;
1344 }
1345
1346 /**
1347 * \test Negative test.
1348 */
FlagsTestParse17(void)1349 static int FlagsTestParse17(void)
1350 {
1351 Packet *p = SCMalloc(SIZE_OF_PACKET);
1352 if (unlikely(p == NULL))
1353 return 0;
1354 ThreadVars tv;
1355 int ret = 0;
1356 DetectFlagsData *de = NULL;
1357 SigMatch *sm = NULL;
1358 IPV4Hdr ipv4h;
1359 TCPHdr tcph;
1360
1361 memset(&tv, 0, sizeof(ThreadVars));
1362 memset(p, 0, SIZE_OF_PACKET);
1363 memset(&ipv4h, 0, sizeof(IPV4Hdr));
1364 memset(&tcph, 0, sizeof(TCPHdr));
1365
1366 p->ip4h = &ipv4h;
1367 p->tcph = &tcph;
1368 p->tcph->th_flags = TH_ECN | TH_SYN | TH_RST;
1369
1370 de = DetectFlagsParse("EC+");
1371
1372 if (de == NULL || (de->flags != (TH_ECN | TH_CWR)) )
1373 goto error;
1374
1375 sm = SigMatchAlloc();
1376 if (sm == NULL)
1377 goto error;
1378
1379 sm->type = DETECT_FLAGS;
1380 sm->ctx = (SigMatchCtx *)de;
1381
1382 ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1383
1384 if (ret == 0) {
1385 if (de)
1386 SCFree(de);
1387 if (sm)
1388 SCFree(sm);
1389 SCFree(p);
1390 return 1;
1391 }
1392
1393 error:
1394 if (de)
1395 SCFree(de);
1396 if (sm)
1397 SCFree(sm);
1398 SCFree(p);
1399 return 0;
1400 }
1401
1402 /**
1403 * \brief this function registers unit tests for Flags
1404 */
FlagsRegisterTests(void)1405 static void FlagsRegisterTests(void)
1406 {
1407 UtRegisterTest("FlagsTestParse01", FlagsTestParse01);
1408 UtRegisterTest("FlagsTestParse02", FlagsTestParse02);
1409 UtRegisterTest("FlagsTestParse03", FlagsTestParse03);
1410 UtRegisterTest("FlagsTestParse04", FlagsTestParse04);
1411 UtRegisterTest("FlagsTestParse05", FlagsTestParse05);
1412 UtRegisterTest("FlagsTestParse06", FlagsTestParse06);
1413 UtRegisterTest("FlagsTestParse07", FlagsTestParse07);
1414 UtRegisterTest("FlagsTestParse08", FlagsTestParse08);
1415 UtRegisterTest("FlagsTestParse09", FlagsTestParse09);
1416 UtRegisterTest("FlagsTestParse10", FlagsTestParse10);
1417 UtRegisterTest("FlagsTestParse11", FlagsTestParse11);
1418 UtRegisterTest("FlagsTestParse12", FlagsTestParse12);
1419 UtRegisterTest("FlagsTestParse13", FlagsTestParse13);
1420 UtRegisterTest("FlagsTestParse14", FlagsTestParse14);
1421 UtRegisterTest("FlagsTestParse15", FlagsTestParse15);
1422 UtRegisterTest("FlagsTestParse16", FlagsTestParse16);
1423 UtRegisterTest("FlagsTestParse17", FlagsTestParse17);
1424 }
1425 #endif /* UNITTESTS */