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