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  return PrefilterIsPrefilterableById(s, DETECT_FLAGS);
242 }
243 
244 /*
245  * ONLY TESTS BELOW THIS COMMENT
246  */
247 
248 #ifdef UNITTESTS
249 /**
250  * \test FlagsTestParse03 test if ACK and PUSH are set. Must return success
251  *
252  * \retval 1 on success
253  * \retval 0 on failure
254  */
255 static int FlagsTestParse03 (void)
256 {
257  ThreadVars tv;
258  IPV4Hdr ipv4h;
259  TCPHdr tcph;
260 
261  memset(&tv, 0, sizeof(ThreadVars));
262  memset(&ipv4h, 0, sizeof(IPV4Hdr));
263  memset(&tcph, 0, sizeof(TCPHdr));
264 
265  Packet *p = PacketGetFromAlloc();
266  FAIL_IF_NULL(p);
267  UTHSetIPV4Hdr(p, &ipv4h);
268  tcph.th_flags = TH_ACK | TH_PUSH | TH_SYN | TH_RST;
269  UTHSetTCPHdr(p, &tcph);
270 
271  DetectU8Data *de = SCDetectTcpFlagsParse("AP+");
272  FAIL_IF_NULL(de);
273  FAIL_IF(de->mode != DetectUintModeBitmask);
274  FAIL_IF(de->arg1 != (TH_ACK | TH_PUSH));
275  FAIL_IF(de->arg2 != (TH_ACK | TH_PUSH));
276 
277  SigMatch *sm = SigMatchAlloc();
278  FAIL_IF_NULL(sm);
279  sm->type = DETECT_FLAGS;
280  sm->ctx = (SigMatchCtx *)de;
281 
282  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
283  FAIL_IF_NOT(ret == 1);
284 
285  SigMatchFree(NULL, sm);
286  PacketFree(p);
287  PASS;
288 }
289 
290 /**
291  * \test FlagsTestParse04 check if ACK bit is set. Must fails.
292  *
293  * \retval 1 on success
294  * \retval 0 on failure
295  */
296 static int FlagsTestParse04 (void)
297 {
298  ThreadVars tv;
299  IPV4Hdr ipv4h;
300  TCPHdr tcph;
301 
302  memset(&tv, 0, sizeof(ThreadVars));
303  memset(&ipv4h, 0, sizeof(IPV4Hdr));
304  memset(&tcph, 0, sizeof(TCPHdr));
305 
306  Packet *p = PacketGetFromAlloc();
307  FAIL_IF_NULL(p);
308  UTHSetIPV4Hdr(p, &ipv4h);
309  tcph.th_flags = TH_SYN;
310  UTHSetTCPHdr(p, &tcph);
311 
312  DetectU8Data *de = SCDetectTcpFlagsParse("A");
313  FAIL_IF_NULL(de);
314  FAIL_IF(de->mode != DetectUintModeBitmask);
315  FAIL_IF(de->arg1 != 0xFF);
316  FAIL_IF(de->arg2 != TH_ACK);
317 
318  SigMatch *sm = SigMatchAlloc();
319  FAIL_IF_NULL(sm);
320  sm->type = DETECT_FLAGS;
321  sm->ctx = (SigMatchCtx *)de;
322 
323  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
324  FAIL_IF_NOT(ret == 0);
325 
326  SigMatchFree(NULL, sm);
327  PacketFree(p);
328  PASS;
329 }
330 
331 /**
332  * \test FlagsTestParse05 test if ACK+PUSH and no other flags are set. Ignore SYN and RST bits.
333  * \retval 1 on success
334  * \retval 0 on failure
335  */
336 static int FlagsTestParse05 (void)
337 {
338  ThreadVars tv;
339  IPV4Hdr ipv4h;
340  TCPHdr tcph;
341 
342  memset(&tv, 0, sizeof(ThreadVars));
343  memset(&ipv4h, 0, sizeof(IPV4Hdr));
344  memset(&tcph, 0, sizeof(TCPHdr));
345 
346  Packet *p = PacketGetFromAlloc();
347  FAIL_IF_NULL(p);
348  UTHSetIPV4Hdr(p, &ipv4h);
349  tcph.th_flags = TH_ACK | TH_PUSH | TH_SYN | TH_RST;
350  UTHSetTCPHdr(p, &tcph);
351 
352  DetectU8Data *de = SCDetectTcpFlagsParse("AP,SR");
353  FAIL_IF_NULL(de);
354  FAIL_IF(de->mode != DetectUintModeBitmask);
355  FAIL_IF(de->arg1 != (uint8_t) ~(TH_SYN | TH_RST));
356  FAIL_IF(de->arg2 != (TH_ACK | TH_PUSH));
357 
358  SigMatch *sm = SigMatchAlloc();
359  FAIL_IF_NULL(sm);
360  sm->type = DETECT_FLAGS;
361  sm->ctx = (SigMatchCtx *)de;
362 
363  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
364  FAIL_IF_NOT(ret == 1);
365 
366  SigMatchFree(NULL, sm);
367  PacketFree(p);
368  PASS;
369 }
370 
371 /**
372  * \test FlagsTestParse06 test if ACK+PUSH and no other flags are set. Ignore URG and RST bits.
373  * Must fail as TH_SYN is also set
374  * \retval 1 on success
375  * \retval 0 on failure
376  */
377 static int FlagsTestParse06 (void)
378 {
379  ThreadVars tv;
380  IPV4Hdr ipv4h;
381  TCPHdr tcph;
382 
383  memset(&tv, 0, sizeof(ThreadVars));
384  memset(&ipv4h, 0, sizeof(IPV4Hdr));
385  memset(&tcph, 0, sizeof(TCPHdr));
386 
387  Packet *p = PacketGetFromAlloc();
388  FAIL_IF_NULL(p);
389  UTHSetIPV4Hdr(p, &ipv4h);
390  tcph.th_flags = TH_ACK | TH_PUSH | TH_SYN | TH_RST;
391  UTHSetTCPHdr(p, &tcph);
392 
393  DetectU8Data *de = SCDetectTcpFlagsParse("AP,UR");
394  FAIL_IF_NULL(de);
395  FAIL_IF(de->mode != DetectUintModeBitmask);
396  FAIL_IF(de->arg1 != (uint8_t) ~(TH_URG | TH_RST));
397  FAIL_IF(de->arg2 != (TH_ACK | TH_PUSH));
398 
399  SigMatch *sm = SigMatchAlloc();
400  FAIL_IF_NULL(sm);
401  sm->type = DETECT_FLAGS;
402  sm->ctx = (SigMatchCtx *)de;
403 
404  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
405  FAIL_IF_NOT(ret == 0);
406 
407  SigMatchFree(NULL, sm);
408  PacketFree(p);
409  PASS;
410 }
411 
412 /**
413  * \test FlagsTestParse07 test if SYN or RST are set. Must fails.
414  *
415  * \retval 1 on success
416  * \retval 0 on failure
417  */
418 static int FlagsTestParse07 (void)
419 {
420  ThreadVars tv;
421  IPV4Hdr ipv4h;
422  TCPHdr tcph;
423 
424  memset(&tv, 0, sizeof(ThreadVars));
425  memset(&ipv4h, 0, sizeof(IPV4Hdr));
426  memset(&tcph, 0, sizeof(TCPHdr));
427 
428  Packet *p = PacketGetFromAlloc();
429  FAIL_IF_NULL(p);
430  UTHSetIPV4Hdr(p, &ipv4h);
431  tcph.th_flags = TH_SYN | TH_RST;
432  UTHSetTCPHdr(p, &tcph);
433 
434  DetectU8Data *de = SCDetectTcpFlagsParse("*AP");
435  FAIL_IF_NULL(de);
436  FAIL_IF(de->mode != DetectUintModeNegBitmask);
437  FAIL_IF(de->arg1 != (TH_ACK | TH_PUSH));
438  FAIL_IF(de->arg2 != 0);
439 
440  SigMatch *sm = SigMatchAlloc();
441  FAIL_IF_NULL(sm);
442  sm->type = DETECT_FLAGS;
443  sm->ctx = (SigMatchCtx *)de;
444 
445  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
446  FAIL_IF_NOT(ret == 0);
447 
448  SigMatchFree(NULL, sm);
449  PacketFree(p);
450  PASS;
451 }
452 
453 /**
454  * \test FlagsTestParse08 test if SYN or RST are set. Must return success.
455  *
456  * \retval 1 on success
457  * \retval 0 on failure
458  */
459 static int FlagsTestParse08 (void)
460 {
461  ThreadVars tv;
462  IPV4Hdr ipv4h;
463  TCPHdr tcph;
464 
465  memset(&tv, 0, sizeof(ThreadVars));
466  memset(&ipv4h, 0, sizeof(IPV4Hdr));
467  memset(&tcph, 0, sizeof(TCPHdr));
468 
469  Packet *p = PacketGetFromAlloc();
470  FAIL_IF_NULL(p);
471  UTHSetIPV4Hdr(p, &ipv4h);
472  tcph.th_flags = TH_SYN | TH_RST;
473  UTHSetTCPHdr(p, &tcph);
474 
475  DetectU8Data *de = SCDetectTcpFlagsParse("*SA");
476  FAIL_IF_NULL(de);
477  FAIL_IF(de->mode != DetectUintModeNegBitmask);
478  FAIL_IF(de->arg1 != (TH_ACK | TH_SYN));
479 
480  SigMatch *sm = SigMatchAlloc();
481  FAIL_IF_NULL(sm);
482  sm->type = DETECT_FLAGS;
483  sm->ctx = (SigMatchCtx *)de;
484 
485  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
486  FAIL_IF_NOT(ret == 1);
487 
488  SigMatchFree(NULL, sm);
489  PacketFree(p);
490  PASS;
491 }
492 
493 /**
494  * \test FlagsTestParse09 test if SYN and RST are not set. Must fails.
495  *
496  * \retval 1 on success
497  * \retval 0 on failure
498  */
499 static int FlagsTestParse09 (void)
500 {
501  ThreadVars tv;
502  IPV4Hdr ipv4h;
503  TCPHdr tcph;
504 
505  memset(&tv, 0, sizeof(ThreadVars));
506  memset(&ipv4h, 0, sizeof(IPV4Hdr));
507  memset(&tcph, 0, sizeof(TCPHdr));
508 
509  Packet *p = PacketGetFromAlloc();
510  FAIL_IF_NULL(p);
511  UTHSetIPV4Hdr(p, &ipv4h);
512  tcph.th_flags = TH_SYN | TH_RST;
513  UTHSetTCPHdr(p, &tcph);
514 
515  DetectU8Data *de = SCDetectTcpFlagsParse("!PA");
516  FAIL_IF_NULL(de);
517  FAIL_IF(de->mode != DetectUintModeNegBitmask);
518  FAIL_IF(de->arg1 != (TH_ACK | TH_PUSH));
519  FAIL_IF(de->arg2 != (TH_ACK | TH_PUSH));
520 
521  SigMatch *sm = SigMatchAlloc();
522  FAIL_IF_NULL(sm);
523  sm->type = DETECT_FLAGS;
524  sm->ctx = (SigMatchCtx *)de;
525 
526  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
527  FAIL_IF_NOT(ret == 1);
528 
529  SigMatchFree(NULL, sm);
530  PacketFree(p);
531  PASS;
532 }
533 
534 /**
535  * \test FlagsTestParse10 test if ACK and PUSH are not set. Must return success.
536  *
537  * \retval 1 on success
538  * \retval 0 on failure
539  */
540 static int FlagsTestParse10 (void)
541 {
542  ThreadVars tv;
543  IPV4Hdr ipv4h;
544  TCPHdr tcph;
545 
546  memset(&tv, 0, sizeof(ThreadVars));
547  memset(&ipv4h, 0, sizeof(IPV4Hdr));
548  memset(&tcph, 0, sizeof(TCPHdr));
549 
550  Packet *p = PacketGetFromAlloc();
551  FAIL_IF_NULL(p);
552  UTHSetIPV4Hdr(p, &ipv4h);
553  tcph.th_flags = TH_SYN | TH_RST;
554  UTHSetTCPHdr(p, &tcph);
555 
556  DetectU8Data *de = SCDetectTcpFlagsParse("!AP");
557  FAIL_IF_NULL(de);
558 
559  FAIL_IF(de->mode != DetectUintModeNegBitmask);
560  FAIL_IF(de->arg1 != (TH_ACK | TH_PUSH));
561 
562  SigMatch *sm = SigMatchAlloc();
563  FAIL_IF_NULL(sm);
564  sm->type = DETECT_FLAGS;
565  sm->ctx = (SigMatchCtx *)de;
566 
567  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
568  FAIL_IF_NOT(ret == 1);
569 
570  SigMatchFree(NULL, sm);
571  PacketFree(p);
572  PASS;
573 }
574 
575 /**
576  * \test FlagsTestParse11 test if flags are ACK and PUSH. Ignore SYN and RST.
577  *
578  * \retval 1 on success
579  * \retval 0 on failure
580  */
581 static int FlagsTestParse11 (void)
582 {
583  ThreadVars tv;
584  IPV4Hdr ipv4h;
585  TCPHdr tcph;
586 
587  memset(&tv, 0, sizeof(ThreadVars));
588  memset(&ipv4h, 0, sizeof(IPV4Hdr));
589  memset(&tcph, 0, sizeof(TCPHdr));
590 
591  Packet *p = PacketGetFromAlloc();
592  FAIL_IF_NULL(p);
593  UTHSetIPV4Hdr(p, &ipv4h);
594  tcph.th_flags = TH_SYN | TH_RST | TH_URG;
595  UTHSetTCPHdr(p, &tcph);
596 
597  DetectU8Data *de = SCDetectTcpFlagsParse("AP,SR");
598  FAIL_IF_NULL(de);
599  FAIL_IF(de->mode != DetectUintModeBitmask);
600  FAIL_IF(de->arg1 != (uint8_t) ~(TH_SYN | TH_RST));
601  FAIL_IF(de->arg2 != (TH_ACK | TH_PUSH));
602 
603  SigMatch *sm = SigMatchAlloc();
604  FAIL_IF_NULL(de);
605  sm->type = DETECT_FLAGS;
606  sm->ctx = (SigMatchCtx *)de;
607 
608  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
609  FAIL_IF_NOT(ret == 0);
610 
611  SigMatchFree(NULL, sm);
612  PacketFree(p);
613  PASS;
614 }
615 
616 /**
617  * \test FlagsTestParse12 check if no flags are set. Must fail.
618  *
619  * \retval 1 on success
620  * \retval 0 on failure
621  */
622 static int FlagsTestParse12 (void)
623 {
624  ThreadVars tv;
625  IPV4Hdr ipv4h;
626  TCPHdr tcph;
627 
628  memset(&tv, 0, sizeof(ThreadVars));
629  memset(&ipv4h, 0, sizeof(IPV4Hdr));
630  memset(&tcph, 0, sizeof(TCPHdr));
631 
632  Packet *p = PacketGetFromAlloc();
633  FAIL_IF_NULL(p);
634  UTHSetIPV4Hdr(p, &ipv4h);
635  tcph.th_flags = TH_SYN;
636  UTHSetTCPHdr(p, &tcph);
637 
638  DetectU8Data *de = SCDetectTcpFlagsParse("0");
639  FAIL_IF_NULL(de);
640  FAIL_IF_NOT(de->mode == DetectUintModeEqual);
641  FAIL_IF_NOT(de->arg1 == 0);
642 
643  SigMatch *sm = SigMatchAlloc();
644  FAIL_IF_NULL(sm);
645  sm->type = DETECT_FLAGS;
646  sm->ctx = (SigMatchCtx *)de;
647 
648  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
649  FAIL_IF_NOT(ret == 0);
650 
651  SigMatchFree(NULL, sm);
652  PacketFree(p);
653  PASS;
654 }
655 
656 static int FlagsTestParse15(void)
657 {
658  ThreadVars tv;
659  IPV4Hdr ipv4h;
660  TCPHdr tcph;
661 
662  memset(&tv, 0, sizeof(ThreadVars));
663  memset(&ipv4h, 0, sizeof(IPV4Hdr));
664  memset(&tcph, 0, sizeof(TCPHdr));
665 
666  Packet *p = PacketGetFromAlloc();
667  FAIL_IF_NULL(p);
668  UTHSetIPV4Hdr(p, &ipv4h);
669  tcph.th_flags = TH_ECN | TH_CWR | TH_SYN | TH_RST;
670  UTHSetTCPHdr(p, &tcph);
671 
672  DetectU8Data *de = SCDetectTcpFlagsParse("EC+");
673  FAIL_IF_NULL(de);
674  FAIL_IF_NOT(de->mode == DetectUintModeBitmask);
675  FAIL_IF_NOT(de->arg1 == (TH_ECN | TH_CWR));
676  FAIL_IF_NOT(de->arg2 == (TH_ECN | TH_CWR));
677 
678  SigMatch *sm = SigMatchAlloc();
679  FAIL_IF_NULL(sm);
680  sm->type = DETECT_FLAGS;
681  sm->ctx = (SigMatchCtx *)de;
682 
683  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
684  FAIL_IF_NOT(ret == 1);
685 
686  SigMatchFree(NULL, sm);
687  PacketFree(p);
688  PASS;
689 }
690 
691 static int FlagsTestParse16(void)
692 {
693  ThreadVars tv;
694  IPV4Hdr ipv4h;
695  TCPHdr tcph;
696 
697  memset(&tv, 0, sizeof(ThreadVars));
698  memset(&ipv4h, 0, sizeof(IPV4Hdr));
699  memset(&tcph, 0, sizeof(TCPHdr));
700 
701  Packet *p = PacketGetFromAlloc();
702  FAIL_IF_NULL(p);
703  UTHSetIPV4Hdr(p, &ipv4h);
704  tcph.th_flags = TH_ECN | TH_SYN | TH_RST;
705  UTHSetTCPHdr(p, &tcph);
706 
707  DetectU8Data *de = SCDetectTcpFlagsParse("EC*");
708  FAIL_IF_NULL(de);
709  FAIL_IF_NOT(de->mode == DetectUintModeNegBitmask);
710  FAIL_IF_NOT(de->arg1 == (TH_ECN | TH_CWR));
711  FAIL_IF_NOT(de->arg2 == 0);
712 
713  SigMatch *sm = SigMatchAlloc();
714  FAIL_IF_NULL(sm);
715  sm->type = DETECT_FLAGS;
716  sm->ctx = (SigMatchCtx *)de;
717 
718  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
719 
720  FAIL_IF_NOT(ret == 1);
721 
722  SigMatchFree(NULL, sm);
723  PacketFree(p);
724  PASS;
725 }
726 
727 /**
728  * \test Negative test.
729  */
730 static int FlagsTestParse17(void)
731 {
732  ThreadVars tv;
733  IPV4Hdr ipv4h;
734  TCPHdr tcph;
735 
736  memset(&tv, 0, sizeof(ThreadVars));
737  memset(&ipv4h, 0, sizeof(IPV4Hdr));
738  memset(&tcph, 0, sizeof(TCPHdr));
739 
740  Packet *p = PacketGetFromAlloc();
741  FAIL_IF_NULL(p);
742  UTHSetIPV4Hdr(p, &ipv4h);
743  tcph.th_flags = TH_ECN | TH_SYN | TH_RST;
744  UTHSetTCPHdr(p, &tcph);
745 
746  DetectU8Data *de = SCDetectTcpFlagsParse("EC+");
747  FAIL_IF_NULL(de);
748  FAIL_IF_NOT(de->mode == DetectUintModeBitmask);
749  FAIL_IF_NOT(de->arg1 == (TH_ECN | TH_CWR));
750  FAIL_IF_NOT(de->arg2 == (TH_ECN | TH_CWR));
751 
752  SigMatch *sm = SigMatchAlloc();
753  FAIL_IF_NULL(sm);
754  sm->type = DETECT_FLAGS;
755  sm->ctx = (SigMatchCtx *)de;
756 
757  int ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
758  FAIL_IF_NOT(ret == 0);
759 
760  SigMatchFree(NULL, sm);
761  PacketFree(p);
762  PASS;
763 }
764 
765 /**
766  * \brief this function registers unit tests for Flags
767  */
768 static void FlagsRegisterTests(void)
769 {
770  UtRegisterTest("FlagsTestParse03", FlagsTestParse03);
771  UtRegisterTest("FlagsTestParse04", FlagsTestParse04);
772  UtRegisterTest("FlagsTestParse05", FlagsTestParse05);
773  UtRegisterTest("FlagsTestParse06", FlagsTestParse06);
774  UtRegisterTest("FlagsTestParse07", FlagsTestParse07);
775  UtRegisterTest("FlagsTestParse08", FlagsTestParse08);
776  UtRegisterTest("FlagsTestParse09", FlagsTestParse09);
777  UtRegisterTest("FlagsTestParse10", FlagsTestParse10);
778  UtRegisterTest("FlagsTestParse11", FlagsTestParse11);
779  UtRegisterTest("FlagsTestParse12", FlagsTestParse12);
780  UtRegisterTest("FlagsTestParse15", FlagsTestParse15);
781  UtRegisterTest("FlagsTestParse16", FlagsTestParse16);
782  UtRegisterTest("FlagsTestParse17", FlagsTestParse17);
783 }
784 #endif /* UNITTESTS */
detect-tcp-flags.h
detect-engine-uint.h
SigTableElmt_::url
const char * url
Definition: detect.h:1461
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:1460
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:1445
SigTableElmt_::name
const char * name
Definition: detect.h:1458
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:1628
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:1449
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
TH_RST
#define TH_RST
Definition: decode-tcp.h:36
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1348
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:933
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:1681
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1440
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:1443
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:19
DetectEngineThreadCtx_
Definition: detect.h:1245
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: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:223
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:286
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:1699
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:1420
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:1459
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:357
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:33
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:262
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:1442
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:1687
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:102
TCPHdr_
Definition: decode-tcp.h:149
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1447
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:254