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