60 static int rule_warnings_only = 0;
116 { 0,
false,
false,
true,
"http_uri",
"http uri" },
117 { 0,
false,
false,
false,
"http_raw_uri",
"http raw uri" },
118 { 0,
false,
true,
false,
"http_method",
"http method" },
119 { 0,
false,
false,
false,
"http_request_line",
"http request line" },
120 { 0,
false,
false,
false,
"http_client_body",
"http client body" },
121 { 0,
false,
false,
true,
"http_header",
"http header" },
122 { 0,
false,
false,
false,
"http_raw_header",
"http raw header" },
123 { 0,
false,
false,
true,
"http_cookie",
"http cookie" },
124 { 0,
false,
false,
false,
"http_user_agent",
"http user agent" },
125 { 0,
false,
false,
false,
"http_host",
"http host" },
126 { 0,
false,
false,
false,
"http_raw_host",
"http raw host" },
127 { 0,
false,
false,
false,
"http_accept_enc",
"http accept enc" },
128 { 0,
false,
false,
false,
"http_referer",
"http referer" },
129 { 0,
false,
false,
false,
"http_content_type",
"http content type" },
130 { 0,
false,
false,
false,
"http_header_names",
"http header names" },
133 { 0,
false,
false,
false,
"http_stat_msg",
"http stat msg" },
134 { 0,
false,
false,
false,
"http_stat_code",
"http stat code" },
135 { 0,
false,
true,
false,
"file_data",
"http server body" },
138 { 0,
false,
false,
false,
"http_request_line",
"http request line" },
139 { 0,
false,
false,
false,
"http_accept",
"http accept" },
140 { 0,
false,
false,
false,
"http_accept_lang",
"http accept lang" },
141 { 0,
false,
false,
false,
"http_connection",
"http connection" },
142 { 0,
false,
false,
false,
"http_content_len",
"http content len" },
143 { 0,
false,
false,
false,
"http_protocol",
"http protocol" },
144 { 0,
false,
false,
false,
"http_start",
"http start" },
147 { 0,
false,
false,
false,
"http_response_line",
"http response line" },
148 { 0,
false,
false,
false,
"http.server",
"http server" },
149 { 0,
false,
false,
false,
"http.location",
"http location" },
152 static void FpPatternStatsAdd(
FpPatternStats *fp,
int list, uint16_t patlen)
161 else if (patlen < f->min)
173 int fast_pattern_set = 0;
174 int fast_pattern_only_set = 0;
175 int fast_pattern_chop_set = 0;
180 if (mpm_sm != NULL) {
183 fast_pattern_set = 1;
185 fast_pattern_only_set = 1;
187 fast_pattern_chop_set = 1;
193 fprintf(fp,
"== Sid: %u ==\n", s->
id);
194 fprintf(fp,
"%s\n", line);
196 fprintf(fp,
" Fast Pattern analysis:\n");
198 fprintf(fp,
" Prefilter on: %s\n",
205 fprintf(fp,
" No content present\n");
210 fprintf(fp,
" Fast pattern matcher: ");
211 int list_type = mpm_sm_list;
213 fprintf(fp,
"content\n");
218 fprintf(fp,
"%s (%s)\n", desc,
name);
223 fprintf(fp,
" Flags:");
225 fprintf(fp,
" Offset");
228 fprintf(fp,
" Depth");
232 fprintf(fp,
" Within");
236 fprintf(fp,
" Distance");
240 fprintf(fp,
" Nocase");
244 fprintf(fp,
" Negated");
248 fprintf(fp,
" None");
251 fprintf(fp,
" Fast pattern set: %s\n", fast_pattern_set ?
"yes" :
"no");
252 fprintf(fp,
" Fast pattern only set: %s\n", fast_pattern_only_set ?
"yes" :
"no");
253 fprintf(fp,
" Fast pattern chop set: %s\n", fast_pattern_chop_set ?
"yes" :
"no");
254 if (fast_pattern_chop_set) {
255 fprintf(fp,
" Fast pattern offset, length: %u, %u\n", fp_cd->
fp_chop_offset,
266 fprintf(fp,
" Original content: ");
270 if (fast_pattern_chop_set) {
279 fprintf(fp,
" Final content: ");
285 fprintf(fp,
" Final content: ");
304 int fp_engine_analysis_set = 0;
306 if ((
SCConfGetBool(
"engine-analysis.rules-fast-pattern", &fp_engine_analysis_set)) == 0) {
310 if (fp_engine_analysis_set == 0)
314 char *log_path =
SCMalloc(PATH_MAX);
315 if (log_path == NULL) {
316 FatalError(
"Unable to allocate scratch memory for rule filename");
318 snprintf(log_path, PATH_MAX,
"%s/%s%s", log_dir,
321 FILE *fp = fopen(log_path,
"w");
323 SCLogError(
"failed to open %s: %s", log_path, strerror(errno));
330 SCLogInfo(
"Engine-Analysis for fast_pattern printed to file - %s",
335 gettimeofday(&tval, NULL);
337 struct tm *tms =
SCLocalTime(tval.tv_sec, &local_tm);
338 fprintf(fp,
"----------------------------------------------"
339 "---------------------\n");
341 "Date: %" PRId32
"/%" PRId32
"/%04d -- "
343 tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
345 fprintf(fp,
"----------------------------------------------"
346 "---------------------\n");
359 #define DETECT_PERCENT_ENCODING_REGEX "%[0-9|a-f|A-F]{2}"
365 PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
367 PCRE2_UCHAR errbuffer[256];
368 pcre2_get_error_message(en, errbuffer,
sizeof(errbuffer));
389 }
else if (value && strcasecmp(value,
"warnings-only") == 0) {
391 rule_warnings_only = 1;
396 char log_path[PATH_MAX];
397 snprintf(log_path,
sizeof(log_path),
"%s/%s%s", log_dir,
401 SCLogError(
"failed to open %s: %s", log_path, strerror(errno));
405 SCLogInfo(
"Engine-Analysis for rules printed to file - %s",
409 gettimeofday(&tval, NULL);
411 struct tm *tms =
SCLocalTime(tval.tv_sec, &local_tm);
413 "----------------------------------------------"
414 "---------------------\n");
416 "Date: %" PRId32
"/%" PRId32
"/%04d -- "
418 tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
421 "----------------------------------------------"
422 "---------------------\n");
425 if (!PerCentEncodingSetup(
de_ctx->
ea)) {
427 "Error compiling regex; can't check for percent encoding in normalized "
433 SCLogInfo(
"Conf parameter \"engine-analysis.rules\" not found. "
434 "Defaulting to not printing the rules analysis report.");
437 SCLogInfo(
"Engine-Analysis for rules disabled in conf file.");
446 fprintf(fp,
"============\n"
447 "Summary:\n============\n");
455 "%s, smallest pattern %u byte(s), longest pattern %u byte(s), number of patterns "
456 "%u, avg pattern len %.2f byte(s)\n",
458 (
float)((
double)f->
tot / (
float)f->
cnt));
478 *fp_analysis =
false;
479 *rule_analysis =
false;
483 FatalError(
"Unable to allocate per-engine analysis context");
488 if (cfg_prefix_len > 0) {
493 FatalError(
"Unable to allocate per-engine analysis context name buffer");
499 *fp_analysis = SetupFPAnalyzer(
de_ctx);
500 *rule_analysis = SetupRuleAnalyzer(
de_ctx);
502 if (!(*fp_analysis || *rule_analysis)) {
514 CleanupRuleAnalyzer(
de_ctx);
515 CleanupFPAnalyzer(
de_ctx);
532 static int PerCentEncodingMatch(
EngineAnalysisCtx *ea_ctx, uint8_t *content, uint16_t content_len)
536 pcre2_match_data *match = pcre2_match_data_create_from_pattern(ea_ctx->
percent_re, NULL);
537 ret = pcre2_match(ea_ctx->
percent_re, (PCRE2_SPTR8)content, content_len, 0, 0, match, NULL);
540 }
else if (ret < -1) {
541 SCLogError(
"Error parsing content - %s; error code is %d", content, ret);
544 pcre2_match_data_free(match);
554 if (mpm_sm != NULL) {
592 const int list_type = mpm_sm_list;
601 payload ? (stream ?
"payload and reassembled stream" :
"payload")
602 :
"reassembled stream");
609 }
else if (desc ||
name) {
629 fprintf(tmp_fp,
"== Sid: UNKNOWN ==\n");
630 fprintf(tmp_fp,
"%s\n", line);
631 fprintf(tmp_fp,
" FAILURE: invalid rule.\n");
632 fprintf(tmp_fp,
" File: %s.\n", file);
633 fprintf(tmp_fp,
" Line: %d.\n", lineno);
634 fprintf(tmp_fp,
"\n");
651 vsnprintf(
str,
sizeof(
str), fmt, ap);
655 ctx->js_notes = SCJbNewArray();
657 SCJbAppendString(
ctx->js_notes,
str);
666 vsnprintf(
str,
sizeof(
str), fmt, ap);
669 if (!
ctx->js_warnings)
670 ctx->js_warnings = SCJbNewArray();
671 if (
ctx->js_warnings)
672 SCJbAppendString(
ctx->js_warnings,
str);
675 #define CHECK(pat) if (strlen((pat)) <= len && memcmp((pat), buf, MIN(len, strlen((pat)))) == 0) return true;
677 static bool LooksLikeHTTPMethod(
const uint8_t *buf, uint16_t
len)
686 static bool LooksLikeHTTPUA(
const uint8_t *buf, uint16_t
len)
688 CHECK(
"User-Agent: ");
689 CHECK(
"\nUser-Agent: ");
695 char pattern_str[1024] =
"";
698 SCJbSetString(js,
"pattern", pattern_str);
707 SCJbSetUint(js,
"offset", cd->
offset);
710 SCJbSetUint(js,
"depth", cd->
depth);
713 SCJbSetInt(js,
"distance", cd->
distance);
716 SCJbSetInt(js,
"within", cd->
within);
735 SCJbOpenArray(js,
"matches");
739 SCJbSetString(js,
"name", mname);
745 SCJbOpenObject(js,
"content");
748 AnalyzerNote(
ctx, (
char *)
"'fast_pattern:only' option is silently ignored and "
749 "is interpreted as regular 'fast_pattern'");
753 (
char *)
"pattern looks like it inspects HTTP, use http.request_line or "
754 "http.method and http.uri instead for improved performance");
758 (
char *)
"pattern looks like it inspects HTTP, use http.user_agent "
759 "or http.header for improved performance");
762 AnalyzerNote(
ctx, (
char *)
"'within' option for pattern w/o previous content "
763 "was converted to 'depth'");
766 AnalyzerNote(
ctx, (
char *)
"'distance' option for pattern w/o previous content "
767 "was converted to 'offset'");
775 SCJbOpenObject(js,
"pcre");
780 (
char *)
"'/B' (rawbytes) option is a no-op and is silently ignored");
787 SCJbOpenObject(js,
"byte_jump");
788 SCJbSetUint(js,
"nbytes", cd->
nbytes);
789 SCJbSetInt(js,
"offset", cd->
offset);
790 SCJbSetUint(js,
"multiplier", cd->
multiplier);
794 SCJbSetString(js,
"base",
"unset");
797 SCJbSetString(js,
"base",
"oct");
800 SCJbSetString(js,
"base",
"dec");
803 SCJbSetString(js,
"base",
"hex");
806 SCJbOpenArray(js,
"flags");
808 SCJbAppendString(js,
"from_beginning");
810 SCJbAppendString(js,
"little_endian");
812 SCJbAppendString(js,
"big_endian");
814 SCJbAppendString(js,
"string");
816 SCJbAppendString(js,
"relative");
818 SCJbAppendString(js,
"align");
820 SCJbAppendString(js,
"dce");
822 SCJbAppendString(js,
"offset_be");
824 SCJbAppendString(js,
"from_end");
832 SCJbOpenObject(js,
"byte_test");
833 SCJbSetUint(js,
"nbytes", cd->
nbytes);
834 SCJbSetInt(js,
"offset", cd->
offset);
837 SCJbSetString(js,
"base",
"unset");
840 SCJbSetString(js,
"base",
"oct");
843 SCJbSetString(js,
"base",
"dec");
846 SCJbSetString(js,
"base",
"hex");
849 SCJbOpenArray(js,
"flags");
851 SCJbAppendString(js,
"little_endian");
853 SCJbAppendString(js,
"big_endian");
855 SCJbAppendString(js,
"string");
857 SCJbAppendString(js,
"relative");
859 SCJbAppendString(js,
"dce");
866 SCJbOpenObject(js,
"absent");
867 SCJbSetBool(js,
"or_else", dad->
or_else);
875 SCJbOpenObject(js,
"ipopts");
877 SCJbSetString(js,
"option", flag);
884 SCJbOpenObject(js,
"flowbits");
887 SCJbSetString(js,
"cmd",
"isset");
890 SCJbSetString(js,
"cmd",
"isnotset");
893 SCJbSetString(js,
"cmd",
"set");
896 SCJbSetString(js,
"cmd",
"unset");
899 SCJbSetString(js,
"cmd",
"toggle");
903 SCJbOpenArray(js,
"names");
909 const char *varname =
911 SCJbAppendString(js, varname);
916 SCJbSetString(js,
"operator",
"or");
924 SCJbOpenObject(js,
"flowint");
927 SCJbSetString(js,
"cmd",
"set");
930 SCJbSetString(js,
"cmd",
"add");
933 SCJbSetString(js,
"cmd",
"sub");
936 SCJbSetString(js,
"cmd",
"lt");
939 SCJbSetString(js,
"cmd",
"lte");
942 SCJbSetString(js,
"cmd",
"eq");
945 SCJbSetString(js,
"cmd",
"ne");
948 SCJbSetString(js,
"cmd",
"gte");
951 SCJbSetString(js,
"cmd",
"gt");
954 SCJbSetString(js,
"cmd",
"isset");
957 SCJbSetString(js,
"cmd",
"isnotset");
961 if (varname != NULL) {
962 SCJbSetString(js,
"var", varname);
976 SCJbOpenObject(js,
"ack");
977 SCDetectU32ToJson(js, cd);
983 SCJbOpenObject(js,
"seq");
984 SCDetectU32ToJson(js, cd);
990 SCJbOpenObject(js,
"tcp_mss");
991 SCDetectU16ToJson(js, cd);
997 SCJbOpenObject(js,
"dsize");
998 SCDetectU16ToJson(js, cd);
1004 SCJbOpenObject(js,
"code");
1005 SCDetectU8ToJson(js, cd);
1011 SCJbOpenObject(js,
"ttl");
1012 SCDetectU8ToJson(js, cd);
1018 SCJbOpenObject(js,
"id");
1019 SCDetectU16ToJson(js, cd);
1025 SCJbOpenObject(js,
"window");
1026 SCDetectU16ToJson(js, cd);
1032 SCJbOpenObject(js,
"flow_age");
1033 SCDetectU32ToJson(js, cd);
1054 ctx.js = SCJbNewObject();
1065 SCJbSetUint(
ctx.js,
"id", s->
id);
1066 SCJbSetUint(
ctx.js,
"gid", s->
gid);
1067 SCJbSetUint(
ctx.js,
"rev", s->
rev);
1068 SCJbSetString(
ctx.js,
"msg", s->
msg);
1071 SCJbSetString(
ctx.js,
"app_proto", alproto);
1073 SCJbOpenArray(
ctx.js,
"requirements");
1075 SCJbAppendString(
ctx.js,
"payload");
1078 SCJbAppendString(
ctx.js,
"no_payload");
1081 SCJbAppendString(
ctx.js,
"flow");
1084 SCJbAppendString(
ctx.js,
"tcp_flags_init_deinit");
1087 SCJbAppendString(
ctx.js,
"tcp_flags_unusual");
1090 SCJbAppendString(
ctx.js,
"engine_event");
1093 SCJbAppendString(
ctx.js,
"real_pkt");
1097 SCJbOpenObject(
ctx.js,
"match_policy");
1098 SCJbOpenArray(
ctx.js,
"actions");
1100 SCJbAppendString(
ctx.js,
"alert");
1103 SCJbAppendString(
ctx.js,
"drop");
1106 SCJbAppendString(
ctx.js,
"reject");
1109 SCJbAppendString(
ctx.js,
"reject_dst");
1112 SCJbAppendString(
ctx.js,
"reject_both");
1115 SCJbAppendString(
ctx.js,
"config");
1118 SCJbAppendString(
ctx.js,
"pass");
1121 SCJbAppendString(
ctx.js,
"accept");
1127 switch (flow_action) {
1129 SCJbSetString(
ctx.js,
"scope",
"packet");
1132 SCJbSetString(
ctx.js,
"scope",
"flow");
1135 SCJbSetString(
ctx.js,
"scope",
"flow_if_stateful");
1142 SCJbSetString(
ctx.js,
"scope",
"packet");
1145 SCJbSetString(
ctx.js,
"scope",
"flow");
1148 SCJbSetString(
ctx.js,
"scope",
"hook");
1151 SCJbSetString(
ctx.js,
"scope",
"tx");
1161 SCJbSetString(
ctx.js,
"type",
"unset");
1164 SCJbSetString(
ctx.js,
"type",
"ip_only");
1167 SCJbSetString(
ctx.js,
"type",
"like_ip_only");
1170 SCJbSetString(
ctx.js,
"type",
"pd_only");
1173 SCJbSetString(
ctx.js,
"type",
"de_only");
1176 SCJbSetString(
ctx.js,
"type",
"pkt");
1179 SCJbSetString(
ctx.js,
"type",
"pkt_stream");
1182 SCJbSetString(
ctx.js,
"type",
"stream");
1185 SCJbSetString(
ctx.js,
"type",
"app_layer");
1188 SCJbSetString(
ctx.js,
"type",
"app_tx");
1191 SCJbSetString(
ctx.js,
"type",
"error");
1197 SCJbOpenObject(
ctx.js,
"dependencies");
1198 SCJbOpenObject(
ctx.js,
"flowbits");
1199 SCJbOpenObject(
ctx.js,
"upstream");
1201 SCJbOpenObject(
ctx.js,
"state_modifying_rules");
1202 SCJbOpenArray(
ctx.js,
"sids");
1207 SCJbOpenArray(
ctx.js,
"names");
1210 SCJbAppendString(
ctx.js,
1223 SCJbOpenArray(
ctx.js,
"flags");
1225 SCJbAppendString(
ctx.js,
"src_any");
1228 SCJbAppendString(
ctx.js,
"dst_any");
1231 SCJbAppendString(
ctx.js,
"sp_any");
1234 SCJbAppendString(
ctx.js,
"dp_any");
1237 SCJbAppendString(
ctx.js,
"noalert");
1240 SCJbAppendString(
ctx.js,
"dsize");
1243 SCJbAppendString(
ctx.js,
"applayer");
1246 SCJbAppendString(
ctx.js,
"need_packet");
1249 SCJbAppendString(
ctx.js,
"need_stream");
1252 SCJbAppendString(
ctx.js,
"negated_mpm");
1255 SCJbAppendString(
ctx.js,
"flush");
1258 SCJbAppendString(
ctx.js,
"need_flowvar");
1261 SCJbAppendString(
ctx.js,
"filestore");
1264 SCJbAppendString(
ctx.js,
"toserver");
1267 SCJbAppendString(
ctx.js,
"toclient");
1270 SCJbAppendString(
ctx.js,
"tlsstore");
1273 SCJbAppendString(
ctx.js,
"bypass");
1276 SCJbAppendString(
ctx.js,
"prefilter");
1279 SCJbAppendString(
ctx.js,
"src_is_target");
1282 SCJbAppendString(
ctx.js,
"dst_is_target");
1289 SCJbOpenArray(
ctx.js,
"pkt_engines");
1291 for ( ; pkt != NULL; pkt = pkt->
next) {
1306 SCJbStartObject(
ctx.js);
1307 SCJbSetString(
ctx.js,
"name",
name);
1308 SCJbSetBool(
ctx.js,
"is_mpm", pkt->
mpm);
1310 SCJbOpenArray(
ctx.js,
"transforms");
1312 SCJbStartObject(
ctx.js);
1313 SCJbSetString(
ctx.js,
"name",
1326 SCJbOpenArray(
ctx.js,
"frame_engines");
1328 for (; frame != NULL; frame = frame->
next) {
1330 SCJbStartObject(
ctx.js);
1331 SCJbSetString(
ctx.js,
"name",
name);
1332 SCJbSetBool(
ctx.js,
"is_mpm", frame->
mpm);
1334 SCJbOpenArray(
ctx.js,
"transforms");
1336 SCJbStartObject(
ctx.js);
1337 SCJbSetString(
ctx.js,
"name",
1349 bool has_stream =
false;
1350 bool has_client_body_mpm =
false;
1351 bool has_file_data_mpm =
false;
1353 SCJbOpenArray(
ctx.js,
"engines");
1355 for ( ; app != NULL; app = app->
next) {
1370 }
else if (app->
mpm && strcmp(
name,
"http_client_body") == 0) {
1371 has_client_body_mpm =
true;
1372 }
else if (app->
mpm && strcmp(
name,
"file_data") == 0) {
1373 has_file_data_mpm =
true;
1376 SCJbStartObject(
ctx.js);
1377 SCJbSetString(
ctx.js,
"name",
name);
1378 const char *direction = app->
dir == 0 ?
"toserver" :
"toclient";
1379 SCJbSetString(
ctx.js,
"direction", direction);
1380 SCJbSetBool(
ctx.js,
"is_mpm", app->
mpm);
1385 SCJbOpenArray(
ctx.js,
"transforms");
1387 SCJbStartObject(
ctx.js);
1388 SCJbSetString(
ctx.js,
"name",
1402 if (has_stream && has_client_body_mpm)
1403 AnalyzerNote(&
ctx, (
char *)
"mpm in http_client_body combined with stream match leads to stream buffering");
1404 if (has_stream && has_file_data_mpm)
1405 AnalyzerNote(&
ctx, (
char *)
"mpm in file_data combined with stream match leads to stream buffering");
1408 SCJbOpenObject(
ctx.js,
"lists");
1418 if (pkt_mpm || app_mpm) {
1419 SCJbOpenObject(
ctx.js,
"mpm");
1427 SCJbSetString(
ctx.js,
"buffer",
name);
1434 switch (smd->
type) {
1438 DumpContent(
ctx.js, cd);
1450 SCJbOpenObject(
ctx.js,
"prefilter");
1457 SCJbSetString(
ctx.js,
"buffer",
name);
1459 SCJbSetString(
ctx.js,
"name", mname);
1463 if (
ctx.js_warnings) {
1464 SCJbClose(
ctx.js_warnings);
1465 SCJbSetObject(
ctx.js,
"warnings",
ctx.js_warnings);
1466 SCJbFree(
ctx.js_warnings);
1467 ctx.js_warnings = NULL;
1470 SCJbClose(
ctx.js_notes);
1471 SCJbSetObject(
ctx.js,
"notes",
ctx.js_notes);
1472 SCJbFree(
ctx.js_notes);
1473 ctx.js_notes = NULL;
1477 const char *filename =
"rules.json";
1479 char json_path[PATH_MAX] =
"";
1480 snprintf(json_path,
sizeof(json_path),
"%s/%s%s", log_dir,
1484 FILE *fp = fopen(json_path,
"a");
1486 fwrite(SCJbPtr(
ctx.js), SCJbLen(
ctx.js), 1, fp);
1500 SCJsonBuilder *root_jb = SCJbNewObject();
1504 SCJbOpenArray(root_jb,
"buffers");
1508 char str[1024] =
"";
1512 SCJsonBuilder *jb = arrays[p->
sm_list];
1513 if (arrays[p->
sm_list] == NULL) {
1514 jb = arrays[p->
sm_list] = SCJbNewObject();
1520 SCJbSetString(jb,
"name",
name);
1521 SCJbSetUint(jb,
"list_id", p->
sm_list);
1523 SCJbOpenArray(jb,
"patterns");
1526 SCJbStartObject(jb);
1527 SCJbSetString(jb,
"pattern",
str);
1529 SCJbSetUint(jb,
"cnt", p->
cnt);
1530 SCJbSetUint(jb,
"mpm", p->
mpm);
1531 SCJbOpenObject(jb,
"flags");
1542 SCJsonBuilder *jb = arrays[i];
1549 SCJbAppendObject(root_jb, jb);
1555 const char *filename =
"patterns.json";
1557 char json_path[PATH_MAX] =
"";
1558 snprintf(json_path,
sizeof(json_path),
"%s/%s%s", log_dir,
1562 FILE *fp = fopen(json_path,
"a");
1564 fwrite(SCJbPtr(root_jb), SCJbLen(root_jb), 1, fp);
1585 EngineAnalysisItemsReset(ea_ctx);
1593 FatalError(
"Unable to allocate analysis scratch pad");
1603 analyzer_item->
item_id = (uint16_t)item_id;
1604 if (analyzer_item->
item_id == -1) {
1606 FatalError(
"unable to initialize engine-analysis table: detect buffer \"%s\" not "
1639 uint32_t rule_bidirectional = 0;
1640 uint32_t rule_pcre = 0;
1641 uint32_t rule_pcre_http = 0;
1642 uint32_t rule_content = 0;
1643 uint32_t rule_flow = 0;
1644 uint32_t rule_flags = 0;
1645 uint32_t rule_flow_toserver = 0;
1646 uint32_t rule_flow_toclient = 0;
1647 uint32_t rule_flow_nostream = 0;
1648 uint32_t rule_ipv4_only = 0;
1649 uint32_t rule_ipv6_only = 0;
1650 uint32_t rule_flowbits = 0;
1651 uint32_t rule_flowint = 0;
1652 uint32_t rule_content_http = 0;
1653 uint32_t rule_content_offset_depth = 0;
1654 int32_t list_id = 0;
1655 uint32_t rule_warning = 0;
1656 uint32_t stream_buf = 0;
1657 uint32_t packet_buf = 0;
1658 uint32_t file_store = 0;
1659 uint32_t warn_pcre_no_content = 0;
1660 uint32_t warn_pcre_http_content = 0;
1661 uint32_t warn_pcre_http = 0;
1662 uint32_t warn_content_http_content = 0;
1663 uint32_t warn_content_http = 0;
1664 uint32_t warn_tcp_no_flow = 0;
1665 uint32_t warn_client_ports = 0;
1666 uint32_t warn_direction = 0;
1667 uint32_t warn_method_toclient = 0;
1668 uint32_t warn_method_serverbody = 0;
1669 uint32_t warn_pcre_method = 0;
1670 uint32_t warn_encoding_norm_http_buf = 0;
1671 uint32_t warn_file_store_not_present = 0;
1672 uint32_t warn_offset_depth_pkt_stream = 0;
1673 uint32_t warn_offset_depth_alproto = 0;
1674 uint32_t warn_non_alproto_fp_for_alproto_sig = 0;
1675 uint32_t warn_no_direction = 0;
1676 uint32_t warn_both_direction = 0;
1678 EngineAnalysisItemsInit(
de_ctx->
ea);
1684 rule_bidirectional = 1;
1698 rule_ipv4_only += 1;
1701 rule_ipv6_only += 1;
1709 if (item_slot == -1) {
1717 if (item_slot == -1) {
1722 rule_content_offset_depth++;
1728 rule_content_http++;
1735 warn_encoding_norm_http_buf += 1;
1742 rule_flow_toserver = 1;
1745 rule_flow_toclient = 1;
1750 rule_flow_nostream = 1;
1764 if (sm->
ctx != NULL) {
1774 warn_file_store_not_present = 1;
1777 if (rule_pcre > 0 && rule_content == 0 && rule_content_http == 0) {
1779 warn_pcre_no_content = 1;
1782 if (rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0) {
1784 warn_pcre_http_content = 1;
1790 if (rule_content > 0 && rule_content_http > 0) {
1792 warn_content_http_content = 1;
1796 warn_content_http = 1;
1798 if (rule_content == 1) {
1803 (rule_content || rule_content_http || rule_pcre || rule_pcre_http || rule_flowbits ||
1806 warn_tcp_no_flow = 1;
1808 if (rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)
1813 warn_client_ports = 1;
1816 if (rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)) {
1821 if (*http_method_item_seen_ptr) {
1822 if (rule_flow && rule_flow_toclient) {
1824 warn_method_toclient = 1;
1826 if (*http_server_body_item_seen_ptr) {
1828 warn_method_serverbody = 1;
1830 if (rule_content == 0 && rule_content_http == 0 && (rule_pcre > 0 || rule_pcre_http > 0)) {
1832 warn_pcre_method = 1;
1835 if (rule_content_offset_depth > 0 && stream_buf && packet_buf) {
1837 warn_offset_depth_pkt_stream = 1;
1841 warn_offset_depth_alproto = 1;
1846 warn_non_alproto_fp_for_alproto_sig = 1;
1850 warn_no_direction += 1;
1857 warn_both_direction += 1;
1862 if (!rule_warnings_only || (rule_warnings_only && rule_warning > 0)) {
1864 fprintf(fp,
"== Sid: %u ==\n", s->
id);
1865 fprintf(fp,
"%s\n", line);
1871 fprintf(fp,
" Rule is ip only.\n");
1874 fprintf(fp,
" Rule is like ip only.\n");
1877 fprintf(fp,
" Rule is PD only.\n");
1880 fprintf(fp,
" Rule is DE only.\n");
1883 fprintf(fp,
" Rule is packet inspecting.\n");
1886 fprintf(fp,
" Rule is packet and stream inspecting.\n");
1889 fprintf(fp,
" Rule is stream inspecting.\n");
1892 fprintf(fp,
" Rule is app-layer inspecting.\n");
1895 fprintf(fp,
" Rule is App-layer TX inspecting.\n");
1901 fprintf(fp,
" Rule is IPv6 only.\n");
1903 fprintf(fp,
" Rule is IPv4 only.\n");
1905 fprintf(fp,
" Rule matches on packets.\n");
1906 if (!rule_flow_nostream && stream_buf &&
1907 (rule_flow || rule_flowbits || rule_flowint || rule_content || rule_pcre)) {
1908 fprintf(fp,
" Rule matches on reassembled stream.\n");
1913 fprintf(fp,
" Rule matches on %s buffer.\n", ai->
display_name);
1919 if (rule_content || rule_content_http || rule_pcre || rule_pcre_http) {
1921 " Rule contains %u content options, %u http content options, %u pcre "
1922 "options, and %u pcre options with http modifiers.\n",
1923 rule_content, rule_content_http, rule_pcre, rule_pcre_http);
1928 fprintf(fp,
" Prefilter on: %s.\n",
1931 EngineAnalysisRulesPrintFP(
de_ctx, s);
1935 if (warn_pcre_no_content ) {
1936 fprintf(fp,
" Warning: Rule uses pcre without a content option present.\n"
1937 " -Consider adding a content to improve performance of this "
1940 if (warn_pcre_http_content ) {
1941 fprintf(fp,
" Warning: Rule uses content options with http_* and pcre options "
1942 "without http modifiers.\n"
1943 " -Consider adding http pcre modifier.\n");
1945 else if (warn_pcre_http ) {
1946 fprintf(fp,
" Warning: Rule app layer protocol is http, but pcre options do not "
1947 "have http modifiers.\n"
1948 " -Consider adding http pcre modifiers.\n");
1950 if (warn_content_http_content ) {
1952 " Warning: Rule contains content with http_* and content without http_*.\n"
1953 " -Consider adding http content modifiers.\n");
1955 if (warn_content_http ) {
1956 fprintf(fp,
" Warning: Rule app layer protocol is http, but content options do not "
1957 "have http_* modifiers.\n"
1958 " -Consider adding http content modifiers.\n");
1960 if (rule_content == 1) {
1963 if (warn_encoding_norm_http_buf) {
1964 fprintf(fp,
" Warning: Rule may contain percent encoded content for a normalized "
1965 "http buffer match.\n");
1967 if (warn_tcp_no_flow
1969 fprintf(fp,
" Warning: TCP rule without a flow or flags option.\n"
1970 " -Consider adding flow or flags to improve performance of "
1973 if (warn_client_ports
1978 " Warning: Rule contains ports or port variables only on the client side.\n"
1979 " -Flow direction possibly inconsistent with rule.\n");
1981 if (warn_direction ) {
1982 fprintf(fp,
" Warning: Rule is bidirectional and has a flow option with a specific "
1985 if (warn_method_toclient ) {
1986 fprintf(fp,
" Warning: Rule uses content or pcre for http_method with "
1987 "flow:to_client or from_server\n");
1989 if (warn_method_serverbody ) {
1990 fprintf(fp,
" Warning: Rule uses content or pcre for http_method with content or "
1991 "pcre for http_server_body.\n");
1993 if (warn_pcre_method
1995 fprintf(fp,
" Warning: Rule uses pcre with only a http_method content; possible "
1996 "performance issue.\n");
1998 if (warn_offset_depth_pkt_stream) {
1999 fprintf(fp,
" Warning: Rule has depth"
2000 "/offset with raw content keywords. Please note the "
2001 "offset/depth will be checked against both packet "
2002 "payloads and stream. If you meant to have the offset/"
2003 "depth checked against just the payload, you can update "
2004 "the signature as \"alert tcp-pkt...\"\n");
2006 if (warn_offset_depth_alproto) {
2008 " Warning: Rule has "
2009 "offset/depth set along with a match on a specific "
2010 "app layer protocol - %d. This can lead to FNs if we "
2011 "have a offset/depth content match on a packet payload "
2012 "before we can detect the app layer protocol for the "
2016 if (warn_non_alproto_fp_for_alproto_sig) {
2017 fprintf(fp,
" Warning: Rule app layer "
2018 "protocol is http, but the fast_pattern is set on the raw "
2019 "stream. Consider adding fast_pattern over a http "
2020 "buffer for increased performance.");
2022 if (warn_no_direction) {
2023 fprintf(fp,
" Warning: Rule has no direction indicator.\n");
2025 if (warn_both_direction) {
2026 fprintf(fp,
" Warning: Rule is inspecting both the request and the response.\n");
2028 if (warn_file_store_not_present) {
2029 fprintf(fp,
" Warning: Rule requires file-store but the output file-store is not "
2032 if (rule_warning == 0) {
2033 fprintf(fp,
" No warnings for this rule.\n");
2044 uint32_t accept_rules = 0;
2045 SCJbSetString(
ctx->js,
"policy",
"drop:flow");
2046 SCJbOpenArray(
ctx->js,
"rules");
2055 if (direction == STREAM_TOSERVER) {
2072 if (accept_rules == 0) {
2073 AnalyzerWarning(
ctx, (
char *)
"no accept rules for state, default policy will be applied");
2080 ctx.js = SCJbNewObject();
2084 SCJbOpenObject(
ctx.js,
"tables");
2085 SCJbOpenObject(
ctx.js,
"packet:filter");
2086 SCJbSetString(
ctx.js,
"policy",
"drop:packet");
2087 SCJbOpenArray(
ctx.js,
"rules");
2088 uint32_t accept_rules = 0;
2089 uint32_t last_sid = 0;
2096 if (last_sid == s->
id)
2103 if (accept_rules == 0) {
2104 AnalyzerWarning(&
ctx,
2105 (
char *)
"no accept rules for \'packet:filter\', default policy will be applied");
2107 if (
ctx.js_warnings) {
2108 SCJbClose(
ctx.js_warnings);
2109 SCJbSetObject(
ctx.js,
"warnings",
ctx.js_warnings);
2110 SCJbFree(
ctx.js_warnings);
2111 ctx.js_warnings = NULL;
2116 if (!AppProtoIsValid(a))
2125 const uint8_t complete_state_ts =
2127 for (uint8_t state = 0; state < complete_state_ts; state++) {
2130 char table_name[128];
2132 SCJbOpenObject(
ctx.js, table_name);
2133 FirewallAddRulesForState(
de_ctx, a, state, STREAM_TOSERVER, &
ctx);
2134 if (
ctx.js_warnings) {
2135 SCJbClose(
ctx.js_warnings);
2136 SCJbSetObject(
ctx.js,
"warnings",
ctx.js_warnings);
2137 SCJbFree(
ctx.js_warnings);
2138 ctx.js_warnings = NULL;
2142 const uint8_t complete_state_tc =
2144 for (uint8_t state = 0; state < complete_state_tc; state++) {
2147 char table_name[128];
2149 SCJbOpenObject(
ctx.js, table_name);
2150 FirewallAddRulesForState(
de_ctx, a, state, STREAM_TOCLIENT, &
ctx);
2151 if (
ctx.js_warnings) {
2152 SCJbClose(
ctx.js_warnings);
2153 SCJbSetObject(
ctx.js,
"warnings",
ctx.js_warnings);
2154 SCJbFree(
ctx.js_warnings);
2155 ctx.js_warnings = NULL;
2161 SCJbOpenObject(
ctx.js,
"packet:td");
2162 SCJbSetString(
ctx.js,
"policy",
"accept:hook");
2164 SCJbOpenArray(
ctx.js,
"rules");
2170 if (last_sid == s->
id)
2177 SCJbOpenObject(
ctx.js,
"app:td");
2178 SCJbSetString(
ctx.js,
"policy",
"accept:hook");
2180 SCJbOpenArray(
ctx.js,
"rules");
2186 if (last_sid == s->
id)
2195 SCJbOpenObject(
ctx.js,
"lists");
2196 SCJbOpenObject(
ctx.js,
"firewall");
2198 SCJbOpenArray(
ctx.js,
"rules");
2202 if (last_sid == s->
id)
2210 SCJbOpenObject(
ctx.js,
"td");
2212 SCJbOpenArray(
ctx.js,
"rules");
2216 if (last_sid == s->
id)
2224 SCJbOpenObject(
ctx.js,
"all");
2226 SCJbOpenArray(
ctx.js,
"rules");
2228 if (last_sid == s->
id)
2240 const char *filename =
"firewall.json";
2242 char json_path[PATH_MAX] =
"";
2243 snprintf(json_path,
sizeof(json_path),
"%s/%s", log_dir, filename);
2246 FILE *fp = fopen(json_path,
"w");
2248 fwrite(SCJbPtr(
ctx.js), SCJbLen(
ctx.js), 1, fp);