suricata
detect-dsize.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 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 Victor Julien <victor@inliniac.net>
22  *
23  * Implements the dsize keyword
24  */
25 
26 #include "suricata-common.h"
27 #include "decode.h"
28 
29 #include "detect.h"
30 #include "detect-parse.h"
32 
33 #include "flow-var.h"
34 
35 #include "detect-content.h"
36 #include "detect-dsize.h"
37 
38 #include "util-unittest.h"
39 #include "util-debug.h"
40 #include "util-byte.h"
41 
42 #include "pkt-var.h"
43 #include "host.h"
44 #include "util-profiling.h"
45 
46 /**
47  * dsize:[<>!]<0-65535>[<><0-65535>];
48  */
49 #define PARSE_REGEX "^\\s*(<|>|!)?\\s*([0-9]{1,5})\\s*(?:(<>)\\s*([0-9]{1,5}))?\\s*$"
50 static DetectParseRegex parse_regex;
51 
52 static int DetectDsizeMatch (DetectEngineThreadCtx *, Packet *,
53  const Signature *, const SigMatchCtx *);
54 static int DetectDsizeSetup (DetectEngineCtx *, Signature *s, const char *str);
55 #ifdef UNITTESTS
56 static void DsizeRegisterTests(void);
57 #endif
58 static void DetectDsizeFree(DetectEngineCtx *, void *);
59 
60 static int PrefilterSetupDsize(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
61 static bool PrefilterDsizeIsPrefilterable(const Signature *s);
62 
63 /**
64  * \brief Registration function for dsize: keyword
65  */
67 {
68  sigmatch_table[DETECT_DSIZE].name = "dsize";
69  sigmatch_table[DETECT_DSIZE].desc = "match on the size of the packet payload";
70  sigmatch_table[DETECT_DSIZE].url = "/rules/payload-keywords.html#dsize";
71  sigmatch_table[DETECT_DSIZE].Match = DetectDsizeMatch;
72  sigmatch_table[DETECT_DSIZE].Setup = DetectDsizeSetup;
73  sigmatch_table[DETECT_DSIZE].Free = DetectDsizeFree;
74 #ifdef UNITTESTS
75  sigmatch_table[DETECT_DSIZE].RegisterTests = DsizeRegisterTests;
76 #endif
77  sigmatch_table[DETECT_DSIZE].SupportsPrefilter = PrefilterDsizeIsPrefilterable;
78  sigmatch_table[DETECT_DSIZE].SetupPrefilter = PrefilterSetupDsize;
79 
80  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
81 }
82 
83 static inline int
84 DsizeMatch(const uint16_t psize, const uint8_t mode,
85  const uint16_t dsize, const uint16_t dsize2)
86 {
87  if (mode == DETECTDSIZE_EQ && dsize == psize)
88  return 1;
89  else if (mode == DETECTDSIZE_LT && psize < dsize)
90  return 1;
91  else if (mode == DETECTDSIZE_GT && psize > dsize)
92  return 1;
93  else if (mode == DETECTDSIZE_RA && psize > dsize && psize < dsize2)
94  return 1;
95  else if (mode == DETECTDSIZE_NE && dsize != psize)
96  return 1;
97 
98  return 0;
99 }
100 
101 /**
102  * \internal
103  * \brief This function is used to match flags on a packet with those passed via dsize:
104  *
105  * \param t pointer to thread vars
106  * \param det_ctx pointer to the pattern matcher thread
107  * \param p pointer to the current packet
108  * \param s pointer to the Signature
109  * \param m pointer to the sigmatch
110  *
111  * \retval 0 no match
112  * \retval 1 match
113  */
114 static int DetectDsizeMatch (DetectEngineThreadCtx *det_ctx, Packet *p,
115  const Signature *s, const SigMatchCtx *ctx)
116 {
117  SCEnter();
118  int ret = 0;
119 
120  if (PKT_IS_PSEUDOPKT(p)) {
121  SCReturnInt(0);
122  }
123 
124  const DetectDsizeData *dd = (const DetectDsizeData *)ctx;
125 
126  SCLogDebug("p->payload_len %"PRIu16"", p->payload_len);
127 
128  ret = DsizeMatch(p->payload_len, dd->mode, dd->dsize, dd->dsize2);
129 
130  SCReturnInt(ret);
131 }
132 
133 /**
134  * \internal
135  * \brief This function is used to parse dsize options passed via dsize: keyword
136  *
137  * \param rawstr Pointer to the user provided dsize options
138  *
139  * \retval dd pointer to DetectDsizeData on success
140  * \retval NULL on failure
141  */
142 static DetectDsizeData *DetectDsizeParse (const char *rawstr)
143 {
144  DetectDsizeData *dd = NULL;
145  int ret = 0, res = 0;
146  size_t pcre2len;
147  char mode[2] = "";
148  char value1[6] = "";
149  char value2[6] = "";
150  char range[3] = "";
151 
152  ret = DetectParsePcreExec(&parse_regex, rawstr, 0, 0);
153  if (ret < 3 || ret > 5) {
154  SCLogError(SC_ERR_PCRE_MATCH,"Parse error %s", rawstr);
155  goto error;
156  }
157 
158  pcre2len = sizeof(mode);
159  res = SC_Pcre2SubstringCopy(parse_regex.match, 1, (PCRE2_UCHAR8 *)mode, &pcre2len);
160  if (res < 0) {
161  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_copy_bynumber failed with %d", res);
162  goto error;
163  }
164  SCLogDebug("mode \"%s\"", mode);
165 
166  pcre2len = sizeof(value1);
167  res = pcre2_substring_copy_bynumber(parse_regex.match, 2, (PCRE2_UCHAR8 *)value1, &pcre2len);
168  if (res < 0) {
169  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_copy_bynumber failed");
170  goto error;
171  }
172  SCLogDebug("value1 \"%s\"", value1);
173 
174  if (ret > 3) {
175  pcre2len = sizeof(range);
176  res = pcre2_substring_copy_bynumber(parse_regex.match, 3, (PCRE2_UCHAR8 *)range, &pcre2len);
177  if (res < 0) {
178  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_copy_bynumber failed");
179  goto error;
180  }
181  SCLogDebug("range \"%s\"", range);
182 
183  if (ret > 4) {
184  pcre2len = sizeof(value2);
185  res = pcre2_substring_copy_bynumber(
186  parse_regex.match, 4, (PCRE2_UCHAR8 *)value2, &pcre2len);
187  if (res < 0) {
188  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_copy_bynumber failed");
189  goto error;
190  }
191  SCLogDebug("value2 \"%s\"", value2);
192  }
193  }
194 
195  dd = SCMalloc(sizeof(DetectDsizeData));
196  if (unlikely(dd == NULL))
197  goto error;
198  dd->dsize = 0;
199  dd->dsize2 = 0;
200  dd->mode = 0;
201 
202  if (strcmp("<>", range) == 0) {
203  if (strlen(mode) != 0) {
204  SCLogError(SC_ERR_INVALID_ARGUMENT,"Range specified but mode also set");
205  goto error;
206  }
207  dd->mode = DETECTDSIZE_RA;
208  } else if (strlen(mode) > 0) {
209  if (mode[0] == '<')
210  dd->mode = DETECTDSIZE_LT;
211  else if (mode[0] == '>')
212  dd->mode = DETECTDSIZE_GT;
213  else if (mode[0] == '!')
214  dd->mode = DETECTDSIZE_NE;
215  else
216  dd->mode = DETECTDSIZE_EQ;
217  } else {
218  dd->mode = DETECTDSIZE_EQ; // default
219  }
220 
221  /** set the first dsize value */
222  if (StringParseUint16(&dd->dsize,10,strlen(value1),value1) <= 0) {
223  SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid size value1:\"%s\"", value1);
224  goto error;
225  }
226 
227  /** set the second dsize value if specified */
228  if (strlen(value2) > 0) {
229  if (dd->mode != DETECTDSIZE_RA) {
230  SCLogError(SC_ERR_INVALID_ARGUMENT,"Multiple dsize values specified but mode is not range");
231  goto error;
232  }
233 
234  if (StringParseUint16(&dd->dsize2,10,strlen(value2),value2) <= 0) {
235  SCLogError(SC_ERR_INVALID_ARGUMENT,"Invalid size value2:\"%s\"",value2);
236  goto error;
237  }
238 
239  if (dd->dsize2 <= dd->dsize) {
240  SCLogError(SC_ERR_INVALID_ARGUMENT,"dsize2:%"PRIu16" <= dsize:%"PRIu16"",dd->dsize2,dd->dsize);
241  goto error;
242  }
243  }
244 
245  SCLogDebug("dsize parsed successfully dsize: %"PRIu16" dsize2: %"PRIu16"",dd->dsize,dd->dsize2);
246  return dd;
247 
248 error:
249  if (dd)
250  SCFree(dd);
251  return NULL;
252 }
253 
254 /**
255  * \internal
256  * \brief this function is used to add the parsed dsize into the current signature
257  *
258  * \param de_ctx pointer to the Detection Engine Context
259  * \param s pointer to the Current Signature
260  * \param rawstr pointer to the user provided flags options
261  *
262  * \retval 0 on Success
263  * \retval -1 on Failure
264  */
265 static int DetectDsizeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
266 {
267  DetectDsizeData *dd = NULL;
268  SigMatch *sm = NULL;
269 
271  SCLogError(SC_ERR_INVALID_SIGNATURE, "Can't use 2 or more dsizes in "
272  "the same sig. Invalidating signature.");
273  goto error;
274  }
275 
276  SCLogDebug("\'%s\'", rawstr);
277 
278  dd = DetectDsizeParse(rawstr);
279  if (dd == NULL) {
280  SCLogError(SC_ERR_INVALID_ARGUMENT,"Parsing \'%s\' failed", rawstr);
281  goto error;
282  }
283 
284  /* Okay so far so good, lets get this into a SigMatch
285  * and put it in the Signature. */
286  sm = SigMatchAlloc();
287  if (sm == NULL){
288  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for SigMatch");
289  SCFree(dd);
290  goto error;
291  }
292 
293  sm->type = DETECT_DSIZE;
294  sm->ctx = (SigMatchCtx *)dd;
295 
297 
298  SCLogDebug("dd->dsize %"PRIu16", dd->dsize2 %"PRIu16", dd->mode %"PRIu8"",
299  dd->dsize, dd->dsize2, dd->mode);
300  /* tell the sig it has a dsize to speed up engine init */
302  s->flags |= SIG_FLAG_DSIZE;
303 
304  if (s->init_data->dsize_sm == NULL) {
305  s->init_data->dsize_sm = sm;
306  }
307 
308  return 0;
309 
310 error:
311  return -1;
312 }
313 
314 /**
315  * \internal
316  * \brief this function will free memory associated with DetectDsizeData
317  *
318  * \param de pointer to DetectDsizeData
319  */
320 void DetectDsizeFree(DetectEngineCtx *de_ctx, void *de_ptr)
321 {
322  DetectDsizeData *dd = (DetectDsizeData *)de_ptr;
323  if(dd) SCFree(dd);
324 }
325 
326 /* prefilter code */
327 
328 static void
329 PrefilterPacketDsizeMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
330 {
331  if (PKT_IS_PSEUDOPKT(p)) {
332  SCReturn;
333  }
334 
335  const PrefilterPacketHeaderCtx *ctx = pectx;
336  if (!PrefilterPacketHeaderExtraMatch(ctx, p))
337  return;
338 
339  const uint16_t dsize = p->payload_len;
340  if (DsizeMatch(dsize, ctx->v1.u8[0], ctx->v1.u16[1], ctx->v1.u16[2]))
341  {
342  SCLogDebug("packet matches dsize %u", dsize);
343  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
344  }
345 }
346 
347 static void
348 PrefilterPacketDsizeSet(PrefilterPacketHeaderValue *v, void *smctx)
349 {
350  const DetectDsizeData *a = smctx;
351  v->u8[0] = a->mode;
352  v->u16[1] = a->dsize;
353  v->u16[2] = a->dsize2;
354 }
355 
356 static bool
357 PrefilterPacketDsizeCompare(PrefilterPacketHeaderValue v, void *smctx)
358 {
359  const DetectDsizeData *a = smctx;
360  if (v.u8[0] == a->mode &&
361  v.u16[1] == a->dsize &&
362  v.u16[2] == a->dsize2)
363  return true;
364  return false;
365 }
366 
367 static int PrefilterSetupDsize(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
368 {
370  PrefilterPacketDsizeSet,
371  PrefilterPacketDsizeCompare,
372  PrefilterPacketDsizeMatch);
373 }
374 
375 static bool PrefilterDsizeIsPrefilterable(const Signature *s)
376 {
377  const SigMatch *sm;
378  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
379  switch (sm->type) {
380  case DETECT_DSIZE:
381  return true;
382  }
383  }
384  return false;
385 }
386 
387 /** \brief get max dsize "depth"
388  * \param s signature to get dsize value from
389  * \retval depth or negative value
390  */
392 {
393  if (s->flags & SIG_FLAG_DSIZE && s->init_data->dsize_sm != NULL) {
394  const DetectDsizeData *dd = (const DetectDsizeData *)s->init_data->dsize_sm->ctx;
395 
396  switch (dd->mode) {
397  case DETECTDSIZE_LT:
398  case DETECTDSIZE_EQ:
399  case DETECTDSIZE_NE:
400  return dd->dsize;
401  case DETECTDSIZE_RA:
402  return dd->dsize2;
403  case DETECTDSIZE_GT:
404  default:
405  SCReturnInt(-2);
406  }
407  }
408  SCReturnInt(-1);
409 }
410 
411 /** \brief set prefilter dsize pair
412  * \param s signature to get dsize value from
413  */
415 {
416  if (s->flags & SIG_FLAG_DSIZE && s->init_data->dsize_sm != NULL) {
418 
419  uint16_t low = 0;
420  uint16_t high = 65535;
421 
422  switch (dd->mode) {
423  case DETECTDSIZE_LT:
424  low = 0;
425  high = dd->dsize;
426  break;
427  case DETECTDSIZE_EQ:
428  case DETECTDSIZE_NE:
429  low = dd->dsize;
430  high = dd->dsize;
431  break;
432  case DETECTDSIZE_RA:
433  low = dd->dsize;
434  high = dd->dsize2;
435  break;
436  case DETECTDSIZE_GT:
437  low = dd->dsize;
438  high = 65535;
439  break;
440  }
441  s->dsize_mode = dd->mode;
442  s->dsize_low = low;
443  s->dsize_high = high;
444 
445  SCLogDebug("low %u, high %u, mode %u", low, high, dd->mode);
446  }
447 }
448 
449 /**
450  * \brief Apply dsize as depth to content matches in the rule
451  * \param s signature to get dsize value from
452  */
454 {
455  SCEnter();
456 
457  if (s->flags & SIG_FLAG_DSIZE) {
459 
460  int dsize = SigParseGetMaxDsize(s);
461  if (dsize < 0) {
462  /* nothing to do */
463  return;
464  }
465 
467  for ( ; sm != NULL; sm = sm->next) {
468  if (sm->type != DETECT_CONTENT) {
469  continue;
470  }
471 
473  if (cd == NULL) {
474  continue;
475  }
476 
477  if (cd->depth == 0 || cd->depth >= dsize) {
479  cd->depth = (uint16_t)dsize;
480  SCLogDebug("updated %u, content %u to have depth %u "
481  "because of dsize.", s->id, cd->id, cd->depth);
482  }
483  }
484  }
485 }
486 
487 /*
488  * ONLY TESTS BELOW THIS COMMENT
489  */
490 
491 #ifdef UNITTESTS
492 #include "detect-engine.h"
493 
494 /**
495  * \test this is a test for a valid dsize value 1
496  *
497  */
498 static int DsizeTestParse01(void)
499 {
500  DetectDsizeData *dd = DetectDsizeParse("1");
501  FAIL_IF_NULL(dd);
502  FAIL_IF_NOT(dd->dsize == 1);
503  FAIL_IF_NOT(dd->dsize2 == 0);
504 
505  DetectDsizeFree(NULL, dd);
506  PASS;
507 }
508 
509 /**
510  * \test this is a test for a valid dsize value >10
511  *
512  */
513 static int DsizeTestParse02(void)
514 {
515  DetectDsizeData *dd = DetectDsizeParse(">10");
516  FAIL_IF_NULL(dd);
517  FAIL_IF_NOT(dd->dsize == 10);
519  DetectDsizeFree(NULL, dd);
520  PASS;
521 }
522 
523 /**
524  * \test this is a test for a valid dsize value <100
525  *
526  */
527 static int DsizeTestParse03(void)
528 {
529  DetectDsizeData *dd = DetectDsizeParse("<100");
530  FAIL_IF_NULL(dd);
531  FAIL_IF_NOT(dd->dsize == 100);
533 
534  DetectDsizeFree(NULL, dd);
535  PASS;
536 }
537 
538 /**
539  * \test this is a test for a valid dsize value 1<>2
540  *
541  */
542 static int DsizeTestParse04(void)
543 {
544  DetectDsizeData *dd = DetectDsizeParse("1<>2");
545  FAIL_IF_NULL(dd);
546  FAIL_IF_NOT(dd->dsize == 1);
547  FAIL_IF_NOT(dd->dsize2 == 2);
549 
550  DetectDsizeFree(NULL, dd);
551  PASS;
552 }
553 
554 /**
555  * \test this is a test for a valid dsize value 1 <> 2
556  *
557  */
558 static int DsizeTestParse05(void)
559 {
560  DetectDsizeData *dd = DetectDsizeParse(" 1 <> 2 ");
561  FAIL_IF_NULL(dd);
562  FAIL_IF_NOT(dd->dsize == 1);
563  FAIL_IF_NOT(dd->dsize2 == 2);
565 
566  DetectDsizeFree(NULL, dd);
567  PASS;
568 }
569 
570 /**
571  * \test this is test for a valid dsize value > 2
572  *
573  */
574 static int DsizeTestParse06(void)
575 {
576  DetectDsizeData *dd = DetectDsizeParse("> 2 ");
577  FAIL_IF_NULL(dd);
578  FAIL_IF_NOT(dd->dsize == 2);
580 
581  DetectDsizeFree(NULL, dd);
582  PASS;
583 }
584 
585 /**
586  * \test test for a valid dsize value < 12
587  *
588  */
589 static int DsizeTestParse07(void)
590 {
591  DetectDsizeData *dd = DetectDsizeParse("< 12 ");
592  FAIL_IF_NULL(dd);
593  FAIL_IF_NOT(dd->dsize == 12);
595 
596  DetectDsizeFree(NULL, dd);
597  PASS;
598 }
599 
600 /**
601  * \test test for a valid dsize value 12
602  *
603  */
604 static int DsizeTestParse08(void)
605 {
606  DetectDsizeData *dd = DetectDsizeParse(" 12 ");
607  FAIL_IF_NULL(dd);
608  FAIL_IF_NOT(dd->dsize == 12);
610 
611  DetectDsizeFree(NULL, dd);
612  PASS;
613 }
614 
615 /**
616  * \test this is a test for a valid dsize value !1
617  *
618  */
619 static int DsizeTestParse09(void)
620 {
621  DetectDsizeData *dd = DetectDsizeParse("!1");
622  FAIL_IF_NULL(dd);
623  DetectDsizeFree(NULL, dd);
624  PASS;
625 }
626 
627 /**
628  * \test this is a test for a valid dsize value ! 1
629  *
630  */
631 static int DsizeTestParse10(void)
632 {
633  DetectDsizeData *dd = DetectDsizeParse("! 1");
634  FAIL_IF_NULL(dd);
635  DetectDsizeFree(NULL, dd);
636  PASS;
637 }
638 
639 /**
640  * \test this is a test for invalid dsize values
641  * A, >10<>10, <>10, 1<>, "", " ", 2<>1, 1!
642  *
643  */
644 static int DsizeTestParse11(void)
645 {
646  const char *strings[] = { "A", ">10<>10", "<>10", "1<>", "", " ", "2<>1", "1!", NULL };
647  for (int i = 0; strings[i]; i++) {
648  DetectDsizeData *dd = DetectDsizeParse(strings[i]);
649  FAIL_IF_NOT_NULL(dd);
650  }
651 
652  PASS;
653 }
654 
655 /**
656  * \test this is a test for positive ! dsize matching
657  *
658  */
659 static int DsizeTestMatch01(void)
660 {
661  uint16_t psize = 1;
662  uint16_t dsizelow = 2;
663  uint16_t dsizehigh = 0;
664 
665  FAIL_IF_NOT(DsizeMatch(psize, DETECTDSIZE_NE, dsizelow, dsizehigh));
666 
667  PASS;
668 }
669 
670 /**
671  * \test this is a test for negative ! dsize matching
672  *
673  */
674 static int DsizeTestMatch02(void)
675 {
676  uint16_t psize = 1;
677  uint16_t dsizelow = 1;
678  uint16_t dsizehigh = 0;
679 
680  FAIL_IF(DsizeMatch(psize, DETECTDSIZE_NE, dsizelow, dsizehigh));
681 
682  PASS;
683 }
684 
685 /**
686  * \test DetectDsizeIcmpv6Test01 is a test for checking the working of
687  * dsize keyword by creating 2 rules and matching a crafted packet
688  * against them. Only the first one shall trigger.
689  */
690 static int DetectDsizeIcmpv6Test01(void)
691 {
692  static uint8_t raw_icmpv6[] = {
693  0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3a, 0xff,
694  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696  0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
698  0x01, 0x00, 0x7b, 0x85, 0x00, 0x00, 0x00, 0x00,
699  0x60, 0x4b, 0xe8, 0xbd, 0x00, 0x00, 0x3b, 0xff,
700  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702  0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
704 
706  FAIL_IF_NULL(p);
707 
708  IPV6Hdr ip6h;
709  ThreadVars tv;
711  ThreadVars th_v;
712  DetectEngineThreadCtx *det_ctx = NULL;
713 
714  memset(&tv, 0, sizeof(ThreadVars));
715  memset(p, 0, SIZE_OF_PACKET);
716  memset(&dtv, 0, sizeof(DecodeThreadVars));
717  memset(&ip6h, 0, sizeof(IPV6Hdr));
718  memset(&th_v, 0, sizeof(ThreadVars));
719 
721  p->src.family = AF_INET6;
722  p->dst.family = AF_INET6;
723  p->ip6h = &ip6h;
724 
725  DecodeIPV6(&tv, &dtv, p, raw_icmpv6, sizeof(raw_icmpv6));
726 
729 
730  de_ctx->flags |= DE_QUIET;
731 
733  "alert icmp any any -> any any "
734  "(msg:\"ICMP Large ICMP Packet\"; dsize:>8; sid:1; rev:4;)");
735  FAIL_IF_NULL(s);
736 
738  "alert icmp any any -> any any "
739  "(msg:\"ICMP Large ICMP Packet\"; dsize:>800; sid:2; rev:4;)");
740  FAIL_IF_NULL(s);
741 
743  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
744 
745  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
746  FAIL_IF(PacketAlertCheck(p, 1) == 0);
747  FAIL_IF(PacketAlertCheck(p, 2));
748 
749  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
751 
752  PACKET_RECYCLE(p);
753  FlowShutdown();
754  SCFree(p);
755 
756  PASS;
757 }
758 
759 /**
760  * \brief this function registers unit tests for dsize
761  */
762 static void DsizeRegisterTests(void)
763 {
764  UtRegisterTest("DsizeTestParse01", DsizeTestParse01);
765  UtRegisterTest("DsizeTestParse02", DsizeTestParse02);
766  UtRegisterTest("DsizeTestParse03", DsizeTestParse03);
767  UtRegisterTest("DsizeTestParse04", DsizeTestParse04);
768  UtRegisterTest("DsizeTestParse05", DsizeTestParse05);
769  UtRegisterTest("DsizeTestParse06", DsizeTestParse06);
770  UtRegisterTest("DsizeTestParse07", DsizeTestParse07);
771  UtRegisterTest("DsizeTestParse08", DsizeTestParse08);
772  UtRegisterTest("DsizeTestParse09", DsizeTestParse09);
773  UtRegisterTest("DsizeTestParse10", DsizeTestParse10);
774  UtRegisterTest("DsizeTestParse11", DsizeTestParse11);
775  UtRegisterTest("DsizeTestMatch01", DsizeTestMatch01);
776  UtRegisterTest("DsizeTestMatch02", DsizeTestMatch02);
777 
778  UtRegisterTest("DetectDsizeIcmpv6Test01", DetectDsizeIcmpv6Test01);
779 }
780 #endif /* UNITTESTS */
util-byte.h
host.h
DetectDsizeRegister
void DetectDsizeRegister(void)
Registration function for dsize: keyword.
Definition: detect-dsize.c:66
DetectParseRegex::match
pcre2_match_data * match
Definition: detect-parse.h:45
SigTableElmt_::url
const char * url
Definition: detect.h:1204
detect-content.h
detect-engine.h
StringParseUint16
int StringParseUint16(uint16_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:336
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:90
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SigTableElmt_::desc
const char * desc
Definition: detect.h:1203
detect-dsize.h
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, const char *str, int start_offset, int options)
Definition: detect-parse.c:2435
PARSE_REGEX
#define PARSE_REGEX
Definition: detect-dsize.c:49
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1191
DetectParseRegex
Definition: detect-parse.h:42
SigTableElmt_::name
const char * name
Definition: detect.h:1201
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1201
DETECTDSIZE_NE
#define DETECTDSIZE_NE
Definition: detect-dsize.h:31
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1346
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DETECTDSIZE_EQ
#define DETECTDSIZE_EQ
Definition: detect-dsize.h:28
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:60
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
SigParseGetMaxDsize
int SigParseGetMaxDsize(const Signature *s)
get max dsize "depth"
Definition: detect-dsize.c:391
DetectDsizeData_::dsize2
uint16_t dsize2
Definition: detect-dsize.h:35
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:138
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1101
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:758
SC_ERR_INVALID_SIGNATURE
@ SC_ERR_INVALID_SIGNATURE
Definition: util-error.h:69
PrefilterPacketHeaderCtx_::sigs_array
SigIntId * sigs_array
Definition: detect-engine-prefilter-common.h:41
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2069
PrefilterPacketHeaderValue::u8
uint8_t u8[16]
Definition: detect-engine-prefilter-common.h:22
DE_QUIET
#define DE_QUIET
Definition: detect.h:294
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1653
DetectContentData_
Definition: detect-content.h:86
PrefilterPacketHeaderCtx_::sigs_cnt
uint32_t sigs_cnt
Definition: detect-engine-prefilter-common.h:40
SC_ERR_PCRE_GET_SUBSTRING
@ SC_ERR_PCRE_GET_SUBSTRING
Definition: util-error.h:34
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1186
DetectDsizeData_::mode
uint8_t mode
Definition: detect-dsize.h:36
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:552
Signature_::dsize_low
uint16_t dsize_low
Definition: detect.h:523
PrefilterPacketHeaderValue::u16
uint16_t u16[8]
Definition: detect-engine-prefilter-common.h:23
util-unittest.h
DetectDsizeData_
Definition: detect-dsize.h:33
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:1189
FlowInitConfig
void FlowInitConfig(bool quiet)
initialize the configuration
Definition: flow.c:523
PrefilterPacketHeaderCtx_
Definition: detect-engine-prefilter-common.h:33
decode.h
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
SC_ERR_PCRE_MATCH
@ SC_ERR_PCRE_MATCH
Definition: util-error.h:32
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1003
DETECTDSIZE_GT
#define DETECTDSIZE_GT
Definition: detect-dsize.h:29
res
PoolThreadReserved res
Definition: stream-tcp-private.h:0
DetectSetupParseRegexes
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
Definition: detect-parse.c:2558
DETECT_CONTENT_DEPTH
#define DETECT_CONTENT_DEPTH
Definition: detect-content.h:33
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
pkt-var.h
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:324
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:89
SIZE_OF_PACKET
#define SIZE_OF_PACKET
Definition: decode.h:634
SC_ERR_INVALID_ARGUMENT
@ SC_ERR_INVALID_ARGUMENT
Definition: util-error.h:43
DETECTDSIZE_RA
#define DETECTDSIZE_RA
Definition: detect-dsize.h:30
DetectContentData_::id
PatIntId id
Definition: detect-content.h:98
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:323
SigParseSetDsizePair
void SigParseSetDsizePair(Signature *s)
set prefilter dsize pair
Definition: detect-dsize.c:414
util-profiling.h
SCReturn
#define SCReturn
Definition: util-debug.h:302
Signature_::flags
uint32_t flags
Definition: detect.h:518
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:99
IPV6Hdr_
Definition: decode-ipv6.h:32
Packet_
Definition: decode.h:414
DecodeIPV6
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-ipv6.c:570
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:97
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:587
DETECTDSIZE_LT
#define DETECTDSIZE_LT
Definition: detect-dsize.h:27
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1169
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:511
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:235
DETECT_DSIZE
@ DETECT_DSIZE
Definition: detect-engine-register.h:50
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1932
SigMatch_::type
uint8_t type
Definition: detect.h:321
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
PrefilterPacketHeaderCtx_::v1
PrefilterPacketHeaderValue v1
Definition: detect-engine-prefilter-common.h:34
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:315
SignatureInitData_::dsize_sm
SigMatch * dsize_sm
Definition: detect.h:486
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2381
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:2773
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:2981
Signature_::dsize_high
uint16_t dsize_high
Definition: detect.h:524
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:651
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
PrefilterSetupPacketHeader
int PrefilterSetupPacketHeader(DetectEngineCtx *de_ctx, SigGroupHead *sgh, int sm_type, 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:417
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:272
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:638
SigTableElmt_::SupportsPrefilter
bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1188
Signature_::id
uint32_t id
Definition: detect.h:551
detect-parse.h
Signature_
Signature container.
Definition: detect.h:517
SigMatch_
a single match condition for a signature
Definition: detect.h:320
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2024
Signature_::dsize_mode
uint8_t dsize_mode
Definition: detect.h:525
SC_Pcre2SubstringCopy
int SC_Pcre2SubstringCopy(pcre2_match_data *match_data, uint32_t number, PCRE2_UCHAR *buffer, PCRE2_SIZE *bufflen)
Definition: detect-parse.c:2534
SC_ERR_MEM_ALLOC
@ SC_ERR_MEM_ALLOC
Definition: util-error.h:31
Address_::family
char family
Definition: decode.h:120
Packet_::dst
Address dst
Definition: decode.h:419
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:42
PrefilterPacketHeaderValue
Definition: detect-engine-prefilter-common.h:21
SigParseApplyDsizeToContent
void SigParseApplyDsizeToContent(Signature *s)
Apply dsize as depth to content matches in the rule.
Definition: detect-dsize.c:453
DetectGetLastSMFromLists
SigMatch * DetectGetLastSMFromLists(const Signature *s,...)
Returns the sm with the largest index (added latest) from the lists passed to us.
Definition: detect-parse.c:468
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:759
detect-engine-prefilter-common.h
Packet_::ip6h
IPV6Hdr * ip6h
Definition: decode.h:511
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
flow-var.h
DetectDsizeData_::dsize
uint16_t dsize
Definition: detect-dsize.h:34
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:349
Packet_::src
Address src
Definition: decode.h:418
PACKET_RECYCLE
#define PACKET_RECYCLE(p)
Definition: decode.h:842
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1193
SIG_FLAG_DSIZE
#define SIG_FLAG_DSIZE
Definition: detect.h:217
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:223