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