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