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