suricata
detect-content.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2022 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  * Simple content match part of the detection engine.
24  */
25 
26 #include "suricata-common.h"
27 #include "decode.h"
28 #include "detect.h"
29 #include "detect-content.h"
30 #include "detect-uricontent.h"
31 #include "detect-engine-mpm.h"
32 #include "detect-engine.h"
33 #include "detect-engine-build.h"
34 #include "detect-engine-state.h"
35 #include "detect-parse.h"
36 #include "detect-pcre.h"
37 #include "util-mpm.h"
38 #include "flow.h"
39 #include "flow-util.h"
40 #include "flow-var.h"
41 #include "detect-flow.h"
42 #include "app-layer.h"
43 #include "util-unittest.h"
44 #include "util-print.h"
45 #include "util-debug.h"
46 #include "util-spm.h"
47 #include "threads.h"
48 #include "util-unittest-helper.h"
49 #include "pkt-var.h"
50 #include "host.h"
51 #include "util-profiling.h"
52 #include "detect-dsize.h"
53 
54 #ifdef UNITTESTS
55 static void DetectContentRegisterTests(void);
56 #endif
57 
59 {
60  sigmatch_table[DETECT_CONTENT].name = "content";
61  sigmatch_table[DETECT_CONTENT].desc = "match on payload content";
62  sigmatch_table[DETECT_CONTENT].url = "/rules/payload-keywords.html#content";
66 #ifdef UNITTESTS
67  sigmatch_table[DETECT_CONTENT].RegisterTests = DetectContentRegisterTests;
68 #endif
70 }
71 
72 /**
73  * \brief Parse a content string, ie "abc|DE|fgh"
74  *
75  * \param content_str null terminated string containing the content
76  * \param result result pointer to pass the fully parsed byte array
77  * \param result_len size of the resulted data
78  * \param flags flags to be set by this parsing function
79  *
80  * \retval -1 error
81  * \retval 0 ok
82  */
83 int DetectContentDataParse(const char *keyword, const char *contentstr,
84  uint8_t **pstr, uint16_t *plen)
85 {
86  char *str = NULL;
87  size_t slen = 0;
88 
89  slen = strlen(contentstr);
90  if (slen == 0) {
91  return -1;
92  }
93  uint8_t buffer[slen + 1];
94  strlcpy((char *)&buffer, contentstr, slen + 1);
95  str = (char *)buffer;
96 
97  SCLogDebug("\"%s\", len %" PRIuMAX, str, (uintmax_t)slen);
98 
99  //SCLogDebug("DetectContentParse: \"%s\", len %" PRIu32 "", str, len);
100  char converted = 0;
101 
102  {
103  size_t i, x;
104  uint8_t bin = 0;
105  uint8_t escape = 0;
106  uint8_t binstr[3] = "";
107  uint8_t binpos = 0;
108  uint16_t bin_count = 0;
109 
110  for (i = 0, x = 0; i < slen; i++) {
111  // SCLogDebug("str[%02u]: %c", i, str[i]);
112  if (str[i] == '|') {
113  bin_count++;
114  if (bin) {
115  if (binpos > 0) {
116  SCLogError("Incomplete hex code in content - %s. Invalidating signature.",
117  contentstr);
118  goto error;
119  }
120  bin = 0;
121  } else {
122  bin = 1;
123  }
124  } else if(!escape && str[i] == '\\') {
125  escape = 1;
126  } else {
127  if (bin) {
128  if (isdigit((unsigned char)str[i]) ||
129  str[i] == 'A' || str[i] == 'a' ||
130  str[i] == 'B' || str[i] == 'b' ||
131  str[i] == 'C' || str[i] == 'c' ||
132  str[i] == 'D' || str[i] == 'd' ||
133  str[i] == 'E' || str[i] == 'e' ||
134  str[i] == 'F' || str[i] == 'f')
135  {
136  // SCLogDebug("part of binary: %c", str[i]);
137 
138  binstr[binpos] = (char)str[i];
139  binpos++;
140 
141  if (binpos == 2) {
142  uint8_t c = strtol((char *)binstr, (char **) NULL, 16) & 0xFF;
143  binpos = 0;
144  str[x] = c;
145  x++;
146  converted = 1;
147  }
148  } else if (str[i] == ' ') {
149  // SCLogDebug("space as part of binary string");
150  }
151  else if (str[i] != ',') {
152  SCLogError("Invalid hex code in "
153  "content - %s, hex %c. Invalidating signature.",
154  contentstr, str[i]);
155  goto error;
156  }
157  } else if (escape) {
158  if (str[i] == ':' ||
159  str[i] == ';' ||
160  str[i] == '\\' ||
161  str[i] == '\"')
162  {
163  str[x] = str[i];
164  x++;
165  } else {
166  SCLogError("'%c' has to be escaped", str[i - 1]);
167  goto error;
168  }
169  escape = 0;
170  converted = 1;
171  } else if (str[i] == '"') {
172  SCLogError("Invalid unescaped double quote within content section.");
173  goto error;
174  } else {
175  str[x] = str[i];
176  x++;
177  }
178  }
179  }
180 
181  if (bin_count % 2 != 0) {
182  SCLogError("Invalid hex code assembly in "
183  "%s - %s. Invalidating signature.",
184  keyword, contentstr);
185  goto error;
186  }
187 
188  if (converted) {
189  slen = x;
190  }
191  }
192 
193  if (slen) {
194  uint8_t *ptr = SCCalloc(1, slen);
195  if (ptr == NULL) {
196  return -1;
197  }
198  memcpy(ptr, str, slen);
199 
200  *plen = (uint16_t)slen;
201  *pstr = ptr;
202  return 0;
203  }
204 error:
205  return -1;
206 }
207 /**
208  * \brief DetectContentParse
209  * \initonly
210  */
212  const char *contentstr)
213 {
214  DetectContentData *cd = NULL;
215  uint8_t *content = NULL;
216  uint16_t len = 0;
217  int ret;
218 
219  ret = DetectContentDataParse("content", contentstr, &content, &len);
220  if (ret == -1) {
221  return NULL;
222  }
223 
224  cd = SCCalloc(1, sizeof(DetectContentData) + len);
225  if (unlikely(cd == NULL)) {
226  SCFree(content);
227  exit(EXIT_FAILURE);
228  }
229 
230  cd->content = (uint8_t *)cd + sizeof(DetectContentData);
231  memcpy(cd->content, content, len);
232  cd->content_len = len;
233 
234  /* Prepare SPM search context. */
235  cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 0,
236  spm_global_thread_ctx);
237  if (cd->spm_ctx == NULL) {
238  SCFree(content);
239  SCFree(cd);
240  return NULL;
241  }
242 
243  cd->depth = 0;
244  cd->offset = 0;
245  cd->within = 0;
246  cd->distance = 0;
247 
248  SCFree(content);
249  return cd;
250 
251 }
252 
254  const char *contentstr)
255 {
256  return DetectContentParse(spm_global_thread_ctx, contentstr);
257 }
258 
259 /**
260  * \brief Helper function to print a DetectContentData
261  */
263 {
264  int i = 0;
265  if (cd == NULL) {
266  SCLogDebug("DetectContentData \"cd\" is NULL");
267  return;
268  }
269  char *tmpstr = SCMalloc(sizeof(char) * cd->content_len + 1);
270  if (tmpstr != NULL) {
271  for (i = 0; i < cd->content_len; i++) {
272  if (isprint(cd->content[i]))
273  tmpstr[i] = cd->content[i];
274  else
275  tmpstr[i] = '.';
276  }
277  tmpstr[i] = '\0';
278  SCLogDebug("Content: \"%s\"", tmpstr);
279  SCFree(tmpstr);
280  } else {
281  SCLogDebug("Content: ");
282  for (i = 0; i < cd->content_len; i++)
283  SCLogDebug("%c", cd->content[i]);
284  }
285 
286  SCLogDebug("Content_id: %"PRIu32, cd->id);
287  SCLogDebug("Content_len: %"PRIu16, cd->content_len);
288  SCLogDebug("Depth: %"PRIu16, cd->depth);
289  SCLogDebug("Offset: %"PRIu16, cd->offset);
290  SCLogDebug("Within: %"PRIi32, cd->within);
291  SCLogDebug("Distance: %"PRIi32, cd->distance);
292  SCLogDebug("flags: %u ", cd->flags);
293  SCLogDebug("negated: %s ", cd->flags & DETECT_CONTENT_NEGATED ? "true" : "false");
294  SCLogDebug("relative match next: %s ", cd->flags & DETECT_CONTENT_RELATIVE_NEXT ? "true" : "false");
295 
296  if (cd->replace && cd->replace_len) {
297  char *tmprstr = SCMalloc(sizeof(char) * cd->replace_len + 1);
298 
299  if (tmprstr != NULL) {
300  for (i = 0; i < cd->replace_len; i++) {
301  if (isprint(cd->replace[i]))
302  tmprstr[i] = cd->replace[i];
303  else
304  tmprstr[i] = '.';
305  }
306  tmprstr[i] = '\0';
307  SCLogDebug("Replace: \"%s\"", tmprstr);
308  SCFree(tmprstr);
309  } else {
310  SCLogDebug("Replace: ");
311  for (i = 0; i < cd->replace_len; i++)
312  SCLogDebug("%c", cd->replace[i]);
313  }
314  }
315  SCLogDebug("-----------");
316 }
317 
318 /**
319  * \brief Function to setup a content pattern.
320  *
321  * \param de_ctx pointer to the current detection_engine
322  * \param s pointer to the current Signature
323  * \param m pointer to the last parsed SigMatch
324  * \param contentstr pointer to the current keyword content string
325  * \retval -1 if error
326  * \retval 0 if all was ok
327  */
328 int DetectContentSetup(DetectEngineCtx *de_ctx, Signature *s, const char *contentstr)
329 {
330  DetectContentData *cd = NULL;
331  SigMatch *sm = NULL;
332 
334  if (cd == NULL)
335  goto error;
336  if (s->init_data->negated == true) {
338  }
339 
340  DetectContentPrint(cd);
341 
342  if (DetectBufferGetActiveList(de_ctx, s) == -1)
343  goto error;
344 
345  int sm_list = s->init_data->list;
346  if (sm_list == DETECT_SM_LIST_NOTSET) {
347  sm_list = DETECT_SM_LIST_PMATCH;
348  } else if (sm_list > DETECT_SM_LIST_MAX &&
349  0 == (cd->flags & DETECT_CONTENT_NEGATED)) {
350  /* Check transform compatibility */
351  const char *tstr;
353  de_ctx, sm_list, cd->content, cd->content_len, &tstr)) {
354  SCLogError("content string \"%s\" incompatible with %s transform", contentstr, tstr);
355  goto error;
356  }
357  }
358 
359  sm = SigMatchAlloc();
360  if (sm == NULL)
361  goto error;
362  sm->ctx = (void *)cd;
363  sm->type = DETECT_CONTENT;
364  SigMatchAppendSMToList(s, sm, sm_list);
365 
366  return 0;
367 
368 error:
370  return -1;
371 }
372 
373 /**
374  * \brief this function will SCFree memory associated with DetectContentData
375  *
376  * \param cd pointer to DetectContentData
377  */
379 {
380  SCEnter();
382 
383  if (cd == NULL)
384  SCReturn;
385 
386  SpmDestroyCtx(cd->spm_ctx);
387 
388  SCFree(cd);
389  SCReturn;
390 }
391 
392 /*
393  * \brief Determine the size needed to accommodate the content
394  * elements of a signature
395  * \param s signature to get dsize value from
396  * \param max_size Maximum buffer/data size allowed.
397  * \param list signature match list.
398  * \param len Maximum length required
399  * \param offset Maximum offset encountered
400  *
401  * Note that negated content does not contribute to the maximum
402  * required size value. However, each negated content's values
403  * must not exceed the size value.
404  *
405  * Values from negated content blocks are used to determine if the
406  * negated content block requires a value that exceeds "max_size". The
407  * distance and within values from negated content blocks are added to
408  * the running total of required content size to see if the max_size
409  * would be exceeded.
410  *
411  * - Non-negated content contributes to the required size (content length, distance)
412  * - Negated content values are checked but not accumulated for the required size.
413  */
415  const Signature *s, const int max_size, const SigMatch *sm, int *len, int *offset)
416 {
417  int max_offset = 0, total_len = 0;
418  bool first = true;
419  for (; sm != NULL; sm = sm->next) {
420  if (sm->type != DETECT_CONTENT || sm->ctx == NULL) {
421  continue;
422  }
423 
425  SCLogDebug("content_len %d; negated: %s; distance: %d, offset: %d, depth: %d",
426  cd->content_len, cd->flags & DETECT_CONTENT_NEGATED ? "yes" : "no", cd->distance,
427  cd->offset, cd->depth);
428 
429  if (!first) {
430  /* only count content with relative modifiers */
431  if (!((cd->flags & DETECT_CONTENT_DISTANCE) || (cd->flags & DETECT_CONTENT_WITHIN)))
432  continue;
433 
434  if (cd->flags & DETECT_CONTENT_NEGATED) {
435  /* Check if distance/within cause max to be exceeded */
436  int check = total_len + cd->distance + cd->within;
437  if (max_size < check) {
438  *len = check;
439  return;
440  }
441 
442  continue;
443  }
444  }
445  SCLogDebug("content_len %d; distance: %d, offset: %d, depth: %d", cd->content_len,
446  cd->distance, cd->offset, cd->depth);
447  total_len += cd->content_len + cd->distance;
448  max_offset = MAX(max_offset, cd->offset);
449  first = false;
450  }
451 
452  *len = total_len;
453  *offset = max_offset;
454 }
455 
456 /**
457  * \retval true valid
458  * \retval false invalid
459  */
461 {
462  if (!(s->flags & SIG_FLAG_DSIZE)) {
463  return true;
464  }
465 
466  int max_right_edge_i = SigParseGetMaxDsize(s);
467  if (max_right_edge_i < 0) {
468  return true;
469  }
470 
471  uint32_t max_right_edge = (uint32_t)max_right_edge_i;
472 
473  int min_dsize_required = SigParseMaxRequiredDsize(s);
474  if (min_dsize_required >= 0) {
475  SCLogDebug("min_dsize %d; max_right_edge %d", min_dsize_required, max_right_edge);
476  if ((uint32_t)min_dsize_required > max_right_edge) {
477  SCLogError("signature can't match as required content length %d exceeds dsize value %d",
478  min_dsize_required, max_right_edge);
479  return false;
480  }
481  }
482 
483  return true;
484 }
485 
486 /** \brief apply depth/offset and distance/within to content matches
487  *
488  * The idea is that any limitation we can set is a win, as the mpm
489  * can use this to reduce match candidates.
490  *
491  * E.g. if we have 'content:"1"; depth:1; content:"2"; distance:0; within:1;'
492  * we know that we can add 'offset:1; depth:2;' to the 2nd condition. This
493  * will then be used in mpm if the 2nd condition would be selected for mpm.
494  *
495  * Another example: 'content:"1"; depth:1; content:"2"; distance:0;'. Here we
496  * cannot set a depth, but we can set an offset of 'offset:1;'. This will
497  * make the mpm a bit more precise.
498  */
499 static void PropagateLimits(Signature *s, SigMatch *sm_head)
500 {
501 #define VALIDATE(e) \
502  if (!(e)) { \
503  return; \
504  }
505  uint16_t offset = 0;
506  uint16_t offset_plus_pat = 0;
507  uint16_t depth = 0;
508  bool has_active_depth_chain = false;
509 
510  bool has_depth = false;
511  bool has_ends_with = false;
512  uint16_t ends_with_depth = 0;
513 
514  for (SigMatch *sm = sm_head; sm != NULL; sm = sm->next) {
515  switch (sm->type) {
516  case DETECT_CONTENT: {
517  DetectContentData *cd = (DetectContentData *)sm->ctx;
520  offset = depth = 0;
521  offset_plus_pat = cd->content_len;
522  SCLogDebug("reset");
523  has_active_depth_chain = false;
524  continue;
525  }
526  if (sm->prev == NULL) {
527  if (cd->distance >= 0 && cd->distance <= (int32_t)USHRT_MAX &&
528  cd->within >= 0 && cd->within <= (int32_t)USHRT_MAX) {
529  if (cd->flags & DETECT_CONTENT_DISTANCE) {
530  if (cd->distance > 0)
533  cd->offset = (uint16_t)cd->distance;
534  cd->distance = 0;
536  }
537  if (cd->flags & DETECT_CONTENT_WITHIN) {
540  cd->depth = (uint16_t)cd->within + cd->offset;
541  cd->within = 0;
543  }
544  }
545  }
546 
547  if (cd->flags & DETECT_CONTENT_NEGATED) {
548  offset = depth = 0;
549  offset_plus_pat = 0;
550  SCLogDebug("reset because of negation");
551  has_active_depth_chain = false;
552  continue;
553  }
554 
555  if (cd->depth) {
556  has_depth = true;
557  has_active_depth_chain = true;
558  }
559 
560  SCLogDebug("sm %p depth %u offset %u distance %d within %d", sm, cd->depth,
561  cd->offset, cd->distance, cd->within);
562  SCLogDebug("stored: offset %u depth %u offset_plus_pat %u", offset, depth,
563  offset_plus_pat);
564 
565  if ((cd->flags & (DETECT_DEPTH | DETECT_CONTENT_WITHIN)) == 0) {
566  if (depth)
567  SCLogDebug("no within, reset depth");
568  depth = 0;
569  has_active_depth_chain = false;
570  }
571  if ((cd->flags & DETECT_CONTENT_DISTANCE) == 0) {
572  if (offset_plus_pat)
573  SCLogDebug("no distance, reset offset_plus_pat & offset");
574  offset_plus_pat = offset = 0;
575  }
576 
577  SCLogDebug("stored: offset %u depth %u offset_plus_pat %u "
578  "has_active_depth_chain %s",
579  offset, depth, offset_plus_pat, has_active_depth_chain ? "true" : "false");
580  if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) {
581  VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX);
582  offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
583  SCLogDebug("updated content to have offset %u", cd->offset);
584  }
585  if (has_active_depth_chain) {
586  if (offset_plus_pat && cd->flags & DETECT_CONTENT_WITHIN && cd->within >= 0) {
587  if (depth && depth > offset_plus_pat) {
588  int32_t dist = 0;
589  if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance > 0) {
590  dist = cd->distance;
591  SCLogDebug(
592  "distance to add: %u. depth + dist %u", dist, depth + dist);
593  }
594  SCLogDebug("depth %u + cd->within %u", depth, cd->within);
595  VALIDATE(depth + cd->within + dist >= 0 &&
596  depth + cd->within + dist <= UINT16_MAX);
597  depth = cd->depth = (uint16_t)(depth + cd->within + dist);
598  } else {
599  SCLogDebug("offset %u + cd->within %u", offset, cd->within);
600  VALIDATE(depth + cd->within >= 0 && depth + cd->within <= UINT16_MAX);
601  depth = cd->depth = (uint16_t)(offset + cd->within);
602  }
603  SCLogDebug("updated content to have depth %u", cd->depth);
604  } else {
605  if (cd->depth == 0 && depth != 0) {
606  if (cd->within > 0) {
607  SCLogDebug("within %d distance %d", cd->within, cd->distance);
608  if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) {
609  VALIDATE(offset_plus_pat + cd->distance >= 0 &&
610  offset_plus_pat + cd->distance <= UINT16_MAX);
611  cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
612  SCLogDebug("updated content to have offset %u", cd->offset);
613  }
614 
615  VALIDATE(depth + cd->within >= 0 &&
616  depth + cd->within <= UINT16_MAX);
617  depth = cd->depth = (uint16_t)(cd->within + depth);
618  SCLogDebug("updated content to have depth %u", cd->depth);
619 
620  if (cd->flags & DETECT_CONTENT_ENDS_WITH) {
621  has_ends_with = true;
622  if (ends_with_depth == 0)
623  ends_with_depth = depth;
624  ends_with_depth = MIN(ends_with_depth, depth);
625  }
626  }
627  }
628  }
629  }
630  if (cd->offset == 0) { // && offset != 0) {
631  if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) {
632  cd->offset = offset_plus_pat;
633  SCLogDebug("update content to have offset %u", cd->offset);
634  }
635  }
636 
643  if (cd->distance >= 0) {
644  // only distance
645  VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX);
646  offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
647  offset_plus_pat = offset + cd->content_len;
648  SCLogDebug("offset %u offset_plus_pat %u", offset, offset_plus_pat);
649  }
650  }
651  if (cd->flags & DETECT_CONTENT_OFFSET) {
652  offset = cd->offset;
653  offset_plus_pat = offset + cd->content_len;
654  SCLogDebug("stored offset %u offset_plus_pat %u", offset, offset_plus_pat);
655  }
656  if (cd->depth) {
657  depth = cd->depth;
658  SCLogDebug("stored depth now %u", depth);
659  offset_plus_pat = offset + cd->content_len;
660  if (cd->flags & DETECT_CONTENT_ENDS_WITH) {
661  has_ends_with = true;
662  if (ends_with_depth == 0)
663  ends_with_depth = depth;
664  ends_with_depth = MIN(ends_with_depth, depth);
665  }
666  }
667  if ((cd->flags & (DETECT_CONTENT_WITHIN | DETECT_CONTENT_DEPTH)) == 0) {
668  has_active_depth_chain = false;
669  depth = 0;
670  }
671  break;
672  }
673  case DETECT_PCRE: {
674  // relative could leave offset_plus_pat set.
675  const DetectPcreData *pd = (const DetectPcreData *)sm->ctx;
676  if (pd->flags & DETECT_PCRE_RELATIVE) {
677  depth = 0;
678  } else {
679  SCLogDebug("non-anchored PCRE not supported, reset offset_plus_pat & offset");
680  offset_plus_pat = offset = depth = 0;
681  }
682  has_active_depth_chain = false;
683  break;
684  }
685  default:
686  SCLogDebug("keyword not supported, reset offset_plus_pat & offset");
687  offset_plus_pat = offset = depth = 0;
688  has_active_depth_chain = false;
689  break;
690  }
691  }
692  /* apply anchored 'ends with' as depth to all patterns */
693  if (has_depth && has_ends_with) {
694  for (SigMatch *sm = sm_head; sm != NULL; sm = sm->next) {
695  switch (sm->type) {
696  case DETECT_CONTENT: {
697  DetectContentData *cd = (DetectContentData *)sm->ctx;
698  if (cd->depth == 0)
699  cd->depth = ends_with_depth;
700  cd->depth = MIN(ends_with_depth, cd->depth);
701  if (cd->depth)
703  break;
704  }
705  }
706  }
707  }
708 #undef VALIDATE
709 }
710 
712 {
713  PropagateLimits(s, s->init_data->smlists[DETECT_SM_LIST_PMATCH]);
714  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
715  PropagateLimits(s, s->init_data->buffers[x].head);
716  }
717 }
718 
719 static inline bool NeedsAsHex(uint8_t c)
720 {
721  if (!isprint(c))
722  return true;
723 
724  switch (c) {
725  case '/':
726  case ';':
727  case ':':
728  case '\\':
729  case ' ':
730  case '|':
731  case '"':
732  case '`':
733  case '\'':
734  return true;
735  }
736  return false;
737 }
738 
739 void DetectContentPatternPrettyPrint(const DetectContentData *cd, char *str, size_t str_len)
740 {
741  bool hex = false;
742  for (uint16_t i = 0; i < cd->content_len; i++) {
743  if (NeedsAsHex(cd->content[i])) {
744  char hex_str[4];
745  snprintf(hex_str, sizeof(hex_str), "%s%02X", !hex ? "|" : " ", cd->content[i]);
746  strlcat(str, hex_str, str_len);
747  hex = true;
748  } else {
749  char p_str[3];
750  snprintf(p_str, sizeof(p_str), "%s%c", hex ? "|" : "", cd->content[i]);
751  strlcat(str, p_str, str_len);
752  hex = false;
753  }
754  }
755  if (hex) {
756  strlcat(str, "|", str_len);
757  }
758 }
759 
760 #ifdef UNITTESTS /* UNITTESTS */
761 #include "detect-engine-alert.h"
762 #include "packet.h"
763 
764 static bool TestLastContent(const Signature *s, uint16_t o, uint16_t d)
765 {
767  if (!sm) {
768  SCLogDebug("no sm");
769  return false;
770  }
771  if (!(sm->type == DETECT_CONTENT)) {
772  SCLogDebug("not content");
773  return false;
774  }
775  const DetectContentData *cd = (const DetectContentData *)sm->ctx;
776  if (o != cd->offset) {
777  SCLogDebug("offset mismatch %u != %u", o, cd->offset);
778  return false;
779  }
780  if (d != cd->depth) {
781  SCLogDebug("depth mismatch %u != %u", d, cd->depth);
782  return false;
783  }
784  return true;
785 }
786 
787 #define TEST_RUN(sig, o, d) \
788  { \
789  SCLogDebug("TEST_RUN start: '%s'", (sig)); \
790  DetectEngineCtx *de_ctx = DetectEngineCtxInit(); \
791  FAIL_IF_NULL(de_ctx); \
792  de_ctx->flags |= DE_QUIET; \
793  char rule[2048]; \
794  snprintf(rule, sizeof(rule), "alert tcp any any -> any any (%s sid:1; rev:1;)", (sig)); \
795  Signature *s = DetectEngineAppendSig(de_ctx, rule); \
796  FAIL_IF_NULL(s); \
797  SigAddressPrepareStage1(de_ctx); \
798  bool res = TestLastContent(s, (o), (d)); \
799  FAIL_IF(res == false); \
800  DetectEngineCtxFree(de_ctx); \
801  }
802 
803 #define TEST_DONE \
804  PASS
805 
806 /** \test test propagation of depth/offset/distance/within */
807 static int DetectContentDepthTest01(void)
808 {
809  // straight depth/offset
810  TEST_RUN("content:\"abc\"; offset:1; depth:3;", 1, 4);
811  // dsize applied as depth
812  TEST_RUN("dsize:10; content:\"abc\";", 0, 10);
813  TEST_RUN("dsize:<10; content:\"abc\";", 0, 10);
814  TEST_RUN("dsize:5<>10; content:\"abc\";", 0, 10);
815 
816  // relative match, directly following anchored content
817  TEST_RUN("content:\"abc\"; depth:3; content:\"xyz\"; distance:0; within:3; ", 3, 6);
818  // relative match, directly following anchored content
819  TEST_RUN("content:\"abc\"; offset:3; depth:3; content:\"xyz\"; distance:0; within:3; ", 6, 9);
820  TEST_RUN("content:\"abc\"; depth:6; content:\"xyz\"; distance:0; within:3; ", 3, 9);
821 
822  // multiple relative matches after anchored content
823  TEST_RUN("content:\"abc\"; depth:3; content:\"klm\"; distance:0; within:3; content:\"xyz\"; distance:0; within:3; ", 6, 9);
824  // test 'reset' due to unanchored content
825  TEST_RUN("content:\"abc\"; depth:3; content:\"klm\"; content:\"xyz\"; distance:0; within:3; ", 3, 0);
826  // test 'reset' due to unanchored pcre
827  TEST_RUN("content:\"abc\"; depth:3; pcre:/\"klm\"/; content:\"xyz\"; distance:0; within:3; ", 0, 0);
828  // test relative pcre. We can use previous offset+pattern len
829  TEST_RUN("content:\"abc\"; depth:3; pcre:/\"klm\"/R; content:\"xyz\"; distance:0; within:3; ", 3, 0);
830  TEST_RUN("content:\"abc\"; offset:3; depth:3; pcre:/\"klm\"/R; content:\"xyz\"; distance:0; within:3; ", 6, 0);
831 
832  TEST_RUN("content:\"abc\"; depth:3; content:\"klm\"; within:3; content:\"xyz\"; within:3; ", 0, 9);
833 
834  TEST_RUN("content:\"abc\"; depth:3; content:\"klm\"; distance:0; content:\"xyz\"; distance:0; ", 6, 0);
835 
836  // tests to see if anchored 'ends_with' is applied to other content as depth
837  TEST_RUN("content:\"abc\"; depth:6; isdataat:!1,relative; content:\"klm\";", 0, 6);
838  TEST_RUN("content:\"abc\"; depth:3; content:\"klm\"; within:3; content:\"xyz\"; within:3; isdataat:!1,relative; content:\"def\"; ", 0, 9);
839 
840  TEST_RUN("content:\"|03|\"; depth:1; content:\"|e0|\"; distance:4; within:1;", 5, 6);
841  TEST_RUN("content:\"|03|\"; depth:1; content:\"|e0|\"; distance:4; within:1; content:\"Cookie|3a|\"; distance:5; within:7;", 11, 18);
842 
843  TEST_RUN("content:\"this\"; content:\"is\"; within:6; content:\"big\"; within:8; content:\"string\"; within:8;", 0, 0);
844 
845  TEST_RUN("dsize:<80; content:!\"|00 22 02 00|\"; depth: 4; content:\"|00 00 04|\"; distance:8; within:3; content:\"|00 00 00 00 00|\"; distance:6; within:5;", 17, 80);
846  TEST_RUN("content:!\"|00 22 02 00|\"; depth: 4; content:\"|00 00 04|\"; distance:8; within:3; content:\"|00 00 00 00 00|\"; distance:6; within:5;", 17, 0);
847 
848  TEST_RUN("content:\"|0d 0a 0d 0a|\"; content:\"code=\"; distance:0;", 4, 0);
849  TEST_RUN("content:\"|0d 0a 0d 0a|\"; content:\"code=\"; distance:0; content:\"xploit.class\"; distance:2; within:18;", 11, 0);
850 
851  TEST_RUN("content:\"|16 03|\"; depth:2; content:\"|55 04 0a|\"; distance:0;", 2, 0);
852  TEST_RUN("content:\"|16 03|\"; depth:2; content:\"|55 04 0a|\"; distance:0; content:\"|0d|LogMeIn, Inc.\"; distance:1; within:14;", 6, 0);
853  TEST_RUN("content:\"|16 03|\"; depth:2; content:\"|55 04 0a|\"; distance:0; content:\"|0d|LogMeIn, Inc.\"; distance:1; within:14; content:\".app\";", 0, 0);
854 
855  TEST_RUN("content:\"=\"; offset:4; depth:9;", 4, 13);
856  // low end: offset 4 + patlen 1 = 5. So 5 + distance 55 = 60.
857  // hi end: depth '13' (4+9) + distance 55 = 68 + within 2 = 70
858  TEST_RUN("content:\"=\"; offset:4; depth:9; content:\"=&\"; distance:55; within:2;", 60, 70);
859 
860  // distance value is too high so we bail and not set anything on this content
861  TEST_RUN("content:\"0123456789\"; content:\"abcdef\"; distance:1048576;", 0, 0);
862 
863  // Bug #5162.
864  TEST_RUN("content:\"SMB\"; depth:8; content:\"|09 00|\"; distance:8; within:2;", 11, 18);
865  TEST_RUN("content:\"SMB\"; depth:8; content:\"|09 00|\"; distance:8; within:2; content:\"|05 "
866  "00 00|\"; distance:0;",
867  13, 0);
868  TEST_RUN("content:\"SMB\"; depth:8; content:\"|09 00|\"; distance:8; within:2; content:\"|05 "
869  "00 00|\"; distance:0; content:\"|0c 00|\"; distance:19; within:2;",
870  35, 0);
871  TEST_RUN("content:\"SMB\"; depth:8; content:\"|09 00|\"; distance:8; within:2; content:\"|05 "
872  "00 00|\"; distance:0; content:\"|0c 00|\"; distance:19; within:2; content:\"|15 00 "
873  "00 00|\"; distance:20; within:4;",
874  57, 0);
875 
876  TEST_DONE;
877 }
878 
879 /**
880  * \brief Print list of DETECT_CONTENT SigMatch's allocated in a
881  * SigMatch list, from the current sm to the end
882  * \param sm pointer to the current SigMatch to start printing from
883  */
884 static void DetectContentPrintAll(SigMatch *sm)
885 {
886 #ifdef DEBUG
887  if (SCLogDebugEnabled()) {
888  int i = 0;
889 
890  if (sm == NULL)
891  return;
892 
893  SigMatch *first_sm = sm;
894 
895  /* Print all of them */
896  for (; first_sm != NULL; first_sm = first_sm->next) {
897  if (first_sm->type == DETECT_CONTENT) {
898  SCLogDebug("Printing SigMatch DETECT_CONTENT %d", ++i);
900  }
901  }
902  }
903 #endif /* DEBUG */
904 }
905 
906 static int g_file_data_buffer_id = 0;
907 static int g_dce_stub_data_buffer_id = 0;
908 
909 /**
910  * \test DetectContentParseTest01 this is a test to make sure we can deal with escaped colons
911  */
912 static int DetectContentParseTest01 (void)
913 {
914  int result = 1;
915  DetectContentData *cd = NULL;
916  const char *teststring = "abc\\:def";
917  const char *teststringparsed = "abc:def";
918 
919  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
920  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
921  FAIL_IF(spm_global_thread_ctx == NULL);
922 
923  cd = DetectContentParse(spm_global_thread_ctx, teststring);
924  if (cd != NULL) {
925  if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) {
926  SCLogDebug("expected %s got ", teststringparsed);
927  PrintRawUriFp(stdout,cd->content,cd->content_len);
928  SCLogDebug(": ");
929  result = 0;
930  DetectContentFree(NULL, cd);
931  }
932  } else {
933  SCLogDebug("expected %s got NULL: ", teststringparsed);
934  result = 0;
935  }
936  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
937  return result;
938 }
939 
940 /**
941  * \test DetectContentParseTest02 this is a test to make sure we can deal with escaped semi-colons
942  */
943 static int DetectContentParseTest02 (void)
944 {
945  int result = 1;
946  DetectContentData *cd = NULL;
947  const char *teststring = "abc\\;def";
948  const char *teststringparsed = "abc;def";
949 
950  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
951  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
952  FAIL_IF(spm_global_thread_ctx == NULL);
953 
954  cd = DetectContentParse(spm_global_thread_ctx, teststring);
955  if (cd != NULL) {
956  if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) {
957  SCLogDebug("expected %s got ", teststringparsed);
958  PrintRawUriFp(stdout,cd->content,cd->content_len);
959  SCLogDebug(": ");
960  result = 0;
961  DetectContentFree(NULL, cd);
962  }
963  } else {
964  SCLogDebug("expected %s got NULL: ", teststringparsed);
965  result = 0;
966  }
967  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
968  return result;
969 }
970 
971 /**
972  * \test DetectContentParseTest03 this is a test to make sure we can deal with escaped double-quotes
973  */
974 static int DetectContentParseTest03 (void)
975 {
976  int result = 1;
977  DetectContentData *cd = NULL;
978  const char *teststring = "abc\\\"def";
979  const char *teststringparsed = "abc\"def";
980 
981  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
982  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
983  FAIL_IF(spm_global_thread_ctx == NULL);
984 
985  cd = DetectContentParse(spm_global_thread_ctx, teststring);
986  if (cd != NULL) {
987  if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) {
988  SCLogDebug("expected %s got ", teststringparsed);
989  PrintRawUriFp(stdout,cd->content,cd->content_len);
990  SCLogDebug(": ");
991  result = 0;
992  DetectContentFree(NULL, cd);
993  }
994  } else {
995  SCLogDebug("expected %s got NULL: ", teststringparsed);
996  result = 0;
997  }
998  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
999  return result;
1000 }
1001 
1002 /**
1003  * \test DetectContentParseTest04 this is a test to make sure we can deal with escaped backslashes
1004  */
1005 static int DetectContentParseTest04 (void)
1006 {
1007  int result = 1;
1008  DetectContentData *cd = NULL;
1009  const char *teststring = "abc\\\\def";
1010  const char *teststringparsed = "abc\\def";
1011 
1012  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1013  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1014  FAIL_IF(spm_global_thread_ctx == NULL);
1015 
1016  cd = DetectContentParse(spm_global_thread_ctx, teststring);
1017  if (cd != NULL) {
1018  uint16_t len = (cd->content_len > strlen(teststringparsed));
1019  if (memcmp(cd->content, teststringparsed, len) != 0) {
1020  SCLogDebug("expected %s got ", teststringparsed);
1021  PrintRawUriFp(stdout,cd->content,cd->content_len);
1022  SCLogDebug(": ");
1023  result = 0;
1024  DetectContentFree(NULL, cd);
1025  }
1026  } else {
1027  SCLogDebug("expected %s got NULL: ", teststringparsed);
1028  result = 0;
1029  }
1030  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1031  return result;
1032 }
1033 
1034 /**
1035  * \test DetectContentParseTest05 test illegal escape
1036  */
1037 static int DetectContentParseTest05 (void)
1038 {
1039  int result = 1;
1040  DetectContentData *cd = NULL;
1041  const char *teststring = "abc\\def";
1042 
1043  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1044  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1045  FAIL_IF(spm_global_thread_ctx == NULL);
1046 
1047  cd = DetectContentParse(spm_global_thread_ctx, teststring);
1048  if (cd != NULL) {
1049  SCLogDebug("expected NULL got ");
1050  PrintRawUriFp(stdout,cd->content,cd->content_len);
1051  SCLogDebug(": ");
1052  result = 0;
1053  DetectContentFree(NULL, cd);
1054  }
1055  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1056  return result;
1057 }
1058 
1059 /**
1060  * \test DetectContentParseTest06 test a binary content
1061  */
1062 static int DetectContentParseTest06 (void)
1063 {
1064  int result = 1;
1065  DetectContentData *cd = NULL;
1066  const char *teststring = "a|42|c|44|e|46|";
1067  const char *teststringparsed = "abcdef";
1068 
1069  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1070  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1071  FAIL_IF(spm_global_thread_ctx == NULL);
1072 
1073  cd = DetectContentParse(spm_global_thread_ctx, teststring);
1074  if (cd != NULL) {
1075  uint16_t len = (cd->content_len > strlen(teststringparsed));
1076  if (memcmp(cd->content, teststringparsed, len) != 0) {
1077  SCLogDebug("expected %s got ", teststringparsed);
1078  PrintRawUriFp(stdout,cd->content,cd->content_len);
1079  SCLogDebug(": ");
1080  result = 0;
1081  DetectContentFree(NULL, cd);
1082  }
1083  } else {
1084  SCLogDebug("expected %s got NULL: ", teststringparsed);
1085  result = 0;
1086  }
1087  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1088  return result;
1089 }
1090 
1091 /**
1092  * \test DetectContentParseTest07 test an empty content
1093  */
1094 static int DetectContentParseTest07 (void)
1095 {
1096  int result = 1;
1097  DetectContentData *cd = NULL;
1098  const char *teststring = "";
1099 
1100  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1101  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1102  FAIL_IF(spm_global_thread_ctx == NULL);
1103 
1104  cd = DetectContentParse(spm_global_thread_ctx, teststring);
1105  if (cd != NULL) {
1106  SCLogDebug("expected NULL got %p: ", cd);
1107  result = 0;
1108  DetectContentFree(NULL, cd);
1109  }
1110  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1111  return result;
1112 }
1113 
1114 /**
1115  * \test DetectContentParseTest08 test an empty content
1116  */
1117 static int DetectContentParseTest08 (void)
1118 {
1119  int result = 1;
1120  DetectContentData *cd = NULL;
1121  const char *teststring = "";
1122 
1123  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1124  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1125  FAIL_IF(spm_global_thread_ctx == NULL);
1126 
1127  cd = DetectContentParse(spm_global_thread_ctx, teststring);
1128  if (cd != NULL) {
1129  SCLogDebug("expected NULL got %p: ", cd);
1130  result = 0;
1131  DetectContentFree(NULL, cd);
1132  }
1133  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1134  return result;
1135 }
1136 
1137 /**
1138  * \test Test packet Matches
1139  * \param raw_eth_pkt pointer to the ethernet packet
1140  * \param pktsize size of the packet
1141  * \param sig pointer to the signature to test
1142  * \param sid sid number of the signature
1143  * \retval return 1 if match
1144  * \retval return 0 if not
1145  */
1146 static int DetectContentLongPatternMatchTest(uint8_t *raw_eth_pkt, uint16_t pktsize, const char *sig,
1147  uint32_t sid)
1148 {
1149  int result = 0;
1150 
1151  Packet *p = PacketGetFromAlloc();
1152  if (unlikely(p == NULL))
1153  return 0;
1155 
1156  ThreadVars th_v;
1157  DetectEngineThreadCtx *det_ctx = NULL;
1158 
1159  memset(&dtv, 0, sizeof(DecodeThreadVars));
1160  memset(&th_v, 0, sizeof(th_v));
1161 
1163  DecodeEthernet(&th_v, &dtv, p, raw_eth_pkt, pktsize);
1164 
1166  if (de_ctx == NULL) {
1167  goto end;
1168  }
1169 
1170  de_ctx->flags |= DE_QUIET;
1171 
1172  de_ctx->sig_list = SigInit(de_ctx, sig);
1173  if (de_ctx->sig_list == NULL) {
1174  goto end;
1175  }
1176  de_ctx->sig_list->next = NULL;
1177 
1181  ->ctx;
1182  if (co->flags & DETECT_CONTENT_RELATIVE_NEXT) {
1183  printf("relative next flag set on final match which is content: ");
1184  goto end;
1185  }
1186  }
1187 
1188  SCLogDebug("---DetectContentLongPatternMatchTest---");
1189  DetectContentPrintAll(de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_MATCH]);
1190 
1192  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1193 
1194  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1195  if (PacketAlertCheck(p, sid) != 1) {
1196  goto end;
1197  }
1198 
1199  result = 1;
1200 end:
1201  if (de_ctx != NULL)
1202  {
1205  if (det_ctx != NULL)
1206  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1208  }
1209  PacketRecycle(p);
1210  FlowShutdown();
1211 
1212  SCFree(p);
1213  return result;
1214 }
1215 
1216 /**
1217  * \brief Wrapper for DetectContentLongPatternMatchTest
1218  */
1219 static int DetectContentLongPatternMatchTestWrp(const char *sig, uint32_t sid)
1220 {
1221  /** Real packet with the following tcp data:
1222  * "Hi, this is a big test to check content matches of splitted"
1223  * "patterns between multiple chunks!"
1224  * (without quotes! :) )
1225  */
1226  uint8_t raw_eth_pkt[] = {
1227  0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
1228  0x00,0x00,0x00,0x00,0x08,0x00,0x45,0x00,
1229  0x00,0x85,0x00,0x01,0x00,0x00,0x40,0x06,
1230  0x7c,0x70,0x7f,0x00,0x00,0x01,0x7f,0x00,
1231  0x00,0x01,0x00,0x14,0x00,0x50,0x00,0x00,
1232  0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x02,
1233  0x20,0x00,0xc9,0xad,0x00,0x00,0x48,0x69,
1234  0x2c,0x20,0x74,0x68,0x69,0x73,0x20,0x69,
1235  0x73,0x20,0x61,0x20,0x62,0x69,0x67,0x20,
1236  0x74,0x65,0x73,0x74,0x20,0x74,0x6f,0x20,
1237  0x63,0x68,0x65,0x63,0x6b,0x20,0x63,0x6f,
1238  0x6e,0x74,0x65,0x6e,0x74,0x20,0x6d,0x61,
1239  0x74,0x63,0x68,0x65,0x73,0x20,0x6f,0x66,
1240  0x20,0x73,0x70,0x6c,0x69,0x74,0x74,0x65,
1241  0x64,0x20,0x70,0x61,0x74,0x74,0x65,0x72,
1242  0x6e,0x73,0x20,0x62,0x65,0x74,0x77,0x65,
1243  0x65,0x6e,0x20,0x6d,0x75,0x6c,0x74,0x69,
1244  0x70,0x6c,0x65,0x20,0x63,0x68,0x75,0x6e,
1245  0x6b,0x73,0x21 }; /* end raw_eth_pkt */
1246 
1247  return DetectContentLongPatternMatchTest(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
1248  sig, sid);
1249 }
1250 
1251 /**
1252  * \test Check if we match a normal pattern (not splitted)
1253  */
1254 static int DetectContentLongPatternMatchTest01(void)
1255 {
1256  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
1257  " content:\"Hi, this is a big test\"; sid:1;)";
1258  return DetectContentLongPatternMatchTestWrp(sig, 1);
1259 }
1260 
1261 /**
1262  * \test Check if we match a splitted pattern
1263  */
1264 static int DetectContentLongPatternMatchTest02(void)
1265 {
1266  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
1267  " content:\"Hi, this is a big test to check content matches of"
1268  " splitted patterns between multiple chunks!\"; sid:1;)";
1269  return DetectContentLongPatternMatchTestWrp(sig, 1);
1270 }
1271 
1272 /**
1273  * \test Check that we don't match the signature if one of the splitted
1274  * chunks doesn't match the packet
1275  */
1276 static int DetectContentLongPatternMatchTest03(void)
1277 {
1278  /** The last chunk of the content should not match */
1279  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
1280  " content:\"Hi, this is a big test to check content matches of"
1281  " splitted patterns between multiple splitted chunks!\"; sid:1;)";
1282  return (DetectContentLongPatternMatchTestWrp(sig, 1) == 0) ? 1: 0;
1283 }
1284 
1285 /**
1286  * \test Check if we match multiple content (not splitted)
1287  */
1288 static int DetectContentLongPatternMatchTest04(void)
1289 {
1290  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1291  " content:\"Hi, this is\"; depth:15 ;content:\"a big test\"; "
1292  " within:15; content:\"to check content matches of\"; "
1293  " within:30; content:\"splitted patterns\"; distance:1; "
1294  " within:30; "
1295  " sid:1;)";
1296  return DetectContentLongPatternMatchTestWrp(sig, 1);
1297 }
1298 
1299 /**
1300  * \test Check that we match packets with multiple chunks and not chunks
1301  * Here we should specify only contents that fit in 32 bytes
1302  * Each of them with their modifier values
1303  */
1304 static int DetectContentLongPatternMatchTest05(void)
1305 {
1306  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1307  " content:\"Hi, this is a big\"; depth:17; "
1308  " isdataat:30, relative; "
1309  " content:\"test\"; within: 5; distance:1; "
1310  " isdataat:15, relative; "
1311  " content:\"of splitted\"; within:37; distance:15; "
1312  " isdataat:20,relative; "
1313  " content:\"patterns\"; within:9; distance:1; "
1314  " isdataat:10, relative; "
1315  " sid:1;)";
1316  return DetectContentLongPatternMatchTestWrp(sig, 1);
1317 }
1318 
1319 /**
1320  * \test Check that we match packets with multiple chunks and not chunks
1321  * Here we should specify contents that fit and contents that must be splitted
1322  * Each of them with their modifier values
1323  */
1324 static int DetectContentLongPatternMatchTest06(void)
1325 {
1326  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1327  " content:\"Hi, this is a big test to check cont\"; depth:36;"
1328  " content:\"ent matches\"; within:11; distance:0; "
1329  " content:\"of splitted patterns between multiple\"; "
1330  " within:38; distance:1; "
1331  " content:\"chunks!\"; within: 8; distance:1; "
1332  " sid:1;)";
1333  return DetectContentLongPatternMatchTestWrp(sig, 1);
1334 }
1335 
1336 /**
1337  * \test Check if we match contents that are in the payload
1338  * but not in the same order as specified in the signature
1339  */
1340 static int DetectContentLongPatternMatchTest07(void)
1341 {
1342  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1343  " content:\"chunks!\"; "
1344  " content:\"content matches\"; offset:32; depth:47; "
1345  " content:\"of splitted patterns between multiple\"; "
1346  " content:\"Hi, this is a big\"; offset:0; depth:17; "
1347  " sid:1;)";
1348  return DetectContentLongPatternMatchTestWrp(sig, 1);
1349 }
1350 
1351 /**
1352  * \test Check if we match contents that are in the payload
1353  * but not in the same order as specified in the signature
1354  */
1355 static int DetectContentLongPatternMatchTest08(void)
1356 {
1357  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1358  " content:\"ent matches\"; "
1359  " content:\"of splitted patterns between multiple\"; "
1360  " within:38; distance:1; "
1361  " content:\"chunks!\"; within: 8; distance:1; "
1362  " content:\"Hi, this is a big test to check cont\"; depth:36;"
1363  " sid:1;)";
1364  return DetectContentLongPatternMatchTestWrp(sig, 1);
1365 }
1366 
1367 /**
1368  * \test Check if we match contents that are in the payload
1369  * but not in the same order as specified in the signature
1370  */
1371 static int DetectContentLongPatternMatchTest09(void)
1372 {
1373  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1374  " content:\"ent matches\"; "
1375  " content:\"of splitted patterns between multiple\"; "
1376  " offset:47; depth:85; "
1377  " content:\"chunks!\"; within: 8; distance:1; "
1378  " content:\"Hi, this is a big test to chec\"; depth:36;"
1379  " content:\"k cont\"; distance:0; within:6;"
1380  " sid:1;)";
1381  return DetectContentLongPatternMatchTestWrp(sig, 1);
1382 }
1383 
1384 /**
1385  * \test Check if we match two consecutive simple contents
1386  */
1387 static int DetectContentLongPatternMatchTest10(void)
1388 {
1389  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1390  " content:\"Hi, this is a big test to check \"; "
1391  " content:\"con\"; "
1392  " sid:1;)";
1393  return DetectContentLongPatternMatchTestWrp(sig, 1);
1394 }
1395 
1396 /**
1397  * \test Check if we match two contents of length 1
1398  */
1399 static int DetectContentLongPatternMatchTest11(void)
1400 {
1401  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1402  " content:\"H\"; "
1403  " content:\"i\"; "
1404  " sid:1;)";
1405  return DetectContentLongPatternMatchTestWrp(sig, 1);
1406 }
1407 
1408 static int DetectContentParseTest09(void)
1409 {
1410  DetectContentData *cd = NULL;
1411  const char *teststring = "boo";
1412 
1413  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
1414  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1415  FAIL_IF(spm_global_thread_ctx == NULL);
1416 
1417  cd = DetectContentParse(spm_global_thread_ctx, teststring);
1418  FAIL_IF_NULL(cd);
1419  DetectContentFree(NULL, cd);
1420  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1421  PASS;
1422 }
1423 
1424 /**
1425  * \test Test cases where if within specified is < content length we invalidate
1426  * the sig.
1427  */
1428 static int DetectContentParseTest17(void)
1429 {
1430  int result = 0;
1431  const char *sigstr = "alert tcp any any -> any any (msg:\"Dummy\"; "
1432  "content:\"one\"; content:\"two\"; within:2; sid:1;)";
1433 
1435  if (de_ctx == NULL)
1436  goto end;
1437 
1438  de_ctx->sig_list = SigInit(de_ctx, sigstr);
1439  if (de_ctx->sig_list != NULL)
1440  goto end;
1441 
1442  result = 1;
1443 
1444 end:
1446  if (de_ctx != NULL)
1448  return result;
1449 }
1450 
1451 /**
1452  * \test Test content for dce sig.
1453  */
1454 static int DetectContentParseTest18(void)
1455 {
1458 
1459  Signature *s = SigAlloc();
1460  FAIL_IF_NULL(s);
1462  FAIL_IF_NOT(DetectContentSetup(de_ctx, s, "one") == 0);
1463  FAIL_IF(DetectBufferIsPresent(s, g_dce_stub_data_buffer_id));
1465  SigFree(de_ctx, s);
1466 
1467  s = SigAlloc();
1468  FAIL_IF_NULL(s);
1469  FAIL_IF_NOT(DetectContentSetup(de_ctx, s, "one") == 0);
1470  FAIL_IF(DetectBufferIsPresent(s, g_dce_stub_data_buffer_id));
1472  SigFree(de_ctx, s);
1473 
1475  PASS;
1476 }
1477 
1478 /**
1479  * \test Test content for dce sig.
1480  */
1481 
1482 static int DetectContentParseTest19(void)
1483 {
1484 
1487  de_ctx->flags |= DE_QUIET;
1488 
1489  Signature *s =
1490  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1491  "(msg:\"Testing dce iface, stub_data with content\"; "
1492  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1493  "dce_stub_data; "
1494  "content:\"one\"; distance:0; sid:1;)");
1495  FAIL_IF_NULL(s);
1496 
1497  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1498  FAIL_IF_NULL(sm);
1501 
1502  DetectContentData *data = (DetectContentData *)sm->ctx;
1504 
1506  "alert tcp any any -> any any "
1507  "(msg:\"Testing dce iface, stub_data with contents & distance, within\"; "
1508  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1509  "dce_stub_data; "
1510  "content:\"one\"; distance:0; content:\"two\"; within:10; sid:2;)");
1511  FAIL_IF_NULL(s);
1512  sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1513  FAIL_IF_NULL(sm);
1515  FAIL_IF_NULL(sm->next);
1516  sm = sm->next;
1519 
1520  data = (DetectContentData *)sm->ctx;
1522  FAIL_IF_NOT(data->within == 10);
1523 
1525  "alert tcp any any -> any any "
1526  "(msg:\"Testing dce iface, stub with contents, distance, within\"; "
1527  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1528  "dce_stub_data; "
1529  "content:\"one\"; distance:0; "
1530  "content:\"two\"; within:10; distance:2; sid:3;)");
1531  FAIL_IF_NULL(s);
1532  sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1533  FAIL_IF_NULL(sm);
1535  FAIL_IF_NULL(sm->next);
1536  sm = sm->next;
1538  data = (DetectContentData *)sm->ctx;
1540  FAIL_IF_NOT(data->within == 10);
1541  FAIL_IF_NOT(data->distance == 2);
1543 
1544  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1545  "(msg:\"Testing content\"; "
1546  "content:\"one\"; sid:4;)");
1547  FAIL_IF_NULL(s);
1548  FAIL_IF(DetectBufferIsPresent(s, g_dce_stub_data_buffer_id));
1550 
1552  PASS;
1553 }
1554 
1555 /**
1556  * \test Test content for dce sig.
1557  */
1558 static int DetectContentParseTest20(void)
1559 {
1560  DetectEngineCtx *de_ctx = NULL;
1561  int result = 1;
1562 
1564  if (de_ctx == NULL)
1565  goto end;
1566 
1567  de_ctx->flags |= DE_QUIET;
1569  "alert udp any any -> any any "
1570  "(msg:\"test\"; content:\"\"; sid:238012;)");
1571  if (de_ctx->sig_list != NULL) {
1572  result = 0;
1573  goto end;
1574  }
1575 
1576  end:
1580 
1581  return result;
1582 }
1583 
1584 /**
1585  * \test Parsing test
1586  */
1587 static int DetectContentParseTest21(void)
1588 {
1589  DetectEngineCtx *de_ctx = NULL;
1590  int result = 1;
1591 
1593  if (de_ctx == NULL)
1594  goto end;
1595 
1596  de_ctx->flags |= DE_QUIET;
1598  "alert udp any any -> any any "
1599  "(msg:\"test\"; content:\"; sid:238012;)");
1600  if (de_ctx->sig_list != NULL) {
1601  result = 0;
1602  goto end;
1603  }
1604 
1605  end:
1609 
1610  return result;
1611 }
1612 
1613 /**
1614  * \test Parsing test
1615  */
1616 static int DetectContentParseTest22(void)
1617 {
1618  DetectEngineCtx *de_ctx = NULL;
1619  int result = 1;
1620 
1622  if (de_ctx == NULL)
1623  goto end;
1624 
1625  de_ctx->flags |= DE_QUIET;
1627  "alert udp any any -> any any "
1628  "(msg:\"test\"; content:\"boo; sid:238012;)");
1629  if (de_ctx->sig_list != NULL) {
1630  result = 0;
1631  goto end;
1632  }
1633 
1634  end:
1638 
1639  return result;
1640 }
1641 
1642 /**
1643  * \test Parsing test
1644  */
1645 static int DetectContentParseTest23(void)
1646 {
1647  DetectEngineCtx *de_ctx = NULL;
1648  int result = 1;
1649 
1651  if (de_ctx == NULL)
1652  goto end;
1653 
1654  de_ctx->flags |= DE_QUIET;
1656  "alert udp any any -> any any "
1657  "(msg:\"test\"; content:boo\"; sid:238012;)");
1658  if (de_ctx->sig_list != NULL) {
1659  result = 0;
1660  goto end;
1661  }
1662 
1663  end:
1667 
1668  return result;
1669 }
1670 
1671 /**
1672  * \test Parsing test
1673  */
1674 static int DetectContentParseTest24(void)
1675 {
1676  DetectEngineCtx *de_ctx = NULL;
1677  DetectContentData *cd = 0;
1678  Signature *s = NULL;
1679  int result = 1;
1680 
1682  if (de_ctx == NULL)
1683  goto end;
1684 
1685  de_ctx->flags |= DE_QUIET;
1686  s = de_ctx->sig_list = SigInit(de_ctx,
1687  "alert udp any any -> any any "
1688  "(msg:\"test\"; content: !\"boo\"; sid:238012;)");
1689  if (de_ctx->sig_list == NULL) {
1690  printf("de_ctx->sig_list == NULL: ");
1691  result = 0;
1692  goto end;
1693  }
1694 
1695  if (s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH] == NULL ||
1697  printf("de_ctx->pmatch_tail == NULL || de_ctx->pmatch_tail->ctx == NULL: ");
1698  result = 0;
1699  goto end;
1700  }
1701 
1703  result = (strncmp("boo", (char *)cd->content, cd->content_len) == 0);
1704 
1705 end:
1709 
1710  return result;
1711 }
1712 
1713 /**
1714  * \test Parsing test
1715  */
1716 static int DetectContentParseTest25(void)
1717 {
1718  DetectEngineCtx *de_ctx = NULL;
1719  int result = 1;
1720 
1722  if (de_ctx == NULL)
1723  goto end;
1724 
1725  de_ctx->flags |= DE_QUIET;
1727  "alert udp any any -> any any "
1728  "(msg:\"test\"; content:\"|\"; sid:1;)");
1729  if (de_ctx->sig_list != NULL) {
1730  result = 0;
1731  goto end;
1732  }
1733 
1734  end:
1738 
1739  return result;
1740 }
1741 
1742 /**
1743  * \test Parsing test
1744  */
1745 static int DetectContentParseTest26(void)
1746 {
1747  DetectEngineCtx *de_ctx = NULL;
1748  int result = 1;
1749 
1751  if (de_ctx == NULL)
1752  goto end;
1753 
1754  de_ctx->flags |= DE_QUIET;
1756  "alert udp any any -> any any "
1757  "(msg:\"test\"; content:\"|af\"; sid:1;)");
1758  if (de_ctx->sig_list != NULL) {
1759  result = 0;
1760  goto end;
1761  }
1762 
1763  end:
1767 
1768  return result;
1769 }
1770 
1771 /**
1772  * \test Parsing test
1773  */
1774 static int DetectContentParseTest27(void)
1775 {
1776  DetectEngineCtx *de_ctx = NULL;
1777  int result = 1;
1778 
1780  if (de_ctx == NULL)
1781  goto end;
1782 
1783  de_ctx->flags |= DE_QUIET;
1785  "alert udp any any -> any any "
1786  "(msg:\"test\"; content:\"af|\"; sid:1;)");
1787  if (de_ctx->sig_list != NULL) {
1788  result = 0;
1789  goto end;
1790  }
1791 
1792  end:
1796 
1797  return result;
1798 }
1799 
1800 /**
1801  * \test Parsing test
1802  */
1803 static int DetectContentParseTest28(void)
1804 {
1805  DetectEngineCtx *de_ctx = NULL;
1806  int result = 1;
1807 
1809  if (de_ctx == NULL)
1810  goto end;
1811 
1812  de_ctx->flags |= DE_QUIET;
1814  "alert udp any any -> any any "
1815  "(msg:\"test\"; content:\"|af|\"; sid:1;)");
1816  if (de_ctx->sig_list == NULL) {
1817  result = 0;
1818  goto end;
1819  }
1820 
1821  end:
1825 
1826  return result;
1827 }
1828 
1829 /**
1830  * \test Parsing test
1831  */
1832 static int DetectContentParseTest29(void)
1833 {
1834  DetectEngineCtx *de_ctx = NULL;
1835  int result = 1;
1836 
1838  if (de_ctx == NULL)
1839  goto end;
1840 
1841  de_ctx->flags |= DE_QUIET;
1843  "alert udp any any -> any any "
1844  "(msg:\"test\"; content:\"aast|\"; sid:1;)");
1845  if (de_ctx->sig_list != NULL) {
1846  result = 0;
1847  goto end;
1848  }
1849 
1850  end:
1854 
1855  return result;
1856 }
1857 
1858 /**
1859  * \test Parsing test
1860  */
1861 static int DetectContentParseTest30(void)
1862 {
1863  DetectEngineCtx *de_ctx = NULL;
1864  int result = 1;
1865 
1867  if (de_ctx == NULL)
1868  goto end;
1869 
1870  de_ctx->flags |= DE_QUIET;
1872  "alert udp any any -> any any "
1873  "(msg:\"test\"; content:\"aast|af\"; sid:1;)");
1874  if (de_ctx->sig_list != NULL) {
1875  result = 0;
1876  goto end;
1877  }
1878 
1879  end:
1883 
1884  return result;
1885 }
1886 
1887 /**
1888  * \test Parsing test
1889  */
1890 static int DetectContentParseTest31(void)
1891 {
1892  DetectEngineCtx *de_ctx = NULL;
1893  int result = 1;
1894 
1896  if (de_ctx == NULL)
1897  goto end;
1898 
1899  de_ctx->flags |= DE_QUIET;
1901  "alert udp any any -> any any "
1902  "(msg:\"test\"; content:\"aast|af|\"; sid:1;)");
1903  if (de_ctx->sig_list == NULL) {
1904  result = 0;
1905  goto end;
1906  }
1907 
1908  end:
1912 
1913  return result;
1914 }
1915 
1916 /**
1917  * \test Parsing test
1918  */
1919 static int DetectContentParseTest32(void)
1920 {
1921  DetectEngineCtx *de_ctx = NULL;
1922  int result = 1;
1923 
1925  if (de_ctx == NULL)
1926  goto end;
1927 
1928  de_ctx->flags |= DE_QUIET;
1930  "alert udp any any -> any any "
1931  "(msg:\"test\"; content:\"|af|asdf\"; sid:1;)");
1932  if (de_ctx->sig_list == NULL) {
1933  result = 0;
1934  goto end;
1935  }
1936 
1937  end:
1941 
1942  return result;
1943 }
1944 
1945 /**
1946  * \test Parsing test
1947  */
1948 static int DetectContentParseTest33(void)
1949 {
1950  DetectEngineCtx *de_ctx = NULL;
1951  int result = 1;
1952 
1954  if (de_ctx == NULL)
1955  goto end;
1956 
1957  de_ctx->flags |= DE_QUIET;
1959  "alert udp any any -> any any "
1960  "(msg:\"test\"; content:\"|af|af|\"; sid:1;)");
1961  if (de_ctx->sig_list != NULL) {
1962  result = 0;
1963  goto end;
1964  }
1965 
1966  end:
1970 
1971  return result;
1972 }
1973 
1974 /**
1975  * \test Parsing test
1976  */
1977 static int DetectContentParseTest34(void)
1978 {
1979  DetectEngineCtx *de_ctx = NULL;
1980  int result = 1;
1981 
1983  if (de_ctx == NULL)
1984  goto end;
1985 
1986  de_ctx->flags |= DE_QUIET;
1988  "alert udp any any -> any any "
1989  "(msg:\"test\"; content:\"|af|af|af\"; sid:1;)");
1990  if (de_ctx->sig_list != NULL) {
1991  result = 0;
1992  goto end;
1993  }
1994 
1995  end:
1999 
2000  return result;
2001 }
2002 
2003 /**
2004  * \test Parsing test
2005  */
2006 static int DetectContentParseTest35(void)
2007 {
2008  DetectEngineCtx *de_ctx = NULL;
2009  int result = 1;
2010 
2012  if (de_ctx == NULL)
2013  goto end;
2014 
2015  de_ctx->flags |= DE_QUIET;
2017  "alert udp any any -> any any "
2018  "(msg:\"test\"; content:\"|af|af|af|\"; sid:1;)");
2019  if (de_ctx->sig_list == NULL) {
2020  result = 0;
2021  goto end;
2022  }
2023 
2024  end:
2028 
2029  return result;
2030 }
2031 
2032 static int SigTestPositiveTestContent(const char *rule, uint8_t *buf)
2033 {
2034  uint16_t buflen = strlen((char *)buf);
2035  ThreadVars th_v;
2036  DetectEngineThreadCtx *det_ctx = NULL;
2037 
2038  memset(&th_v, 0, sizeof(th_v));
2039  Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2040  FAIL_IF_NULL(p);
2041 
2044  de_ctx->flags |= DE_QUIET;
2045 
2046  de_ctx->sig_list = SigInit(de_ctx, rule);
2048 
2050  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2051  FAIL_IF_NULL(det_ctx);
2052 
2053  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2054 
2055  FAIL_IF(PacketAlertCheck(p, 1) != 1);
2056 
2057  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2059 
2060  UTHFreePackets(&p, 1);
2061  PASS;
2062 }
2063 
2064 static int DetectContentParseTest41(void)
2065 {
2066  int result = 1;
2067  DetectContentData *cd = NULL;
2068  int patlen = 255;
2069  char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2070  if (unlikely(teststring == NULL))
2071  return 0;
2072  int idx = 0;
2073  for (int i = 0; i < patlen; idx++, i++) {
2074  teststring[idx] = 'a';
2075  }
2076  teststring[idx++] = '\0';
2077 
2078  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
2079  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2080  FAIL_IF(spm_global_thread_ctx == NULL);
2081 
2082  cd = DetectContentParse(spm_global_thread_ctx, teststring);
2083  if (cd == NULL) {
2084  SCLogDebug("expected not NULL");
2085  result = 0;
2086  }
2087 
2088  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2089  SCFree(teststring);
2090  DetectContentFree(NULL, cd);
2091  return result;
2092 }
2093 
2094 /**
2095  * Tests that content lengths > 255 are supported.
2096  */
2097 static int DetectContentParseTest42(void)
2098 {
2099  int result = 1;
2100  DetectContentData *cd = NULL;
2101  int patlen = 256;
2102  char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2103  if (unlikely(teststring == NULL))
2104  return 0;
2105  int idx = 0;
2106  for (int i = 0; i < patlen; idx++, i++) {
2107  teststring[idx] = 'a';
2108  }
2109  teststring[idx++] = '\0';
2110 
2111  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
2112  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2113  FAIL_IF(spm_global_thread_ctx == NULL);
2114 
2115  cd = DetectContentParse(spm_global_thread_ctx, teststring);
2116  if (cd == NULL) {
2117  SCLogDebug("expected not NULL");
2118  result = 0;
2119  }
2120 
2121  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2122  SCFree(teststring);
2123  DetectContentFree(NULL, cd);
2124  return result;
2125 }
2126 
2127 static int DetectContentParseTest43(void)
2128 {
2129  int result = 1;
2130  DetectContentData *cd = NULL;
2131  int patlen = 258;
2132  char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2133  if (unlikely(teststring == NULL))
2134  return 0;
2135  int idx = 0;
2136  teststring[idx++] = '|';
2137  teststring[idx++] = '4';
2138  teststring[idx++] = '6';
2139  teststring[idx++] = '|';
2140  for (int i = 0; i < (patlen - 4); idx++, i++) {
2141  teststring[idx] = 'a';
2142  }
2143  teststring[idx++] = '\0';
2144 
2145  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
2146  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2147  FAIL_IF(spm_global_thread_ctx == NULL);
2148 
2149  cd = DetectContentParse(spm_global_thread_ctx, teststring);
2150  if (cd == NULL) {
2151  SCLogDebug("expected not NULL");
2152  result = 0;
2153  }
2154 
2155  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2156  SCFree(teststring);
2157  DetectContentFree(NULL, cd);
2158  return result;
2159 }
2160 
2161 /**
2162  * Tests that content lengths > 255 are supported.
2163  */
2164 static int DetectContentParseTest44(void)
2165 {
2166  int result = 1;
2167  DetectContentData *cd = NULL;
2168  int patlen = 259;
2169  char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2170  if (unlikely(teststring == NULL))
2171  return 0;
2172  int idx = 0;
2173  teststring[idx++] = '|';
2174  teststring[idx++] = '4';
2175  teststring[idx++] = '6';
2176  teststring[idx++] = '|';
2177  for (int i = 0; i < (patlen - 4); idx++, i++) {
2178  teststring[idx] = 'a';
2179  }
2180  teststring[idx++] = '\0';
2181 
2182  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
2183  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2184  FAIL_IF(spm_global_thread_ctx == NULL);
2185 
2186  cd = DetectContentParse(spm_global_thread_ctx, teststring);
2187  if (cd == NULL) {
2188  SCLogDebug("expected not NULL");
2189  result = 0;
2190  }
2191 
2192  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2193  SCFree(teststring);
2194  DetectContentFree(NULL, cd);
2195  return result;
2196 }
2197 
2198 /**
2199  * \test Parsing test to check for unescaped quote within content section
2200  */
2201 static int DetectContentParseTest45(void)
2202 {
2203  DetectEngineCtx *de_ctx = NULL;
2204 
2207 
2208  de_ctx->flags |= DE_QUIET;
2210  "alert tcp any any -> any any "
2211  "(msg:\"test\"; content:\"|ff|\" content:\"TEST\"; sid:1;)");
2213 
2215 
2216  PASS;
2217 }
2218 
2219 static int SigTestNegativeTestContent(const char *rule, uint8_t *buf)
2220 {
2221  uint16_t buflen = strlen((char *)buf);
2222  Packet *p = NULL;
2223  ThreadVars th_v;
2224  DetectEngineThreadCtx *det_ctx = NULL;
2225  int result = 0;
2226  memset(&th_v, 0, sizeof(th_v));
2227 
2228  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2229 
2231  if (de_ctx == NULL)
2232  goto end;
2233 
2234  de_ctx->flags |= DE_QUIET;
2235 
2236  de_ctx->sig_list = SigInit(de_ctx, rule);
2237  if (de_ctx->sig_list == NULL) {
2238  goto end;
2239  }
2240 
2242  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2243 
2244  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2245  if (PacketAlertCheck(p, 1) != 0) {
2246  goto end;
2247  }
2248 
2249  result = 1;
2250 end:
2251  if (det_ctx != NULL) {
2252  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2253  }
2254  if (de_ctx != NULL) {
2258  }
2259  UTHFreePackets(&p, 1);
2260  return result;
2261 }
2262 
2263 /**
2264  * \test A positive test that checks that the content string doesn't contain
2265  * the negated content
2266  */
2267 static int SigTest41TestNegatedContent(void)
2268 {
2269  return SigTestPositiveTestContent("alert tcp any any -> any any "
2270  "(msg:\"HTTP URI cap\"; content:!\"GES\"; sid:1;)",
2271 
2272  (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\n"
2273  "GET /two/ HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2274 }
2275 
2276 /**
2277  * \test crash condition: as packet has no direction, it defaults to toclient
2278  * in stream ctx inspection of packet. There a null ptr deref happens
2279  * We don't care about the match/nomatch here.
2280  */
2281 static int SigTest41aTestNegatedContent(void)
2282 {
2283  (void)SigTestPositiveTestContent("alert tcp any any -> any any (msg:\"HTTP URI cap\"; flow:to_server; content:\"GET\"; sid:1;)", (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\nGET /two/ HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2284  return 1;
2285 }
2286 
2287 
2288 /**
2289  * \test A positive test that checks that the content string doesn't contain
2290  * the negated content within the specified depth
2291  */
2292 static int SigTest42TestNegatedContent(void)
2293 {
2294  return SigTestPositiveTestContent(
2295  "alert tcp any any -> any any (content:!\"eeeeeeeeeee\"; depth:22; offset:35; sid:1;)",
2296  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2297 }
2298 
2299 /**
2300  * \test A negative test that checks that the content string doesn't contain
2301  * the negated content within the specified depth, and also after the
2302  * specified offset. Since the content is there, the match fails.
2303  *
2304  * Match is at offset:23, depth:34
2305  */
2306 static int SigTest43TestNegatedContent(void)
2307 {
2308  return SigTestNegativeTestContent(
2309  "alert tcp any any -> any any (content:!\"eeeeeeeeeee\"; depth:34; offset:23; sid:1;)",
2310  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2311 }
2312 
2313 /**
2314  * \test A negative test that checks that the content string doesn't contain
2315  * the negated content after the specified offset and within the specified
2316  * depth.
2317  */
2318 static int SigTest44TestNegatedContent(void)
2319 {
2320  return SigTestPositiveTestContent(
2321  "alert tcp any any -> any any (content:!\"eeeeeeeeeee\"; offset:40; depth:35; sid:1;)",
2322  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2323 }
2324 
2325 /**
2326  * \test A positive test that uses a combination of content string with negated
2327  * content string
2328  */
2329 static int SigTest45TestNegatedContent(void)
2330 {
2331  return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:5; "
2332  "content:!\"eeeeeeeeeee\"; depth:23; sid:1;)",
2333  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2334 }
2335 
2336 /**
2337  * \test A negative test that uses a combination of content string with negated
2338  * content string, with we receiving a failure for 'onee' itself.
2339  */
2340 static int SigTest46TestNegatedContent(void)
2341 {
2342  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaaE\"; "
2343  "content:!\"eeeeeeeeeee\"; depth:23; sid:1;)",
2344  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2345 }
2346 
2347 /**
2348  * \test A negative test that uses a combination of content string with negated
2349  * content string, with we receiving a failure of first content's offset
2350  * condition
2351  */
2352 static int SigTest47TestNegatedContent(void)
2353 {
2354  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; offset:5; "
2355  "content:!\"eeeeeeeeeee\"; depth:23; sid:1;)",
2356  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2357 }
2358 
2359 /**
2360  * \test A positive test that checks that we don't have a negated content within
2361  * the specified length from the previous content match.
2362  */
2363 static int SigTest48TestNegatedContent(void)
2364 {
2365  return SigTestPositiveTestContent(
2366  "alert tcp any any -> any any (content:\"GET\"; content:!\"GES\"; within:26; sid:1;)",
2367  (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\nGET /two/ "
2368  "HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2369 }
2370 
2371 /**
2372  * \test A negative test that checks the combined use of content and negated
2373  * content with the use of within
2374  */
2375 static int SigTest49TestNegatedContent(void)
2376 {
2377  return SigTestNegativeTestContent(
2378  "alert tcp any any -> any any (content:\"GET\"; content:!\"Host\"; within:26; sid:1;)",
2379  (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\nGET /two/ "
2380  "HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2381 }
2382 
2383 /**
2384  * \test A positive test that checks the combined use of content and negated
2385  * content with the use of distance
2386  */
2387 static int SigTest50TestNegatedContent(void)
2388 {
2389  return SigTestPositiveTestContent(
2390  "alert tcp any any -> any any (content:\"GET\"; content:!\"GES\"; distance:25; sid:1;)",
2391  (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\nGET /two/ "
2392  "HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2393 }
2394 
2395 /**
2396  * \test A negative test that checks the combined use of content and negated
2397  * content with the use of distance
2398  *
2399  * First GET at offset 0
2400  * First Host at offset 21
2401  */
2402 static int SigTest51TestNegatedContent(void)
2403 {
2404  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"GET\"; content:!\"Host\"; distance:17; sid:1;)", (uint8_t *)"GET /one/ HTTP/1.1\r\nHost: one.example.org\r\n\r\n\r\nGET /two/ HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2405 }
2406 
2407 /**
2408  * \test A negative test that checks the combined use of content and negated
2409  * content, with the content not being present
2410  */
2411 static int SigTest52TestNegatedContent(void)
2412 {
2413  return SigTestNegativeTestContent(
2414  "alert tcp any any -> any any (content:\"GES\"; content:!\"BOO\"; sid:1;)",
2415  (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\nGET /two/ "
2416  "HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2417 }
2418 
2419 /**
2420  * \test A negative test that checks the combined use of content and negated
2421  * content, in the presence of within
2422  */
2423 static int SigTest53TestNegatedContent(void)
2424 {
2425  return SigTestNegativeTestContent(
2426  "alert tcp any any -> any any (content:\"aaa\"; content:!\"Ggggg\"; within:56; sid:1;)",
2427  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2428 }
2429 
2430 /**
2431  * \test A positive test that checks the combined use of content and negated
2432  * content, in the presence of within
2433  */
2434 static int SigTest54TestNegatedContent(void)
2435 {
2436  return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2437  "content:!\"gggggg\"; within:20; sid:1;)",
2438  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff ggggggggg hhhhhhhh");
2439 }
2440 
2441 /**
2442  * \test A negative test that checks the use of negated content along with
2443  * the presence of depth
2444  */
2445 static int SigTest55TestNegatedContent(void)
2446 {
2447  return SigTestNegativeTestContent(
2448  "alert tcp any any -> any any (content:!\"aaa\"; depth:5; sid:1;)",
2449  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2450 }
2451 
2452 /**
2453  * \test A positive test that checks the combined use of 2 contents in the
2454  * presence of within
2455  */
2456 static int SigTest56TestNegatedContent(void)
2457 {
2458  return SigTestPositiveTestContent(
2459  "alert tcp any any -> any any (content:\"aaa\"; content:\"Ggggg\"; within:56; sid:1;)",
2460  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Gggggggg hhhhhhhh");
2461 }
2462 
2463 /**
2464  * \test A negative test that checks the combined use of content and negated
2465  * content, in the presence of within
2466  */
2467 static int SigTest57TestNegatedContent(void)
2468 {
2469  return SigTestNegativeTestContent(
2470  "alert tcp any any -> any any (content:\"aaa\"; content:!\"Ggggg\"; within:56; sid:1;)",
2471  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2472 }
2473 
2474 /**
2475  * \test A positive test that checks the combined use of content and negated
2476  * content, in the presence of distance
2477  */
2478 static int SigTest58TestNegatedContent(void)
2479 {
2480  return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2481  "content:!\"Ggggg\"; distance:57; sid:1;)",
2482  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2483 }
2484 
2485 /**
2486  * \test A negative test that checks the combined use of content and negated
2487  * content, in the presence of distance
2488  */
2489 static int SigTest59TestNegatedContent(void)
2490 {
2491  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2492  "content:!\"Gggg\"; distance:30; sid:1;)",
2493  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2494 }
2495 
2496 static int SigTest60TestNegatedContent(void)
2497 {
2498  return SigTestNegativeTestContent(
2499  "alert tcp any any -> any any (content:!\"aaa\"; content:\"Ggggg\"; sid:1;)",
2500  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2501 }
2502 
2503 static int SigTest61TestNegatedContent(void)
2504 {
2505  return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2506  "content:!\"Ggggg\"; within:30; sid:1;)",
2507  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2508 }
2509 
2510 /** \test Test negation in combination with within and depth
2511  *
2512  * Match of "aaa" at offset:0, depth:3
2513  * Match of "Gggggg" at offset:46, depth:52
2514  *
2515  * This signature should not match for the test to pass.
2516  */
2517 static int SigTest62TestNegatedContent(void)
2518 {
2519  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2520  "content:!\"Gggggg\"; within:49; sid:1;)",
2521  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2522 }
2523 
2524 static int SigTest63TestNegatedContent(void)
2525 {
2526  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2527  "content:!\"Gggggg\"; within:56; sid:1;)",
2528  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2529 }
2530 
2531 static int SigTest64TestNegatedContent(void)
2532 {
2533  return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2534  "content:!\"Gggggg\"; within:30; sid:1;)",
2535  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2536 }
2537 
2538 /** \test Test negation in combination with within and depth
2539  *
2540  * Match of "aaa" at offset:0, depth:3
2541  * Match of "gggggg" at offset:46, depth:52
2542  *
2543  * This signature should not match for the test to pass.
2544  */
2545 static int SigTest65TestNegatedContent(void)
2546 {
2547  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2548  "content:!\"Gggggg\"; distance:0; within:49; sid:1;)",
2549  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2550 }
2551 
2552 static int SigTest66TestNegatedContent(void)
2553 {
2554  return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2555  "content:!\"Gggggg\"; within:30; sid:1;)",
2556  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2557 }
2558 
2559 static int SigTest67TestNegatedContent(void)
2560 {
2561  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2562  "content:!\"XXXX\"; within:56; sid:1;)",
2563  (uint8_t *)"aaa bbbb cccc XXXXdddd eeeeeeeeeee ffffffffff XXXXggggg hhhhhhhh");
2564 }
2565 
2566 static int SigTest68TestNegatedContent(void)
2567 {
2568  return SigTestPositiveTestContent(
2569  "alert tcp any any -> any any (content:\"aaa\"; depth:10; content:\"cccc\"; offset:8; "
2570  "content:!\"Gggggg\"; within:28; content:\"hhhhhhhh\"; sid:1;)",
2571  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2572 }
2573 
2574 static int SigTest69TestNegatedContent(void)
2575 {
2576  return SigTestNegativeTestContent(
2577  "alert tcp any any -> any any (content:\"aaa\"; depth:10; content:\"cccc\"; offset:8; "
2578  "content:!\"Gggggg\"; within:48; content:\"hhhhhhhh\"; sid:1;)",
2579  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2580 }
2581 
2582 static int SigTest70TestNegatedContent(void)
2583 {
2584  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2585  "content:!\"Gggggg\"; within:52; sid:1;)",
2586  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2587 }
2588 
2589 /** \test within and distance */
2590 static int SigTest71TestNegatedContent(void)
2591 {
2592  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2593  "content:!\"Gggggg\"; within:40; distance:43; sid:1;)",
2594  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2595 }
2596 
2597 static int SigTest72TestNegatedContent(void)
2598 {
2599  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2600  "content:!\"Gggggg\"; within:49; distance:43; sid:1;)",
2601  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2602 }
2603 
2604 static int SigTest73TestNegatedContent(void)
2605 {
2606  return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:5; "
2607  "content:!\"eeeeeeeeeee\"; depth:35; sid:1;)",
2608  (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff ggggggggg hhhhhhhh");
2609 }
2610 
2611 static int SigTest74TestNegatedContent(void)
2612 {
2613  return SigTestPositiveTestContent("alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"USER\"; content:!\"PASS\"; sid:1;)", (uint8_t *)"USER apple");
2614 }
2615 
2616 static int SigTest75TestNegatedContent(void)
2617 {
2618  return SigTestPositiveTestContent("alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"USER\"; content:\"!PASS\"; sid:1;)", (uint8_t *)"USER !PASS");
2619 }
2620 
2621 static int SigTest76TestBug134(void)
2622 {
2623  uint8_t *buf = (uint8_t *)"test detect ${IFS} in traffic";
2624  uint16_t buflen = strlen((char *)buf);
2625  Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
2626  int result = 0;
2627  Flow f;
2628 
2629  memset(&f, 0, sizeof(Flow));
2630  FLOW_INITIALIZE(&f);
2631 
2632  p->dp = 515;
2635  p->flow = &f;
2636  p->flags |= PKT_HAS_FLOW;
2637 
2638  char sig[] = "alert tcp any any -> any 515 "
2639  "(msg:\"detect IFS\"; flow:to_server,established; content:\"${IFS}\";"
2640  " depth:50; offset:0; sid:900091; rev:1;)";
2641  if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
2642  result = 0;
2643  goto end;
2644  }
2645 
2646  result = 1;
2647 end:
2648  if (p != NULL)
2649  UTHFreePacket(p);
2650 
2651  FLOW_DESTROY(&f);
2652  return result;
2653 }
2654 
2655 static int SigTest77TestBug139(void)
2656 {
2657  uint8_t buf[] = {
2658  0x12, 0x23, 0x34, 0x35, 0x52, 0x52, 0x24, 0x42, 0x22, 0x24,
2659  0x52, 0x24, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x34 };
2660  uint16_t buflen = sizeof(buf);
2661  Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_UDP);
2662  int result = 0;
2663 
2664  p->dp = 53;
2665  char sig[] = "alert udp any any -> any 53 (msg:\"dns testing\";"
2666  " content:\"|00 00|\"; depth:5; offset:13; sid:9436601;"
2667  " rev:1;)";
2668  if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
2669  result = 0;
2670  goto end;
2671  }
2672 
2673  result = 1;
2674 end:
2675  if (p != NULL)
2676  UTHFreePacket(p);
2677  return result;
2678 }
2679 
2680 static int DetectLongContentTestCommon(const char *sig, uint32_t sid)
2681 {
2682  /* Packet with 512 A's in it for testing long content. */
2683  static uint8_t pkt[739] = {
2684  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2685  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
2686  0x02, 0xd5, 0x4a, 0x18, 0x40, 0x00, 0x40, 0x06,
2687  0xd7, 0xd6, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10,
2688  0x01, 0x0a, 0xdb, 0x36, 0x00, 0x50, 0xca, 0xc5,
2689  0xcc, 0xd1, 0x95, 0x77, 0x0f, 0x7d, 0x80, 0x18,
2690  0x00, 0xe5, 0x77, 0x9d, 0x00, 0x00, 0x01, 0x01,
2691  0x08, 0x0a, 0x1d, 0xe0, 0x86, 0xc6, 0xfc, 0x73,
2692  0x49, 0xf3, 0x50, 0x4f, 0x53, 0x54, 0x20, 0x2f,
2693  0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e,
2694  0x31, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2695  0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x63,
2696  0x75, 0x72, 0x6c, 0x2f, 0x37, 0x2e, 0x33, 0x37,
2697  0x2e, 0x30, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74,
2698  0x3a, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x36, 0x2e,
2699  0x31, 0x2e, 0x31, 0x30, 0x0d, 0x0a, 0x41, 0x63,
2700  0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x2a, 0x2f,
2701  0x2a, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65,
2702  0x6e, 0x74, 0x2d, 0x4c, 0x65, 0x6e, 0x67, 0x74,
2703  0x68, 0x3a, 0x20, 0x35, 0x32, 0x38, 0x0d, 0x0a,
2704  0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
2705  0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70,
2706  0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
2707  0x6e, 0x2f, 0x78, 0x2d, 0x77, 0x77, 0x77, 0x2d,
2708  0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x75, 0x72, 0x6c,
2709  0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x0d,
2710  0x0a, 0x0d, 0x0a, 0x58, 0x58, 0x58, 0x58, 0x58,
2711  0x58, 0x58, 0x58, 0x41, 0x41, 0x41, 0x41, 0x41,
2712  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2713  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2714  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2715  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2716  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2717  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2718  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2719  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2720  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2721  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2722  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2723  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2724  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2725  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2726  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2727  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2728  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2729  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2730  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2731  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2732  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2733  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2734  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2735  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2736  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2737  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2738  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2739  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2740  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2741  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2742  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2743  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2744  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2745  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2746  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2747  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2748  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2749  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2750  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2751  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2752  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2753  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2754  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2755  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2756  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2757  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2758  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2759  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2760  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2761  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2762  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2763  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2764  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2765  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2766  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2767  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2768  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2769  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2770  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2771  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2772  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2773  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2774  0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2775  0x41, 0x41, 0x41, 0x58, 0x58, 0x58, 0x58, 0x58,
2776  0x58, 0x58, 0x58
2777  };
2778 
2779  return DetectContentLongPatternMatchTest(pkt, (uint16_t)sizeof(pkt), sig,
2780  sid);
2781 }
2782 
2783 static int DetectLongContentTest1(void)
2784 {
2785  /* Signature with 256 A's. */
2786  const char *sig = "alert tcp any any -> any any (msg:\"Test Rule\"; content:\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"; sid:1;)";
2787 
2788  return DetectLongContentTestCommon(sig, 1);
2789 }
2790 
2791 static int DetectLongContentTest2(void)
2792 {
2793  /* Signature with 512 A's. */
2794  const char *sig = "alert tcp any any -> any any (msg:\"Test Rule\"; content:\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"; sid:1;)";
2795 
2796  return DetectLongContentTestCommon(sig, 1);
2797 }
2798 
2799 static int DetectLongContentTest3(void)
2800 {
2801  /* Signature with 513 A's. */
2802  const char *sig = "alert tcp any any -> any any (msg:\"Test Rule\"; content:\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"; sid:1;)";
2803 
2804  return !DetectLongContentTestCommon(sig, 1);
2805 }
2806 
2807 static int DetectBadBinContent(void)
2808 {
2809  DetectEngineCtx *de_ctx = NULL;
2812  de_ctx->flags |= DE_QUIET;
2814  de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|a|\"; sid:1;)"));
2816  de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|aa b|\"; sid:1;)"));
2818  de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|aa bz|\"; sid:1;)"));
2819  /* https://redmine.openinfosecfoundation.org/issues/5201 */
2821  de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|22 2 22|\"; sid:1;)"));
2823  PASS;
2824 }
2825 
2826 /**
2827  * \brief this function registers unit tests for DetectContent
2828  */
2829 static void DetectContentRegisterTests(void)
2830 {
2831  g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
2832  g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
2833 
2834  UtRegisterTest("DetectContentDepthTest01", DetectContentDepthTest01);
2835 
2836  UtRegisterTest("DetectContentParseTest01", DetectContentParseTest01);
2837  UtRegisterTest("DetectContentParseTest02", DetectContentParseTest02);
2838  UtRegisterTest("DetectContentParseTest03", DetectContentParseTest03);
2839  UtRegisterTest("DetectContentParseTest04", DetectContentParseTest04);
2840  UtRegisterTest("DetectContentParseTest05", DetectContentParseTest05);
2841  UtRegisterTest("DetectContentParseTest06", DetectContentParseTest06);
2842  UtRegisterTest("DetectContentParseTest07", DetectContentParseTest07);
2843  UtRegisterTest("DetectContentParseTest08", DetectContentParseTest08);
2844  UtRegisterTest("DetectContentParseTest09", DetectContentParseTest09);
2845  UtRegisterTest("DetectContentParseTest17", DetectContentParseTest17);
2846  UtRegisterTest("DetectContentParseTest18", DetectContentParseTest18);
2847  UtRegisterTest("DetectContentParseTest19", DetectContentParseTest19);
2848  UtRegisterTest("DetectContentParseTest20", DetectContentParseTest20);
2849  UtRegisterTest("DetectContentParseTest21", DetectContentParseTest21);
2850  UtRegisterTest("DetectContentParseTest22", DetectContentParseTest22);
2851  UtRegisterTest("DetectContentParseTest23", DetectContentParseTest23);
2852  UtRegisterTest("DetectContentParseTest24", DetectContentParseTest24);
2853  UtRegisterTest("DetectContentParseTest25", DetectContentParseTest25);
2854  UtRegisterTest("DetectContentParseTest26", DetectContentParseTest26);
2855  UtRegisterTest("DetectContentParseTest27", DetectContentParseTest27);
2856  UtRegisterTest("DetectContentParseTest28", DetectContentParseTest28);
2857  UtRegisterTest("DetectContentParseTest29", DetectContentParseTest29);
2858  UtRegisterTest("DetectContentParseTest30", DetectContentParseTest30);
2859  UtRegisterTest("DetectContentParseTest31", DetectContentParseTest31);
2860  UtRegisterTest("DetectContentParseTest32", DetectContentParseTest32);
2861  UtRegisterTest("DetectContentParseTest33", DetectContentParseTest33);
2862  UtRegisterTest("DetectContentParseTest34", DetectContentParseTest34);
2863  UtRegisterTest("DetectContentParseTest35", DetectContentParseTest35);
2864  UtRegisterTest("DetectContentParseTest41", DetectContentParseTest41);
2865  UtRegisterTest("DetectContentParseTest42", DetectContentParseTest42);
2866  UtRegisterTest("DetectContentParseTest43", DetectContentParseTest43);
2867  UtRegisterTest("DetectContentParseTest44", DetectContentParseTest44);
2868  UtRegisterTest("DetectContentParseTest45", DetectContentParseTest45);
2869 
2870  /* The reals */
2871  UtRegisterTest("DetectContentLongPatternMatchTest01",
2872  DetectContentLongPatternMatchTest01);
2873  UtRegisterTest("DetectContentLongPatternMatchTest02",
2874  DetectContentLongPatternMatchTest02);
2875  UtRegisterTest("DetectContentLongPatternMatchTest03",
2876  DetectContentLongPatternMatchTest03);
2877  UtRegisterTest("DetectContentLongPatternMatchTest04",
2878  DetectContentLongPatternMatchTest04);
2879  UtRegisterTest("DetectContentLongPatternMatchTest05",
2880  DetectContentLongPatternMatchTest05);
2881  UtRegisterTest("DetectContentLongPatternMatchTest06",
2882  DetectContentLongPatternMatchTest06);
2883  UtRegisterTest("DetectContentLongPatternMatchTest07",
2884  DetectContentLongPatternMatchTest07);
2885  UtRegisterTest("DetectContentLongPatternMatchTest08",
2886  DetectContentLongPatternMatchTest08);
2887  UtRegisterTest("DetectContentLongPatternMatchTest09",
2888  DetectContentLongPatternMatchTest09);
2889  UtRegisterTest("DetectContentLongPatternMatchTest10",
2890  DetectContentLongPatternMatchTest10);
2891  UtRegisterTest("DetectContentLongPatternMatchTest11",
2892  DetectContentLongPatternMatchTest11);
2893 
2894  /* Negated content tests */
2895  UtRegisterTest("SigTest41TestNegatedContent", SigTest41TestNegatedContent);
2896  UtRegisterTest("SigTest41aTestNegatedContent",
2897  SigTest41aTestNegatedContent);
2898  UtRegisterTest("SigTest42TestNegatedContent", SigTest42TestNegatedContent);
2899  UtRegisterTest("SigTest43TestNegatedContent", SigTest43TestNegatedContent);
2900  UtRegisterTest("SigTest44TestNegatedContent", SigTest44TestNegatedContent);
2901  UtRegisterTest("SigTest45TestNegatedContent", SigTest45TestNegatedContent);
2902  UtRegisterTest("SigTest46TestNegatedContent", SigTest46TestNegatedContent);
2903  UtRegisterTest("SigTest47TestNegatedContent", SigTest47TestNegatedContent);
2904  UtRegisterTest("SigTest48TestNegatedContent", SigTest48TestNegatedContent);
2905  UtRegisterTest("SigTest49TestNegatedContent", SigTest49TestNegatedContent);
2906  UtRegisterTest("SigTest50TestNegatedContent", SigTest50TestNegatedContent);
2907  UtRegisterTest("SigTest51TestNegatedContent", SigTest51TestNegatedContent);
2908  UtRegisterTest("SigTest52TestNegatedContent", SigTest52TestNegatedContent);
2909  UtRegisterTest("SigTest53TestNegatedContent", SigTest53TestNegatedContent);
2910  UtRegisterTest("SigTest54TestNegatedContent", SigTest54TestNegatedContent);
2911  UtRegisterTest("SigTest55TestNegatedContent", SigTest55TestNegatedContent);
2912  UtRegisterTest("SigTest56TestNegatedContent", SigTest56TestNegatedContent);
2913  UtRegisterTest("SigTest57TestNegatedContent", SigTest57TestNegatedContent);
2914  UtRegisterTest("SigTest58TestNegatedContent", SigTest58TestNegatedContent);
2915  UtRegisterTest("SigTest59TestNegatedContent", SigTest59TestNegatedContent);
2916  UtRegisterTest("SigTest60TestNegatedContent", SigTest60TestNegatedContent);
2917  UtRegisterTest("SigTest61TestNegatedContent", SigTest61TestNegatedContent);
2918  UtRegisterTest("SigTest62TestNegatedContent", SigTest62TestNegatedContent);
2919  UtRegisterTest("SigTest63TestNegatedContent", SigTest63TestNegatedContent);
2920  UtRegisterTest("SigTest64TestNegatedContent", SigTest64TestNegatedContent);
2921  UtRegisterTest("SigTest65TestNegatedContent", SigTest65TestNegatedContent);
2922  UtRegisterTest("SigTest66TestNegatedContent", SigTest66TestNegatedContent);
2923  UtRegisterTest("SigTest67TestNegatedContent", SigTest67TestNegatedContent);
2924  UtRegisterTest("SigTest68TestNegatedContent", SigTest68TestNegatedContent);
2925  UtRegisterTest("SigTest69TestNegatedContent", SigTest69TestNegatedContent);
2926  UtRegisterTest("SigTest70TestNegatedContent", SigTest70TestNegatedContent);
2927  UtRegisterTest("SigTest71TestNegatedContent", SigTest71TestNegatedContent);
2928  UtRegisterTest("SigTest72TestNegatedContent", SigTest72TestNegatedContent);
2929  UtRegisterTest("SigTest73TestNegatedContent", SigTest73TestNegatedContent);
2930  UtRegisterTest("SigTest74TestNegatedContent", SigTest74TestNegatedContent);
2931  UtRegisterTest("SigTest75TestNegatedContent", SigTest75TestNegatedContent);
2932 
2933  UtRegisterTest("SigTest76TestBug134", SigTest76TestBug134);
2934  UtRegisterTest("SigTest77TestBug139", SigTest77TestBug139);
2935 
2936  UtRegisterTest("DetectLongContentTest1", DetectLongContentTest1);
2937  UtRegisterTest("DetectLongContentTest2", DetectLongContentTest2);
2938  UtRegisterTest("DetectLongContentTest3", DetectLongContentTest3);
2939 
2940  UtRegisterTest("DetectBadBinContent", DetectBadBinContent);
2941 }
2942 #endif /* UNITTESTS */
DETECT_DEPTH
@ DETECT_DEPTH
Definition: detect-engine-register.h:65
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:107
host.h
SigTableElmt_::url
const char * url
Definition: detect.h:1245
DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_RELATIVE_NEXT
Definition: detect-content.h:66
DetectSignatureSetAppProto
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
Definition: detect-parse.c:1627
SignatureInitDataBuffer_::head
SigMatch * head
Definition: detect.h:494
detect-content.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:81
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:382
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:542
SigTableElmt_::desc
const char * desc
Definition: detect.h:1244
detect-dsize.h
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1007
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
ALPROTO_DCERPC
@ ALPROTO_DCERPC
Definition: app-layer-protos.h:38
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1232
flow-util.h
SigTableElmt_::name
const char * name
Definition: detect.h:1242
SignatureInitData_::smlists_tail
struct SigMatch_ * smlists_tail[DETECT_SM_LIST_MAX]
Definition: detect.h:544
SigFree
void SigFree(DetectEngineCtx *, Signature *)
Definition: detect-parse.c:1518
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectContentData_::within
int32_t within
Definition: detect-content.h:109
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:62
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
SigParseGetMaxDsize
int SigParseGetMaxDsize(const Signature *s)
get max dsize "depth"
Definition: detect-dsize.c:226
DETECT_CONTENT_WITHIN2DEPTH
#define DETECT_CONTENT_WITHIN2DEPTH
Definition: detect-content.h:62
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:141
Packet_::flags
uint32_t flags
Definition: decode.h:464
PacketRecycle
void PacketRecycle(Packet *p)
Definition: packet.c:167
threads.h
Flow_
Flow data structure.
Definition: flow.h:343
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1236
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:801
UTHPacketMatchSigMpm
int UTHPacketMatchSigMpm(Packet *p, char *sig, uint16_t mpm_type)
Definition: util-unittest-helper.c:789
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2588
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:218
MIN
#define MIN(x, y)
Definition: suricata-common.h:386
DE_QUIET
#define DE_QUIET
Definition: detect.h:290
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:337
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1822
DetectContentData_
Definition: detect-content.h:93
DetectPcreData_::flags
uint16_t flags
Definition: detect-pcre.h:48
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:46
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2493
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:460
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:1452
MAX
#define MAX(x, y)
Definition: suricata-common.h:390
DetectBufferIsPresent
bool DetectBufferIsPresent(const Signature *s, const uint32_t buf_id)
Definition: detect-engine.c:1376
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1227
detect-pcre.h
DetectContentFree
void DetectContentFree(DetectEngineCtx *de_ctx, void *ptr)
this function will SCFree memory associated with DetectContentData
Definition: detect-content.c:378
DetectContentPMATCHValidateCallback
bool DetectContentPMATCHValidateCallback(const Signature *s)
Definition: detect-content.c:460
util-unittest.h
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1132
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
Signature_::next
struct Signature_ * next
Definition: detect.h:631
SIGMATCH_QUOTES_MANDATORY
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1443
FlowInitConfig
void FlowInitConfig(bool quiet)
initialize the configuration
Definition: flow.c:543
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
DetectContentPrint
void DetectContentPrint(DetectContentData *cd)
Helper function to print a DetectContentData.
Definition: detect-content.c:262
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
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
DETECT_CONTENT_ENDS_WITH
#define DETECT_CONTENT_ENDS_WITH
Definition: detect-content.h:42
DETECT_CONTENT_DISTANCE
#define DETECT_CONTENT_DISTANCE
Definition: detect-content.h:30
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectContentSetup
int DetectContentSetup(DetectEngineCtx *de_ctx, Signature *s, const char *contentstr)
Function to setup a content pattern.
Definition: detect-content.c:328
MPM_AC
@ MPM_AC
Definition: util-mpm.h:36
DetectEngineThreadCtx_
Definition: detect.h:1032
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
DetectContentRegister
void DetectContentRegister(void)
Definition: detect-content.c:58
DETECT_CONTENT_DEPTH
#define DETECT_CONTENT_DEPTH
Definition: detect-content.h:33
DETECT_CONTENT_DISTANCE2OFFSET
#define DETECT_CONTENT_DISTANCE2OFFSET
Definition: detect-content.h:63
SignatureInitData_::list
int list
Definition: detect.h:526
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DetectEngineBufferTypeValidateTransform
bool DetectEngineBufferTypeValidateTransform(DetectEngineCtx *de_ctx, int sm_list, const uint8_t *content, uint16_t content_len, const char **namestr)
Check content byte array compatibility with transforms.
Definition: detect-engine.c:1699
pkt-var.h
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:320
DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_NEGATED
Definition: detect-content.h:40
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:79
DetectContentPropagateLimits
void DetectContentPropagateLimits(Signature *s)
Definition: detect-content.c:711
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2188
DetectContentData_::id
PatIntId id
Definition: detect-content.h:105
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:319
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2003
util-profiling.h
SCReturn
#define SCReturn
Definition: util-debug.h:273
Signature_::flags
uint32_t flags
Definition: detect.h:558
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:106
SigParseRequiredContentSize
void SigParseRequiredContentSize(const Signature *s, const int max_size, const SigMatch *sm, int *len, int *offset)
Definition: detect-content.c:414
Packet_
Definition: decode.h:429
detect-engine-build.h
detect-engine-alert.h
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:104
SinglePatternMatchDefaultMatcher
uint16_t SinglePatternMatchDefaultMatcher(void)
Returns the single pattern matcher algorithm to be used, based on the spm-algo setting in yaml.
Definition: util-spm.c:68
DetectContentData_::replace_len
uint16_t replace_len
Definition: detect-content.h:96
SIGMATCH_HANDLE_NEGATION
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1447
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:628
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
SignatureInitData_::negated
bool negated
Definition: detect.h:504
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1210
DetectContentPatternPrettyPrint
void DetectContentPatternPrettyPrint(const DetectContentData *cd, char *str, size_t str_len)
Definition: detect-content.c:739
DetectContentData_::replace
uint8_t * replace
Definition: detect-content.h:113
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:267
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:64
SpmDestroyGlobalThreadCtx
void SpmDestroyGlobalThreadCtx(SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:144
VALIDATE
#define VALIDATE(e)
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1934
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
DETECT_SM_LIST_NOTSET
#define DETECT_SM_LIST_NOTSET
Definition: detect.h:106
DetectContentDataParse
int DetectContentDataParse(const char *keyword, const char *contentstr, uint8_t **pstr, uint16_t *plen)
Parse a content string, ie "abc|DE|fgh".
Definition: detect-content.c:83
Packet_::flow
struct Flow_ * flow
Definition: decode.h:466
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3300
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
util-mpm.h
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3514
SigMatch_::type
uint16_t type
Definition: detect.h:317
DetectContentData_::distance
int32_t distance
Definition: detect-content.h:108
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:689
packet.h
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:77
DetectBufferGetFirstSigMatch
SigMatch * DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id)
Definition: detect-engine.c:1355
util-spm.h
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:94
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:806
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:173
SpmGlobalThreadCtx_
Definition: util-spm.h:47
detect-flow.h
PrintRawUriFp
void PrintRawUriFp(FILE *fp, uint8_t *buf, uint32_t buflen)
Definition: util-print.c:95
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DetectContentData_::spm_ctx
SpmCtx * spm_ctx
Definition: detect-content.h:111
SignatureInitData_::buffers
SignatureInitDataBuffer * buffers
Definition: detect.h:547
str
#define str(s)
Definition: suricata-common.h:286
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:665
UTHFreePacket
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:485
DETECT_CONTENT_OFFSET
#define DETECT_CONTENT_OFFSET
Definition: detect-content.h:32
TEST_RUN
#define TEST_RUN(sig, o, d)
Definition: detect-content.c:787
detect-parse.h
Signature_
Signature container.
Definition: detect.h:557
SigMatch_
a single match condition for a signature
Definition: detect.h:316
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:97
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:220
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2549
DetectPcreData_
Definition: detect-pcre.h:43
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:41
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:95
detect-uricontent.h
DetectEngineCtx_::spm_global_thread_ctx
SpmGlobalThreadCtx * spm_global_thread_ctx
Definition: detect.h:857
DetectContentParse
DetectContentData * DetectContentParse(SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr)
DetectContentParse \initonly.
Definition: detect-content.c:211
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:848
DetectContentParseEncloseQuotes
DetectContentData * DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr)
Definition: detect-content.c:253
SpmInitGlobalThreadCtx
SpmGlobalThreadCtx * SpmInitGlobalThreadCtx(uint16_t matcher)
Definition: util-spm.c:138
DETECT_PCRE_RELATIVE
#define DETECT_PCRE_RELATIVE
Definition: detect-pcre.h:29
SigAlloc
Signature * SigAlloc(void)
Definition: detect-parse.c:1403
flow.h
SpmDestroyCtx
void SpmDestroyCtx(SpmCtx *ctx)
Definition: util-spm.c:183
Packet_::dp
Port dp
Definition: decode.h:444
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SigParseMaxRequiredDsize
int SigParseMaxRequiredDsize(const Signature *s)
Determine the required dsize for the signature.
Definition: detect-dsize.c:303
SignatureInitData_::buffer_index
uint32_t buffer_index
Definition: detect.h:548
flow-var.h
SpmInitCtx
SpmCtx * SpmInitCtx(const uint8_t *needle, uint16_t needle_len, int nocase, SpmGlobalThreadCtx *global_thread_ctx)
Definition: util-spm.c:173
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:771
DecodeEthernet
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ethernet.c:42
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:127
DETECT_CONTENT_WITHIN
#define DETECT_CONTENT_WITHIN
Definition: detect-content.h:31
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1234
SIG_FLAG_DSIZE
#define SIG_FLAG_DSIZE
Definition: detect.h:208
TEST_DONE
#define TEST_DONE
Definition: detect-content.c:803
app-layer.h
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:468