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