suricata
detect-tcp-flags.c
Go to the documentation of this file.
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 #include "rust.h"
30 
31 #include "detect.h"
32 #include "detect-parse.h"
35 #include "detect-engine-uint.h"
36 
37 #include "flow-var.h"
38 #include "decode-events.h"
39 
40 #include "detect-tcp-flags.h"
41 #include "util-unittest-helper.h"
42 
43 #include "util-debug.h"
44 
45 static int DetectFlagsMatch (DetectEngineThreadCtx *, Packet *,
46  const Signature *, const SigMatchCtx *);
47 static int DetectFlagsSetup (DetectEngineCtx *, Signature *, const char *);
48 static void DetectFlagsFree(DetectEngineCtx *, void *);
49 
50 static bool PrefilterTcpFlagsIsPrefilterable(const Signature *s);
51 static int PrefilterSetupTcpFlags(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
52 #ifdef UNITTESTS
53 static void FlagsRegisterTests(void);
54 #endif
55 
56 /**
57  * \brief Registration function for flags: keyword
58  */
59 
61 {
62  sigmatch_table[DETECT_FLAGS].name = "tcp.flags";
64  sigmatch_table[DETECT_FLAGS].desc = "detect which flags are set in the TCP header";
65  sigmatch_table[DETECT_FLAGS].url = "/rules/header-keywords.html#tcp-flags";
66  sigmatch_table[DETECT_FLAGS].Match = DetectFlagsMatch;
67  sigmatch_table[DETECT_FLAGS].Setup = DetectFlagsSetup;
68  sigmatch_table[DETECT_FLAGS].Free = DetectFlagsFree;
69 #ifdef UNITTESTS
70  sigmatch_table[DETECT_FLAGS].RegisterTests = FlagsRegisterTests;
71 #endif
72  sigmatch_table[DETECT_FLAGS].SupportsPrefilter = PrefilterTcpFlagsIsPrefilterable;
73  sigmatch_table[DETECT_FLAGS].SetupPrefilter = PrefilterSetupTcpFlags;
76 }
77 
78 /**
79  * \internal
80  * \brief This function is used to match flags on a packet with those passed via flags:
81  *
82  * \param t pointer to thread vars
83  * \param det_ctx pointer to the pattern matcher thread
84  * \param p pointer to the current packet
85  * \param s pointer to the Signature
86  * \param m pointer to the sigmatch
87  *
88  * \retval 0 no match
89  * \retval 1 match
90  */
91 static int DetectFlagsMatch (DetectEngineThreadCtx *det_ctx, Packet *p,
92  const Signature *s, const SigMatchCtx *ctx)
93 {
94  SCEnter();
95 
97  if (!(PacketIsTCP(p))) {
98  SCReturnInt(0);
99  }
100 
101  const TCPHdr *tcph = PacketGetTCP(p);
102  const uint8_t flags = tcph->th_flags;
103  DetectU8Data *du8 = (DetectU8Data *)ctx;
104  return DetectU8Match(flags, du8);
105 }
106 
107 /**
108  * \internal
109  * \brief this function is used to add the parsed flags into the current signature
110  *
111  * \param de_ctx pointer to the Detection Engine Context
112  * \param s pointer to the Current Signature
113  * \param m pointer to the Current SigMatch
114  * \param rawstr pointer to the user provided flags options
115  *
116  * \retval 0 on Success
117  * \retval -1 on Failure
118  */
119 static int DetectFlagsSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
120 {
121  DetectU8Data *du8 = SCDetectTcpFlagsParse(rawstr);
122  if (du8 == NULL)
123  goto error;
124 
126  de_ctx, s, DETECT_FLAGS, (SigMatchCtx *)du8, DETECT_SM_LIST_MATCH) == NULL) {
127  goto error;
128  }
130 
131  return 0;
132 
133 error:
134  if (du8)
135  DetectFlagsFree(NULL, du8);
136  return -1;
137 }
138 
139 /**
140  * \internal
141  * \brief this function will free memory associated with DetectU8Data
142  *
143  * \param de pointer to DetectU8Data
144  */
145 static void DetectFlagsFree(DetectEngineCtx *de_ctx, void *de_ptr)
146 {
147  SCDetectU8Free(de_ptr);
148 }
149 
151 {
152  const SigMatch *sm;
153  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
154  switch (sm->type) {
155  case DETECT_FLAGS:
156  {
157  const DetectU8Data *fl = (const DetectU8Data *)sm->ctx;
158 
159  if (DetectU8Match(TH_SYN, fl)) {
160  return 1;
161  }
162  break;
163  }
164  }
165  }
166  return 0;
167 }
168 
170 {
171  const SigMatch *sm;
172  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
173  switch (sm->type) {
174  case DETECT_FLAGS:
175  {
176  const DetectU8Data *fl = (const DetectU8Data *)sm->ctx;
177 
178  if (!(fl->mode == DetectUintModeNegBitmask) && (fl->arg1 == TH_SYN)) {
179  return 1;
180  }
181  break;
182  }
183  }
184  }
185  return 0;
186 }
187 
188 static void
189 PrefilterPacketFlagsMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
190 {
192  if (!(PacketIsTCP(p))) {
193  SCReturn;
194  }
195 
196  const PrefilterPacketHeaderCtx *ctx = pectx;
197  if (!PrefilterPacketHeaderExtraMatch(ctx, p))
198  return;
199 
200  const TCPHdr *tcph = PacketGetTCP(p);
201  const uint8_t flags = tcph->th_flags;
202  DetectU8Data du8;
203  du8.mode = ctx->v1.u8[0];
204  du8.arg1 = ctx->v1.u8[1];
205  du8.arg2 = ctx->v1.u8[2];
206  if (DetectU8Match(flags, &du8)) {
207  SCLogDebug("packet matches TCP flags %02x", ctx->v1.u8[1]);
208  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
209  }
210 }
211 
212 static void
213 PrefilterPacketFlagsSet(PrefilterPacketHeaderValue *v, void *smctx)
214 {
215  const DetectU8Data *a = smctx;
216  v->u8[0] = a->mode;
217  v->u8[1] = a->arg1;
218  v->u8[2] = a->arg2;
219  SCLogDebug("v->u8[0] = %02x", v->u8[0]);
220 }
221 
222 static bool
223 PrefilterPacketFlagsCompare(PrefilterPacketHeaderValue v, void *smctx)
224 {
225  const DetectU8Data *a = smctx;
226  return v.u8[0] == a->mode && v.u8[1] == a->arg1 && v.u8[2] == a->arg2;
227 }
228 
229 static int PrefilterSetupTcpFlags(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
230 {
232  PrefilterPacketFlagsSet, PrefilterPacketFlagsCompare, PrefilterPacketFlagsMatch);
233 }
234 
235 static bool PrefilterTcpFlagsIsPrefilterable(const Signature *s)
236 {
237  return PrefilterIsPrefilterableById(s, DETECT_FLAGS);
238 }
239 
240 /*
241  * ONLY TESTS BELOW THIS COMMENT
242  */
243 
244 #ifdef UNITTESTS
245 /**
246  * \test FlagsTestParse03 test if ACK and PUSH are set. Must return success
247  *
248  * \retval 1 on success
249  * \retval 0 on failure
250  */
251 static int FlagsTestParse03 (void)
252 {
253  ThreadVars tv;
254  IPV4Hdr ipv4h;
255  TCPHdr tcph;
256 
257  memset(&tv, 0, sizeof(ThreadVars));
258  memset(&ipv4h, 0, sizeof(IPV4Hdr));
259  memset(&tcph, 0, sizeof(TCPHdr));
260 
262  FAIL_IF_NULL(p);
263  UTHSetIPV4Hdr(p, &ipv4h);
264  tcph.th_flags = TH_ACK | TH_PUSH | TH_SYN | TH_RST;
265  UTHSetTCPHdr(p, &tcph);
266 
267  DetectU8Data *de = SCDetectTcpFlagsParse("AP+");
268  FAIL_IF_NULL(de);
269  FAIL_IF(de->mode != DetectUintModeBitmask);
270  FAIL_IF(de->arg1 != (TH_ACK | TH_PUSH));
271  FAIL_IF(de->arg2 != (TH_ACK | TH_PUSH));
272 
273  SigMatch *sm = SigMatchAlloc();
274  FAIL_IF_NULL(sm);
275  sm->type = DETECT_FLAGS;
276  sm->ctx = (SigMatchCtx *)de;
277 
278  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
279  FAIL_IF_NOT(ret == 1);
280 
281  SigMatchFree(NULL, sm);
282  PacketFree(p);
283  PASS;
284 }
285 
286 /**
287  * \test FlagsTestParse04 check if ACK bit is set. Must fails.
288  *
289  * \retval 1 on success
290  * \retval 0 on failure
291  */
292 static int FlagsTestParse04 (void)
293 {
294  ThreadVars tv;
295  IPV4Hdr ipv4h;
296  TCPHdr tcph;
297 
298  memset(&tv, 0, sizeof(ThreadVars));
299  memset(&ipv4h, 0, sizeof(IPV4Hdr));
300  memset(&tcph, 0, sizeof(TCPHdr));
301 
303  FAIL_IF_NULL(p);
304  UTHSetIPV4Hdr(p, &ipv4h);
305  tcph.th_flags = TH_SYN;
306  UTHSetTCPHdr(p, &tcph);
307 
308  DetectU8Data *de = SCDetectTcpFlagsParse("A");
309  FAIL_IF_NULL(de);
310  FAIL_IF(de->mode != DetectUintModeBitmask);
311  FAIL_IF(de->arg1 != 0xFF);
312  FAIL_IF(de->arg2 != TH_ACK);
313 
314  SigMatch *sm = SigMatchAlloc();
315  FAIL_IF_NULL(sm);
316  sm->type = DETECT_FLAGS;
317  sm->ctx = (SigMatchCtx *)de;
318 
319  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
320  FAIL_IF_NOT(ret == 0);
321 
322  SigMatchFree(NULL, sm);
323  PacketFree(p);
324  PASS;
325 }
326 
327 /**
328  * \test FlagsTestParse05 test if ACK+PUSH and no other flags are set. Ignore SYN and RST bits.
329  * \retval 1 on success
330  * \retval 0 on failure
331  */
332 static int FlagsTestParse05 (void)
333 {
334  ThreadVars tv;
335  IPV4Hdr ipv4h;
336  TCPHdr tcph;
337 
338  memset(&tv, 0, sizeof(ThreadVars));
339  memset(&ipv4h, 0, sizeof(IPV4Hdr));
340  memset(&tcph, 0, sizeof(TCPHdr));
341 
343  FAIL_IF_NULL(p);
344  UTHSetIPV4Hdr(p, &ipv4h);
345  tcph.th_flags = TH_ACK | TH_PUSH | TH_SYN | TH_RST;
346  UTHSetTCPHdr(p, &tcph);
347 
348  DetectU8Data *de = SCDetectTcpFlagsParse("AP,SR");
349  FAIL_IF_NULL(de);
350  FAIL_IF(de->mode != DetectUintModeBitmask);
351  FAIL_IF(de->arg1 != (uint8_t) ~(TH_SYN | TH_RST));
352  FAIL_IF(de->arg2 != (TH_ACK | TH_PUSH));
353 
354  SigMatch *sm = SigMatchAlloc();
355  FAIL_IF_NULL(sm);
356  sm->type = DETECT_FLAGS;
357  sm->ctx = (SigMatchCtx *)de;
358 
359  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
360  FAIL_IF_NOT(ret == 1);
361 
362  SigMatchFree(NULL, sm);
363  PacketFree(p);
364  PASS;
365 }
366 
367 /**
368  * \test FlagsTestParse06 test if ACK+PUSH and no other flags are set. Ignore URG and RST bits.
369  * Must fail as TH_SYN is also set
370  * \retval 1 on success
371  * \retval 0 on failure
372  */
373 static int FlagsTestParse06 (void)
374 {
375  ThreadVars tv;
376  IPV4Hdr ipv4h;
377  TCPHdr tcph;
378 
379  memset(&tv, 0, sizeof(ThreadVars));
380  memset(&ipv4h, 0, sizeof(IPV4Hdr));
381  memset(&tcph, 0, sizeof(TCPHdr));
382 
384  FAIL_IF_NULL(p);
385  UTHSetIPV4Hdr(p, &ipv4h);
386  tcph.th_flags = TH_ACK | TH_PUSH | TH_SYN | TH_RST;
387  UTHSetTCPHdr(p, &tcph);
388 
389  DetectU8Data *de = SCDetectTcpFlagsParse("AP,UR");
390  FAIL_IF_NULL(de);
391  FAIL_IF(de->mode != DetectUintModeBitmask);
392  FAIL_IF(de->arg1 != (uint8_t) ~(TH_URG | TH_RST));
393  FAIL_IF(de->arg2 != (TH_ACK | TH_PUSH));
394 
395  SigMatch *sm = SigMatchAlloc();
396  FAIL_IF_NULL(sm);
397  sm->type = DETECT_FLAGS;
398  sm->ctx = (SigMatchCtx *)de;
399 
400  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
401  FAIL_IF_NOT(ret == 0);
402 
403  SigMatchFree(NULL, sm);
404  PacketFree(p);
405  PASS;
406 }
407 
408 /**
409  * \test FlagsTestParse07 test if SYN or RST are set. Must fails.
410  *
411  * \retval 1 on success
412  * \retval 0 on failure
413  */
414 static int FlagsTestParse07 (void)
415 {
416  ThreadVars tv;
417  IPV4Hdr ipv4h;
418  TCPHdr tcph;
419 
420  memset(&tv, 0, sizeof(ThreadVars));
421  memset(&ipv4h, 0, sizeof(IPV4Hdr));
422  memset(&tcph, 0, sizeof(TCPHdr));
423 
425  FAIL_IF_NULL(p);
426  UTHSetIPV4Hdr(p, &ipv4h);
427  tcph.th_flags = TH_SYN | TH_RST;
428  UTHSetTCPHdr(p, &tcph);
429 
430  DetectU8Data *de = SCDetectTcpFlagsParse("*AP");
431  FAIL_IF_NULL(de);
432  FAIL_IF(de->mode != DetectUintModeNegBitmask);
433  FAIL_IF(de->arg1 != (TH_ACK | TH_PUSH));
434  FAIL_IF(de->arg2 != 0);
435 
436  SigMatch *sm = SigMatchAlloc();
437  FAIL_IF_NULL(sm);
438  sm->type = DETECT_FLAGS;
439  sm->ctx = (SigMatchCtx *)de;
440 
441  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
442  FAIL_IF_NOT(ret == 0);
443 
444  SigMatchFree(NULL, sm);
445  PacketFree(p);
446  PASS;
447 }
448 
449 /**
450  * \test FlagsTestParse08 test if SYN or RST are set. Must return success.
451  *
452  * \retval 1 on success
453  * \retval 0 on failure
454  */
455 static int FlagsTestParse08 (void)
456 {
457  ThreadVars tv;
458  IPV4Hdr ipv4h;
459  TCPHdr tcph;
460 
461  memset(&tv, 0, sizeof(ThreadVars));
462  memset(&ipv4h, 0, sizeof(IPV4Hdr));
463  memset(&tcph, 0, sizeof(TCPHdr));
464 
466  FAIL_IF_NULL(p);
467  UTHSetIPV4Hdr(p, &ipv4h);
468  tcph.th_flags = TH_SYN | TH_RST;
469  UTHSetTCPHdr(p, &tcph);
470 
471  DetectU8Data *de = SCDetectTcpFlagsParse("*SA");
472  FAIL_IF_NULL(de);
473  FAIL_IF(de->mode != DetectUintModeNegBitmask);
474  FAIL_IF(de->arg1 != (TH_ACK | TH_SYN));
475 
476  SigMatch *sm = SigMatchAlloc();
477  FAIL_IF_NULL(sm);
478  sm->type = DETECT_FLAGS;
479  sm->ctx = (SigMatchCtx *)de;
480 
481  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
482  FAIL_IF_NOT(ret == 1);
483 
484  SigMatchFree(NULL, sm);
485  PacketFree(p);
486  PASS;
487 }
488 
489 /**
490  * \test FlagsTestParse09 test if SYN and RST are not set. Must fails.
491  *
492  * \retval 1 on success
493  * \retval 0 on failure
494  */
495 static int FlagsTestParse09 (void)
496 {
497  ThreadVars tv;
498  IPV4Hdr ipv4h;
499  TCPHdr tcph;
500 
501  memset(&tv, 0, sizeof(ThreadVars));
502  memset(&ipv4h, 0, sizeof(IPV4Hdr));
503  memset(&tcph, 0, sizeof(TCPHdr));
504 
506  FAIL_IF_NULL(p);
507  UTHSetIPV4Hdr(p, &ipv4h);
508  tcph.th_flags = TH_SYN | TH_RST;
509  UTHSetTCPHdr(p, &tcph);
510 
511  DetectU8Data *de = SCDetectTcpFlagsParse("!PA");
512  FAIL_IF_NULL(de);
513  FAIL_IF(de->mode != DetectUintModeNegBitmask);
514  FAIL_IF(de->arg1 != (TH_ACK | TH_PUSH));
515  FAIL_IF(de->arg2 != (TH_ACK | TH_PUSH));
516 
517  SigMatch *sm = SigMatchAlloc();
518  FAIL_IF_NULL(sm);
519  sm->type = DETECT_FLAGS;
520  sm->ctx = (SigMatchCtx *)de;
521 
522  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
523  FAIL_IF_NOT(ret == 1);
524 
525  SigMatchFree(NULL, sm);
526  PacketFree(p);
527  PASS;
528 }
529 
530 /**
531  * \test FlagsTestParse10 test if ACK and PUSH are not set. Must return success.
532  *
533  * \retval 1 on success
534  * \retval 0 on failure
535  */
536 static int FlagsTestParse10 (void)
537 {
538  ThreadVars tv;
539  IPV4Hdr ipv4h;
540  TCPHdr tcph;
541 
542  memset(&tv, 0, sizeof(ThreadVars));
543  memset(&ipv4h, 0, sizeof(IPV4Hdr));
544  memset(&tcph, 0, sizeof(TCPHdr));
545 
547  FAIL_IF_NULL(p);
548  UTHSetIPV4Hdr(p, &ipv4h);
549  tcph.th_flags = TH_SYN | TH_RST;
550  UTHSetTCPHdr(p, &tcph);
551 
552  DetectU8Data *de = SCDetectTcpFlagsParse("!AP");
553  FAIL_IF_NULL(de);
554 
555  FAIL_IF(de->mode != DetectUintModeNegBitmask);
556  FAIL_IF(de->arg1 != (TH_ACK | TH_PUSH));
557 
558  SigMatch *sm = SigMatchAlloc();
559  FAIL_IF_NULL(sm);
560  sm->type = DETECT_FLAGS;
561  sm->ctx = (SigMatchCtx *)de;
562 
563  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
564  FAIL_IF_NOT(ret == 1);
565 
566  SigMatchFree(NULL, sm);
567  PacketFree(p);
568  PASS;
569 }
570 
571 /**
572  * \test FlagsTestParse11 test if flags are ACK and PUSH. Ignore SYN and RST.
573  *
574  * \retval 1 on success
575  * \retval 0 on failure
576  */
577 static int FlagsTestParse11 (void)
578 {
579  ThreadVars tv;
580  IPV4Hdr ipv4h;
581  TCPHdr tcph;
582 
583  memset(&tv, 0, sizeof(ThreadVars));
584  memset(&ipv4h, 0, sizeof(IPV4Hdr));
585  memset(&tcph, 0, sizeof(TCPHdr));
586 
588  FAIL_IF_NULL(p);
589  UTHSetIPV4Hdr(p, &ipv4h);
590  tcph.th_flags = TH_SYN | TH_RST | TH_URG;
591  UTHSetTCPHdr(p, &tcph);
592 
593  DetectU8Data *de = SCDetectTcpFlagsParse("AP,SR");
594  FAIL_IF_NULL(de);
595  FAIL_IF(de->mode != DetectUintModeBitmask);
596  FAIL_IF(de->arg1 != (uint8_t) ~(TH_SYN | TH_RST));
597  FAIL_IF(de->arg2 != (TH_ACK | TH_PUSH));
598 
599  SigMatch *sm = SigMatchAlloc();
600  FAIL_IF_NULL(de);
601  sm->type = DETECT_FLAGS;
602  sm->ctx = (SigMatchCtx *)de;
603 
604  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
605  FAIL_IF_NOT(ret == 0);
606 
607  SigMatchFree(NULL, sm);
608  PacketFree(p);
609  PASS;
610 }
611 
612 /**
613  * \test FlagsTestParse12 check if no flags are set. Must fail.
614  *
615  * \retval 1 on success
616  * \retval 0 on failure
617  */
618 static int FlagsTestParse12 (void)
619 {
620  ThreadVars tv;
621  IPV4Hdr ipv4h;
622  TCPHdr tcph;
623 
624  memset(&tv, 0, sizeof(ThreadVars));
625  memset(&ipv4h, 0, sizeof(IPV4Hdr));
626  memset(&tcph, 0, sizeof(TCPHdr));
627 
629  FAIL_IF_NULL(p);
630  UTHSetIPV4Hdr(p, &ipv4h);
631  tcph.th_flags = TH_SYN;
632  UTHSetTCPHdr(p, &tcph);
633 
634  DetectU8Data *de = SCDetectTcpFlagsParse("0");
635  FAIL_IF_NULL(de);
636  FAIL_IF_NOT(de->mode == DetectUintModeEqual);
637  FAIL_IF_NOT(de->arg1 == 0);
638 
639  SigMatch *sm = SigMatchAlloc();
640  FAIL_IF_NULL(sm);
641  sm->type = DETECT_FLAGS;
642  sm->ctx = (SigMatchCtx *)de;
643 
644  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
645  FAIL_IF_NOT(ret == 0);
646 
647  SigMatchFree(NULL, sm);
648  PacketFree(p);
649  PASS;
650 }
651 
652 static int FlagsTestParse15(void)
653 {
654  ThreadVars tv;
655  IPV4Hdr ipv4h;
656  TCPHdr tcph;
657 
658  memset(&tv, 0, sizeof(ThreadVars));
659  memset(&ipv4h, 0, sizeof(IPV4Hdr));
660  memset(&tcph, 0, sizeof(TCPHdr));
661 
663  FAIL_IF_NULL(p);
664  UTHSetIPV4Hdr(p, &ipv4h);
665  tcph.th_flags = TH_ECN | TH_CWR | TH_SYN | TH_RST;
666  UTHSetTCPHdr(p, &tcph);
667 
668  DetectU8Data *de = SCDetectTcpFlagsParse("EC+");
669  FAIL_IF_NULL(de);
670  FAIL_IF_NOT(de->mode == DetectUintModeBitmask);
671  FAIL_IF_NOT(de->arg1 == (TH_ECN | TH_CWR));
672  FAIL_IF_NOT(de->arg2 == (TH_ECN | TH_CWR));
673 
674  SigMatch *sm = SigMatchAlloc();
675  FAIL_IF_NULL(sm);
676  sm->type = DETECT_FLAGS;
677  sm->ctx = (SigMatchCtx *)de;
678 
679  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
680  FAIL_IF_NOT(ret == 1);
681 
682  SigMatchFree(NULL, sm);
683  PacketFree(p);
684  PASS;
685 }
686 
687 static int FlagsTestParse16(void)
688 {
689  ThreadVars tv;
690  IPV4Hdr ipv4h;
691  TCPHdr tcph;
692 
693  memset(&tv, 0, sizeof(ThreadVars));
694  memset(&ipv4h, 0, sizeof(IPV4Hdr));
695  memset(&tcph, 0, sizeof(TCPHdr));
696 
698  FAIL_IF_NULL(p);
699  UTHSetIPV4Hdr(p, &ipv4h);
700  tcph.th_flags = TH_ECN | TH_SYN | TH_RST;
701  UTHSetTCPHdr(p, &tcph);
702 
703  DetectU8Data *de = SCDetectTcpFlagsParse("EC*");
704  FAIL_IF_NULL(de);
705  FAIL_IF_NOT(de->mode == DetectUintModeNegBitmask);
706  FAIL_IF_NOT(de->arg1 == (TH_ECN | TH_CWR));
707  FAIL_IF_NOT(de->arg2 == 0);
708 
709  SigMatch *sm = SigMatchAlloc();
710  FAIL_IF_NULL(sm);
711  sm->type = DETECT_FLAGS;
712  sm->ctx = (SigMatchCtx *)de;
713 
714  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
715 
716  FAIL_IF_NOT(ret == 1);
717 
718  SigMatchFree(NULL, sm);
719  PacketFree(p);
720  PASS;
721 }
722 
723 /**
724  * \test Negative test.
725  */
726 static int FlagsTestParse17(void)
727 {
728  ThreadVars tv;
729  IPV4Hdr ipv4h;
730  TCPHdr tcph;
731 
732  memset(&tv, 0, sizeof(ThreadVars));
733  memset(&ipv4h, 0, sizeof(IPV4Hdr));
734  memset(&tcph, 0, sizeof(TCPHdr));
735 
737  FAIL_IF_NULL(p);
738  UTHSetIPV4Hdr(p, &ipv4h);
739  tcph.th_flags = TH_ECN | TH_SYN | TH_RST;
740  UTHSetTCPHdr(p, &tcph);
741 
742  DetectU8Data *de = SCDetectTcpFlagsParse("EC+");
743  FAIL_IF_NULL(de);
744  FAIL_IF_NOT(de->mode == DetectUintModeBitmask);
745  FAIL_IF_NOT(de->arg1 == (TH_ECN | TH_CWR));
746  FAIL_IF_NOT(de->arg2 == (TH_ECN | TH_CWR));
747 
748  SigMatch *sm = SigMatchAlloc();
749  FAIL_IF_NULL(sm);
750  sm->type = DETECT_FLAGS;
751  sm->ctx = (SigMatchCtx *)de;
752 
753  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
754  FAIL_IF_NOT(ret == 0);
755 
756  SigMatchFree(NULL, sm);
757  PacketFree(p);
758  PASS;
759 }
760 
761 /**
762  * \brief this function registers unit tests for Flags
763  */
764 static void FlagsRegisterTests(void)
765 {
766  UtRegisterTest("FlagsTestParse03", FlagsTestParse03);
767  UtRegisterTest("FlagsTestParse04", FlagsTestParse04);
768  UtRegisterTest("FlagsTestParse05", FlagsTestParse05);
769  UtRegisterTest("FlagsTestParse06", FlagsTestParse06);
770  UtRegisterTest("FlagsTestParse07", FlagsTestParse07);
771  UtRegisterTest("FlagsTestParse08", FlagsTestParse08);
772  UtRegisterTest("FlagsTestParse09", FlagsTestParse09);
773  UtRegisterTest("FlagsTestParse10", FlagsTestParse10);
774  UtRegisterTest("FlagsTestParse11", FlagsTestParse11);
775  UtRegisterTest("FlagsTestParse12", FlagsTestParse12);
776  UtRegisterTest("FlagsTestParse15", FlagsTestParse15);
777  UtRegisterTest("FlagsTestParse16", FlagsTestParse16);
778  UtRegisterTest("FlagsTestParse17", FlagsTestParse17);
779 }
780 #endif /* UNITTESTS */
detect-tcp-flags.h
detect-engine-uint.h
SigTableElmt_::url
const char * url
Definition: detect.h:1545
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SIG_MASK_REQUIRE_REAL_PKT
#define SIG_MASK_REQUIRE_REAL_PKT
Definition: detect.h:320
DetectFlagsSignatureNeedsSynOnlyPackets
int DetectFlagsSignatureNeedsSynOnlyPackets(const Signature *s)
Definition: detect-tcp-flags.c:169
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:666
SigTableElmt_::desc
const char * desc
Definition: detect.h:1544
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:78
SigMatchFree
void SigMatchFree(DetectEngineCtx *de_ctx, SigMatch *sm)
free a SigMatch
Definition: detect-parse.c:325
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1529
SigTableElmt_::name
const char * name
Definition: detect.h:1542
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1364
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1730
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:101
SigTableElmt_::flags
uint32_t flags
Definition: detect.h:1533
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
TH_RST
#define TH_RST
Definition: decode-tcp.h:36
SIGMATCH_INFO_UINT8
#define SIGMATCH_INFO_UINT8
Definition: detect-engine-register.h:342
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1429
UTHSetIPV4Hdr
void UTHSetIPV4Hdr(Packet *p, IPV4Hdr *ip4h)
Definition: util-unittest-helper.c:251
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:995
DetectFlagsSignatureNeedsSynPackets
int DetectFlagsSignatureNeedsSynPackets(const Signature *s)
Definition: detect-tcp-flags.c:150
PrefilterPacketHeaderValue::u8
uint8_t u8[16]
Definition: detect-engine-prefilter-common.h:24
rust.h
UTHSetTCPHdr
void UTHSetTCPHdr(Packet *p, TCPHdr *tcph)
Definition: util-unittest-helper.c:261
p
Packet * p
Definition: fuzz_dataset.c:30
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1524
detect-engine-prefilter.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
SigTableElmt_::SetupPrefilter
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1527
PrefilterPacketHeaderCtx_
Definition: detect-engine-prefilter-common.h:35
TCPHdr_::th_flags
uint8_t th_flags
Definition: decode-tcp.h:155
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
DetectEngineThreadCtx_
Definition: detect.h:1316
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
SCSigMatchAppendSMToList
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:424
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:364
PacketFree
void PacketFree(Packet *p)
Return a malloced packet.
Definition: decode.c:221
DetectU8Data
DetectUintData_u8 DetectU8Data
Definition: detect-engine-uint.h:43
TH_ACK
#define TH_ACK
Definition: decode-tcp.h:38
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:118
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:363
SCReturn
#define SCReturn
Definition: util-debug.h:286
Signature_::flags
uint32_t flags
Definition: detect.h:693
Packet_
Definition: decode.h:516
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:775
TH_ECN
#define TH_ECN
Definition: decode-tcp.h:41
PrefilterSetupPacketHeader
int PrefilterSetupPacketHeader(DetectEngineCtx *de_ctx, SigGroupHead *sgh, int sm_type, SignatureMask mask, void(*Set)(PrefilterPacketHeaderValue *v, void *), bool(*Compare)(PrefilterPacketHeaderValue v, void *), void(*Match)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx))
Definition: detect-engine-prefilter-common.c:470
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1504
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:311
TH_URG
#define TH_URG
Definition: decode-tcp.h:39
decode-events.h
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:355
IPV4Hdr_
Definition: decode-ipv4.h:72
TH_PUSH
#define TH_PUSH
Definition: decode-tcp.h:37
DetectU8Match
int DetectU8Match(const uint8_t parg, const DetectUintData_u8 *du8)
Definition: detect-engine-uint.c:71
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
TH_SYN
#define TH_SYN
Definition: decode-tcp.h:35
flags
uint8_t flags
Definition: decode-gre.h:0
SigTableElmt_::alias
const char * alias
Definition: detect.h:1543
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:361
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:34
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:260
SIGMATCH_INFO_BITFLAGS_UINT
#define SIGMATCH_INFO_BITFLAGS_UINT
Definition: detect-engine-register.h:358
DetectFlagsRegister
void DetectFlagsRegister(void)
Registration function for flags: keyword.
Definition: detect-tcp-flags.c:60
SigTableElmt_::SupportsPrefilter
bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1526
detect-parse.h
Signature_
Signature container.
Definition: detect.h:692
SigMatch_
a single match condition for a signature
Definition: detect.h:360
TH_CWR
#define TH_CWR
Definition: decode-tcp.h:43
SIGMATCH_SUPPORT_FIREWALL
#define SIGMATCH_SUPPORT_FIREWALL
Definition: detect-engine-register.h:336
suricata.h
PrefilterPacketHeaderValue
Definition: detect-engine-prefilter-common.h:23
detect-engine-prefilter-common.h
DETECT_FLAGS
@ DETECT_FLAGS
Definition: detect-engine-register.h:42
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
flow-var.h
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
TCPHdr_
Definition: decode-tcp.h:149
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1531
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:257