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