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