suricata
detect-dsize.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 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 
96  return 0;
97 }
98 
99 /**
100  * \internal
101  * \brief This function is used to match flags on a packet with those passed via dsize:
102  *
103  * \param t pointer to thread vars
104  * \param det_ctx pointer to the pattern matcher thread
105  * \param p pointer to the current packet
106  * \param s pointer to the Signature
107  * \param m pointer to the sigmatch
108  *
109  * \retval 0 no match
110  * \retval 1 match
111  */
112 static int DetectDsizeMatch (DetectEngineThreadCtx *det_ctx, Packet *p,
113  const Signature *s, const SigMatchCtx *ctx)
114 {
115  SCEnter();
116  int ret = 0;
117 
118  if (PKT_IS_PSEUDOPKT(p)) {
119  SCReturnInt(0);
120  }
121 
122  const DetectDsizeData *dd = (const DetectDsizeData *)ctx;
123 
124  SCLogDebug("p->payload_len %"PRIu16"", p->payload_len);
125 
126  ret = DsizeMatch(p->payload_len, dd->mode, dd->dsize, dd->dsize2);
127 
128  SCReturnInt(ret);
129 }
130 
131 /**
132  * \internal
133  * \brief This function is used to parse dsize options passed via dsize: keyword
134  *
135  * \param rawstr Pointer to the user provided dsize options
136  *
137  * \retval dd pointer to DetectDsizeData on success
138  * \retval NULL on failure
139  */
140 static DetectDsizeData *DetectDsizeParse (const char *rawstr)
141 {
142  DetectDsizeData *dd = NULL;
143  int ret = 0, res = 0;
144  int ov[MAX_SUBSTRINGS];
145  char mode[2] = "";
146  char value1[6] = "";
147  char value2[6] = "";
148  char range[3] = "";
149 
150  ret = DetectParsePcreExec(&parse_regex, rawstr, 0, 0, ov, MAX_SUBSTRINGS);
151  if (ret < 3 || ret > 5) {
152  SCLogError(SC_ERR_PCRE_MATCH,"Parse error %s", rawstr);
153  goto error;
154  }
155 
156  res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, mode, sizeof(mode));
157  if (res < 0) {
158  SCLogError(SC_ERR_PCRE_GET_SUBSTRING,"pcre_copy_substring failed");
159  goto error;
160  }
161  SCLogDebug("mode \"%s\"", mode);
162 
163  res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, value1, sizeof(value1));
164  if (res < 0) {
165  SCLogError(SC_ERR_PCRE_GET_SUBSTRING,"pcre_copy_substring failed");
166  goto error;
167  }
168  SCLogDebug("value1 \"%s\"", value1);
169 
170  if (ret > 3) {
171  res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 3, range, sizeof(range));
172  if (res < 0) {
173  SCLogError(SC_ERR_PCRE_GET_SUBSTRING,"pcre_copy_substring failed");
174  goto error;
175  }
176  SCLogDebug("range \"%s\"", range);
177 
178  if (ret > 4) {
179  res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 4, value2, sizeof(value2));
180  if (res < 0) {
181  SCLogError(SC_ERR_PCRE_GET_SUBSTRING,"pcre_copy_substring failed");
182  goto error;
183  }
184  SCLogDebug("value2 \"%s\"", value2);
185  }
186  }
187 
188  dd = SCMalloc(sizeof(DetectDsizeData));
189  if (unlikely(dd == NULL))
190  goto error;
191  dd->dsize = 0;
192  dd->dsize2 = 0;
193  dd->mode = DETECTDSIZE_EQ; // default
194 
195  if (strlen(mode) > 0) {
196  if (mode[0] == '<')
197  dd->mode = DETECTDSIZE_LT;
198  else if (mode[0] == '>')
199  dd->mode = DETECTDSIZE_GT;
200  else
201  dd->mode = DETECTDSIZE_EQ;
202  }
203 
204  if (strcmp("<>", range) == 0) {
205  if (strlen(mode) != 0) {
206  SCLogError(SC_ERR_INVALID_ARGUMENT,"Range specified but mode also set");
207  goto error;
208  }
209  dd->mode = DETECTDSIZE_RA;
210  }
211 
212  /** set the first dsize value */
213  if (StringParseUint16(&dd->dsize,10,strlen(value1),value1) <= 0) {
214  SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid size value1:\"%s\"", value1);
215  goto error;
216  }
217 
218  /** set the second dsize value if specified */
219  if (strlen(value2) > 0) {
220  if (dd->mode != DETECTDSIZE_RA) {
221  SCLogError(SC_ERR_INVALID_ARGUMENT,"Multiple dsize values specified but mode is not range");
222  goto error;
223  }
224 
225  if (StringParseUint16(&dd->dsize2,10,strlen(value2),value2) <= 0) {
226  SCLogError(SC_ERR_INVALID_ARGUMENT,"Invalid size value2:\"%s\"",value2);
227  goto error;
228  }
229 
230  if (dd->dsize2 <= dd->dsize) {
231  SCLogError(SC_ERR_INVALID_ARGUMENT,"dsize2:%"PRIu16" <= dsize:%"PRIu16"",dd->dsize2,dd->dsize);
232  goto error;
233  }
234  }
235 
236  SCLogDebug("dsize parsed successfully dsize: %"PRIu16" dsize2: %"PRIu16"",dd->dsize,dd->dsize2);
237  return dd;
238 
239 error:
240  if (dd)
241  SCFree(dd);
242  return NULL;
243 }
244 
245 /**
246  * \internal
247  * \brief this function is used to add the parsed dsize into the current signature
248  *
249  * \param de_ctx pointer to the Detection Engine Context
250  * \param s pointer to the Current Signature
251  * \param rawstr pointer to the user provided flags options
252  *
253  * \retval 0 on Success
254  * \retval -1 on Failure
255  */
256 static int DetectDsizeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
257 {
258  DetectDsizeData *dd = NULL;
259  SigMatch *sm = NULL;
260 
262  SCLogError(SC_ERR_INVALID_SIGNATURE, "Can't use 2 or more dsizes in "
263  "the same sig. Invalidating signature.");
264  goto error;
265  }
266 
267  SCLogDebug("\'%s\'", rawstr);
268 
269  dd = DetectDsizeParse(rawstr);
270  if (dd == NULL) {
271  SCLogError(SC_ERR_INVALID_ARGUMENT,"Parsing \'%s\' failed", rawstr);
272  goto error;
273  }
274 
275  /* Okay so far so good, lets get this into a SigMatch
276  * and put it in the Signature. */
277  sm = SigMatchAlloc();
278  if (sm == NULL){
279  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for SigMatch");
280  SCFree(dd);
281  goto error;
282  }
283 
284  sm->type = DETECT_DSIZE;
285  sm->ctx = (SigMatchCtx *)dd;
286 
288 
289  SCLogDebug("dd->dsize %"PRIu16", dd->dsize2 %"PRIu16", dd->mode %"PRIu8"",
290  dd->dsize, dd->dsize2, dd->mode);
291  /* tell the sig it has a dsize to speed up engine init */
293  s->flags |= SIG_FLAG_DSIZE;
294 
295  if (s->init_data->dsize_sm == NULL) {
296  s->init_data->dsize_sm = sm;
297  }
298 
299  return 0;
300 
301 error:
302  return -1;
303 }
304 
305 /**
306  * \internal
307  * \brief this function will free memory associated with DetectDsizeData
308  *
309  * \param de pointer to DetectDsizeData
310  */
311 void DetectDsizeFree(DetectEngineCtx *de_ctx, void *de_ptr)
312 {
313  DetectDsizeData *dd = (DetectDsizeData *)de_ptr;
314  if(dd) SCFree(dd);
315 }
316 
317 /* prefilter code */
318 
319 static void
320 PrefilterPacketDsizeMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
321 {
322  if (PKT_IS_PSEUDOPKT(p)) {
323  SCReturn;
324  }
325 
326  const PrefilterPacketHeaderCtx *ctx = pectx;
327  if (PrefilterPacketHeaderExtraMatch(ctx, p) == FALSE)
328  return;
329 
330  const uint16_t dsize = p->payload_len;
331  if (DsizeMatch(dsize, ctx->v1.u8[0], ctx->v1.u16[1], ctx->v1.u16[2]))
332  {
333  SCLogDebug("packet matches dsize %u", dsize);
334  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
335  }
336 }
337 
338 static void
339 PrefilterPacketDsizeSet(PrefilterPacketHeaderValue *v, void *smctx)
340 {
341  const DetectDsizeData *a = smctx;
342  v->u8[0] = a->mode;
343  v->u16[1] = a->dsize;
344  v->u16[2] = a->dsize2;
345 }
346 
347 static bool
348 PrefilterPacketDsizeCompare(PrefilterPacketHeaderValue v, void *smctx)
349 {
350  const DetectDsizeData *a = smctx;
351  if (v.u8[0] == a->mode &&
352  v.u16[1] == a->dsize &&
353  v.u16[2] == a->dsize2)
354  return TRUE;
355  return FALSE;
356 }
357 
358 static int PrefilterSetupDsize(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
359 {
361  PrefilterPacketDsizeSet,
362  PrefilterPacketDsizeCompare,
363  PrefilterPacketDsizeMatch);
364 }
365 
366 static bool PrefilterDsizeIsPrefilterable(const Signature *s)
367 {
368  const SigMatch *sm;
369  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
370  switch (sm->type) {
371  case DETECT_DSIZE:
372  return TRUE;
373  }
374  }
375  return FALSE;
376 }
377 
378 /** \brief get max dsize "depth"
379  * \param s signature to get dsize value from
380  * \retval depth or negative value
381  */
383 {
384  if (s->flags & SIG_FLAG_DSIZE && s->init_data->dsize_sm != NULL) {
385  const DetectDsizeData *dd = (const DetectDsizeData *)s->init_data->dsize_sm->ctx;
386 
387  switch (dd->mode) {
388  case DETECTDSIZE_LT:
389  case DETECTDSIZE_EQ:
390  return dd->dsize;
391  case DETECTDSIZE_RA:
392  return dd->dsize2;
393  case DETECTDSIZE_GT:
394  default:
395  SCReturnInt(-2);
396  }
397  }
398  SCReturnInt(-1);
399 }
400 
401 /** \brief set prefilter dsize pair
402  * \param s signature to get dsize value from
403  */
405 {
406  if (s->flags & SIG_FLAG_DSIZE && s->init_data->dsize_sm != NULL) {
408 
409  uint16_t low = 0;
410  uint16_t high = 65535;
411 
412  switch (dd->mode) {
413  case DETECTDSIZE_LT:
414  low = 0;
415  high = dd->dsize;
416  break;
417  case DETECTDSIZE_EQ:
418  low = dd->dsize;
419  high = dd->dsize;
420  break;
421  case DETECTDSIZE_RA:
422  low = dd->dsize;
423  high = dd->dsize2;
424  break;
425  case DETECTDSIZE_GT:
426  low = dd->dsize;
427  high = 65535;
428  break;
429  }
430  s->dsize_low = low;
431  s->dsize_high = high;
432 
433  SCLogDebug("low %u, high %u", low, high);
434  }
435 }
436 
437 /**
438  * \brief Apply dsize as depth to content matches in the rule
439  * \param s signature to get dsize value from
440  */
442 {
443  SCEnter();
444 
445  if (s->flags & SIG_FLAG_DSIZE) {
447 
448  int dsize = SigParseGetMaxDsize(s);
449  if (dsize < 0) {
450  /* nothing to do */
451  return;
452  }
453 
455  for ( ; sm != NULL; sm = sm->next) {
456  if (sm->type != DETECT_CONTENT) {
457  continue;
458  }
459 
461  if (cd == NULL) {
462  continue;
463  }
464 
465  if (cd->depth == 0 || cd->depth >= dsize) {
466  cd->depth = (uint16_t)dsize;
467  SCLogDebug("updated %u, content %u to have depth %u "
468  "because of dsize.", s->id, cd->id, cd->depth);
469  }
470  }
471  }
472 }
473 
474 /*
475  * ONLY TESTS BELOW THIS COMMENT
476  */
477 
478 #ifdef UNITTESTS
479 #include "detect-engine.h"
480 
481 /**
482  * \test this is a test for a valid dsize value 1
483  *
484  * \retval 1 on succces
485  * \retval 0 on failure
486  */
487 static int DsizeTestParse01 (void)
488 {
489  DetectDsizeData *dd = NULL;
490  dd = DetectDsizeParse("1");
491  if (dd) {
492  DetectDsizeFree(NULL, dd);
493  return 1;
494  }
495 
496  return 0;
497 }
498 
499 /**
500  * \test this is a test for a valid dsize value >10
501  *
502  * \retval 1 on succces
503  * \retval 0 on failure
504  */
505 static int DsizeTestParse02 (void)
506 {
507  DetectDsizeData *dd = NULL;
508  dd = DetectDsizeParse(">10");
509  if (dd) {
510  DetectDsizeFree(NULL, dd);
511  return 1;
512  }
513 
514  return 0;
515 }
516 
517 /**
518  * \test this is a test for a valid dsize value <100
519  *
520  * \retval 1 on succces
521  * \retval 0 on failure
522  */
523 static int DsizeTestParse03 (void)
524 {
525  DetectDsizeData *dd = NULL;
526  dd = DetectDsizeParse("<100");
527  if (dd) {
528  DetectDsizeFree(NULL, dd);
529  return 1;
530  }
531 
532  return 0;
533 }
534 
535 /**
536  * \test this is a test for a valid dsize value 1<>2
537  *
538  * \retval 1 on succces
539  * \retval 0 on failure
540  */
541 static int DsizeTestParse04 (void)
542 {
543  DetectDsizeData *dd = NULL;
544  dd = DetectDsizeParse("1<>2");
545  if (dd) {
546  DetectDsizeFree(NULL, dd);
547  return 1;
548  }
549 
550  return 0;
551 }
552 
553 /**
554  * \test this is a test for a valid dsize value 1
555  *
556  * \retval 1 on succces
557  * \retval 0 on failure
558  */
559 static int DsizeTestParse05 (void)
560 {
561  int result = 0;
562  DetectDsizeData *dd = NULL;
563  dd = DetectDsizeParse("1");
564  if (dd) {
565  if (dd->dsize == 1)
566  result = 1;
567 
568  DetectDsizeFree(NULL, dd);
569  }
570 
571  return result;
572 }
573 
574 /**
575  * \test this is a test for a valid dsize value >10
576  *
577  * \retval 1 on succces
578  * \retval 0 on failure
579  */
580 static int DsizeTestParse06 (void)
581 {
582  int result = 0;
583  DetectDsizeData *dd = NULL;
584  dd = DetectDsizeParse(">10");
585  if (dd) {
586  if (dd->dsize == 10 && dd->mode == DETECTDSIZE_GT)
587  result = 1;
588 
589  DetectDsizeFree(NULL, dd);
590  }
591 
592  return result;
593 }
594 
595 /**
596  * \test this is a test for a valid dsize value <100
597  *
598  * \retval 1 on succces
599  * \retval 0 on failure
600  */
601 static int DsizeTestParse07 (void)
602 {
603  int result = 0;
604  DetectDsizeData *dd = NULL;
605  dd = DetectDsizeParse("<100");
606  if (dd) {
607  if (dd->dsize == 100 && dd->mode == DETECTDSIZE_LT)
608  result = 1;
609 
610  DetectDsizeFree(NULL, dd);
611  }
612 
613  return result;
614 }
615 
616 /**
617  * \test this is a test for a valid dsize value 1<>2
618  *
619  * \retval 1 on succces
620  * \retval 0 on failure
621  */
622 static int DsizeTestParse08 (void)
623 {
624  int result = 0;
625  DetectDsizeData *dd = NULL;
626  dd = DetectDsizeParse("1<>2");
627  if (dd) {
628  if (dd->dsize == 1 && dd->dsize2 == 2 && dd->mode == DETECTDSIZE_RA)
629  result = 1;
630 
631  DetectDsizeFree(NULL, dd);
632  }
633 
634  return result;
635 }
636 
637 /**
638  * \test this is a test for a invalid dsize value A
639  *
640  * \retval 1 on succces
641  * \retval 0 on failure
642  */
643 static int DsizeTestParse09 (void)
644 {
645  DetectDsizeData *dd = NULL;
646  dd = DetectDsizeParse("A");
647  if (dd) {
648  DetectDsizeFree(NULL, dd);
649  return 0;
650  }
651 
652  return 1;
653 }
654 
655 /**
656  * \test this is a test for a invalid dsize value >10<>10
657  *
658  * \retval 1 on succces
659  * \retval 0 on failure
660  */
661 static int DsizeTestParse10 (void)
662 {
663  DetectDsizeData *dd = NULL;
664  dd = DetectDsizeParse(">10<>10");
665  if (dd) {
666  DetectDsizeFree(NULL, dd);
667  return 0;
668  }
669 
670  return 1;
671 }
672 
673 /**
674  * \test this is a test for a invalid dsize value <>10
675  *
676  * \retval 1 on succces
677  * \retval 0 on failure
678  */
679 static int DsizeTestParse11 (void)
680 {
681  DetectDsizeData *dd = NULL;
682  dd = DetectDsizeParse("<>10");
683  if (dd) {
684  DetectDsizeFree(NULL, dd);
685  return 0;
686  }
687 
688  return 1;
689 }
690 
691 /**
692  * \test this is a test for a invalid dsize value 1<>
693  *
694  * \retval 1 on succces
695  * \retval 0 on failure
696  */
697 static int DsizeTestParse12 (void)
698 {
699  DetectDsizeData *dd = NULL;
700  dd = DetectDsizeParse("1<>");
701  if (dd) {
702  DetectDsizeFree(NULL, dd);
703  return 0;
704  }
705 
706  return 1;
707 }
708 
709 /**
710  * \test this is a test for a valid dsize value 1
711  *
712  * \retval 1 on succces
713  * \retval 0 on failure
714  */
715 static int DsizeTestParse13 (void)
716 {
717  int result = 0;
718  DetectDsizeData *dd = NULL;
719  dd = DetectDsizeParse("1");
720  if (dd) {
721  if (dd->dsize2 == 0)
722  result = 1;
723 
724  DetectDsizeFree(NULL, dd);
725  }
726 
727  return result;
728 }
729 
730 /**
731  * \test this is a test for a invalid dsize value ""
732  *
733  * \retval 1 on succces
734  * \retval 0 on failure
735  */
736 static int DsizeTestParse14 (void)
737 {
738  DetectDsizeData *dd = NULL;
739  dd = DetectDsizeParse("");
740  if (dd) {
741  DetectDsizeFree(NULL, dd);
742  return 0;
743  }
744 
745  return 1;
746 }
747 
748 /**
749  * \test this is a test for a invalid dsize value " "
750  *
751  * \retval 1 on succces
752  * \retval 0 on failure
753  */
754 static int DsizeTestParse15 (void)
755 {
756  DetectDsizeData *dd = NULL;
757  dd = DetectDsizeParse(" ");
758  if (dd) {
759  DetectDsizeFree(NULL, dd);
760  return 0;
761  }
762 
763  return 1;
764 }
765 
766 /**
767  * \test this is a test for a invalid dsize value 2<>1
768  *
769  * \retval 1 on succces
770  * \retval 0 on failure
771  */
772 static int DsizeTestParse16 (void)
773 {
774  DetectDsizeData *dd = NULL;
775  dd = DetectDsizeParse("2<>1");
776  if (dd) {
777  DetectDsizeFree(NULL, dd);
778  return 0;
779  }
780 
781  return 1;
782 }
783 
784 /**
785  * \test this is a test for a valid dsize value 1 <> 2
786  *
787  * \retval 1 on succces
788  * \retval 0 on failure
789  */
790 static int DsizeTestParse17 (void)
791 {
792  int result = 0;
793  DetectDsizeData *dd = NULL;
794  dd = DetectDsizeParse(" 1 <> 2 ");
795  if (dd) {
796  if (dd->dsize == 1 && dd->dsize2 == 2 && dd->mode == DETECTDSIZE_RA)
797  result = 1;
798 
799  DetectDsizeFree(NULL, dd);
800  }
801 
802  return result;
803 }
804 
805 /**
806  * \test this is test for a valid dsize value > 2
807  *
808  * \retval 1 on succces
809  * \retval 0 on failure
810  */
811 static int DsizeTestParse18 (void)
812 {
813  int result = 0;
814  DetectDsizeData *dd = NULL;
815  dd = DetectDsizeParse("> 2 ");
816  if (dd) {
817  if (dd->dsize == 2 && dd->mode == DETECTDSIZE_GT)
818  result = 1;
819 
820  DetectDsizeFree(NULL, dd);
821  }
822 
823  return result;
824 }
825 
826 /**
827  * \test test for a valid dsize value < 12
828  *
829  * \retval 1 on succces
830  * \retval 0 on failure
831  */
832 static int DsizeTestParse19 (void)
833 {
834  int result = 0;
835  DetectDsizeData *dd = NULL;
836  dd = DetectDsizeParse("< 12 ");
837  if (dd) {
838  if (dd->dsize == 12 && dd->mode == DETECTDSIZE_LT)
839  result = 1;
840 
841  DetectDsizeFree(NULL, dd);
842  }
843 
844  return result;
845 }
846 
847 /**
848  * \test test for a valid dsize value 12
849  *
850  * \retval 1 on succces
851  * \retval 0 on failure
852  */
853 static int DsizeTestParse20 (void)
854 {
855  int result = 0;
856  DetectDsizeData *dd = NULL;
857  dd = DetectDsizeParse(" 12 ");
858  if (dd) {
859  if (dd->dsize == 12 && dd->mode == DETECTDSIZE_EQ)
860  result = 1;
861 
862  DetectDsizeFree(NULL, dd);
863  }
864 
865  return result;
866 }
867 
868 /**
869  * \test DetectDsizeIcmpv6Test01 is a test for checking the working of
870  * dsize keyword by creating 2 rules and matching a crafted packet
871  * against them. Only the first one shall trigger.
872  */
873 static int DetectDsizeIcmpv6Test01 (void)
874 {
875  int result = 0;
876 
877  static uint8_t raw_icmpv6[] = {
878  0x60, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3a, 0xff,
879  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881  0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
882  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
883  0x01, 0x00, 0x7b, 0x85, 0x00, 0x00, 0x00, 0x00,
884  0x60, 0x4b, 0xe8, 0xbd, 0x00, 0x00, 0x3b, 0xff,
885  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
886  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
887  0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
888  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
889 
891  if (unlikely(p == NULL))
892  return 0;
893  IPV6Hdr ip6h;
894  ThreadVars tv;
896  Signature *s = NULL;
897  ThreadVars th_v;
898  DetectEngineThreadCtx *det_ctx = NULL;
899 
900  memset(&tv, 0, sizeof(ThreadVars));
901  memset(p, 0, SIZE_OF_PACKET);
902  memset(&dtv, 0, sizeof(DecodeThreadVars));
903  memset(&ip6h, 0, sizeof(IPV6Hdr));
904  memset(&th_v, 0, sizeof(ThreadVars));
905 
907  p->src.family = AF_INET6;
908  p->dst.family = AF_INET6;
909  p->ip6h = &ip6h;
910 
911  DecodeIPV6(&tv, &dtv, p, raw_icmpv6, sizeof(raw_icmpv6));
912 
914  if (de_ctx == NULL) {
915  goto end;
916  }
917 
918  de_ctx->flags |= DE_QUIET;
919 
920  s = de_ctx->sig_list = SigInit(de_ctx, "alert icmp any any -> any any "
921  "(msg:\"ICMP Large ICMP Packet\"; dsize:>8; sid:1; rev:4;)");
922  if (s == NULL) {
923  goto end;
924  }
925 
926  s = s->next = SigInit(de_ctx, "alert icmp any any -> any any "
927  "(msg:\"ICMP Large ICMP Packet\"; dsize:>800; sid:2; rev:4;)");
928  if (s == NULL) {
929  goto end;
930  }
931 
933  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
934 
935  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
936  if (PacketAlertCheck(p, 1) == 0) {
937  printf("sid 1 did not alert, but should have: ");
938  goto cleanup;
939  } else if (PacketAlertCheck(p, 2)) {
940  printf("sid 2 alerted, but should not have: ");
941  goto cleanup;
942  }
943 
944  result = 1;
945 
946 cleanup:
949 
950  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
952 
953  PACKET_RECYCLE(p);
954  FlowShutdown();
955 end:
956  SCFree(p);
957  return result;
958 
959 }
960 
961 /**
962  * \brief this function registers unit tests for dsize
963  */
964 static void DsizeRegisterTests(void)
965 {
966  UtRegisterTest("DsizeTestParse01", DsizeTestParse01);
967  UtRegisterTest("DsizeTestParse02", DsizeTestParse02);
968  UtRegisterTest("DsizeTestParse03", DsizeTestParse03);
969  UtRegisterTest("DsizeTestParse04", DsizeTestParse04);
970  UtRegisterTest("DsizeTestParse05", DsizeTestParse05);
971  UtRegisterTest("DsizeTestParse06", DsizeTestParse06);
972  UtRegisterTest("DsizeTestParse07", DsizeTestParse07);
973  UtRegisterTest("DsizeTestParse08", DsizeTestParse08);
974  UtRegisterTest("DsizeTestParse09", DsizeTestParse09);
975  UtRegisterTest("DsizeTestParse10", DsizeTestParse10);
976  UtRegisterTest("DsizeTestParse11", DsizeTestParse11);
977  UtRegisterTest("DsizeTestParse12", DsizeTestParse12);
978  UtRegisterTest("DsizeTestParse13", DsizeTestParse13);
979  UtRegisterTest("DsizeTestParse14", DsizeTestParse14);
980  UtRegisterTest("DsizeTestParse15", DsizeTestParse15);
981  UtRegisterTest("DsizeTestParse16", DsizeTestParse16);
982  UtRegisterTest("DsizeTestParse17", DsizeTestParse17);
983  UtRegisterTest("DsizeTestParse18", DsizeTestParse18);
984  UtRegisterTest("DsizeTestParse19", DsizeTestParse19);
985  UtRegisterTest("DsizeTestParse20", DsizeTestParse20);
986 
987  UtRegisterTest("DetectDsizeIcmpv6Test01", DetectDsizeIcmpv6Test01);
988 }
989 #endif /* UNITTESTS */
util-byte.h
host.h
DetectDsizeRegister
void DetectDsizeRegister(void)
Registration function for dsize: keyword.
Definition: detect-dsize.c:66
SigTableElmt_::url
const char * url
Definition: detect.h:1214
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
SigTableElmt_::desc
const char * desc
Definition: detect.h:1213
detect-dsize.h
PARSE_REGEX
#define PARSE_REGEX
Definition: detect-dsize.c:49
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1201
SigTableElmt_::name
const char * name
Definition: detect.h:1211
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1147
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1347
MAX_SUBSTRINGS
#define MAX_SUBSTRINGS
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:59
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
SigParseGetMaxDsize
int SigParseGetMaxDsize(const Signature *s)
get max dsize "depth"
Definition: detect-dsize.c:382
DetectDsizeData_::dsize2
uint16_t dsize2
Definition: detect-dsize.h:34
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
SigInit
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2056
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1111
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:767
FlowInitConfig
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:516
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:2093
PrefilterPacketHeaderValue::u8
uint8_t u8[16]
Definition: detect-engine-prefilter-common.h:22
DE_QUIET
#define DE_QUIET
Definition: detect.h:294
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
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:39
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1196
DetectDsizeData_::mode
uint8_t mode
Definition: detect-dsize.h:35
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:550
Signature_::dsize_low
uint16_t dsize_low
Definition: detect.h:534
PrefilterPacketHeaderValue::u16
uint16_t u16[8]
Definition: detect-engine-prefilter-common.h:23
util-unittest.h
DetectDsizeData_
Definition: detect-dsize.h:32
SigTableElmt_::SetupPrefilter
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1199
Signature_::next
struct Signature_ * next
Definition: detect.h:600
PrefilterPacketHeaderCtx_
Definition: detect-engine-prefilter-common.h:33
decode.h
util-debug.h
SC_ERR_PCRE_MATCH
@ SC_ERR_PCRE_MATCH
Definition: util-error.h:32
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1010
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:2493
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:627
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
TRUE
#define TRUE
Definition: suricata-common.h:33
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:323
SigMatchSignatures
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1688
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:1953
SigParseSetDsizePair
void SigParseSetDsizePair(Signature *s)
set prefilter dsize pair
Definition: detect-dsize.c:404
util-profiling.h
FALSE
#define FALSE
Definition: suricata-common.h:34
SCReturn
#define SCReturn
Definition: util-debug.h:302
Signature_::flags
uint32_t flags
Definition: detect.h:529
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:99
IPV6Hdr_
Definition: decode-ipv6.h:32
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, const char *str, int start_offset, int options, int *ovector, int ovector_size)
Definition: detect-parse.c:2423
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:580
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:597
DETECTDSIZE_LT
#define DETECTDSIZE_LT
Definition: detect-dsize.h:27
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1179
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:522
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:235
DETECT_DSIZE
@ DETECT_DSIZE
Definition: detect-engine-register.h:49
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1888
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:497
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:2797
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3005
Signature_::dsize_high
uint16_t dsize_high
Definition: detect.h:535
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:644
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
DetectParseRegex_
Definition: detect-parse.h:42
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:773
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:407
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:273
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:631
SigTableElmt_::SupportsPrefilter
bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1198
Signature_::id
uint32_t id
Definition: detect.h:561
detect-parse.h
Signature_
Signature container.
Definition: detect.h:528
SigMatch_
a single match condition for a signature
Definition: detect.h:320
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2048
SC_ERR_MEM_ALLOC
@ SC_ERR_MEM_ALLOC
Definition: util-error.h:31
Address_::family
char family
Definition: decode.h:117
Packet_::dst
Address dst
Definition: decode.h:419
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:39
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:441
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:768
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:33
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:827
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1203
SIG_FLAG_DSIZE
#define SIG_FLAG_DSIZE
Definition: detect.h:217
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:223