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  const 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  const 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 
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;
1658  FAIL_IF(de_ctx == NULL);
1659 
1660  de_ctx->flags |= DE_QUIET;
1661 
1662  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;)");
1663  FAIL_IF(de_ctx->sig_list == NULL);
1664 
1665  SigGroupBuild(de_ctx);
1666  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1667 
1668  int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP,
1669  STREAM_TOSERVER | STREAM_START, buf, buflen);
1670  FAIL_IF(r != 0);
1671 
1672  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1673  FAIL_IF_NOT(PacketAlertCheck(p, 1) == 1);
1674 
1675  AppLayerParserThreadCtxFree(alp_tctx);
1676  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1677  DetectEngineCtxFree(de_ctx);
1678 
1680  UTHFreeFlow(f);
1681 
1683  UTHFreePackets(&p, 1);
1684  PASS;
1685 }
1686 
1687 static int DetectPcreTestSig02(void)
1688 {
1689  uint8_t *buf = (uint8_t *)
1690  "GET /one/ HTTP/1.1\r\n"
1691  "Host: one.example.org\r\n"
1692  "\r\n\r\n"
1693  "GET /two/ HTTP/1.1\r\n"
1694  "Host: two.example.org\r\n"
1695  "\r\n\r\n";
1696  uint16_t buflen = strlen((char *)buf);
1697  Packet *p = NULL;
1698  Flow f;
1699  ThreadVars th_v;
1700  DetectEngineThreadCtx *det_ctx;
1701 
1702  memset(&th_v, 0, sizeof(th_v));
1703  memset(&f, 0, sizeof(f));
1704 
1705  FLOW_INITIALIZE(&f);
1706 
1707  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1708  p->flow = &f;
1710 
1711  pcre_match_limit = 100;
1712  pcre_match_limit_recursion = 100;
1713 
1715  FAIL_IF(de_ctx == NULL);
1716 
1717  de_ctx->flags |= DE_QUIET;
1718 
1719  de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; pcre:\"/two/O\"; sid:2;)");
1720  FAIL_IF(de_ctx->sig_list == NULL);
1721 
1722  SigGroupBuild(de_ctx);
1723  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1724 
1725  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1726  FAIL_IF_NOT(PacketAlertCheck(p, 2) == 1);
1727 
1728  SigGroupCleanup(de_ctx);
1729  SigCleanSignatures(de_ctx);
1730 
1731  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1732  DetectEngineCtxFree(de_ctx);
1733  FLOW_DESTROY(&f);
1734 
1735  UTHFreePackets(&p, 1);
1736  PASS;
1737 }
1738 
1739 /**
1740  * \test DetectPcreTestSig03Real negation test ! outside of "" this sig should not match
1741  */
1742 static int DetectPcreTestSig03(void)
1743 {
1744  uint8_t *buf = (uint8_t *)
1745  "GET /one/ HTTP/1.1\r\n"
1746  "Host: one.example.org\r\n"
1747  "\r\n\r\n"
1748  "GET /two/ HTTP/1.1\r\n"
1749  "Host: two.example.org\r\n"
1750  "\r\n\r\n";
1751  uint16_t buflen = strlen((char *)buf);
1752  Packet *p = NULL;
1753  ThreadVars th_v;
1754  DetectEngineThreadCtx *det_ctx;
1755 
1756  memset(&th_v, 0, sizeof(th_v));
1757 
1758  p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1759 
1761  FAIL_IF(de_ctx == NULL);
1762 
1763  de_ctx->flags |= DE_QUIET;
1764 
1765  de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"GET\"; pcre:!\"/two/\"; sid:1;)");
1766  FAIL_IF(de_ctx->sig_list == NULL);
1767 
1768  SigGroupBuild(de_ctx);
1769  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1770 
1771  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1772  FAIL_IF(PacketAlertCheck(p, 1));
1773  SigGroupCleanup(de_ctx);
1774  SigCleanSignatures(de_ctx);
1775 
1776  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1777  DetectEngineCtxFree(de_ctx);
1778 
1779  UTHFreePackets(&p, 1);
1780  PASS;
1781 }
1782 
1783 /**
1784  * \test Check the signature with pcre modifier P (match with L7 to http body data)
1785  */
1786 static int DetectPcreModifPTest04(void)
1787 {
1788  uint8_t httpbuf1[] =
1789  "GET / HTTP/1.1\r\n"
1790  "Host: www.emergingthreats.net\r\n"
1791  "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"
1792  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8\r\n"
1793  "Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
1794  "Accept-Encoding: gzip,deflate\r\n"
1795  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
1796  "Date: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
1797  "Server: Apache\r\n"
1798  "X-Powered-By: PHP/5.2.5\r\n"
1799  "P3P: CP=\"NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM\"\r\n"
1800  "Expires: Mon, 1 Jan 2001 00:00:00 GMT\r\n"
1801  "Last-Modified: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
1802  "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n"
1803  "Pragma: no-cache\r\n"
1804  "Keep-Alive: timeout=15, max=100\r\n"
1805  "Connection: Keep-Alive\r\n"
1806  "Transfer-Encoding: chunked\r\n"
1807  "Content-Type: text/html; charset=utf-8\r\n"
1808  "\r\n"
1809  "15"
1810  "\r\n"
1811  "<!DOCTYPE html PUBLIC\r\n"
1812  "0\r\n\r\n";
1813 
1814  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1815  TcpSession ssn;
1816  Packet *p = NULL;
1817  Flow f;
1818  Signature *s = NULL;
1819  ThreadVars th_v;
1820  DetectEngineThreadCtx *det_ctx;
1822 
1823  memset(&th_v, 0, sizeof(th_v));
1824  memset(&f, 0, sizeof(f));
1825  memset(&ssn, 0, sizeof(ssn));
1826 
1827  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1828 
1829  FLOW_INITIALIZE(&f);
1830  f.protoctx = (void *)&ssn;
1831  f.proto = IPPROTO_TCP;
1832  f.flags |= FLOW_IPV4;
1833 
1834  p->flow = &f;
1838  f.alproto = ALPROTO_HTTP;
1839 
1841 
1843  FAIL_IF(de_ctx == NULL);
1844 
1845  de_ctx->flags |= DE_QUIET;
1846 
1847  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
1848  "\"Pcre modifier P\"; pcre:\"/DOCTYPE/P\"; "
1849  "sid:1;)");
1850  FAIL_IF(s == NULL);
1851 
1852  s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\""
1853  "Pcre modifier P (no match)\"; pcre:\"/blah/P\"; sid:2;)");
1854  FAIL_IF(s->next == NULL);
1855 
1856  SigGroupBuild(de_ctx);
1857  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1858 
1859  FLOWLOCK_WRLOCK(&f);
1860  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1861  STREAM_TOSERVER, httpbuf1, httplen1);
1862  FAIL_IF(r != 0);
1863  FLOWLOCK_UNLOCK(&f);
1864 
1865  HtpState *http_state = f.alstate;
1866  FAIL_IF(http_state == NULL);
1867 
1868  /* do detect */
1869  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1870 
1871  FAIL_IF(!(PacketAlertCheck(p, 1)));
1872  FAIL_IF(PacketAlertCheck(p, 2));
1873 
1874  if (alp_tctx != NULL)
1875  AppLayerParserThreadCtxFree(alp_tctx);
1876  if (de_ctx != NULL) SigGroupCleanup(de_ctx);
1877  if (de_ctx != NULL) SigCleanSignatures(de_ctx);
1878  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
1879 
1881  FLOW_DESTROY(&f);
1882  UTHFreePackets(&p, 1);
1883  PASS;
1884 }
1885 
1886 /**
1887  * \test Check the signature with pcre modifier P (match with L7 to http body data)
1888  * over fragmented chunks (DOCTYPE fragmented)
1889  */
1890 static int DetectPcreModifPTest05(void)
1891 {
1892  uint8_t httpbuf1[] =
1893  "GET / HTTP/1.1\r\n"
1894  "Host: www.emergingthreats.net\r\n"
1895  "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"
1896  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8\r\n"
1897  "Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
1898  "Accept-Encoding: gzip,deflate\r\n"
1899  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
1900  "Date: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
1901  "Server: Apache\r\n"
1902  "X-Powered-By: PHP/5.2.5\r\n"
1903  "P3P: CP=\"NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM\"\r\n"
1904  "Expires: Mon, 1 Jan 2001 00:00:00 GMT\r\n"
1905  "Last-Modified: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
1906  "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n"
1907  "Pragma: no-cache\r\n"
1908  "Keep-Alive: timeout=15, max=100\r\n"
1909  "Connection: Keep-Alive\r\n"
1910  "Transfer-Encoding: chunked\r\n"
1911  "Content-Type: text/html; charset=utf-8\r\n"
1912  "\r\n"
1913  "15"
1914  "\r\n"
1915  "<!DOC";
1916 
1917  uint8_t httpbuf2[] = "<!DOCTYPE html PUBLIC\r\n0\r\n\r\n";
1918 
1919  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1920  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1921  TcpSession ssn;
1922  Packet *p1 = NULL;
1923  Packet *p2 = NULL;
1924  Flow f;
1925  Signature *s = NULL;
1926  ThreadVars th_v;
1927  DetectEngineThreadCtx *det_ctx;
1929 
1930  memset(&th_v, 0, sizeof(th_v));
1931  memset(&f, 0, sizeof(f));
1932  memset(&ssn, 0, sizeof(ssn));
1933 
1934  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1935  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1936 
1937  FLOW_INITIALIZE(&f);
1938  f.protoctx = (void *)&ssn;
1939  f.proto = IPPROTO_TCP;
1940  f.flags |= FLOW_IPV4;
1941 
1942  p1->flow = &f;
1946  p2->flow = &f;
1950  f.alproto = ALPROTO_HTTP;
1951 
1953 
1955  FAIL_IF(de_ctx == NULL);
1956 
1957  de_ctx->flags |= DE_QUIET;
1958 
1959  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
1960  "\"Pcre modifier P\"; pcre:\"/DOC/P\"; "
1961  "sid:1;)");
1962  FAIL_IF(s == NULL);
1963 
1964  s->next = SigInit(de_ctx,"alert http any any -> any any (msg:\""
1965  "Pcre modifier P (no match)\"; pcre:\"/DOCTYPE/P\"; sid:2;)");
1966  FAIL_IF(s->next == NULL);
1967 
1968  SigGroupBuild(de_ctx);
1969  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1970 
1971  FLOWLOCK_WRLOCK(&f);
1972  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1973  STREAM_TOSERVER, httpbuf1, httplen1);
1974  FAIL_IF(r != 0);
1975  FLOWLOCK_UNLOCK(&f);
1976 
1977  /* do detect for p1 */
1978  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1979 
1980  HtpState *http_state = f.alstate;
1981  FAIL_IF(http_state == NULL);
1982 
1983  FAIL_IF(PacketAlertCheck(p1, 1));
1984 
1985  FAIL_IF(PacketAlertCheck(p1, 2));
1986 
1987  FLOWLOCK_WRLOCK(&f);
1988  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1989  STREAM_TOSERVER, httpbuf2, httplen2);
1990  FAIL_IF(r != 0);
1991  FLOWLOCK_UNLOCK(&f);
1992 
1993  /* do detect for p2 */
1994  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1995 
1996  FAIL_IF(!(PacketAlertCheck(p2, 1)));
1997 
1998  FAIL_IF(!(PacketAlertCheck(p2, 2)));
1999 
2000  if (alp_tctx != NULL)
2001  AppLayerParserThreadCtxFree(alp_tctx);
2002  if (de_ctx != NULL) SigGroupCleanup(de_ctx);
2003  if (de_ctx != NULL) SigCleanSignatures(de_ctx);
2004  if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2005 
2007  FLOW_DESTROY(&f);
2008  UTHFreePackets(&p1, 1);
2009  UTHFreePackets(&p2, 1);
2010  PASS;
2011 }
2012 
2013 static int DetectPcreTestSig06(void)
2014 {
2015  uint8_t *buf = (uint8_t *)
2016  "lalala lalala\\ lala\n";
2017  uint16_t buflen = strlen((char *)buf);
2018  Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
2019  int result = 0;
2020 
2021  char sig[] = "alert tcp any any -> any any (msg:\"pcre with an ending slash\"; pcre:\"/ lalala\\\\/\"; sid:1;)";
2022  if (UTHPacketMatchSig(p, sig) == 0) {
2023  result = 0;
2024  goto end;
2025  }
2026  result = 1;
2027 end:
2028  if (p != NULL)
2029  UTHFreePacket(p);
2030  return result;
2031 }
2032 
2033 /** \test anchored pcre */
2034 static int DetectPcreTestSig07(void)
2035 {
2036  uint8_t *buf = (uint8_t *)
2037  "lalala\n";
2038  uint16_t buflen = strlen((char *)buf);
2039  Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
2040 
2041  char sig[] = "alert tcp any any -> any any (msg:\"pcre with an ending slash\"; pcre:\"/^(la)+$/\"; sid:1;)";
2042  FAIL_IF(UTHPacketMatchSig(p, sig) == 0);
2043 
2044  if (p != NULL)
2045  UTHFreePacket(p);
2046  PASS;
2047 }
2048 
2049 /** \test anchored pcre */
2050 static int DetectPcreTestSig08(void)
2051 {
2052  /* test it also without ending in a newline "\n" */
2053  uint8_t *buf = (uint8_t *)
2054  "lalala";
2055  uint16_t buflen = strlen((char *)buf);
2056  Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
2057 
2058  char sig[] = "alert tcp any any -> any any (msg:\"pcre with an ending slash\"; pcre:\"/^(la)+$/\"; sid:1;)";
2059  FAIL_IF(UTHPacketMatchSig(p, sig) == 0);
2060 
2061  if (p != NULL)
2062  UTHFreePacket(p);
2063  PASS;
2064 }
2065 
2066 /** \test Check the signature working to alert when cookie modifier is
2067  * passed to pcre
2068  */
2069 static int DetectPcreTestSig09(void)
2070 {
2071  Flow f;
2072  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2073  "Cookie: dummy\r\n\r\n";
2074  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2075  TcpSession ssn;
2076  Packet *p = NULL;
2077  Signature *s = NULL;
2078  ThreadVars th_v;
2079  DetectEngineThreadCtx *det_ctx = NULL;
2080  HtpState *http_state = NULL;
2082 
2083  memset(&th_v, 0, sizeof(th_v));
2084  memset(&p, 0, sizeof(p));
2085  memset(&f, 0, sizeof(f));
2086  memset(&ssn, 0, sizeof(ssn));
2087 
2088  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2089 
2090  FLOW_INITIALIZE(&f);
2091  f.protoctx = (void *)&ssn;
2092  f.proto = IPPROTO_TCP;
2093  f.flags |= FLOW_IPV4;
2094 
2095  p->flow = &f;
2099  f.alproto = ALPROTO_HTTP;
2100 
2102 
2104  FAIL_IF(de_ctx == NULL);
2105 
2106  de_ctx->flags |= DE_QUIET;
2107 
2108  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2109  "\"HTTP cookie\"; pcre:\"/dummy/C\"; "
2110  " sid:1;)");
2111  FAIL_IF(s == NULL);
2112 
2113  SigGroupBuild(de_ctx);
2114  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2115 
2116  FLOWLOCK_WRLOCK(&f);
2117  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2118  STREAM_TOSERVER, httpbuf1, httplen1);
2119  FAIL_IF(r != 0);
2120  FLOWLOCK_UNLOCK(&f);
2121 
2122  http_state = f.alstate;
2123  FAIL_IF(http_state == NULL);
2124 
2125  /* do detect */
2126  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2127 
2128  FAIL_IF(!PacketAlertCheck(p, 1));
2129 
2130  if (alp_tctx != NULL)
2131  AppLayerParserThreadCtxFree(alp_tctx);
2132  if (det_ctx != NULL) {
2133  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2134  }
2135  if (de_ctx != NULL) {
2136  SigGroupCleanup(de_ctx);
2137  DetectEngineCtxFree(de_ctx);
2138  }
2139 
2141  UTHFreePackets(&p, 1);
2142  PASS;
2143 }
2144 
2145 /** \test Check the signature working to alert when cookie modifier is
2146  * passed to a negated pcre
2147  */
2148 static int DetectPcreTestSig10(void)
2149 {
2150  Flow f;
2151  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2152  "Cookie: dummoOOooooO\r\n\r\n";
2153  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2154  TcpSession ssn;
2155  Packet *p = NULL;
2156  Signature *s = NULL;
2157  ThreadVars th_v;
2158  DetectEngineThreadCtx *det_ctx = NULL;
2159  HtpState *http_state = NULL;
2161 
2162  memset(&th_v, 0, sizeof(th_v));
2163  memset(&p, 0, sizeof(p));
2164  memset(&f, 0, sizeof(f));
2165  memset(&ssn, 0, sizeof(ssn));
2166 
2167  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2168 
2169  FLOW_INITIALIZE(&f);
2170  f.protoctx = (void *)&ssn;
2171  f.proto = IPPROTO_TCP;
2172  f.flags |= FLOW_IPV4;
2173 
2174  p->flow = &f;
2178  f.alproto = ALPROTO_HTTP;
2179 
2181 
2183  FAIL_IF(de_ctx == NULL);
2184 
2185  de_ctx->flags |= DE_QUIET;
2186 
2187  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2188  "\"HTTP cookie\"; pcre:!\"/dummy/C\"; "
2189  " sid:1;)");
2190  FAIL_IF(s == NULL);
2191 
2192  SigGroupBuild(de_ctx);
2193  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2194 
2195  FLOWLOCK_WRLOCK(&f);
2196  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2197  STREAM_TOSERVER, httpbuf1, httplen1);
2198  FAIL_IF(r != 0);
2199  FLOWLOCK_UNLOCK(&f);
2200 
2201  http_state = f.alstate;
2202  FAIL_IF(http_state == NULL);
2203 
2204  /* do detect */
2205  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2206 
2207  FAIL_IF(!PacketAlertCheck(p, 1));
2208 
2209  if (alp_tctx != NULL)
2210  AppLayerParserThreadCtxFree(alp_tctx);
2211  if (det_ctx != NULL) {
2212  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2213  }
2214  if (de_ctx != NULL) {
2215  SigGroupCleanup(de_ctx);
2216  DetectEngineCtxFree(de_ctx);
2217  }
2218 
2220  UTHFreePackets(&p, 1);
2221  PASS;
2222 }
2223 
2224 /** \test Check the signature working to alert when method modifier is
2225  * passed to pcre
2226  */
2227 static int DetectPcreTestSig11(void)
2228 {
2229  Flow f;
2230  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2231  "Cookie: dummy\r\n\r\n";
2232  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2233  TcpSession ssn;
2234  Packet *p = NULL;
2235  Signature *s = NULL;
2236  ThreadVars th_v;
2237  DetectEngineThreadCtx *det_ctx = NULL;
2238  HtpState *http_state = NULL;
2240 
2241  memset(&th_v, 0, sizeof(th_v));
2242  memset(&p, 0, sizeof(p));
2243  memset(&f, 0, sizeof(f));
2244  memset(&ssn, 0, sizeof(ssn));
2245 
2246  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2247 
2248  FLOW_INITIALIZE(&f);
2249  f.protoctx = (void *)&ssn;
2250  f.proto = IPPROTO_TCP;
2251  f.flags |= FLOW_IPV4;
2252 
2253  p->flow = &f;
2257  f.alproto = ALPROTO_HTTP;
2258 
2260 
2262  FAIL_IF(de_ctx == NULL);
2263 
2264  de_ctx->flags |= DE_QUIET;
2265 
2266  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2267  "\"HTTP method\"; pcre:\"/POST/M\"; "
2268  " sid:1;)");
2269  FAIL_IF(s == NULL);
2270 
2271  SigGroupBuild(de_ctx);
2272  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2273 
2274  FLOWLOCK_WRLOCK(&f);
2275  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2276  STREAM_TOSERVER, httpbuf1, httplen1);
2277  FAIL_IF(r != 0);
2278  FLOWLOCK_UNLOCK(&f);
2279 
2280  http_state = f.alstate;
2281  FAIL_IF(http_state == NULL);
2282 
2283  /* do detect */
2284  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2285 
2286  FAIL_IF(!PacketAlertCheck(p, 1));
2287 
2288  if (alp_tctx != NULL)
2289  AppLayerParserThreadCtxFree(alp_tctx);
2290  if (det_ctx != NULL) {
2291  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2292  }
2293  if (de_ctx != NULL) {
2294  SigGroupCleanup(de_ctx);
2295  DetectEngineCtxFree(de_ctx);
2296  }
2297 
2299  UTHFreePackets(&p, 1);
2300  PASS;
2301 }
2302 
2303 /** \test Check the signature working to alert when method modifier is
2304  * passed to a negated pcre
2305  */
2306 static int DetectPcreTestSig12(void)
2307 {
2308  Flow f;
2309  uint8_t httpbuf1[] = "GET / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2310  "Cookie: dummoOOooooO\r\n\r\n";
2311  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2312  TcpSession ssn;
2313  Packet *p = NULL;
2314  Signature *s = NULL;
2315  ThreadVars th_v;
2316  DetectEngineThreadCtx *det_ctx = NULL;
2317  HtpState *http_state = NULL;
2319 
2320  memset(&th_v, 0, sizeof(th_v));
2321  memset(&p, 0, sizeof(p));
2322  memset(&f, 0, sizeof(f));
2323  memset(&ssn, 0, sizeof(ssn));
2324 
2325  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2326 
2327  FLOW_INITIALIZE(&f);
2328  f.protoctx = (void *)&ssn;
2329  f.proto = IPPROTO_TCP;
2330  f.flags |= FLOW_IPV4;
2331 
2332  p->flow = &f;
2336  f.alproto = ALPROTO_HTTP;
2337 
2339 
2341  FAIL_IF(de_ctx == NULL);
2342 
2343  de_ctx->flags |= DE_QUIET;
2344 
2345  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2346  "\"HTTP method\"; pcre:!\"/POST/M\"; "
2347  " sid:1;)");
2348  FAIL_IF(s == NULL);
2349 
2350  SigGroupBuild(de_ctx);
2351  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2352 
2353  FLOWLOCK_WRLOCK(&f);
2354  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2355  STREAM_TOSERVER, httpbuf1, httplen1);
2356  FAIL_IF(r != 0);
2357  FLOWLOCK_UNLOCK(&f);
2358 
2359  http_state = f.alstate;
2360  FAIL_IF(http_state == NULL);
2361 
2362  /* do detect */
2363  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2364 
2365  FAIL_IF(!PacketAlertCheck(p, 1));
2366 
2367  if (alp_tctx != NULL)
2368  AppLayerParserThreadCtxFree(alp_tctx);
2369  if (det_ctx != NULL) {
2370  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2371  }
2372  if (de_ctx != NULL) {
2373  SigGroupCleanup(de_ctx);
2374  DetectEngineCtxFree(de_ctx);
2375  }
2376 
2378  UTHFreePackets(&p, 1);
2379  PASS;
2380 }
2381 
2382 /** \test Check the signature working to alert when header modifier is
2383  * passed to pcre
2384  */
2385 static int DetectPcreTestSig13(void)
2386 {
2387  Flow f;
2388  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2389  "Cookie: dummy\r\n\r\n";
2390  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2391  TcpSession ssn;
2392  Packet *p = NULL;
2393  Signature *s = NULL;
2394  ThreadVars th_v;
2395  DetectEngineThreadCtx *det_ctx = NULL;
2396  HtpState *http_state = NULL;
2398 
2399  memset(&th_v, 0, sizeof(th_v));
2400  memset(&p, 0, sizeof(p));
2401  memset(&f, 0, sizeof(f));
2402  memset(&ssn, 0, sizeof(ssn));
2403 
2404  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2405 
2406  FLOW_INITIALIZE(&f);
2407  f.protoctx = (void *)&ssn;
2408  f.proto = IPPROTO_TCP;
2409  f.flags |= FLOW_IPV4;
2410 
2411  p->flow = &f;
2415  f.alproto = ALPROTO_HTTP;
2416 
2418 
2420  FAIL_IF(de_ctx == NULL);
2421 
2422  de_ctx->flags |= DE_QUIET;
2423 
2424  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2425  "\"HTTP header\"; pcre:\"/User[-_]Agent[:]?\\sMozilla/H\"; "
2426  " sid:1;)");
2427  FAIL_IF(s == NULL);
2428 
2429  SigGroupBuild(de_ctx);
2430  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2431 
2432  FLOWLOCK_WRLOCK(&f);
2433  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2434  STREAM_TOSERVER, httpbuf1, httplen1);
2435  FAIL_IF(r != 0);
2436  FLOWLOCK_UNLOCK(&f);
2437 
2438  http_state = f.alstate;
2439  FAIL_IF(http_state == NULL);
2440 
2441  /* do detect */
2442  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2443 
2444  FAIL_IF(!PacketAlertCheck(p, 1));
2445 
2446  if (alp_tctx != NULL)
2447  AppLayerParserThreadCtxFree(alp_tctx);
2448  if (det_ctx != NULL) {
2449  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2450  }
2451  if (de_ctx != NULL) {
2452  SigGroupCleanup(de_ctx);
2453  DetectEngineCtxFree(de_ctx);
2454  }
2455 
2457  UTHFreePackets(&p, 1);
2458  PASS;
2459 }
2460 
2461 /** \test Check the signature working to alert when header modifier is
2462  * passed to a negated pcre
2463  */
2464 static int DetectPcreTestSig14(void)
2465 {
2466  Flow f;
2467  uint8_t httpbuf1[] = "GET / HTTP/1.0\r\nUser-Agent: IEXPLORER/1.0\r\n"
2468  "Cookie: dummoOOooooO\r\n\r\n";
2469  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2470  TcpSession ssn;
2471  Packet *p = NULL;
2472  Signature *s = NULL;
2473  ThreadVars th_v;
2474  DetectEngineThreadCtx *det_ctx = NULL;
2475  HtpState *http_state = NULL;
2477 
2478  memset(&th_v, 0, sizeof(th_v));
2479  memset(&p, 0, sizeof(p));
2480  memset(&f, 0, sizeof(f));
2481  memset(&ssn, 0, sizeof(ssn));
2482 
2483  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2484 
2485  FLOW_INITIALIZE(&f);
2486  f.protoctx = (void *)&ssn;
2487  f.proto = IPPROTO_TCP;
2488  f.flags |= FLOW_IPV4;
2489 
2490  p->flow = &f;
2494  f.alproto = ALPROTO_HTTP;
2495 
2497 
2499  FAIL_IF(de_ctx == NULL);
2500 
2501  de_ctx->flags |= DE_QUIET;
2502 
2503  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2504  "\"HTTP header\"; pcre:!\"/User-Agent[:]?\\s+Mozilla/H\"; "
2505  " sid:1;)");
2506  FAIL_IF(s == NULL);
2507 
2508  SigGroupBuild(de_ctx);
2509  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2510 
2511  FLOWLOCK_WRLOCK(&f);
2512  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2513  STREAM_TOSERVER, httpbuf1, httplen1);
2514  FAIL_IF(r != 0);
2515  FLOWLOCK_UNLOCK(&f);
2516 
2517  http_state = f.alstate;
2518  FAIL_IF(http_state == NULL);
2519 
2520  /* do detect */
2521  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2522 
2523  FAIL_IF(!PacketAlertCheck(p, 1));
2524 
2525  if (alp_tctx != NULL)
2526  AppLayerParserThreadCtxFree(alp_tctx);
2527  if (det_ctx != NULL) {
2528  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2529  }
2530  if (de_ctx != NULL) {
2531  SigGroupCleanup(de_ctx);
2532  DetectEngineCtxFree(de_ctx);
2533  }
2534 
2536  UTHFreePackets(&p, 1);
2537  PASS;
2538 }
2539 
2540 /** \test Check the signature working to alert when cookie and relative modifiers are
2541  * passed to pcre
2542  */
2543 static int DetectPcreTestSig15(void)
2544 {
2545  Flow f;
2546  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2547  "Cookie: dummy 1234\r\n\r\n";
2548  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2549  TcpSession ssn;
2550  Packet *p = NULL;
2551  Signature *s = NULL;
2552  ThreadVars th_v;
2553  DetectEngineThreadCtx *det_ctx = NULL;
2554  HtpState *http_state = NULL;
2556 
2557  memset(&th_v, 0, sizeof(th_v));
2558  memset(&p, 0, sizeof(p));
2559  memset(&f, 0, sizeof(f));
2560  memset(&ssn, 0, sizeof(ssn));
2561 
2562  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2563 
2564  FLOW_INITIALIZE(&f);
2565  f.protoctx = (void *)&ssn;
2566  f.proto = IPPROTO_TCP;
2567  f.flags |= FLOW_IPV4;
2568 
2569  p->flow = &f;
2573  f.alproto = ALPROTO_HTTP;
2574 
2576 
2578  FAIL_IF(de_ctx == NULL);
2579 
2580  de_ctx->flags |= DE_QUIET;
2581 
2582  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2583  "\"pcre relative HTTP cookie\"; content:\"dummy\";"
2584  " http_cookie; pcre:\"/1234/RC\"; "
2585  " sid:1;)");
2586  FAIL_IF(s == NULL);
2587 
2588  SigGroupBuild(de_ctx);
2589  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2590 
2591  FLOWLOCK_WRLOCK(&f);
2592  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2593  STREAM_TOSERVER, httpbuf1, httplen1);
2594  FAIL_IF(r != 0);
2595  FLOWLOCK_UNLOCK(&f);
2596 
2597  http_state = f.alstate;
2598  FAIL_IF(http_state == NULL);
2599 
2600  /* do detect */
2601  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2602 
2603  FAIL_IF(!PacketAlertCheck(p, 1));
2604 
2605  if (alp_tctx != NULL)
2606  AppLayerParserThreadCtxFree(alp_tctx);
2607  if (det_ctx != NULL) {
2608  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2609  }
2610  if (de_ctx != NULL) {
2611  SigGroupCleanup(de_ctx);
2612  DetectEngineCtxFree(de_ctx);
2613  }
2614 
2616  UTHFreePackets(&p, 1);
2617  PASS;
2618 }
2619 
2620 /** \test Check the signature working to alert when method and relative modifiers are
2621  * passed to pcre
2622  */
2623 static int DetectPcreTestSig16(void)
2624 {
2625  Flow f;
2626  uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Mozilla/1.0\r\n"
2627  "Cookie: dummy 1234\r\n\r\n";
2628  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2629  TcpSession ssn;
2630  Packet *p = NULL;
2631  Signature *s = NULL;
2632  ThreadVars th_v;
2633  DetectEngineThreadCtx *det_ctx = NULL;
2634  HtpState *http_state = NULL;
2636 
2637  memset(&th_v, 0, sizeof(th_v));
2638  memset(&p, 0, sizeof(p));
2639  memset(&f, 0, sizeof(f));
2640  memset(&ssn, 0, sizeof(ssn));
2641 
2642  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2643 
2644  FLOW_INITIALIZE(&f);
2645  f.protoctx = (void *)&ssn;
2646  f.proto = IPPROTO_TCP;
2647  f.flags |= FLOW_IPV4;
2648 
2649  p->flow = &f;
2653  f.alproto = ALPROTO_HTTP;
2654 
2656 
2658  FAIL_IF(de_ctx == NULL);
2659 
2660  de_ctx->flags |= DE_QUIET;
2661 
2662  s = de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any (msg:"
2663  "\"pcre relative HTTP method\"; content:\"PO\";"
2664  " http_method; pcre:\"/ST/RM\"; "
2665  " sid:1;)");
2666  FAIL_IF(s == NULL);
2667 
2668  SigGroupBuild(de_ctx);
2669  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2670 
2671  FLOWLOCK_WRLOCK(&f);
2672  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2673  STREAM_TOSERVER, httpbuf1, httplen1);
2674  FAIL_IF(r != 0);
2675  FLOWLOCK_UNLOCK(&f);
2676 
2677  http_state = f.alstate;
2678  FAIL_IF(http_state == NULL);
2679 
2680  /* do detect */
2681  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2682 
2683  FAIL_IF(!PacketAlertCheck(p, 1));
2684 
2685  if (alp_tctx != NULL)
2686  AppLayerParserThreadCtxFree(alp_tctx);
2687  if (det_ctx != NULL) {
2688  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2689  }
2690  if (de_ctx != NULL) {
2691  SigGroupCleanup(de_ctx);
2692  DetectEngineCtxFree(de_ctx);
2693  }
2694 
2696  UTHFreePackets(&p, 1);
2697  PASS;
2698 }
2699 
2700 /** \test Test tracking of body chunks per transactions (on requests)
2701  */
2702 static int DetectPcreTxBodyChunksTest01(void)
2703 {
2704  Flow f;
2705  TcpSession ssn;
2706  Packet *p = NULL;
2707  uint8_t httpbuf1[] = "GET / HTTP/1.1\r\n";
2708  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
2709  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
2710  uint8_t httpbuf4[] = "Body one!!";
2711  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2712  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2713  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
2714  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
2715  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
2716  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
2717  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
2718  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
2719  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
2720  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
2722 
2723  memset(&f, 0, sizeof(f));
2724  memset(&ssn, 0, sizeof(ssn));
2725 
2726  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2727 
2728  FLOW_INITIALIZE(&f);
2729  f.protoctx = (void *)&ssn;
2730  f.proto = IPPROTO_TCP;
2731  f.flags |= FLOW_IPV4;
2732 
2733  p->flow = &f;
2737  f.alproto = ALPROTO_HTTP;
2738 
2740 
2742 
2743  FLOWLOCK_WRLOCK(&f);
2744  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2745  STREAM_TOSERVER | STREAM_START, httpbuf1,
2746  httplen1);
2747  FAIL_IF(r != 0);
2748 
2749  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2750  STREAM_TOSERVER, httpbuf2, httplen2);
2751  FAIL_IF(r != 0);
2752 
2753  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2754  STREAM_TOSERVER, httpbuf3, httplen3);
2755  FAIL_IF(r != 0);
2756 
2757  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2758  STREAM_TOSERVER, httpbuf4, httplen4);
2759  FAIL_IF(r != 0);
2760 
2761  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2762  STREAM_TOSERVER, httpbuf5, httplen5);
2763  FAIL_IF(r != 0);
2764 
2765  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2766  STREAM_TOSERVER, httpbuf6, httplen6);
2767  FAIL_IF(r != 0);
2768 
2769  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2770  STREAM_TOSERVER, httpbuf7, httplen7);
2771  FAIL_IF(r != 0);
2772 
2773  /* Now we should have 2 transactions, each with it's own list
2774  * of request body chunks (let's test it) */
2775 
2776  HtpState *htp_state = f.alstate;
2777  FAIL_IF(htp_state == NULL);
2778 
2779  /* hardcoded check of the transactions and it's client body chunks */
2780  FAIL_IF(AppLayerParserGetTxCnt(&f, htp_state) != 2);
2781 
2782  htp_tx_t *t1 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, 0);
2783  htp_tx_t *t2 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, 1);
2784 
2785  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
2786  FAIL_IF(htud == NULL);
2787 
2788  HtpBodyChunk *cur = htud->request_body.first;
2789  FAIL_IF(htud->request_body.first == NULL);
2790 
2791  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body one!!", 10) != 1);
2792 
2793  htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
2794 
2795  cur = htud->request_body.first;
2796  FAIL_IF(htud->request_body.first == NULL);
2797 
2798  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body two!!", 10) != 1);
2799 
2800  if (alp_tctx != NULL)
2801  AppLayerParserThreadCtxFree(alp_tctx);
2802  FLOWLOCK_UNLOCK(&f);
2804  FLOW_DESTROY(&f);
2805  UTHFreePacket(p);
2806  PASS;
2807 }
2808 
2809 /** \test test pcre P modifier with multiple pipelined http transactions */
2810 static int DetectPcreTxBodyChunksTest02(void)
2811 {
2812  Signature *s = NULL;
2813  DetectEngineThreadCtx *det_ctx = NULL;
2814  ThreadVars th_v;
2815  Flow f;
2816  TcpSession ssn;
2817  Packet *p = NULL;
2818  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
2819  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
2820  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
2821  uint8_t httpbuf4[] = "Body one!!";
2822  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2823  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2824  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
2825  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
2826  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
2827  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
2828  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
2829  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
2830  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
2831  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
2833 
2834  memset(&th_v, 0, sizeof(th_v));
2835  memset(&f, 0, sizeof(f));
2836  memset(&ssn, 0, sizeof(ssn));
2837 
2838  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2839 
2840  FLOW_INITIALIZE(&f);
2841  f.protoctx = (void *)&ssn;
2842  f.proto = IPPROTO_TCP;
2843  f.flags |= FLOW_IPV4;
2844 
2845  p->flow = &f;
2849  f.alproto = ALPROTO_HTTP;
2850 
2852 
2854  FAIL_IF(de_ctx == NULL);
2855 
2856  de_ctx->flags |= DE_QUIET;
2857 
2858  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;)");
2859  FAIL_IF(s == NULL);
2860  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;)");
2861  FAIL_IF(s == NULL);
2862 
2863  SigGroupBuild(de_ctx);
2864  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2865 
2866  FLOWLOCK_WRLOCK(&f);
2867  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2868  STREAM_TOSERVER, httpbuf1, httplen1);
2869  FAIL_IF(r != 0);
2870  FLOWLOCK_UNLOCK(&f);
2871 
2872  /* do detect */
2873  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2874  FAIL_IF(PacketAlertCheck(p, 1));
2875  p->alerts.cnt = 0;
2876 
2877  FLOWLOCK_WRLOCK(&f);
2878  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2879  STREAM_TOSERVER, httpbuf2, httplen2);
2880  FAIL_IF(r != 0);
2881  FLOWLOCK_UNLOCK(&f);
2882 
2883  /* do detect */
2884  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2885  FAIL_IF(PacketAlertCheck(p, 1));
2886  p->alerts.cnt = 0;
2887 
2888  FLOWLOCK_WRLOCK(&f);
2889  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2890  STREAM_TOSERVER, httpbuf3, httplen3);
2891  FAIL_IF(r != 0);
2892  FLOWLOCK_UNLOCK(&f);
2893 
2894  /* do detect */
2895  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2896  FAIL_IF(PacketAlertCheck(p, 1));
2897  p->alerts.cnt = 0;
2898 
2899  FLOWLOCK_WRLOCK(&f);
2900  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2901  STREAM_TOSERVER, httpbuf4, httplen4);
2902  FAIL_IF(r != 0);
2903  FLOWLOCK_UNLOCK(&f);
2904 
2905  /* do detect */
2906  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2907  FAIL_IF(!(PacketAlertCheck(p, 1)));
2908  p->alerts.cnt = 0;
2909 
2910  FLOWLOCK_WRLOCK(&f);
2911  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2912  STREAM_TOSERVER, httpbuf5, httplen5);
2913  FAIL_IF(r != 0);
2914  FLOWLOCK_UNLOCK(&f);
2915 
2916  /* do detect */
2917  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2918  FAIL_IF(PacketAlertCheck(p, 1));
2919  p->alerts.cnt = 0;
2920 
2921  FLOWLOCK_WRLOCK(&f);
2922  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2923  STREAM_TOSERVER, httpbuf6, httplen6);
2924  FAIL_IF(r != 0);
2925  FLOWLOCK_UNLOCK(&f);
2926 
2927  /* do detect */
2928  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2929  FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
2930  p->alerts.cnt = 0;
2931 
2932  SCLogDebug("sending data chunk 7");
2933 
2934  FLOWLOCK_WRLOCK(&f);
2935  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
2936  STREAM_TOSERVER, httpbuf7, httplen7);
2937  FAIL_IF(r != 0);
2938  FLOWLOCK_UNLOCK(&f);
2939 
2940  /* do detect */
2941  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2942  FAIL_IF(!(PacketAlertCheck(p, 2)));
2943  p->alerts.cnt = 0;
2944 
2945  HtpState *htp_state = f.alstate;
2946  FAIL_IF(htp_state == NULL);
2947 
2948  /* hardcoded check of the transactions and it's client body chunks */
2949  FAIL_IF(AppLayerParserGetTxCnt(&f, htp_state) != 2);
2950 
2951  htp_tx_t *t1 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, 0);
2952  htp_tx_t *t2 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, 1);
2953 
2954  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
2955 
2956  HtpBodyChunk *cur = htud->request_body.first;
2957  FAIL_IF(htud->request_body.first == NULL);
2958 
2959  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body one!!", 10) != 1);
2960 
2961  htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
2962 
2963  cur = htud->request_body.first;
2964  FAIL_IF(htud->request_body.first == NULL);
2965 
2966  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body two!!", 10) != 1);
2967 
2968  if (alp_tctx != NULL)
2969  AppLayerParserThreadCtxFree(alp_tctx);
2970  if (det_ctx != NULL) {
2971  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2972  }
2973  if (de_ctx != NULL) {
2974  SigGroupCleanup(de_ctx);
2975  DetectEngineCtxFree(de_ctx);
2976  }
2977 
2979  FLOW_DESTROY(&f);
2980  UTHFreePacket(p);
2981  PASS;
2982 }
2983 
2984 /** \test multiple http transactions and body chunks of request handling */
2985 static int DetectPcreTxBodyChunksTest03(void)
2986 {
2987  Signature *s = NULL;
2988  DetectEngineThreadCtx *det_ctx = NULL;
2989  ThreadVars th_v;
2990  Flow f;
2991  TcpSession ssn;
2992  Packet *p = NULL;
2993  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
2994  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
2995  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
2996  uint8_t httpbuf4[] = "Body one!!";
2997  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2998  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2999  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
3000  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
3001  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
3002  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
3003  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
3004  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
3005  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
3006  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
3008 
3009  memset(&th_v, 0, sizeof(th_v));
3010  memset(&f, 0, sizeof(f));
3011  memset(&ssn, 0, sizeof(ssn));
3012 
3013  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3014 
3015  FLOW_INITIALIZE(&f);
3016  f.protoctx = (void *)&ssn;
3017  f.proto = IPPROTO_TCP;
3018  f.flags |= FLOW_IPV4;
3019 
3020  p->flow = &f;
3024  f.alproto = ALPROTO_HTTP;
3025 
3027 
3029  FAIL_IF(de_ctx == NULL);
3030 
3031  de_ctx->flags |= DE_QUIET;
3032 
3033  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;)");
3034  FAIL_IF(s == NULL);
3035  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;)");
3036  FAIL_IF(s == NULL);
3037 
3038  SigGroupBuild(de_ctx);
3039  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3040 
3041  FLOWLOCK_WRLOCK(&f);
3042  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3043  STREAM_TOSERVER, httpbuf1, httplen1);
3044  FAIL_IF(r != 0);
3045  FLOWLOCK_UNLOCK(&f);
3046 
3047  /* do detect */
3048  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3049  FAIL_IF(PacketAlertCheck(p, 1));
3050  p->alerts.cnt = 0;
3051 
3052  FLOWLOCK_WRLOCK(&f);
3053  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3054  STREAM_TOSERVER, httpbuf2, httplen2);
3055  FAIL_IF(r != 0);
3056  FLOWLOCK_UNLOCK(&f);
3057 
3058  /* do detect */
3059  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3060  FAIL_IF(PacketAlertCheck(p, 1));
3061  p->alerts.cnt = 0;
3062 
3063  FLOWLOCK_WRLOCK(&f);
3064  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3065  STREAM_TOSERVER, httpbuf3, httplen3);
3066  FAIL_IF(r != 0);
3067  FLOWLOCK_UNLOCK(&f);
3068 
3069  /* do detect */
3070  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3071  FAIL_IF(PacketAlertCheck(p, 1));
3072  p->alerts.cnt = 0;
3073 
3074  FLOWLOCK_WRLOCK(&f);
3075  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3076  STREAM_TOSERVER, httpbuf4, httplen4);
3077  FAIL_IF(r != 0);
3078  FLOWLOCK_UNLOCK(&f);
3079 
3080  /* do detect */
3081  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3082  FAIL_IF(!(PacketAlertCheck(p, 1)));
3083  p->alerts.cnt = 0;
3084 
3085  FLOWLOCK_WRLOCK(&f);
3086  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3087  STREAM_TOSERVER, httpbuf5, httplen5);
3088  FAIL_IF(r != 0);
3089  FLOWLOCK_UNLOCK(&f);
3090 
3091  /* do detect */
3092  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3093  FAIL_IF(PacketAlertCheck(p, 1));
3094  p->alerts.cnt = 0;
3095 
3096  FLOWLOCK_WRLOCK(&f);
3097  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3098  STREAM_TOSERVER, httpbuf6, httplen6);
3099  FAIL_IF(r != 0);
3100  FLOWLOCK_UNLOCK(&f);
3101 
3102  /* do detect */
3103  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3104  FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
3105  p->alerts.cnt = 0;
3106 
3107  SCLogDebug("sending data chunk 7");
3108 
3109  FLOWLOCK_WRLOCK(&f);
3110  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3111  STREAM_TOSERVER, httpbuf7, httplen7);
3112  FAIL_IF(r != 0);
3113  FLOWLOCK_UNLOCK(&f);
3114 
3115  /* do detect */
3116  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3117  FAIL_IF(!(PacketAlertCheck(p, 2)));
3118  p->alerts.cnt = 0;
3119 
3120  HtpState *htp_state = f.alstate;
3121  FAIL_IF(htp_state == NULL);
3122 
3123  FAIL_IF(AppLayerParserGetTxCnt(&f, htp_state) != 2);
3124 
3125  if (alp_tctx != NULL)
3126  AppLayerParserThreadCtxFree(alp_tctx);
3127  if (det_ctx != NULL) {
3128  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
3129  }
3130  if (de_ctx != NULL) {
3131  SigGroupCleanup(de_ctx);
3132  DetectEngineCtxFree(de_ctx);
3133  }
3134 
3136  FLOW_DESTROY(&f);
3137  UTHFreePacket(p);
3138  PASS;
3139 }
3140 
3141 /**
3142  * \test flowvar capture on http buffer
3143  */
3144 static int DetectPcreFlowvarCapture01(void)
3145 {
3146  uint8_t uabuf1[] =
3147  "Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.9.0.13) Gecko/2009080315 Ubuntu/8.10 (intrepid) Firefox/3.0.13";
3148  uint32_t ualen1 = sizeof(uabuf1) - 1; /* minus the \0 */
3149  uint8_t httpbuf1[] =
3150  "GET / HTTP/1.1\r\n"
3151  "Host: www.emergingthreats.net\r\n"
3152  "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"
3153  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8\r\n"
3154  "Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
3155  "Accept-Encoding: gzip,deflate\r\n"
3156  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
3157  "Date: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
3158  "Server: Apache\r\n"
3159  "\r\n"
3160  "<!DOCTYPE html PUBLIC\r\n\r\n";
3161  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3162  TcpSession ssn;
3163  Packet *p1 = NULL;
3164  Flow f;
3165  Signature *s = NULL;
3166  ThreadVars th_v;
3167  DetectEngineThreadCtx *det_ctx;
3169 
3170  memset(&th_v, 0, sizeof(th_v));
3171  memset(&f, 0, sizeof(f));
3172  memset(&ssn, 0, sizeof(ssn));
3173 
3174  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3175 
3176  FLOW_INITIALIZE(&f);
3177  f.protoctx = (void *)&ssn;
3178  f.proto = IPPROTO_TCP;
3179  f.flags |= FLOW_IPV4;
3180  f.alproto = ALPROTO_HTTP;
3181 
3182  p1->flow = &f;
3186 
3188 
3190  FAIL_IF(de_ctx == NULL);
3191  de_ctx->flags |= DE_QUIET;
3192 
3193  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"User-Agent: \"; http_header; pcre:\"/(?P<flow_ua>.*)\\r\\n/HR\"; sid:1;)");
3194  FAIL_IF(s == NULL);
3195 
3196  FAIL_IF(s->sm_lists[g_http_header_buffer_id] == NULL ||
3197  s->sm_lists[g_http_header_buffer_id]->next == NULL ||
3198  s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
3199  DetectPcreData *pd = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
3200 
3201  SigGroupBuild(de_ctx);
3202  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3203 
3204  FLOWLOCK_WRLOCK(&f);
3205  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3206  STREAM_TOSERVER, httpbuf1, httplen1);
3207  FAIL_IF(r != 0);
3208  FLOWLOCK_UNLOCK(&f);
3209 
3210  HtpState *http_state = f.alstate;
3211  FAIL_IF(http_state == NULL);
3212 
3213  /* do detect for p1 */
3214  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
3215 
3216  FAIL_IF(!(PacketAlertCheck(p1, 1)));
3217 
3218  FlowVar *fv = FlowVarGet(&f, pd->capids[0]);
3219  FAIL_IF(fv == NULL);
3220 
3221  FAIL_IF(fv->data.fv_str.value_len != ualen1);
3222 
3223  if (memcmp(fv->data.fv_str.value, uabuf1, ualen1) != 0) {
3224  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
3225  PrintRawDataFp(stdout, uabuf1, ualen1);
3226 
3227  printf("buffer mismatch: ");
3228  FAIL;
3229  }
3230 
3231  if (alp_tctx != NULL)
3232  AppLayerParserThreadCtxFree(alp_tctx);
3233  if (de_ctx != NULL)
3234  DetectEngineCtxFree(de_ctx);
3235 
3237  FLOW_DESTROY(&f);
3238  UTHFreePackets(&p1, 1);
3239  PASS;
3240 }
3241 
3242 /**
3243  * \test flowvar capture on http buffer, capture overwrite
3244  */
3245 static int DetectPcreFlowvarCapture02(void)
3246 {
3247  uint8_t uabuf1[] =
3248  "Apache";
3249  uint32_t ualen1 = sizeof(uabuf1) - 1; /* minus the \0 */
3250  uint8_t httpbuf1[] =
3251  "GET / HTTP/1.1\r\n"
3252  "Host: www.emergingthreats.net\r\n"
3253  "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"
3254  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8\r\n"
3255  "Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
3256  "Accept-Encoding: gzip,deflate\r\n"
3257  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
3258  "Date: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
3259  "Server: Apache\r\n"
3260  "\r\n"
3261  "<!DOCTYPE html PUBLIC\r\n\r\n";
3262  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3263  TcpSession ssn;
3264  Packet *p1 = NULL;
3265  Flow f;
3266  Signature *s = NULL;
3267  ThreadVars th_v;
3268  DetectEngineThreadCtx *det_ctx;
3270 
3271  memset(&th_v, 0, sizeof(th_v));
3272  memset(&f, 0, sizeof(f));
3273  memset(&ssn, 0, sizeof(ssn));
3274 
3275  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3276 
3277  FLOW_INITIALIZE(&f);
3278  f.protoctx = (void *)&ssn;
3279  f.proto = IPPROTO_TCP;
3280  f.flags |= FLOW_IPV4;
3281  f.alproto = ALPROTO_HTTP;
3282 
3283  p1->flow = &f;
3287 
3289 
3291  FAIL_IF(de_ctx == NULL);
3292  de_ctx->flags |= DE_QUIET;
3293 
3294  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;)");
3295  FAIL_IF(s == NULL);
3296 
3297  FAIL_IF(s->sm_lists[g_http_header_buffer_id] == NULL ||
3298  s->sm_lists[g_http_header_buffer_id]->next == NULL ||
3299  s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
3300  DetectPcreData *pd1 = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
3301 
3302  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;)");
3303  FAIL_IF(s == NULL);
3304 
3305  FAIL_IF(s->sm_lists[g_http_header_buffer_id] == NULL ||
3306  s->sm_lists[g_http_header_buffer_id]->next == NULL ||
3307  s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
3308  DetectPcreData *pd2 = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
3309 
3310  FAIL_IF(pd1->capids[0] != pd2->capids[0]);
3311 
3313  SCSigOrderSignatures(de_ctx);
3315  SigGroupBuild(de_ctx);
3316  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3317 
3318  FLOWLOCK_WRLOCK(&f);
3319  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3320  STREAM_TOSERVER, httpbuf1, httplen1);
3321  FAIL_IF(r != 0);
3322  FLOWLOCK_UNLOCK(&f);
3323 
3324  HtpState *http_state = f.alstate;
3325  FAIL_IF(http_state == NULL);
3326 
3327  /* do detect for p1 */
3328  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
3329 
3330  FAIL_IF(!(PacketAlertCheck(p1, 1)));
3331 
3332  FlowVar *fv = FlowVarGet(&f, pd1->capids[0]);
3333  FAIL_IF(fv == NULL);
3334 
3335  if (fv->data.fv_str.value_len != ualen1) {
3336  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
3337  PrintRawDataFp(stdout, uabuf1, ualen1);
3338  printf("%u != %u: ", fv->data.fv_str.value_len, ualen1);
3339  FAIL;
3340  }
3341 
3342  if (memcmp(fv->data.fv_str.value, uabuf1, ualen1) != 0) {
3343  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
3344  PrintRawDataFp(stdout, uabuf1, ualen1);
3345 
3346  printf("buffer mismatch: ");
3347  FAIL;
3348  }
3349 
3350  if (alp_tctx != NULL)
3351  AppLayerParserThreadCtxFree(alp_tctx);
3352  if (de_ctx != NULL)
3353  DetectEngineCtxFree(de_ctx);
3354 
3356  FLOW_DESTROY(&f);
3357  UTHFreePackets(&p1, 1);
3358  PASS;
3359 }
3360 
3361 /**
3362  * \test flowvar capture on http buffer, capture overwrite + no matching sigs, so flowvars should not be set.
3363  */
3364 static int DetectPcreFlowvarCapture03(void)
3365 {
3366  uint8_t httpbuf1[] =
3367  "GET / HTTP/1.1\r\n"
3368  "Host: www.emergingthreats.net\r\n"
3369  "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"
3370  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8\r\n"
3371  "Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
3372  "Accept-Encoding: gzip,deflate\r\n"
3373  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
3374  "Date: Tue, 22 Sep 2009 19:24:48 GMT\r\n"
3375  "Server: Apache\r\n"
3376  "\r\n"
3377  "<!DOCTYPE html PUBLIC\r\n\r\n";
3378  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
3379  TcpSession ssn;
3380  Packet *p1 = NULL;
3381  Flow f;
3382  Signature *s = NULL;
3383  ThreadVars th_v;
3384  DetectEngineThreadCtx *det_ctx;
3386 
3387  memset(&th_v, 0, sizeof(th_v));
3388  memset(&f, 0, sizeof(f));
3389  memset(&ssn, 0, sizeof(ssn));
3390 
3391  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
3392 
3393  FLOW_INITIALIZE(&f);
3394  f.protoctx = (void *)&ssn;
3395  f.proto = IPPROTO_TCP;
3396  f.flags |= FLOW_IPV4;
3397  f.alproto = ALPROTO_HTTP;
3398 
3399  p1->flow = &f;
3403 
3405 
3407  FAIL_IF(de_ctx == NULL);
3408  de_ctx->flags |= DE_QUIET;
3409 
3410  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;)");
3411  FAIL_IF(s == NULL);
3412 
3413  FAIL_IF(s->sm_lists[g_http_header_buffer_id] == NULL ||
3414  s->sm_lists[g_http_header_buffer_id]->next == NULL ||
3415  s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
3416  DetectPcreData *pd1 = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
3417 
3418  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;)");
3419  FAIL_IF(s == NULL);
3420 
3421  FAIL_IF(s->sm_lists[g_http_header_buffer_id] == NULL ||
3422  s->sm_lists[g_http_header_buffer_id]->next == NULL ||
3423  s->sm_lists[g_http_header_buffer_id]->next->type != DETECT_PCRE);
3424  DetectPcreData *pd2 = (DetectPcreData *)s->sm_lists[g_http_header_buffer_id]->next->ctx;
3425 
3426  FAIL_IF(pd1->capids[0] != pd2->capids[0]);
3427 
3428  SigGroupBuild(de_ctx);
3429  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3430 
3431  FLOWLOCK_WRLOCK(&f);
3432  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
3433  STREAM_TOSERVER, httpbuf1, httplen1);
3434  FAIL_IF(r != 0);
3435  FLOWLOCK_UNLOCK(&f);
3436 
3437  HtpState *http_state = f.alstate;
3438  FAIL_IF(http_state == NULL);
3439 
3440  /* do detect for p1 */
3441  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
3442 
3443  FAIL_IF(PacketAlertCheck(p1, 1));
3444 
3445  FlowVar *fv = FlowVarGet(&f, pd1->capids[0]);
3446  FAIL_IF(fv != NULL);
3447 
3448  if (alp_tctx != NULL)
3449  AppLayerParserThreadCtxFree(alp_tctx);
3450  if (de_ctx != NULL)
3451  DetectEngineCtxFree(de_ctx);
3452 
3454  FLOW_DESTROY(&f);
3455  UTHFreePackets(&p1, 1);
3456  PASS;
3457 }
3458 
3459 /**
3460  * \brief Test parsing of pcre's with the W modifier set.
3461  */
3462 static int DetectPcreParseHttpHost(void)
3463 {
3464  AppProto alproto = ALPROTO_UNKNOWN;
3465  int list = DETECT_SM_LIST_NOTSET;
3467 
3468  FAIL_IF(de_ctx == NULL);
3469 
3470  DetectPcreData *pd = DetectPcreParse(de_ctx, "/domain\\.com/W", &list, NULL, 0, false, &alproto);
3471  FAIL_IF(pd == NULL);
3472  DetectPcreFree(pd);
3473 
3474  list = DETECT_SM_LIST_NOTSET;
3475  pd = DetectPcreParse(de_ctx, "/dOmain\\.com/W", &list, NULL, 0, false, &alproto);
3476  FAIL_IF(pd != NULL);
3477 
3478  /* Uppercase meta characters are valid. */
3479  list = DETECT_SM_LIST_NOTSET;
3480  pd = DetectPcreParse(de_ctx, "/domain\\D+\\.com/W", &list, NULL, 0, false, &alproto);
3481  FAIL_IF(pd == NULL);
3482  DetectPcreFree(pd);
3483 
3484  /* This should not parse as the first \ escapes the second \, then
3485  * we have a D. */
3486  list = DETECT_SM_LIST_NOTSET;
3487  pd = DetectPcreParse(de_ctx, "/\\\\Ddomain\\.com/W", &list, NULL, 0, false, &alproto);
3488  FAIL_IF(pd != NULL);
3489 
3490  DetectEngineCtxFree(de_ctx);
3491  PASS;
3492 }
3493 
3494 /**
3495  * \brief Test parsing of capture extension
3496  */
3497 static int DetectPcreParseCaptureTest(void)
3498 {
3500  FAIL_IF(de_ctx == NULL);
3501 
3502  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
3503  "(content:\"Server: \"; http_header; pcre:\"/(.*)\\r\\n/HR, flow:somecapture\"; content:\"xyz\"; http_header; sid:1;)");
3504  FAIL_IF(s == NULL);
3505  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
3506  "(content:\"Server: \"; http_header; pcre:\"/(flow:.*)\\r\\n/HR\"; content:\"xyz\"; http_header; sid:2;)");
3507  FAIL_IF(s == NULL);
3508  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
3509  "(content:\"Server: \"; http_header; pcre:\"/([a-z]+)([0-9]+)\\r\\n/HR, flow:somecapture, pkt:anothercap\"; content:\"xyz\"; http_header; sid:3;)");
3510  FAIL_IF(s == NULL);
3511 
3512  SigGroupBuild(de_ctx);
3513 
3514  uint32_t capid = VarNameStoreLookupByName("somecapture", VAR_TYPE_FLOW_VAR);
3515  FAIL_IF (capid != 1);
3516  capid = VarNameStoreLookupByName("anothercap", VAR_TYPE_PKT_VAR);
3517  FAIL_IF (capid != 2);
3518 
3519  DetectEngineCtxFree(de_ctx);
3520  PASS;
3521 }
3522 
3523 #endif /* UNITTESTS */
3524 
3525 /**
3526  * \brief this function registers unit tests for DetectPcre
3527  */
3528 static void DetectPcreRegisterTests(void)
3529 {
3530 #ifdef UNITTESTS /* UNITTESTS */
3531  g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
3532  g_http_header_buffer_id = DetectBufferTypeGetByName("http_header");
3533  g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
3534 
3535  UtRegisterTest("DetectPcreParseTest01", DetectPcreParseTest01);
3536  UtRegisterTest("DetectPcreParseTest02", DetectPcreParseTest02);
3537  UtRegisterTest("DetectPcreParseTest03", DetectPcreParseTest03);
3538  UtRegisterTest("DetectPcreParseTest04", DetectPcreParseTest04);
3539  UtRegisterTest("DetectPcreParseTest05", DetectPcreParseTest05);
3540  UtRegisterTest("DetectPcreParseTest06", DetectPcreParseTest06);
3541  UtRegisterTest("DetectPcreParseTest07", DetectPcreParseTest07);
3542  UtRegisterTest("DetectPcreParseTest08", DetectPcreParseTest08);
3543  UtRegisterTest("DetectPcreParseTest09", DetectPcreParseTest09);
3544  UtRegisterTest("DetectPcreParseTest10", DetectPcreParseTest10);
3545  UtRegisterTest("DetectPcreParseTest11", DetectPcreParseTest11);
3546  UtRegisterTest("DetectPcreParseTest12", DetectPcreParseTest12);
3547  UtRegisterTest("DetectPcreParseTest13", DetectPcreParseTest13);
3548  UtRegisterTest("DetectPcreParseTest14", DetectPcreParseTest14);
3549  UtRegisterTest("DetectPcreParseTest15", DetectPcreParseTest15);
3550  UtRegisterTest("DetectPcreParseTest16", DetectPcreParseTest16);
3551  UtRegisterTest("DetectPcreParseTest17", DetectPcreParseTest17);
3552  UtRegisterTest("DetectPcreParseTest18", DetectPcreParseTest18);
3553  UtRegisterTest("DetectPcreParseTest19", DetectPcreParseTest19);
3554  UtRegisterTest("DetectPcreParseTest20", DetectPcreParseTest20);
3555  UtRegisterTest("DetectPcreParseTest21", DetectPcreParseTest21);
3556  UtRegisterTest("DetectPcreParseTest22", DetectPcreParseTest22);
3557  UtRegisterTest("DetectPcreParseTest23", DetectPcreParseTest23);
3558  UtRegisterTest("DetectPcreParseTest24", DetectPcreParseTest24);
3559  UtRegisterTest("DetectPcreParseTest25", DetectPcreParseTest25);
3560  UtRegisterTest("DetectPcreParseTest26", DetectPcreParseTest26);
3561  UtRegisterTest("DetectPcreParseTest27", DetectPcreParseTest27);
3562  UtRegisterTest("DetectPcreParseTest28", DetectPcreParseTest28);
3563 
3564  UtRegisterTest("DetectPcreTestSig01 -- pcre test", DetectPcreTestSig01);
3565  UtRegisterTest("DetectPcreTestSig02 -- pcre test", DetectPcreTestSig02);
3566  UtRegisterTest("DetectPcreTestSig03 -- negated pcre test",
3567  DetectPcreTestSig03);
3568 
3569  UtRegisterTest("DetectPcreModifPTest04 -- Modifier P",
3570  DetectPcreModifPTest04);
3571  UtRegisterTest("DetectPcreModifPTest05 -- Modifier P fragmented",
3572  DetectPcreModifPTest05);
3573  UtRegisterTest("DetectPcreTestSig06", DetectPcreTestSig06);
3574  UtRegisterTest("DetectPcreTestSig07 -- anchored pcre",
3575  DetectPcreTestSig07);
3576  UtRegisterTest("DetectPcreTestSig08 -- anchored pcre",
3577  DetectPcreTestSig08);
3578  UtRegisterTest("DetectPcreTestSig09 -- Cookie modifier",
3579  DetectPcreTestSig09);
3580  UtRegisterTest("DetectPcreTestSig10 -- negated Cookie modifier",
3581  DetectPcreTestSig10);
3582  UtRegisterTest("DetectPcreTestSig11 -- Method modifier",
3583  DetectPcreTestSig11);
3584  UtRegisterTest("DetectPcreTestSig12 -- negated Method modifier",
3585  DetectPcreTestSig12);
3586  UtRegisterTest("DetectPcreTestSig13 -- Header modifier",
3587  DetectPcreTestSig13);
3588  UtRegisterTest("DetectPcreTestSig14 -- negated Header modifier",
3589  DetectPcreTestSig14);
3590  UtRegisterTest("DetectPcreTestSig15 -- relative Cookie modifier",
3591  DetectPcreTestSig15);
3592  UtRegisterTest("DetectPcreTestSig16 -- relative Method modifier",
3593  DetectPcreTestSig16);
3594 
3595  UtRegisterTest("DetectPcreTxBodyChunksTest01",
3596  DetectPcreTxBodyChunksTest01);
3597  UtRegisterTest("DetectPcreTxBodyChunksTest02 -- modifier P, body chunks per tx",
3598  DetectPcreTxBodyChunksTest02);
3599  UtRegisterTest("DetectPcreTxBodyChunksTest03 -- modifier P, body chunks per tx",
3600  DetectPcreTxBodyChunksTest03);
3601 
3602  UtRegisterTest("DetectPcreFlowvarCapture01 -- capture for http_header",
3603  DetectPcreFlowvarCapture01);
3604  UtRegisterTest("DetectPcreFlowvarCapture02 -- capture for http_header",
3605  DetectPcreFlowvarCapture02);
3606  UtRegisterTest("DetectPcreFlowvarCapture03 -- capture for http_header",
3607  DetectPcreFlowvarCapture03);
3608 
3609  UtRegisterTest("DetectPcreParseHttpHost", DetectPcreParseHttpHost);
3610  UtRegisterTest("DetectPcreParseCaptureTest", DetectPcreParseCaptureTest);
3611 
3612 #endif /* UNITTESTS */
3613 }
3614 
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:1448
SignatureInitData * init_data
Definition: detect.h:591
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1186
#define SCLogDebug(...)
Definition: util-debug.h:335
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
#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:523
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:323
Signature * sig_list
Definition: detect.h:767
#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:327
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:1032
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
const char * name
Definition: detect.h:1200
uint16_t AppProto
TCPHdr * tcph
Definition: decode.h:522
Signature container.
Definition: detect.h:522
StreamingBufferSegment sbseg
#define TRUE
HtpBody request_body
#define SIG_FLAG_APPLAYER
Definition: detect.h:218
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:761
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 *)
int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *payload, uint32_t payload_len)
Match a regex on a single payload.
Definition: detect-pcre.c:171
#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:292
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:505
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:865
uint8_t flags
Definition: detect.h:762
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:1191
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:121
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:1669
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:1381
#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:115
uint8_t flowflags
Definition: decode.h:439
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
union FlowVar_::@117 data
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
#define DETECT_PCRE_CAPTURE_MAX
Definition: detect-pcre.h:35
AppProto alproto
Definition: detect.h:526
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:1170
int SigGroupCleanup(DetectEngineCtx *de_ctx)
struct Signature_ * next
Definition: detect.h:594
uint8_t type
Definition: detect.h:319
#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:1202
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:346
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:321
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
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:1034
int UTHAddSessionToFlow(Flow *f, uint32_t ts_isn, uint32_t tc_isn)
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
#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:1203
#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:1093
#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:647
#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:1389
#define DOC_VERSION
Definition: suricata.h:91
#define DETECT_VAR_TYPE_PKT_POSTMATCH
Definition: detect.h:648
uint16_t flags
Definition: detect.h:1194
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself...
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:1091
void(* RegisterTests)(void)
Definition: detect.h:1192
a single match condition for a signature
Definition: detect.h:318
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
SigMatchCtx * ctx
Definition: detect.h:330
void UTHFreeFlow(Flow *flow)
DetectEngineCtx * DetectEngineCtxInit(void)