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