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