83 static void SigMatchTransferSigMatchAcrossLists(
SigMatch *sm,
118 static const uint8_t fw_packet_hook_scopes[] = {
123 static const uint8_t fw_app_hook_scopes[] = {
130 #define FW_POLICY_YAML_PATH_MAX 320
132 #define FW_POLICY_YAML_PATH_NAME_MAX 64
134 #define FW_POLICY_CHAIN_MAX 6
147 #define CASE_CODE_STRING(E, S) case E: return S; break
158 #undef CASE_CODE_STRING
162 #define CASE_CODE(E) case E: return #E
180 Signature *s,
const char *arg,
int sm_type,
int sm_list,
186 if (arg != NULL && strcmp(arg,
"") != 0) {
195 "with a sticky buffer still set. Reset sticky buffer "
196 "with pkt_data before using the modifier.",
210 "found inside the rule without a content context. "
211 "Please use a \"content\" keyword before using the "
219 "be used with the rawbytes rule keyword",
225 "be used with the replace rule keyword",
264 bool reuse_buffer =
false;
277 SCLogError(
"failed to expand rule buffer array");
286 SCLogDebug(
"idx %u list %d set up curbuf %p s->init_data->buffer_index %u",
327 if (sm->
ctx != NULL) {
338 ptrdiff_t
offset = e - table;
352 if (st->
name != NULL) {
384 if (strcmp(
str,
"all") == 0) {
396 char *xsaveptr = NULL;
397 char *key = strtok_r(copy,
",", &xsaveptr);
398 while (key != NULL) {
404 "argument '%s' not found",
407 key = strtok_r(NULL,
",", &xsaveptr);
434 SCLogDebug(
"s:%p new:%p list:%d: %s, s->init_data->list_set %s s->init_data->list %d", s,
new,
468 SCLogDebug(
"reusing buffer %u as it isn't multi-capable", x);
478 SCLogError(
"failed to expand rule buffer array");
508 SCLogDebug(
"appended %s to list %d, rule pos %u (s->init_data->list %d)",
527 if (sm->
prev != NULL)
529 if (sm->
next != NULL)
571 if (sm_last == NULL || sm_new->
idx > sm_last->
idx)
583 if (sm_last == NULL || sm_new->
idx > sm_last->
idx)
605 SCLogDebug(
"skip x %u s->init_data->list %d (int)s->init_data->buffers[x].id %d", x,
614 for (sm_type = va_arg(ap,
int); sm_type != -1; sm_type = va_arg(ap,
int)) {
618 if (sm_last == NULL || sm_new->
idx > sm_last->
idx)
635 for (sm_type = va_arg(ap,
int); sm_type != -1; sm_type = va_arg(ap,
int))
640 if (sm_last == NULL || sm_new->
idx > sm_last->
idx)
665 va_start(ap, sm_list);
667 for (sm_type = va_arg(ap,
int); sm_type != -1; sm_type = va_arg(ap,
int))
669 sm_new = SigMatchGetLastSMByType(sm_list, sm_type);
672 if (sm_last == NULL || sm_new->
idx > sm_last->
idx)
703 va_start(ap, list_id);
705 for (sm_type = va_arg(ap,
int); sm_type != -1; sm_type = va_arg(ap,
int)) {
709 if (sm_last == NULL || sm_new->
idx > sm_last->
idx)
721 va_start(ap, list_id);
723 for (sm_type = va_arg(ap,
int); sm_type != -1; sm_type = va_arg(ap,
int)) {
724 sm_new = SigMatchGetLastSMByType(sm_list, sm_type);
727 if (sm_last == NULL || sm_new->
idx > sm_last->
idx)
750 if (sm_last == NULL || sm_new->
idx > sm_last->
idx)
758 if (sm_last == NULL || sm_new->
idx > sm_last->
idx)
765 static void SigMatchTransferSigMatchAcrossLists(
SigMatch *sm,
771 if (sm->
prev != NULL)
773 if (sm->
next != NULL)
776 if (sm == *src_sm_list)
777 *src_sm_list = sm->
next;
778 if (sm == *src_sm_list_tail)
779 *src_sm_list_tail = sm->
prev;
781 if (*dst_sm_list == NULL) {
783 *dst_sm_list_tail = sm;
791 *dst_sm_list_tail = sm;
818 SCLogError(
"Unable to find the sm in any of the "
832 static int DetectSetupDirection(
Signature *s,
char **
str,
bool only_dir)
835 if (strncmp(*
str,
"to_client", strlen(
"to_client")) == 0) {
836 *
str += strlen(
"to_client");
838 while (**
str && isblank(**
str)) {
844 SCLogError(
"unknown option: only accepts to_server or to_client");
854 while (**
str && isblank(**
str)) {
866 }
else if (strncmp(*
str,
"to_server", strlen(
"to_server")) == 0) {
867 *
str += strlen(
"to_server");
869 while (**
str && isblank(**
str)) {
875 SCLogError(
"unknown option: only accepts to_server or to_client");
885 while (**
str && isblank(**
str)) {
897 }
else if (only_dir) {
898 SCLogError(
"unknown option: only accepts to_server or to_client");
905 size_t output_size,
bool requires)
908 char *optname = NULL;
909 char *optvalue = NULL;
912 while (isblank(*optstr)) {
917 char *optend = optstr;
919 optend = strchr(optend,
';');
920 if (optend == NULL) {
924 else if (optend > optstr && *(optend -1 ) ==
'\\') {
933 char *optvalptr = strchr(optstr,
':');
935 *(optvalptr++) =
'\0';
938 for (
size_t i = strlen(optvalptr); i > 0; i--) {
939 if (isblank(optvalptr[i - 1])) {
940 optvalptr[i - 1] =
'\0';
946 optvalue = optvalptr;
950 for (
size_t i = strlen(optstr); i > 0; i--) {
951 if (isblank(optstr[i - 1])) {
952 optstr[i - 1] =
'\0';
961 bool requires_only = strcasecmp(optname,
"requires") == 0 || strcasecmp(optname,
"sid") == 0;
962 if ((requires && !requires_only) || (!requires && requires_only)) {
967 st = SigTableGet(optname);
968 if (st == NULL || st->
Setup == NULL) {
969 SCLogError(
"unknown rule keyword '%s'.", optname);
974 if (optvalue == NULL || strlen(optvalue) == 0) {
976 "invalid formatting or malformed option to %s keyword: '%s'", optname, optstr);
980 if (optvalue && strlen(optvalue)) {
981 SCLogError(
"unexpected option to %s keyword: '%s'", optname, optstr);
991 #define URL "https://suricata.io/our-story/deprecation-policy/"
994 "and will be removed soon. See %s",
998 "and will be removed soon. Use '%s' instead. "
1005 SCLogError(
"keyword \'%s\' is not allowed with firewall rules", optname);
1010 SCLogError(
"keyword \'%s\' is not allowed in firewall mode", optname);
1017 if (optvalue != NULL && strlen(optvalue) > 0) {
1018 size_t ovlen = strlen(optvalue);
1019 char *ptr = optvalue;
1029 SCLogError(
"invalid formatting or malformed option to %s keyword: \'%s\'", optname,
1035 SCLogWarning(
"keyword \'%s\' has not been tested for firewall rules", optname);
1052 SCLogError(
"invalid formatting or malformed option to %s keyword: \'%s\'", optname,
1058 SCLogError(
"invalid formatting to %s keyword: "
1059 "value must be double quoted \'%s\'",
1065 && ovlen && *ptr ==
'"')
1067 for (; ovlen > 0; ovlen--) {
1068 if (isblank(ptr[ovlen - 1])) {
1069 ptr[ovlen - 1] =
'\0';
1074 if (ovlen && ptr[ovlen - 1] !=
'"') {
1075 SCLogError(
"bad option value formatting (possible missing semicolon) "
1076 "for keyword %s: \'%s\'",
1084 ptr[ovlen - 1] =
'\0';
1089 "for keyword %s: \'%s\'",
1096 "quotes on %s keyword that doesn't support them: \'%s\'", optname, optstr);
1114 if (setup_ret < 0) {
1118 if (setup_ret == -2) {
1130 if (strlen(optend) > 0) {
1131 strlcpy(output, optend, output_size);
1146 Signature *s,
const char *addrstr,
char flag)
1148 SCLogDebug(
"Address Group \"%s\" to be parsed now", addrstr);
1152 if (strcasecmp(addrstr,
"any") == 0)
1160 if (strcasecmp(addrstr,
"any") == 0)
1175 static bool IsBuiltIn(
const char *n)
1177 return strcmp(n,
"request_started") == 0 || strcmp(n,
"response_started") == 0 ||
1178 strcmp(n,
"request_complete") == 0 || strcmp(n,
"response_complete") == 0;
1186 const uint8_t state,
const uint8_t complete_state,
const int direction)
1189 return (direction == STREAM_TOSERVER) ?
"request-started" :
"response-started";
1190 if (state == complete_state)
1191 return (direction == STREAM_TOSERVER) ?
"request-complete" :
"response-complete";
1207 SCLogDebug(
"alproto %u/%s", a, alproto_name);
1211 SCLogDebug(
"%s: max sub state for %u is %u", alproto_name, a, max_sub_state);
1212 for (uint8_t s = 1; s <= max_sub_state; s++) {
1216 if (sub_state_name == NULL)
1219 char ts_tx_started[64];
1220 snprintf(ts_tx_started,
sizeof(ts_tx_started),
"%s:%s:request_started:generic",
1221 alproto_name, sub_state_name);
1225 char tc_tx_started[64];
1226 snprintf(tc_tx_started,
sizeof(tc_tx_started),
"%s:%s:response_started:generic",
1227 alproto_name, sub_state_name);
1231 char ts_tx_complete[64];
1232 snprintf(ts_tx_complete,
sizeof(ts_tx_complete),
"%s:%s:request_complete:generic",
1233 alproto_name, sub_state_name);
1237 char tc_tx_complete[64];
1238 snprintf(tc_tx_complete,
sizeof(tc_tx_complete),
"%s:%s:response_complete:generic",
1239 alproto_name, sub_state_name);
1244 for (uint8_t state = 0; state <= max_state; state++) {
1245 const char *state_name =
1247 BUG_ON(state_name == NULL);
1249 if (state_name != NULL && !IsBuiltIn(state_name)) {
1251 snprintf(list_name,
sizeof(list_name),
"%s:%s:%s:generic", alproto_name,
1252 sub_state_name, state_name);
1258 for (uint8_t state = 0; state <= max_state; state++) {
1259 const char *state_name =
1261 BUG_ON(state_name == NULL);
1262 if (state_name != NULL && !IsBuiltIn(state_name)) {
1264 snprintf(list_name,
sizeof(list_name),
"%s:%s:%s:generic", alproto_name,
1265 sub_state_name, state_name);
1272 const uint8_t max_progress_ts =
1274 const uint8_t max_progress_tc =
1277 char ts_tx_started[64];
1278 snprintf(ts_tx_started,
sizeof(ts_tx_started),
"%s:request_started:generic",
1282 SCLogDebug(
"- hook %s:%s list %s (%u)", alproto_name,
"request_name", ts_tx_started,
1283 (uint32_t)strlen(ts_tx_started));
1285 char tc_tx_started[64];
1286 snprintf(tc_tx_started,
sizeof(tc_tx_started),
"%s:response_started:generic",
1290 SCLogDebug(
"- hook %s:%s list %s (%u)", alproto_name,
"response_name", tc_tx_started,
1291 (uint32_t)strlen(tc_tx_started));
1293 char ts_tx_complete[64];
1294 snprintf(ts_tx_complete,
sizeof(ts_tx_complete),
"%s:request_complete:generic",
1298 SCLogDebug(
"- hook %s:%s list %s (%u)", alproto_name,
"request_name", ts_tx_complete,
1299 (uint32_t)strlen(ts_tx_complete));
1301 char tc_tx_complete[64];
1302 snprintf(tc_tx_complete,
sizeof(tc_tx_complete),
"%s:response_complete:generic",
1306 SCLogDebug(
"- hook %s:%s list %s (%u)", alproto_name,
"response_name", tc_tx_complete,
1307 (uint32_t)strlen(tc_tx_complete));
1309 for (uint8_t
p = 0;
p <= max_progress_ts;
p++) {
1311 IPPROTO_TCP , a,
p, STREAM_TOSERVER);
1312 if (
name != NULL && !IsBuiltIn(
name)) {
1314 snprintf(list_name,
sizeof(list_name),
"%s:%s:generic", alproto_name,
name);
1315 SCLogDebug(
"- hook %s:%s list %s (%u)", alproto_name,
name, list_name,
1316 (uint32_t)strlen(list_name));
1322 for (uint8_t
p = 0;
p <= max_progress_tc;
p++) {
1324 IPPROTO_TCP , a,
p, STREAM_TOCLIENT);
1325 if (
name != NULL && !IsBuiltIn(
name)) {
1327 snprintf(list_name,
sizeof(list_name),
"%s:%s:generic", alproto_name,
name);
1328 SCLogDebug(
"- hook %s:%s list %s (%u)", alproto_name,
name, list_name,
1329 (uint32_t)strlen(list_name));
1356 if (strcmp(
str,
"flow_start") == 0) {
1358 }
else if (strcmp(
str,
"pre_flow") == 0) {
1360 }
else if (strcmp(
str,
"pre_stream") == 0) {
1362 }
else if (strcmp(
str,
"all") == 0) {
1375 return "flow_start";
1379 return "pre_stream";
1391 .t.pkt.ph = HookPktFromString(hook_str),
1399 static int SigParseProtoHookPkt(
Signature *s,
const char *proto_hook,
const char *
p,
const char *h)
1412 SCLogDebug(
"protocol:%s hook:%s: type:%s parsed hook:%s",
p, h,
1422 .t.app.alproto = alproto,
1423 .t.app.sub_state = sub_state,
1424 .t.app.app_progress = progress,
1432 static int SigParseProtoHookApp(
1433 Signature *s,
const char *proto_hook,
const char *
p,
const char *in_h)
1436 char generic_hook_name[256];
1437 strlcpy(hook, in_h,
sizeof(hook));
1438 const char *h = hook;
1439 const char *t = NULL;
1440 uint8_t sub_state = 0;
1442 bool has_type = strchr(hook,
':') != NULL;
1445 t = strtok_r(hook,
":", &rem);
1449 if (h == NULL || strlen(h) == 0) {
1450 SCLogError(
"invalid hook specification '%s'", hook);
1455 if (strlen(t) == 0) {
1456 SCLogError(
"invalid tx type specification '%s'", hook);
1459 if (strcmp(
p,
"http2") == 0 || strcmp(
p,
"doh2") == 0) {
1460 if (strcmp(t,
"stream") == 0) {
1461 sub_state = HTTP2TxTypeStream;
1462 }
else if (strcmp(t,
"global") == 0) {
1463 sub_state = HTTP2TxTypeGlobal;
1465 SCLogError(
"unknown %s tx type specification '%s': valid values are 'stream' "
1471 SCLogError(
"sub states currently only supported for http2 and doh2");
1482 if (strcmp(h,
"request_started") == 0) {
1486 }
else if (strcmp(h,
"response_started") == 0) {
1490 }
else if (strcmp(h,
"request_complete") == 0) {
1493 }
else if (strcmp(h,
"response_complete") == 0) {
1497 const int8_t progress_ts =
1499 if (progress_ts >= 0) {
1504 s->
alproto, sub_state, h, STREAM_TOCLIENT);
1505 if (progress_tc < 0) {
1512 snprintf(generic_hook_name,
sizeof(generic_hook_name),
"%s:%s:%s:generic",
p, t, h);
1516 "protocol %s requires a substate specification: %s:<sub_state>:%s",
p,
p, hook);
1527 if (strcmp(h,
"request_started") == 0) {
1531 }
else if (strcmp(h,
"response_started") == 0) {
1535 }
else if (strcmp(h,
"request_complete") == 0) {
1539 }
else if (strcmp(h,
"response_complete") == 0) {
1545 IPPROTO_TCP , s->
alproto, h, STREAM_TOSERVER);
1546 if (progress_ts >= 0) {
1554 IPPROTO_TCP , s->
alproto, h, STREAM_TOCLIENT);
1562 snprintf(generic_hook_name,
sizeof(generic_hook_name),
"%s:%s:generic",
p, h);
1564 SCLogDebug(
"generic_hook_name %s", generic_hook_name);
1568 SCLogError(
"no list registered as %s for hook %s", generic_hook_name, proto_hook);
1573 SCLogDebug(
"protocol:%s hook:%s: type:%s alproto:%u hook:%d",
p, h,
1583 printf(
"=========Supported Rule Protocols=========\n");
1600 static int SigParseProto(
Signature *s,
const char *protostr)
1603 if (strlen(protostr) >= 64)
1609 const char *h = NULL;
1611 bool has_hook = strchr(
proto,
':') != NULL;
1614 p = strtok_r(
proto,
":", &rem);
1618 if (
p == NULL || strlen(
p) == 0) {
1633 if (strlen(h) == 0) {
1637 if (SigParseProtoHookApp(s, protostr,
p, h) < 0) {
1638 SCLogError(
"protocol \"%s\" does not support hook \"%s\"",
p, h);
1645 "in a signature. Either detection for this protocol "
1646 "is not yet supported OR detection has been disabled for "
1647 "protocol through the yaml option "
1648 "app-layer.protocols.%s.detection-enabled",
1652 }
else if (h != NULL) {
1653 SCLogDebug(
"non-app-layer rule with %s:%s",
p, h);
1655 if (SigParseProtoHookPkt(s, protostr,
p, h) < 0) {
1656 SCLogError(
"protocol \"%s\" does not support hook \"%s\"",
p, h);
1685 Signature *s,
const char *portstr,
char flag)
1691 SCLogDebug(
"Port group \"%s\" to be parsed", portstr);
1694 if (strcasecmp(portstr,
"any") == 0)
1698 }
else if (flag == 1) {
1699 if (strcasecmp(portstr,
"any") == 0)
1714 static int SigParseActionRejectValidate(
const char *action)
1716 #ifdef HAVE_LIBNET11
1717 #if defined HAVE_LIBCAP_NG && !defined HAVE_LIBNET_CAPABILITIES
1720 "incompatible with POSIX based capabilities with privs dropping. "
1721 "For rejects to work, run as root/super user.");
1727 "required for action \"%s\" but is not compiled into Suricata",
1737 static uint8_t ActionStringToFlags(
const char *action)
1739 if (strcasecmp(action,
"alert") == 0) {
1741 }
else if (strcasecmp(action,
"drop") == 0) {
1743 }
else if (strcasecmp(action,
"pass") == 0) {
1745 }
else if (strcasecmp(action,
"reject") == 0 ||
1746 strcasecmp(action,
"rejectsrc") == 0)
1748 if (!(SigParseActionRejectValidate(action)))
1751 }
else if (strcasecmp(action,
"rejectdst") == 0) {
1752 if (!(SigParseActionRejectValidate(action)))
1755 }
else if (strcasecmp(action,
"rejectboth") == 0) {
1756 if (!(SigParseActionRejectValidate(action)))
1759 }
else if (strcasecmp(action,
"config") == 0) {
1761 }
else if (strcasecmp(action,
"accept") == 0) {
1764 SCLogError(
"An invalid action \"%s\" was given", action);
1780 static int SigParseActionDo(
const char *action_in,
const int idx,
const bool fw_rule,
1781 uint8_t *action_out, uint8_t *scope_out)
1784 strlcpy(action, action_in,
sizeof(action));
1785 const char *a = action;
1786 const char *o = NULL;
1788 bool has_scope = strchr(action,
':') != NULL;
1790 char *xsaveptr = NULL;
1791 a = strtok_r(action,
":", &xsaveptr);
1792 o = strtok_r(NULL,
":", &xsaveptr);
1796 SCLogError(
"invalid protocol specification '%s'", action_in);
1800 uint8_t
flags = ActionStringToFlags(a);
1813 SCLogError(
"only accept, config, drop and reject actions allowed as primary action "
1820 SCLogError(
"accept, config, drop and reject actions not allowed as secondary action "
1826 SCLogError(
"'pass' is only supported as a secondary action for 'accept'");
1833 uint8_t scope_flags = 0;
1835 if (strcmp(o,
"packet") == 0) {
1837 }
else if (strcmp(o,
"flow") == 0) {
1840 SCLogError(
"invalid action scope '%s' in action '%s': only 'packet' and 'flow' "
1846 if (strcmp(o,
"packet") == 0) {
1848 }
else if (strcmp(o,
"hook") == 0) {
1850 }
else if (strcmp(o,
"tx") == 0) {
1852 }
else if (strcmp(o,
"flow") == 0) {
1856 "invalid action scope '%s' in action '%s': only 'packet', 'flow', 'tx' and "
1862 if (strcmp(o,
"packet") == 0) {
1865 SCLogError(
"invalid action scope '%s' in action '%s': only 'packet' allowed", o,
1870 SCLogError(
"invalid action scope '%s' in action '%s': scope only supported for actions "
1871 "'drop', 'pass' and 'reject'",
1875 if (*scope_out != 0 && *scope_out != scope_flags) {
1876 SCLogError(
"multi-action rules cannot use different action scopes");
1879 *scope_out = scope_flags;
1884 SCLogError(
"invalid action scope '%s' in action '%s': only 'packet' and 'flow' allowed",
1891 if (fw_rule && *scope_out == 0) {
1892 SCLogError(
"firewall rules require setting an explicit action scope");
1897 SCLogError(
"'accept' action only supported for firewall rules");
1900 *action_out |=
flags;
1904 static int SigParseAction(
Signature *s,
const char *action_in)
1913 FatalError(
"could not duplicate opt string");
1916 char *xsaveptr = NULL;
1917 char *a = strtok_r(copy,
",", &xsaveptr);
1923 a = strtok_r(NULL,
",", &xsaveptr);
1944 static inline int SigParseToken(
char **input,
char *output,
1945 const size_t output_size)
1947 size_t len = *input == NULL ? 0 : strlen(*input);
1953 while (
len && isblank(**input)) {
1958 char *endptr = strpbrk(*input,
" \t\n\r");
1959 if (endptr != NULL) {
1962 strlcpy(output, *input, output_size);
1979 static inline int SigParseList(
char **input,
char *output,
1980 const size_t output_size)
1983 size_t len = *input != NULL ? strlen(*input) : 0;
1989 while (
len && isblank(**input)) {
1995 for (i = 0; i <
len; i++) {
1996 char c = (*input)[i];
1999 }
else if (c ==
']') {
2001 }
else if (c ==
' ') {
2012 strlcpy(output, *input, output_size);
2013 *input = *input + i + 1;
2033 SigParseToken(&index, parser->
action,
sizeof(parser->
action));
2039 SigParseList(&index, parser->
src,
sizeof(parser->
src));
2042 SigParseList(&index, parser->
sp,
sizeof(parser->
sp));
2048 SigParseList(&index, parser->
dst,
sizeof(parser->
dst));
2051 SigParseList(&index, parser->
dp,
sizeof(parser->
dp));
2054 if (index == NULL) {
2058 while (isspace(*index) || *index ==
'(') {
2061 for (
size_t i = strlen(index); i > 0; i--) {
2062 if (isspace(index[i - 1]) || index[i - 1] ==
')') {
2063 index[i - 1] =
'\0';
2075 if (SigParseAction(s, parser->
action) < 0)
2078 if (SigParseProto(s, parser->
protocol) < 0)
2081 if (strcmp(parser->
direction,
"<>") == 0) {
2083 }
else if (strcmp(parser->
direction,
"=>") == 0) {
2085 SCLogError(
"transactional bidirectional rules not supported for firewall rules");
2090 }
else if (strcmp(parser->
direction,
"->") != 0) {
2091 SCLogError(
"\"%s\" is not a valid direction modifier, "
2092 "\"->\" and \"<>\" are supported.",
2119 static inline bool CheckAscii(
const char *
str)
2121 for (
size_t i = 0; i < strlen(
str); i++) {
2122 if (
str[i] < 0x20) {
2124 if (
str[i] == 0x0a ||
str[i] == 0x0d ||
str[i] == 0x09) {
2128 }
else if (
str[i] == 0x7f) {
2152 if (!SCCheckUtf8(sigstr)) {
2157 if (!CheckAscii(sigstr)) {
2158 SCLogError(
"rule contains invalid (control) characters");
2162 int ret = SigParseBasics(
de_ctx, s, sigstr, parser, addrs_direction, requires);
2169 if (strlen(parser->
opts) > 0) {
2170 size_t buffer_size = strlen(parser->
opts) + 1;
2172 char input[buffer_size];
2173 char output[buffer_size];
2174 memset(input, 0x00, buffer_size);
2175 memcpy(input, parser->
opts, strlen(parser->
opts) + 1);
2181 memset(output, 0x00, buffer_size);
2182 ret = SigParseOptions(
de_ctx, s, input, output, buffer_size, requires);
2184 memcpy(input, output, buffer_size);
2216 memset(b, 0,
sizeof(*b));
2264 static void SigMetadataFree(
Signature *s)
2271 if (s == NULL || s->
metadata == NULL) {
2278 next_mdata = mdata->
next;
2309 next_ref = ref->
next;
2363 while (sm != NULL) {
2372 while (sm != NULL) {
2393 if (s->
sp != NULL) {
2396 if (s->
dp != NULL) {
2445 if (s->
alproto == *alprotos) {
2488 }
else if (i == 1) {
2520 if (!AppProtoIsValid(alproto)) {
2544 alproto = AppProtoCommon(s->
alproto, alproto);
2546 SCLogError(
"can't set rule app proto to %s: already set to %s",
2573 if (addr_match4 == NULL) {
2579 addr_match4[idx].
ip =
SCNtohl(da->ip.addr_data32[0]);
2580 addr_match4[idx].
ip2 =
SCNtohl(da->ip2.addr_data32[0]);
2599 if (addr_match6 == NULL) {
2605 addr_match6[idx].
ip[0] =
SCNtohl(da->ip.addr_data32[0]);
2606 addr_match6[idx].
ip[1] =
SCNtohl(da->ip.addr_data32[1]);
2607 addr_match6[idx].
ip[2] =
SCNtohl(da->ip.addr_data32[2]);
2608 addr_match6[idx].
ip[3] =
SCNtohl(da->ip.addr_data32[3]);
2609 addr_match6[idx].
ip2[0] =
SCNtohl(da->ip2.addr_data32[0]);
2610 addr_match6[idx].
ip2[1] =
SCNtohl(da->ip2.addr_data32[1]);
2611 addr_match6[idx].
ip2[2] =
SCNtohl(da->ip2.addr_data32[2]);
2612 addr_match6[idx].
ip2[3] =
SCNtohl(da->ip2.addr_data32[3]);
2625 static void SigBuildAddressMatchArray(
Signature *s)
2642 static int SigMatchListLen(
SigMatch *sm)
2645 for (; sm != NULL; sm = sm->
next)
2656 int len = SigMatchListLen(
head);
2662 FatalError(
"initializing the detection engine failed");
2668 for (; sm != NULL; sm = sm->
next, smd++) {
2686 SCLogDebug(
"no prefilter for SIG_FLAG_FW_HOOK_LTE sig");
2713 SCLogDebug(
"s %u: no mpm; prefilter? de_ctx->prefilter_setting %u "
2714 "s->init_data->has_possible_prefilter %s",
2728 prefilter_list =
MIN(prefilter_list, sm->
type);
2738 if (sm->
type == prefilter_list) {
2755 static bool DetectRuleValidateTable(
const Signature *s)
2764 if (kw_tables_supported != 0 && (kw_tables_supported & table_as_flag) == 0) {
2765 SCLogError(
"rule %u uses hook \"%s\", but keyword \"%s\" doesn't support this hook",
2776 SCLogError(
"rule %u is loaded as a firewall rule, but does not specify an "
2786 SCLogError(
"rule %u uses action scope \"packet\" for an non-UDP app hook",
2804 SCLogError(
"rule %u: auto-accept notation (<hook) can only be used with accept:flow, "
2805 "accept:tx and accept:hook",
2814 static void DetectRuleSetTable(
Signature *s)
2847 if (!DetectFirewallRuleValidate(
de_ctx, s))
2853 static int SigValidateCheckBuffers(
2856 bool has_frame =
false;
2857 bool has_app =
false;
2858 bool has_pkt =
false;
2859 bool has_pmatch =
false;
2865 nlists += (nlists > 0);
2869 SCLogError(
"rule %u setup buffer %s but didn't add matches to it", s->
id,
2883 struct BufferVsDir {
2886 } bufdir[nlists + 1];
2887 memset(&bufdir, 0, (nlists + 1) *
sizeof(
struct BufferVsDir));
2901 if (b->
head == NULL) {
2906 has_frame |= bt->
frame;
2912 "specific matches (like dsize, flags, ttl) with stream / "
2913 "state matching by matching on app layer proto (like using "
2914 "http_* keywords).");
2918 uint32_t app_buffers_evaluated = 0;
2919 bool buffer_consumed =
false;
2920 uint32_t buffer_skip_alproto = 0;
2921 uint32_t buffer_skip_substate = 0;
2923 for (; app != NULL; app = app->
next) {
2926 app_buffers_evaluated++;
2934 SCLogDebug(
"%u:%s: for buffer %s skip engine %s alproto %s", s->
id,
2938 buffer_skip_alproto++;
2943 buffer_skip_substate++;
2949 SCLogDebug(
"%u:%s: for buffer %s skip engine %s alproto %s", s->
id,
2953 buffer_skip_alproto++;
2970 bufdir[b->
id].ts += (app->
dir == 0);
2971 bufdir[b->
id].tc += (app->
dir == 1);
2983 SCLogError(
"engine progress value doesn't match hook");
2988 buffer_consumed =
true;
2990 if (app_buffers_evaluated && !buffer_consumed) {
2991 SCLogError(
"incompatible rule conditions, skipped buffer %s, reasons: app proto %u sub "
2993 bt->
name, buffer_skip_alproto, buffer_skip_substate);
3008 if (has_pmatch && has_frame) {
3009 SCLogError(
"can't mix pure content and frame inspection");
3012 if (has_app && has_frame) {
3013 SCLogError(
"can't mix app-layer buffer and frame inspection");
3016 if (has_pkt && has_frame) {
3017 SCLogError(
"can't mix pkt buffer and frame inspection");
3021 for (
int x = 0; x < nlists; x++) {
3022 if (bufdir[x].
ts == 0 && bufdir[x].tc == 0)
3024 (*ts_excl) += (bufdir[x].ts > 0 && bufdir[x].tc == 0);
3025 (*tc_excl) += (bufdir[x].ts == 0 && bufdir[x].tc > 0);
3026 (*dir_amb) += (bufdir[x].ts > 0 && bufdir[x].tc > 0);
3035 static int SigValidatePacketStream(
const Signature *s)
3039 "tcp-stream or flow:only_stream. Invalidating signature.");
3045 static int SigConsolidateDirection(
3046 Signature *s,
const int ts_excl,
const int tc_excl,
const int dir_amb)
3049 if (!ts_excl || !tc_excl) {
3050 SCLogError(
"rule %u should use both directions, but does not", s->
id);
3054 SCLogError(
"rule %u means to use both directions, cannot have keywords ambiguous about "
3059 }
else if (ts_excl && tc_excl) {
3061 "rule %u mixes keywords with conflicting directions, a transactional rule with => "
3065 }
else if (ts_excl) {
3066 SCLogDebug(
"%u: implied rule direction is toserver", s->
id);
3068 SCLogError(
"rule %u mixes keywords with conflicting directions", s->
id);
3071 }
else if (tc_excl) {
3072 SCLogDebug(
"%u: implied rule direction is toclient", s->
id);
3074 SCLogError(
"rule %u mixes keywords with conflicting directions", s->
id);
3077 }
else if (dir_amb) {
3078 SCLogDebug(
"%u: rule direction cannot be deduced from keywords", s->
id);
3083 static void SigConsolidateTcpBuffer(
Signature *s)
3115 static bool SigInspectsFiles(
const Signature *s)
3126 static int SigValidateFileHandling(
const Signature *s)
3128 if (!SigInspectsFiles(s)) {
3135 "support file matching",
3152 SCLogError(
"No protocol support file matching");
3157 SCLogError(
"protocol HTTP2 doesn't support file name matching");
3163 static bool SigValidateEthernet(
const Signature *s)
3168 SCLogError(
"can't use ports with ether or arp rule");
3176 static bool SigValidateProtoPkthdr(
const Signature *s)
3179 SCLogError(
"protocol 'pkthdr' is for decoder-events only");
3208 static int SigValidateConsolidate(
3213 if (SigValidateFirewall(
de_ctx, s) == 0)
3216 if (SigValidatePacketStream(s) == 0) {
3220 if (!SigValidateEthernet(s)) {
3228 if (SigValidateCheckBuffers(
de_ctx, s, &ts_excl, &tc_excl, &dir_amb) == 0) {
3232 if (SigConsolidateDirection(s, ts_excl, tc_excl, dir_amb) == 0) {
3236 SigConsolidateTcpBuffer(s);
3239 DetectRuleSetTable(s);
3241 if (!SigValidateProtoPkthdr(s)) {
3245 if (!SigValidateFlowbitUse(
de_ctx, s)) {
3252 int r = SigValidateFileHandling(s);
3256 if (SigInspectsFiles(s)) {
3261 if (DetectRuleValidateTable(s) ==
false) {
3284 memset(&parser, 0x00,
sizeof(parser));
3289 if (firewall_rule) {
3306 int ret = SigParse(
de_ctx, sig, sigstr, dir, &parser,
true);
3313 }
else if (ret < 0) {
3319 SCLogError(
"Signature missing required value \"sid\".");
3324 ret = SigParse(
de_ctx, sig, sigstr, dir, &parser,
false);
3330 }
else if (ret == -2) {
3333 }
else if (ret < 0) {
3338 if (sig->
prio == -1)
3345 int override_needed = 0;
3349 override_needed = 1;
3351 override_needed = 1;
3355 override_needed = 0;
3364 if (override_needed)
3374 for ( ; sm != NULL; sm = sm->
next) {
3398 SCLogDebug(
"sig %"PRIu32
" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s",
3402 SigBuildAddressMatchArray(sig);
3413 SigSetupPrefilter(
de_ctx, sig);
3416 if (SigValidateConsolidate(
de_ctx, sig, &parser, dir) == 0) {
3435 static bool SigHasSameSourceAndDestination(
const Signature *s)
3477 if (SigHasSameSourceAndDestination(sig)) {
3478 SCLogInfo(
"Rule with ID %u is bidirectional, but source and destination are the same, "
3479 "treating the rule as unidirectional", sig->
id);
3484 if (sig->
next == NULL) {
3514 return SigInitDo(
de_ctx, sigstr,
false);
3519 return SigInitDo(
de_ctx, sigstr,
true);
3528 static void DetectParseDupSigFreeFunc(
void *data)
3544 static uint32_t DetectParseDupSigHashFunc(
HashListTable *ht,
void *data, uint16_t datalen)
3563 static char DetectParseDupSigCompareFunc(
void *data1, uint16_t len1,
void *data2,
3569 if (sw1 == NULL || sw2 == NULL ||
3570 sw1->
s == NULL || sw2->
s == NULL)
3574 if (sw1->
s->
id == sw2->
s->
id && sw1->
s->
gid == sw2->
s->
gid)
return 1;
3590 DetectParseDupSigHashFunc,
3591 DetectParseDupSigCompareFunc,
3592 DetectParseDupSigFreeFunc);
3653 if (sw_dup == NULL) {
3666 (
void *)&sw_tmp, 0);
3680 if (sw->
s->
rev <= sw_dup->
s->
rev) {
3689 if (sw_dup->
s_prev == NULL) {
3697 sw_temp.
s = sw_dup->
s->
next;
3701 if (sw_temp.
s != NULL) {
3703 (
void *)&sw_temp, 0);
3724 sw_temp.
s = sw_dup->
s->
next;
3732 if (sw_temp.
s != NULL) {
3734 (
void *)&sw_temp, 0);
3750 (
void *)&sw_tmp, 0);
3752 if (sw_old->
s != sw_dup->
s) {
3795 int dup_sig = DetectEngineSignatureIsDuplicate(
de_ctx, sig);
3799 SCLogError(
"Duplicate signature \"%s\"", sigstr);
3801 }
else if (dup_sig == 2) {
3803 " so the older sig replaced by this new signature \"%s\"",
3808 if (sig->
next != NULL) {
3825 return (dup_sig == 0 || dup_sig == 2) ? sig : NULL;
3829 if (sig != NULL && sig->
next != NULL) {
3867 int dup_sig = DetectEngineSignatureIsDuplicate(
de_ctx, sig);
3871 SCLogError(
"Duplicate signature \"%s\"", sigstr);
3873 }
else if (dup_sig == 2) {
3875 " so the older sig replaced by this new signature \"%s\"",
3880 if (sig->
next != NULL) {
3897 return (dup_sig == 0 || dup_sig == 2) ? sig : NULL;
3901 if (sig != NULL && sig->
next != NULL) {
3914 int start_offset,
int options)
3916 *match = pcre2_match_data_create_from_pattern(parse_regex->
regex, NULL);
3918 return pcre2_match(parse_regex->
regex, (PCRE2_SPTR8)
str, strlen(
str), options, start_offset,
3919 *match, parse_regex->
context);
3926 pcre2_code_free(r->
regex);
3929 pcre2_match_context_free(r->
context);
3944 g_detect_parse_regex_list = NULL;
3953 FatalError(
"failed to alloc memory for pcre free list");
3956 r->
next = g_detect_parse_regex_list;
3957 g_detect_parse_regex_list = r;
3965 detect_parse->
regex =
3966 pcre2_compile((PCRE2_SPTR8)parse_str, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
3967 if (detect_parse->
regex == NULL) {
3968 PCRE2_UCHAR errbuffer[256];
3969 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
3970 SCLogError(
"pcre compile of \"%s\" failed at "
3972 parse_str, en, errbuffer);
3975 detect_parse->
context = pcre2_match_context_create(NULL);
3976 if (detect_parse->
context == NULL) {
3977 SCLogError(
"pcre2 could not create match context");
3978 pcre2_code_free(detect_parse->
regex);
3979 detect_parse->
regex = NULL;
3994 if (detect_parse == NULL) {
3998 detect_parse->
regex =
3999 pcre2_compile((PCRE2_SPTR8)parse_str, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
4000 if (detect_parse->
regex == NULL) {
4001 PCRE2_UCHAR errbuffer[256];
4002 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
4003 SCLogError(
"pcre2 compile of \"%s\" failed at "
4005 parse_str, (
int)eo, errbuffer);
4010 detect_parse->
next = g_detect_parse_regex_list;
4011 g_detect_parse_regex_list = detect_parse;
4012 return detect_parse;
4016 pcre2_match_data *match_data, uint32_t number, PCRE2_UCHAR *buffer, PCRE2_SIZE *bufflen)
4018 int r = pcre2_substring_copy_bynumber(match_data, number, buffer, bufflen);
4019 if (r == PCRE2_ERROR_UNSET) {
4028 pcre2_match_data *match_data, uint32_t number, PCRE2_UCHAR **bufferptr, PCRE2_SIZE *bufflen)
4030 int r = pcre2_substring_get_bynumber(match_data, number, bufferptr, bufflen);
4031 if (r == PCRE2_ERROR_UNSET) {
4046 static uint32_t AppPolicyHashFunc(
HashTable *ht,
void *data, uint16_t datalen)
4050 uint32_t hash =
p->alproto * 65537 +
p->sub_state * 257 +
p->progress * 5 +
4051 (
p->direction == STREAM_TOSERVER);
4052 hash ^= (hash >> 10) ^ (hash >> 20);
4056 static char AppPolicyCompareFunc(
void *data1, uint16_t datalen1,
void *data2, uint16_t datalen2)
4061 if (p1 == NULL || p2 == NULL)
4068 static void AppPolicyHashFree(
void *data)
4105 snprintf(out, out_size,
"rejectdst:%s", as);
4107 snprintf(out, out_size,
"rejectboth:%s", as);
4109 snprintf(out, out_size,
"rejectsrc:%s", as);
4112 snprintf(out, out_size,
"drop:%s", as);
4114 snprintf(out, out_size,
"accept:%s", as);
4120 strlcat(out,
",pass:flow", out_size);
4126 strlcat(out,
",alert", out_size);
4148 snprintf(msg,
sizeof(msg),
"SURICATA FW default packet policy");
4150 if (s->
msg == NULL) {
4174 snprintf(msg,
sizeof(msg),
"SURICATA FW default app policy");
4176 if (s->
msg == NULL) {
4201 if (policy_actions == NULL) {
4202 SCLogDebug(
"fw: no policy at %s", policy_name);
4207 uint8_t action_scope = 0;
4212 if (SigParseActionDo(paction->
val, idx,
true, &action, &action_scope) < 0)
4218 SCLogError(
"%s: 'config' is not a valid default policy action", policy_name);
4228 const uint8_t *set = NULL;
4230 switch (pol_class) {
4232 set = fw_packet_hook_scopes;
4236 set = fw_app_hook_scopes;
4240 FatalError(
"Invalid firewall policy class %u", (
unsigned)pol_class);
4242 for (
size_t i = 0; i < n; i++) {
4243 if (set[i] == scope) {
4253 static void FirewallScopeHintForClass(
4256 const uint8_t *set = NULL;
4258 switch (pol_class) {
4260 set = fw_packet_hook_scopes;
4264 set = fw_app_hook_scopes;
4268 FatalError(
"Invalid firewall policy class %u", (
unsigned)pol_class);
4271 for (
size_t i = 0; i < n; i++) {
4272 if ((i > 0 &&
strlcat(out,
"/", out_size) >= out_size) ||
4274 FatalError(
"firewall policy scope hint too long");
4288 char *path = chain->path[chain->len];
4295 FatalError(
"%s: firewall YAML config path formatting failed", fmt);
4298 FatalError(
"%s: firewall YAML config path too long", path);
4301 for (uint8_t i = 0; i < chain->len; i++) {
4302 if (strcmp(chain->path[i], path) == 0)
4322 for (uint8_t i = 0; i < chain->
len; i++) {
4323 const char *path = chain->
path[i];
4325 int r = DoParsePolicy(path, &tmp);
4331 SCLogError(
"%s: policy is set but empty", path);
4334 if (!FirewallScopeValidForClass(tmp.
action_scope, pol_class)) {
4336 FirewallScopeHintForClass(pol_class, hint,
sizeof(hint));
4337 SCLogError(
"%s: action scope (\"%s\") is not valid. Valid scopes: %s", path,
4348 static void FirewallHookNameConvertUnderscoreToDash(
const char *in,
char *out,
size_t out_size)
4350 if (
strlcpy(out, in, out_size) >= out_size) {
4351 FatalError(
"%s: firewall policy config name too long", in);
4353 for (
size_t i = 0; out[i] !=
'\0'; i++) {
4365 static int DoParseAppPolicy(
const char *prefix,
const AppProto app_proto,
const uint8_t sub_state,
4366 const char *sub_state_name,
const char *hookname,
const uint8_t state,
4367 const uint8_t complete_state,
const int direction,
4371 if (app_proto_str == NULL) {
4372 SCLogError(
"Unknown app proto %u", (
unsigned)app_proto);
4378 if (hookname != NULL) {
4379 FirewallHookNameConvertUnderscoreToDash(hookname, hook,
sizeof(hook));
4384 if (sub_state_name != NULL) {
4386 FirewallHookNameConvertUnderscoreToDash(sub_state_name, sub + 1,
sizeof(sub) - 1);
4390 if (hookname != NULL) {
4392 FirewallPolicyChainAdd(&chain,
"%s.app.%s%s.%s", prefix, app_proto_str, sub, hook);
4394 if (generic_hook != NULL) {
4396 FirewallPolicyChainAdd(&chain,
"%s.app.%s%s.%s", prefix, app_proto_str, sub, generic_hook);
4399 FirewallPolicyChainAdd(&chain,
"%s.app.%s%s.default-policy", prefix, app_proto_str, sub);
4401 FirewallPolicyChainAdd(&chain,
"%s.app.%s.default-policy", prefix, app_proto_str);
4403 FirewallPolicyChainAdd(&chain,
"%s.app.default-policy", prefix);
4405 FirewallPolicyChainAdd(&chain,
"%s.default-policy", prefix);
4408 if (app_pol == NULL)
4427 FatalError(
"internal error: insert policy into hash table");
4433 return AddAppPolicySignature(app_pol);
4443 if (fw_policies == NULL)
4446 HashTableInit(512, AppPolicyHashFunc, AppPolicyCompareFunc, AppPolicyHashFree);
4474 FirewallPolicyChainAdd(&chain,
"%s.packet.%s", prefix, leaf);
4476 FirewallPolicyChainAdd(&chain,
"%s.packet.default-policy", prefix);
4478 FirewallPolicyChainAdd(&chain,
"%s.default-policy", prefix);
4486 return AddPktPolicySignature(fw_policies, pol,
id);
4494 static int DetectFirewallLoadPacketPolicies(
4497 if (DetectFirewallLoadPacketPolicy(
4500 if (DetectFirewallLoadPacketPolicy(
4503 if (DetectFirewallLoadPacketPolicy(
4511 char prefix[96] =
"firewall.policies";
4517 if (fw_policies == NULL)
4520 if (DetectFirewallLoadPacketPolicies(fw_policies, prefix) < 0)
4524 if (!AppProtoIsValid(a))
4530 for (uint8_t s = 1; s <= max_sub_state; s++) {
4534 if (sub_state_name == NULL)
4541 for (uint8_t state = 0; state <= max_state; state++) {
4543 sub_state_name, state);
4544 const char *state_name =
4546 BUG_ON(state_name == NULL);
4548 sub_state_name, state_name);
4549 if (DoParseAppPolicy(prefix, a, s, sub_state_name, state_name, state, max_state,
4550 STREAM_TOSERVER, fw_policies) < 0)
4554 for (uint8_t state = 0; state <= max_state; state++) {
4556 sub_state_name, state);
4557 const char *state_name =
4559 BUG_ON(state_name == NULL);
4561 sub_state_name, state_name);
4562 if (DoParseAppPolicy(prefix, a, s, sub_state_name, state_name, state, max_state,
4563 STREAM_TOCLIENT, fw_policies) < 0)
4568 const uint8_t complete_state_ts =
4570 a, STREAM_TOSERVER);
4571 for (uint8_t state = 0; state <= complete_state_ts; state++) {
4574 if (DoParseAppPolicy(prefix, a, 0, NULL,
name, state, complete_state_ts,
4575 STREAM_TOSERVER, fw_policies) < 0)
4578 const uint8_t complete_state_tc =
4580 a, STREAM_TOCLIENT);
4581 for (uint8_t state = 0; state <= complete_state_tc; state++) {
4584 if (DoParseAppPolicy(prefix, a, 0, NULL,
name, state, complete_state_tc,
4585 STREAM_TOCLIENT, fw_policies) < 0)
4601 static int SigParseTest01 (
void)
4610 sig =
SigInit(
de_ctx,
"alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
4620 static int SigParseTest02 (
void)
4635 sig =
SigInit(
de_ctx,
"alert tcp any !21:902 -> any any (msg:\"ET MALWARE Suspicious 220 Banner on Local Port\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:2003055; rev:4;)");
4663 static int SigParseTest03 (
void)
4672 sig =
SigInit(
de_ctx,
"alert tcp 1.2.3.4 any <- !1.2.3.4 any (msg:\"SigParseTest03\"; sid:1;)");
4675 printf(
"expected NULL got sig ptr %p: ",sig);
4684 static int SigParseTest04 (
void)
4693 sig =
SigInit(
de_ctx,
"alert tcp 1.2.3.4 1024: -> !1.2.3.4 1024: (msg:\"SigParseTest04\"; sid:1;)");
4704 static int SigParseTest05 (
void)
4713 sig =
SigInit(
de_ctx,
"alert tcp 1.2.3.4 1024:65536 -> !1.2.3.4 any (msg:\"SigParseTest05\"; sid:1;)");
4717 printf(
"signature didn't fail to parse as we expected: ");
4727 static int SigParseTest06 (
void)
4736 sig =
SigInit(
de_ctx,
"alert tcp any any -> any any (flow:to_server; content:\"GET\"; nocase; http_method; uricontent:\"/uri/\"; nocase; content:\"Host|3A| abc\"; nocase; sid:1; rev:1;)");
4740 printf(
"signature failed to parse: ");
4754 static int SigParseTest07(
void)
4776 static int SigParseTest08(
void)
4799 static int SigParseTest09(
void)
4850 static int SigParseTest10(
void)
4882 static int SigParseTest11(
void)
4893 "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking the http link\"; sid:1;) ");
4895 printf(
"sig 1 didn't parse: ");
4900 "the http link\"; sid:2;) ");
4902 printf(
"sig 2 didn't parse: ");
4916 static int SigParseTest12(
void)
4928 printf(
"sig 1 should have given an error: ");
4942 static int SigParseTest13(
void)
4954 printf(
"sig 1 invalidated: failure");
4959 printf(
"sig doesn't have stream flag set\n");
4964 printf(
"sig has packet flag set\n");
4979 static int SigParseTest14(
void)
4991 printf(
"sig 1 invalidated: failure");
4996 printf(
"sig doesn't have packet flag set\n");
5001 printf(
"sig has stream flag set\n");
5016 static int SigParseTest15(
void)
5028 printf(
"sig 1 invalidated: failure");
5033 printf(
"sig doesn't have packet flag set\n");
5038 printf(
"sig doesn't have stream flag set\n");
5053 static int SigParseTest16(
void)
5065 printf(
"sig 1 invalidated: failure");
5070 printf(
"sig doesn't have packet flag set\n");
5075 printf(
"sig doesn't have stream flag set\n");
5090 static int SigParseTest17(
void)
5102 printf(
"sig 1 invalidated: failure");
5107 printf(
"sig doesn't have packet flag set\n");
5112 printf(
"sig doesn't have stream flag set\n");
5125 static int SigParseTest18 (
void)
5133 if (
DetectEngineAppendSig(
de_ctx,
"alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:99999999999999999999;)") != NULL)
5144 static int SigParseTest19 (
void)
5152 if (
DetectEngineAppendSig(
de_ctx,
"alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; gid:99999999999999999999;)") != NULL)
5163 static int SigParseTest20 (
void)
5171 if (
DetectEngineAppendSig(
de_ctx,
"alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; rev:99999999999999999999;)") != NULL)
5182 static int SigParseTest21 (
void)
5201 static int SigParseTest22 (
void)
5209 if (
DetectEngineAppendSig(
de_ctx,
"alert tcp [10.10.10.0/24, !10.10.10.247] any -> [10.10.10.0/24, !10.10.10.247] any (sid:1;)") == NULL)
5222 static int SigParseTest23(
void)
5237 static int SigParseBidirecTest06 (
void)
5257 static int SigParseBidirecTest07 (
void)
5277 static int SigParseBidirecTest08 (
void)
5297 static int SigParseBidirecTest09 (
void)
5317 static int SigParseBidirecTest10 (
void)
5337 static int SigParseBidirecTest11 (
void)
5357 static int SigParseBidirecTest12 (
void)
5377 static int SigParseBidirecTest13 (
void)
5396 static int SigParseBidirecTest14 (
void)
5417 static int SigTestBidirec01 (
void)
5429 if (sig->
next != NULL)
5448 static int SigTestBidirec02 (
void)
5467 if (sig->
next == NULL)
5472 if (copy->
next != NULL)
5493 static int SigTestBidirec03 (
void)
5505 const char *sigs[3];
5506 sigs[0] =
"alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)";
5507 sigs[1] =
"alert tcp any any <> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)";
5508 sigs[2] =
"alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)";
5515 if (sig->
next == NULL)
5526 uint8_t rawpkt1_ether[] = {
5527 0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
5528 0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
5529 0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
5530 0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
5531 0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
5532 0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
5533 0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
5534 0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
5535 0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
5536 0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
5537 0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
5538 0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
5539 0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
5540 0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
5541 0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
5542 0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
5543 0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
5544 0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
5545 0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
5546 0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
5547 0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
5548 0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
5549 0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
5550 0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
5551 0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
5552 0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
5553 0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
5554 0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
5555 0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
5556 0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
5557 0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
5558 0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
5559 0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
5560 0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
5561 0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
5562 0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
5563 0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
5564 0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
5565 0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
5566 0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
5567 0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
5568 0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
5569 0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
5570 0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
5571 0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
5572 0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
5573 0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
5574 0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
5575 0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
5576 0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
5577 0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
5578 0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
5579 0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
5580 0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
5581 0x76,0x65,0x0d,0x0a,0x0d,0x0a };
5591 uint32_t sids[3] = {1, 2, 3};
5592 uint32_t results[3] = {1, 1, 1};
5608 static int SigTestBidirec04 (
void)
5623 sig =
DetectEngineAppendSig(
de_ctx,
"alert tcp 192.168.1.1 any <> any any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)");
5628 if (sig->
next == NULL)
5640 if (sig->
next == NULL)
5651 uint8_t rawpkt1_ether[] = {
5652 0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
5653 0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
5654 0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
5655 0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
5656 0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
5657 0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
5658 0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
5659 0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
5660 0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
5661 0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
5662 0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
5663 0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
5664 0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
5665 0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
5666 0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
5667 0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
5668 0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
5669 0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
5670 0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
5671 0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
5672 0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
5673 0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
5674 0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
5675 0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
5676 0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
5677 0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
5678 0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
5679 0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
5680 0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
5681 0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
5682 0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
5683 0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
5684 0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
5685 0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
5686 0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
5687 0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
5688 0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
5689 0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
5690 0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
5691 0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
5692 0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
5693 0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
5694 0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
5695 0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
5696 0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
5697 0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
5698 0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
5699 0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
5700 0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
5701 0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
5702 0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
5703 0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
5704 0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
5705 0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
5706 0x76,0x65,0x0d,0x0a,0x0d,0x0a };
5755 static int SigParseTestNegation01 (
void)
5769 static int SigParseTestNegation02 (
void)
5775 "alert tcp any !any -> any any (msg:\"SigTest41-02 src ip is !any \"; "
5776 "classtype:misc-activity; sid:410002; rev:1;)");
5784 static int SigParseTestNegation03 (
void)
5790 "alert tcp any any -> any [80:!80] (msg:\"SigTest41-03 dst port [80:!80] \"; "
5791 "classtype:misc-activity; sid:410003; rev:1;)");
5799 static int SigParseTestNegation04 (
void)
5810 s =
SigInit(
de_ctx,
"alert tcp any any -> any [80,!80] (msg:\"SigTest41-03 dst port [80:!80] \"; classtype:misc-activity; sid:410003; rev:1;)");
5825 static int SigParseTestNegation05 (
void)
5836 s =
SigInit(
de_ctx,
"alert tcp any any -> [192.168.0.2,!192.168.0.2] any (msg:\"SigTest41-04 dst ip [192.168.0.2,!192.168.0.2] \"; classtype:misc-activity; sid:410004; rev:1;)");
5851 static int SigParseTestNegation06 (
void)
5862 s =
SigInit(
de_ctx,
"alert tcp any any -> any [100:1000,!1:20000] (msg:\"SigTest41-05 dst port [100:1000,!1:20000] \"; classtype:misc-activity; sid:410005; rev:1;)");
5878 static int SigParseTestNegation07 (
void)
5884 de_ctx,
"alert tcp any any -> [192.168.0.2,!192.168.0.0/24] any (sid:410006;)");
5893 static int SigParseTestNegation08 (
void)
5905 "alert tcp any any -> [192.168.0.0/16,!192.168.0.0/24] any (sid:410006; rev:1;)");
5920 static int SigParseTestMpm01 (
void)
5929 sig =
SigInit(
de_ctx,
"alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; sid:1;)");
5931 printf(
"sig failed to init: ");
5936 printf(
"sig doesn't have content list: ");
5951 static int SigParseTestMpm02 (
void)
5960 sig =
SigInit(
de_ctx,
"alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; content:\"abcdef\"; sid:1;)");
5962 printf(
"sig failed to init: ");
5967 printf(
"sig doesn't have content list: ");
5982 static int SigParseTestAppLayerTLS01(
void)
5993 s =
SigInit(
de_ctx,
"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS01 \"; sid:410006; rev:1;)");
5995 printf(
"parsing sig failed: ");
6000 printf(
"alproto not set: ");
6017 static int SigParseTestAppLayerTLS02(
void)
6028 s =
SigInit(
de_ctx,
"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS02 \"; tls.version:1.0; sid:410006; rev:1;)");
6030 printf(
"parsing sig failed: ");
6035 printf(
"alproto not set: ");
6051 static int SigParseTestAppLayerTLS03(
void)
6058 "alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS03 \"; "
6059 "tls.version:2.5; sid:410006; rev:1;)");
6065 static int SigParseTestUnbalancedQuotes01(
void)
6071 "alert http any any -> any any (msg:\"SigParseTestUnbalancedQuotes01\"; "
6072 "pcre:\"/\\/[a-z]+\\.php\\?[a-z]+?=\\d{7}&[a-z]+?=\\d{7,8}$/U\" "
6073 "flowbits:set,et.exploitkitlanding; classtype:trojan-activity; sid:2017078; rev:5;)");
6079 static int SigParseTestContentGtDsize01(
void)
6086 "dsize:21; content:\"0123456789001234567890|00 00|\"; "
6093 static int SigParseTestContentGtDsize02(
void)
6100 "dsize:21; content:\"0123456789|00 00|\"; offset:10; "
6117 static int SigParseBidirWithSameSrcAndDest01(
void)
6134 "alert tcp [1.2.3.4, 5.6.7.8] [80, 81] <> [5.6.7.8, 1.2.3.4] [81, 80] (sid:3;)");
6143 static int SigParseBidirWithSameSrcAndDest02(
void)
6151 de_ctx,
"alert tcp 1.2.3.4 any <> [1.2.3.4, 5.6.7.8, ::1] any (sid:1;)");
6158 de_ctx,
"alert tcp [1.2.3.4, ::1] [80, 81, 82] <> [1.2.3.4, ::1] [80, 81] (sid:2;)");
6165 "alert tcp [1.2.3.4, ::1, ABCD:AAAA::1] [80] <> [1.2.3.4, ::1] [80, 81] (sid:3;)");
6172 de_ctx,
"alert tcp [!1.2.3.4, 1.2.3.0/24] any <> [1.2.3.0/24, !1.2.3.4] any (sid:4;)");
6179 de_ctx,
"alert tcp [1.2.3.4, 1.2.3.0/24] any <> [1.2.3.0/24, !1.2.3.4] any (sid:5;)");
6188 static int SigParseTestActionReject(
void)
6194 de_ctx,
"reject tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
6195 #ifdef HAVE_LIBNET11
6206 static int SigParseTestActionDrop(
void)
6212 de_ctx,
"drop tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
6220 static int SigSetMultiAppProto(
void)
6295 static int DetectSetupDirection01(
void)
6300 char *
str = (
char *)
"to_client";
6301 FAIL_IF(DetectSetupDirection(s, &
str,
true) < 0);
6306 static int DetectSetupDirection02(
void)
6310 char *
str = (
char *)
"to_server";
6311 FAIL_IF(DetectSetupDirection(s, &
str,
true) < 0);
6313 str = (
char *)
"to_client";
6314 FAIL_IF(DetectSetupDirection(s, &
str,
true) >= 0);
6320 static int DetectSetupDirection03(
void)
6324 char *
str = (
char *)
"to_client , something";
6325 FAIL_IF(DetectSetupDirection(s, &
str,
false) < 0);
6327 str = (
char *)
"to_client,something";
6328 FAIL_IF(DetectSetupDirection(s, &
str,
false) < 0);
6334 static int DetectSetupDirection04(
void)
6339 char *
str = (
char *)
"to_client_toto";
6340 FAIL_IF(DetectSetupDirection(s, &
str,
true) >= 0);
6342 str = (
char *)
"to_client_toto";
6343 FAIL_IF(DetectSetupDirection(s, &
str,
false) < 0);
6345 str = (
char *)
"to_client,something";
6347 FAIL_IF(DetectSetupDirection(s, &
str,
true) >= 0);
6384 UtRegisterTest(
"SigParseTest21 -- address with space", SigParseTest21);
6385 UtRegisterTest(
"SigParseTest22 -- address with space", SigParseTest22);
6386 UtRegisterTest(
"SigParseTest23 -- carriage return", SigParseTest23);
6401 UtRegisterTest(
"SigParseTestNegation01", SigParseTestNegation01);
6402 UtRegisterTest(
"SigParseTestNegation02", SigParseTestNegation02);
6403 UtRegisterTest(
"SigParseTestNegation03", SigParseTestNegation03);
6404 UtRegisterTest(
"SigParseTestNegation04", SigParseTestNegation04);
6405 UtRegisterTest(
"SigParseTestNegation05", SigParseTestNegation05);
6406 UtRegisterTest(
"SigParseTestNegation06", SigParseTestNegation06);
6407 UtRegisterTest(
"SigParseTestNegation07", SigParseTestNegation07);
6408 UtRegisterTest(
"SigParseTestNegation08", SigParseTestNegation08);
6411 UtRegisterTest(
"SigParseTestAppLayerTLS01", SigParseTestAppLayerTLS01);
6412 UtRegisterTest(
"SigParseTestAppLayerTLS02", SigParseTestAppLayerTLS02);
6413 UtRegisterTest(
"SigParseTestAppLayerTLS03", SigParseTestAppLayerTLS03);
6414 UtRegisterTest(
"SigParseTestUnbalancedQuotes01", SigParseTestUnbalancedQuotes01);
6417 SigParseTestContentGtDsize01);
6419 SigParseTestContentGtDsize02);
6422 SigParseBidirWithSameSrcAndDest01);
6424 SigParseBidirWithSameSrcAndDest02);
6425 UtRegisterTest(
"SigParseTestActionReject", SigParseTestActionReject);
6426 UtRegisterTest(
"SigParseTestActionDrop", SigParseTestActionDrop);
6430 UtRegisterTest(
"DetectSetupDirection01", DetectSetupDirection01);
6431 UtRegisterTest(
"DetectSetupDirection02", DetectSetupDirection02);
6432 UtRegisterTest(
"DetectSetupDirection03", DetectSetupDirection03);
6433 UtRegisterTest(
"DetectSetupDirection04", DetectSetupDirection04);