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