48 static int rule_warnings_only = 0;
104 { 0,
false,
false,
true,
"http_uri",
"http uri" },
105 { 0,
false,
false,
false,
"http_raw_uri",
"http raw uri" },
106 { 0,
false,
true,
false,
"http_method",
"http method" },
107 { 0,
false,
false,
false,
"http_request_line",
"http request line" },
108 { 0,
false,
false,
false,
"http_client_body",
"http client body" },
109 { 0,
false,
false,
true,
"http_header",
"http header" },
110 { 0,
false,
false,
false,
"http_raw_header",
"http raw header" },
111 { 0,
false,
false,
true,
"http_cookie",
"http cookie" },
112 { 0,
false,
false,
false,
"http_user_agent",
"http user agent" },
113 { 0,
false,
false,
false,
"http_host",
"http host" },
114 { 0,
false,
false,
false,
"http_raw_host",
"http raw host" },
115 { 0,
false,
false,
false,
"http_accept_enc",
"http accept enc" },
116 { 0,
false,
false,
false,
"http_referer",
"http referer" },
117 { 0,
false,
false,
false,
"http_content_type",
"http content type" },
118 { 0,
false,
false,
false,
"http_header_names",
"http header names" },
121 { 0,
false,
false,
false,
"http_stat_msg",
"http stat msg" },
122 { 0,
false,
false,
false,
"http_stat_code",
"http stat code" },
123 { 0,
false,
true,
false,
"file_data",
"http server body" },
126 { 0,
false,
false,
false,
"http_request_line",
"http request line" },
127 { 0,
false,
false,
false,
"http_accept",
"http accept" },
128 { 0,
false,
false,
false,
"http_accept_lang",
"http accept lang" },
129 { 0,
false,
false,
false,
"http_connection",
"http connection" },
130 { 0,
false,
false,
false,
"http_content_len",
"http content len" },
131 { 0,
false,
false,
false,
"http_protocol",
"http protocol" },
132 { 0,
false,
false,
false,
"http_start",
"http start" },
135 { 0,
false,
false,
false,
"http_response_line",
"http response line" },
136 { 0,
false,
false,
false,
"http.server",
"http server" },
137 { 0,
false,
false,
false,
"http.location",
"http location" },
140 static void FpPatternStatsAdd(
FpPatternStats *fp,
int list, uint16_t patlen)
149 else if (patlen < f->min)
161 int fast_pattern_set = 0;
162 int fast_pattern_only_set = 0;
163 int fast_pattern_chop_set = 0;
168 if (mpm_sm != NULL) {
171 fast_pattern_set = 1;
173 fast_pattern_only_set = 1;
175 fast_pattern_chop_set = 1;
181 fprintf(fp,
"== Sid: %u ==\n", s->
id);
182 fprintf(fp,
"%s\n", line);
184 fprintf(fp,
" Fast Pattern analysis:\n");
186 fprintf(fp,
" Prefilter on: %s\n",
193 fprintf(fp,
" No content present\n");
198 fprintf(fp,
" Fast pattern matcher: ");
199 int list_type = mpm_sm_list;
201 fprintf(fp,
"content\n");
206 fprintf(fp,
"%s (%s)\n", desc, name);
211 fprintf(fp,
" Flags:");
213 fprintf(fp,
" Offset");
216 fprintf(fp,
" Depth");
220 fprintf(fp,
" Within");
224 fprintf(fp,
" Distance");
228 fprintf(fp,
" Nocase");
232 fprintf(fp,
" Negated");
236 fprintf(fp,
" None");
239 fprintf(fp,
" Fast pattern set: %s\n", fast_pattern_set ?
"yes" :
"no");
240 fprintf(fp,
" Fast pattern only set: %s\n", fast_pattern_only_set ?
"yes" :
"no");
241 fprintf(fp,
" Fast pattern chop set: %s\n", fast_pattern_chop_set ?
"yes" :
"no");
242 if (fast_pattern_chop_set) {
243 fprintf(fp,
" Fast pattern offset, length: %u, %u\n", fp_cd->
fp_chop_offset,
254 fprintf(fp,
" Original content: ");
258 if (fast_pattern_chop_set) {
267 fprintf(fp,
" Final content: ");
273 fprintf(fp,
" Final content: ");
293 int fp_engine_analysis_set = 0;
295 if ((
ConfGetBool(
"engine-analysis.rules-fast-pattern",
296 &fp_engine_analysis_set)) == 0) {
300 if (fp_engine_analysis_set == 0)
304 char *log_path =
SCMalloc(PATH_MAX);
305 if (log_path == NULL) {
306 FatalError(
"Unable to allocate scratch memory for rule filename");
308 snprintf(log_path, PATH_MAX,
"%s/%s%s", log_dir,
311 FILE *fp = fopen(log_path,
"w");
313 SCLogError(
"failed to open %s: %s", log_path, strerror(errno));
320 SCLogInfo(
"Engine-Analysis for fast_pattern printed to file - %s",
325 gettimeofday(&tval, NULL);
327 struct tm *tms =
SCLocalTime(tval.tv_sec, &local_tm);
328 fprintf(fp,
"----------------------------------------------"
329 "---------------------\n");
331 "Date: %" PRId32
"/%" PRId32
"/%04d -- "
333 tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
335 fprintf(fp,
"----------------------------------------------"
336 "---------------------\n");
349 #define DETECT_PERCENT_ENCODING_REGEX "%[0-9|a-f|A-F]{2}"
355 PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
357 PCRE2_UCHAR errbuffer[256];
358 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
379 }
else if (value && strcasecmp(value,
"warnings-only") == 0) {
381 rule_warnings_only = 1;
386 char log_path[PATH_MAX];
387 snprintf(log_path,
sizeof(log_path),
"%s/%s%s", log_dir,
391 SCLogError(
"failed to open %s: %s", log_path, strerror(errno));
395 SCLogInfo(
"Engine-Analysis for rules printed to file - %s",
399 gettimeofday(&tval, NULL);
401 struct tm *tms =
SCLocalTime(tval.tv_sec, &local_tm);
403 "----------------------------------------------"
404 "---------------------\n");
406 "Date: %" PRId32
"/%" PRId32
"/%04d -- "
408 tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
411 "----------------------------------------------"
412 "---------------------\n");
415 if (!PerCentEncodingSetup(
de_ctx->
ea)) {
417 "Error compiling regex; can't check for percent encoding in normalized "
423 SCLogInfo(
"Conf parameter \"engine-analysis.rules\" not found. "
424 "Defaulting to not printing the rules analysis report.");
427 SCLogInfo(
"Engine-Analysis for rules disabled in conf file.");
436 fprintf(fp,
"============\n"
437 "Summary:\n============\n");
445 "%s, smallest pattern %u byte(s), longest pattern %u byte(s), number of patterns "
446 "%u, avg pattern len %.2f byte(s)\n",
448 (
float)((
double)f->
tot / (
float)f->
cnt));
470 *fp_analysis =
false;
471 *rule_analysis =
false;
475 FatalError(
"Unable to allocate per-engine analysis context");
480 if (cfg_prefix_len > 0) {
484 FatalError(
"Unable to allocate per-engine analysis context name buffer");
492 *fp_analysis = SetupFPAnalyzer(
de_ctx);
493 *rule_analysis = SetupRuleAnalyzer(
de_ctx);
495 if (!(*fp_analysis || *rule_analysis)) {
507 CleanupRuleAnalyzer(
de_ctx);
508 CleanupFPAnalyzer(
de_ctx);
525 static int PerCentEncodingMatch(
EngineAnalysisCtx *ea_ctx, uint8_t *content, uint16_t content_len)
529 pcre2_match_data *match = pcre2_match_data_create_from_pattern(ea_ctx->
percent_re, NULL);
530 ret = pcre2_match(ea_ctx->
percent_re, (PCRE2_SPTR8)content, content_len, 0, 0, match, NULL);
533 }
else if (ret < -1) {
534 SCLogError(
"Error parsing content - %s; error code is %d", content, ret);
537 pcre2_match_data_free(match);
547 if (mpm_sm != NULL) {
585 const int list_type = mpm_sm_list;
594 payload ? (stream ?
"payload and reassembled stream" :
"payload")
595 :
"reassembled stream");
602 }
else if (desc || name) {
641 vsnprintf(
str,
sizeof(
str), fmt, ap);
645 ctx->js_notes = jb_new_array();
647 jb_append_string(ctx->js_notes,
str);
656 vsnprintf(
str,
sizeof(
str), fmt, ap);
659 if (!ctx->js_warnings)
660 ctx->js_warnings = jb_new_array();
661 if (ctx->js_warnings)
662 jb_append_string(ctx->js_warnings,
str);
665 #define CHECK(pat) if (strlen((pat)) <= len && memcmp((pat), buf, MIN(len, strlen((pat)))) == 0) return true;
667 static bool LooksLikeHTTPMethod(
const uint8_t *buf, uint16_t
len)
676 static bool LooksLikeHTTPUA(
const uint8_t *buf, uint16_t
len)
678 CHECK(
"User-Agent: ");
679 CHECK(
"\nUser-Agent: ");
685 char pattern_str[1024] =
"";
688 jb_set_string(js,
"pattern", pattern_str);
697 jb_set_uint(js,
"offset", cd->
offset);
700 jb_set_uint(js,
"depth", cd->
depth);
703 jb_set_uint(js,
"distance", cd->
distance);
706 jb_set_uint(js,
"within", cd->
within);
725 jb_open_array(js,
"matches");
729 jb_set_string(js,
"name", mname);
735 jb_open_object(js,
"content");
738 AnalyzerNote(ctx, (
char *)
"'fast_pattern:only' option is silently ignored and "
739 "is interpreted as regular 'fast_pattern'");
743 (
char *)
"pattern looks like it inspects HTTP, use http.request_line or "
744 "http.method and http.uri instead for improved performance");
748 (
char *)
"pattern looks like it inspects HTTP, use http.user_agent "
749 "or http.header for improved performance");
752 AnalyzerNote(ctx, (
char *)
"'within' option for pattern w/o previous content "
753 "was converted to 'depth'");
756 AnalyzerNote(ctx, (
char *)
"'distance' option for pattern w/o previous content "
757 "was converted to 'offset'");
765 jb_open_object(js,
"pcre");
770 (
char *)
"'/B' (rawbytes) option is a no-op and is silently ignored");
777 jb_open_object(js,
"byte_jump");
778 jb_set_uint(js,
"nbytes", cd->
nbytes);
779 jb_set_uint(js,
"offset", cd->
offset);
780 jb_set_uint(js,
"multiplier", cd->
multiplier);
784 jb_set_string(js,
"base",
"unset");
787 jb_set_string(js,
"base",
"oct");
790 jb_set_string(js,
"base",
"dec");
793 jb_set_string(js,
"base",
"hex");
796 jb_open_array(js,
"flags");
798 jb_append_string(js,
"from_beginning");
800 jb_append_string(js,
"little_endian");
802 jb_append_string(js,
"big_endian");
804 jb_append_string(js,
"string");
806 jb_append_string(js,
"relative");
808 jb_append_string(js,
"align");
810 jb_append_string(js,
"dce");
812 jb_append_string(js,
"offset_be");
814 jb_append_string(js,
"from_end");
822 jb_open_object(js,
"byte_test");
823 jb_set_uint(js,
"nbytes", cd->
nbytes);
824 jb_set_uint(js,
"offset", cd->
offset);
827 jb_set_string(js,
"base",
"unset");
830 jb_set_string(js,
"base",
"oct");
833 jb_set_string(js,
"base",
"dec");
836 jb_set_string(js,
"base",
"hex");
839 jb_open_array(js,
"flags");
841 jb_append_string(js,
"little_endian");
843 jb_append_string(js,
"big_endian");
845 jb_append_string(js,
"string");
847 jb_append_string(js,
"relative");
849 jb_append_string(js,
"dce");
871 ctx.
js = jb_new_object();
875 jb_set_string(ctx.
js,
"raw", s->
sig_str);
876 jb_set_uint(ctx.
js,
"id", s->
id);
877 jb_set_uint(ctx.
js,
"gid", s->
gid);
878 jb_set_uint(ctx.
js,
"rev", s->
rev);
879 jb_set_string(ctx.
js,
"msg", s->
msg);
882 jb_set_string(ctx.
js,
"app_proto", alproto);
884 jb_open_array(ctx.
js,
"requirements");
886 jb_append_string(ctx.
js,
"payload");
889 jb_append_string(ctx.
js,
"no_payload");
892 jb_append_string(ctx.
js,
"flow");
895 jb_append_string(ctx.
js,
"tcp_flags_init_deinit");
898 jb_append_string(ctx.
js,
"tcp_flags_unusual");
901 jb_append_string(ctx.
js,
"dcerpc");
904 jb_append_string(ctx.
js,
"engine_event");
910 jb_set_string(ctx.
js,
"type",
"unset");
913 jb_set_string(ctx.
js,
"type",
"ip_only");
916 jb_set_string(ctx.
js,
"type",
"like_ip_only");
919 jb_set_string(ctx.
js,
"type",
"pd_only");
922 jb_set_string(ctx.
js,
"type",
"de_only");
925 jb_set_string(ctx.
js,
"type",
"pkt");
928 jb_set_string(ctx.
js,
"type",
"pkt_stream");
931 jb_set_string(ctx.
js,
"type",
"stream");
934 jb_set_string(ctx.
js,
"type",
"app_layer");
937 jb_set_string(ctx.
js,
"type",
"app_tx");
940 jb_set_string(ctx.
js,
"type",
"error");
944 jb_open_array(ctx.
js,
"flags");
946 jb_append_string(ctx.
js,
"src_any");
949 jb_append_string(ctx.
js,
"dst_any");
952 jb_append_string(ctx.
js,
"sp_any");
955 jb_append_string(ctx.
js,
"dp_any");
958 jb_append_string(ctx.
js,
"noalert");
961 jb_append_string(ctx.
js,
"dsize");
964 jb_append_string(ctx.
js,
"applayer");
967 jb_append_string(ctx.
js,
"need_packet");
970 jb_append_string(ctx.
js,
"need_stream");
973 jb_append_string(ctx.
js,
"negated_mpm");
976 jb_append_string(ctx.
js,
"flush");
979 jb_append_string(ctx.
js,
"need_flowvar");
982 jb_append_string(ctx.
js,
"filestore");
985 jb_append_string(ctx.
js,
"toserver");
988 jb_append_string(ctx.
js,
"toclient");
991 jb_append_string(ctx.
js,
"tlsstore");
994 jb_append_string(ctx.
js,
"bypass");
997 jb_append_string(ctx.
js,
"prefilter");
1000 jb_append_string(ctx.
js,
"src_is_target");
1003 jb_append_string(ctx.
js,
"dst_is_target");
1010 jb_open_array(ctx.
js,
"pkt_engines");
1012 for ( ; pkt != NULL; pkt = pkt->
next) {
1027 jb_start_object(ctx.
js);
1028 jb_set_string(ctx.
js,
"name", name);
1029 jb_set_bool(ctx.
js,
"is_mpm", pkt->
mpm);
1031 jb_open_array(ctx.
js,
"transforms");
1033 jb_start_object(ctx.
js);
1034 jb_set_string(ctx.
js,
"name",
1040 DumpMatches(&ctx, ctx.
js, pkt->
smd);
1047 jb_open_array(ctx.
js,
"frame_engines");
1049 for (; frame != NULL; frame = frame->
next) {
1051 jb_start_object(ctx.
js);
1052 jb_set_string(ctx.
js,
"name", name);
1053 jb_set_bool(ctx.
js,
"is_mpm", frame->
mpm);
1055 jb_open_array(ctx.
js,
"transforms");
1057 jb_start_object(ctx.
js);
1058 jb_set_string(ctx.
js,
"name",
1064 DumpMatches(&ctx, ctx.
js, frame->
smd);
1070 bool has_stream =
false;
1071 bool has_client_body_mpm =
false;
1072 bool has_file_data_mpm =
false;
1074 jb_open_array(ctx.
js,
"engines");
1076 for ( ; app != NULL; app = app->
next) {
1091 }
else if (app->
mpm && strcmp(name,
"http_client_body") == 0) {
1092 has_client_body_mpm =
true;
1093 }
else if (app->
mpm && strcmp(name,
"file_data") == 0) {
1094 has_file_data_mpm =
true;
1097 jb_start_object(ctx.
js);
1098 jb_set_string(ctx.
js,
"name", name);
1099 const char *direction = app->
dir == 0 ?
"toserver" :
"toclient";
1100 jb_set_string(ctx.
js,
"direction", direction);
1101 jb_set_bool(ctx.
js,
"is_mpm", app->
mpm);
1103 jb_set_uint(ctx.
js,
"progress", app->
progress);
1106 jb_open_array(ctx.
js,
"transforms");
1108 jb_start_object(ctx.
js);
1109 jb_set_string(ctx.
js,
"name",
1115 DumpMatches(&ctx, ctx.
js, app->
smd);
1123 if (has_stream && has_client_body_mpm)
1124 AnalyzerNote(&ctx, (
char *)
"mpm in http_client_body combined with stream match leads to stream buffering");
1125 if (has_stream && has_file_data_mpm)
1126 AnalyzerNote(&ctx, (
char *)
"mpm in file_data combined with stream match leads to stream buffering");
1129 jb_open_object(ctx.
js,
"lists");
1139 if (pkt_mpm || app_mpm) {
1140 jb_open_object(ctx.
js,
"mpm");
1148 jb_set_string(ctx.
js,
"buffer", name);
1155 switch (smd->
type) {
1159 DumpContent(ctx.
js, cd);
1171 jb_open_object(ctx.
js,
"prefilter");
1178 jb_set_string(ctx.
js,
"buffer", name);
1180 jb_set_string(ctx.
js,
"name", mname);
1192 jb_set_object(ctx.
js,
"notes", ctx.
js_notes);
1198 const char *filename =
"rules.json";
1200 char json_path[PATH_MAX] =
"";
1201 snprintf(json_path,
sizeof(json_path),
"%s/%s%s", log_dir,
1205 FILE *fp = fopen(json_path,
"a");
1207 fwrite(jb_ptr(ctx.
js), jb_len(ctx.
js), 1, fp);
1221 JsonBuilder *root_jb = jb_new_object();
1225 jb_open_array(root_jb,
"buffers");
1229 char str[1024] =
"";
1233 JsonBuilder *jb = arrays[p->
sm_list];
1234 if (arrays[p->
sm_list] == NULL) {
1235 jb = arrays[p->
sm_list] = jb_new_object();
1241 jb_set_string(jb,
"name", name);
1242 jb_set_uint(jb,
"list_id", p->
sm_list);
1244 jb_open_array(jb,
"patterns");
1247 jb_start_object(jb);
1248 jb_set_string(jb,
"pattern",
str);
1250 jb_set_uint(jb,
"cnt", p->
cnt);
1251 jb_set_uint(jb,
"mpm", p->
mpm);
1252 jb_open_object(jb,
"flags");
1263 JsonBuilder *jb = arrays[i];
1270 jb_append_object(root_jb, jb);
1276 const char *filename =
"patterns.json";
1278 char json_path[PATH_MAX] =
"";
1279 snprintf(json_path,
sizeof(json_path),
"%s/%s%s", log_dir,
1283 FILE *fp = fopen(json_path,
"a");
1285 fwrite(jb_ptr(root_jb), jb_len(root_jb), 1, fp);
1306 EngineAnalysisItemsReset(ea_ctx);
1314 FatalError(
"Unable to allocate analysis scratch pad");
1324 analyzer_item->
item_id = (uint16_t)item_id;
1325 if (analyzer_item->
item_id == -1) {
1327 FatalError(
"unable to initialize engine-analysis table: detect buffer \"%s\" not "
1360 uint32_t rule_bidirectional = 0;
1361 uint32_t rule_pcre = 0;
1362 uint32_t rule_pcre_http = 0;
1363 uint32_t rule_content = 0;
1364 uint32_t rule_flow = 0;
1365 uint32_t rule_flags = 0;
1366 uint32_t rule_flow_toserver = 0;
1367 uint32_t rule_flow_toclient = 0;
1368 uint32_t rule_flow_nostream = 0;
1369 uint32_t rule_ipv4_only = 0;
1370 uint32_t rule_ipv6_only = 0;
1371 uint32_t rule_flowbits = 0;
1372 uint32_t rule_flowint = 0;
1373 uint32_t rule_content_http = 0;
1374 uint32_t rule_content_offset_depth = 0;
1375 int32_t list_id = 0;
1376 uint32_t rule_warning = 0;
1377 uint32_t stream_buf = 0;
1378 uint32_t packet_buf = 0;
1379 uint32_t file_store = 0;
1380 uint32_t warn_pcre_no_content = 0;
1381 uint32_t warn_pcre_http_content = 0;
1382 uint32_t warn_pcre_http = 0;
1383 uint32_t warn_content_http_content = 0;
1384 uint32_t warn_content_http = 0;
1385 uint32_t warn_tcp_no_flow = 0;
1386 uint32_t warn_client_ports = 0;
1387 uint32_t warn_direction = 0;
1388 uint32_t warn_method_toclient = 0;
1389 uint32_t warn_method_serverbody = 0;
1390 uint32_t warn_pcre_method = 0;
1391 uint32_t warn_encoding_norm_http_buf = 0;
1392 uint32_t warn_file_store_not_present = 0;
1393 uint32_t warn_offset_depth_pkt_stream = 0;
1394 uint32_t warn_offset_depth_alproto = 0;
1395 uint32_t warn_non_alproto_fp_for_alproto_sig = 0;
1396 uint32_t warn_no_direction = 0;
1397 uint32_t warn_both_direction = 0;
1399 EngineAnalysisItemsInit(
de_ctx->
ea);
1405 rule_bidirectional = 1;
1419 rule_ipv4_only += 1;
1422 rule_ipv6_only += 1;
1430 if (item_slot == -1) {
1438 if (item_slot == -1) {
1443 rule_content_offset_depth++;
1449 rule_content_http++;
1456 warn_encoding_norm_http_buf += 1;
1463 rule_flow_toserver = 1;
1466 rule_flow_toclient = 1;
1471 rule_flow_nostream = 1;
1496 warn_file_store_not_present = 1;
1499 if (rule_pcre > 0 && rule_content == 0 && rule_content_http == 0) {
1501 warn_pcre_no_content = 1;
1504 if (rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0) {
1506 warn_pcre_http_content = 1;
1512 if (rule_content > 0 && rule_content_http > 0) {
1514 warn_content_http_content = 1;
1518 warn_content_http = 1;
1520 if (rule_content == 1) {
1525 (rule_content || rule_content_http || rule_pcre || rule_pcre_http || rule_flowbits ||
1528 warn_tcp_no_flow = 1;
1530 if (rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)
1535 warn_client_ports = 1;
1538 if (rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)) {
1543 if (*http_method_item_seen_ptr) {
1544 if (rule_flow && rule_flow_toclient) {
1546 warn_method_toclient = 1;
1548 if (*http_server_body_item_seen_ptr) {
1550 warn_method_serverbody = 1;
1552 if (rule_content == 0 && rule_content_http == 0 && (rule_pcre > 0 || rule_pcre_http > 0)) {
1554 warn_pcre_method = 1;
1557 if (rule_content_offset_depth > 0 && stream_buf && packet_buf) {
1559 warn_offset_depth_pkt_stream = 1;
1563 warn_offset_depth_alproto = 1;
1568 warn_non_alproto_fp_for_alproto_sig = 1;
1572 warn_no_direction += 1;
1579 warn_both_direction += 1;
1584 if (!rule_warnings_only || (rule_warnings_only && rule_warning > 0)) {
1586 fprintf(fp,
"== Sid: %u ==\n", s->
id);
1587 fprintf(fp,
"%s\n", line);
1593 fprintf(fp,
" Rule is ip only.\n");
1596 fprintf(fp,
" Rule is like ip only.\n");
1599 fprintf(fp,
" Rule is PD only.\n");
1602 fprintf(fp,
" Rule is DE only.\n");
1605 fprintf(fp,
" Rule is packet inspecting.\n");
1608 fprintf(fp,
" Rule is packet and stream inspecting.\n");
1611 fprintf(fp,
" Rule is stream inspecting.\n");
1614 fprintf(fp,
" Rule is app-layer inspecting.\n");
1617 fprintf(fp,
" Rule is App-layer TX inspecting.\n");
1623 fprintf(fp,
" Rule is IPv6 only.\n");
1625 fprintf(fp,
" Rule is IPv4 only.\n");
1627 fprintf(fp,
" Rule matches on packets.\n");
1628 if (!rule_flow_nostream && stream_buf &&
1629 (rule_flow || rule_flowbits || rule_flowint || rule_content || rule_pcre)) {
1630 fprintf(fp,
" Rule matches on reassembled stream.\n");
1635 fprintf(fp,
" Rule matches on %s buffer.\n", ai->
display_name);
1641 if (rule_content || rule_content_http || rule_pcre || rule_pcre_http) {
1643 " Rule contains %u content options, %u http content options, %u pcre "
1644 "options, and %u pcre options with http modifiers.\n",
1645 rule_content, rule_content_http, rule_pcre, rule_pcre_http);
1650 fprintf(fp,
" Prefilter on: %s.\n",
1653 EngineAnalysisRulesPrintFP(
de_ctx, s);
1657 if (warn_pcre_no_content ) {
1658 fprintf(fp,
" Warning: Rule uses pcre without a content option present.\n"
1659 " -Consider adding a content to improve performance of this "
1662 if (warn_pcre_http_content ) {
1663 fprintf(fp,
" Warning: Rule uses content options with http_* and pcre options "
1664 "without http modifiers.\n"
1665 " -Consider adding http pcre modifier.\n");
1667 else if (warn_pcre_http ) {
1668 fprintf(fp,
" Warning: Rule app layer protocol is http, but pcre options do not "
1669 "have http modifiers.\n"
1670 " -Consider adding http pcre modifiers.\n");
1672 if (warn_content_http_content ) {
1674 " Warning: Rule contains content with http_* and content without http_*.\n"
1675 " -Consider adding http content modifiers.\n");
1677 if (warn_content_http ) {
1678 fprintf(fp,
" Warning: Rule app layer protocol is http, but content options do not "
1679 "have http_* modifiers.\n"
1680 " -Consider adding http content modifiers.\n");
1682 if (rule_content == 1) {
1685 if (warn_encoding_norm_http_buf) {
1686 fprintf(fp,
" Warning: Rule may contain percent encoded content for a normalized "
1687 "http buffer match.\n");
1689 if (warn_tcp_no_flow
1691 fprintf(fp,
" Warning: TCP rule without a flow or flags option.\n"
1692 " -Consider adding flow or flags to improve performance of "
1695 if (warn_client_ports
1700 " Warning: Rule contains ports or port variables only on the client side.\n"
1701 " -Flow direction possibly inconsistent with rule.\n");
1703 if (warn_direction ) {
1704 fprintf(fp,
" Warning: Rule is bidirectional and has a flow option with a specific "
1707 if (warn_method_toclient ) {
1708 fprintf(fp,
" Warning: Rule uses content or pcre for http_method with "
1709 "flow:to_client or from_server\n");
1711 if (warn_method_serverbody ) {
1712 fprintf(fp,
" Warning: Rule uses content or pcre for http_method with content or "
1713 "pcre for http_server_body.\n");
1715 if (warn_pcre_method
1717 fprintf(fp,
" Warning: Rule uses pcre with only a http_method content; possible "
1718 "performance issue.\n");
1720 if (warn_offset_depth_pkt_stream) {
1721 fprintf(fp,
" Warning: Rule has depth"
1722 "/offset with raw content keywords. Please note the "
1723 "offset/depth will be checked against both packet "
1724 "payloads and stream. If you meant to have the offset/"
1725 "depth checked against just the payload, you can update "
1726 "the signature as \"alert tcp-pkt...\"\n");
1728 if (warn_offset_depth_alproto) {
1730 " Warning: Rule has "
1731 "offset/depth set along with a match on a specific "
1732 "app layer protocol - %d. This can lead to FNs if we "
1733 "have a offset/depth content match on a packet payload "
1734 "before we can detect the app layer protocol for the "
1738 if (warn_non_alproto_fp_for_alproto_sig) {
1739 fprintf(fp,
" Warning: Rule app layer "
1740 "protocol is http, but the fast_pattern is set on the raw "
1741 "stream. Consider adding fast_pattern over a http "
1742 "buffer for increased performance.");
1744 if (warn_no_direction) {
1745 fprintf(fp,
" Warning: Rule has no direction indicator.\n");
1747 if (warn_both_direction) {
1748 fprintf(fp,
" Warning: Rule is inspecting both the request and the response.\n");
1750 if (warn_file_store_not_present) {
1751 fprintf(fp,
" Warning: Rule requires file-store but the output file-store is not "
1754 if (rule_warning == 0) {
1755 fprintf(fp,
" No warnings for this rule.\n");