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