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