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