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