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