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  //SCLogDebug("Can't escape %c", str[i]);
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 
1289  s->alproto = ALPROTO_DCERPC;
1290 
1291  result &= (DetectContentSetup(de_ctx, s, "one") == 0);
1292  result &= (s->sm_lists[g_dce_stub_data_buffer_id] == NULL && s->sm_lists[DETECT_SM_LIST_PMATCH] != NULL);
1293 
1294  SigFree(s);
1295 
1296  s = SigAlloc();
1297  if (s == NULL)
1298  return 0;
1299 
1300  result &= (DetectContentSetup(de_ctx, s, "one") == 0);
1301  result &= (s->sm_lists[g_dce_stub_data_buffer_id] == NULL && s->sm_lists[DETECT_SM_LIST_PMATCH] != NULL);
1302 
1303  end:
1304  SigFree(s);
1305  DetectEngineCtxFree(de_ctx);
1306 
1307  return result;
1308 }
1309 
1310 /**
1311  * \test Test content for dce sig.
1312  */
1313 
1314 static int DetectContentParseTest19(void)
1315 {
1316  DetectEngineCtx *de_ctx = NULL;
1317  int result = 1;
1318  Signature *s = NULL;
1319  DetectContentData *data = NULL;
1320 
1321  de_ctx = DetectEngineCtxInit();
1322  if (de_ctx == NULL)
1323  goto end;
1324 
1325  de_ctx->flags |= DE_QUIET;
1326  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
1327  "(msg:\"Testing dce iface, stub_data with content\"; "
1328  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1329  "dce_stub_data; "
1330  "content:\"one\"; distance:0; sid:1;)");
1331  if (de_ctx->sig_list == NULL) {
1332  printf ("failed dce iface, stub_data with content ");
1333  result = 0;
1334  goto end;
1335  }
1336  s = de_ctx->sig_list;
1337  if (s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL) {
1338  result = 0;
1339  goto end;
1340  }
1341  result &= (s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_CONTENT);
1342  result &= (s->sm_lists[DETECT_SM_LIST_PMATCH] == NULL);
1343  data = (DetectContentData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1344  if (data->flags & DETECT_CONTENT_RAWBYTES ||
1345  data->flags & DETECT_CONTENT_NOCASE ||
1346  data->flags & DETECT_CONTENT_WITHIN ||
1347  !(data->flags & DETECT_CONTENT_DISTANCE) ||
1349  data->flags & DETECT_CONTENT_NEGATED ||
1350  result == 0) {
1351  result = 0;
1352  goto end;
1353  }
1354 
1355  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1356  "(msg:\"Testing dce iface, stub_data with contents & distance, within\"; "
1357  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1358  "dce_stub_data; "
1359  "content:\"one\"; distance:0; content:\"two\"; within:10; sid:1;)");
1360  if (s->next == NULL) {
1361  printf("failed dce iface, stub_data with content & distance, within");
1362  result = 0;
1363  goto end;
1364  }
1365  s = s->next;
1366  if (s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL) {
1367  result = 0;
1368  goto end;
1369  }
1370  result &= (s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_CONTENT);
1371  result &= (s->sm_lists[DETECT_SM_LIST_PMATCH] == NULL);
1372  data = (DetectContentData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1373  if (data->flags & DETECT_CONTENT_RAWBYTES ||
1374  data->flags & DETECT_CONTENT_NOCASE ||
1375  !(data->flags & DETECT_CONTENT_WITHIN) ||
1376  data->flags & DETECT_CONTENT_DISTANCE ||
1378  data->flags & DETECT_CONTENT_NEGATED ||
1379  result == 0) {
1380  result = 0;
1381  goto end;
1382  }
1383  result &= (data->within == 10);
1384 /*
1385  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1386  "(msg:\"Testing dce iface, stub_data with contents & offset, depth\"; "
1387  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1388  "dce_stub_data; "
1389  "content:\"one\"; offset:5; depth:9; "
1390  "content:\"two\"; within:10; sid:1;)");
1391  if (s->next == NULL) {
1392  printf ("failed dce iface, stub_data with contents & offset, depth");
1393  result = 0;
1394  goto end;
1395  }
1396  s = s->next;
1397  if (s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL) {
1398  result = 0;
1399  goto end;
1400  }
1401  result &= (s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_CONTENT);
1402  result &= (s->sm_lists[DETECT_SM_LIST_PMATCH] == NULL);
1403  data = (DetectContentData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1404  if (data->flags & DETECT_CONTENT_RAWBYTES ||
1405  data->flags & DETECT_CONTENT_NOCASE ||
1406  data->flags & DETECT_CONTENT_WITHIN ||
1407  data->flags & DETECT_CONTENT_DISTANCE ||
1408  data->flags & DETECT_CONTENT_FAST_PATTERN ||
1409  data->flags & DETECT_CONTENT_NEGATED ||
1410  result == 0) {
1411  result = 0;
1412  goto end;
1413  }
1414  result &= (data->offset == 5 && data->depth == 9);
1415  data = (DetectContentData *)s->sm_lists[g_dce_stub_data_buffer_id]->ctx;
1416  if (data->flags & DETECT_CONTENT_RAWBYTES ||
1417  data->flags & DETECT_CONTENT_NOCASE ||
1418  !(data->flags & DETECT_CONTENT_WITHIN) ||
1419  data->flags & DETECT_CONTENT_DISTANCE ||
1420  data->flags & DETECT_CONTENT_FAST_PATTERN ||
1421  data->flags & DETECT_CONTENT_NEGATED ||
1422  result == 0) {
1423  result = 0;
1424  goto end;
1425  }
1426 
1427  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1428  "(msg:\"Testing dce iface, stub with contents, distance\"; "
1429  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1430  "dce_stub_data; "
1431  "content:\"one\"; distance:0; "
1432  "content:\"two\"; distance:2; sid:1;)");
1433  if (s->next == NULL) {
1434  result = 0;
1435  goto end;
1436  }
1437  s = s->next;
1438  if (s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL) {
1439  result = 0;
1440  goto end;
1441  }
1442  result &= (s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_CONTENT);
1443  result &= (s->sm_lists[DETECT_SM_LIST_PMATCH] == NULL);
1444  data = (DetectContentData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1445  if (data->flags & DETECT_CONTENT_RAWBYTES ||
1446  data->flags & DETECT_CONTENT_NOCASE ||
1447  data->flags & DETECT_CONTENT_WITHIN ||
1448  !(data->flags & DETECT_CONTENT_DISTANCE) ||
1449  data->flags & DETECT_CONTENT_FAST_PATTERN ||
1450  data->flags & DETECT_CONTENT_NEGATED ||
1451  result == 0) {
1452  result = 0;
1453  goto end;
1454  }
1455  result &= (data->distance == 2);
1456 */
1457  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1458  "(msg:\"Testing dce iface, stub with contents, distance, within\"; "
1459  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1460  "dce_stub_data; "
1461  "content:\"one\"; distance:0; "
1462  "content:\"two\"; within:10; distance:2; sid:1;)");
1463  if (s->next == NULL) {
1464  result = 0;
1465  goto end;
1466  }
1467  s = s->next;
1468  if (s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL) {
1469  result = 0;
1470  goto end;
1471  }
1472  result &= (s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_CONTENT);
1473  result &= (s->sm_lists[DETECT_SM_LIST_PMATCH] == NULL);
1474  data = (DetectContentData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1475  if (data->flags & DETECT_CONTENT_RAWBYTES ||
1476  data->flags & DETECT_CONTENT_NOCASE ||
1477  !(data->flags & DETECT_CONTENT_WITHIN) ||
1478  !(data->flags & DETECT_CONTENT_DISTANCE) ||
1480  data->flags & DETECT_CONTENT_NEGATED ||
1481  result == 0) {
1482  result = 0;
1483  goto end;
1484  }
1485  result &= (data->within == 10 && data->distance == 2);
1486 /*
1487  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1488  "(msg:\"Testing dce iface, stub_data with content, offset\"; "
1489  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1490  "dce_stub_data; "
1491  "content:\"one\"; offset:10; sid:1;)");
1492  if (s->next == NULL) {
1493  printf ("Failed dce iface, stub_data with content, offset ");
1494  result = 0;
1495  goto end;
1496  }
1497  s = s->next;
1498  if (s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL) {
1499  result = 0;
1500  goto end;
1501  }
1502  result &= (s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_CONTENT);
1503  result &= (s->sm_lists[DETECT_SM_LIST_PMATCH] == NULL);
1504  data = (DetectContentData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1505  if (data->flags & DETECT_CONTENT_RAWBYTES ||
1506  data->flags & DETECT_CONTENT_NOCASE ||
1507  data->flags & DETECT_CONTENT_WITHIN ||
1508  data->flags & DETECT_CONTENT_DISTANCE ||
1509  data->flags & DETECT_CONTENT_FAST_PATTERN ||
1510  data->flags & DETECT_CONTENT_NEGATED ||
1511  result == 0) {
1512  result = 0;
1513  goto end;
1514  }
1515  result &= (data->offset == 10);
1516 
1517  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1518  "(msg:\"Testing dce iface, stub_data with content, depth\"; "
1519  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1520  "dce_stub_data; "
1521  "content:\"one\"; depth:10; sid:1;)");
1522  if (s->next == NULL) {
1523  printf ("failed dce iface, stub_data with content, depth");
1524  result = 0;
1525  goto end;
1526  }
1527  s = s->next;
1528  if (s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL) {
1529  result = 0;
1530  goto end;
1531  }
1532  result &= (s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_CONTENT);
1533  result &= (s->sm_lists[DETECT_SM_LIST_PMATCH] == NULL);
1534  data = (DetectContentData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1535  if (data->flags & DETECT_CONTENT_RAWBYTES ||
1536  data->flags & DETECT_CONTENT_NOCASE ||
1537  data->flags & DETECT_CONTENT_WITHIN ||
1538  data->flags & DETECT_CONTENT_DISTANCE ||
1539  data->flags & DETECT_CONTENT_FAST_PATTERN ||
1540  data->flags & DETECT_CONTENT_NEGATED ||
1541  result == 0) {
1542  result = 0;
1543  goto end;
1544  }
1545  result &= (data->depth == 10);
1546 
1547  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1548  "(msg:\"Testing dce iface, stub_data with content, offset, depth\"; "
1549  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1550  "dce_stub_data; "
1551  "content:\"one\"; offset:10; depth:3; sid:1;)");
1552  if (s->next == NULL) {
1553  printf("failed dce iface, stub_data with content, offset, depth");
1554  result = 0;
1555  goto end;
1556  }
1557  s = s->next;
1558  if (s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL) {
1559  result = 0;
1560  goto end;
1561  }
1562  result &= (s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_CONTENT);
1563  result &= (s->sm_lists[DETECT_SM_LIST_PMATCH] == NULL);
1564  data = (DetectContentData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1565  if (data->flags & DETECT_CONTENT_RAWBYTES ||
1566  data->flags & DETECT_CONTENT_NOCASE ||
1567  data->flags & DETECT_CONTENT_WITHIN ||
1568  data->flags & DETECT_CONTENT_DISTANCE ||
1569  data->flags & DETECT_CONTENT_FAST_PATTERN ||
1570  data->flags & DETECT_CONTENT_NEGATED ||
1571  result == 0) {
1572  result = 0;
1573  goto end;
1574  }
1575  result &= (data->offset == 10 && data->depth == 13);
1576 */
1577  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1578  "(msg:\"Testing content\"; "
1579  "content:\"one\"; sid:1;)");
1580  if (s->next == NULL) {
1581  printf ("failed testing content");
1582  result = 0;
1583  goto end;
1584  }
1585  s = s->next;
1586  if (s->sm_lists_tail[g_dce_stub_data_buffer_id] != NULL) {
1587  result = 0;
1588  goto end;
1589  }
1590  result &= (s->sm_lists[DETECT_SM_LIST_PMATCH] != NULL);
1591 
1592  end:
1593  SigGroupCleanup(de_ctx);
1594  SigCleanSignatures(de_ctx);
1595  DetectEngineCtxFree(de_ctx);
1596 
1597  return result;
1598 }
1599 
1600 /**
1601  * \test Test content for dce sig.
1602  */
1603 static int DetectContentParseTest20(void)
1604 {
1605  DetectEngineCtx *de_ctx = NULL;
1606  int result = 1;
1607 
1608  de_ctx = DetectEngineCtxInit();
1609  if (de_ctx == NULL)
1610  goto end;
1611 
1612  de_ctx->flags |= DE_QUIET;
1613  de_ctx->sig_list = SigInit(de_ctx,
1614  "alert udp any any -> any any "
1615  "(msg:\"test\"; content:\"\"; sid:238012;)");
1616  if (de_ctx->sig_list != NULL) {
1617  result = 0;
1618  goto end;
1619  }
1620 
1621  end:
1622  SigGroupCleanup(de_ctx);
1623  SigCleanSignatures(de_ctx);
1624  DetectEngineCtxFree(de_ctx);
1625 
1626  return result;
1627 }
1628 
1629 /**
1630  * \test Parsing test
1631  */
1632 static int DetectContentParseTest21(void)
1633 {
1634  DetectEngineCtx *de_ctx = NULL;
1635  int result = 1;
1636 
1637  de_ctx = DetectEngineCtxInit();
1638  if (de_ctx == NULL)
1639  goto end;
1640 
1641  de_ctx->flags |= DE_QUIET;
1642  de_ctx->sig_list = SigInit(de_ctx,
1643  "alert udp any any -> any any "
1644  "(msg:\"test\"; content:\"; sid:238012;)");
1645  if (de_ctx->sig_list != NULL) {
1646  result = 0;
1647  goto end;
1648  }
1649 
1650  end:
1651  SigGroupCleanup(de_ctx);
1652  SigCleanSignatures(de_ctx);
1653  DetectEngineCtxFree(de_ctx);
1654 
1655  return result;
1656 }
1657 
1658 /**
1659  * \test Parsing test
1660  */
1661 static int DetectContentParseTest22(void)
1662 {
1663  DetectEngineCtx *de_ctx = NULL;
1664  int result = 1;
1665 
1666  de_ctx = DetectEngineCtxInit();
1667  if (de_ctx == NULL)
1668  goto end;
1669 
1670  de_ctx->flags |= DE_QUIET;
1671  de_ctx->sig_list = SigInit(de_ctx,
1672  "alert udp any any -> any any "
1673  "(msg:\"test\"; content:\"boo; sid:238012;)");
1674  if (de_ctx->sig_list != NULL) {
1675  result = 0;
1676  goto end;
1677  }
1678 
1679  end:
1680  SigGroupCleanup(de_ctx);
1681  SigCleanSignatures(de_ctx);
1682  DetectEngineCtxFree(de_ctx);
1683 
1684  return result;
1685 }
1686 
1687 /**
1688  * \test Parsing test
1689  */
1690 static int DetectContentParseTest23(void)
1691 {
1692  DetectEngineCtx *de_ctx = NULL;
1693  int result = 1;
1694 
1695  de_ctx = DetectEngineCtxInit();
1696  if (de_ctx == NULL)
1697  goto end;
1698 
1699  de_ctx->flags |= DE_QUIET;
1700  de_ctx->sig_list = SigInit(de_ctx,
1701  "alert udp any any -> any any "
1702  "(msg:\"test\"; content:boo\"; sid:238012;)");
1703  if (de_ctx->sig_list != NULL) {
1704  result = 0;
1705  goto end;
1706  }
1707 
1708  end:
1709  SigGroupCleanup(de_ctx);
1710  SigCleanSignatures(de_ctx);
1711  DetectEngineCtxFree(de_ctx);
1712 
1713  return result;
1714 }
1715 
1716 /**
1717  * \test Parsing test
1718  */
1719 static int DetectContentParseTest24(void)
1720 {
1721  DetectEngineCtx *de_ctx = NULL;
1722  DetectContentData *cd = 0;
1723  Signature *s = NULL;
1724  int result = 1;
1725 
1726  de_ctx = DetectEngineCtxInit();
1727  if (de_ctx == NULL)
1728  goto end;
1729 
1730  de_ctx->flags |= DE_QUIET;
1731  s = de_ctx->sig_list = SigInit(de_ctx,
1732  "alert udp any any -> any any "
1733  "(msg:\"test\"; content: !\"boo\"; sid:238012;)");
1734  if (de_ctx->sig_list == NULL) {
1735  printf("de_ctx->sig_list == NULL: ");
1736  result = 0;
1737  goto end;
1738  }
1739 
1740  if (s->sm_lists_tail[DETECT_SM_LIST_PMATCH] == NULL || s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx == NULL) {
1741  printf("de_ctx->pmatch_tail == NULL || de_ctx->pmatch_tail->ctx == NULL: ");
1742  result = 0;
1743  goto end;
1744  }
1745 
1746  cd = (DetectContentData *)s->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
1747  result = (strncmp("boo", (char *)cd->content, cd->content_len) == 0);
1748 
1749 end:
1750  SigGroupCleanup(de_ctx);
1751  SigCleanSignatures(de_ctx);
1752  DetectEngineCtxFree(de_ctx);
1753 
1754  return result;
1755 }
1756 
1757 /**
1758  * \test Parsing test
1759  */
1760 static int DetectContentParseTest25(void)
1761 {
1762  DetectEngineCtx *de_ctx = NULL;
1763  int result = 1;
1764 
1765  de_ctx = DetectEngineCtxInit();
1766  if (de_ctx == NULL)
1767  goto end;
1768 
1769  de_ctx->flags |= DE_QUIET;
1770  de_ctx->sig_list = SigInit(de_ctx,
1771  "alert udp any any -> any any "
1772  "(msg:\"test\"; content:\"|\"; sid:1;)");
1773  if (de_ctx->sig_list != NULL) {
1774  result = 0;
1775  goto end;
1776  }
1777 
1778  end:
1779  SigGroupCleanup(de_ctx);
1780  SigCleanSignatures(de_ctx);
1781  DetectEngineCtxFree(de_ctx);
1782 
1783  return result;
1784 }
1785 
1786 /**
1787  * \test Parsing test
1788  */
1789 static int DetectContentParseTest26(void)
1790 {
1791  DetectEngineCtx *de_ctx = NULL;
1792  int result = 1;
1793 
1794  de_ctx = DetectEngineCtxInit();
1795  if (de_ctx == NULL)
1796  goto end;
1797 
1798  de_ctx->flags |= DE_QUIET;
1799  de_ctx->sig_list = SigInit(de_ctx,
1800  "alert udp any any -> any any "
1801  "(msg:\"test\"; content:\"|af\"; sid:1;)");
1802  if (de_ctx->sig_list != NULL) {
1803  result = 0;
1804  goto end;
1805  }
1806 
1807  end:
1808  SigGroupCleanup(de_ctx);
1809  SigCleanSignatures(de_ctx);
1810  DetectEngineCtxFree(de_ctx);
1811 
1812  return result;
1813 }
1814 
1815 /**
1816  * \test Parsing test
1817  */
1818 static int DetectContentParseTest27(void)
1819 {
1820  DetectEngineCtx *de_ctx = NULL;
1821  int result = 1;
1822 
1823  de_ctx = DetectEngineCtxInit();
1824  if (de_ctx == NULL)
1825  goto end;
1826 
1827  de_ctx->flags |= DE_QUIET;
1828  de_ctx->sig_list = SigInit(de_ctx,
1829  "alert udp any any -> any any "
1830  "(msg:\"test\"; content:\"af|\"; sid:1;)");
1831  if (de_ctx->sig_list != NULL) {
1832  result = 0;
1833  goto end;
1834  }
1835 
1836  end:
1837  SigGroupCleanup(de_ctx);
1838  SigCleanSignatures(de_ctx);
1839  DetectEngineCtxFree(de_ctx);
1840 
1841  return result;
1842 }
1843 
1844 /**
1845  * \test Parsing test
1846  */
1847 static int DetectContentParseTest28(void)
1848 {
1849  DetectEngineCtx *de_ctx = NULL;
1850  int result = 1;
1851 
1852  de_ctx = DetectEngineCtxInit();
1853  if (de_ctx == NULL)
1854  goto end;
1855 
1856  de_ctx->flags |= DE_QUIET;
1857  de_ctx->sig_list = SigInit(de_ctx,
1858  "alert udp any any -> any any "
1859  "(msg:\"test\"; content:\"|af|\"; sid:1;)");
1860  if (de_ctx->sig_list == NULL) {
1861  result = 0;
1862  goto end;
1863  }
1864 
1865  end:
1866  SigGroupCleanup(de_ctx);
1867  SigCleanSignatures(de_ctx);
1868  DetectEngineCtxFree(de_ctx);
1869 
1870  return result;
1871 }
1872 
1873 /**
1874  * \test Parsing test
1875  */
1876 static int DetectContentParseTest29(void)
1877 {
1878  DetectEngineCtx *de_ctx = NULL;
1879  int result = 1;
1880 
1881  de_ctx = DetectEngineCtxInit();
1882  if (de_ctx == NULL)
1883  goto end;
1884 
1885  de_ctx->flags |= DE_QUIET;
1886  de_ctx->sig_list = SigInit(de_ctx,
1887  "alert udp any any -> any any "
1888  "(msg:\"test\"; content:\"aast|\"; sid:1;)");
1889  if (de_ctx->sig_list != NULL) {
1890  result = 0;
1891  goto end;
1892  }
1893 
1894  end:
1895  SigGroupCleanup(de_ctx);
1896  SigCleanSignatures(de_ctx);
1897  DetectEngineCtxFree(de_ctx);
1898 
1899  return result;
1900 }
1901 
1902 /**
1903  * \test Parsing test
1904  */
1905 static int DetectContentParseTest30(void)
1906 {
1907  DetectEngineCtx *de_ctx = NULL;
1908  int result = 1;
1909 
1910  de_ctx = DetectEngineCtxInit();
1911  if (de_ctx == NULL)
1912  goto end;
1913 
1914  de_ctx->flags |= DE_QUIET;
1915  de_ctx->sig_list = SigInit(de_ctx,
1916  "alert udp any any -> any any "
1917  "(msg:\"test\"; content:\"aast|af\"; sid:1;)");
1918  if (de_ctx->sig_list != NULL) {
1919  result = 0;
1920  goto end;
1921  }
1922 
1923  end:
1924  SigGroupCleanup(de_ctx);
1925  SigCleanSignatures(de_ctx);
1926  DetectEngineCtxFree(de_ctx);
1927 
1928  return result;
1929 }
1930 
1931 /**
1932  * \test Parsing test
1933  */
1934 static int DetectContentParseTest31(void)
1935 {
1936  DetectEngineCtx *de_ctx = NULL;
1937  int result = 1;
1938 
1939  de_ctx = DetectEngineCtxInit();
1940  if (de_ctx == NULL)
1941  goto end;
1942 
1943  de_ctx->flags |= DE_QUIET;
1944  de_ctx->sig_list = SigInit(de_ctx,
1945  "alert udp any any -> any any "
1946  "(msg:\"test\"; content:\"aast|af|\"; sid:1;)");
1947  if (de_ctx->sig_list == NULL) {
1948  result = 0;
1949  goto end;
1950  }
1951 
1952  end:
1953  SigGroupCleanup(de_ctx);
1954  SigCleanSignatures(de_ctx);
1955  DetectEngineCtxFree(de_ctx);
1956 
1957  return result;
1958 }
1959 
1960 /**
1961  * \test Parsing test
1962  */
1963 static int DetectContentParseTest32(void)
1964 {
1965  DetectEngineCtx *de_ctx = NULL;
1966  int result = 1;
1967 
1968  de_ctx = DetectEngineCtxInit();
1969  if (de_ctx == NULL)
1970  goto end;
1971 
1972  de_ctx->flags |= DE_QUIET;
1973  de_ctx->sig_list = SigInit(de_ctx,
1974  "alert udp any any -> any any "
1975  "(msg:\"test\"; content:\"|af|asdf\"; sid:1;)");
1976  if (de_ctx->sig_list == NULL) {
1977  result = 0;
1978  goto end;
1979  }
1980 
1981  end:
1982  SigGroupCleanup(de_ctx);
1983  SigCleanSignatures(de_ctx);
1984  DetectEngineCtxFree(de_ctx);
1985 
1986  return result;
1987 }
1988 
1989 /**
1990  * \test Parsing test
1991  */
1992 static int DetectContentParseTest33(void)
1993 {
1994  DetectEngineCtx *de_ctx = NULL;
1995  int result = 1;
1996 
1997  de_ctx = DetectEngineCtxInit();
1998  if (de_ctx == NULL)
1999  goto end;
2000 
2001  de_ctx->flags |= DE_QUIET;
2002  de_ctx->sig_list = SigInit(de_ctx,
2003  "alert udp any any -> any any "
2004  "(msg:\"test\"; content:\"|af|af|\"; sid:1;)");
2005  if (de_ctx->sig_list != NULL) {
2006  result = 0;
2007  goto end;
2008  }
2009 
2010  end:
2011  SigGroupCleanup(de_ctx);
2012  SigCleanSignatures(de_ctx);
2013  DetectEngineCtxFree(de_ctx);
2014 
2015  return result;
2016 }
2017 
2018 /**
2019  * \test Parsing test
2020  */
2021 static int DetectContentParseTest34(void)
2022 {
2023  DetectEngineCtx *de_ctx = NULL;
2024  int result = 1;
2025 
2026  de_ctx = DetectEngineCtxInit();
2027  if (de_ctx == NULL)
2028  goto end;
2029 
2030  de_ctx->flags |= DE_QUIET;
2031  de_ctx->sig_list = SigInit(de_ctx,
2032  "alert udp any any -> any any "
2033  "(msg:\"test\"; content:\"|af|af|af\"; sid:1;)");
2034  if (de_ctx->sig_list != NULL) {
2035  result = 0;
2036  goto end;
2037  }
2038 
2039  end:
2040  SigGroupCleanup(de_ctx);
2041  SigCleanSignatures(de_ctx);
2042  DetectEngineCtxFree(de_ctx);
2043 
2044  return result;
2045 }
2046 
2047 /**
2048  * \test Parsing test
2049  */
2050 static int DetectContentParseTest35(void)
2051 {
2052  DetectEngineCtx *de_ctx = NULL;
2053  int result = 1;
2054 
2055  de_ctx = DetectEngineCtxInit();
2056  if (de_ctx == NULL)
2057  goto end;
2058 
2059  de_ctx->flags |= DE_QUIET;
2060  de_ctx->sig_list = SigInit(de_ctx,
2061  "alert udp any any -> any any "
2062  "(msg:\"test\"; content:\"|af|af|af|\"; sid:1;)");
2063  if (de_ctx->sig_list == NULL) {
2064  result = 0;
2065  goto end;
2066  }
2067 
2068  end:
2069  SigGroupCleanup(de_ctx);
2070  SigCleanSignatures(de_ctx);
2071  DetectEngineCtxFree(de_ctx);
2072 
2073  return result;
2074 }
2075 
2076 /**
2077  * \test Parsing test: file_data
2078  */
2079 static int DetectContentParseTest36(void)
2080 {
2081  DetectEngineCtx *de_ctx = NULL;
2082  int result = 0;
2083 
2084  de_ctx = DetectEngineCtxInit();
2085  if (de_ctx == NULL)
2086  goto end;
2087 
2088  de_ctx->flags |= DE_QUIET;
2089  de_ctx->sig_list = SigInit(de_ctx,
2090  "alert tcp any any -> any any "
2091  "(msg:\"test\"; file_data; content:\"abc\"; sid:1;)");
2092  if (de_ctx->sig_list == NULL) {
2093  printf("sig parse failed: ");
2094  goto end;
2095  }
2096 
2097  if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
2098  printf("content still in PMATCH list: ");
2099  goto end;
2100  }
2101 
2102  if (de_ctx->sig_list->sm_lists[g_file_data_buffer_id] == NULL) {
2103  printf("content not in FILEDATA list: ");
2104  goto end;
2105  }
2106 
2107  result = 1;
2108 end:
2109  SigGroupCleanup(de_ctx);
2110  SigCleanSignatures(de_ctx);
2111  DetectEngineCtxFree(de_ctx);
2112 
2113  return result;
2114 }
2115 
2116 /**
2117  * \test Parsing test: file_data
2118  */
2119 static int DetectContentParseTest37(void)
2120 {
2121  DetectEngineCtx *de_ctx = NULL;
2122  int result = 0;
2123 
2124  de_ctx = DetectEngineCtxInit();
2125  if (de_ctx == NULL)
2126  goto end;
2127 
2128  de_ctx->flags |= DE_QUIET;
2129  de_ctx->sig_list = SigInit(de_ctx,
2130  "alert tcp any any -> any any "
2131  "(msg:\"test\"; file_data; content:\"abc\"; content:\"def\"; sid:1;)");
2132  if (de_ctx->sig_list == NULL) {
2133  printf("sig parse failed: ");
2134  goto end;
2135  }
2136 
2137  if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
2138  printf("content still in PMATCH list: ");
2139  goto end;
2140  }
2141 
2142  if (de_ctx->sig_list->sm_lists[g_file_data_buffer_id] == NULL) {
2143  printf("content not in FILEDATA list: ");
2144  goto end;
2145  }
2146 
2147  result = 1;
2148 end:
2149  SigGroupCleanup(de_ctx);
2150  SigCleanSignatures(de_ctx);
2151  DetectEngineCtxFree(de_ctx);
2152 
2153  return result;
2154 }
2155 
2156 /**
2157  * \test Parsing test: file_data
2158  */
2159 static int DetectContentParseTest38(void)
2160 {
2161  DetectEngineCtx *de_ctx = NULL;
2162  int result = 0;
2163 
2164  de_ctx = DetectEngineCtxInit();
2165  if (de_ctx == NULL)
2166  goto end;
2167 
2168  de_ctx->flags |= DE_QUIET;
2169  de_ctx->sig_list = SigInit(de_ctx,
2170  "alert tcp any any -> any any "
2171  "(msg:\"test\"; file_data; content:\"abc\"; content:\"def\"; within:8; sid:1;)");
2172  if (de_ctx->sig_list == NULL) {
2173  printf("sig parse failed: ");
2174  goto end;
2175  }
2176 
2177  if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
2178  printf("content still in PMATCH list: ");
2179  goto end;
2180  }
2181 
2182  if (de_ctx->sig_list->sm_lists[g_file_data_buffer_id] == NULL) {
2183  printf("content not in FILEDATA list: ");
2184  goto end;
2185  }
2186 
2187  result = 1;
2188 end:
2189  SigGroupCleanup(de_ctx);
2190  SigCleanSignatures(de_ctx);
2191  DetectEngineCtxFree(de_ctx);
2192 
2193  return result;
2194 }
2195 
2196 static int SigTestPositiveTestContent(const char *rule, uint8_t *buf)
2197 {
2198  uint16_t buflen = strlen((char *)buf);
2199  ThreadVars th_v;
2200  DetectEngineThreadCtx *det_ctx = NULL;
2201 
2202  memset(&th_v, 0, sizeof(th_v));
2203  Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2204  FAIL_IF_NULL(p);
2205 
2207  FAIL_IF_NULL(de_ctx);
2208  de_ctx->flags |= DE_QUIET;
2209 
2210  de_ctx->sig_list = SigInit(de_ctx, rule);
2211  FAIL_IF_NULL(de_ctx->sig_list);
2212 
2213  SigGroupBuild(de_ctx);
2214  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2215  FAIL_IF_NULL(det_ctx);
2216 
2217  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2218 
2219  FAIL_IF(PacketAlertCheck(p, 1) != 1);
2220 
2221  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2222  DetectEngineCtxFree(de_ctx);
2223 
2224  UTHFreePackets(&p, 1);
2225  PASS;
2226 }
2227 
2228 /**
2229  * \test Parsing test: file_data, within relative to file_data
2230  */
2231 static int DetectContentParseTest39(void)
2232 {
2233  DetectEngineCtx *de_ctx = NULL;
2234  int result = 0;
2235 
2236  de_ctx = DetectEngineCtxInit();
2237  if (de_ctx == NULL)
2238  goto end;
2239 
2240  de_ctx->flags |= DE_QUIET;
2241  de_ctx->sig_list = SigInit(de_ctx,
2242  "alert tcp any any -> any any "
2243  "(msg:\"test\"; file_data; content:\"abc\"; within:8; sid:1;)");
2244  if (de_ctx->sig_list == NULL) {
2245  printf("sig parse failed: ");
2246  goto end;
2247  }
2248 
2249  if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
2250  printf("content still in PMATCH list: ");
2251  goto end;
2252  }
2253 
2254  if (de_ctx->sig_list->sm_lists[g_file_data_buffer_id] == NULL) {
2255  printf("content not in FILEDATA list: ");
2256  goto end;
2257  }
2258 
2259  result = 1;
2260 end:
2261  SigGroupCleanup(de_ctx);
2262  SigCleanSignatures(de_ctx);
2263  DetectEngineCtxFree(de_ctx);
2264 
2265  return result;
2266 }
2267 
2268 /**
2269  * \test Parsing test: file_data, distance relative to file_data
2270  */
2271 static int DetectContentParseTest40(void)
2272 {
2273  DetectEngineCtx *de_ctx = NULL;
2274  int result = 0;
2275 
2276  de_ctx = DetectEngineCtxInit();
2277  if (de_ctx == NULL)
2278  goto end;
2279 
2280  de_ctx->flags |= DE_QUIET;
2281  de_ctx->sig_list = SigInit(de_ctx,
2282  "alert tcp any any -> any any "
2283  "(msg:\"test\"; file_data; content:\"abc\"; distance:3; sid:1;)");
2284  if (de_ctx->sig_list == NULL) {
2285  printf("sig parse failed: ");
2286  goto end;
2287  }
2288 
2289  if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH] != NULL) {
2290  printf("content still in PMATCH list: ");
2291  goto end;
2292  }
2293 
2294  if (de_ctx->sig_list->sm_lists[g_file_data_buffer_id] == NULL) {
2295  printf("content not in FILEDATA list: ");
2296  goto end;
2297  }
2298 
2299  result = 1;
2300 end:
2301  SigGroupCleanup(de_ctx);
2302  SigCleanSignatures(de_ctx);
2303  DetectEngineCtxFree(de_ctx);
2304 
2305  return result;
2306 }
2307 
2308 static int DetectContentParseTest41(void)
2309 {
2310  int result = 1;
2311  DetectContentData *cd = NULL;
2312  int patlen = 255;
2313  char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2314  if (unlikely(teststring == NULL))
2315  return 0;
2316  int idx = 0;
2317  for (int i = 0; i < patlen; idx++, i++) {
2318  teststring[idx] = 'a';
2319  }
2320  teststring[idx++] = '\0';
2321 
2322  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
2323  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2324  FAIL_IF(spm_global_thread_ctx == NULL);
2325 
2326  cd = DetectContentParse(spm_global_thread_ctx, teststring);
2327  if (cd == NULL) {
2328  SCLogDebug("expected not NULL");
2329  result = 0;
2330  }
2331 
2332  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2333  SCFree(teststring);
2334  DetectContentFree(cd);
2335  return result;
2336 }
2337 
2338 /**
2339  * Tests that content lengths > 255 are supported.
2340  */
2341 static int DetectContentParseTest42(void)
2342 {
2343  int result = 1;
2344  DetectContentData *cd = NULL;
2345  int patlen = 256;
2346  char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2347  if (unlikely(teststring == NULL))
2348  return 0;
2349  int idx = 0;
2350  for (int i = 0; i < patlen; idx++, i++) {
2351  teststring[idx] = 'a';
2352  }
2353  teststring[idx++] = '\0';
2354 
2355  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
2356  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2357  FAIL_IF(spm_global_thread_ctx == NULL);
2358 
2359  cd = DetectContentParse(spm_global_thread_ctx, teststring);
2360  if (cd == NULL) {
2361  SCLogDebug("expected not NULL");
2362  result = 0;
2363  }
2364 
2365  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2366  SCFree(teststring);
2367  DetectContentFree(cd);
2368  return result;
2369 }
2370 
2371 static int DetectContentParseTest43(void)
2372 {
2373  int result = 1;
2374  DetectContentData *cd = NULL;
2375  int patlen = 258;
2376  char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2377  if (unlikely(teststring == NULL))
2378  return 0;
2379  int idx = 0;
2380  teststring[idx++] = '|';
2381  teststring[idx++] = '4';
2382  teststring[idx++] = '6';
2383  teststring[idx++] = '|';
2384  for (int i = 0; i < (patlen - 4); idx++, i++) {
2385  teststring[idx] = 'a';
2386  }
2387  teststring[idx++] = '\0';
2388 
2389  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
2390  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2391  FAIL_IF(spm_global_thread_ctx == NULL);
2392 
2393  cd = DetectContentParse(spm_global_thread_ctx, teststring);
2394  if (cd == NULL) {
2395  SCLogDebug("expected not NULL");
2396  result = 0;
2397  }
2398 
2399  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2400  SCFree(teststring);
2401  DetectContentFree(cd);
2402  return result;
2403 }
2404 
2405 /**
2406  * Tests that content lengths > 255 are supported.
2407  */
2408 static int DetectContentParseTest44(void)
2409 {
2410  int result = 1;
2411  DetectContentData *cd = NULL;
2412  int patlen = 259;
2413  char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2414  if (unlikely(teststring == NULL))
2415  return 0;
2416  int idx = 0;
2417  teststring[idx++] = '|';
2418  teststring[idx++] = '4';
2419  teststring[idx++] = '6';
2420  teststring[idx++] = '|';
2421  for (int i = 0; i < (patlen - 4); idx++, i++) {
2422  teststring[idx] = 'a';
2423  }
2424  teststring[idx++] = '\0';
2425 
2426  uint16_t spm_matcher = SinglePatternMatchDefaultMatcher();
2427  SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2428  FAIL_IF(spm_global_thread_ctx == NULL);
2429 
2430  cd = DetectContentParse(spm_global_thread_ctx, teststring);
2431  if (cd == NULL) {
2432  SCLogDebug("expected not NULL");
2433  result = 0;
2434  }
2435 
2436  SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2437  SCFree(teststring);
2438  DetectContentFree(cd);
2439  return result;
2440 }
2441 
2442 /**
2443  * \test Parsing test to check for unescaped quote within content section
2444  */
2445 static int DetectContentParseTest45(void)
2446 {
2447  DetectEngineCtx *de_ctx = NULL;
2448 
2449  de_ctx = DetectEngineCtxInit();
2450  FAIL_IF_NULL(de_ctx);
2451 
2452  de_ctx->flags |= DE_QUIET;
2453  de_ctx->sig_list = SigInit(de_ctx,
2454  "alert tcp any any -> any any "
2455  "(msg:\"test\"; content:\"|ff|\" content:\"TEST\"; sid:1;)");
2456  FAIL_IF_NOT_NULL(de_ctx->sig_list);
2457 
2458  DetectEngineCtxFree(de_ctx);
2459 
2460  PASS;
2461 }
2462 
2463 static int SigTestNegativeTestContent(const char *rule, uint8_t *buf)
2464 {
2465  uint16_t buflen = strlen((char *)buf);
2466  Packet *p = NULL;
2467  ThreadVars th_v;
2468  DetectEngineThreadCtx *det_ctx = NULL;
2469  int result = 0;
2470  memset(&th_v, 0, sizeof(th_v));
2471 
2472  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2473 
2475  if (de_ctx == NULL)
2476  goto end;
2477 
2478  de_ctx->flags |= DE_QUIET;
2479 
2480  de_ctx->sig_list = SigInit(de_ctx, rule);
2481  if (de_ctx->sig_list == NULL) {
2482  goto end;
2483  }
2484 
2485  SigGroupBuild(de_ctx);
2486  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2487 
2488  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2489  if (PacketAlertCheck(p, 1) != 0) {
2490  goto end;
2491  }
2492 
2493  result = 1;
2494 end:
2495  if (det_ctx != NULL) {
2496  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2497  }
2498  if (de_ctx != NULL) {
2499  SigGroupCleanup(de_ctx);
2500  SigCleanSignatures(de_ctx);
2501  DetectEngineCtxFree(de_ctx);
2502  }
2503  UTHFreePackets(&p, 1);
2504  return result;
2505 }
2506 
2507 /**
2508  * \test A positive test that checks that the content string doesn't contain
2509  * the negated content
2510  */
2511 static int SigTest41TestNegatedContent(void)
2512 {
2513  return SigTestPositiveTestContent("alert tcp any any -> any any "
2514  "(msg:\"HTTP URI cap\"; content:!\"GES\"; sid:1;)",
2515 
2516  (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\n"
2517  "GET /two/ HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2518 }
2519 
2520 /**
2521  * \test crash condition: as packet has no direction, it defaults to toclient
2522  * in stream ctx inspection of packet. There a null ptr deref happens
2523  * We don't care about the match/nomatch here.
2524  */
2525 static int SigTest41aTestNegatedContent(void)
2526 {
2527  (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");
2528  return 1;
2529 }
2530 
2531 
2532 /**
2533  * \test A positive test that checks that the content string doesn't contain
2534  * the negated content within the specified depth
2535  */
2536 static int SigTest42TestNegatedContent(void)
2537 { // 01 5 10 15 20 24
2538  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");
2539 }
2540 
2541 /**
2542  * \test A negative test that checks that the content string doesn't contain
2543  * the negated content within the specified depth, and also after the
2544  * specified offset. Since the content is there, the match fails.
2545  *
2546  * Match is at offset:23, depth:34
2547  */
2548 static int SigTest43TestNegatedContent(void)
2549 {
2550  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");
2551 }
2552 
2553 /**
2554  * \test A negative test that checks that the content string doesn't contain
2555  * the negated content after the specified offset and within the specified
2556  * depth.
2557  */
2558 static int SigTest44TestNegatedContent(void)
2559 {
2560  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");
2561 }
2562 
2563 /**
2564  * \test A positive test that uses a combination of content string with negated
2565  * content string
2566  */
2567 static int SigTest45TestNegatedContent(void)
2568 {
2569  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");
2570 }
2571 
2572 /**
2573  * \test A negative test that uses a combination of content string with negated
2574  * content string, with we receiving a failure for 'onee' itself.
2575  */
2576 static int SigTest46TestNegatedContent(void)
2577 {
2578  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");
2579 }
2580 
2581 /**
2582  * \test A negative test that uses a combination of content string with negated
2583  * content string, with we receiving a failure of first content's offset
2584  * condition
2585  */
2586 static int SigTest47TestNegatedContent(void)
2587 {
2588  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");
2589 }
2590 
2591 /**
2592  * \test A positive test that checks that we don't have a negated content within
2593  * the specified length from the previous content match.
2594  */
2595 static int SigTest48TestNegatedContent(void)
2596 {
2597  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");
2598 }
2599 
2600 /**
2601  * \test A negative test that checks the combined use of content and negated
2602  * content with the use of within
2603  */
2604 static int SigTest49TestNegatedContent(void)
2605 {
2606  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");
2607 }
2608 
2609 /**
2610  * \test A positive test that checks the combined use of content and negated
2611  * content with the use of distance
2612  */
2613 static int SigTest50TestNegatedContent(void)
2614 {
2615  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");
2616 }
2617 
2618 /**
2619  * \test A negative test that checks the combined use of content and negated
2620  * content with the use of distance
2621  *
2622  * First GET at offset 0
2623  * First Host at offset 21
2624  */
2625 static int SigTest51TestNegatedContent(void)
2626 {
2627  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");
2628 }
2629 
2630 /**
2631  * \test A negative test that checks the combined use of content and negated
2632  * content, with the content not being present
2633  */
2634 static int SigTest52TestNegatedContent(void)
2635 {
2636  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");
2637 }
2638 
2639 /**
2640  * \test A negative test that checks the combined use of content and negated
2641  * content, in the presence of within
2642  */
2643 static int SigTest53TestNegatedContent(void)
2644 {
2645  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");
2646 }
2647 
2648 /**
2649  * \test A positive test that checks the combined use of content and negated
2650  * content, in the presence of within
2651  */
2652 static int SigTest54TestNegatedContent(void)
2653 {
2654  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");
2655 }
2656 
2657 /**
2658  * \test A negative test that checks the use of negated content along with
2659  * the presence of depth
2660  */
2661 static int SigTest55TestNegatedContent(void)
2662 {
2663  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");
2664 }
2665 
2666 /**
2667  * \test A positive test that checks the combined use of 2 contents in the
2668  * presence of within
2669  */
2670 static int SigTest56TestNegatedContent(void)
2671 {
2672  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");
2673 }
2674 
2675 /**
2676  * \test A negative test that checks the combined use of content and negated
2677  * content, in the presence of within
2678  */
2679 static int SigTest57TestNegatedContent(void)
2680 {
2681  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");
2682 }
2683 
2684 /**
2685  * \test A positive test that checks the combined use of content and negated
2686  * content, in the presence of distance
2687  */
2688 static int SigTest58TestNegatedContent(void)
2689 {
2690  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");
2691 }
2692 
2693 /**
2694  * \test A negative test that checks the combined use of content and negated
2695  * content, in the presence of distance
2696  */
2697 static int SigTest59TestNegatedContent(void)
2698 {
2699  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");
2700 }
2701 
2702 static int SigTest60TestNegatedContent(void)
2703 {
2704  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");
2705 }
2706 
2707 static int SigTest61TestNegatedContent(void)
2708 {
2709  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");
2710 }
2711 
2712 /** \test Test negation in combination with within and depth
2713  *
2714  * Match of "one" at offset:0, depth:3
2715  * Match of "fourty" at offset:46, depth:52
2716  *
2717  * This signature should not match for the test to pass.
2718  */
2719 static int SigTest62TestNegatedContent(void)
2720 {
2721  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");
2722 }
2723 
2724 static int SigTest63TestNegatedContent(void)
2725 {
2726  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");
2727 }
2728 
2729 static int SigTest64TestNegatedContent(void)
2730 {
2731  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");
2732 }
2733 
2734 /** \test Test negation in combination with within and depth
2735  *
2736  * Match of "one" at offset:0, depth:3
2737  * Match of "fourty" at offset:46, depth:52
2738  *
2739  * This signature should not match for the test to pass.
2740  */
2741 static int SigTest65TestNegatedContent(void)
2742 {
2743  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");
2744 }
2745 
2746 static int SigTest66TestNegatedContent(void)
2747 {
2748  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");
2749 }
2750 
2751 static int SigTest67TestNegatedContent(void)
2752 {
2753  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");
2754 }
2755 
2756 static int SigTest68TestNegatedContent(void)
2757 {
2758  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");
2759 }
2760 
2761 static int SigTest69TestNegatedContent(void)
2762 {
2763  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");
2764 }
2765 
2766 static int SigTest70TestNegatedContent(void)
2767 {
2768  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");
2769 }
2770 
2771 /** \test within and distance */
2772 static int SigTest71TestNegatedContent(void)
2773 {
2774  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");
2775 }
2776 
2777 static int SigTest72TestNegatedContent(void)
2778 {
2779  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");
2780 }
2781 
2782 static int SigTest73TestNegatedContent(void)
2783 {
2784  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");
2785 }
2786 
2787 static int SigTest74TestNegatedContent(void)
2788 {
2789  return SigTestPositiveTestContent("alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"USER\"; content:!\"PASS\"; sid:1;)", (uint8_t *)"USER apple");
2790 }
2791 
2792 static int SigTest75TestNegatedContent(void)
2793 {
2794  return SigTestPositiveTestContent("alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"USER\"; content:\"!PASS\"; sid:1;)", (uint8_t *)"USER !PASS");
2795 }
2796 
2797 static int SigTest76TestBug134(void)
2798 {
2799  uint8_t *buf = (uint8_t *)"test detect ${IFS} in traffic";
2800  uint16_t buflen = strlen((char *)buf);
2801  Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
2802  int result = 0;
2803  Flow f;
2804 
2805  memset(&f, 0, sizeof(Flow));
2806  FLOW_INITIALIZE(&f);
2807 
2808  p->dp = 515;
2811  p->flow = &f;
2812  p->flags |= PKT_HAS_FLOW;
2813 
2814  char sig[] = "alert tcp any any -> any 515 "
2815  "(msg:\"detect IFS\"; flow:to_server,established; content:\"${IFS}\";"
2816  " depth:50; offset:0; sid:900091; rev:1;)";
2817  if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
2818  result = 0;
2819  goto end;
2820  }
2821 
2822  result = 1;
2823 end:
2824  if (p != NULL)
2825  UTHFreePacket(p);
2826 
2827  FLOW_DESTROY(&f);
2828  return result;
2829 }
2830 
2831 static int SigTest77TestBug139(void)
2832 {
2833  uint8_t buf[] = {
2834  0x12, 0x23, 0x34, 0x35, 0x52, 0x52, 0x24, 0x42, 0x22, 0x24,
2835  0x52, 0x24, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x34 };
2836  uint16_t buflen = sizeof(buf);
2837  Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_UDP);
2838  int result = 0;
2839 
2840  p->dp = 53;
2841  char sig[] = "alert udp any any -> any 53 (msg:\"dns testing\";"
2842  " content:\"|00 00|\"; depth:5; offset:13; sid:9436601;"
2843  " rev:1;)";
2844  if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
2845  result = 0;
2846  goto end;
2847  }
2848 
2849  result = 1;
2850 end:
2851  if (p != NULL)
2852  UTHFreePacket(p);
2853  return result;
2854 }
2855 
2856 static int DetectLongContentTestCommon(const char *sig, uint32_t sid)
2857 {
2858  /* Packet with 512 A's in it for testing long content. */
2859  static uint8_t pkt[739] = {
2860  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2861  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
2862  0x02, 0xd5, 0x4a, 0x18, 0x40, 0x00, 0x40, 0x06,
2863  0xd7, 0xd6, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10,
2864  0x01, 0x0a, 0xdb, 0x36, 0x00, 0x50, 0xca, 0xc5,
2865  0xcc, 0xd1, 0x95, 0x77, 0x0f, 0x7d, 0x80, 0x18,
2866  0x00, 0xe5, 0x77, 0x9d, 0x00, 0x00, 0x01, 0x01,
2867  0x08, 0x0a, 0x1d, 0xe0, 0x86, 0xc6, 0xfc, 0x73,
2868  0x49, 0xf3, 0x50, 0x4f, 0x53, 0x54, 0x20, 0x2f,
2869  0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e,
2870  0x31, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2871  0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x63,
2872  0x75, 0x72, 0x6c, 0x2f, 0x37, 0x2e, 0x33, 0x37,
2873  0x2e, 0x30, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74,
2874  0x3a, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x36, 0x2e,
2875  0x31, 0x2e, 0x31, 0x30, 0x0d, 0x0a, 0x41, 0x63,
2876  0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x2a, 0x2f,
2877  0x2a, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65,
2878  0x6e, 0x74, 0x2d, 0x4c, 0x65, 0x6e, 0x67, 0x74,
2879  0x68, 0x3a, 0x20, 0x35, 0x32, 0x38, 0x0d, 0x0a,
2880  0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
2881  0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70,
2882  0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
2883  0x6e, 0x2f, 0x78, 0x2d, 0x77, 0x77, 0x77, 0x2d,
2884  0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x75, 0x72, 0x6c,
2885  0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x0d,
2886  0x0a, 0x0d, 0x0a, 0x58, 0x58, 0x58, 0x58, 0x58,
2887  0x58, 0x58, 0x58, 0x41, 0x41, 0x41, 0x41, 0x41,
2888  0x41, 0x41, 0x41, 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, 0x58, 0x58, 0x58, 0x58, 0x58,
2952  0x58, 0x58, 0x58
2953  };
2954 
2955  return DetectContentLongPatternMatchTest(pkt, (uint16_t)sizeof(pkt), sig,
2956  sid);
2957 }
2958 
2959 static int DetectLongContentTest1(void)
2960 {
2961  /* Signature with 256 A's. */
2962  const char *sig = "alert tcp any any -> any any (msg:\"Test Rule\"; content:\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"; sid:1;)";
2963 
2964  return DetectLongContentTestCommon(sig, 1);
2965 }
2966 
2967 static int DetectLongContentTest2(void)
2968 {
2969  /* Signature with 512 A's. */
2970  const char *sig = "alert tcp any any -> any any (msg:\"Test Rule\"; content:\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"; sid:1;)";
2971 
2972  return DetectLongContentTestCommon(sig, 1);
2973 }
2974 
2975 static int DetectLongContentTest3(void)
2976 {
2977  /* Signature with 513 A's. */
2978  const char *sig = "alert tcp any any -> any any (msg:\"Test Rule\"; content:\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"; sid:1;)";
2979 
2980  return !DetectLongContentTestCommon(sig, 1);
2981 }
2982 
2983 #endif /* UNITTESTS */
2984 
2985 /**
2986  * \brief this function registers unit tests for DetectContent
2987  */
2988 static void DetectContentRegisterTests(void)
2989 {
2990 #ifdef UNITTESTS /* UNITTESTS */
2991  g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
2992  g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
2993 
2994  UtRegisterTest("DetectContentDepthTest01", DetectContentDepthTest01);
2995 
2996  UtRegisterTest("DetectContentParseTest01", DetectContentParseTest01);
2997  UtRegisterTest("DetectContentParseTest02", DetectContentParseTest02);
2998  UtRegisterTest("DetectContentParseTest03", DetectContentParseTest03);
2999  UtRegisterTest("DetectContentParseTest04", DetectContentParseTest04);
3000  UtRegisterTest("DetectContentParseTest05", DetectContentParseTest05);
3001  UtRegisterTest("DetectContentParseTest06", DetectContentParseTest06);
3002  UtRegisterTest("DetectContentParseTest07", DetectContentParseTest07);
3003  UtRegisterTest("DetectContentParseTest08", DetectContentParseTest08);
3004  UtRegisterTest("DetectContentParseTest09", DetectContentParseTest09);
3005  UtRegisterTest("DetectContentParseTest17", DetectContentParseTest17);
3006  UtRegisterTest("DetectContentParseTest18", DetectContentParseTest18);
3007  UtRegisterTest("DetectContentParseTest19", DetectContentParseTest19);
3008  UtRegisterTest("DetectContentParseTest20", DetectContentParseTest20);
3009  UtRegisterTest("DetectContentParseTest21", DetectContentParseTest21);
3010  UtRegisterTest("DetectContentParseTest22", DetectContentParseTest22);
3011  UtRegisterTest("DetectContentParseTest23", DetectContentParseTest23);
3012  UtRegisterTest("DetectContentParseTest24", DetectContentParseTest24);
3013  UtRegisterTest("DetectContentParseTest25", DetectContentParseTest25);
3014  UtRegisterTest("DetectContentParseTest26", DetectContentParseTest26);
3015  UtRegisterTest("DetectContentParseTest27", DetectContentParseTest27);
3016  UtRegisterTest("DetectContentParseTest28", DetectContentParseTest28);
3017  UtRegisterTest("DetectContentParseTest29", DetectContentParseTest29);
3018  UtRegisterTest("DetectContentParseTest30", DetectContentParseTest30);
3019  UtRegisterTest("DetectContentParseTest31", DetectContentParseTest31);
3020  UtRegisterTest("DetectContentParseTest32", DetectContentParseTest32);
3021  UtRegisterTest("DetectContentParseTest33", DetectContentParseTest33);
3022  UtRegisterTest("DetectContentParseTest34", DetectContentParseTest34);
3023  UtRegisterTest("DetectContentParseTest35", DetectContentParseTest35);
3024  UtRegisterTest("DetectContentParseTest36", DetectContentParseTest36);
3025  UtRegisterTest("DetectContentParseTest37", DetectContentParseTest37);
3026  UtRegisterTest("DetectContentParseTest38", DetectContentParseTest38);
3027  UtRegisterTest("DetectContentParseTest39", DetectContentParseTest39);
3028  UtRegisterTest("DetectContentParseTest40", DetectContentParseTest40);
3029  UtRegisterTest("DetectContentParseTest41", DetectContentParseTest41);
3030  UtRegisterTest("DetectContentParseTest42", DetectContentParseTest42);
3031  UtRegisterTest("DetectContentParseTest43", DetectContentParseTest43);
3032  UtRegisterTest("DetectContentParseTest44", DetectContentParseTest44);
3033  UtRegisterTest("DetectContentParseTest45", DetectContentParseTest45);
3034 
3035  /* The reals */
3036  UtRegisterTest("DetectContentLongPatternMatchTest01",
3037  DetectContentLongPatternMatchTest01);
3038  UtRegisterTest("DetectContentLongPatternMatchTest02",
3039  DetectContentLongPatternMatchTest02);
3040  UtRegisterTest("DetectContentLongPatternMatchTest03",
3041  DetectContentLongPatternMatchTest03);
3042  UtRegisterTest("DetectContentLongPatternMatchTest04",
3043  DetectContentLongPatternMatchTest04);
3044  UtRegisterTest("DetectContentLongPatternMatchTest05",
3045  DetectContentLongPatternMatchTest05);
3046  UtRegisterTest("DetectContentLongPatternMatchTest06",
3047  DetectContentLongPatternMatchTest06);
3048  UtRegisterTest("DetectContentLongPatternMatchTest07",
3049  DetectContentLongPatternMatchTest07);
3050  UtRegisterTest("DetectContentLongPatternMatchTest08",
3051  DetectContentLongPatternMatchTest08);
3052  UtRegisterTest("DetectContentLongPatternMatchTest09",
3053  DetectContentLongPatternMatchTest09);
3054  UtRegisterTest("DetectContentLongPatternMatchTest10",
3055  DetectContentLongPatternMatchTest10);
3056  UtRegisterTest("DetectContentLongPatternMatchTest11",
3057  DetectContentLongPatternMatchTest11);
3058 
3059  /* Negated content tests */
3060  UtRegisterTest("SigTest41TestNegatedContent", SigTest41TestNegatedContent);
3061  UtRegisterTest("SigTest41aTestNegatedContent",
3062  SigTest41aTestNegatedContent);
3063  UtRegisterTest("SigTest42TestNegatedContent", SigTest42TestNegatedContent);
3064  UtRegisterTest("SigTest43TestNegatedContent", SigTest43TestNegatedContent);
3065  UtRegisterTest("SigTest44TestNegatedContent", SigTest44TestNegatedContent);
3066  UtRegisterTest("SigTest45TestNegatedContent", SigTest45TestNegatedContent);
3067  UtRegisterTest("SigTest46TestNegatedContent", SigTest46TestNegatedContent);
3068  UtRegisterTest("SigTest47TestNegatedContent", SigTest47TestNegatedContent);
3069  UtRegisterTest("SigTest48TestNegatedContent", SigTest48TestNegatedContent);
3070  UtRegisterTest("SigTest49TestNegatedContent", SigTest49TestNegatedContent);
3071  UtRegisterTest("SigTest50TestNegatedContent", SigTest50TestNegatedContent);
3072  UtRegisterTest("SigTest51TestNegatedContent", SigTest51TestNegatedContent);
3073  UtRegisterTest("SigTest52TestNegatedContent", SigTest52TestNegatedContent);
3074  UtRegisterTest("SigTest53TestNegatedContent", SigTest53TestNegatedContent);
3075  UtRegisterTest("SigTest54TestNegatedContent", SigTest54TestNegatedContent);
3076  UtRegisterTest("SigTest55TestNegatedContent", SigTest55TestNegatedContent);
3077  UtRegisterTest("SigTest56TestNegatedContent", SigTest56TestNegatedContent);
3078  UtRegisterTest("SigTest57TestNegatedContent", SigTest57TestNegatedContent);
3079  UtRegisterTest("SigTest58TestNegatedContent", SigTest58TestNegatedContent);
3080  UtRegisterTest("SigTest59TestNegatedContent", SigTest59TestNegatedContent);
3081  UtRegisterTest("SigTest60TestNegatedContent", SigTest60TestNegatedContent);
3082  UtRegisterTest("SigTest61TestNegatedContent", SigTest61TestNegatedContent);
3083  UtRegisterTest("SigTest62TestNegatedContent", SigTest62TestNegatedContent);
3084  UtRegisterTest("SigTest63TestNegatedContent", SigTest63TestNegatedContent);
3085  UtRegisterTest("SigTest64TestNegatedContent", SigTest64TestNegatedContent);
3086  UtRegisterTest("SigTest65TestNegatedContent", SigTest65TestNegatedContent);
3087  UtRegisterTest("SigTest66TestNegatedContent", SigTest66TestNegatedContent);
3088  UtRegisterTest("SigTest67TestNegatedContent", SigTest67TestNegatedContent);
3089  UtRegisterTest("SigTest68TestNegatedContent", SigTest68TestNegatedContent);
3090  UtRegisterTest("SigTest69TestNegatedContent", SigTest69TestNegatedContent);
3091  UtRegisterTest("SigTest70TestNegatedContent", SigTest70TestNegatedContent);
3092  UtRegisterTest("SigTest71TestNegatedContent", SigTest71TestNegatedContent);
3093  UtRegisterTest("SigTest72TestNegatedContent", SigTest72TestNegatedContent);
3094  UtRegisterTest("SigTest73TestNegatedContent", SigTest73TestNegatedContent);
3095  UtRegisterTest("SigTest74TestNegatedContent", SigTest74TestNegatedContent);
3096  UtRegisterTest("SigTest75TestNegatedContent", SigTest75TestNegatedContent);
3097 
3098  UtRegisterTest("SigTest76TestBug134", SigTest76TestBug134);
3099  UtRegisterTest("SigTest77TestBug139", SigTest77TestBug139);
3100 
3101  UtRegisterTest("DetectLongContentTest1", DetectLongContentTest1);
3102  UtRegisterTest("DetectLongContentTest2", DetectLongContentTest2);
3103  UtRegisterTest("DetectLongContentTest3", DetectLongContentTest3);
3104 #endif /* UNITTESTS */
3105 }
#define TEST_RUN(sig, o, d)
void DetectContentRegister(void)
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1409
SignatureInitData * init_data
Definition: detect.h:564
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1150
SpmGlobalThreadCtx * spm_global_thread_ctx
Definition: detect.h:778
#define SCLogDebug(...)
Definition: util-debug.h:335
#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:443
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:497
#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:421
void DetectContentPrint(DetectContentData *cd)
Helper function to print a DetectContentData.
Signature * sig_list
Definition: detect.h:730
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:817
#define DETECT_CONTENT_DISTANCE
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
const char * name
Definition: detect.h:1164
Signature container.
Definition: detect.h:496
#define DETECT_CONTENT_DEPTH
#define TRUE
uint16_t flags
Definition: detect-pcre.h:42
struct SigMatch_ * next
Definition: detect.h:326
main detection engine ctx
Definition: detect.h:724
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:631
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:296
#define SIZE_OF_PACKET
Definition: decode.h:618
int DetectBufferTypeGetByName(const char *name)
#define str(s)
#define SCCalloc(nm, a)
Definition: util-mem.h:197
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:725
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1155
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
#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:119
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:1742
int SigParseGetMaxDsize(const Signature *s)
get max dsize "depth"
Definition: detect-dsize.c:381
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1348
#define SCEnter(...)
Definition: util-debug.h:337
#define DETECT_SM_LIST_NOTSET
Definition: detect.h:118
uint8_t flowflags
Definition: decode.h:437
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)
AppProto alproto
Definition: detect.h:500
struct SigMatch_ ** smlists_tail
Definition: detect.h:492
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
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:567
uint8_t type
Definition: detect.h:323
void DetectContentFree(void *ptr)
this function will SCFree memory associated with DetectContentData
#define DETECT_CONTENT_ENDS_WITH
const char * desc
Definition: detect.h:1166
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:288
struct SigMatch_ ** smlists
Definition: detect.h:490
Signature * SigAlloc(void)
uint32_t smlists_array_size
Definition: detect.h:488
SigMatchCtx * ctx
Definition: detect.h:325
#define SCMalloc(a)
Definition: util-mem.h:166
#define DETECT_CONTENT_NEGATED
#define SCFree(a)
Definition: util-mem.h:228
#define SIG_FLAG_DSIZE
Definition: detect.h:222
SpmGlobalThreadCtx * SpmInitGlobalThreadCtx(uint16_t matcher)
Definition: util-spm.c:131
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:667
int(* Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1133
void SpmDestroyCtx(SpmCtx *ctx)
Definition: util-spm.c:176
const char * url
Definition: detect.h:1167
#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:1092
#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
#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:441
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1352
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1158
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:1156
a single match condition for a signature
Definition: detect.h:322
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:512