66#define PARSE_CAPTURE_REGEX "\\(\\?P\\<([A-z]+)\\_([A-z0-9_]+)\\>"
67#define PARSE_REGEX "(?<!\\\\)/(.*(?<!(?<!\\\\)\\\\))/([^\"]*)"
69static int pcre_match_limit = 0;
70static int pcre_match_limit_recursion = 0;
76static int pcre2_use_jit = 1;
84 const char *
str,
const size_t strlen,
int start_offset,
int options,
85 pcre2_match_data *match)
94static void DetectPcreRegisterTests(
void);
114 SCLogDebug(
"Using PCRE match-limit setting of: %i", pcre_match_limit);
116 pcre_match_limit = (int)val;
118 SCLogInfo(
"Using PCRE match-limit setting of: %i", pcre_match_limit);
120 SCLogDebug(
"Using PCRE match-limit setting of: %i", pcre_match_limit);
126 if (!
SCConfGetInt(
"pcre.match-limit-recursion", &val)) {
128 SCLogDebug(
"Using PCRE match-limit-recursion setting of: %i", pcre_match_limit_recursion);
130 pcre_match_limit_recursion = (int)val;
132 SCLogInfo(
"Using PCRE match-limit-recursion setting of: %i", pcre_match_limit_recursion);
134 SCLogDebug(
"Using PCRE match-limit-recursion setting of: %i", pcre_match_limit_recursion);
139 if (parse_regex == NULL) {
140 FatalError(
"pcre2 compile failed for parse_regex");
146 if (parse_capture_regex == NULL) {
147 FatalError(
"pcre2 compile failed for parse_capture_regex");
152 SCLogConfig(
"PCRE2 won't use JIT as OS doesn't allow RWX pages");
159 uint8_t *str_ptr, uint16_t capture_len)
164 if (json_key == NULL) {
176 SCJsonBuilder *js = SCJbNewObject();
181 SCJbSetStringFromBytes(js, json_key, str_ptr, capture_len);
182 uint32_t js_len = (uint32_t)SCJbLen(js);
184 SCLogDebug(
"Captured length is too long for JSON.");
190 SCLogDebug(
"Captured length is zero for JSON.");
228 const uint8_t *ptr = NULL;
230 PCRE2_SIZE capture_len = 0;
242 int start_offset = 0;
248 pcre2_match_data *match =
251 ret = DetectPcreExec(det_ctx, pe, (
char *)ptr,
len, start_offset, 0, match);
254 if (ret == PCRE2_ERROR_NOMATCH) {
262 }
else if (ret >= 0) {
274 if (ret > 1 && pe->
idx != 0) {
276 for (x = 0; x < pe->
idx; x++) {
278 const char *pcre2_str_ptr = NULL;
279 ret = pcre2_substring_get_bynumber(
280 match, x + 1, (PCRE2_UCHAR8 **)&pcre2_str_ptr, &capture_len);
282 pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr);
286 capture_len = (capture_len < 0xffff) ? (uint16_t)capture_len : 0xffff;
287 uint8_t *str_ptr =
SCMalloc(capture_len);
289 pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr);
292 memcpy(str_ptr, pcre2_str_ptr, capture_len);
293 pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr);
300 const char *pcre2_str_ptr2 = NULL;
302 uint16_t key_len = (capture_len < 0xff) ? (uint16_t)capture_len : 0xff;
303 int ret2 = pcre2_substring_get_bynumber(
304 match, x + 2, (PCRE2_UCHAR8 **)&pcre2_str_ptr2, &capture_len);
308 pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr2);
311 capture_len = (capture_len < 0xffff) ? (uint16_t)capture_len : 0xffff;
312 uint8_t *str_ptr2 =
SCMalloc(capture_len);
315 pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr2);
318 memcpy(str_ptr2, pcre2_str_ptr2, capture_len);
319 pcre2_substring_free((PCRE2_UCHAR8 *)pcre2_str_ptr2);
322 (uint8_t *)str_ptr2, (uint16_t)capture_len,
334 (void)DetectAlertStoreMatch(det_ctx, s, pe->
capids[x], (uint8_t *)str_ptr,
335 (uint16_t)capture_len);
344 PCRE2_SIZE *ov = pcre2_get_ovector_pointer(match);
346 det_ctx->
buffer_offset = (uint32_t)((ptr + ov[1]) - payload);
359static int DetectPcreSetList(
int list,
int set)
362 SCLogError(
"only one pcre option to specify a buffer type is allowed");
368static int DetectPcreHasUpperCase(
const char *re)
370 size_t len = strlen(re);
371 bool is_meta =
false;
372 bool is_meta_hex =
false;
373 int meta_hex_cnt = 0;
375 for (
size_t i = 0; i <
len; i++) {
379 if (meta_hex_cnt == 2) {
383 }
else if (is_meta) {
390 else if (re[i] ==
'\\') {
393 else if (isupper((
unsigned char)re[i])) {
402 const char *regexstr,
int *sm_list,
char *capture_names,
403 size_t capture_names_size,
bool negate,
AppProto *alproto)
405 pcre2_match_data *match = NULL;
411 int ret = 0, res = 0;
412 int check_host_header = 0;
413 char op_str[64] =
"";
415 bool apply_match_limit =
false;
418 char *fcap = strstr(regexstr,
"flow:");
419 char *pcap = strstr(regexstr,
"pkt:");
420 char *acap = strstr(regexstr,
"alert:");
423 size_t slen = strlen(regexstr) + 1;
424 if (fcap || pcap || acap) {
431 cut_capture = (int)(fcap - regexstr);
435 cut_capture = (int)
MIN(cut_capture, (pcap - regexstr));
437 cut_capture = (int)(pcap - regexstr);
443 cut_capture =
MIN(cut_capture, (
int)(acap - regexstr));
445 cut_capture = (int)(acap - regexstr);
450 if (cut_capture > 1) {
451 int offset = cut_capture - 1;
454 if (regexstr[
offset] ==
',' || regexstr[
offset] ==
' ') {
461 if (cut_capture == (
offset + 1)) {
462 SCLogDebug(
"missing separators, assume it's part of the regex");
465 strlcpy(capture_names, regexstr+cut_capture, capture_names_size);
466 if (capture_names[strlen(capture_names)-1] ==
'"')
467 capture_names[strlen(capture_names)-1] =
'\0';
474 match = pcre2_match_data_create_from_pattern(parse_regex->
regex, NULL);
479 ret = pcre2_match(parse_regex->
regex, (PCRE2_SPTR8)regexstr, slen, 0, 0, match, NULL);
485 res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)re, &slen);
487 SCLogError(
"pcre2_substring_copy_bynumber failed");
488 pcre2_match_data_free(match);
493 size_t copylen =
sizeof(op_str);
494 res = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)op_str, ©len);
496 SCLogError(
"pcre2_substring_copy_bynumber failed");
497 pcre2_match_data_free(match);
517 opts |= PCRE2_ANCHORED;
520 opts |= PCRE2_DOLLAR_ENDONLY;
523 opts |= PCRE2_UNGREEDY;
527 opts |= PCRE2_CASELESS;
531 opts |= PCRE2_MULTILINE;
534 opts |= PCRE2_DOTALL;
537 opts |= PCRE2_EXTENDED;
541 apply_match_limit =
true;
546 SCLogError(
"regex modifier 'B' inconsistent with chosen buffer");
559 SCLogError(
"regex modifier 'U' inconsistent with 'B'");
563 *sm_list = DetectPcreSetList(*sm_list, list);
569 SCLogError(
"regex modifier 'V' inconsistent with 'B'");
573 *sm_list = DetectPcreSetList(*sm_list, list);
579 SCLogError(
"regex modifier 'W' inconsistent with 'B'");
583 *sm_list = DetectPcreSetList(*sm_list, list);
585 check_host_header = 1;
590 SCLogError(
"regex modifier 'Z' inconsistent with 'B'");
594 *sm_list = DetectPcreSetList(*sm_list, list);
600 SCLogError(
"regex modifier 'H' inconsistent with 'B'");
604 *sm_list = DetectPcreSetList(*sm_list, list);
609 SCLogError(
"regex modifier 'I' inconsistent with 'B'");
613 *sm_list = DetectPcreSetList(*sm_list, list);
619 *sm_list = DetectPcreSetList(*sm_list, list);
625 SCLogError(
"regex modifier 'M' inconsistent with 'B'");
629 *sm_list = DetectPcreSetList(*sm_list, list);
635 SCLogError(
"regex modifier 'C' inconsistent with 'B'");
639 *sm_list = DetectPcreSetList(*sm_list, list);
646 *sm_list = DetectPcreSetList(*sm_list, list);
653 *sm_list = DetectPcreSetList(*sm_list, list);
660 *sm_list = DetectPcreSetList(*sm_list, list);
667 *sm_list = DetectPcreSetList(*sm_list, list);
672 SCLogError(
"unknown regex modifier '%c'", *op);
684 if (check_host_header) {
687 "specified along with \"i(caseless)\" modifier. "
688 "Since the hostname buffer we match against "
689 "is actually lowercase, having a "
690 "nocase is redundant.");
692 else if (DetectPcreHasUpperCase(re)) {
694 "specified has an uppercase char. "
695 "Since the hostname buffer we match against "
696 "is actually lowercase, please specify an "
697 "all lowercase based pcre.");
707 if (capture_names == NULL || strlen(capture_names) == 0)
708 opts |= PCRE2_NO_AUTO_CAPTURE;
711 pcre2_compile((PCRE2_SPTR8)re, PCRE2_ZERO_TERMINATED, opts, &en, &eo2, NULL);
713 opts &= ~PCRE2_NO_AUTO_CAPTURE;
715 pcre2_compile((PCRE2_SPTR8)re, PCRE2_ZERO_TERMINATED, opts, &en, &eo2, NULL);
718 PCRE2_UCHAR errbuffer[256];
719 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
720 SCLogError(
"pcre2 compile of \"%s\" failed at "
722 regexstr, (
int)eo2, errbuffer);
733 SCLogDebug(
"PCRE2 JIT compiler does not support: %s. "
734 "Falling back to regular PCRE2 handling (%s:%d)",
742 SCLogError(
"pcre2 could not create match context");
746 if (apply_match_limit) {
747 if (pcre_match_limit >= -1) {
750 if (pcre_match_limit_recursion >= -1) {
759 pcre2_match_data_free(match);
763 pcre2_match_data_free(match);
764 DetectPcreFree(
de_ctx, pd);
774 int ret = 0, res = 0;
775 char type_str[16] =
"";
776 const char *orig_right_edge = regexstr + strlen(regexstr);
782 pcre2_match_data *match = NULL;
784 SCLogDebug(
"regexstr %s, pd %p", regexstr, pd);
786 ret = pcre2_pattern_info(pd->
parse_regex.
regex, PCRE2_INFO_CAPTURECOUNT, &capture_cnt);
787 SCLogDebug(
"ret %d capture_cnt %d", ret, capture_cnt);
788 if (ret == 0 && capture_cnt && strlen(capture_names) > 0)
791 while ((name_array[name_idx] = strtok_r(name_idx == 0 ? capture_names : NULL,
" ,", &ptr))){
792 if (name_idx > (capture_cnt - 1)) {
794 "var capture names than capturing substrings");
797 SCLogDebug(
"name '%s'", name_array[name_idx]);
799 if (strcmp(name_array[name_idx],
"pkt:key") == 0) {
807 }
else if (key == 1 && strcmp(name_array[name_idx],
"pkt:value") == 0) {
812 }
else if (key == 0 && strcmp(name_array[name_idx],
"pkt:value") == 0) {
814 }
else if (key == 1) {
817 }
else if (strncmp(name_array[name_idx],
"flow:", 5) == 0) {
823 }
else if (strncmp(name_array[name_idx],
"pkt:", 4) == 0) {
830 }
else if (strncmp(name_array[name_idx],
"alert:", 6) == 0) {
838 "var capture names must start with 'pkt:' or 'flow:'");
850 size_t cap_buffer_len = strlen(regexstr) + 1;
851 char capture_str[cap_buffer_len];
852 memset(capture_str, 0x00, cap_buffer_len);
862 pcre2_match_data_free(match);
865 copylen =
sizeof(type_str);
866 res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)type_str, ©len);
868 SCLogError(
"pcre2_substring_copy_bynumber failed");
871 cap_buffer_len = strlen(regexstr) + 1;
872 res = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)capture_str, &cap_buffer_len);
874 SCLogError(
"pcre2_substring_copy_bynumber failed");
877 if (strlen(capture_str) == 0 || strlen(type_str) == 0) {
885 SCLogError(
"rule can have maximally %d pkt/flow "
888 pcre2_match_data_free(match);
892 if (strcmp(type_str,
"pkt") == 0) {
897 }
else if (strcmp(type_str,
"flow") == 0) {
901 }
else if (strcmp(type_str,
"alert") == 0) {
908 PCRE2_SIZE *ov = pcre2_get_ovector_pointer(match);
911 pcre2_match_data_free(match);
914 if (regexstr >= orig_right_edge)
920 pcre2_match_data_free(match);
924static void *DetectPcreThreadInit(
void *data)
927 pcre2_match_data *match = pcre2_match_data_create_from_pattern(pd->
parse_regex.
regex, NULL);
931static void DetectPcreThreadFree(
void *
ctx)
934 pcre2_match_data *match = (pcre2_match_data *)
ctx;
935 pcre2_match_data_free(match);
944 char capture_names[1024] =
"";
947 pd = DetectPcreParse(
de_ctx, regexstr, &parsed_sm_list,
952 if (DetectPcreParseCapture(regexstr,
de_ctx, pd, capture_names) < 0)
956 de_ctx,
"pcre", DetectPcreThreadInit, (
void *)pd, DetectPcreThreadFree, 0);
963 SCLogError(
"Expression seen with a sticky buffer still set; either (1) reset sticky "
964 "buffer with pkt_data or (2) use a sticky buffer providing \"%s\".",
973 switch (parsed_sm_list) {
987 sm_list = parsed_sm_list;
1000 for (uint8_t x = 0; x < pd->
idx; x++) {
1014 "preceding match in the same buffer");
1017 }
else if (prev_pm == NULL) {
1031 DetectPcreFree(
de_ctx, pd);
1045 for (uint8_t i = 0; i < pd->
idx; i++) {
1053static int g_file_data_buffer_id = 0;
1054static int g_http_header_buffer_id = 0;
1055static int g_dce_stub_data_buffer_id = 0;
1060static int DetectPcreParseTest01 (
void)
1064 const char *teststring =
"/blah/7";
1070 pd = DetectPcreParse(
de_ctx, teststring, &list, NULL, 0,
false, &alproto);
1080static int DetectPcreParseTest02 (
void)
1084 const char *teststring =
"/blah/Ui$";
1090 pd = DetectPcreParse(
de_ctx, teststring, &list, NULL, 0,
false, &alproto);
1101static int DetectPcreParseTest03 (
void)
1105 const char *teststring =
"/blah/UNi";
1111 pd = DetectPcreParse(
de_ctx, teststring, &list, NULL, 0,
false, &alproto);
1121static int DetectPcreParseTest04 (
void)
1125 const char *teststring =
"/b\\\"lah/i";
1131 pd = DetectPcreParse(
de_ctx, teststring, &list, NULL, 0,
false, &alproto);
1135 DetectPcreFree(
de_ctx, pd);
1143static int DetectPcreParseTest05 (
void)
1147 const char *teststring =
"/b(l|a)h/";
1153 pd = DetectPcreParse(
de_ctx, teststring, &list, NULL, 0,
false, &alproto);
1157 DetectPcreFree(
de_ctx, pd);
1165static int DetectPcreParseTest06 (
void)
1169 const char *teststring =
"/b(l|a)h/smi";
1175 pd = DetectPcreParse(
de_ctx, teststring, &list, NULL, 0,
false, &alproto);
1179 DetectPcreFree(
de_ctx, pd);
1187static int DetectPcreParseTest07 (
void)
1191 const char *teststring =
"/blah/Ui";
1197 pd = DetectPcreParse(
de_ctx, teststring, &list, NULL, 0,
false, &alproto);
1201 DetectPcreFree(
de_ctx, pd);
1209static int DetectPcreParseTest08 (
void)
1213 const char *teststring =
"/b(l|a)h/O";
1219 pd = DetectPcreParse(
de_ctx, teststring, &list, NULL, 0,
false, &alproto);
1223 DetectPcreFree(
de_ctx, pd);
1232static int DetectPcreParseTest09 (
void)
1235 const char *teststring =
"/lala\\\\/";
1241 pd = DetectPcreParse(
de_ctx, teststring, &list, NULL, 0,
false, &alproto);
1244 DetectPcreFree(
de_ctx, pd);
1252static int DetectPcreParseTest10(
void)
1281static int DetectPcreParseTest15(
void)
1289 "alert tcp any any -> any any "
1290 "(msg:\"Testing pcre relative http_method\"; "
1292 "http_method; pcre:\"/abc/RM\"; sid:1;)");
1304static int DetectPcreParseTest16(
void)
1312 "alert tcp any any -> any any "
1313 "(msg:\"Testing pcre relative http_cookie\"; "
1314 "content:\"test\"; "
1315 "http_cookie; pcre:\"/abc/RC\"; sid:1;)");
1326static int DetectPcreParseTest17(
void)
1334 "alert tcp any any -> any any "
1335 "(msg:\"Testing pcre relative http_raw_header\"; "
1336 "flow:to_server; content:\"test\"; "
1337 "http_raw_header; pcre:\"/abc/RD\"; sid:1;)");
1348static int DetectPcreParseTest18(
void)
1356 "alert tcp any any -> any any "
1357 "(msg:\"Testing pcre relative http_header\"; "
1358 "content:\"test\"; "
1359 "http_header; pcre:\"/abc/RH\"; sid:1;)");
1370static int DetectPcreParseTest19(
void)
1378 "alert tcp any any -> any any "
1379 "(msg:\"Testing pcre relative http_client_body\"; "
1380 "content:\"test\"; "
1381 "http_client_body; pcre:\"/abc/RP\"; sid:1;)");
1392static int DetectPcreParseTest20(
void)
1400 "alert tcp any any -> any any "
1401 "(msg:\"Testing http_raw_uri\"; "
1402 "content:\"test\"; "
1403 "http_raw_uri; pcre:\"/abc/RI\"; sid:1;)");
1414static int DetectPcreParseTest21(
void)
1422 "alert tcp any any -> any any "
1423 "(msg:\"Testing pcre relative uricontent\"; "
1424 "uricontent:\"test\"; "
1425 "pcre:\"/abc/RU\"; sid:1;)");
1436static int DetectPcreParseTest22(
void)
1444 "alert tcp any any -> any any "
1445 "(msg:\"Testing pcre relative http_uri\"; "
1446 "content:\"test\"; "
1447 "http_uri; pcre:\"/abc/RU\"; sid:1;)");
1458static int DetectPcreParseTest23(
void)
1466 "alert tcp any any -> any any "
1467 "(msg:\"Testing inconsistent pcre relative\"; "
1469 "http_cookie; pcre:\"/abc/RM\"; sid:1;)");
1480static int DetectPcreParseTest24(
void)
1488 "alert tcp any any -> any any "
1489 "(msg:\"Testing inconsistent pcre modifiers\"; "
1490 "pcre:\"/abc/UI\"; sid:1;)");
1501static int DetectPcreParseTest25(
void)
1509 "alert tcp any any -> any any "
1510 "(msg:\"Testing inconsistent pcre modifiers\"; "
1511 "pcre:\"/abc/DH\"; sid:1;)");
1522static int DetectPcreParseTest26(
void)
1530 "alert http any any -> any any "
1531 "(msg:\"Testing inconsistent pcre modifiers\"; "
1532 "pcre:\"/abc/F\"; sid:1;)");
1543static int DetectPcreParseTest27(
void)
1551 "(content:\"baduricontent\"; http_raw_uri; "
1552 "pcre:\"/^[a-z]{5}\\.html/R\"; sid:2; rev:2;)");
1563static int DetectPcreParseTest28(
void)
1571 "(content:\"|2E|suricata\"; http_host; pcre:\"/\\x2Esuricata$/W\"; "
1579static int DetectPcreTestSig01(
void)
1581 uint8_t *buf = (uint8_t *)
"lalala lalala\\ lala\n";
1582 uint16_t buflen = strlen((
char *)buf);
1586 char sig[] =
"alert tcp any any -> any any (msg:\"pcre with an ending slash\"; pcre:\"/ "
1587 "lalala\\\\/\"; sid:1;)";
1600static int DetectPcreTestSig02(
void)
1602 uint8_t *buf = (uint8_t *)
"lalala\n";
1603 uint16_t buflen = strlen((
char *)buf);
1606 char sig[] =
"alert tcp any any -> any any (msg:\"pcre with an ending slash\"; "
1607 "pcre:\"/^(la)+$/\"; sid:1;)";
1616static int DetectPcreTestSig03(
void)
1619 uint8_t *buf = (uint8_t *)
"lalala";
1620 uint16_t buflen = strlen((
char *)buf);
1623 char sig[] =
"alert tcp any any -> any any (msg:\"pcre with an ending slash\"; "
1624 "pcre:\"/^(la)+$/\"; sid:1;)";
1634static int DetectPcreTxBodyChunksTest01(
void)
1639 uint8_t httpbuf1[] =
"GET / HTTP/1.1\r\n";
1640 uint8_t httpbuf2[] =
"User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
1641 uint8_t httpbuf3[] =
"Cookie: dummy\r\n\r\n";
1642 uint8_t httpbuf4[] =
"Body one!!";
1643 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
1644 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
1645 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
1646 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
1647 uint8_t httpbuf5[] =
"GET /?var=val HTTP/1.1\r\n";
1648 uint8_t httpbuf6[] =
"User-Agent: Firefox/1.0\r\n";
1649 uint8_t httpbuf7[] =
"Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
1650 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
1651 uint32_t httplen6 =
sizeof(httpbuf6) - 1;
1652 uint32_t httplen7 =
sizeof(httpbuf7) - 1;
1655 memset(&f, 0,
sizeof(f));
1656 memset(&ssn, 0,
sizeof(ssn));
1662 f.
proto = IPPROTO_TCP;
1733static int DetectPcreTxBodyChunksTest02(
void)
1741 uint8_t httpbuf1[] =
"POST / HTTP/1.1\r\n";
1742 uint8_t httpbuf2[] =
"User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
1743 uint8_t httpbuf3[] =
"Cookie: dummy\r\n\r\n";
1744 uint8_t httpbuf4[] =
"Body one!!";
1745 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
1746 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
1747 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
1748 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
1749 uint8_t httpbuf5[] =
"GET /?var=val HTTP/1.1\r\n";
1750 uint8_t httpbuf6[] =
"User-Agent: Firefox/1.0\r\n";
1751 uint8_t httpbuf7[] =
"Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
1752 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
1753 uint32_t httplen6 =
sizeof(httpbuf6) - 1;
1754 uint32_t httplen7 =
sizeof(httpbuf7) - 1;
1757 memset(&th_v, 0,
sizeof(th_v));
1758 memset(&f, 0,
sizeof(f));
1759 memset(&ssn, 0,
sizeof(ssn));
1765 f.
proto = IPPROTO_TCP;
1781 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;)");
1783 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;)");
1873 if (det_ctx != NULL) {
1888static int DetectPcreTxBodyChunksTest03(
void)
1896 uint8_t httpbuf1[] =
"POST / HTTP/1.1\r\n";
1897 uint8_t httpbuf2[] =
"User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
1898 uint8_t httpbuf3[] =
"Cookie: dummy\r\n\r\n";
1899 uint8_t httpbuf4[] =
"Body one!!";
1900 uint32_t httplen1 =
sizeof(httpbuf1) - 1;
1901 uint32_t httplen2 =
sizeof(httpbuf2) - 1;
1902 uint32_t httplen3 =
sizeof(httpbuf3) - 1;
1903 uint32_t httplen4 =
sizeof(httpbuf4) - 1;
1904 uint8_t httpbuf5[] =
"GET /?var=val HTTP/1.1\r\n";
1905 uint8_t httpbuf6[] =
"User-Agent: Firefox/1.0\r\n";
1906 uint8_t httpbuf7[] =
"Cookie: dummy2\r\nContent-Length: 10\r\n\r\nBody two!!";
1907 uint32_t httplen5 =
sizeof(httpbuf5) - 1;
1908 uint32_t httplen6 =
sizeof(httpbuf6) - 1;
1909 uint32_t httplen7 =
sizeof(httpbuf7) - 1;
1912 memset(&th_v, 0,
sizeof(th_v));
1913 memset(&f, 0,
sizeof(f));
1914 memset(&ssn, 0,
sizeof(ssn));
1920 f.
proto = IPPROTO_TCP;
1936 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;)");
1938 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;)");
2010 if (det_ctx != NULL) {
2027static int DetectPcreParseHttpHost(
void)
2035 DetectPcreData *pd = DetectPcreParse(
de_ctx,
"/domain\\.com/W", &list, NULL, 0,
false, &alproto);
2037 DetectPcreFree(
de_ctx, pd);
2040 pd = DetectPcreParse(
de_ctx,
"/dOmain\\.com/W", &list, NULL, 0,
false, &alproto);
2045 pd = DetectPcreParse(
de_ctx,
"/domain\\D+\\.com/W", &list, NULL, 0,
false, &alproto);
2047 DetectPcreFree(
de_ctx, pd);
2052 pd = DetectPcreParse(
de_ctx,
"/\\\\Ddomain\\.com/W", &list, NULL, 0,
false, &alproto);
2062static int DetectPcreParseCaptureTest(
void)
2068 "(content:\"Server: \"; http_header; pcre:\"/(.*)\\r\\n/HR, flow:somecapture\"; content:\"xyz\"; http_header; sid:1;)");
2071 "(content:\"Server: \"; http_header; pcre:\"/(flow:.*)\\r\\n/HR\"; content:\"xyz\"; http_header; sid:2;)");
2074 "(content:\"Server: \"; http_header; pcre:\"/([a-z]+)([0-9]+)\\r\\n/HR, flow:somecapture, pkt:anothercap\"; content:\"xyz\"; http_header; sid:3;)");
2077 "alert http any any -> any any "
2078 "(content:\"Server: \"; http_header; pcre:\"/([a-z]+)\\r\\n/HR, flow:somecapture, "
2079 "pkt:anothercap\"; content:\"xyz\"; http_header; sid:3;)");
2097static void DetectPcreRegisterTests(
void)
2129 UtRegisterTest(
"DetectPcreTestSig02 -- anchored pcre", DetectPcreTestSig02);
2130 UtRegisterTest(
"DetectPcreTestSig03 -- anchored pcre", DetectPcreTestSig03);
2133 DetectPcreTxBodyChunksTest01);
2134 UtRegisterTest(
"DetectPcreTxBodyChunksTest02 -- modifier P, body chunks per tx",
2135 DetectPcreTxBodyChunksTest02);
2136 UtRegisterTest(
"DetectPcreTxBodyChunksTest03 -- modifier P, body chunks per tx",
2137 DetectPcreTxBodyChunksTest03);
2139 UtRegisterTest(
"DetectPcreParseHttpHost", DetectPcreParseHttpHost);
2140 UtRegisterTest(
"DetectPcreParseCaptureTest", DetectPcreParseCaptureTest);
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
#define DETECT_CONTENT_RELATIVE_NEXT
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
SigMatch * DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id)
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
void SigCleanSignatures(DetectEngineCtx *de_ctx)
int SigGroupCleanup(DetectEngineCtx *de_ctx)
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
void SigFree(DetectEngineCtx *, Signature *)
Data structures and function prototypes for keeping state for the detection engine.
void * DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
const char * DetectEngineBufferTypeGetDescriptionById(const DetectEngineCtx *de_ctx, const int id)
int DetectRegisterThreadCtxFuncs(DetectEngineCtx *de_ctx, const char *name, void *(*InitFunc)(void *), void *data, void(*FreeFunc)(void *), int mode)
Register Thread keyword context Funcs.
int DetectUnregisterThreadCtxFuncs(DetectEngineCtx *de_ctx, void *data, const char *name)
Remove Thread keyword context registration.
int DetectEngineThreadCtxGetJsonContext(DetectEngineThreadCtx *det_ctx)
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
int DetectBufferTypeGetByName(const char *name)
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
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.
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.
int DetectFlowvarPostMatchSetup(DetectEngineCtx *de_ctx, Signature *s, uint32_t idx)
Setup a post-match for flowvar storage We're piggyback riding the DetectFlowvarData struct.
DetectParseRegex * DetectSetupPCRE2(const char *parse_str, int opts)
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.
void DetectParseFreeRegex(DetectParseRegex *r)
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Signature * SigAlloc(void)
SigTableElmt * sigmatch_table
#define PARSE_CAPTURE_REGEX
void DetectPcreRegister(void)
int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *payload, uint32_t payload_len)
Match a regex on a single payload.
#define DETECT_PCRE_RELATIVE_NEXT
#define DETECT_PCRE_NEGATE
#define DETECT_PCRE_RAWBYTES
#define DETECT_PCRE_CASELESS
#define SC_MATCH_LIMIT_RECURSION_DEFAULT
#define SC_MATCH_LIMIT_DEFAULT
#define DETECT_PCRE_RELATIVE
#define DETECT_PCRE_CAPTURE_MAX
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
#define DETECT_SM_LIST_NOTSET
#define DETECT_VAR_TYPE_FLOW_POSTMATCH
#define SIG_JSON_CONTENT_ITEM_LEN
#define SIGMATCH_QUOTES_OPTIONAL
#define DETECT_VAR_TYPE_PKT_POSTMATCH
#define SIGMATCH_HANDLE_NEGATION
#define FLOW_INITIALIZE(f)
#define FLOW_PKT_TOSERVER
#define FLOW_PKT_ESTABLISHED
AppLayerParserThreadCtx * alp_tctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
void AppLayerHtpEnableRequestBodyCallback(void)
Sets a flag that informs the HTP app layer that some module in the engine needs the http request body...
void StreamTcpFreeConfig(bool quiet)
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
main detection engine ctx
uint32_t pcre_match_start_offset
SigJsonContent * json_content
pcre2_match_context * context
uint32_t capids[DETECT_PCRE_CAPTURE_MAX]
DetectParseRegex parse_regex
uint8_t captypes[DETECT_PCRE_CAPTURE_MAX]
AppProto alproto
application level protocol
StreamingBufferSegment sbseg
char json_content[SIG_JSON_CONTENT_ITEM_LEN]
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
a single match condition for a signature
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
void(* Free)(DetectEngineCtx *, void *)
void(* RegisterTests)(void)
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
SignatureInitData * init_data
Per thread variable structure.
size_t strlcpy(char *dst, const char *src, size_t siz)
#define SCLogWarning(...)
Macro used to log WARNING messages.
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
#define SCLogError(...)
Macro used to log ERROR messages.
#define PageSupportsRWX()
int StreamingBufferSegmentCompareRawData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t *rawdata, uint32_t rawdata_len)
int UTHPacketMatchSig(Packet *p, const char *sig)
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.
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
void VarNameStoreUnregister(const uint32_t id, const enum VarTypes type)
uint32_t VarNameStoreRegister(const char *name, const enum VarTypes type)
const char * VarNameStoreLookupById(const uint32_t id, const enum VarTypes type)
find name for id+type at packet time. As the active store won't be modified, we don't need locks.
uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
find name for id+type at packet time. As the active store won't be modified, we don't need locks.