suricata
detect-pcre.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2022 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 "decode.h"
28 #include "detect.h"
29 
30 #include "pkt-var.h"
31 #include "flow-var.h"
32 #include "flow-util.h"
33 
34 #include "detect-pcre.h"
35 #include "detect-flowvar.h"
36 
37 #include "detect-parse.h"
38 #include "detect-content.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 #include "detect-engine-build.h"
44 
45 #include "util-var-name.h"
46 #include "util-unittest-helper.h"
47 #include "util-debug.h"
48 #include "util-unittest.h"
49 #include "util-print.h"
50 #include "util-pool.h"
51 
52 #include "conf.h"
53 #include "app-layer.h"
54 #include "app-layer-htp.h"
55 #include "stream.h"
56 #include "stream-tcp.h"
57 #include "stream-tcp-private.h"
58 #include "stream-tcp-reassemble.h"
59 #include "app-layer-protos.h"
60 #include "app-layer-parser.h"
61 #include "util-pages.h"
62 
63 /* pcre named substring capture supports only 32byte names, A-z0-9 plus _
64  * and needs to start with non-numeric. */
65 #define PARSE_CAPTURE_REGEX "\\(\\?P\\<([A-z]+)\\_([A-z0-9_]+)\\>"
66 #define PARSE_REGEX "(?<!\\\\)/(.*(?<!(?<!\\\\)\\\\))/([^\"]*)"
67 
68 static int pcre_match_limit = 0;
69 static int pcre_match_limit_recursion = 0;
70 
71 static DetectParseRegex *parse_regex;
72 static DetectParseRegex *parse_capture_regex;
73 
74 #ifdef PCRE2_HAVE_JIT
75 static int pcre2_use_jit = 1;
76 #endif
77 
78 // TODOpcre2 pcre2_jit_stack_create ?
79 
80 /* \brief Helper function for using pcre2_match with/without JIT
81  */
82 static inline int DetectPcreExec(DetectEngineThreadCtx *det_ctx, const DetectPcreData *pd,
83  const char *str, const size_t strlen, int start_offset, int options,
84  pcre2_match_data *match)
85 {
86  return pcre2_match(pd->parse_regex.regex, (PCRE2_SPTR8)str, strlen, start_offset, options,
87  match, pd->parse_regex.context);
88 }
89 
90 static int DetectPcreSetup (DetectEngineCtx *, Signature *, const char *);
91 static void DetectPcreFree(DetectEngineCtx *, void *);
92 #ifdef UNITTESTS
93 static void DetectPcreRegisterTests(void);
94 #endif
95 
96 void DetectPcreRegister (void)
97 {
99  sigmatch_table[DETECT_PCRE].desc = "match on regular expression";
100  sigmatch_table[DETECT_PCRE].url = "/rules/payload-keywords.html#pcre-perl-compatible-regular-expressions";
102  sigmatch_table[DETECT_PCRE].Setup = DetectPcreSetup;
103  sigmatch_table[DETECT_PCRE].Free = DetectPcreFree;
104 #ifdef UNITTESTS
105  sigmatch_table[DETECT_PCRE].RegisterTests = DetectPcreRegisterTests;
106 #endif
108 
109  intmax_t val = 0;
110 
111  if (!ConfGetInt("pcre.match-limit", &val)) {
112  pcre_match_limit = SC_MATCH_LIMIT_DEFAULT;
113  SCLogDebug("Using PCRE match-limit setting of: %i", pcre_match_limit);
114  }
115  else {
116  pcre_match_limit = val;
117  if (pcre_match_limit != SC_MATCH_LIMIT_DEFAULT) {
118  SCLogInfo("Using PCRE match-limit setting of: %i", pcre_match_limit);
119  } else {
120  SCLogDebug("Using PCRE match-limit setting of: %i", pcre_match_limit);
121  }
122  }
123 
124  val = 0;
125 
126  if (!ConfGetInt("pcre.match-limit-recursion", &val)) {
127  pcre_match_limit_recursion = SC_MATCH_LIMIT_RECURSION_DEFAULT;
128  SCLogDebug("Using PCRE match-limit-recursion setting of: %i", pcre_match_limit_recursion);
129  }
130  else {
131  pcre_match_limit_recursion = val;
132  if (pcre_match_limit_recursion != SC_MATCH_LIMIT_RECURSION_DEFAULT) {
133  SCLogInfo("Using PCRE match-limit-recursion setting of: %i", pcre_match_limit_recursion);
134  } else {
135  SCLogDebug("Using PCRE match-limit-recursion setting of: %i", pcre_match_limit_recursion);
136  }
137  }
138 
139  parse_regex = DetectSetupPCRE2(PARSE_REGEX, 0);
140  if (parse_regex == NULL) {
141  FatalError("pcre2 compile failed for parse_regex");
142  }
143 
144  /* setup the capture regex, as it needs PCRE2_UNGREEDY we do it manually */
145  /* pkt_http_ua should be pkt, http_ua, for this reason the UNGREEDY */
146  parse_capture_regex = DetectSetupPCRE2(PARSE_CAPTURE_REGEX, PCRE2_UNGREEDY);
147  if (parse_capture_regex == NULL) {
148  FatalError("pcre2 compile failed for parse_capture_regex");
149  }
150 
151 #ifdef PCRE2_HAVE_JIT
152  if (PageSupportsRWX() == 0) {
153  SCLogConfig("PCRE2 won't use JIT as OS doesn't allow RWX pages");
154  pcre2_use_jit = 0;
155  }
156 #endif
157 }
158 
159 /**
160  * \brief Match a regex on a single payload.
161  *
162  * \param det_ctx Thread detection ctx.
163  * \param s Signature.
164  * \param sm Sig match to match against.
165  * \param p Packet to set PktVars if any.
166  * \param f Flow to set FlowVars if any.
167  * \param payload Payload to inspect.
168  * \param payload_len Length of the payload.
169  *
170  * \retval 1 Match.
171  * \retval 0 No match.
172  */
174  const SigMatchData *smd, Packet *p, Flow *f,
175  const uint8_t *payload, uint32_t payload_len)
176 {
177  SCEnter();
178  int ret = 0;
179  const uint8_t *ptr = NULL;
180  uint32_t len = 0;
181  PCRE2_SIZE capture_len = 0;
182 
183  const DetectPcreData *pe = (const DetectPcreData *)smd->ctx;
184 
185  if (pe->flags & DETECT_PCRE_RELATIVE) {
186  ptr = payload + det_ctx->buffer_offset;
187  len = payload_len - det_ctx->buffer_offset;
188  } else {
189  ptr = payload;
190  len = payload_len;
191  }
192 
193  int start_offset = 0;
194  if (det_ctx->pcre_match_start_offset != 0) {
195  start_offset = (payload + det_ctx->pcre_match_start_offset - ptr);
196  }
197 
198  /* run the actual pcre detection */
199  pcre2_match_data *match =
200  (pcre2_match_data *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, pe->thread_ctx_id);
201 
202  ret = DetectPcreExec(det_ctx, pe, (char *)ptr, len, start_offset, 0, match);
203  SCLogDebug("ret %d (negating %s)", ret, (pe->flags & DETECT_PCRE_NEGATE) ? "set" : "not set");
204 
205  if (ret == PCRE2_ERROR_NOMATCH) {
206  if (pe->flags & DETECT_PCRE_NEGATE) {
207  /* regex didn't match with negate option means we
208  * consider it a match */
209  ret = 1;
210  } else {
211  ret = 0;
212  }
213  } else if (ret >= 0) {
214  if (pe->flags & DETECT_PCRE_NEGATE) {
215  /* regex matched but we're negated, so not
216  * considering it a match */
217  ret = 0;
218  } else {
219  /* regex matched and we're not negated,
220  * considering it a match */
221 
222  SCLogDebug("ret %d pe->idx %u", ret, pe->idx);
223 
224  /* see if we need to do substring capturing. */
225  if (ret > 1 && pe->idx != 0) {
226  uint8_t x;
227  for (x = 0; x < pe->idx; x++) {
228  SCLogDebug("capturing %u", x);
229  const char *pcre2_str_ptr = NULL;
230  ret = pcre2_substring_get_bynumber(
231  match, x + 1, (PCRE2_UCHAR8 **)&pcre2_str_ptr, &capture_len);
232  if (unlikely(ret != 0)) {
233  pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr);
234  continue;
235  }
236  /* store max 64k. Errors are ignored */
237  capture_len = (capture_len < 0xffff) ? (uint16_t)capture_len : 0xffff;
238  uint8_t *str_ptr = SCMalloc(capture_len);
239  if (unlikely(str_ptr == NULL)) {
240  pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr);
241  continue;
242  }
243  memcpy(str_ptr, pcre2_str_ptr, capture_len);
244  pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr);
245 
246  SCLogDebug("data %p/%u, type %u id %u p %p",
247  str_ptr, ret, pe->captypes[x], pe->capids[x], p);
248 
249  if (pe->captypes[x] == VAR_TYPE_PKT_VAR_KV) {
250  /* get the value, as first capture is the key */
251  const char *pcre2_str_ptr2 = NULL;
252  /* key length is limited to 256 chars */
253  uint16_t key_len = (capture_len < 0xff) ? (uint16_t)capture_len : 0xff;
254  int ret2 = pcre2_substring_get_bynumber(
255  match, x + 2, (PCRE2_UCHAR8 **)&pcre2_str_ptr2, &capture_len);
256 
257  if (unlikely(ret2 != 0)) {
258  SCFree(str_ptr);
259  pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr2);
260  break;
261  }
262  capture_len = (capture_len < 0xffff) ? (uint16_t)capture_len : 0xffff;
263  uint8_t *str_ptr2 = SCMalloc(capture_len);
264  if (unlikely(str_ptr2 == NULL)) {
265  SCFree(str_ptr);
266  pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr2);
267  break;
268  }
269  memcpy(str_ptr2, pcre2_str_ptr2, capture_len);
270  pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr2);
271 
272  (void)DetectVarStoreMatchKeyValue(det_ctx, (uint8_t *)str_ptr, key_len,
273  (uint8_t *)str_ptr2, (uint16_t)capture_len,
275 
276  } else if (pe->captypes[x] == VAR_TYPE_PKT_VAR) {
277  (void)DetectVarStoreMatch(det_ctx, pe->capids[x], (uint8_t *)str_ptr,
278  (uint16_t)capture_len, DETECT_VAR_TYPE_PKT_POSTMATCH);
279 
280  } else if (pe->captypes[x] == VAR_TYPE_FLOW_VAR && f != NULL) {
281  (void)DetectVarStoreMatch(det_ctx, pe->capids[x], (uint8_t *)str_ptr,
282  (uint16_t)capture_len, DETECT_VAR_TYPE_FLOW_POSTMATCH);
283  } else {
284  BUG_ON(1); // Impossible captype
285  SCFree(str_ptr);
286  }
287  }
288  }
289 
290  PCRE2_SIZE *ov = pcre2_get_ovector_pointer(match);
291  /* update offset for pcre RELATIVE */
292  det_ctx->buffer_offset = (ptr + ov[1]) - payload;
293  det_ctx->pcre_match_start_offset = (ptr + ov[0] + 1) - payload;
294 
295  ret = 1;
296  }
297 
298  } else {
299  SCLogDebug("pcre had matching error");
300  ret = 0;
301  }
302  SCReturnInt(ret);
303 }
304 
305 static int DetectPcreSetList(int list, int set)
306 {
307  if (list != DETECT_SM_LIST_NOTSET) {
308  SCLogError("only one pcre option to specify a buffer type is allowed");
309  return -1;
310  }
311  return set;
312 }
313 
314 static int DetectPcreHasUpperCase(const char *re)
315 {
316  size_t len = strlen(re);
317  bool is_meta = false;
318  bool is_meta_hex = false;
319  int meta_hex_cnt = 0;
320 
321  for (size_t i = 0; i < len; i++) {
322  if (is_meta_hex) {
323  meta_hex_cnt++;
324 
325  if (meta_hex_cnt == 2) {
326  is_meta_hex = false;
327  meta_hex_cnt = 0;
328  }
329  } else if (is_meta) {
330  if (re[i] == 'x') {
331  is_meta_hex = true;
332  } else {
333  is_meta = false;
334  }
335  }
336  else if (re[i] == '\\') {
337  is_meta = true;
338  }
339  else if (isupper((unsigned char)re[i])) {
340  return 1;
341  }
342  }
343 
344  return 0;
345 }
346 
347 static DetectPcreData *DetectPcreParse (DetectEngineCtx *de_ctx,
348  const char *regexstr, int *sm_list, char *capture_names,
349  size_t capture_names_size, bool negate, AppProto *alproto)
350 {
351  pcre2_match_data *match = NULL;
352  int en;
353  PCRE2_SIZE eo2;
354  int opts = 0;
355  DetectPcreData *pd = NULL;
356  char *op = NULL;
357  int ret = 0, res = 0;
358  int check_host_header = 0;
359  char op_str[64] = "";
360 
361  bool apply_match_limit = false;
362 
363  int cut_capture = 0;
364  char *fcap = strstr(regexstr, "flow:");
365  char *pcap = strstr(regexstr, "pkt:");
366  /* take the size of the whole input as buffer size for the regex we will
367  * extract below. Add 1 to please Coverity's alloc_strlen test. */
368  size_t slen = strlen(regexstr) + 1;
369  if (fcap || pcap) {
370  SCLogDebug("regexstr %s", regexstr);
371 
372  if (fcap && !pcap)
373  cut_capture = fcap - regexstr;
374  else if (pcap && !fcap)
375  cut_capture = pcap - regexstr;
376  else {
377  BUG_ON(pcap == NULL); // added to assist cppcheck
378  BUG_ON(fcap == NULL);
379  cut_capture = MIN((pcap - regexstr), (fcap - regexstr));
380  }
381 
382  SCLogDebug("cut_capture %d", cut_capture);
383 
384  if (cut_capture > 1) {
385  int offset = cut_capture - 1;
386  while (offset) {
387  SCLogDebug("regexstr[offset] %c", regexstr[offset]);
388  if (regexstr[offset] == ',' || regexstr[offset] == ' ') {
389  offset--;
390  }
391  else
392  break;
393  }
394 
395  if (cut_capture == (offset + 1)) {
396  SCLogDebug("missing separators, assume it's part of the regex");
397  } else {
398  slen = offset + 1;
399  strlcpy(capture_names, regexstr+cut_capture, capture_names_size);
400  if (capture_names[strlen(capture_names)-1] == '"')
401  capture_names[strlen(capture_names)-1] = '\0';
402  }
403  }
404  }
405 
406  char re[slen];
407 
408  match = pcre2_match_data_create_from_pattern(parse_regex->regex, NULL);
409  if (!match) {
410  goto error;
411  }
412 
413  ret = pcre2_match(parse_regex->regex, (PCRE2_SPTR8)regexstr, slen, 0, 0, match, NULL);
414  if (ret <= 0) {
415  SCLogError("pcre parse error: %s", regexstr);
416  goto error;
417  }
418 
419  res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)re, &slen);
420  if (res < 0) {
421  SCLogError("pcre2_substring_copy_bynumber failed");
422  pcre2_match_data_free(match);
423  return NULL;
424  }
425 
426  if (ret > 2) {
427  size_t copylen = sizeof(op_str);
428  res = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)op_str, &copylen);
429  if (res < 0) {
430  SCLogError("pcre2_substring_copy_bynumber failed");
431  pcre2_match_data_free(match);
432  return NULL;
433  }
434  op = op_str;
435  }
436  //printf("ret %" PRId32 " re \'%s\', op \'%s\'\n", ret, re, op);
437 
438  pd = SCCalloc(1, sizeof(DetectPcreData));
439  if (unlikely(pd == NULL))
440  goto error;
441 
442  if (negate)
443  pd->flags |= DETECT_PCRE_NEGATE;
444 
445  if (op != NULL) {
446  while (*op) {
447  SCLogDebug("regex option %c", *op);
448 
449  switch (*op) {
450  case 'A':
451  opts |= PCRE2_ANCHORED;
452  break;
453  case 'E':
454  opts |= PCRE2_DOLLAR_ENDONLY;
455  break;
456  case 'G':
457  opts |= PCRE2_UNGREEDY;
458  break;
459 
460  case 'i':
461  opts |= PCRE2_CASELESS;
463  break;
464  case 'm':
465  opts |= PCRE2_MULTILINE;
466  break;
467  case 's':
468  opts |= PCRE2_DOTALL;
469  break;
470  case 'x':
471  opts |= PCRE2_EXTENDED;
472  break;
473 
474  case 'O':
475  apply_match_limit = true;
476  break;
477 
478  case 'B': /* snort's option */
479  if (*sm_list != DETECT_SM_LIST_NOTSET) {
480  SCLogError("regex modifier 'B' inconsistent with chosen buffer");
481  goto error;
482  }
484  break;
485  case 'R': /* snort's option */
487  break;
488 
489  /* buffer selection */
490 
491  case 'U': { /* snort's option */
492  if (pd->flags & DETECT_PCRE_RAWBYTES) {
493  SCLogError("regex modifier 'U' inconsistent with 'B'");
494  goto error;
495  }
496  int list = DetectBufferTypeGetByName("http_uri");
497  *sm_list = DetectPcreSetList(*sm_list, list);
498  *alproto = ALPROTO_HTTP1;
499  break;
500  }
501  case 'V': {
502  if (pd->flags & DETECT_PCRE_RAWBYTES) {
503  SCLogError("regex modifier 'V' inconsistent with 'B'");
504  goto error;
505  }
506  int list = DetectBufferTypeGetByName("http_user_agent");
507  *sm_list = DetectPcreSetList(*sm_list, list);
508  *alproto = ALPROTO_HTTP1;
509  break;
510  }
511  case 'W': {
512  if (pd->flags & DETECT_PCRE_RAWBYTES) {
513  SCLogError("regex modifier 'W' inconsistent with 'B'");
514  goto error;
515  }
516  int list = DetectBufferTypeGetByName("http_host");
517  *sm_list = DetectPcreSetList(*sm_list, list);
518  *alproto = ALPROTO_HTTP1;
519  check_host_header = 1;
520  break;
521  }
522  case 'Z': {
523  if (pd->flags & DETECT_PCRE_RAWBYTES) {
524  SCLogError("regex modifier 'Z' inconsistent with 'B'");
525  goto error;
526  }
527  int list = DetectBufferTypeGetByName("http_raw_host");
528  *sm_list = DetectPcreSetList(*sm_list, list);
529  *alproto = ALPROTO_HTTP1;
530  break;
531  }
532  case 'H': { /* snort's option */
533  if (pd->flags & DETECT_PCRE_RAWBYTES) {
534  SCLogError("regex modifier 'H' inconsistent with 'B'");
535  goto error;
536  }
537  int list = DetectBufferTypeGetByName("http_header");
538  *sm_list = DetectPcreSetList(*sm_list, list);
539  *alproto = ALPROTO_HTTP1;
540  break;
541  } case 'I': { /* snort's option */
542  if (pd->flags & DETECT_PCRE_RAWBYTES) {
543  SCLogError("regex modifier 'I' inconsistent with 'B'");
544  goto error;
545  }
546  int list = DetectBufferTypeGetByName("http_raw_uri");
547  *sm_list = DetectPcreSetList(*sm_list, list);
548  *alproto = ALPROTO_HTTP1;
549  break;
550  }
551  case 'D': { /* snort's option */
552  int list = DetectBufferTypeGetByName("http_raw_header");
553  *sm_list = DetectPcreSetList(*sm_list, list);
554  *alproto = ALPROTO_HTTP1;
555  break;
556  }
557  case 'M': { /* snort's option */
558  if (pd->flags & DETECT_PCRE_RAWBYTES) {
559  SCLogError("regex modifier 'M' inconsistent with 'B'");
560  goto error;
561  }
562  int list = DetectBufferTypeGetByName("http_method");
563  *sm_list = DetectPcreSetList(*sm_list, list);
564  *alproto = ALPROTO_HTTP1;
565  break;
566  }
567  case 'C': { /* snort's option */
568  if (pd->flags & DETECT_PCRE_RAWBYTES) {
569  SCLogError("regex modifier 'C' inconsistent with 'B'");
570  goto error;
571  }
572  int list = DetectBufferTypeGetByName("http_cookie");
573  *sm_list = DetectPcreSetList(*sm_list, list);
574  *alproto = ALPROTO_HTTP1;
575  break;
576  }
577  case 'P': {
578  /* snort's option (http request body inspection) */
579  int list = DetectBufferTypeGetByName("http_client_body");
580  *sm_list = DetectPcreSetList(*sm_list, list);
581  *alproto = ALPROTO_HTTP1;
582  break;
583  }
584  case 'Q': {
585  int list = DetectBufferTypeGetByName("file_data");
586  /* suricata extension (http response body inspection) */
587  *sm_list = DetectPcreSetList(*sm_list, list);
588  *alproto = ALPROTO_HTTP1;
589  break;
590  }
591  case 'Y': {
592  /* snort's option */
593  int list = DetectBufferTypeGetByName("http_stat_msg");
594  *sm_list = DetectPcreSetList(*sm_list, list);
595  *alproto = ALPROTO_HTTP1;
596  break;
597  }
598  case 'S': {
599  /* snort's option */
600  int list = DetectBufferTypeGetByName("http_stat_code");
601  *sm_list = DetectPcreSetList(*sm_list, list);
602  *alproto = ALPROTO_HTTP1;
603  break;
604  }
605  default:
606  SCLogError("unknown regex modifier '%c'", *op);
607  goto error;
608  }
609  op++;
610  }
611  }
612  if (*sm_list == -1)
613  goto error;
614 
615  SCLogDebug("DetectPcreParse: \"%s\"", re);
616 
617  /* host header */
618  if (check_host_header) {
619  if (pd->flags & DETECT_PCRE_CASELESS) {
620  SCLogWarning("http host pcre(\"W\") "
621  "specified along with \"i(caseless)\" modifier. "
622  "Since the hostname buffer we match against "
623  "is actually lowercase, having a "
624  "nocase is redundant.");
625  }
626  else if (DetectPcreHasUpperCase(re)) {
627  SCLogError("pcre host(\"W\") "
628  "specified has an uppercase char. "
629  "Since the hostname buffer we match against "
630  "is actually lowercase, please specify an "
631  "all lowercase based pcre.");
632  goto error;
633  }
634  }
635 
636  /* Try to compile as if all (...) groups had been meant as (?:...),
637  * which is the common case in most rules.
638  * If we fail because a capture group is later referenced (e.g., \1),
639  * PCRE will let us know.
640  */
641  if (capture_names == NULL || strlen(capture_names) == 0)
642  opts |= PCRE2_NO_AUTO_CAPTURE;
643 
644  pd->parse_regex.regex =
645  pcre2_compile((PCRE2_SPTR8)re, PCRE2_ZERO_TERMINATED, opts, &en, &eo2, NULL);
646  if (pd->parse_regex.regex == NULL && en == 115) { // reference to nonexistent subpattern
647  opts &= ~PCRE2_NO_AUTO_CAPTURE;
648  pd->parse_regex.regex =
649  pcre2_compile((PCRE2_SPTR8)re, PCRE2_ZERO_TERMINATED, opts, &en, &eo2, NULL);
650  }
651  if (pd->parse_regex.regex == NULL) {
652  PCRE2_UCHAR errbuffer[256];
653  pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
654  SCLogError("pcre2 compile of \"%s\" failed at "
655  "offset %d: %s",
656  regexstr, (int)eo2, errbuffer);
657  goto error;
658  }
659 
660 #ifdef PCRE2_HAVE_JIT
661  if (pcre2_use_jit) {
662  ret = pcre2_jit_compile(pd->parse_regex.regex, PCRE2_JIT_COMPLETE);
663  if (ret != 0) {
664  /* warning, so we won't print the sig after this. Adding
665  * file and line to the message so the admin can figure
666  * out what sig this is about */
667  SCLogDebug("PCRE2 JIT compiler does not support: %s. "
668  "Falling back to regular PCRE2 handling (%s:%d)",
669  regexstr, de_ctx->rule_file, de_ctx->rule_line);
670  }
671  }
672 #endif /*PCRE2_HAVE_JIT*/
673 
674  pd->parse_regex.context = pcre2_match_context_create(NULL);
675  if (pd->parse_regex.context == NULL) {
676  SCLogError("pcre2 could not create match context");
677  goto error;
678  }
679 
680  if (apply_match_limit) {
681  if (pcre_match_limit >= -1) {
682  pcre2_set_match_limit(pd->parse_regex.context, pcre_match_limit);
683  }
684  if (pcre_match_limit_recursion >= -1) {
685  // pcre2_set_depth_limit unsupported on ubuntu 16.04
686  pcre2_set_recursion_limit(pd->parse_regex.context, pcre_match_limit_recursion);
687  }
688  } else {
689  pcre2_set_match_limit(pd->parse_regex.context, SC_MATCH_LIMIT_DEFAULT);
690  pcre2_set_recursion_limit(pd->parse_regex.context, SC_MATCH_LIMIT_RECURSION_DEFAULT);
691  }
692 
693  pcre2_match_data_free(match);
694  return pd;
695 
696 error:
697  pcre2_match_data_free(match);
698  DetectPcreFree(de_ctx, pd);
699  return NULL;
700 }
701 
702 /** \internal
703  * \brief check if we need to extract capture settings and set them up if needed
704  */
705 static int DetectPcreParseCapture(const char *regexstr, DetectEngineCtx *de_ctx, DetectPcreData *pd,
706  char *capture_names)
707 {
708  int ret = 0, res = 0;
709  char type_str[16] = "";
710  const char *orig_right_edge = regexstr + strlen(regexstr);
711  char *name_array[DETECT_PCRE_CAPTURE_MAX] = { NULL };
712  int name_idx = 0;
713  int capture_cnt = 0;
714  int key = 0;
715  size_t copylen;
716  pcre2_match_data *match = NULL;
717 
718  SCLogDebug("regexstr %s, pd %p", regexstr, pd);
719 
720  ret = pcre2_pattern_info(pd->parse_regex.regex, PCRE2_INFO_CAPTURECOUNT, &capture_cnt);
721  SCLogDebug("ret %d capture_cnt %d", ret, capture_cnt);
722  if (ret == 0 && capture_cnt && strlen(capture_names) > 0)
723  {
724  char *ptr = NULL;
725  while ((name_array[name_idx] = strtok_r(name_idx == 0 ? capture_names : NULL, " ,", &ptr))){
726  if (name_idx > (capture_cnt - 1)) {
727  SCLogError("more pkt/flow "
728  "var capture names than capturing substrings");
729  return -1;
730  }
731  SCLogDebug("name '%s'", name_array[name_idx]);
732 
733  if (strcmp(name_array[name_idx], "pkt:key") == 0) {
734  key = 1;
735  SCLogDebug("key-value/key");
736 
737  pd->captypes[pd->idx] = VAR_TYPE_PKT_VAR_KV;
738  SCLogDebug("id %u type %u", pd->capids[pd->idx], pd->captypes[pd->idx]);
739  pd->idx++;
740 
741  } else if (key == 1 && strcmp(name_array[name_idx], "pkt:value") == 0) {
742  SCLogDebug("key-value/value");
743  key = 0;
744 
745  /* kv error conditions */
746  } else if (key == 0 && strcmp(name_array[name_idx], "pkt:value") == 0) {
747  return -1;
748  } else if (key == 1) {
749  return -1;
750 
751  } else if (strncmp(name_array[name_idx], "flow:", 5) == 0) {
752  pd->capids[pd->idx] =
753  VarNameStoreRegister(name_array[name_idx] + 5, VAR_TYPE_FLOW_VAR);
754  pd->captypes[pd->idx] = VAR_TYPE_FLOW_VAR;
755  pd->idx++;
756 
757  } else if (strncmp(name_array[name_idx], "pkt:", 4) == 0) {
758  pd->capids[pd->idx] =
759  VarNameStoreRegister(name_array[name_idx] + 4, VAR_TYPE_PKT_VAR);
760  pd->captypes[pd->idx] = VAR_TYPE_PKT_VAR;
761  SCLogDebug("id %u type %u", pd->capids[pd->idx], pd->captypes[pd->idx]);
762  pd->idx++;
763 
764  } else {
765  SCLogError(" pkt/flow "
766  "var capture names must start with 'pkt:' or 'flow:'");
767  return -1;
768  }
769 
770  name_idx++;
771  if (name_idx >= DETECT_PCRE_CAPTURE_MAX)
772  break;
773  }
774  }
775 
776  /* take the size of the whole input as buffer size for the string we will
777  * extract below. Add 1 to please Coverity's alloc_strlen test. */
778  size_t cap_buffer_len = strlen(regexstr) + 1;
779  char capture_str[cap_buffer_len];
780  memset(capture_str, 0x00, cap_buffer_len);
781 
782  if (de_ctx == NULL)
783  goto error;
784 
785  while (1) {
786  SCLogDebug("\'%s\'", regexstr);
787 
788  ret = DetectParsePcreExec(parse_capture_regex, &match, regexstr, 0, 0);
789  if (ret < 3) {
790  pcre2_match_data_free(match);
791  return 0;
792  }
793  copylen = sizeof(type_str);
794  res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)type_str, &copylen);
795  if (res != 0) {
796  SCLogError("pcre2_substring_copy_bynumber failed");
797  goto error;
798  }
799  cap_buffer_len = strlen(regexstr) + 1;
800  res = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)capture_str, &cap_buffer_len);
801  if (res != 0) {
802  SCLogError("pcre2_substring_copy_bynumber failed");
803  goto error;
804  }
805  if (strlen(capture_str) == 0 || strlen(type_str) == 0) {
806  goto error;
807  }
808 
809  SCLogDebug("type \'%s\'", type_str);
810  SCLogDebug("capture \'%s\'", capture_str);
811 
812  if (pd->idx >= DETECT_PCRE_CAPTURE_MAX) {
813  SCLogError("rule can have maximally %d pkt/flow "
814  "var captures",
816  pcre2_match_data_free(match);
817  return -1;
818  }
819 
820  if (strcmp(type_str, "pkt") == 0) {
821  pd->capids[pd->idx] = VarNameStoreRegister((char *)capture_str, VAR_TYPE_PKT_VAR);
822  pd->captypes[pd->idx] = VAR_TYPE_PKT_VAR;
823  SCLogDebug("id %u type %u", pd->capids[pd->idx], pd->captypes[pd->idx]);
824  pd->idx++;
825  } else if (strcmp(type_str, "flow") == 0) {
826  pd->capids[pd->idx] = VarNameStoreRegister((char *)capture_str, VAR_TYPE_FLOW_VAR);
827  pd->captypes[pd->idx] = VAR_TYPE_FLOW_VAR;
828  pd->idx++;
829  }
830 
831  //SCLogNotice("pd->capname %s", pd->capname);
832  PCRE2_SIZE *ov = pcre2_get_ovector_pointer(match);
833  regexstr += ov[1];
834 
835  pcre2_match_data_free(match);
836  match = NULL;
837 
838  if (regexstr >= orig_right_edge)
839  break;
840  }
841  return 0;
842 
843 error:
844  pcre2_match_data_free(match);
845  return -1;
846 }
847 
848 static void *DetectPcreThreadInit(void *data)
849 {
850  DetectPcreData *pd = (DetectPcreData *)data;
851  pcre2_match_data *match = pcre2_match_data_create_from_pattern(pd->parse_regex.regex, NULL);
852  return match;
853 }
854 
855 static void DetectPcreThreadFree(void *ctx)
856 {
857  if (ctx != NULL) {
858  pcre2_match_data *match = (pcre2_match_data *)ctx;
859  pcre2_match_data_free(match);
860  }
861 }
862 
863 static int DetectPcreSetup (DetectEngineCtx *de_ctx, Signature *s, const char *regexstr)
864 {
865  SCEnter();
866  DetectPcreData *pd = NULL;
867  int parsed_sm_list = DETECT_SM_LIST_NOTSET;
868  char capture_names[1024] = "";
869  AppProto alproto = ALPROTO_UNKNOWN;
870 
871  pd = DetectPcreParse(de_ctx, regexstr, &parsed_sm_list,
872  capture_names, sizeof(capture_names), s->init_data->negated,
873  &alproto);
874  if (pd == NULL)
875  goto error;
876  if (DetectPcreParseCapture(regexstr, de_ctx, pd, capture_names) < 0)
877  goto error;
878 
880  de_ctx, "pcre", DetectPcreThreadInit, (void *)pd, DetectPcreThreadFree, 0);
881  if (pd->thread_ctx_id == -1)
882  goto error;
883 
884  int sm_list = -1;
885  if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
886  if (parsed_sm_list != DETECT_SM_LIST_NOTSET && parsed_sm_list != s->init_data->list) {
887  SCLogError("Expression seen with a sticky buffer still set; either (1) reset sticky "
888  "buffer with pkt_data or (2) use a sticky buffer providing \"%s\".",
890  goto error;
891  }
892  if (DetectBufferGetActiveList(de_ctx, s) == -1)
893  goto error;
894 
895  sm_list = s->init_data->list;
896  } else {
897  switch (parsed_sm_list) {
899  sm_list = DETECT_SM_LIST_PMATCH;
900  break;
901  default: {
902  if (alproto != ALPROTO_UNKNOWN) {
903  /* see if the proto doesn't conflict
904  * with what we already have. */
905  if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, alproto)) {
906  goto error;
907  }
908  if (DetectSignatureSetAppProto(s, alproto) < 0)
909  goto error;
910  }
911  sm_list = parsed_sm_list;
912  break;
913  }
914  }
915  }
916  if (sm_list == -1)
917  goto error;
918 
919  SigMatch *sm = SigMatchAppendSMToList(de_ctx, s, DETECT_PCRE, (SigMatchCtx *)pd, sm_list);
920  if (sm == NULL) {
921  goto error;
922  }
923 
924  for (uint8_t x = 0; x < pd->idx; x++) {
925  if (DetectFlowvarPostMatchSetup(de_ctx, s, pd->capids[x]) < 0)
926  goto error_nofree;
927  }
928 
929  if (!(pd->flags & DETECT_PCRE_RELATIVE))
930  goto okay;
931 
932  /* errors below shouldn't free pd */
933 
934  SigMatch *prev_pm = DetectGetLastSMByListPtr(s, sm->prev,
936  if (s->init_data->list == DETECT_SM_LIST_NOTSET && prev_pm == NULL) {
937  SCLogError("pcre with /R (relative) needs "
938  "preceding match in the same buffer");
939  goto error_nofree;
940  /* null is allowed when we use a sticky buffer */
941  } else if (prev_pm == NULL) {
942  goto okay;
943  }
944  if (prev_pm->type == DETECT_CONTENT) {
945  DetectContentData *cd = (DetectContentData *)prev_pm->ctx;
947  } else if (prev_pm->type == DETECT_PCRE) {
948  DetectPcreData *tmp = (DetectPcreData *)prev_pm->ctx;
950  }
951 
952  okay:
953  SCReturnInt(0);
954  error:
955  DetectPcreFree(de_ctx, pd);
956  error_nofree:
957  SCReturnInt(-1);
958 }
959 
960 static void DetectPcreFree(DetectEngineCtx *de_ctx, void *ptr)
961 {
962  if (ptr == NULL)
963  return;
964 
965  DetectPcreData *pd = (DetectPcreData *)ptr;
968 
969  for (uint8_t i = 0; i < pd->idx; i++) {
970  VarNameStoreUnregister(pd->capids[i], pd->captypes[i]);
971  }
972  SCFree(pd);
973 }
974 
975 #ifdef UNITTESTS /* UNITTESTS */
976 #include "detect-engine-alert.h"
977 static int g_file_data_buffer_id = 0;
978 static int g_http_header_buffer_id = 0;
979 static int g_dce_stub_data_buffer_id = 0;
980 
981 /**
982  * \test DetectPcreParseTest01 make sure we don't allow invalid opts 7.
983  */
984 static int DetectPcreParseTest01 (void)
985 {
986  int result = 1;
987  DetectPcreData *pd = NULL;
988  const char *teststring = "/blah/7";
989  int list = DETECT_SM_LIST_NOTSET;
992  AppProto alproto = ALPROTO_UNKNOWN;
993 
994  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
995  FAIL_IF_NOT_NULL(pd);
996 
998  return result;
999 }
1000 
1001 /**
1002  * \test DetectPcreParseTest02 make sure we don't allow invalid opts Ui$.
1003  */
1004 static int DetectPcreParseTest02 (void)
1005 {
1006  int result = 1;
1007  DetectPcreData *pd = NULL;
1008  const char *teststring = "/blah/Ui$";
1009  int list = DETECT_SM_LIST_NOTSET;
1012  AppProto alproto = ALPROTO_UNKNOWN;
1013 
1014  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1015  FAIL_IF_NOT_NULL(pd);
1016  FAIL_IF_NOT(alproto == ALPROTO_HTTP1);
1017 
1019  return result;
1020 }
1021 
1022 /**
1023  * \test DetectPcreParseTest03 make sure we don't allow invalid opts UZi.
1024  */
1025 static int DetectPcreParseTest03 (void)
1026 {
1027  int result = 1;
1028  DetectPcreData *pd = NULL;
1029  const char *teststring = "/blah/UNi";
1030  int list = DETECT_SM_LIST_NOTSET;
1033  AppProto alproto = ALPROTO_UNKNOWN;
1034 
1035  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1036  FAIL_IF_NOT_NULL(pd);
1037 
1039  return result;
1040 }
1041 
1042 /**
1043  * \test DetectPcreParseTest04 make sure we allow escaped "
1044  */
1045 static int DetectPcreParseTest04 (void)
1046 {
1047  int result = 1;
1048  DetectPcreData *pd = NULL;
1049  const char *teststring = "/b\\\"lah/i";
1050  int list = DETECT_SM_LIST_NOTSET;
1053  AppProto alproto = ALPROTO_UNKNOWN;
1054 
1055  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1056  FAIL_IF_NULL(pd);
1057  FAIL_IF_NOT(alproto == ALPROTO_UNKNOWN);
1058 
1059  DetectPcreFree(de_ctx, pd);
1061  return result;
1062 }
1063 
1064 /**
1065  * \test DetectPcreParseTest05 make sure we parse pcre with no opts
1066  */
1067 static int DetectPcreParseTest05 (void)
1068 {
1069  int result = 1;
1070  DetectPcreData *pd = NULL;
1071  const char *teststring = "/b(l|a)h/";
1072  int list = DETECT_SM_LIST_NOTSET;
1075  AppProto alproto = ALPROTO_UNKNOWN;
1076 
1077  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1078  FAIL_IF_NULL(pd);
1079  FAIL_IF_NOT(alproto == ALPROTO_UNKNOWN);
1080 
1081  DetectPcreFree(de_ctx, pd);
1083  return result;
1084 }
1085 
1086 /**
1087  * \test DetectPcreParseTest06 make sure we parse pcre with smi opts
1088  */
1089 static int DetectPcreParseTest06 (void)
1090 {
1091  int result = 1;
1092  DetectPcreData *pd = NULL;
1093  const char *teststring = "/b(l|a)h/smi";
1094  int list = DETECT_SM_LIST_NOTSET;
1097  AppProto alproto = ALPROTO_UNKNOWN;
1098 
1099  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1100  FAIL_IF_NULL(pd);
1101  FAIL_IF_NOT(alproto == ALPROTO_UNKNOWN);
1102 
1103  DetectPcreFree(de_ctx, pd);
1105  return result;
1106 }
1107 
1108 /**
1109  * \test DetectPcreParseTest07 make sure we parse pcre with /Ui opts
1110  */
1111 static int DetectPcreParseTest07 (void)
1112 {
1113  int result = 1;
1114  DetectPcreData *pd = NULL;
1115  const char *teststring = "/blah/Ui";
1116  int list = DETECT_SM_LIST_NOTSET;
1119  AppProto alproto = ALPROTO_UNKNOWN;
1120 
1121  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1122  FAIL_IF_NULL(pd);
1123  FAIL_IF_NOT(alproto == ALPROTO_HTTP1);
1124 
1125  DetectPcreFree(de_ctx, pd);
1127  return result;
1128 }
1129 
1130 /**
1131  * \test DetectPcreParseTest08 make sure we parse pcre with O opts
1132  */
1133 static int DetectPcreParseTest08 (void)
1134 {
1135  int result = 1;
1136  DetectPcreData *pd = NULL;
1137  const char *teststring = "/b(l|a)h/O";
1138  int list = DETECT_SM_LIST_NOTSET;
1141  AppProto alproto = ALPROTO_UNKNOWN;
1142 
1143  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1144  FAIL_IF_NULL(pd);
1145  FAIL_IF_NOT(alproto == ALPROTO_UNKNOWN);
1146 
1147  DetectPcreFree(de_ctx, pd);
1149  return result;
1150 }
1151 
1152 /**
1153  * \test DetectPcreParseTest09 make sure we parse pcre with a content
1154  * that has slashes
1155  */
1156 static int DetectPcreParseTest09 (void)
1157 {
1158  DetectPcreData *pd = NULL;
1159  const char *teststring = "/lala\\\\/";
1160  int list = DETECT_SM_LIST_NOTSET;
1163  AppProto alproto = ALPROTO_UNKNOWN;
1164 
1165  pd = DetectPcreParse(de_ctx, teststring, &list, NULL, 0, false, &alproto);
1166  FAIL_IF_NULL(pd);
1167 
1168  DetectPcreFree(de_ctx, pd);
1170  PASS;
1171 }
1172 
1173 /**
1174  * \test Test pcre option for dce sig(yeah I'm bored of writing test titles).
1175  */
1176 static int DetectPcreParseTest10(void)
1177 {
1178  Signature *s = SigAlloc();
1181 
1183 
1184  FAIL_IF_NOT(DetectPcreSetup(de_ctx, s, "/bamboo/") == 0);
1185  FAIL_IF_NOT(DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id) == NULL);
1187 
1188  SigFree(de_ctx, s);
1189 
1190  s = SigAlloc();
1191  FAIL_IF_NULL(s);
1192 
1193  /* failure since we have no preceding content/pcre/bytejump */
1194  FAIL_IF_NOT(DetectPcreSetup(de_ctx, s, "/bamboo/") == 0);
1195  FAIL_IF_NOT(DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id) == NULL);
1197 
1198  SigFree(de_ctx, s);
1200 
1201  PASS;
1202 }
1203 
1204 /** \test Check a signature with pcre relative method */
1205 static int DetectPcreParseTest15(void)
1206 {
1207  DetectEngineCtx *de_ctx = NULL;
1208 
1209  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1210 
1211  de_ctx->flags |= DE_QUIET;
1213  "alert tcp any any -> any any "
1214  "(msg:\"Testing pcre relative http_method\"; "
1215  "content:\"GET\"; "
1216  "http_method; pcre:\"/abc/RM\"; sid:1;)");
1218 
1219  if (de_ctx != NULL)
1221  if (de_ctx != NULL)
1223  PASS;
1224 }
1225 
1226 
1227 /** \test Check a signature with pcre relative cookie */
1228 static int DetectPcreParseTest16(void)
1229 {
1230  DetectEngineCtx *de_ctx = NULL;
1231 
1232  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1233 
1234  de_ctx->flags |= DE_QUIET;
1236  "alert tcp any any -> any any "
1237  "(msg:\"Testing pcre relative http_cookie\"; "
1238  "content:\"test\"; "
1239  "http_cookie; pcre:\"/abc/RC\"; sid:1;)");
1241 
1242  if (de_ctx != NULL)
1244  if (de_ctx != NULL)
1246  PASS;
1247 }
1248 
1249 /** \test Check a signature with pcre relative raw header */
1250 static int DetectPcreParseTest17(void)
1251 {
1252  DetectEngineCtx *de_ctx = NULL;
1253 
1254  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1255 
1256  de_ctx->flags |= DE_QUIET;
1258  "alert tcp any any -> any any "
1259  "(msg:\"Testing pcre relative http_raw_header\"; "
1260  "flow:to_server; content:\"test\"; "
1261  "http_raw_header; pcre:\"/abc/RD\"; sid:1;)");
1263 
1264  if (de_ctx != NULL)
1266  if (de_ctx != NULL)
1268  PASS;
1269 }
1270 
1271 /** \test Check a signature with pcre relative header */
1272 static int DetectPcreParseTest18(void)
1273 {
1274  DetectEngineCtx *de_ctx = NULL;
1275 
1276  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1277 
1278  de_ctx->flags |= DE_QUIET;
1280  "alert tcp any any -> any any "
1281  "(msg:\"Testing pcre relative http_header\"; "
1282  "content:\"test\"; "
1283  "http_header; pcre:\"/abc/RH\"; sid:1;)");
1285 
1286  if (de_ctx != NULL)
1288  if (de_ctx != NULL)
1290  PASS;
1291 }
1292 
1293 /** \test Check a signature with pcre relative client-body */
1294 static int DetectPcreParseTest19(void)
1295 {
1296  DetectEngineCtx *de_ctx = NULL;
1297 
1298  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1299 
1300  de_ctx->flags |= DE_QUIET;
1302  "alert tcp any any -> any any "
1303  "(msg:\"Testing pcre relative http_client_body\"; "
1304  "content:\"test\"; "
1305  "http_client_body; pcre:\"/abc/RP\"; sid:1;)");
1307 
1308  if (de_ctx != NULL)
1310  if (de_ctx != NULL)
1312  PASS;
1313 }
1314 
1315 /** \test Check a signature with pcre relative raw uri */
1316 static int DetectPcreParseTest20(void)
1317 {
1318  DetectEngineCtx *de_ctx = NULL;
1319 
1320  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1321 
1322  de_ctx->flags |= DE_QUIET;
1324  "alert tcp any any -> any any "
1325  "(msg:\"Testing http_raw_uri\"; "
1326  "content:\"test\"; "
1327  "http_raw_uri; pcre:\"/abc/RI\"; sid:1;)");
1329 
1330  if (de_ctx != NULL)
1332  if (de_ctx != NULL)
1334  PASS;
1335 }
1336 
1337 /** \test Check a signature with pcre relative uricontent */
1338 static int DetectPcreParseTest21(void)
1339 {
1340  DetectEngineCtx *de_ctx = NULL;
1341 
1342  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1343 
1344  de_ctx->flags |= DE_QUIET;
1346  "alert tcp any any -> any any "
1347  "(msg:\"Testing pcre relative uricontent\"; "
1348  "uricontent:\"test\"; "
1349  "pcre:\"/abc/RU\"; sid:1;)");
1351 
1352  if (de_ctx != NULL)
1354  if (de_ctx != NULL)
1356  PASS;
1357 }
1358 
1359 /** \test Check a signature with pcre relative http_uri */
1360 static int DetectPcreParseTest22(void)
1361 {
1362  DetectEngineCtx *de_ctx = NULL;
1363 
1364  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1365 
1366  de_ctx->flags |= DE_QUIET;
1368  "alert tcp any any -> any any "
1369  "(msg:\"Testing pcre relative http_uri\"; "
1370  "content:\"test\"; "
1371  "http_uri; pcre:\"/abc/RU\"; sid:1;)");
1373 
1374  if (de_ctx != NULL)
1376  if (de_ctx != NULL)
1378  PASS;
1379 }
1380 
1381 /** \test Check a signature with inconsistent pcre relative */
1382 static int DetectPcreParseTest23(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 inconsistent pcre relative\"; "
1392  "content:\"GET\"; "
1393  "http_cookie; pcre:\"/abc/RM\"; sid:1;)");
1395 
1396  if (de_ctx != NULL)
1398  if (de_ctx != NULL)
1400  PASS;
1401 }
1402 
1403 /** \test Check a signature with inconsistent pcre modifiers */
1404 static int DetectPcreParseTest24(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 inconsistent pcre modifiers\"; "
1414  "pcre:\"/abc/UI\"; sid:1;)");
1416 
1417  if (de_ctx != NULL)
1419  if (de_ctx != NULL)
1421  PASS;
1422 }
1423 
1424 /** \test Check a signature with inconsistent pcre modifiers */
1425 static int DetectPcreParseTest25(void)
1426 {
1427  DetectEngineCtx *de_ctx = NULL;
1428 
1429  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1430 
1431  de_ctx->flags |= DE_QUIET;
1433  "alert tcp any any -> any any "
1434  "(msg:\"Testing inconsistent pcre modifiers\"; "
1435  "pcre:\"/abc/DH\"; sid:1;)");
1437 
1438  if (de_ctx != NULL)
1440  if (de_ctx != NULL)
1442  PASS;
1443 }
1444 
1445 /** \test Check a signature with inconsistent pcre modifiers */
1446 static int DetectPcreParseTest26(void)
1447 {
1448  DetectEngineCtx *de_ctx = NULL;
1449 
1450  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1451 
1452  de_ctx->flags |= DE_QUIET;
1454  "alert http any any -> any any "
1455  "(msg:\"Testing inconsistent pcre modifiers\"; "
1456  "pcre:\"/abc/F\"; sid:1;)");
1458 
1459  if (de_ctx != NULL)
1461  if (de_ctx != NULL)
1463  PASS;
1464 }
1465 
1466 /** \test Bug 1098 */
1467 static int DetectPcreParseTest27(void)
1468 {
1469  DetectEngineCtx *de_ctx = NULL;
1470 
1471  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1472 
1473  de_ctx->flags |= DE_QUIET;
1474  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any 80 "
1475  "(content:\"baduricontent\"; http_raw_uri; "
1476  "pcre:\"/^[a-z]{5}\\.html/R\"; sid:2; rev:2;)");
1477  FAIL_IF_NOT(de_ctx->sig_list == NULL);
1478 
1479  if (de_ctx != NULL)
1481  if (de_ctx != NULL)
1483  PASS;
1484 }
1485 
1486 /** \test Bug 1957 */
1487 static int DetectPcreParseTest28(void)
1488 {
1489  DetectEngineCtx *de_ctx = NULL;
1490 
1491  FAIL_IF( (de_ctx = DetectEngineCtxInit()) == NULL);
1492 
1493  de_ctx->flags |= DE_QUIET;
1494  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any 80 "
1495  "(content:\"|2E|suricata\"; http_host; pcre:\"/\\x2Esuricata$/W\"; "
1496  "sid:2; rev:2;)");
1498 
1500  PASS;
1501 }
1502 
1503 static int DetectPcreTestSig01(void)
1504 {
1505  uint8_t *buf = (uint8_t *)"lalala lalala\\ lala\n";
1506  uint16_t buflen = strlen((char *)buf);
1507  Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1508  int result = 0;
1509 
1510  char sig[] = "alert tcp any any -> any any (msg:\"pcre with an ending slash\"; pcre:\"/ "
1511  "lalala\\\\/\"; sid:1;)";
1512  if (UTHPacketMatchSig(p, sig) == 0) {
1513  result = 0;
1514  goto end;
1515  }
1516  result = 1;
1517 end:
1518  if (p != NULL)
1519  UTHFreePacket(p);
1520  return result;
1521 }
1522 
1523 /** \test anchored pcre */
1524 static int DetectPcreTestSig02(void)
1525 {
1526  uint8_t *buf = (uint8_t *)"lalala\n";
1527  uint16_t buflen = strlen((char *)buf);
1528  Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1529 
1530  char sig[] = "alert tcp any any -> any any (msg:\"pcre with an ending slash\"; "
1531  "pcre:\"/^(la)+$/\"; sid:1;)";
1532  FAIL_IF(UTHPacketMatchSig(p, sig) == 0);
1533 
1534  if (p != NULL)
1535  UTHFreePacket(p);
1536  PASS;
1537 }
1538 
1539 /** \test anchored pcre */
1540 static int DetectPcreTestSig03(void)
1541 {
1542  /* test it also without ending in a newline "\n" */
1543  uint8_t *buf = (uint8_t *)"lalala";
1544  uint16_t buflen = strlen((char *)buf);
1545  Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1546 
1547  char sig[] = "alert tcp any any -> any any (msg:\"pcre with an ending slash\"; "
1548  "pcre:\"/^(la)+$/\"; sid:1;)";
1549  FAIL_IF(UTHPacketMatchSig(p, sig) == 0);
1550 
1551  if (p != NULL)
1552  UTHFreePacket(p);
1553  PASS;
1554 }
1555 
1556 /** \test Test tracking of body chunks per transactions (on requests)
1557  */
1558 static int DetectPcreTxBodyChunksTest01(void)
1559 {
1560  Flow f;
1561  TcpSession ssn;
1562  Packet *p = NULL;
1563  uint8_t httpbuf1[] = "GET / HTTP/1.1\r\n";
1564  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
1565  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
1566  uint8_t httpbuf4[] = "Body one!!";
1567  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1568  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1569  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1570  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1571  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
1572  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
1573  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
1574  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
1575  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
1576  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
1578 
1579  memset(&f, 0, sizeof(f));
1580  memset(&ssn, 0, sizeof(ssn));
1581 
1582  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1583 
1584  FLOW_INITIALIZE(&f);
1585  f.protoctx = (void *)&ssn;
1586  f.proto = IPPROTO_TCP;
1587  f.flags |= FLOW_IPV4;
1588 
1589  p->flow = &f;
1593  f.alproto = ALPROTO_HTTP1;
1594 
1595  StreamTcpInitConfig(true);
1596 
1598 
1599  int r = AppLayerParserParse(
1600  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1601  FAIL_IF(r != 0);
1602 
1603  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1604  FAIL_IF(r != 0);
1605 
1606  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1607  FAIL_IF(r != 0);
1608 
1609  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
1610  FAIL_IF(r != 0);
1611 
1612  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
1613  FAIL_IF(r != 0);
1614 
1615  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
1616  FAIL_IF(r != 0);
1617 
1618  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf7, httplen7);
1619  FAIL_IF(r != 0);
1620 
1621  /* Now we should have 2 transactions, each with it's own list
1622  * of request body chunks (let's test it) */
1623 
1624  HtpState *htp_state = f.alstate;
1625  FAIL_IF(htp_state == NULL);
1626 
1627  /* hardcoded check of the transactions and it's client body chunks */
1628  FAIL_IF(AppLayerParserGetTxCnt(&f, htp_state) != 2);
1629 
1630  htp_tx_t *t1 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, 0);
1631  htp_tx_t *t2 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, 1);
1632 
1633  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
1634  FAIL_IF(htud == NULL);
1635 
1636  HtpBodyChunk *cur = htud->request_body.first;
1637  FAIL_IF(htud->request_body.first == NULL);
1638 
1639  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body one!!", 10) != 1);
1640 
1641  htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
1642 
1643  cur = htud->request_body.first;
1644  FAIL_IF(htud->request_body.first == NULL);
1645 
1646  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body two!!", 10) != 1);
1647 
1648  if (alp_tctx != NULL)
1650  StreamTcpFreeConfig(true);
1651  FLOW_DESTROY(&f);
1652  UTHFreePacket(p);
1653  PASS;
1654 }
1655 
1656 /** \test test pcre P modifier with multiple pipelined http transactions */
1657 static int DetectPcreTxBodyChunksTest02(void)
1658 {
1659  Signature *s = NULL;
1660  DetectEngineThreadCtx *det_ctx = NULL;
1661  ThreadVars th_v;
1662  Flow f;
1663  TcpSession ssn;
1664  Packet *p = NULL;
1665  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
1666  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
1667  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
1668  uint8_t httpbuf4[] = "Body one!!";
1669  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1670  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1671  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1672  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1673  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
1674  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
1675  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
1676  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
1677  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
1678  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
1680 
1681  memset(&th_v, 0, sizeof(th_v));
1682  memset(&f, 0, sizeof(f));
1683  memset(&ssn, 0, sizeof(ssn));
1684 
1685  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1686 
1687  FLOW_INITIALIZE(&f);
1688  f.protoctx = (void *)&ssn;
1689  f.proto = IPPROTO_TCP;
1690  f.flags |= FLOW_IPV4;
1691 
1692  p->flow = &f;
1696  f.alproto = ALPROTO_HTTP1;
1697 
1698  StreamTcpInitConfig(true);
1699 
1701  FAIL_IF(de_ctx == NULL);
1702 
1703  de_ctx->flags |= DE_QUIET;
1704 
1705  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;)");
1706  FAIL_IF(s == NULL);
1707  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;)");
1708  FAIL_IF(s == NULL);
1709 
1711  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1712 
1713  int r = AppLayerParserParse(
1714  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1715  FAIL_IF(r != 0);
1716 
1717  /* do detect */
1718  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1719  FAIL_IF(PacketAlertCheck(p, 1));
1720  p->alerts.cnt = 0;
1721 
1722  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1723  FAIL_IF(r != 0);
1724 
1725  /* do detect */
1726  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1727  FAIL_IF(PacketAlertCheck(p, 1));
1728  p->alerts.cnt = 0;
1729 
1730  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1731  FAIL_IF(r != 0);
1732 
1733  /* do detect */
1734  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1735  FAIL_IF(PacketAlertCheck(p, 1));
1736  p->alerts.cnt = 0;
1737 
1738  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
1739  FAIL_IF(r != 0);
1740 
1741  /* do detect */
1742  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1743  FAIL_IF(!(PacketAlertCheck(p, 1)));
1744  p->alerts.cnt = 0;
1745 
1746  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
1747  FAIL_IF(r != 0);
1748 
1749  /* do detect */
1750  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1751  FAIL_IF(PacketAlertCheck(p, 1));
1752  p->alerts.cnt = 0;
1753 
1754  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
1755  FAIL_IF(r != 0);
1756 
1757  /* do detect */
1758  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1759  FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
1760  p->alerts.cnt = 0;
1761 
1762  SCLogDebug("sending data chunk 7");
1763 
1764  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf7, httplen7);
1765  FAIL_IF(r != 0);
1766 
1767  /* do detect */
1768  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1769  FAIL_IF(!(PacketAlertCheck(p, 2)));
1770  p->alerts.cnt = 0;
1771 
1772  HtpState *htp_state = f.alstate;
1773  FAIL_IF(htp_state == NULL);
1774 
1775  /* hardcoded check of the transactions and it's client body chunks */
1776  FAIL_IF(AppLayerParserGetTxCnt(&f, htp_state) != 2);
1777 
1778  htp_tx_t *t1 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, 0);
1779  htp_tx_t *t2 = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, 1);
1780 
1781  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
1782 
1783  HtpBodyChunk *cur = htud->request_body.first;
1784  FAIL_IF(htud->request_body.first == NULL);
1785 
1786  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body one!!", 10) != 1);
1787 
1788  htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
1789 
1790  cur = htud->request_body.first;
1791  FAIL_IF(htud->request_body.first == NULL);
1792 
1793  FAIL_IF(StreamingBufferSegmentCompareRawData(htud->request_body.sb, &cur->sbseg, (uint8_t *)"Body two!!", 10) != 1);
1794 
1795  if (alp_tctx != NULL)
1797  if (det_ctx != NULL) {
1798  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1799  }
1800  if (de_ctx != NULL) {
1803  }
1804 
1805  StreamTcpFreeConfig(true);
1806  FLOW_DESTROY(&f);
1807  UTHFreePacket(p);
1808  PASS;
1809 }
1810 
1811 /** \test multiple http transactions and body chunks of request handling */
1812 static int DetectPcreTxBodyChunksTest03(void)
1813 {
1814  Signature *s = NULL;
1815  DetectEngineThreadCtx *det_ctx = NULL;
1816  ThreadVars th_v;
1817  Flow f;
1818  TcpSession ssn;
1819  Packet *p = NULL;
1820  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
1821  uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
1822  uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
1823  uint8_t httpbuf4[] = "Body one!!";
1824  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1825  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1826  uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1827  uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1828  uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
1829  uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
1830  uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
1831  uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
1832  uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
1833  uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
1835 
1836  memset(&th_v, 0, sizeof(th_v));
1837  memset(&f, 0, sizeof(f));
1838  memset(&ssn, 0, sizeof(ssn));
1839 
1840  p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1841 
1842  FLOW_INITIALIZE(&f);
1843  f.protoctx = (void *)&ssn;
1844  f.proto = IPPROTO_TCP;
1845  f.flags |= FLOW_IPV4;
1846 
1847  p->flow = &f;
1851  f.alproto = ALPROTO_HTTP1;
1852 
1853  StreamTcpInitConfig(true);
1854 
1856  FAIL_IF(de_ctx == NULL);
1857 
1858  de_ctx->flags |= DE_QUIET;
1859 
1860  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;)");
1861  FAIL_IF(s == NULL);
1862  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;)");
1863  FAIL_IF(s == NULL);
1864 
1866  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1867 
1868  int r = AppLayerParserParse(
1869  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1870  FAIL_IF(r != 0);
1871 
1872  /* do detect */
1873  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1874  FAIL_IF(PacketAlertCheck(p, 1));
1875  p->alerts.cnt = 0;
1876 
1877  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1878  FAIL_IF(r != 0);
1879 
1880  /* do detect */
1881  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1882  FAIL_IF(PacketAlertCheck(p, 1));
1883  p->alerts.cnt = 0;
1884 
1885  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1886  FAIL_IF(r != 0);
1887 
1888  /* do detect */
1889  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1890  FAIL_IF(PacketAlertCheck(p, 1));
1891  p->alerts.cnt = 0;
1892 
1893  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
1894  FAIL_IF(r != 0);
1895 
1896  /* do detect */
1897  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1898  FAIL_IF(!(PacketAlertCheck(p, 1)));
1899  p->alerts.cnt = 0;
1900 
1901  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
1902  FAIL_IF(r != 0);
1903 
1904  /* do detect */
1905  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1906  FAIL_IF(PacketAlertCheck(p, 1));
1907  p->alerts.cnt = 0;
1908 
1909  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
1910  FAIL_IF(r != 0);
1911 
1912  /* do detect */
1913  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1914  FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
1915  p->alerts.cnt = 0;
1916 
1917  SCLogDebug("sending data chunk 7");
1918 
1919  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf7, httplen7);
1920  FAIL_IF(r != 0);
1921 
1922  /* do detect */
1923  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1924  FAIL_IF(!(PacketAlertCheck(p, 2)));
1925  p->alerts.cnt = 0;
1926 
1927  HtpState *htp_state = f.alstate;
1928  FAIL_IF(htp_state == NULL);
1929 
1930  FAIL_IF(AppLayerParserGetTxCnt(&f, htp_state) != 2);
1931 
1932  if (alp_tctx != NULL)
1934  if (det_ctx != NULL) {
1935  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1936  }
1937  if (de_ctx != NULL) {
1940  }
1941 
1942  StreamTcpFreeConfig(true);
1943  FLOW_DESTROY(&f);
1944  UTHFreePacket(p);
1945  PASS;
1946 }
1947 
1948 /**
1949  * \brief Test parsing of pcre's with the W modifier set.
1950  */
1951 static int DetectPcreParseHttpHost(void)
1952 {
1953  AppProto alproto = ALPROTO_UNKNOWN;
1954  int list = DETECT_SM_LIST_NOTSET;
1956 
1957  FAIL_IF(de_ctx == NULL);
1958 
1959  DetectPcreData *pd = DetectPcreParse(de_ctx, "/domain\\.com/W", &list, NULL, 0, false, &alproto);
1960  FAIL_IF(pd == NULL);
1961  DetectPcreFree(de_ctx, pd);
1962 
1963  list = DETECT_SM_LIST_NOTSET;
1964  pd = DetectPcreParse(de_ctx, "/dOmain\\.com/W", &list, NULL, 0, false, &alproto);
1965  FAIL_IF(pd != NULL);
1966 
1967  /* Uppercase meta characters are valid. */
1968  list = DETECT_SM_LIST_NOTSET;
1969  pd = DetectPcreParse(de_ctx, "/domain\\D+\\.com/W", &list, NULL, 0, false, &alproto);
1970  FAIL_IF(pd == NULL);
1971  DetectPcreFree(de_ctx, pd);
1972 
1973  /* This should not parse as the first \ escapes the second \, then
1974  * we have a D. */
1975  list = DETECT_SM_LIST_NOTSET;
1976  pd = DetectPcreParse(de_ctx, "/\\\\Ddomain\\.com/W", &list, NULL, 0, false, &alproto);
1977  FAIL_IF(pd != NULL);
1978 
1980  PASS;
1981 }
1982 
1983 /**
1984  * \brief Test parsing of capture extension
1985  */
1986 static int DetectPcreParseCaptureTest(void)
1987 {
1989  FAIL_IF(de_ctx == NULL);
1990 
1991  Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
1992  "(content:\"Server: \"; http_header; pcre:\"/(.*)\\r\\n/HR, flow:somecapture\"; content:\"xyz\"; http_header; sid:1;)");
1993  FAIL_IF(s == NULL);
1994  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
1995  "(content:\"Server: \"; http_header; pcre:\"/(flow:.*)\\r\\n/HR\"; content:\"xyz\"; http_header; sid:2;)");
1996  FAIL_IF(s == NULL);
1997  s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
1998  "(content:\"Server: \"; http_header; pcre:\"/([a-z]+)([0-9]+)\\r\\n/HR, flow:somecapture, pkt:anothercap\"; content:\"xyz\"; http_header; sid:3;)");
1999  FAIL_IF(s == NULL);
2001  "alert http any any -> any any "
2002  "(content:\"Server: \"; http_header; pcre:\"/([a-z]+)\\r\\n/HR, flow:somecapture, "
2003  "pkt:anothercap\"; content:\"xyz\"; http_header; sid:3;)");
2004  FAIL_IF_NOT_NULL(s);
2005 
2007 
2008  uint32_t capid1 = VarNameStoreLookupByName("somecapture", VAR_TYPE_FLOW_VAR);
2009  FAIL_IF(capid1 == 0);
2010  uint32_t capid2 = VarNameStoreLookupByName("anothercap", VAR_TYPE_PKT_VAR);
2011  FAIL_IF(capid2 == 0);
2012  FAIL_IF(capid1 == capid2);
2013 
2015  PASS;
2016 }
2017 
2018 /**
2019  * \brief this function registers unit tests for DetectPcre
2020  */
2021 static void DetectPcreRegisterTests(void)
2022 {
2023  g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
2024  g_http_header_buffer_id = DetectBufferTypeGetByName("http_header");
2025  g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
2026 
2027  UtRegisterTest("DetectPcreParseTest01", DetectPcreParseTest01);
2028  UtRegisterTest("DetectPcreParseTest02", DetectPcreParseTest02);
2029  UtRegisterTest("DetectPcreParseTest03", DetectPcreParseTest03);
2030  UtRegisterTest("DetectPcreParseTest04", DetectPcreParseTest04);
2031  UtRegisterTest("DetectPcreParseTest05", DetectPcreParseTest05);
2032  UtRegisterTest("DetectPcreParseTest06", DetectPcreParseTest06);
2033  UtRegisterTest("DetectPcreParseTest07", DetectPcreParseTest07);
2034  UtRegisterTest("DetectPcreParseTest08", DetectPcreParseTest08);
2035  UtRegisterTest("DetectPcreParseTest09", DetectPcreParseTest09);
2036  UtRegisterTest("DetectPcreParseTest10", DetectPcreParseTest10);
2037  UtRegisterTest("DetectPcreParseTest15", DetectPcreParseTest15);
2038  UtRegisterTest("DetectPcreParseTest16", DetectPcreParseTest16);
2039  UtRegisterTest("DetectPcreParseTest17", DetectPcreParseTest17);
2040  UtRegisterTest("DetectPcreParseTest18", DetectPcreParseTest18);
2041  UtRegisterTest("DetectPcreParseTest19", DetectPcreParseTest19);
2042  UtRegisterTest("DetectPcreParseTest20", DetectPcreParseTest20);
2043  UtRegisterTest("DetectPcreParseTest21", DetectPcreParseTest21);
2044  UtRegisterTest("DetectPcreParseTest22", DetectPcreParseTest22);
2045  UtRegisterTest("DetectPcreParseTest23", DetectPcreParseTest23);
2046  UtRegisterTest("DetectPcreParseTest24", DetectPcreParseTest24);
2047  UtRegisterTest("DetectPcreParseTest25", DetectPcreParseTest25);
2048  UtRegisterTest("DetectPcreParseTest26", DetectPcreParseTest26);
2049  UtRegisterTest("DetectPcreParseTest27", DetectPcreParseTest27);
2050  UtRegisterTest("DetectPcreParseTest28", DetectPcreParseTest28);
2051 
2052  UtRegisterTest("DetectPcreTestSig01", DetectPcreTestSig01);
2053  UtRegisterTest("DetectPcreTestSig02 -- anchored pcre", DetectPcreTestSig02);
2054  UtRegisterTest("DetectPcreTestSig03 -- anchored pcre", DetectPcreTestSig03);
2055 
2056  UtRegisterTest("DetectPcreTxBodyChunksTest01",
2057  DetectPcreTxBodyChunksTest01);
2058  UtRegisterTest("DetectPcreTxBodyChunksTest02 -- modifier P, body chunks per tx",
2059  DetectPcreTxBodyChunksTest02);
2060  UtRegisterTest("DetectPcreTxBodyChunksTest03 -- modifier P, body chunks per tx",
2061  DetectPcreTxBodyChunksTest03);
2062 
2063  UtRegisterTest("DetectPcreParseHttpHost", DetectPcreParseHttpHost);
2064  UtRegisterTest("DetectPcreParseCaptureTest", DetectPcreParseCaptureTest);
2065 }
2066 #endif /* UNITTESTS */
DETECT_PCRE_CASELESS
#define DETECT_PCRE_CASELESS
Definition: detect-pcre.h:32
ConfGetInt
int ConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:399
SigTableElmt_::url
const char * url
Definition: detect.h:1304
SC_MATCH_LIMIT_DEFAULT
#define SC_MATCH_LIMIT_DEFAULT
Definition: detect-pcre.h:39
DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_RELATIVE_NEXT
Definition: detect-content.h:66
DetectSignatureSetAppProto
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
Definition: detect-parse.c:1737
SigMatch_::prev
struct SigMatch_ * prev
Definition: detect.h:354
detect-content.h
DetectPcreData_::idx
uint8_t idx
Definition: detect-pcre.h:47
len
uint8_t len
Definition: app-layer-dnp3.h:2
DetectEngineThreadCtx_::buffer_offset
uint32_t buffer_offset
Definition: detect.h:1119
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:259
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:116
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:586
SigTableElmt_::desc
const char * desc
Definition: detect.h:1303
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:127
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1281
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:1291
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:173
DetectParseRegex
Definition: detect-parse.h:62
SigTableElmt_::name
const char * name
Definition: detect.h:1301
stream-tcp.h
HtpBody_::sb
StreamingBuffer * sb
Definition: app-layer-htp.h:187
SigFree
void SigFree(DetectEngineCtx *, Signature *)
Definition: detect-parse.c:1628
DetectEngineCtx_::rule_file
char * rule_file
Definition: detect.h:930
DetectThreadCtxGetKeywordThreadCtx
void * DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
Definition: detect-engine.c:3661
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:223
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:70
DetectParseRegex::context
pcre2_match_context * context
Definition: detect-parse.h:64
Signature_::alproto
AppProto alproto
Definition: detect.h:606
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
SIGMATCH_QUOTES_OPTIONAL
#define SIGMATCH_QUOTES_OPTIONAL
Definition: detect.h:1497
Flow_::proto
uint8_t proto
Definition: flow.h:382
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:82
PacketAlerts_::cnt
uint16_t cnt
Definition: decode.h:274
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:141
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:361
Packet_::flags
uint32_t flags
Definition: decode.h:519
Flow_
Flow data structure.
Definition: flow.h:360
DetectSetupPCRE2
DetectParseRegex * DetectSetupPCRE2(const char *parse_str, int opts)
Definition: detect-parse.c:2728
PARSE_REGEX
#define PARSE_REGEX
Definition: detect-pcre.c:66
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1295
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:841
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2592
HtpTxUserData_::request_body
HtpBody request_body
Definition: app-layer-htp.h:217
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:300
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:232
util-var-name.h
MIN
#define MIN(x, y)
Definition: suricata-common.h:391
DetectParseRegex::regex
pcre2_code * regex
Definition: detect-parse.h:63
DetectPcreData_::parse_regex
DetectParseRegex parse_regex
Definition: detect-pcre.h:43
DE_QUIET
#define DE_QUIET
Definition: detect.h:323
UTHPacketMatchSig
int UTHPacketMatchSig(Packet *p, const char *sig)
Definition: util-unittest-helper.c:804
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:668
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:359
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1904
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
Definition: detect-parse.c:2652
DetectContentData_
Definition: detect-content.h:93
DetectPcreData_::flags
uint16_t flags
Definition: detect-pcre.h:46
VarNameStoreRegister
uint32_t VarNameStoreRegister(const char *name, const enum VarTypes type)
Definition: util-var-name.c:155
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:55
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:745
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2598
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:513
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:1417
StreamingBufferSegmentCompareRawData
int StreamingBufferSegmentCompareRawData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t *rawdata, uint32_t rawdata_len)
Definition: util-streaming-buffer.c:1770
Flow_::protoctx
void * protoctx
Definition: flow.h:450
SigMatchData_
Data needed for Match()
Definition: detect.h:358
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1286
detect-pcre.h
PARSE_CAPTURE_REGEX
#define PARSE_CAPTURE_REGEX
Definition: detect-pcre.c:65
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:99
Packet_::alerts
PacketAlerts alerts
Definition: decode.h:603
util-unittest.h
HtpBody_::first
HtpBodyChunk * first
Definition: app-layer-htp.h:184
HtpState_
Definition: app-layer-htp.h:236
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
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1086
VAR_TYPE_PKT_VAR_KV
@ VAR_TYPE_PKT_VAR_KV
Definition: util-var.h:34
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:49
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:461
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
app-layer-htp.h
VarNameStoreLookupByName
uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
find name for id+type at packet time.
Definition: util-var-name.c:322
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
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
DETECT_PCRE_RAWBYTES
#define DETECT_PCRE_RAWBYTES
Definition: detect-pcre.h:31
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1090
DetectEngineBufferTypeGetDescriptionById
const char * DetectEngineBufferTypeGetDescriptionById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1194
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:474
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:22
SignatureInitData_::list
int list
Definition: detect.h:570
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DetectPcreData_::thread_ctx_id
int thread_ctx_id
Definition: detect-pcre.h:44
pkt-var.h
VarNameStoreUnregister
void VarNameStoreUnregister(const uint32_t id, const enum VarTypes type)
Definition: util-var-name.c:201
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2296
app-layer-parser.h
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:352
SC_MATCH_LIMIT_RECURSION_DEFAULT
#define SC_MATCH_LIMIT_RECURSION_DEFAULT
Definition: detect-pcre.h:40
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2228
stream.h
Packet_
Definition: decode.h:482
detect-engine-build.h
stream-tcp-private.h
detect-engine-alert.h
conf.h
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:104
SIGMATCH_HANDLE_NEGATION
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1505
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:670
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
SignatureInitData_::negated
bool negated
Definition: detect.h:545
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1269
PageSupportsRWX
#define PageSupportsRWX()
Definition: util-pages.h:37
util-pages.h
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:72
DETECT_VAR_TYPE_FLOW_POSTMATCH
#define DETECT_VAR_TYPE_FLOW_POSTMATCH
Definition: detect.h:744
AppLayerParserGetTx
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Definition: app-layer-parser.c:1088
DetectPcreData_::captypes
uint8_t captypes[DETECT_PCRE_CAPTURE_MAX]
Definition: detect-pcre.h:48
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2161
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:279
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:344
DETECT_SM_LIST_NOTSET
#define DETECT_SM_LIST_NOTSET
Definition: detect.h:141
Packet_::flow
struct Flow_ * flow
Definition: decode.h:521
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3307
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:792
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:3591
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:1266
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3534
SigMatch_::type
uint16_t type
Definition: detect.h:350
HtpBodyChunk_
Definition: app-layer-htp.h:175
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:30
DetectBufferGetFirstSigMatch
SigMatch * DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id)
Definition: detect-engine.c:1318
FatalError
#define FatalError(...)
Definition: util-debug.h:502
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:849
HtpTxUserData_
Definition: app-layer-htp.h:204
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:1123
str
#define str(s)
Definition: suricata-common.h:291
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
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:467
Flow_::alstate
void * alstate
Definition: flow.h:485
Flow_::flags
uint32_t flags
Definition: flow.h:430
detect-parse.h
Signature_
Signature container.
Definition: detect.h:601
SigMatch_
a single match condition for a signature
Definition: detect.h:349
payload_len
uint16_t payload_len
Definition: stream-tcp-private.h:1
VAR_TYPE_FLOW_VAR
@ VAR_TYPE_FLOW_VAR
Definition: util-var.h:38
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:234
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2553
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:203
DetectPcreData_
Definition: detect-pcre.h:42
DetectParseFreeRegex
void DetectParseFreeRegex(DetectParseRegex *r)
Definition: detect-parse.c:2662
SigMatchAppendSMToList
SigMatch * SigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:436
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:843
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:58
DETECT_PCRE_RELATIVE
#define DETECT_PCRE_RELATIVE
Definition: detect-pcre.h:29
SigAlloc
Signature * SigAlloc(void)
Definition: detect-parse.c:1513
DetectUnregisterThreadCtxFuncs
int DetectUnregisterThreadCtxFuncs(DetectEngineCtx *de_ctx, void *data, const char *name)
Remove Thread keyword context registration.
Definition: detect-engine.c:3643
DetectEngineCtx_::rule_line
int rule_line
Definition: detect.h:929
TcpSession_
Definition: stream-tcp-private.h:283
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:459
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-pool.h
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
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:1081
HtpBodyChunk_::sbseg
StreamingBufferSegment sbseg
Definition: app-layer-htp.h:178
DetectPcreRegister
void DetectPcreRegister(void)
Definition: detect-pcre.c:96
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:121
VAR_TYPE_PKT_VAR
@ VAR_TYPE_PKT_VAR
Definition: util-var.h:33
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1278
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1293
app-layer.h