suricata
detect-pcre.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 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  * Implements the pcre keyword
24  */
25 
26 #include "suricata-common.h"
27 #include "debug.h"
28 #include "decode.h"
29 #include "detect.h"
30 
31 #include "pkt-var.h"
32 #include "flow-var.h"
33 #include "flow-util.h"
34 
35 #include "detect-pcre.h"
36 #include "detect-flowvar.h"
37 
38 #include "detect-parse.h"
39 #include "detect-engine.h"
40 #include "detect-engine-sigorder.h"
41 #include "detect-engine-mpm.h"
42 #include "detect-engine-state.h"
43 
44 #include "util-var-name.h"
45 #include "util-unittest-helper.h"
46 #include "util-debug.h"
47 #include "util-unittest.h"
48 #include "util-print.h"
49 #include "util-pool.h"
50 
51 #include "conf.h"
52 #include "app-layer.h"
53 #include "app-layer-htp.h"
54 #include "stream.h"
55 #include "stream-tcp.h"
56 #include "stream-tcp-private.h"
57 #include "stream-tcp-reassemble.h"
58 #include "app-layer-protos.h"
59 #include "app-layer-parser.h"
60 #include "util-pages.h"
61 
62 /* pcre named substring capture supports only 32byte names, A-z0-9 plus _
63  * and needs to start with non-numeric. */
64 #define PARSE_CAPTURE_REGEX "\\(\\?P\\<([A-z]+)\\_([A-z0-9_]+)\\>"
65 #define PARSE_REGEX "(?<!\\\\)/(.*(?<!(?<!\\\\)\\\\))/([^\"]*)"
66 
67 #define SC_MATCH_LIMIT_DEFAULT 3500
68 #define SC_MATCH_LIMIT_RECURSION_DEFAULT 1500
69 
70 static int pcre_match_limit = 0;
71 static int pcre_match_limit_recursion = 0;
72 
73 static pcre *parse_regex;
74 static pcre_extra *parse_regex_study;
75 static pcre *parse_capture_regex;
76 static pcre_extra *parse_capture_regex_study;
77 
78 #ifdef PCRE_HAVE_JIT
79 static int pcre_use_jit = 1;
80 #endif
81 
82 static int DetectPcreSetup (DetectEngineCtx *, Signature *, const char *);
83 static void DetectPcreFree(void *);
84 static void DetectPcreRegisterTests(void);
85 
86 void DetectPcreRegister (void)
87 {
89  sigmatch_table[DETECT_PCRE].desc = "match on regular expression";
90  sigmatch_table[DETECT_PCRE].url = DOC_URL DOC_VERSION "/rules/payload-keywords.html#pcre-perl-compatible-regular-expressions";
92  sigmatch_table[DETECT_PCRE].Setup = DetectPcreSetup;
93  sigmatch_table[DETECT_PCRE].Free = DetectPcreFree;
94  sigmatch_table[DETECT_PCRE].RegisterTests = DetectPcreRegisterTests;
96 
97  intmax_t val = 0;
98 
99  if (!ConfGetInt("pcre.match-limit", &val)) {
100  pcre_match_limit = SC_MATCH_LIMIT_DEFAULT;
101  SCLogDebug("Using PCRE match-limit setting of: %i", pcre_match_limit);
102  }
103  else {
104  pcre_match_limit = val;
105  if (pcre_match_limit != SC_MATCH_LIMIT_DEFAULT) {
106  SCLogInfo("Using PCRE match-limit setting of: %i", pcre_match_limit);
107  } else {
108  SCLogDebug("Using PCRE match-limit setting of: %i", pcre_match_limit);
109  }
110  }
111 
112  val = 0;
113 
114  if (!ConfGetInt("pcre.match-limit-recursion", &val)) {
115  pcre_match_limit_recursion = SC_MATCH_LIMIT_RECURSION_DEFAULT;
116  SCLogDebug("Using PCRE match-limit-recursion setting of: %i", pcre_match_limit_recursion);
117  }
118  else {
119  pcre_match_limit_recursion = val;
120  if (pcre_match_limit_recursion != SC_MATCH_LIMIT_RECURSION_DEFAULT) {
121  SCLogInfo("Using PCRE match-limit-recursion setting of: %i", pcre_match_limit_recursion);
122  } else {
123  SCLogDebug("Using PCRE match-limit-recursion setting of: %i", pcre_match_limit_recursion);
124  }
125  }
126 
127  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
128 
129  /* setup the capture regex, as it needs PCRE_UNGREEDY we do it manually */
130  const char *eb;
131  int eo;
132  int opts = PCRE_UNGREEDY; /* pkt_http_ua should be pkt, http_ua, for this reason the UNGREEDY */
133 
134  parse_capture_regex = pcre_compile(PARSE_CAPTURE_REGEX, opts, &eb, &eo, NULL);
135  if (parse_capture_regex == NULL)
136  {
137  FatalError(SC_ERR_PCRE_COMPILE, "pcre compile of \"%s\" failed at offset %" PRId32 ": %s", PARSE_CAPTURE_REGEX, eo, eb);
138  }
139 
140  parse_capture_regex_study = pcre_study(parse_capture_regex, 0, &eb);
141  if(eb != NULL)
142  {
143  FatalError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb);
144  }
145 
146 #ifdef PCRE_HAVE_JIT
147  if (PageSupportsRWX() == 0) {
148  SCLogConfig("PCRE won't use JIT as OS doesn't allow RWX pages");
149  pcre_use_jit = 0;
150  }
151 #endif
152 
153  DetectParseRegexAddToFreeList(parse_capture_regex, parse_capture_regex_study);
154  return;
155 }
156 
157 /**
158  * \brief Match a regex on a single payload.
159  *
160  * \param det_ctx Thread detection ctx.
161  * \param s Signature.
162  * \param sm Sig match to match against.
163  * \param p Packet to set PktVars if any.
164  * \param f Flow to set FlowVars if any.
165  * \param payload Payload to inspect.
166  * \param payload_len Length of the payload.
167  *
168  * \retval 1 Match.
169  * \retval 0 No match.
170  */
172  const SigMatchData *smd, Packet *p, Flow *f,
173  uint8_t *payload, uint32_t payload_len)
174 {
175  SCEnter();
176 #define MAX_SUBSTRINGS 30
177  int ret = 0;
178  int ov[MAX_SUBSTRINGS];
179  uint8_t *ptr = NULL;
180  uint16_t len = 0;
181  uint16_t capture_len = 0;
182 
183  DetectPcreData *pe = (DetectPcreData *)smd->ctx;
184 
185  if (pe->flags & DETECT_PCRE_RELATIVE) {
186  ptr = payload + det_ctx->buffer_offset;
187  len = payload_len - det_ctx->buffer_offset;
188  } else {
189  ptr = payload;
190  len = payload_len;
191  }
192 
193  int start_offset = 0;
194  if (det_ctx->pcre_match_start_offset != 0) {
195  start_offset = (payload + det_ctx->pcre_match_start_offset - ptr);
196  }
197 
198  /* run the actual pcre detection */
199  ret = pcre_exec(pe->re, pe->sd, (char *)ptr, len, start_offset, 0, ov, MAX_SUBSTRINGS);
200  SCLogDebug("ret %d (negating %s)", ret, (pe->flags & DETECT_PCRE_NEGATE) ? "set" : "not set");
201 
202  if (ret == PCRE_ERROR_NOMATCH) {
203  if (pe->flags & DETECT_PCRE_NEGATE) {
204  /* regex didn't match with negate option means we
205  * consider it a match */
206  ret = 1;
207  } else {
208  ret = 0;
209  }
210  } else if (ret >= 0) {
211  if (pe->flags & DETECT_PCRE_NEGATE) {
212  /* regex matched but we're negated, so not
213  * considering it a match */
214  ret = 0;
215  } else {
216  /* regex matched and we're not negated,
217  * considering it a match */
218 
219  SCLogDebug("ret %d pe->idx %u", ret, pe->idx);
220 
221  /* see if we need to do substring capturing. */
222  if (ret > 1 && pe->idx != 0) {
223  uint8_t x;
224  for (x = 0; x < pe->idx; x++) {
225  SCLogDebug("capturing %u", x);
226  const char *str_ptr = NULL;
227  ret = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, x+1, &str_ptr);
228  if (unlikely(ret == 0)) {
229  pcre_free_substring(str_ptr);
230  continue;
231  }
232 
233  SCLogDebug("data %p/%u, type %u id %u p %p",
234  str_ptr, ret, pe->captypes[x], pe->capids[x], p);
235 
236  if (pe->captypes[x] == VAR_TYPE_PKT_VAR_KV) {
237  /* get the value, as first capture is the key */
238  const char *str_ptr2 = NULL;
239  int ret2 = pcre_get_substring((char *)ptr, ov, MAX_SUBSTRINGS, x+2, &str_ptr2);
240  if (unlikely(ret2 == 0)) {
241  pcre_free_substring(str_ptr);
242  pcre_free_substring(str_ptr2);
243  break;
244  }
245  /* key length is limited to 256 chars */
246  uint16_t key_len = (ret < 0xff) ? (uint16_t)ret : 0xff;
247  capture_len = (ret2 < 0xffff) ? (uint16_t)ret2 : 0xffff;
248 
249  (void)DetectVarStoreMatchKeyValue(det_ctx,
250  (uint8_t *)str_ptr, key_len,
251  (uint8_t *)str_ptr2, capture_len,
253 
254  } else if (pe->captypes[x] == VAR_TYPE_PKT_VAR) {
255  /* store max 64k. Errors are ignored */
256  capture_len = (ret < 0xffff) ? (uint16_t)ret : 0xffff;
257  (void)DetectVarStoreMatch(det_ctx, pe->capids[x],
258  (uint8_t *)str_ptr, capture_len,
260 
261  } else if (pe->captypes[x] == VAR_TYPE_FLOW_VAR && f != NULL) {
262  /* store max 64k. Errors are ignored */
263  capture_len = (ret < 0xffff) ? (uint16_t)ret : 0xffff;
264  (void)DetectVarStoreMatch(det_ctx, pe->capids[x],
265  (uint8_t *)str_ptr, capture_len,
267  }
268  }
269  }
270 
271  /* update offset for pcre RELATIVE */
272  det_ctx->buffer_offset = (ptr + ov[1]) - payload;
273  det_ctx->pcre_match_start_offset = (ptr + ov[0] + 1) - payload;
274 
275  ret = 1;
276  }
277 
278  } else {
279  SCLogDebug("pcre had matching error");
280  ret = 0;
281  }
282  SCReturnInt(ret);
283 }
284 
285 static int DetectPcreSetList(int list, int set)
286 {
287  if (list != DETECT_SM_LIST_NOTSET) {
288  SCLogError(SC_ERR_INVALID_SIGNATURE, "only one pcre option to specify a buffer type is allowed");
289  return -1;
290  }
291  return set;
292 }
293 
294 static int DetectPcreHasUpperCase(const char *re)
295 {
296  size_t len = strlen(re);
297  bool is_meta = false;
298  bool is_meta_hex = false;
299  int meta_hex_cnt = 0;
300 
301  for (size_t i = 0; i < len; i++) {
302  if (is_meta_hex) {
303  meta_hex_cnt++;
304 
305  if (meta_hex_cnt == 2) {
306  is_meta_hex = false;
307  meta_hex_cnt = 0;
308  }
309  } else if (is_meta) {
310  if (re[i] == 'x') {
311  is_meta_hex = true;
312  } else {
313  is_meta = false;
314  }
315  }
316  else if (re[i] == '\\') {
317  is_meta = true;
318  }
319  else if (isupper((unsigned char)re[i])) {
320  return 1;
321  }
322  }
323 
324  return 0;
325 }
326 
327 static DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx,
328  const char *regexstr, int *sm_list, char *capture_names,
329  size_t capture_names_size, bool negate, AppProto *alproto)
330 {
331  int ec;
332  const char *eb;
333  int eo;
334  int opts = 0;
335  DetectPcreData *pd = NULL;
336  char *op = NULL;
337 #define MAX_SUBSTRINGS 30
338  int ret = 0, res = 0;
339  int ov[MAX_SUBSTRINGS];
340  int check_host_header = 0;
341  char op_str[64] = "";
342 
343  int cut_capture = 0;
344  char *fcap = strstr(regexstr, "flow:");
345  char *pcap = strstr(regexstr, "pkt:");
346  /* take the size of the whole input as buffer size for the regex we will
347  * extract below. Add 1 to please Coverity's alloc_strlen test. */
348  size_t slen = strlen(regexstr) + 1;
349  if (fcap || pcap) {
350  SCLogDebug("regexstr %s", regexstr);
351 
352  if (fcap && !pcap)
353  cut_capture = fcap - regexstr;
354  else if (pcap && !fcap)
355  cut_capture = pcap - regexstr;
356  else
357  cut_capture = MIN((pcap - regexstr), (fcap - regexstr));
358 
359  SCLogDebug("cut_capture %d", cut_capture);
360 
361  if (cut_capture > 1) {
362  int offset = cut_capture - 1;
363  while (offset) {
364  SCLogDebug("regexstr[offset] %c", regexstr[offset]);
365  if (regexstr[offset] == ',' || regexstr[offset] == ' ') {
366  offset--;
367  }
368  else
369  break;
370  }
371 
372  if (cut_capture == (offset + 1)) {
373  SCLogDebug("missing separators, assume it's part of the regex");
374  } else {
375  slen = offset + 1;
376  strlcpy(capture_names, regexstr+cut_capture, capture_names_size);
377  if (capture_names[strlen(capture_names)-1] == '"')
378  capture_names[strlen(capture_names)-1] = '\0';
379  }
380  }
381  }
382 
383  char re[slen];
384  ret = pcre_exec(parse_regex, parse_regex_study, regexstr, slen,
385  0, 0, ov, MAX_SUBSTRINGS);
386  if (ret <= 0) {
387  SCLogError(SC_ERR_PCRE_MATCH, "pcre parse error: %s", regexstr);
388  goto error;
389  }
390 
391  res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS,
392  1, re, slen);
393  if (res < 0) {
394  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
395  return NULL;
396  }
397 
398  if (ret > 2) {
399  res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS,
400  2, op_str, sizeof(op_str));
401  if (res < 0) {
402  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
403  return NULL;
404  }
405  op = op_str;
406  }
407  //printf("ret %" PRId32 " re \'%s\', op \'%s\'\n", ret, re, op);
408 
409  pd = SCMalloc(sizeof(DetectPcreData));
410  if (unlikely(pd == NULL))
411  goto error;
412  memset(pd, 0, sizeof(DetectPcreData));
413 
414  if (negate)
415  pd->flags |= DETECT_PCRE_NEGATE;
416 
417  if (op != NULL) {
418  while (*op) {
419  SCLogDebug("regex option %c", *op);
420 
421  switch (*op) {
422  case 'A':
423  opts |= PCRE_ANCHORED;
424  break;
425  case 'E':
426  opts |= PCRE_DOLLAR_ENDONLY;
427  break;
428  case 'G':
429  opts |= PCRE_UNGREEDY;
430  break;
431 
432  case 'i':
433  opts |= PCRE_CASELESS;
435  break;
436  case 'm':
437  opts |= PCRE_MULTILINE;
438  break;
439  case 's':
440  opts |= PCRE_DOTALL;
441  break;
442  case 'x':
443  opts |= PCRE_EXTENDED;
444  break;
445 
446  case 'O':
448  break;
449 
450  case 'B': /* snort's option */
451  if (*sm_list != DETECT_SM_LIST_NOTSET) {
452  SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'B' inconsistent with chosen buffer");
453  goto error;
454  }
456  break;
457  case 'R': /* snort's option */
459  break;
460 
461  /* buffer selection */
462 
463  case 'U': { /* snort's option */
464  if (pd->flags & DETECT_PCRE_RAWBYTES) {
465  SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'U' inconsistent with 'B'");
466  goto error;
467  }
468  int list = DetectBufferTypeGetByName("http_uri");
469  *sm_list = DetectPcreSetList(*sm_list, list);
470  *alproto = ALPROTO_HTTP;
471  break;
472  }
473  case 'V': {
474  if (pd->flags & DETECT_PCRE_RAWBYTES) {
475  SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'V' inconsistent with 'B'");
476  goto error;
477  }
478  int list = DetectBufferTypeGetByName("http_user_agent");
479  *sm_list = DetectPcreSetList(*sm_list, list);
480  *alproto = ALPROTO_HTTP;
481  break;
482  }
483  case 'W': {
484  if (pd->flags & DETECT_PCRE_RAWBYTES) {
485  SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'W' inconsistent with 'B'");
486  goto error;
487  }
488  int list = DetectBufferTypeGetByName("http_host");
489  *sm_list = DetectPcreSetList(*sm_list, list);
490  *alproto = ALPROTO_HTTP;
491  check_host_header = 1;
492  break;
493  }
494  case 'Z': {
495  if (pd->flags & DETECT_PCRE_RAWBYTES) {
496  SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'Z' inconsistent with 'B'");
497  goto error;
498  }
499  int list = DetectBufferTypeGetByName("http_raw_host");
500  *sm_list = DetectPcreSetList(*sm_list, list);
501  *alproto = ALPROTO_HTTP;
502  break;
503  }
504  case 'H': { /* snort's option */
505  if (pd->flags & DETECT_PCRE_RAWBYTES) {
506  SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'H' inconsistent with 'B'");
507  goto error;
508  }
509  int list = DetectBufferTypeGetByName("http_header");
510  *sm_list = DetectPcreSetList(*sm_list, list);
511  *alproto = ALPROTO_HTTP;
512  break;
513  } case 'I': { /* snort's option */
514  if (pd->flags & DETECT_PCRE_RAWBYTES) {
515  SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'I' inconsistent with 'B'");
516  goto error;
517  }
518  int list = DetectBufferTypeGetByName("http_raw_uri");
519  *sm_list = DetectPcreSetList(*sm_list, list);
520  *alproto = ALPROTO_HTTP;
521  break;
522  }
523  case 'D': { /* snort's option */
524  int list = DetectBufferTypeGetByName("http_raw_header");
525  *sm_list = DetectPcreSetList(*sm_list, list);
526  *alproto = ALPROTO_HTTP;
527  break;
528  }
529  case 'M': { /* snort's option */
530  if (pd->flags & DETECT_PCRE_RAWBYTES) {
531  SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'M' inconsistent with 'B'");
532  goto error;
533  }
534  int list = DetectBufferTypeGetByName("http_method");
535  *sm_list = DetectPcreSetList(*sm_list, list);
536  *alproto = ALPROTO_HTTP;
537  break;
538  }
539  case 'C': { /* snort's option */
540  if (pd->flags & DETECT_PCRE_RAWBYTES) {
541  SCLogError(SC_ERR_INVALID_SIGNATURE, "regex modifier 'C' inconsistent with 'B'");
542  goto error;
543  }
544  int list = DetectBufferTypeGetByName("http_cookie");
545  *sm_list = DetectPcreSetList(*sm_list, list);
546  *alproto = ALPROTO_HTTP;
547  break;
548  }
549  case 'P': {
550  /* snort's option (http request body inspection) */
551  int list = DetectBufferTypeGetByName("http_client_body");
552  *sm_list = DetectPcreSetList(*sm_list, list);
553  *alproto = ALPROTO_HTTP;
554  break;
555  }
556  case 'Q': {
557  int list = DetectBufferTypeGetByName("file_data");
558  /* suricata extension (http response body inspection) */
559  *sm_list = DetectPcreSetList(*sm_list, list);
560  *alproto = ALPROTO_HTTP;
561  break;
562  }
563  case 'Y': {
564  /* snort's option */
565  int list = DetectBufferTypeGetByName("http_stat_msg");
566  *sm_list = DetectPcreSetList(*sm_list, list);
567  *alproto = ALPROTO_HTTP;
568  break;
569  }
570  case 'S': {
571  /* snort's option */
572  int list = DetectBufferTypeGetByName("http_stat_code");
573  *sm_list = DetectPcreSetList(*sm_list, list);
574  *alproto = ALPROTO_HTTP;
575  break;
576  }
577  default:
578  SCLogError(SC_ERR_UNKNOWN_REGEX_MOD, "unknown regex modifier '%c'", *op);
579  goto error;
580  }
581  op++;
582  }
583  }
584  if (*sm_list == -1)
585  goto error;
586 
587  SCLogDebug("DetectPcreParse: \"%s\"", re);
588 
589  /* host header */
590  if (check_host_header) {
591  if (pd->flags & DETECT_PCRE_CASELESS) {
592  SCLogWarning(SC_ERR_INVALID_SIGNATURE, "http host pcre(\"W\") "
593  "specified along with \"i(caseless)\" modifier. "
594  "Since the hostname buffer we match against "
595  "is actually lowercase, having a "
596  "nocase is redundant.");
597  }
598  else if (DetectPcreHasUpperCase(re)) {
599  SCLogError(SC_ERR_INVALID_SIGNATURE, "pcre host(\"W\") "
600  "specified has an uppercase char. "
601  "Since the hostname buffer we match against "
602  "is actually lowercase, please specify an "
603  "all lowercase based pcre.");
604  goto error;
605  }
606  }
607 
608  /* Try to compile as if all (...) groups had been meant as (?:...),
609  * which is the common case in most rules.
610  * If we fail because a capture group is later referenced (e.g., \1),
611  * PCRE will let us know.
612  */
613  if (capture_names == NULL || strlen(capture_names) == 0)
614  opts |= PCRE_NO_AUTO_CAPTURE;
615 
616  pd->re = pcre_compile2(re, opts, &ec, &eb, &eo, NULL);
617  if (pd->re == NULL && ec == 15) { // reference to non-existent subpattern
618  opts &= ~PCRE_NO_AUTO_CAPTURE;
619  pd->re = pcre_compile(re, opts, &eb, &eo, NULL);
620  }
621 
622  if (pd->re == NULL) {
623  SCLogError(SC_ERR_PCRE_COMPILE, "pcre compile of \"%s\" failed "
624  "at offset %" PRId32 ": %s", regexstr, eo, eb);
625  goto error;
626  }
627 
628  int options = 0;
629 #ifdef PCRE_HAVE_JIT
630  if (pcre_use_jit)
631  options |= PCRE_STUDY_JIT_COMPILE;
632 #endif
633  pd->sd = pcre_study(pd->re, options, &eb);
634  if(eb != NULL) {
635  SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed : %s", eb);
636  goto error;
637  }
638 
639 #ifdef PCRE_HAVE_JIT
640  int jit = 0;
641  ret = pcre_fullinfo(pd->re, pd->sd, PCRE_INFO_JIT, &jit);
642  if (ret != 0 || jit != 1) {
643  /* warning, so we won't print the sig after this. Adding
644  * file and line to the message so the admin can figure
645  * out what sig this is about */
646  SCLogDebug("PCRE JIT compiler does not support: %s. "
647  "Falling back to regular PCRE handling (%s:%d)",
648  regexstr, de_ctx->rule_file, de_ctx->rule_line);
649  }
650 #endif /*PCRE_HAVE_JIT*/
651 
652  if (pd->sd == NULL)
653  pd->sd = (pcre_extra *) SCCalloc(1,sizeof(pcre_extra));
654 
655  if (pd->sd) {
656  if(pd->flags & DETECT_PCRE_MATCH_LIMIT) {
657  if(pcre_match_limit >= -1) {
658  pd->sd->match_limit = pcre_match_limit;
659  pd->sd->flags |= PCRE_EXTRA_MATCH_LIMIT;
660  }
661 #ifndef NO_PCRE_MATCH_RLIMIT
662  if(pcre_match_limit_recursion >= -1) {
663  pd->sd->match_limit_recursion = pcre_match_limit_recursion;
664  pd->sd->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
665  }
666 #endif /* NO_PCRE_MATCH_RLIMIT */
667  } else {
668  pd->sd->match_limit = SC_MATCH_LIMIT_DEFAULT;
669  pd->sd->flags |= PCRE_EXTRA_MATCH_LIMIT;
670 #ifndef NO_PCRE_MATCH_RLIMIT
671  pd->sd->match_limit_recursion = SC_MATCH_LIMIT_RECURSION_DEFAULT;
672  pd->sd->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
673 #endif /* NO_PCRE_MATCH_RLIMIT */
674  }
675  } else {
676  goto error;
677  }
678  return pd;
679 
680 error:
681  if (pd != NULL && pd->re != NULL)
682  pcre_free(pd->re);
683  if (pd != NULL && pd->sd != NULL)
684  pcre_free_study(pd->sd);
685  if (pd)
686  SCFree(pd);
687  return NULL;
688 }
689 
690 /** \internal
691  * \brief check if we need to extract capture settings and set them up if needed
692  */
693 static int DetectPcreParseCapture(const char *regexstr, DetectEngineCtx *de_ctx, DetectPcreData *pd,
694  char *capture_names)
695 {
696  int ret = 0, res = 0;
697  int ov[MAX_SUBSTRINGS];
698  memset(&ov, 0, sizeof(ov));
699  char type_str[16] = "";
700  const char *orig_right_edge = regexstr + strlen(regexstr);
701  char *name_array[DETECT_PCRE_CAPTURE_MAX] = { NULL };
702  int name_idx = 0;
703  int capture_cnt = 0;
704  int key = 0;
705 
706  SCLogDebug("regexstr %s, pd %p", regexstr, pd);
707 
708  ret = pcre_fullinfo(pd->re, pd->sd, PCRE_INFO_CAPTURECOUNT, &capture_cnt);
709  SCLogDebug("ret %d capture_cnt %d", ret, capture_cnt);
710  if (ret == 0 && capture_cnt && strlen(capture_names) > 0)
711  {
712  char *ptr = NULL;
713  while ((name_array[name_idx] = strtok_r(name_idx == 0 ? capture_names : NULL, " ,", &ptr))){
714  if (name_idx > capture_cnt) {
715  SCLogError(SC_ERR_VAR_LIMIT, "more pkt/flow "
716  "var capture names than capturing substrings");
717  return -1;
718  }
719  SCLogDebug("name '%s'", name_array[name_idx]);
720 
721  if (strcmp(name_array[name_idx], "pkt:key") == 0) {
722  key = 1;
723  SCLogDebug("key-value/key");
724 
725  pd->captypes[pd->idx] = VAR_TYPE_PKT_VAR_KV;
726  SCLogDebug("id %u type %u", pd->capids[pd->idx], pd->captypes[pd->idx]);
727  pd->idx++;
728 
729  } else if (key == 1 && strcmp(name_array[name_idx], "pkt:value") == 0) {
730  SCLogDebug("key-value/value");
731  key = 0;
732 
733  /* kv error conditions */
734  } else if (key == 0 && strcmp(name_array[name_idx], "pkt:value") == 0) {
735  return -1;
736  } else if (key == 1) {
737  return -1;
738 
739  } else if (strncmp(name_array[name_idx], "flow:", 5) == 0) {
740  pd->capids[pd->idx] = VarNameStoreSetupAdd(name_array[name_idx]+5, VAR_TYPE_FLOW_VAR);
741  pd->captypes[pd->idx] = VAR_TYPE_FLOW_VAR;
742  pd->idx++;
743 
744  } else if (strncmp(name_array[name_idx], "pkt:", 4) == 0) {
745  pd->capids[pd->idx] = VarNameStoreSetupAdd(name_array[name_idx]+4, VAR_TYPE_PKT_VAR);
746  pd->captypes[pd->idx] = VAR_TYPE_PKT_VAR;
747  SCLogDebug("id %u type %u", pd->capids[pd->idx], pd->captypes[pd->idx]);
748  pd->idx++;
749 
750  } else {
751  SCLogError(SC_ERR_VAR_LIMIT, " pkt/flow "
752  "var capture names must start with 'pkt:' or 'flow:'");
753  return -1;
754  }
755 
756  name_idx++;
757  if (name_idx >= DETECT_PCRE_CAPTURE_MAX)
758  break;
759  }
760  }
761 
762  /* take the size of the whole input as buffer size for the string we will
763  * extract below. Add 1 to please Coverity's alloc_strlen test. */
764  size_t cap_buffer_len = strlen(regexstr) + 1;
765  char capture_str[cap_buffer_len];
766  memset(capture_str, 0x00, cap_buffer_len);
767 
768  if (de_ctx == NULL)
769  goto error;
770 
771  while (1) {
772  SCLogDebug("\'%s\'", regexstr);
773 
774  ret = pcre_exec(parse_capture_regex, parse_capture_regex_study, regexstr, strlen(regexstr), 0, 0, ov, MAX_SUBSTRINGS);
775  if (ret < 3) {
776  return 0;
777  }
778 
779  res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 1, type_str, sizeof(type_str));
780  if (res < 0) {
781  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
782  goto error;
783  }
784  res = pcre_copy_substring((char *)regexstr, ov, MAX_SUBSTRINGS, 2, capture_str, cap_buffer_len);
785  if (res < 0) {
786  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
787  goto error;
788  }
789  if (strlen(capture_str) == 0 || strlen(type_str) == 0) {
790  goto error;
791  }
792 
793  SCLogDebug("type \'%s\'", type_str);
794  SCLogDebug("capture \'%s\'", capture_str);
795 
796  if (pd->idx >= DETECT_PCRE_CAPTURE_MAX) {
797  SCLogError(SC_ERR_VAR_LIMIT, "rule can have maximally %d pkt/flow "
798  "var captures", DETECT_PCRE_CAPTURE_MAX);
799  return -1;
800  }
801 
802  if (strcmp(type_str, "pkt") == 0) {
803  pd->capids[pd->idx] = VarNameStoreSetupAdd((char *)capture_str, VAR_TYPE_PKT_VAR);
804  pd->captypes[pd->idx] = VAR_TYPE_PKT_VAR;
805  SCLogDebug("id %u type %u", pd->capids[pd->idx], pd->captypes[pd->idx]);
806  pd->idx++;
807  } else if (strcmp(type_str, "flow") == 0) {
808  pd->capids[pd->idx] = VarNameStoreSetupAdd((char *)capture_str, VAR_TYPE_FLOW_VAR);
809  pd->captypes[pd->idx] = VAR_TYPE_FLOW_VAR;
810  pd->idx++;
811  }
812 
813  //SCLogNotice("pd->capname %s", pd->capname);
814  regexstr += ov[1];
815 
816  if (regexstr >= orig_right_edge)
817  break;
818  }
819  return 0;
820 
821 error:
822  return -1;
823 }
824 
825 static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, const char *regexstr)
826 {
827  SCEnter();
828  DetectPcreData *pd = NULL;
829  SigMatch *sm = NULL;
830  int ret = -1;
831  int parsed_sm_list = DETECT_SM_LIST_NOTSET;
832  char capture_names[1024] = "";
833  AppProto alproto = ALPROTO_UNKNOWN;
834 
835  pd = DetectPcreParse(de_ctx, regexstr, &parsed_sm_list,
836  capture_names, sizeof(capture_names), s->init_data->negated,
837  &alproto);
838  if (pd == NULL)
839  goto error;
840  if (DetectPcreParseCapture(regexstr, de_ctx, pd, capture_names) < 0)
841  goto error;
842 
843  int sm_list = -1;
844  if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
845  if (DetectBufferGetActiveList(de_ctx, s) == -1)
846  goto error;
847 
848  s->flags |= SIG_FLAG_APPLAYER;
849  sm_list = s->init_data->list;
850  } else {
851  switch(parsed_sm_list) {
853  sm_list = DETECT_SM_LIST_PMATCH;
854  break;
855  default: {
856  if (alproto != ALPROTO_UNKNOWN) {
857  /* see if the proto doesn't conflict
858  * with what we already have. */
859  if (s->alproto != ALPROTO_UNKNOWN &&
860  alproto != s->alproto) {
861  goto error;
862  }
863  s->alproto = alproto;
864  }
865  sm_list = parsed_sm_list;
866  break;
867  }
868  }
869  }
870  if (sm_list == -1)
871  goto error;
872 
873  sm = SigMatchAlloc();
874  if (sm == NULL)
875  goto error;
876  sm->type = DETECT_PCRE;
877  sm->ctx = (void *)pd;
878  SigMatchAppendSMToList(s, sm, sm_list);
879 
880  uint8_t x;
881  for (x = 0; x < pd->idx; x++) {
882  if (DetectFlowvarPostMatchSetup(s, pd->capids[x]) < 0)
883  goto error_nofree;
884  }
885 
886  if (!(pd->flags & DETECT_PCRE_RELATIVE))
887  goto okay;
888 
889  /* errors below shouldn't free pd */
890 
891  SigMatch *prev_pm = DetectGetLastSMByListPtr(s, sm->prev,
893  if (s->init_data->list == DETECT_SM_LIST_NOTSET && prev_pm == NULL) {
894  SCLogError(SC_ERR_INVALID_SIGNATURE, "pcre with /R (relative) needs "
895  "preceeding match in the same buffer");
896  goto error_nofree;
897  /* null is allowed when we use a sticky buffer */
898  } else if (prev_pm == NULL)
899  goto okay;
900  if (prev_pm->type == DETECT_CONTENT) {
901  DetectContentData *cd = (DetectContentData *)prev_pm->ctx;
903  } else if (prev_pm->type == DETECT_PCRE) {
904  DetectPcreData *tmp = (DetectPcreData *)prev_pm->ctx;
906  }
907 
908  okay:
909  ret = 0;
910  SCReturnInt(ret);
911  error:
912  DetectPcreFree(pd);
913  error_nofree:
914  SCReturnInt(ret);
915 }
916 
917 static void DetectPcreFree(void *ptr)
918 {
919  if (ptr == NULL)
920  return;
921 
922  DetectPcreData *pd = (DetectPcreData *)ptr;
923 
924  if (pd->re != NULL)
925  pcre_free(pd->re);
926  if (pd->sd != NULL)
927  pcre_free_study(pd->sd);
928 
929  SCFree(pd);
930  return;
931 }
932 
933 #ifdef UNITTESTS /* UNITTESTS */
934 static int g_file_data_buffer_id = 0;
935 static int g_http_header_buffer_id = 0;
936 static int g_dce_stub_data_buffer_id = 0;
937 
938 /**
939  * \test DetectPcreParseTest01 make sure we don't allow invalid opts 7.
940  */
941 static int DetectPcreParseTest01 (void)
942 {
943  int result = 1;
944  DetectPcreData *pd = NULL;
945  const char *teststring = "/blah/7";
946  int list = DETECT_SM_LIST_NOTSET;
948  FAIL_IF_NULL(de_ctx);
949  AppProto alproto = ALPROTO_UNKNOWN;
950 
951  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
952  FAIL_IF_NOT_NULL(pd);
953 
954  DetectEngineCtxFree(de_ctx);
955  return result;
956 }
957 
958 /**
959  * \test DetectPcreParseTest02 make sure we don't allow invalid opts Ui$.
960  */
961 static int DetectPcreParseTest02 (void)
962 {
963  int result = 1;
964  DetectPcreData *pd = NULL;
965  const char *teststring = "/blah/Ui$";
966  int list = DETECT_SM_LIST_NOTSET;
968  FAIL_IF_NULL(de_ctx);
969  AppProto alproto = ALPROTO_UNKNOWN;
970 
971  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
972  FAIL_IF_NOT_NULL(pd);
973  FAIL_IF_NOT(alproto == ALPROTO_HTTP);
974 
975  DetectEngineCtxFree(de_ctx);
976  return result;
977 }
978 
979 /**
980  * \test DetectPcreParseTest03 make sure we don't allow invalid opts UZi.
981  */
982 static int DetectPcreParseTest03 (void)
983 {
984  int result = 1;
985  DetectPcreData *pd = NULL;
986  const char *teststring = "/blah/UNi";
987  int list = DETECT_SM_LIST_NOTSET;
989  FAIL_IF_NULL(de_ctx);
990  AppProto alproto = ALPROTO_UNKNOWN;
991 
992  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
993  FAIL_IF_NOT_NULL(pd);
994 
995  DetectEngineCtxFree(de_ctx);
996  return result;
997 }
998 
999 /**
1000  * \test DetectPcreParseTest04 make sure we allow escaped "
1001  */
1002 static int DetectPcreParseTest04 (void)
1003 {
1004  int result = 1;
1005  DetectPcreData *pd = NULL;
1006  const char *teststring = "/b\\\"lah/i";
1007  int list = DETECT_SM_LIST_NOTSET;
1009  FAIL_IF_NULL(de_ctx);
1010  AppProto alproto = ALPROTO_UNKNOWN;
1011 
1012  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1013  FAIL_IF_NULL(pd);
1014  FAIL_IF_NOT(alproto == ALPROTO_UNKNOWN);
1015 
1016  DetectPcreFree(pd);
1017  DetectEngineCtxFree(de_ctx);
1018  return result;
1019 }
1020 
1021 /**
1022  * \test DetectPcreParseTest05 make sure we parse pcre with no opts
1023  */
1024 static int DetectPcreParseTest05 (void)
1025 {
1026  int result = 1;
1027  DetectPcreData *pd = NULL;
1028  const char *teststring = "/b(l|a)h/";
1029  int list = DETECT_SM_LIST_NOTSET;
1031  FAIL_IF_NULL(de_ctx);
1032  AppProto alproto = ALPROTO_UNKNOWN;
1033 
1034  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1035  FAIL_IF_NULL(pd);
1036  FAIL_IF_NOT(alproto == ALPROTO_UNKNOWN);
1037 
1038  DetectPcreFree(pd);
1039  DetectEngineCtxFree(de_ctx);
1040  return result;
1041 }
1042 
1043 /**
1044  * \test DetectPcreParseTest06 make sure we parse pcre with smi opts
1045  */
1046 static int DetectPcreParseTest06 (void)
1047 {
1048  int result = 1;
1049  DetectPcreData *pd = NULL;
1050  const char *teststring = "/b(l|a)h/smi";
1051  int list = DETECT_SM_LIST_NOTSET;
1053  FAIL_IF_NULL(de_ctx);
1054  AppProto alproto = ALPROTO_UNKNOWN;
1055 
1056  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1057  FAIL_IF_NULL(pd);
1058  FAIL_IF_NOT(alproto == ALPROTO_UNKNOWN);
1059 
1060  DetectPcreFree(pd);
1061  DetectEngineCtxFree(de_ctx);
1062  return result;
1063 }
1064 
1065 /**
1066  * \test DetectPcreParseTest07 make sure we parse pcre with /Ui opts
1067  */
1068 static int DetectPcreParseTest07 (void)
1069 {
1070  int result = 1;
1071  DetectPcreData *pd = NULL;
1072  const char *teststring = "/blah/Ui";
1073  int list = DETECT_SM_LIST_NOTSET;
1075  FAIL_IF_NULL(de_ctx);
1076  AppProto alproto = ALPROTO_UNKNOWN;
1077 
1078  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1079  FAIL_IF_NULL(pd);
1080  FAIL_IF_NOT(alproto == ALPROTO_HTTP);
1081 
1082  DetectPcreFree(pd);
1083  DetectEngineCtxFree(de_ctx);
1084  return result;
1085 }
1086 
1087 /**
1088  * \test DetectPcreParseTest08 make sure we parse pcre with O opts
1089  */
1090 static int DetectPcreParseTest08 (void)
1091 {
1092  int result = 1;
1093  DetectPcreData *pd = NULL;
1094  const char *teststring = "/b(l|a)h/O";
1095  int list = DETECT_SM_LIST_NOTSET;
1097  FAIL_IF_NULL(de_ctx);
1098  AppProto alproto = ALPROTO_UNKNOWN;
1099 
1100  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1101  FAIL_IF_NULL(pd);
1102  FAIL_IF_NOT(alproto == ALPROTO_UNKNOWN);
1103 
1104  DetectPcreFree(pd);
1105  DetectEngineCtxFree(de_ctx);
1106  return result;
1107 }
1108 
1109 /**
1110  * \test DetectPcreParseTest09 make sure we parse pcre with a content
1111  * that has slashes
1112  */
1113 static int DetectPcreParseTest09 (void)
1114 {
1115  DetectPcreData *pd = NULL;
1116  const char *teststring = "/lala\\\\/";
1117  int list = DETECT_SM_LIST_NOTSET;
1119  FAIL_IF_NULL(de_ctx);
1120  AppProto alproto = ALPROTO_UNKNOWN;
1121 
1122  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1123  FAIL_IF_NULL(pd);
1124 
1125  DetectPcreFree(pd);
1126  DetectEngineCtxFree(de_ctx);
1127  PASS;
1128 }
1129 
1130 /**
1131  * \test Test pcre option for dce sig(yeah I'm bored of writing test titles).
1132  */
1133 static int DetectPcreParseTest10(void)
1134 {
1135  Signature *s = SigAlloc();
1137  FAIL_IF_NULL(de_ctx);
1138 
1139  s->alproto = ALPROTO_DCERPC;
1140 
1141  FAIL_IF_NOT(DetectPcreSetup(de_ctx, s, "/bamboo/") == 0);
1142  FAIL_IF_NOT(s->sm_lists[g_dce_stub_data_buffer_id] == NULL && s->sm_lists[DETECT_SM_LIST_PMATCH] != NULL);
1143 
1144  SigFree(s);
1145 
1146  s = SigAlloc();
1147  FAIL_IF_NULL(s);
1148 
1149  /* failure since we have no preceding content/pcre/bytejump */
1150  FAIL_IF_NOT(DetectPcreSetup(de_ctx, s, "/bamboo/") == 0);
1151  FAIL_IF_NOT(s->sm_lists[g_dce_stub_data_buffer_id] == NULL && s->sm_lists[DETECT_SM_LIST_PMATCH] != NULL);
1152 
1153  SigFree(s);
1154  DetectEngineCtxFree(de_ctx);
1155 
1156  PASS;
1157 }
1158 
1159 /**
1160  * \test Test pcre option for dce sig.
1161  */
1162 static int DetectPcreParseTest11(void)
1163 {
1164  DetectEngineCtx *de_ctx = NULL;
1165  Signature *s = NULL;
1166  DetectPcreData *data = NULL;
1167 
1168  de_ctx = DetectEngineCtxInit();
1169  FAIL_IF_NULL(de_ctx);
1170 
1171  de_ctx->flags |= DE_QUIET;
1172  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
1173  "(msg:\"Testing bytejump_body\"; "
1174  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1175  "dce_stub_data; "
1176  "pcre:/bamboo/R; sid:1;)");
1177  FAIL_IF(de_ctx == NULL);
1178  s = de_ctx->sig_list;
1179  FAIL_IF(s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL);
1180  FAIL_IF_NOT(s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_PCRE);
1181  data = (DetectPcreData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1183  !(data->flags & DETECT_PCRE_RELATIVE));
1184 
1185  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1186  "(msg:\"Testing bytejump_body\"; "
1187  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1188  "dce_stub_data; "
1189  "pcre:/bamboo/R; sid:1;)");
1190  FAIL_IF_NULL(s->next);
1191  s = s->next;
1192  FAIL_IF(s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL);
1193  FAIL_IF_NOT(s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_PCRE);
1194  data = (DetectPcreData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1196  !(data->flags & DETECT_PCRE_RELATIVE));
1197 
1198  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1199  "(msg:\"Testing bytejump_body\"; "
1200  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1201  "dce_stub_data; "
1202  "pcre:/bamboo/RB; sid:1;)");
1203  FAIL_IF(s->next == NULL);
1204  s = s->next;
1205  FAIL_IF(s->sm_lists_tail[g_dce_stub_data_buffer_id] == NULL);
1206  FAIL_IF_NOT(s->sm_lists_tail[g_dce_stub_data_buffer_id]->type == DETECT_PCRE);
1207  data = (DetectPcreData *)s->sm_lists_tail[g_dce_stub_data_buffer_id]->ctx;
1208  FAIL_IF(!(data->flags & DETECT_PCRE_RAWBYTES) ||
1209  !(data->flags & DETECT_PCRE_RELATIVE));
1210 
1211  s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1212  "(msg:\"Testing bytejump_body\"; "
1213  "content:\"one\"; pcre:/bamboo/; sid:1;)");
1214  FAIL_IF(s->next == NULL);
1215  s = s->next;
1216  FAIL_IF(s->sm_lists_tail[g_dce_stub_data_buffer_id] != NULL);
1217 
1218  SigGroupCleanup(de_ctx);
1219  SigCleanSignatures(de_ctx);
1220  DetectEngineCtxFree(de_ctx);
1221 
1222  PASS;
1223 }
1224 
1225 /**
1226  * \test Test pcre option with file data. pcre is relative to file_data,
1227  * so relative flag should be unset.
1228  */
1229 static int DetectPcreParseTest12(void)
1230 {
1231  DetectEngineCtx *de_ctx = NULL;
1232  Signature *s = NULL;
1233  DetectPcreData *data = NULL;
1234 
1235  de_ctx = DetectEngineCtxInit();
1236  FAIL_IF_NULL(de_ctx);
1237 
1238  de_ctx->flags |= DE_QUIET;
1239  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
1240  "(file_data; pcre:/abc/R; sid:1;)");
1241  FAIL_IF (de_ctx->sig_list == NULL);
1242 
1243  s = de_ctx->sig_list;
1244  FAIL_IF(s->sm_lists_tail[g_file_data_buffer_id] == NULL);
1245 
1246  FAIL_IF(s->sm_lists_tail[g_file_data_buffer_id]->type != DETECT_PCRE);
1247 
1248  data = (DetectPcreData *)s->sm_lists_tail[g_file_data_buffer_id]->ctx;
1250  !(data->flags & DETECT_PCRE_RELATIVE));
1251 
1252  SigGroupCleanup(de_ctx);
1253  SigCleanSignatures(de_ctx);
1254  DetectEngineCtxFree(de_ctx);
1255 
1256  PASS;
1257 }
1258 
1259 /**
1260  * \test Test pcre option with file data.
1261  */
1262 static int DetectPcreParseTest13(void)
1263 {
1264  DetectEngineCtx *de_ctx = NULL;
1265  Signature *s = NULL;
1266  DetectPcreData *data = NULL;
1267 
1268  de_ctx = DetectEngineCtxInit();
1269  FAIL_IF_NULL(de_ctx);
1270 
1271  de_ctx->flags |= DE_QUIET;
1272  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
1273  "(file_data; content:\"abc\"; pcre:/def/R; sid:1;)");
1274  FAIL_IF(de_ctx->sig_list == NULL);
1275 
1276  s = de_ctx->sig_list;
1277  FAIL_IF(s->sm_lists_tail[g_file_data_buffer_id] == NULL);
1278 
1279  FAIL_IF(s->sm_lists_tail[g_file_data_buffer_id]->type != DETECT_PCRE);
1280 
1281  data = (DetectPcreData *)s->sm_lists_tail[g_file_data_buffer_id]->ctx;
1283  !(data->flags & DETECT_PCRE_RELATIVE));
1284 
1285  SigGroupCleanup(de_ctx);
1286  SigCleanSignatures(de_ctx);
1287  DetectEngineCtxFree(de_ctx);
1288 
1289  PASS;
1290 }
1291 
1292 /**
1293  * \test Test pcre option with file data.
1294  */
1295 static int DetectPcreParseTest14(void)
1296 {
1297  DetectEngineCtx *de_ctx = NULL;
1298  Signature *s = NULL;
1299  DetectPcreData *data = NULL;
1300 
1301  de_ctx = DetectEngineCtxInit();
1302  FAIL_IF(de_ctx == NULL);
1303 
1304  de_ctx->flags |= DE_QUIET;
1305  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
1306  "(file_data; pcre:/def/; sid:1;)");
1307  FAIL_IF(de_ctx->sig_list == NULL);
1308 
1309  s = de_ctx->sig_list;
1310  FAIL_IF(s->sm_lists_tail[g_file_data_buffer_id] == NULL);
1311 
1312  FAIL_IF(s->sm_lists_tail[g_file_data_buffer_id]->type != DETECT_PCRE);
1313 
1314  data = (DetectPcreData *)s->sm_lists_tail[g_file_data_buffer_id]->ctx;
1316  data->flags & DETECT_PCRE_RELATIVE);
1317 
1318  SigGroupCleanup(de_ctx);
1319  SigCleanSignatures(de_ctx);
1320  DetectEngineCtxFree(de_ctx);
1321 
1322  PASS;
1323 }
1324 
1325 /** \test Check a signature with pcre relative method */
1326 static int DetectPcreParseTest15(void)
1327 {
1328  DetectEngineCtx *de_ctx = NULL;
1329 
1330  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1331 
1332  de_ctx->flags |= DE_QUIET;
1333  de_ctx->sig_list = SigInit(de_ctx,
1334  "alert tcp any any -> any any "
1335  "(msg:\"Testing pcre relative http_method\"; "
1336  "content:\"GET\"; "
1337  "http_method; pcre:\"/abc/RM\"; sid:1;)");
1338  FAIL_IF_NULL(de_ctx->sig_list);
1339 
1340  if (de_ctx != NULL)
1341  SigCleanSignatures(de_ctx);
1342  if (de_ctx != NULL)
1343  DetectEngineCtxFree(de_ctx);
1344  PASS;
1345 }
1346 
1347 
1348 /** \test Check a signature with pcre relative cookie */
1349 static int DetectPcreParseTest16(void)
1350 {
1351  DetectEngineCtx *de_ctx = NULL;
1352 
1353  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1354 
1355  de_ctx->flags |= DE_QUIET;
1356  de_ctx->sig_list = SigInit(de_ctx,
1357  "alert tcp any any -> any any "
1358  "(msg:\"Testing pcre relative http_cookie\"; "
1359  "content:\"test\"; "
1360  "http_cookie; pcre:\"/abc/RC\"; sid:1;)");
1361  FAIL_IF_NULL(de_ctx->sig_list);
1362 
1363  if (de_ctx != NULL)
1364  SigCleanSignatures(de_ctx);
1365  if (de_ctx != NULL)
1366  DetectEngineCtxFree(de_ctx);
1367  PASS;
1368 }
1369 
1370 /** \test Check a signature with pcre relative raw header */
1371 static int DetectPcreParseTest17(void)
1372 {
1373  DetectEngineCtx *de_ctx = NULL;
1374 
1375  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1376 
1377  de_ctx->flags |= DE_QUIET;
1378  de_ctx->sig_list = SigInit(de_ctx,
1379  "alert tcp any any -> any any "
1380  "(msg:\"Testing pcre relative http_raw_header\"; "
1381  "flow:to_server; content:\"test\"; "
1382  "http_raw_header; pcre:\"/abc/RD\"; sid:1;)");
1383  FAIL_IF_NULL(de_ctx->sig_list);
1384 
1385  if (de_ctx != NULL)
1386  SigCleanSignatures(de_ctx);
1387  if (de_ctx != NULL)
1388  DetectEngineCtxFree(de_ctx);
1389  PASS;
1390 }
1391 
1392 /** \test Check a signature with pcre relative header */
1393 static int DetectPcreParseTest18(void)
1394 {
1395  DetectEngineCtx *de_ctx = NULL;
1396 
1397  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1398 
1399  de_ctx->flags |= DE_QUIET;
1400  de_ctx->sig_list = SigInit(de_ctx,
1401  "alert tcp any any -> any any "
1402  "(msg:\"Testing pcre relative http_header\"; "
1403  "content:\"test\"; "
1404  "http_header; pcre:\"/abc/RH\"; sid:1;)");
1405  FAIL_IF_NULL(de_ctx->sig_list);
1406 
1407  if (de_ctx != NULL)
1408  SigCleanSignatures(de_ctx);
1409  if (de_ctx != NULL)
1410  DetectEngineCtxFree(de_ctx);
1411  PASS;
1412 }
1413 
1414 /** \test Check a signature with pcre relative client-body */
1415 static int DetectPcreParseTest19(void)
1416 {
1417  DetectEngineCtx *de_ctx = NULL;
1418 
1419  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1420 
1421  de_ctx->flags |= DE_QUIET;
1422  de_ctx->sig_list = SigInit(de_ctx,
1423  "alert tcp any any -> any any "
1424  "(msg:\"Testing pcre relativie http_client_body\"; "
1425  "content:\"test\"; "
1426  "http_client_body; pcre:\"/abc/RP\"; sid:1;)");
1427  FAIL_IF_NULL(de_ctx->sig_list);
1428 
1429  if (de_ctx != NULL)
1430  SigCleanSignatures(de_ctx);
1431  if (de_ctx != NULL)
1432  DetectEngineCtxFree(de_ctx);
1433  PASS;
1434 }
1435 
1436 /** \test Check a signature with pcre relative raw uri */
1437 static int DetectPcreParseTest20(void)
1438 {
1439  DetectEngineCtx *de_ctx = NULL;
1440 
1441  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1442 
1443  de_ctx->flags |= DE_QUIET;
1444  de_ctx->sig_list = SigInit(de_ctx,
1445  "alert tcp any any -> any any "
1446  "(msg:\"Testing http_raw_uri\"; "
1447  "content:\"test\"; "
1448  "http_raw_uri; pcre:\"/abc/RI\"; sid:1;)");
1449  FAIL_IF_NULL(de_ctx->sig_list);
1450 
1451  if (de_ctx != NULL)
1452  SigCleanSignatures(de_ctx);
1453  if (de_ctx != NULL)
1454  DetectEngineCtxFree(de_ctx);
1455  PASS;
1456 }
1457 
1458 /** \test Check a signature with pcre relative uricontent */
1459 static int DetectPcreParseTest21(void)
1460 {
1461  DetectEngineCtx *de_ctx = NULL;
1462 
1463  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1464 
1465  de_ctx->flags |= DE_QUIET;
1466  de_ctx->sig_list = SigInit(de_ctx,
1467  "alert tcp any any -> any any "
1468  "(msg:\"Testing pcre relative uricontent\"; "
1469  "uricontent:\"test\"; "
1470  "pcre:\"/abc/RU\"; sid:1;)");
1471  FAIL_IF_NULL(de_ctx->sig_list);
1472 
1473  if (de_ctx != NULL)
1474  SigCleanSignatures(de_ctx);
1475  if (de_ctx != NULL)
1476  DetectEngineCtxFree(de_ctx);
1477  PASS;
1478 }
1479 
1480 /** \test Check a signature with pcre relative http_uri */
1481 static int DetectPcreParseTest22(void)
1482 {
1483  DetectEngineCtx *de_ctx = NULL;
1484 
1485  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1486 
1487  de_ctx->flags |= DE_QUIET;
1488  de_ctx->sig_list = SigInit(de_ctx,
1489  "alert tcp any any -> any any "
1490  "(msg:\"Testing pcre relative http_uri\"; "
1491  "content:\"test\"; "
1492  "http_uri; pcre:\"/abc/RU\"; sid:1;)");
1493  FAIL_IF_NULL(de_ctx->sig_list);
1494 
1495  if (de_ctx != NULL)
1496  SigCleanSignatures(de_ctx);
1497  if (de_ctx != NULL)
1498  DetectEngineCtxFree(de_ctx);
1499  PASS;
1500 }
1501 
1502 /** \test Check a signature with inconsistent pcre relative */
1503 static int DetectPcreParseTest23(void)
1504 {
1505  DetectEngineCtx *de_ctx = NULL;
1506 
1507  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1508 
1509  de_ctx->flags |= DE_QUIET;
1510  de_ctx->sig_list = SigInit(de_ctx,
1511  "alert tcp any any -> any any "
1512  "(msg:\"Testing inconsistent pcre relative\"; "
1513  "content:\"GET\"; "
1514  "http_cookie; pcre:\"/abc/RM\"; sid:1;)");
1515  FAIL_IF_NOT_NULL(de_ctx->sig_list);
1516 
1517  if (de_ctx != NULL)
1518  SigCleanSignatures(de_ctx);
1519  if (de_ctx != NULL)
1520  DetectEngineCtxFree(de_ctx);
1521  PASS;
1522 }
1523 
1524 /** \test Check a signature with inconsistent pcre modifiers */
1525 static int DetectPcreParseTest24(void)
1526 {
1527  DetectEngineCtx *de_ctx = NULL;
1528 
1529  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1530 
1531  de_ctx->flags |= DE_QUIET;
1532  de_ctx->sig_list = SigInit(de_ctx,
1533  "alert tcp any any -> any any "
1534  "(msg:\"Testing inconsistent pcre modifiers\"; "
1535  "pcre:\"/abc/UI\"; sid:1;)");
1536  FAIL_IF_NOT_NULL(de_ctx->sig_list);
1537 
1538  if (de_ctx != NULL)
1539  SigCleanSignatures(de_ctx);
1540  if (de_ctx != NULL)
1541  DetectEngineCtxFree(de_ctx);
1542  PASS;
1543 }
1544 
1545 /** \test Check a signature with inconsistent pcre modifiers */
1546 static int DetectPcreParseTest25(void)
1547 {
1548  DetectEngineCtx *de_ctx = NULL;
1549 
1550  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1551 
1552  de_ctx->flags |= DE_QUIET;
1553  de_ctx->sig_list = SigInit(de_ctx,
1554  "alert tcp any any -> any any "
1555  "(msg:\"Testing inconsistent pcre modifiers\"; "
1556  "pcre:\"/abc/DH\"; sid:1;)");
1557  FAIL_IF_NOT_NULL(de_ctx->sig_list);
1558 
1559  if (de_ctx != NULL)
1560  SigCleanSignatures(de_ctx);
1561  if (de_ctx != NULL)
1562  DetectEngineCtxFree(de_ctx);
1563  PASS;
1564 }
1565 
1566 /** \test Check a signature with inconsistent pcre modifiers */
1567 static int DetectPcreParseTest26(void)
1568 {
1569  DetectEngineCtx *de_ctx = NULL;
1570 
1571  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1572 
1573  de_ctx->flags |= DE_QUIET;
1574  de_ctx->sig_list = SigInit(de_ctx,
1575  "alert http any any -> any any "
1576  "(msg:\"Testing inconsistent pcre modifiers\"; "
1577  "pcre:\"/abc/F\"; sid:1;)");
1578  FAIL_IF_NOT_NULL(de_ctx->sig_list);
1579 
1580  if (de_ctx != NULL)
1581  SigCleanSignatures(de_ctx);
1582  if (de_ctx != NULL)
1583  DetectEngineCtxFree(de_ctx);
1584  PASS;
1585 }
1586 
1587 /** \test Bug 1098 */
1588 static int DetectPcreParseTest27(void)
1589 {
1590  DetectEngineCtx *de_ctx = NULL;
1591 
1592  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1593 
1594  de_ctx->flags |= DE_QUIET;
1595  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any 80 "
1596  "(content:\"baduricontent\"; http_raw_uri; "
1597  "pcre:\"/^[a-z]{5}\\.html/R\"; sid:2; rev:2;)");
1598  FAIL_IF_NOT(de_ctx->sig_list == NULL);
1599 
1600  if (de_ctx != NULL)
1601  SigCleanSignatures(de_ctx);
1602  if (de_ctx != NULL)
1603  DetectEngineCtxFree(de_ctx);
1604  PASS;
1605 }
1606 
1607 /** \test Bug 1957 */
1608 static int DetectPcreParseTest28(void)
1609 {
1610  DetectEngineCtx *de_ctx = NULL;
1611 
1612  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1613 
1614  de_ctx->flags |= DE_QUIET;
1615  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any 80 "
1616  "(content:\"|2E|suricata\"; http_host; pcre:\"/\\x2Esuricata$/W\"; "
1617  "sid:2; rev:2;)");
1618  FAIL_IF_NULL(de_ctx->sig_list);
1619 
1620  DetectEngineCtxFree(de_ctx);
1621  PASS;
1622 }
1623 
1624 static int DetectPcreTestSig01(void)
1625 {
1626  uint8_t *buf = (uint8_t *)
1627  "GET /one/ HTTP/1.1\r\n"
1628  "Host: one.example.org\r\n"
1629  "\r\n\r\n"
1630  "GET /two/ HTTP/1.1\r\n"
1631  "Host: two.example.org\r\n"
1632  "\r\n\r\n";
1633  uint16_t buflen = strlen((char *)buf);
1634  Packet *p = NULL;
1635  ThreadVars th_v;
1636  DetectEngineThreadCtx *det_ctx = NULL;
1638 
1639  memset(&th_v, 0, sizeof(th_v));
1640 
1642 
1643  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1644  FAIL_IF_NULL(p);
1645  p->tcph->th_seq = htonl(1000);
1646  Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1", 41424, 80);
1647  FAIL_IF_NULL(f);
1648  f->proto = IPPROTO_TCP;
1649  UTHAddSessionToFlow(f, 1000, 1000);
1650  UTHAddStreamToFlow(f, 0, buf, buflen);
1651 
1652  p->flow = f;
1656  f->alproto = ALPROTO_HTTP;
1657 
1659  FAIL_IF(de_ctx == NULL);
1660 
1661  de_ctx->flags |= DE_QUIET;
1662 
1663  de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; pcre:\"/^gEt/i\"; pcre:\"/\\/two\\//U\"; pcre:\"/GET \\/two\\//\"; pcre:\"/\\s+HTTP/R\"; sid:1;)");
1664  FAIL_IF(de_ctx->sig_list == NULL);
1665 
1666  SigGroupBuild(de_ctx);
1667  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1668 
1669  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1670  STREAM_TOSERVER | STREAM_START, buf, buflen);
1671  FAIL_IF(r != 0);
1672 
1673  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1674  FAIL_IF_NOT(PacketAlertCheck(p, 1) == 1);
1675 
1676  AppLayerParserThreadCtxFree(alp_tctx);
1677  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1678  DetectEngineCtxFree(de_ctx);
1679 
1681  UTHFreeFlow(f);
1682 
1684  UTHFreePackets(&p, 1);
1685  PASS;
1686 }
1687 
1688 static int DetectPcreTestSig02(void)
1689 {
1690  uint8_t *buf = (uint8_t *)
1691  "GET /one/ HTTP/1.1\r\n"
1692  "Host: one.example.org\r\n"
1693  "\r\n\r\n"
1694  "GET /two/ HTTP/1.1\r\n"
1695  "Host: two.example.org\r\n"
1696  "\r\n\r\n";
1697  uint16_t buflen = strlen((char *)buf);
1698  Packet *p = NULL;
1699  Flow f;
1700  ThreadVars th_v;
1701  DetectEngineThreadCtx *det_ctx;
1702 
1703  memset(&th_v, 0, sizeof(th_v));
1704  memset(&f, 0, sizeof(f));
1705 
1706  FLOW_INITIALIZE(&f);
1707 
1708  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1709  p->flow = &f;
1711 
1712  pcre_match_limit = 100;
1713  pcre_match_limit_recursion = 100;
1714 
1716  FAIL_IF(de_ctx == NULL);
1717 
1718  de_ctx->flags |= DE_QUIET;
1719 
1720  de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; pcre:\"/two/O\"; sid:2;)");
1721  FAIL_IF(de_ctx->sig_list == NULL);
1722 
1723  SigGroupBuild(de_ctx);
1724  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1725 
1726  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1727  FAIL_IF_NOT(PacketAlertCheck(p, 2) == 1);
1728 
1729  SigGroupCleanup(de_ctx);
1730  SigCleanSignatures(de_ctx);
1731 
1732  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1733  DetectEngineCtxFree(de_ctx);
1734  FLOW_DESTROY(&f);
1735 
1736  UTHFreePackets(&p, 1);
1737  PASS;
1738 }
1739 
1740 /**
1741  * \test DetectPcreTestSig03Real negation test ! outside of "" this sig should not match
1742  */
1743 static int DetectPcreTestSig03(void)
1744 {
1745  uint8_t *buf = (uint8_t *)
1746  "GET /one/ HTTP/1.1\r\n"
1747  "Host: one.example.org\r\n"
1748  "\r\n\r\n"
1749  "GET /two/ HTTP/1.1\r\n"
1750  "Host: two.example.org\r\n"
1751  "\r\n\r\n";
1752  uint16_t buflen = strlen((char *)buf);
1753  Packet *p = NULL;
1754  ThreadVars th_v;
1755  DetectEngineThreadCtx *det_ctx;
1756 
1757  memset(&th_v, 0, sizeof(th_v));
1758 
1759  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1760 
1762  FAIL_IF(de_ctx == NULL);
1763 
1764  de_ctx->flags |= DE_QUIET;
1765 
1766  de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"GET\"; pcre:!\"/two/\"; sid:1;)");
1767  FAIL_IF(de_ctx->sig_list == NULL);
1768 
1769  SigGroupBuild(de_ctx);
1770  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1771 
1772  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1773  FAIL_IF(PacketAlertCheck(p, 1));
1774  SigGroupCleanup(de_ctx);
1775  SigCleanSignatures(de_ctx);
1776 
1777  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1778  DetectEngineCtxFree(de_ctx);
1779 
1780  UTHFreePackets(&p, 1);
1781  PASS;
1782 }
1783 
1784 /**
1785  * \test Check the signature with pcre modifier P (match with L7 to http body data)
1786  */
1787 static int DetectPcreModifPTest04(void)
1788 {
1789  uint8_t httpbuf1[] =
1790  "GET / HTTP/1.1\r\n"
1791  "Host: www.emergingthreats.net\r\n"
1792  "User-Agent: Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.0.13) Gecko/2009080315 Ubuntu/8.10 (intrepid) Firefox/3.0.13\r\n"
1793  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8\r\n"
1794  "Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
1795  "Accept-Encoding: gzip,deflate\r\n"
1796  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
1797  "Date: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
1798  "Server: Apache\r\n"
1799  "X-Powered-By: PHP/5.2.5\r\n"
1800  "P3P: CP=\"NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM\"\r\n"
1801  "Expires: Mon, 1 Jan 2001 00:00:00 GMT\r\n"
1802  "Last-Modified: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
1803  "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n"
1804  "Pragma: no-cache\r\n"
1805  "Keep-Alive: timeout=15, max=100\r\n"
1806  "Connection: Keep-Alive\r\n"
1807  "Transfer-Encoding: chunked\r\n"
1808  "Content-Type: text/html; charset=utf-8\r\n"
1809  "\r\n"
1810  "15"
1811  "\r\n"
1812  "<!DOCTYPE html PUBLIC\r\n"
1813  "0\r\n\r\n";
1814 
1815  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1816  TcpSession ssn;
1817  Packet *p = NULL;
1818  Flow f;
1819  Signature *s = NULL;
1820  ThreadVars th_v;
1821  DetectEngineThreadCtx *det_ctx;
1823 
1824  memset(&th_v, 0, sizeof(th_v));
1825  memset(&f, 0, sizeof(f));
1826  memset(&ssn, 0, sizeof(ssn));
1827 
1828  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1829 
1830  FLOW_INITIALIZE(&f);
1831  f.protoctx = (void *)&ssn;
1832  f.proto = IPPROTO_TCP;
1833  f.flags |= FLOW_IPV4;
1834 
1835  p->flow = &f;
1839  f.alproto = ALPROTO_HTTP;
1840 
1842 
1844  FAIL_IF(de_ctx == NULL);
1845 
1846  de_ctx->flags |= DE_QUIET;
1847 
1848  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
1849  "\"Pcre modifier P\"; pcre:\"/DOCTYPE/P\"; "
1850  "sid:1;)");
1851  FAIL_IF(s == NULL);
1852 
1853  s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\""
1854  "Pcre modifier P (no match)\"; pcre:\"/blah/P\"; sid:2;)");
1855  FAIL_IF(s->next == NULL);
1856 
1857  SigGroupBuild(de_ctx);
1858  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1859 
1860  FLOWLOCK_WRLOCK(&f);
1861  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1862  STREAM_TOSERVER, httpbuf1, httplen1);
1863  FAIL_IF(r != 0);
1864  FLOWLOCK_UNLOCK(&f);
1865 
1866  HtpState *http_state = f.alstate;
1867  FAIL_IF(http_state == NULL);
1868 
1869  /* do detect */
1870  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1871 
1872  FAIL_IF(!(PacketAlertCheck(p, 1)));
1873  FAIL_IF(PacketAlertCheck(p, 2));
1874 
1875  if (alp_tctx != NULL)
1876  AppLayerParserThreadCtxFree(alp_tctx);
1877  if (de_ctx != NULL) SigGroupCleanup(de_ctx);
1878  if (de_ctx != NULL) SigCleanSignatures(de_ctx);
1879  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
1880 
1882  FLOW_DESTROY(&f);
1883  UTHFreePackets(&p, 1);
1884  PASS;
1885 }
1886 
1887 /**
1888  * \test Check the signature with pcre modifier P (match with L7 to http body data)
1889  * over fragmented chunks (DOCTYPE fragmented)
1890  */
1891 static int DetectPcreModifPTest05(void)
1892 {
1893  uint8_t httpbuf1[] =
1894  "GET / HTTP/1.1\r\n"
1895  "Host: www.emergingthreats.net\r\n"
1896  "User-Agent: Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.0.13) Gecko/2009080315 Ubuntu/8.10 (intrepid) Firefox/3.0.13\r\n"
1897  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8\r\n"
1898  "Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
1899  "Accept-Encoding: gzip,deflate\r\n"
1900  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
1901  "Date: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
1902  "Server: Apache\r\n"
1903  "X-Powered-By: PHP/5.2.5\r\n"
1904  "P3P: CP=\"NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM\"\r\n"
1905  "Expires: Mon, 1 Jan 2001 00:00:00 GMT\r\n"
1906  "Last-Modified: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
1907  "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n"
1908  "Pragma: no-cache\r\n"
1909  "Keep-Alive: timeout=15, max=100\r\n"
1910  "Connection: Keep-Alive\r\n"
1911  "Transfer-Encoding: chunked\r\n"
1912  "Content-Type: text/html; charset=utf-8\r\n"
1913  "\r\n"
1914  "15"
1915  "\r\n"
1916  "<!DOC";
1917 
1918  uint8_t httpbuf2[] = "<!DOCTYPE html PUBLIC\r\n0\r\n\r\n";
1919 
1920  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1921  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1922  TcpSession ssn;
1923  Packet *p1 = NULL;
1924  Packet *p2 = NULL;
1925  Flow f;
1926  Signature *s = NULL;
1927  ThreadVars th_v;
1928  DetectEngineThreadCtx *det_ctx;
1930 
1931  memset(&th_v, 0, sizeof(th_v));
1932  memset(&f, 0, sizeof(f));
1933  memset(&ssn, 0, sizeof(ssn));
1934 
1935  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1936  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1937 
1938  FLOW_INITIALIZE(&f);
1939  f.protoctx = (void *)&ssn;
1940  f.proto = IPPROTO_TCP;
1941  f.flags |= FLOW_IPV4;
1942 
1943  p1->flow = &f;
1947  p2->flow = &f;
1951  f.alproto = ALPROTO_HTTP;
1952 
1954 
1956  FAIL_IF(de_ctx == NULL);
1957 
1958  de_ctx->flags |= DE_QUIET;
1959 
1960  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
1961  "\"Pcre modifier P\"; pcre:\"/DOC/P\"; "
1962  "sid:1;)");
1963  FAIL_IF(s == NULL);
1964 
1965  s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\""
1966  "Pcre modifier P (no match)\"; pcre:\"/DOCTYPE/P\"; sid:2;)");
1967  FAIL_IF(s->next == NULL);
1968 
1969  SigGroupBuild(de_ctx);
1970  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1971 
1972  FLOWLOCK_WRLOCK(&f);
1973  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1974  STREAM_TOSERVER, httpbuf1, httplen1);
1975  FAIL_IF(r != 0);
1976  FLOWLOCK_UNLOCK(&f);
1977 
1978  /* do detect for p1 */
1979  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1980 
1981  HtpState *http_state = f.alstate;
1982  FAIL_IF(http_state == NULL);
1983 
1984  FAIL_IF(PacketAlertCheck(p1, 1));
1985 
1986  FAIL_IF(PacketAlertCheck(p1, 2));
1987 
1988  FLOWLOCK_WRLOCK(&f);
1989  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1990  STREAM_TOSERVER, httpbuf2, httplen2);
1991  FAIL_IF(r != 0);
1992  FLOWLOCK_UNLOCK(&f);
1993 
1994  /* do detect for p2 */
1995  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1996 
1997  FAIL_IF(!(PacketAlertCheck(p2, 1)));
1998 
1999  FAIL_IF(!(PacketAlertCheck(p2, 2)));
2000 
2001  if (alp_tctx != NULL)
2002  AppLayerParserThreadCtxFree(alp_tctx);
2003  if (de_ctx != NULL) SigGroupCleanup(de_ctx);
2004  if (de_ctx != NULL) SigCleanSignatures(de_ctx);
2005  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2006 
2008  FLOW_DESTROY(&f);
2009  UTHFreePackets(&p1, 1);
2010  UTHFreePackets(&p2, 1);
2011  PASS;
2012 }
2013 
2014 static int DetectPcreTestSig06(void)
2015 {
2016  uint8_t *buf = (uint8_t *)
2017  "lalala lalala\\ lala\n";
2018  uint16_t buflen = strlen((char *)buf);
2019  Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
2020  int result = 0;
2021 
2022  char sig[] = "alert tcp any any -> any any (msg:\"pcre with an ending slash\"; pcre:\"/ lalala\\\\/\"; sid:1;)";
2023  if (UTHPacketMatchSig(p, sig) == 0) {
2024  result = 0;
2025  goto end;
2026  }
2027  result = 1;
2028 end:
2029  if (p != NULL)
2030  UTHFreePacket(p);
2031  return result;
2032 }
2033 
2034 /** \test anchored pcre */
2035 static int DetectPcreTestSig07(void)
2036 {
2037  uint8_t *buf = (uint8_t *)
2038  "lalala\n";
2039  uint16_t buflen = strlen((char *)buf);
2040  Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
2041 
2042  char sig[] = "alert tcp any any -> any any (msg:\"pcre with an ending slash\"; pcre:\"/^(la)+$/\"; sid:1;)";
2043  FAIL_IF(UTHPacketMatchSig(p, sig) == 0);
2044 
2045  if (p != NULL)
2046  UTHFreePacket(p);
2047  PASS;
2048 }
2049 
2050 /** \test anchored pcre */
2051 static int DetectPcreTestSig08(void)
2052 {
2053  /* test it also without ending in a newline "\n" */
2054  uint8_t *buf = (uint8_t *)
2055  "lalala";
2056  uint16_t buflen = strlen((char *)buf);
2057  Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
2058 
2059  char sig[] = "alert tcp any any -> any any (msg:\"pcre with an ending slash\"; pcre:\"/^(la)+$/\"; sid:1;)";
2060  FAIL_IF(UTHPacketMatchSig(p, sig) == 0);
2061 
2062  if (p != NULL)
2063  UTHFreePacket(p);
2064  PASS;
2065 }
2066 
2067 /** \test Check the signature working to alert when cookie modifier is
2068  * passed to pcre
2069  */
2070 static int DetectPcreTestSig09(void)
2071 {
2072  Flow f;
2073  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2074  "Cookie: dummy\r\n\r\n";
2075  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2076  TcpSession ssn;
2077  Packet *p = NULL;
2078  Signature *s = NULL;
2079  ThreadVars th_v;
2080  DetectEngineThreadCtx *det_ctx = NULL;
2081  HtpState *http_state = NULL;
2083 
2084  memset(&th_v, 0, sizeof(th_v));
2085  memset(&p, 0, sizeof(p));
2086  memset(&f, 0, sizeof(f));
2087  memset(&ssn, 0, sizeof(ssn));
2088 
2089  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2090 
2091  FLOW_INITIALIZE(&f);
2092  f.protoctx = (void *)&ssn;
2093  f.proto = IPPROTO_TCP;
2094  f.flags |= FLOW_IPV4;
2095 
2096  p->flow = &f;
2100  f.alproto = ALPROTO_HTTP;
2101 
2103 
2105  FAIL_IF(de_ctx == NULL);
2106 
2107  de_ctx->flags |= DE_QUIET;
2108 
2109  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2110  "\"HTTP cookie\"; pcre:\"/dummy/C\"; "
2111  " sid:1;)");
2112  FAIL_IF(s == NULL);
2113 
2114  SigGroupBuild(de_ctx);
2115  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2116 
2117  FLOWLOCK_WRLOCK(&f);
2118  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2119  STREAM_TOSERVER, httpbuf1, httplen1);
2120  FAIL_IF(r != 0);
2121  FLOWLOCK_UNLOCK(&f);
2122 
2123  http_state = f.alstate;
2124  FAIL_IF(http_state == NULL);
2125 
2126  /* do detect */
2127  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2128 
2129  FAIL_IF(!PacketAlertCheck(p, 1));
2130 
2131  if (alp_tctx != NULL)
2132  AppLayerParserThreadCtxFree(alp_tctx);
2133  if (det_ctx != NULL) {
2134  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2135  }
2136  if (de_ctx != NULL) {
2137  SigGroupCleanup(de_ctx);
2138  DetectEngineCtxFree(de_ctx);
2139  }
2140 
2142  UTHFreePackets(&p, 1);
2143  PASS;
2144 }
2145 
2146 /** \test Check the signature working to alert when cookie modifier is
2147  * passed to a negated pcre
2148  */
2149 static int DetectPcreTestSig10(void)
2150 {
2151  Flow f;
2152  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2153  "Cookie: dummoOOooooO\r\n\r\n";
2154  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2155  TcpSession ssn;
2156  Packet *p = NULL;
2157  Signature *s = NULL;
2158  ThreadVars th_v;
2159  DetectEngineThreadCtx *det_ctx = NULL;
2160  HtpState *http_state = NULL;
2162 
2163  memset(&th_v, 0, sizeof(th_v));
2164  memset(&p, 0, sizeof(p));
2165  memset(&f, 0, sizeof(f));
2166  memset(&ssn, 0, sizeof(ssn));
2167 
2168  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2169 
2170  FLOW_INITIALIZE(&f);
2171  f.protoctx = (void *)&ssn;
2172  f.proto = IPPROTO_TCP;
2173  f.flags |= FLOW_IPV4;
2174 
2175  p->flow = &f;
2179  f.alproto = ALPROTO_HTTP;
2180 
2182 
2184  FAIL_IF(de_ctx == NULL);
2185 
2186  de_ctx->flags |= DE_QUIET;
2187 
2188  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2189  "\"HTTP cookie\"; pcre:!\"/dummy/C\"; "
2190  " sid:1;)");
2191  FAIL_IF(s == NULL);
2192 
2193  SigGroupBuild(de_ctx);
2194  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2195 
2196  FLOWLOCK_WRLOCK(&f);
2197  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2198  STREAM_TOSERVER, httpbuf1, httplen1);
2199  FAIL_IF(r != 0);
2200  FLOWLOCK_UNLOCK(&f);
2201 
2202  http_state = f.alstate;
2203  FAIL_IF(http_state == NULL);
2204 
2205  /* do detect */
2206  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2207 
2208  FAIL_IF(!PacketAlertCheck(p, 1));
2209 
2210  if (alp_tctx != NULL)
2211  AppLayerParserThreadCtxFree(alp_tctx);
2212  if (det_ctx != NULL) {
2213  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2214  }
2215  if (de_ctx != NULL) {
2216  SigGroupCleanup(de_ctx);
2217  DetectEngineCtxFree(de_ctx);
2218  }
2219 
2221  UTHFreePackets(&p, 1);
2222  PASS;
2223 }
2224 
2225 /** \test Check the signature working to alert when method modifier is
2226  * passed to pcre
2227  */
2228 static int DetectPcreTestSig11(void)
2229 {
2230  Flow f;
2231  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2232  "Cookie: dummy\r\n\r\n";
2233  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2234  TcpSession ssn;
2235  Packet *p = NULL;
2236  Signature *s = NULL;
2237  ThreadVars th_v;
2238  DetectEngineThreadCtx *det_ctx = NULL;
2239  HtpState *http_state = NULL;
2241 
2242  memset(&th_v, 0, sizeof(th_v));
2243  memset(&p, 0, sizeof(p));
2244  memset(&f, 0, sizeof(f));
2245  memset(&ssn, 0, sizeof(ssn));
2246 
2247  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2248 
2249  FLOW_INITIALIZE(&f);
2250  f.protoctx = (void *)&ssn;
2251  f.proto = IPPROTO_TCP;
2252  f.flags |= FLOW_IPV4;
2253 
2254  p->flow = &f;
2258  f.alproto = ALPROTO_HTTP;
2259 
2261 
2263  FAIL_IF(de_ctx == NULL);
2264 
2265  de_ctx->flags |= DE_QUIET;
2266 
2267  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2268  "\"HTTP method\"; pcre:\"/POST/M\"; "
2269  " sid:1;)");
2270  FAIL_IF(s == NULL);
2271 
2272  SigGroupBuild(de_ctx);
2273  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2274 
2275  FLOWLOCK_WRLOCK(&f);
2276  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2277  STREAM_TOSERVER, httpbuf1, httplen1);
2278  FAIL_IF(r != 0);
2279  FLOWLOCK_UNLOCK(&f);
2280 
2281  http_state = f.alstate;
2282  FAIL_IF(http_state == NULL);
2283 
2284  /* do detect */
2285  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2286 
2287  FAIL_IF(!PacketAlertCheck(p, 1));
2288 
2289  if (alp_tctx != NULL)
2290  AppLayerParserThreadCtxFree(alp_tctx);
2291  if (det_ctx != NULL) {
2292  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2293  }
2294  if (de_ctx != NULL) {
2295  SigGroupCleanup(de_ctx);
2296  DetectEngineCtxFree(de_ctx);
2297  }
2298 
2300  UTHFreePackets(&p, 1);
2301  PASS;
2302 }
2303 
2304 /** \test Check the signature working to alert when method modifier is
2305  * passed to a negated pcre
2306  */
2307 static int DetectPcreTestSig12(void)
2308 {
2309  Flow f;
2310  uint8_t httpbuf1[] = "GET / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2311  "Cookie: dummoOOooooO\r\n\r\n";
2312  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2313  TcpSession ssn;
2314  Packet *p = NULL;
2315  Signature *s = NULL;
2316  ThreadVars th_v;
2317  DetectEngineThreadCtx *det_ctx = NULL;
2318  HtpState *http_state = NULL;
2320 
2321  memset(&th_v, 0, sizeof(th_v));
2322  memset(&p, 0, sizeof(p));
2323  memset(&f, 0, sizeof(f));
2324  memset(&ssn, 0, sizeof(ssn));
2325 
2326  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2327 
2328  FLOW_INITIALIZE(&f);
2329  f.protoctx = (void *)&ssn;
2330  f.proto = IPPROTO_TCP;
2331  f.flags |= FLOW_IPV4;
2332 
2333  p->flow = &f;
2337  f.alproto = ALPROTO_HTTP;
2338 
2340 
2342  FAIL_IF(de_ctx == NULL);
2343 
2344  de_ctx->flags |= DE_QUIET;
2345 
2346  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2347  "\"HTTP method\"; pcre:!\"/POST/M\"; "
2348  " sid:1;)");
2349  FAIL_IF(s == NULL);
2350 
2351  SigGroupBuild(de_ctx);
2352  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2353 
2354  FLOWLOCK_WRLOCK(&f);
2355  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2356  STREAM_TOSERVER, httpbuf1, httplen1);
2357  FAIL_IF(r != 0);
2358  FLOWLOCK_UNLOCK(&f);
2359 
2360  http_state = f.alstate;
2361  FAIL_IF(http_state == NULL);
2362 
2363  /* do detect */
2364  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2365 
2366  FAIL_IF(!PacketAlertCheck(p, 1));
2367 
2368  if (alp_tctx != NULL)
2369  AppLayerParserThreadCtxFree(alp_tctx);
2370  if (det_ctx != NULL) {
2371  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2372  }
2373  if (de_ctx != NULL) {
2374  SigGroupCleanup(de_ctx);
2375  DetectEngineCtxFree(de_ctx);
2376  }
2377 
2379  UTHFreePackets(&p, 1);
2380  PASS;
2381 }
2382 
2383 /** \test Check the signature working to alert when header modifier is
2384  * passed to pcre
2385  */
2386 static int DetectPcreTestSig13(void)
2387 {
2388  Flow f;
2389  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2390  "Cookie: dummy\r\n\r\n";
2391  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2392  TcpSession ssn;
2393  Packet *p = NULL;
2394  Signature *s = NULL;
2395  ThreadVars th_v;
2396  DetectEngineThreadCtx *det_ctx = NULL;
2397  HtpState *http_state = NULL;
2399 
2400  memset(&th_v, 0, sizeof(th_v));
2401  memset(&p, 0, sizeof(p));
2402  memset(&f, 0, sizeof(f));
2403  memset(&ssn, 0, sizeof(ssn));
2404 
2405  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2406 
2407  FLOW_INITIALIZE(&f);
2408  f.protoctx = (void *)&ssn;
2409  f.proto = IPPROTO_TCP;
2410  f.flags |= FLOW_IPV4;
2411 
2412  p->flow = &f;
2416  f.alproto = ALPROTO_HTTP;
2417 
2419 
2421  FAIL_IF(de_ctx == NULL);
2422 
2423  de_ctx->flags |= DE_QUIET;
2424 
2425  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2426  "\"HTTP header\"; pcre:\"/User[-_]Agent[:]?\\sMozilla/H\"; "
2427  " sid:1;)");
2428  FAIL_IF(s == NULL);
2429 
2430  SigGroupBuild(de_ctx);
2431  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2432 
2433  FLOWLOCK_WRLOCK(&f);
2434  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2435  STREAM_TOSERVER, httpbuf1, httplen1);
2436  FAIL_IF(r != 0);
2437  FLOWLOCK_UNLOCK(&f);
2438 
2439  http_state = f.alstate;
2440  FAIL_IF(http_state == NULL);
2441 
2442  /* do detect */
2443  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2444 
2445  FAIL_IF(!PacketAlertCheck(p, 1));
2446 
2447  if (alp_tctx != NULL)
2448  AppLayerParserThreadCtxFree(alp_tctx);
2449  if (det_ctx != NULL) {
2450  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2451  }
2452  if (de_ctx != NULL) {
2453  SigGroupCleanup(de_ctx);
2454  DetectEngineCtxFree(de_ctx);
2455  }
2456 
2458  UTHFreePackets(&p, 1);
2459  PASS;
2460 }
2461 
2462 /** \test Check the signature working to alert when header modifier is
2463  * passed to a negated pcre
2464  */
2465 static int DetectPcreTestSig14(void)
2466 {
2467  Flow f;
2468  uint8_t httpbuf1[] = "GET / HTTP/1.0\r\nUser-Agent: IEXPLORER/1.0\r\n"
2469  "Cookie: dummoOOooooO\r\n\r\n";
2470  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2471  TcpSession ssn;
2472  Packet *p = NULL;
2473  Signature *s = NULL;
2474  ThreadVars th_v;
2475  DetectEngineThreadCtx *det_ctx = NULL;
2476  HtpState *http_state = NULL;
2478 
2479  memset(&th_v, 0, sizeof(th_v));
2480  memset(&p, 0, sizeof(p));
2481  memset(&f, 0, sizeof(f));
2482  memset(&ssn, 0, sizeof(ssn));
2483 
2484  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2485 
2486  FLOW_INITIALIZE(&f);
2487  f.protoctx = (void *)&ssn;
2488  f.proto = IPPROTO_TCP;
2489  f.flags |= FLOW_IPV4;
2490 
2491  p->flow = &f;
2495  f.alproto = ALPROTO_HTTP;
2496 
2498 
2500  FAIL_IF(de_ctx == NULL);
2501 
2502  de_ctx->flags |= DE_QUIET;
2503 
2504  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2505  "\"HTTP header\"; pcre:!\"/User-Agent[:]?\\s+Mozilla/H\"; "
2506  " sid:1;)");
2507  FAIL_IF(s == NULL);
2508 
2509  SigGroupBuild(de_ctx);
2510  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2511 
2512  FLOWLOCK_WRLOCK(&f);
2513  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2514  STREAM_TOSERVER, httpbuf1, httplen1);
2515  FAIL_IF(r != 0);
2516  FLOWLOCK_UNLOCK(&f);
2517 
2518  http_state = f.alstate;
2519  FAIL_IF(http_state == NULL);
2520 
2521  /* do detect */
2522  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2523 
2524  FAIL_IF(!PacketAlertCheck(p, 1));
2525 
2526  if (alp_tctx != NULL)
2527  AppLayerParserThreadCtxFree(alp_tctx);
2528  if (det_ctx != NULL) {
2529  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2530  }
2531  if (de_ctx != NULL) {
2532  SigGroupCleanup(de_ctx);
2533  DetectEngineCtxFree(de_ctx);
2534  }
2535 
2537  UTHFreePackets(&p, 1);
2538  PASS;
2539 }
2540 
2541 /** \test Check the signature working to alert when cookie and relative modifiers are
2542  * passed to pcre
2543  */
2544 static int DetectPcreTestSig15(void)
2545 {
2546  Flow f;
2547  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2548  "Cookie: dummy 1234\r\n\r\n";
2549  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2550  TcpSession ssn;
2551  Packet *p = NULL;
2552  Signature *s = NULL;
2553  ThreadVars th_v;
2554  DetectEngineThreadCtx *det_ctx = NULL;
2555  HtpState *http_state = NULL;
2557 
2558  memset(&th_v, 0, sizeof(th_v));
2559  memset(&p, 0, sizeof(p));
2560  memset(&f, 0, sizeof(f));
2561  memset(&ssn, 0, sizeof(ssn));
2562 
2563  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2564 
2565  FLOW_INITIALIZE(&f);
2566  f.protoctx = (void *)&ssn;
2567  f.proto = IPPROTO_TCP;
2568  f.flags |= FLOW_IPV4;
2569 
2570  p->flow = &f;
2574  f.alproto = ALPROTO_HTTP;
2575 
2577 
2579  FAIL_IF(de_ctx == NULL);
2580 
2581  de_ctx->flags |= DE_QUIET;
2582 
2583  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2584  "\"pcre relative HTTP cookie\"; content:\"dummy\";"
2585  " http_cookie; pcre:\"/1234/RC\"; "
2586  " sid:1;)");
2587  FAIL_IF(s == NULL);
2588 
2589  SigGroupBuild(de_ctx);
2590  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2591 
2592  FLOWLOCK_WRLOCK(&f);
2593  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2594  STREAM_TOSERVER, httpbuf1, httplen1);
2595  FAIL_IF(r != 0);
2596  FLOWLOCK_UNLOCK(&f);
2597 
2598  http_state = f.alstate;
2599  FAIL_IF(http_state == NULL);
2600 
2601  /* do detect */
2602  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2603 
2604  FAIL_IF(!PacketAlertCheck(p, 1));
2605 
2606  if (alp_tctx != NULL)
2607  AppLayerParserThreadCtxFree(alp_tctx);
2608  if (det_ctx != NULL) {
2609  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2610  }
2611  if (de_ctx != NULL) {
2612  SigGroupCleanup(de_ctx);
2613  DetectEngineCtxFree(de_ctx);
2614  }
2615 
2617  UTHFreePackets(&p, 1);
2618  PASS;
2619 }
2620 
2621 /** \test Check the signature working to alert when method and relative modifiers are
2622  * passed to pcre
2623  */
2624 static int DetectPcreTestSig16(void)
2625 {
2626  Flow f;
2627  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2628  "Cookie: dummy 1234\r\n\r\n";
2629  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2630  TcpSession ssn;
2631  Packet *p = NULL;
2632  Signature *s = NULL;
2633  ThreadVars th_v;
2634  DetectEngineThreadCtx *det_ctx = NULL;
2635  HtpState *http_state = NULL;
2637 
2638  memset(&th_v, 0, sizeof(th_v));
2639  memset(&p, 0, sizeof(p));
2640  memset(&f, 0, sizeof(f));
2641  memset(&ssn, 0, sizeof(ssn));
2642 
2643  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2644 
2645  FLOW_INITIALIZE(&f);
2646  f.protoctx = (void *)&ssn;
2647  f.proto = IPPROTO_TCP;
2648  f.flags |= FLOW_IPV4;
2649 
2650  p->flow = &f;
2654  f.alproto = ALPROTO_HTTP;
2655 
2657 
2659  FAIL_IF(de_ctx == NULL);
2660 
2661  de_ctx->flags |= DE_QUIET;
2662 
2663  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2664  "\"pcre relative HTTP method\"; content:\"PO\";"
2665  " http_method; pcre:\"/ST/RM\"; "
2666  " sid:1;)");
2667  FAIL_IF(s == NULL);
2668 
2669  SigGroupBuild(de_ctx);
2670  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2671 
2672  FLOWLOCK_WRLOCK(&f);
2673  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2674  STREAM_TOSERVER, httpbuf1, httplen1);
2675  FAIL_IF(r != 0);
2676  FLOWLOCK_UNLOCK(&f);
2677 
2678  http_state = f.alstate;
2679  FAIL_IF(http_state == NULL);
2680 
2681  /* do detect */
2682  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2683 
2684  FAIL_IF(!PacketAlertCheck(p, 1));
2685 
2686  if (alp_tctx != NULL)
2687  AppLayerParserThreadCtxFree(alp_tctx);
2688  if (det_ctx != NULL) {
2689  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2690  }
2691  if (de_ctx != NULL) {
2692  SigGroupCleanup(de_ctx);
2693  DetectEngineCtxFree(de_ctx);
2694  }
2695 
2697  UTHFreePackets(&p, 1);
2698  PASS;
2699 }
2700 
2701 /** \test Test tracking of body chunks per transactions (on requests)
2702  */
2703 static int DetectPcreTxBodyChunksTest01(void)
2704 {
2705  Flow f;
2706  TcpSession ssn;
2707  Packet *p = NULL;
2708  uint8_t httpbuf1[] = "GET / HTTP/1.1\r\n";
2709  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
2710  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
2711  uint8_t httpbuf4[] = "Body one!!";
2712  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2713  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2714  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
2715  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
2716  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
2717  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
2718  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
2719  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
2720  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
2721  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
2723 
2724  memset(&f, 0, sizeof(f));
2725  memset(&ssn, 0, sizeof(ssn));
2726 
2727  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2728 
2729  FLOW_INITIALIZE(&f);
2730  f.protoctx = (void *)&ssn;
2731  f.proto = IPPROTO_TCP;
2732  f.flags |= FLOW_IPV4;
2733 
2734  p->flow = &f;
2738  f.alproto = ALPROTO_HTTP;
2739 
2741 
2743 
2744  FLOWLOCK_WRLOCK(&f);
2745  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2746  STREAM_TOSERVER | STREAM_START, httpbuf1,
2747  httplen1);
2748  FAIL_IF(r != 0);
2749 
2750  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2751  STREAM_TOSERVER, httpbuf2, httplen2);
2752  FAIL_IF(r != 0);
2753 
2754  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2755  STREAM_TOSERVER, httpbuf3, httplen3);
2756  FAIL_IF(r != 0);
2757 
2758  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2759  STREAM_TOSERVER, httpbuf4, httplen4);
2760  FAIL_IF(r != 0);
2761 
2762  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2763  STREAM_TOSERVER, httpbuf5, httplen5);
2764  FAIL_IF(r != 0);
2765 
2766  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2767  STREAM_TOSERVER, httpbuf6, httplen6);
2768  FAIL_IF(r != 0);
2769 
2770  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2771  STREAM_TOSERVER, httpbuf7, httplen7);
2772  FAIL_IF(r != 0);
2773 
2774  /* Now we should have 2 transactions, each with it's own list
2775  * of request body chunks (let's test it) */
2776 
2777  HtpState *htp_state = f.alstate;
2778  FAIL_IF(htp_state == NULL);
2779 
2780  /* hardcoded check of the transactions and it's client body chunks */
2781  FAIL_IF(AppLayerParserGetTxCnt(&f, htp_state) != 2);
2782 
2783  htp_tx_t *t1 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, 0);
2784  htp_tx_t *t2 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, 1);
2785 
2786  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
2787  FAIL_IF(htud == NULL);
2788 
2789  HtpBodyChunk *cur = htud->request_body.first;
2790  FAIL_IF(htud->request_body.first == NULL);
2791 
2792  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body one!!", 10) != 1);
2793 
2794  htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
2795 
2796  cur = htud->request_body.first;
2797  FAIL_IF(htud->request_body.first == NULL);
2798 
2799  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body two!!", 10) != 1);
2800 
2801  if (alp_tctx != NULL)
2802  AppLayerParserThreadCtxFree(alp_tctx);
2803  FLOWLOCK_UNLOCK(&f);
2805  FLOW_DESTROY(&f);
2806  UTHFreePacket(p);
2807  PASS;
2808 }
2809 
2810 /** \test test pcre P modifier with multiple pipelined http transactions */
2811 static int DetectPcreTxBodyChunksTest02(void)
2812 {
2813  Signature *s = NULL;
2814  DetectEngineThreadCtx *det_ctx = NULL;
2815  ThreadVars th_v;
2816  Flow f;
2817  TcpSession ssn;
2818  Packet *p = NULL;
2819  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
2820  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
2821  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
2822  uint8_t httpbuf4[] = "Body one!!";
2823  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2824  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2825  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
2826  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
2827  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
2828  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
2829  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
2830  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
2831  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
2832  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
2834 
2835  memset(&th_v, 0, sizeof(th_v));
2836  memset(&f, 0, sizeof(f));
2837  memset(&ssn, 0, sizeof(ssn));
2838 
2839  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2840 
2841  FLOW_INITIALIZE(&f);
2842  f.protoctx = (void *)&ssn;
2843  f.proto = IPPROTO_TCP;
2844  f.flags |= FLOW_IPV4;
2845 
2846  p->flow = &f;
2850  f.alproto = ALPROTO_HTTP;
2851 
2853 
2855  FAIL_IF(de_ctx == NULL);
2856 
2857  de_ctx->flags |= DE_QUIET;
2858 
2859  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"Mozilla\"; http_header; content:\"dummy\"; http_cookie; pcre:\"/one/P\"; sid:1; rev:1;)");
2860  FAIL_IF(s == NULL);
2861  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"Firefox\"; http_header; content:\"dummy2\"; http_cookie; pcre:\"/two/P\"; sid:2; rev:1;)");
2862  FAIL_IF(s == NULL);
2863 
2864  SigGroupBuild(de_ctx);
2865  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2866 
2867  FLOWLOCK_WRLOCK(&f);
2868  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2869  STREAM_TOSERVER, httpbuf1, httplen1);
2870  FAIL_IF(r != 0);
2871  FLOWLOCK_UNLOCK(&f);
2872 
2873  /* do detect */
2874  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2875  FAIL_IF(PacketAlertCheck(p, 1));
2876  p->alerts.cnt = 0;
2877 
2878  FLOWLOCK_WRLOCK(&f);
2879  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2880  STREAM_TOSERVER, httpbuf2, httplen2);
2881  FAIL_IF(r != 0);
2882  FLOWLOCK_UNLOCK(&f);
2883 
2884  /* do detect */
2885  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2886  FAIL_IF(PacketAlertCheck(p, 1));
2887  p->alerts.cnt = 0;
2888 
2889  FLOWLOCK_WRLOCK(&f);
2890  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2891  STREAM_TOSERVER, httpbuf3, httplen3);
2892  FAIL_IF(r != 0);
2893  FLOWLOCK_UNLOCK(&f);
2894 
2895  /* do detect */
2896  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2897  FAIL_IF(PacketAlertCheck(p, 1));
2898  p->alerts.cnt = 0;
2899 
2900  FLOWLOCK_WRLOCK(&f);
2901  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2902  STREAM_TOSERVER, httpbuf4, httplen4);
2903  FAIL_IF(r != 0);
2904  FLOWLOCK_UNLOCK(&f);
2905 
2906  /* do detect */
2907  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2908  FAIL_IF(!(PacketAlertCheck(p, 1)));
2909  p->alerts.cnt = 0;
2910 
2911  FLOWLOCK_WRLOCK(&f);
2912  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2913  STREAM_TOSERVER, httpbuf5, httplen5);
2914  FAIL_IF(r != 0);
2915  FLOWLOCK_UNLOCK(&f);
2916 
2917  /* do detect */
2918  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2919  FAIL_IF(PacketAlertCheck(p, 1));
2920  p->alerts.cnt = 0;
2921 
2922  FLOWLOCK_WRLOCK(&f);
2923  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2924  STREAM_TOSERVER, httpbuf6, httplen6);
2925  FAIL_IF(r != 0);
2926  FLOWLOCK_UNLOCK(&f);
2927 
2928  /* do detect */
2929  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2930  FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
2931  p->alerts.cnt = 0;
2932 
2933  SCLogDebug("sending data chunk 7");
2934 
2935  FLOWLOCK_WRLOCK(&f);
2936  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2937  STREAM_TOSERVER, httpbuf7, httplen7);
2938  FAIL_IF(r != 0);
2939  FLOWLOCK_UNLOCK(&f);
2940 
2941  /* do detect */
2942  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2943  FAIL_IF(!(PacketAlertCheck(p, 2)));
2944  p->alerts.cnt = 0;
2945 
2946  HtpState *htp_state = f.alstate;
2947  FAIL_IF(htp_state == NULL);
2948 
2949  /* hardcoded check of the transactions and it's client body chunks */
2950  FAIL_IF(AppLayerParserGetTxCnt(&f, htp_state) != 2);
2951 
2952  htp_tx_t *t1 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, 0);
2953  htp_tx_t *t2 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, 1);
2954 
2955  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
2956 
2957  HtpBodyChunk *cur = htud->request_body.first;
2958  FAIL_IF(htud->request_body.first == NULL);
2959 
2960  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body one!!", 10) != 1);
2961 
2962  htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
2963 
2964  cur = htud->request_body.first;
2965  FAIL_IF(htud->request_body.first == NULL);
2966 
2967  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body two!!", 10) != 1);
2968 
2969  if (alp_tctx != NULL)
2970  AppLayerParserThreadCtxFree(alp_tctx);
2971  if (det_ctx != NULL) {
2972  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2973  }
2974  if (de_ctx != NULL) {
2975  SigGroupCleanup(de_ctx);
2976  DetectEngineCtxFree(de_ctx);
2977  }
2978 
2980  FLOW_DESTROY(&f);
2981  UTHFreePacket(p);
2982  PASS;
2983 }
2984 
2985 /** \test multiple http transactions and body chunks of request handling */
2986 static int DetectPcreTxBodyChunksTest03(void)
2987 {
2988  Signature *s = NULL;
2989  DetectEngineThreadCtx *det_ctx = NULL;
2990  ThreadVars th_v;
2991  Flow f;
2992  TcpSession ssn;
2993  Packet *p = NULL;
2994  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
2995  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
2996  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
2997  uint8_t httpbuf4[] = "Body one!!";
2998  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2999  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
3000  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
3001  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
3002  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
3003  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
3004  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
3005  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
3006  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
3007  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
3009 
3010  memset(&th_v, 0, sizeof(th_v));
3011  memset(&f, 0, sizeof(f));
3012  memset(&ssn, 0, sizeof(ssn));
3013 
3014  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3015 
3016  FLOW_INITIALIZE(&f);
3017  f.protoctx = (void *)&ssn;
3018  f.proto = IPPROTO_TCP;
3019  f.flags |= FLOW_IPV4;
3020 
3021  p->flow = &f;
3025  f.alproto = ALPROTO_HTTP;
3026 
3028 
3030  FAIL_IF(de_ctx == NULL);
3031 
3032  de_ctx->flags |= DE_QUIET;
3033 
3034  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"Mozilla\"; http_header; content:\"dummy\"; http_cookie; pcre:\"/one/P\"; sid:1; rev:1;)");
3035  FAIL_IF(s == NULL);
3036  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"Firefox\"; http_header; content:\"dummy2\"; http_cookie; pcre:\"/two/P\"; sid:2; rev:1;)");
3037  FAIL_IF(s == NULL);
3038 
3039  SigGroupBuild(de_ctx);
3040  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3041 
3042  FLOWLOCK_WRLOCK(&f);
3043  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3044  STREAM_TOSERVER, httpbuf1, httplen1);
3045  FAIL_IF(r != 0);
3046  FLOWLOCK_UNLOCK(&f);
3047 
3048  /* do detect */
3049  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3050  FAIL_IF(PacketAlertCheck(p, 1));
3051  p->alerts.cnt = 0;
3052 
3053  FLOWLOCK_WRLOCK(&f);
3054  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3055  STREAM_TOSERVER, httpbuf2, httplen2);
3056  FAIL_IF(r != 0);
3057  FLOWLOCK_UNLOCK(&f);
3058 
3059  /* do detect */
3060  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3061  FAIL_IF(PacketAlertCheck(p, 1));
3062  p->alerts.cnt = 0;
3063 
3064  FLOWLOCK_WRLOCK(&f);
3065  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3066  STREAM_TOSERVER, httpbuf3, httplen3);
3067  FAIL_IF(r != 0);
3068  FLOWLOCK_UNLOCK(&f);
3069 
3070  /* do detect */
3071  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3072  FAIL_IF(PacketAlertCheck(p, 1));
3073  p->alerts.cnt = 0;
3074 
3075  FLOWLOCK_WRLOCK(&f);
3076  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3077  STREAM_TOSERVER, httpbuf4, httplen4);
3078  FAIL_IF(r != 0);
3079  FLOWLOCK_UNLOCK(&f);
3080 
3081  /* do detect */
3082  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3083  FAIL_IF(!(PacketAlertCheck(p, 1)));
3084  p->alerts.cnt = 0;
3085 
3086  FLOWLOCK_WRLOCK(&f);
3087  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3088  STREAM_TOSERVER, httpbuf5, httplen5);
3089  FAIL_IF(r != 0);
3090  FLOWLOCK_UNLOCK(&f);
3091 
3092  /* do detect */
3093  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3094  FAIL_IF(PacketAlertCheck(p, 1));
3095  p->alerts.cnt = 0;
3096 
3097  FLOWLOCK_WRLOCK(&f);
3098  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3099  STREAM_TOSERVER, httpbuf6, httplen6);
3100  FAIL_IF(r != 0);
3101  FLOWLOCK_UNLOCK(&f);
3102 
3103  /* do detect */
3104  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3105  FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
3106  p->alerts.cnt = 0;
3107 
3108  SCLogDebug("sending data chunk 7");
3109 
3110  FLOWLOCK_WRLOCK(&f);
3111  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3112  STREAM_TOSERVER, httpbuf7, httplen7);
3113  FAIL_IF(r != 0);
3114  FLOWLOCK_UNLOCK(&f);
3115 
3116  /* do detect */
3117  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3118  FAIL_IF(!(PacketAlertCheck(p, 2)));
3119  p->alerts.cnt = 0;
3120 
3121  HtpState *htp_state = f.alstate;
3122  FAIL_IF(htp_state == NULL);
3123 
3124  FAIL_IF(AppLayerParserGetTxCnt(&f, htp_state) != 2);
3125 
3126  if (alp_tctx != NULL)
3127  AppLayerParserThreadCtxFree(alp_tctx);
3128  if (det_ctx != NULL) {
3129  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
3130  }
3131  if (de_ctx != NULL) {
3132  SigGroupCleanup(de_ctx);
3133  DetectEngineCtxFree(de_ctx);
3134  }
3135 
3137  FLOW_DESTROY(&f);
3138  UTHFreePacket(p);
3139  PASS;
3140 }
3141 
3142 /**
3143  * \test flowvar capture on http buffer
3144  */
3145 static int DetectPcreFlowvarCapture01(void)
3146 {
3147  uint8_t uabuf1[] =
3148  "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.0.13) Gecko/2009080315 Ubuntu/8.10 (intrepid) Firefox/3.0.13";
3149  uint32_t ualen1 = sizeof(uabuf1) - 1; /* minus the \0 */
3150  uint8_t httpbuf1[] =
3151  "GET / HTTP/1.1\r\n"
3152  "Host: www.emergingthreats.net\r\n"
3153  "User-Agent: Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.0.13) Gecko/2009080315 Ubuntu/8.10 (intrepid) Firefox/3.0.13\r\n"
3154  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8\r\n"
3155  "Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
3156  "Accept-Encoding: gzip,deflate\r\n"
3157  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
3158  "Date: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
3159  "Server: Apache\r\n"
3160  "\r\n"
3161  "<!DOCTYPE html PUBLIC\r\n\r\n";
3162  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3163  TcpSession ssn;
3164  Packet *p1 = NULL;
3165  Flow f;
3166  Signature *s = NULL;
3167  ThreadVars th_v;
3168  DetectEngineThreadCtx *det_ctx;
3170 
3171  memset(&th_v, 0, sizeof(th_v));
3172  memset(&f, 0, sizeof(f));
3173  memset(&ssn, 0, sizeof(ssn));
3174 
3175  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3176 
3177  FLOW_INITIALIZE(&f);
3178  f.protoctx = (void *)&ssn;
3179  f.proto = IPPROTO_TCP;
3180  f.flags |= FLOW_IPV4;
3181  f.alproto = ALPROTO_HTTP;
3182 
3183  p1->flow = &f;
3187 
3189 
3191  FAIL_IF(de_ctx == NULL);
3192  de_ctx->flags |= DE_QUIET;
3193 
3194  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"User-Agent: \"; http_header; pcre:\"/(?P<flow_ua>.*)\\r\\n/HR\"; sid:1;)");
3195  FAIL_IF(s == NULL);
3196 
3197  FAIL_IF(s->sm_lists[g_http_header_buffer_id] == NULL ||
3198  s->sm_lists[g_http_header_buffer_id]->next == NULL ||
3199  s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
3200  DetectPcreData *pd = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
3201 
3202  SigGroupBuild(de_ctx);
3203  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3204 
3205  FLOWLOCK_WRLOCK(&f);
3206  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3207  STREAM_TOSERVER, httpbuf1, httplen1);
3208  FAIL_IF(r != 0);
3209  FLOWLOCK_UNLOCK(&f);
3210 
3211  HtpState *http_state = f.alstate;
3212  FAIL_IF(http_state == NULL);
3213 
3214  /* do detect for p1 */
3215  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
3216 
3217  FAIL_IF(!(PacketAlertCheck(p1, 1)));
3218 
3219  FlowVar *fv = FlowVarGet(&f, pd->capids[0]);
3220  FAIL_IF(fv == NULL);
3221 
3222  FAIL_IF(fv->data.fv_str.value_len != ualen1);
3223 
3224  if (memcmp(fv->data.fv_str.value, uabuf1, ualen1) != 0) {
3225  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
3226  PrintRawDataFp(stdout, uabuf1, ualen1);
3227 
3228  printf("buffer mismatch: ");
3229  FAIL;
3230  }
3231 
3232  if (alp_tctx != NULL)
3233  AppLayerParserThreadCtxFree(alp_tctx);
3234  if (de_ctx != NULL)
3235  DetectEngineCtxFree(de_ctx);
3236 
3238  FLOW_DESTROY(&f);
3239  UTHFreePackets(&p1, 1);
3240  PASS;
3241 }
3242 
3243 /**
3244  * \test flowvar capture on http buffer, capture overwrite
3245  */
3246 static int DetectPcreFlowvarCapture02(void)
3247 {
3248  uint8_t uabuf1[] =
3249  "Apache";
3250  uint32_t ualen1 = sizeof(uabuf1) - 1; /* minus the \0 */
3251  uint8_t httpbuf1[] =
3252  "GET / HTTP/1.1\r\n"
3253  "Host: www.emergingthreats.net\r\n"
3254  "User-Agent: Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.0.13) Gecko/2009080315 Ubuntu/8.10 (intrepid) Firefox/3.0.13\r\n"
3255  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8\r\n"
3256  "Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
3257  "Accept-Encoding: gzip,deflate\r\n"
3258  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
3259  "Date: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
3260  "Server: Apache\r\n"
3261  "\r\n"
3262  "<!DOCTYPE html PUBLIC\r\n\r\n";
3263  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3264  TcpSession ssn;
3265  Packet *p1 = NULL;
3266  Flow f;
3267  Signature *s = NULL;
3268  ThreadVars th_v;
3269  DetectEngineThreadCtx *det_ctx;
3271 
3272  memset(&th_v, 0, sizeof(th_v));
3273  memset(&f, 0, sizeof(f));
3274  memset(&ssn, 0, sizeof(ssn));
3275 
3276  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3277 
3278  FLOW_INITIALIZE(&f);
3279  f.protoctx = (void *)&ssn;
3280  f.proto = IPPROTO_TCP;
3281  f.flags |= FLOW_IPV4;
3282  f.alproto = ALPROTO_HTTP;
3283 
3284  p1->flow = &f;
3288 
3290 
3292  FAIL_IF(de_ctx == NULL);
3293  de_ctx->flags |= DE_QUIET;
3294 
3295  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"User-Agent: \"; http_header; pcre:\"/(?P<flow_ua>.*)\\r\\n/HR\"; priority:1; sid:1;)");
3296  FAIL_IF(s == NULL);
3297 
3298  FAIL_IF(s->sm_lists[g_http_header_buffer_id] == NULL ||
3299  s->sm_lists[g_http_header_buffer_id]->next == NULL ||
3300  s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
3301  DetectPcreData *pd1 = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
3302 
3303  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"Server: \"; http_header; pcre:\"/(?P<flow_ua>.*)\\r\\n/HR\"; priority:3; sid:2;)");
3304  FAIL_IF(s == NULL);
3305 
3306  FAIL_IF(s->sm_lists[g_http_header_buffer_id] == NULL ||
3307  s->sm_lists[g_http_header_buffer_id]->next == NULL ||
3308  s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
3309  DetectPcreData *pd2 = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
3310 
3311  FAIL_IF(pd1->capids[0] != pd2->capids[0]);
3312 
3314  SCSigOrderSignatures(de_ctx);
3316  SigGroupBuild(de_ctx);
3317  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3318 
3319  FLOWLOCK_WRLOCK(&f);
3320  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3321  STREAM_TOSERVER, httpbuf1, httplen1);
3322  FAIL_IF(r != 0);
3323  FLOWLOCK_UNLOCK(&f);
3324 
3325  HtpState *http_state = f.alstate;
3326  FAIL_IF(http_state == NULL);
3327 
3328  /* do detect for p1 */
3329  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
3330 
3331  FAIL_IF(!(PacketAlertCheck(p1, 1)));
3332 
3333  FlowVar *fv = FlowVarGet(&f, pd1->capids[0]);
3334  FAIL_IF(fv == NULL);
3335 
3336  if (fv->data.fv_str.value_len != ualen1) {
3337  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
3338  PrintRawDataFp(stdout, uabuf1, ualen1);
3339  printf("%u != %u: ", fv->data.fv_str.value_len, ualen1);
3340  FAIL;
3341  }
3342 
3343  if (memcmp(fv->data.fv_str.value, uabuf1, ualen1) != 0) {
3344  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
3345  PrintRawDataFp(stdout, uabuf1, ualen1);
3346 
3347  printf("buffer mismatch: ");
3348  FAIL;
3349  }
3350 
3351  if (alp_tctx != NULL)
3352  AppLayerParserThreadCtxFree(alp_tctx);
3353  if (de_ctx != NULL)
3354  DetectEngineCtxFree(de_ctx);
3355 
3357  FLOW_DESTROY(&f);
3358  UTHFreePackets(&p1, 1);
3359  PASS;
3360 }
3361 
3362 /**
3363  * \test flowvar capture on http buffer, capture overwrite + no matching sigs, so flowvars should not be set.
3364  */
3365 static int DetectPcreFlowvarCapture03(void)
3366 {
3367  uint8_t httpbuf1[] =
3368  "GET / HTTP/1.1\r\n"
3369  "Host: www.emergingthreats.net\r\n"
3370  "User-Agent: Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.0.13) Gecko/2009080315 Ubuntu/8.10 (intrepid) Firefox/3.0.13\r\n"
3371  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8\r\n"
3372  "Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
3373  "Accept-Encoding: gzip,deflate\r\n"
3374  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
3375  "Date: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
3376  "Server: Apache\r\n"
3377  "\r\n"
3378  "<!DOCTYPE html PUBLIC\r\n\r\n";
3379  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3380  TcpSession ssn;
3381  Packet *p1 = NULL;
3382  Flow f;
3383  Signature *s = NULL;
3384  ThreadVars th_v;
3385  DetectEngineThreadCtx *det_ctx;
3387 
3388  memset(&th_v, 0, sizeof(th_v));
3389  memset(&f, 0, sizeof(f));
3390  memset(&ssn, 0, sizeof(ssn));
3391 
3392  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3393 
3394  FLOW_INITIALIZE(&f);
3395  f.protoctx = (void *)&ssn;
3396  f.proto = IPPROTO_TCP;
3397  f.flags |= FLOW_IPV4;
3398  f.alproto = ALPROTO_HTTP;
3399 
3400  p1->flow = &f;
3404 
3406 
3408  FAIL_IF(de_ctx == NULL);
3409  de_ctx->flags |= DE_QUIET;
3410 
3411  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"User-Agent: \"; http_header; pcre:\"/(?P<flow_ua>.*)\\r\\n/HR\"; content:\"xyz\"; http_header; priority:1; sid:1;)");
3412  FAIL_IF(s == NULL);
3413 
3414  FAIL_IF(s->sm_lists[g_http_header_buffer_id] == NULL ||
3415  s->sm_lists[g_http_header_buffer_id]->next == NULL ||
3416  s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
3417  DetectPcreData *pd1 = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
3418 
3419  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"Server: \"; http_header; pcre:\"/(?P<flow_ua>.*)\\r\\n/HR\"; content:\"xyz\"; http_header; priority:3; sid:2;)");
3420  FAIL_IF(s == NULL);
3421 
3422  FAIL_IF(s->sm_lists[g_http_header_buffer_id] == NULL ||
3423  s->sm_lists[g_http_header_buffer_id]->next == NULL ||
3424  s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
3425  DetectPcreData *pd2 = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
3426 
3427  FAIL_IF(pd1->capids[0] != pd2->capids[0]);
3428 
3429  SigGroupBuild(de_ctx);
3430  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3431 
3432  FLOWLOCK_WRLOCK(&f);
3433  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3434  STREAM_TOSERVER, httpbuf1, httplen1);
3435  FAIL_IF(r != 0);
3436  FLOWLOCK_UNLOCK(&f);
3437 
3438  HtpState *http_state = f.alstate;
3439  FAIL_IF(http_state == NULL);
3440 
3441  /* do detect for p1 */
3442  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
3443 
3444  FAIL_IF(PacketAlertCheck(p1, 1));
3445 
3446  FlowVar *fv = FlowVarGet(&f, pd1->capids[0]);
3447  FAIL_IF(fv != NULL);
3448 
3449  if (alp_tctx != NULL)
3450  AppLayerParserThreadCtxFree(alp_tctx);
3451  if (de_ctx != NULL)
3452  DetectEngineCtxFree(de_ctx);
3453 
3455  FLOW_DESTROY(&f);
3456  UTHFreePackets(&p1, 1);
3457  PASS;
3458 }
3459 
3460 /**
3461  * \brief Test parsing of pcre's with the W modifier set.
3462  */
3463 static int DetectPcreParseHttpHost(void)
3464 {
3465  AppProto alproto = ALPROTO_UNKNOWN;
3466  int list = DETECT_SM_LIST_NOTSET;
3468 
3469  FAIL_IF(de_ctx == NULL);
3470 
3471  DetectPcreData *pd = DetectPcreParse(de_ctx, "/domain\\.com/W", &list, NULL, 0, false, &alproto);
3472  FAIL_IF(pd == NULL);
3473  DetectPcreFree(pd);
3474 
3475  list = DETECT_SM_LIST_NOTSET;
3476  pd = DetectPcreParse(de_ctx, "/dOmain\\.com/W", &list, NULL, 0, false, &alproto);
3477  FAIL_IF(pd != NULL);
3478 
3479  /* Uppercase meta characters are valid. */
3480  list = DETECT_SM_LIST_NOTSET;
3481  pd = DetectPcreParse(de_ctx, "/domain\\D+\\.com/W", &list, NULL, 0, false, &alproto);
3482  FAIL_IF(pd == NULL);
3483  DetectPcreFree(pd);
3484 
3485  /* This should not parse as the first \ escapes the second \, then
3486  * we have a D. */
3487  list = DETECT_SM_LIST_NOTSET;
3488  pd = DetectPcreParse(de_ctx, "/\\\\Ddomain\\.com/W", &list, NULL, 0, false, &alproto);
3489  FAIL_IF(pd != NULL);
3490 
3491  DetectEngineCtxFree(de_ctx);
3492  PASS;
3493 }
3494 
3495 /**
3496  * \brief Test parsing of capture extension
3497  */
3498 static int DetectPcreParseCaptureTest(void)
3499 {
3501  FAIL_IF(de_ctx == NULL);
3502 
3503  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
3504  "(content:\"Server: \"; http_header; pcre:\"/(.*)\\r\\n/HR, flow:somecapture\"; content:\"xyz\"; http_header; sid:1;)");
3505  FAIL_IF(s == NULL);
3506  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
3507  "(content:\"Server: \"; http_header; pcre:\"/(flow:.*)\\r\\n/HR\"; content:\"xyz\"; http_header; sid:2;)");
3508  FAIL_IF(s == NULL);
3509  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
3510  "(content:\"Server: \"; http_header; pcre:\"/([a-z]+)([0-9]+)\\r\\n/HR, flow:somecapture, pkt:anothercap\"; content:\"xyz\"; http_header; sid:3;)");
3511  FAIL_IF(s == NULL);
3512 
3513  SigGroupBuild(de_ctx);
3514 
3515  uint32_t capid = VarNameStoreLookupByName("somecapture", VAR_TYPE_FLOW_VAR);
3516  FAIL_IF (capid != 1);
3517  capid = VarNameStoreLookupByName("anothercap", VAR_TYPE_PKT_VAR);
3518  FAIL_IF (capid != 2);
3519 
3520  DetectEngineCtxFree(de_ctx);
3521  PASS;
3522 }
3523 
3524 #endif /* UNITTESTS */
3525 
3526 /**
3527  * \brief this function registers unit tests for DetectPcre
3528  */
3529 static void DetectPcreRegisterTests(void)
3530 {
3531 #ifdef UNITTESTS /* UNITTESTS */
3532  g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
3533  g_http_header_buffer_id = DetectBufferTypeGetByName("http_header");
3534  g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
3535 
3536  UtRegisterTest("DetectPcreParseTest01", DetectPcreParseTest01);
3537  UtRegisterTest("DetectPcreParseTest02", DetectPcreParseTest02);
3538  UtRegisterTest("DetectPcreParseTest03", DetectPcreParseTest03);
3539  UtRegisterTest("DetectPcreParseTest04", DetectPcreParseTest04);
3540  UtRegisterTest("DetectPcreParseTest05", DetectPcreParseTest05);
3541  UtRegisterTest("DetectPcreParseTest06", DetectPcreParseTest06);
3542  UtRegisterTest("DetectPcreParseTest07", DetectPcreParseTest07);
3543  UtRegisterTest("DetectPcreParseTest08", DetectPcreParseTest08);
3544  UtRegisterTest("DetectPcreParseTest09", DetectPcreParseTest09);
3545  UtRegisterTest("DetectPcreParseTest10", DetectPcreParseTest10);
3546  UtRegisterTest("DetectPcreParseTest11", DetectPcreParseTest11);
3547  UtRegisterTest("DetectPcreParseTest12", DetectPcreParseTest12);
3548  UtRegisterTest("DetectPcreParseTest13", DetectPcreParseTest13);
3549  UtRegisterTest("DetectPcreParseTest14", DetectPcreParseTest14);
3550  UtRegisterTest("DetectPcreParseTest15", DetectPcreParseTest15);
3551  UtRegisterTest("DetectPcreParseTest16", DetectPcreParseTest16);
3552  UtRegisterTest("DetectPcreParseTest17", DetectPcreParseTest17);
3553  UtRegisterTest("DetectPcreParseTest18", DetectPcreParseTest18);
3554  UtRegisterTest("DetectPcreParseTest19", DetectPcreParseTest19);
3555  UtRegisterTest("DetectPcreParseTest20", DetectPcreParseTest20);
3556  UtRegisterTest("DetectPcreParseTest21", DetectPcreParseTest21);
3557  UtRegisterTest("DetectPcreParseTest22", DetectPcreParseTest22);
3558  UtRegisterTest("DetectPcreParseTest23", DetectPcreParseTest23);
3559  UtRegisterTest("DetectPcreParseTest24", DetectPcreParseTest24);
3560  UtRegisterTest("DetectPcreParseTest25", DetectPcreParseTest25);
3561  UtRegisterTest("DetectPcreParseTest26", DetectPcreParseTest26);
3562  UtRegisterTest("DetectPcreParseTest27", DetectPcreParseTest27);
3563  UtRegisterTest("DetectPcreParseTest28", DetectPcreParseTest28);
3564 
3565  UtRegisterTest("DetectPcreTestSig01 -- pcre test", DetectPcreTestSig01);
3566  UtRegisterTest("DetectPcreTestSig02 -- pcre test", DetectPcreTestSig02);
3567  UtRegisterTest("DetectPcreTestSig03 -- negated pcre test",
3568  DetectPcreTestSig03);
3569 
3570  UtRegisterTest("DetectPcreModifPTest04 -- Modifier P",
3571  DetectPcreModifPTest04);
3572  UtRegisterTest("DetectPcreModifPTest05 -- Modifier P fragmented",
3573  DetectPcreModifPTest05);
3574  UtRegisterTest("DetectPcreTestSig06", DetectPcreTestSig06);
3575  UtRegisterTest("DetectPcreTestSig07 -- anchored pcre",
3576  DetectPcreTestSig07);
3577  UtRegisterTest("DetectPcreTestSig08 -- anchored pcre",
3578  DetectPcreTestSig08);
3579  UtRegisterTest("DetectPcreTestSig09 -- Cookie modifier",
3580  DetectPcreTestSig09);
3581  UtRegisterTest("DetectPcreTestSig10 -- negated Cookie modifier",
3582  DetectPcreTestSig10);
3583  UtRegisterTest("DetectPcreTestSig11 -- Method modifier",
3584  DetectPcreTestSig11);
3585  UtRegisterTest("DetectPcreTestSig12 -- negated Method modifier",
3586  DetectPcreTestSig12);
3587  UtRegisterTest("DetectPcreTestSig13 -- Header modifier",
3588  DetectPcreTestSig13);
3589  UtRegisterTest("DetectPcreTestSig14 -- negated Header modifier",
3590  DetectPcreTestSig14);
3591  UtRegisterTest("DetectPcreTestSig15 -- relative Cookie modifier",
3592  DetectPcreTestSig15);
3593  UtRegisterTest("DetectPcreTestSig16 -- relative Method modifier",
3594  DetectPcreTestSig16);
3595 
3596  UtRegisterTest("DetectPcreTxBodyChunksTest01",
3597  DetectPcreTxBodyChunksTest01);
3598  UtRegisterTest("DetectPcreTxBodyChunksTest02 -- modifier P, body chunks per tx",
3599  DetectPcreTxBodyChunksTest02);
3600  UtRegisterTest("DetectPcreTxBodyChunksTest03 -- modifier P, body chunks per tx",
3601  DetectPcreTxBodyChunksTest03);
3602 
3603  UtRegisterTest("DetectPcreFlowvarCapture01 -- capture for http_header",
3604  DetectPcreFlowvarCapture01);
3605  UtRegisterTest("DetectPcreFlowvarCapture02 -- capture for http_header",
3606  DetectPcreFlowvarCapture02);
3607  UtRegisterTest("DetectPcreFlowvarCapture03 -- capture for http_header",
3608  DetectPcreFlowvarCapture03);
3609 
3610  UtRegisterTest("DetectPcreParseHttpHost", DetectPcreParseHttpHost);
3611  UtRegisterTest("DetectPcreParseCaptureTest", DetectPcreParseCaptureTest);
3612 
3613 #endif /* UNITTESTS */
3614 }
3615 
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1439
SignatureInitData * init_data
Definition: detect.h:586
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1179
#define SCLogDebug(...)
Definition: util-debug.h:335
int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, uint8_t *payload, uint32_t payload_len)
Match a regex on a single payload.
Definition: detect-pcre.c:171
#define DETECT_PCRE_RELATIVE
Definition: detect-pcre.h:27
uint16_t value_len
Definition: flow-var.h:39
struct Flow_ * flow
Definition: decode.h:445
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
uint32_t flags
Definition: detect.h:518
uint8_t proto
Definition: flow.h:344
#define SC_MATCH_LIMIT_RECURSION_DEFAULT
Definition: detect-pcre.c:68
int DetectFlowvarPostMatchSetup(Signature *s, uint32_t idx)
Setup a post-match for flowvar storage We&#39;re piggyback riding the DetectFlowvarData struct...
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:243
#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.
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
int UTHAddStreamToFlow(Flow *f, int direction, uint8_t *data, uint32_t data_len)
#define DETECT_PCRE_CASELESS
Definition: detect-pcre.h:29
struct SigMatch_ * prev
Definition: detect.h:318
Signature * sig_list
Definition: detect.h:762
#define MIN(x, y)
uint64_t offset
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
uint32_t capids[DETECT_PCRE_CAPTURE_MAX]
Definition: detect-pcre.h:45
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:203
Data needed for Match()
Definition: detect.h:322
void SigCleanSignatures(DetectEngineCtx *de_ctx)
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:240
uint32_t buffer_offset
Definition: detect.h:1025
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
const char * name
Definition: detect.h:1193
uint16_t AppProto
TCPHdr * tcph
Definition: decode.h:522
Signature container.
Definition: detect.h:517
StreamingBufferSegment sbseg
#define TRUE
HtpBody request_body
#define SIG_FLAG_APPLAYER
Definition: detect.h:214
void SCSigOrderSignatures(DetectEngineCtx *de_ctx)
Orders the signatures.
void * protoctx
Definition: flow.h:400
uint16_t flags
Definition: detect-pcre.h:42
main detection engine ctx
Definition: detect.h:756
FlowVarTypeStr fv_str
Definition: flow-var.h:57
uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
#define SC_MATCH_LIMIT_DEFAULT
Definition: detect-pcre.c:67
void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *de_ctx)
Lets you register the Signature ordering functions. The order in which the functions are registered...
void * alstate
Definition: flow.h:438
#define DE_QUIET
Definition: detect.h:287
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
SigMatch * DetectGetLastSMByListPtr(const Signature *s, SigMatch *sm_list,...)
Returns the sm with the largest index (added last) from the list passed to us as a pointer...
Definition: detect-parse.c:447
int DetectBufferTypeGetByName(const char *name)
#define SCCalloc(nm, a)
Definition: util-mem.h:253
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
void DetectPcreRegister(void)
Definition: detect-pcre.c:86
char * rule_file
Definition: detect.h:860
uint8_t flags
Definition: detect.h:757
pcre_extra * sd
Definition: detect-pcre.h:40
#define PARSE_REGEX
Definition: detect-pcre.c:65
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1184
void AppLayerHtpEnableRequestBodyCallback(void)
Sets a flag that informs the HTP app layer that some module in the engine needs the http request body...
#define DETECT_PCRE_MATCH_LIMIT
Definition: detect-pcre.h:31
int UTHPacketMatchSig(Packet *p, const char *sig)
#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
StreamingBuffer * sb
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
#define MAX_SUBSTRINGS
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1670
void DetectSetupParseRegexes(const char *parse_str, pcre **parse_regex, pcre_extra **parse_regex_study)
void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *de_ctx)
De-registers all the signature ordering functions registered.
#define SIGMATCH_QUOTES_OPTIONAL
Definition: detect.h:1374
#define SCEnter(...)
Definition: util-debug.h:337
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
#define DETECT_SM_LIST_NOTSET
Definition: detect.h:111
uint8_t flowflags
Definition: decode.h:439
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
#define DETECT_PCRE_CAPTURE_MAX
Definition: detect-pcre.h:35
AppProto alproto
Definition: detect.h:521
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1163
int SigGroupCleanup(DetectEngineCtx *de_ctx)
struct Signature_ * next
Definition: detect.h:589
uint8_t type
Definition: detect.h:314
#define DETECT_PCRE_RAWBYTES
Definition: detect-pcre.h:28
#define SCReturnInt(x)
Definition: util-debug.h:341
int UTHRemoveSessionFromFlow(Flow *f)
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
const char * desc
Definition: detect.h:1195
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:288
Signature * SigAlloc(void)
uint8_t * value
Definition: flow-var.h:38
int DetectVarStoreMatch(DetectEngineThreadCtx *det_ctx, uint32_t idx, uint8_t *buffer, uint16_t len, int type)
Store flowvar in det_ctx so we can exec it post-match.
#define FAIL
Definition: util-unittest.h:60
SigMatchCtx * ctx
Definition: detect.h:316
void DetectParseRegexAddToFreeList(pcre *regex, pcre_extra *study)
add regex and/or study to at exit free list
#define SCMalloc(a)
Definition: util-mem.h:222
uint8_t captypes[DETECT_PCRE_CAPTURE_MAX]
Definition: detect-pcre.h:44
union FlowVar_::@116 data
uint16_t payload_len
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index &#39;idx&#39; from the flow
Definition: flow-var.c:78
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:141
#define SCFree(a)
Definition: util-mem.h:322
PoolThreadReserved res
int ConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:437
uint32_t pcre_match_start_offset
Definition: detect.h:1027
int UTHAddSessionToFlow(Flow *f, uint32_t ts_isn, uint32_t tc_isn)
#define DETECT_PCRE_NEGATE
Definition: detect-pcre.h:33
uint32_t VarNameStoreSetupAdd(const char *name, const enum VarTypes type)
add to staging or return existing id if already in there
#define FatalError(x,...)
Definition: util-debug.h:539
#define STREAM_START
Definition: stream.h:29
const char * url
Definition: detect.h:1196
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
#define STREAM_TOSERVER
Definition: stream.h:31
int StreamingBufferSegmentCompareRawData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t *rawdata, uint32_t rawdata_len)
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself...
PacketAlerts alerts
Definition: decode.h:555
#define PKT_HAS_FLOW
Definition: decode.h:1090
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
#define DOC_URL
Definition: suricata.h:86
#define PARSE_CAPTURE_REGEX
Definition: detect-pcre.c:64
#define DETECT_VAR_TYPE_FLOW_POSTMATCH
Definition: detect.h:642
#define DETECT_PCRE_RELATIVE_NEXT
Definition: detect-pcre.h:32
HtpBodyChunk * first
#define pcre_free_study
uint16_t cnt
Definition: decode.h:293
#define DETECT_CONTENT_RELATIVE_NEXT
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:232
uint8_t len
Per thread variable structure.
Definition: threadvars.h:57
AppProto alproto
application level protocol
Definition: flow.h:409
#define PageSupportsRWX()
Definition: util-pages.h:37
uint32_t flags
Definition: decode.h:443
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1382
#define DOC_VERSION
Definition: suricata.h:91
#define DETECT_VAR_TYPE_PKT_POSTMATCH
Definition: detect.h:643
uint16_t flags
Definition: detect.h:1187
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...
Flow data structure.
Definition: flow.h:325
#define FLOW_IPV4
Definition: flow.h:94
int DetectVarStoreMatchKeyValue(DetectEngineThreadCtx *det_ctx, uint8_t *key, uint16_t key_len, uint8_t *buffer, uint16_t len, int type)
Store flowvar in det_ctx so we can exec it post-match.
uint32_t flags
Definition: flow.h:379
#define PKT_STREAM_EST
Definition: decode.h:1088
void(* RegisterTests)(void)
Definition: detect.h:1185
a single match condition for a signature
Definition: detect.h:313
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
SigMatchCtx * ctx
Definition: detect.h:325
void UTHFreeFlow(Flow *flow)
DetectEngineCtx * DetectEngineCtxInit(void)