suricata
detect-engine-analyzer.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2025 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Eileen Donlon <emdonlo@gmail.com>
22  * \author Victor Julien <victor@inliniac.net>
23  *
24  * Rule analyzers for the detection engine
25  */
26 
27 #include "suricata-common.h"
28 #include "suricata.h"
29 #include "rust.h"
30 #include "action-globals.h"
31 #include "detect.h"
32 #include "detect-parse.h"
33 #include "detect-engine.h"
34 #include "detect-engine-analyzer.h"
35 #include "detect-engine-mpm.h"
36 #include "detect-engine-uint.h"
37 #include "conf.h"
38 #include "detect-content.h"
39 #include "detect-pcre.h"
40 #include "detect-bytejump.h"
41 #include "detect-bytetest.h"
42 #include "detect-isdataat.h"
43 #include "detect-flow.h"
44 #include "detect-ttl.h"
45 #include "detect-tcp-flags.h"
46 #include "detect-tcp-ack.h"
47 #include "detect-ipopts.h"
48 #include "detect-tcp-seq.h"
49 #include "feature.h"
50 #include "util-print.h"
51 #include "util-validate.h"
52 #include "util-conf.h"
53 #include "detect-flowbits.h"
54 #include "detect-flowint.h"
55 #include "detect-xbits.h"
56 #include "util-var-name.h"
57 #include "detect-icmp-id.h"
58 #include "detect-tcp-window.h"
60 #include "app-layer-parser.h"
61 #include "detect-tcp-session.h"
62 
63 static int rule_warnings_only = 0;
64 
65 /* Details for each buffer being tracked */
66 typedef struct DetectEngineAnalyzerItems {
67  int16_t item_id;
68  bool item_seen;
71  const char *item_name;
72  const char *display_name;
74 
75 typedef struct FpPatternStats_ {
76  uint16_t min;
77  uint16_t max;
78  uint32_t cnt;
79  uint64_t tot;
81 
82 /* Track which items require the item_seen value to be exposed */
84  const char *bufname;
86 };
87 
88 typedef struct EngineAnalysisCtx_ {
89 
92 
94  char *file_prefix;
95  pcre2_code *percent_re;
96 
97  /*
98  * This array contains the map between the `analyzer_items` array listed above and
99  * the item ids returned by DetectBufferTypeGetByName. Iterating signature's sigmatch
100  * array provides list_ids. The map converts those ids into elements of the
101  * analyzer items array.
102  *
103  * Ultimately, the g_buffer_type_hash is searched for each buffer name. The size of that
104  * hashlist is 256, so that's the value we use here.
105  */
106  int16_t analyzer_item_map[256];
108  /*
109  * Certain values must be directly accessible. This array contains items that are directly
110  * accessed when checking if they've been seen or not.
111  */
113 
116 
118  /* request keywords */
119  { 0, false, false, true, "http_uri", "http uri" },
120  { 0, false, false, false, "http_raw_uri", "http raw uri" },
121  { 0, false, true, false, "http_method", "http method" },
122  { 0, false, false, false, "http_request_line", "http request line" },
123  { 0, false, false, false, "http_client_body", "http client body" },
124  { 0, false, false, true, "http_header", "http header" },
125  { 0, false, false, false, "http_raw_header", "http raw header" },
126  { 0, false, false, true, "http_cookie", "http cookie" },
127  { 0, false, false, false, "http_user_agent", "http user agent" },
128  { 0, false, false, false, "http_host", "http host" },
129  { 0, false, false, false, "http_raw_host", "http raw host" },
130  { 0, false, false, false, "http_accept_enc", "http accept enc" },
131  { 0, false, false, false, "http_referer", "http referer" },
132  { 0, false, false, false, "http_content_type", "http content type" },
133  { 0, false, false, false, "http_header_names", "http header names" },
134 
135  /* response keywords not listed above */
136  { 0, false, false, false, "http_stat_msg", "http stat msg" },
137  { 0, false, false, false, "http_stat_code", "http stat code" },
138  { 0, false, true, false, "file_data", "http server body" },
139 
140  /* missing request keywords */
141  { 0, false, false, false, "http_request_line", "http request line" },
142  { 0, false, false, false, "http_accept", "http accept" },
143  { 0, false, false, false, "http_accept_lang", "http accept lang" },
144  { 0, false, false, false, "http_connection", "http connection" },
145  { 0, false, false, false, "http_content_len", "http content len" },
146  { 0, false, false, false, "http_protocol", "http protocol" },
147  { 0, false, false, false, "http_start", "http start" },
148 
149  /* missing response keywords; some of the missing are listed above*/
150  { 0, false, false, false, "http_response_line", "http response line" },
151  { 0, false, false, false, "http.server", "http server" },
152  { 0, false, false, false, "http.location", "http location" },
153 };
154 
155 static void FpPatternStatsAdd(FpPatternStats *fp, int list, uint16_t patlen)
156 {
157  if (list < 0 || list >= DETECT_SM_LIST_MAX)
158  return;
159 
160  FpPatternStats *f = &fp[list];
161 
162  if (f->min == 0)
163  f->min = patlen;
164  else if (patlen < f->min)
165  f->min = patlen;
166 
167  if (patlen > f->max)
168  f->max = patlen;
169 
170  f->cnt++;
171  f->tot += patlen;
172 }
173 
174 void EngineAnalysisFP(const DetectEngineCtx *de_ctx, const Signature *s, const char *line)
175 {
176  int fast_pattern_set = 0;
177  int fast_pattern_only_set = 0;
178  int fast_pattern_chop_set = 0;
179  const DetectContentData *fp_cd = NULL;
180  const SigMatch *mpm_sm = s->init_data->mpm_sm;
181  const int mpm_sm_list = s->init_data->mpm_sm_list;
182 
183  if (mpm_sm != NULL) {
184  fp_cd = (DetectContentData *)mpm_sm->ctx;
185  if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN) {
186  fast_pattern_set = 1;
188  fast_pattern_only_set = 1;
189  } else if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
190  fast_pattern_chop_set = 1;
191  }
192  }
193  }
194 
195  FILE *fp = de_ctx->ea->fp_engine_analysis_fp;
196  fprintf(fp, "== Sid: %u ==\n", s->id);
197  fprintf(fp, "%s\n", line);
198 
199  fprintf(fp, " Fast Pattern analysis:\n");
200  if (s->init_data->prefilter_sm != NULL) {
201  fprintf(fp, " Prefilter on: %s\n",
203  fprintf(fp, "\n");
204  return;
205  }
206 
207  if (fp_cd == NULL) {
208  fprintf(fp, " No content present\n");
209  fprintf(fp, "\n");
210  return;
211  }
212 
213  fprintf(fp, " Fast pattern matcher: ");
214  int list_type = mpm_sm_list;
215  if (list_type == DETECT_SM_LIST_PMATCH)
216  fprintf(fp, "content\n");
217  else {
218  const char *desc = DetectEngineBufferTypeGetDescriptionById(de_ctx, list_type);
219  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, list_type);
220  if (desc && name) {
221  fprintf(fp, "%s (%s)\n", desc, name);
222  }
223  }
224 
225  int flags_set = 0;
226  fprintf(fp, " Flags:");
227  if (fp_cd->flags & DETECT_CONTENT_OFFSET) {
228  fprintf(fp, " Offset");
229  flags_set = 1;
230  } if (fp_cd->flags & DETECT_CONTENT_DEPTH) {
231  fprintf(fp, " Depth");
232  flags_set = 1;
233  }
234  if (fp_cd->flags & DETECT_CONTENT_WITHIN) {
235  fprintf(fp, " Within");
236  flags_set = 1;
237  }
238  if (fp_cd->flags & DETECT_CONTENT_DISTANCE) {
239  fprintf(fp, " Distance");
240  flags_set = 1;
241  }
242  if (fp_cd->flags & DETECT_CONTENT_NOCASE) {
243  fprintf(fp, " Nocase");
244  flags_set = 1;
245  }
246  if (fp_cd->flags & DETECT_CONTENT_NEGATED) {
247  fprintf(fp, " Negated");
248  flags_set = 1;
249  }
250  if (flags_set == 0)
251  fprintf(fp, " None");
252  fprintf(fp, "\n");
253 
254  fprintf(fp, " Fast pattern set: %s\n", fast_pattern_set ? "yes" : "no");
255  fprintf(fp, " Fast pattern only set: %s\n", fast_pattern_only_set ? "yes" : "no");
256  fprintf(fp, " Fast pattern chop set: %s\n", fast_pattern_chop_set ? "yes" : "no");
257  if (fast_pattern_chop_set) {
258  fprintf(fp, " Fast pattern offset, length: %u, %u\n", fp_cd->fp_chop_offset,
259  fp_cd->fp_chop_len);
260  }
261 
262  uint16_t patlen = fp_cd->content_len;
263  uint8_t *pat = SCMalloc(fp_cd->content_len + 1);
264  if (unlikely(pat == NULL)) {
265  FatalError("Error allocating memory");
266  }
267  memcpy(pat, fp_cd->content, fp_cd->content_len);
268  pat[fp_cd->content_len] = '\0';
269  fprintf(fp, " Original content: ");
270  PrintRawUriFp(fp, pat, patlen);
271  fprintf(fp, "\n");
272 
273  if (fast_pattern_chop_set) {
274  SCFree(pat);
275  patlen = fp_cd->fp_chop_len;
276  pat = SCMalloc(fp_cd->fp_chop_len + 1);
277  if (unlikely(pat == NULL)) {
278  exit(EXIT_FAILURE);
279  }
280  memcpy(pat, fp_cd->content + fp_cd->fp_chop_offset, fp_cd->fp_chop_len);
281  pat[fp_cd->fp_chop_len] = '\0';
282  fprintf(fp, " Final content: ");
283  PrintRawUriFp(fp, pat, patlen);
284  fprintf(fp, "\n");
285 
286  FpPatternStatsAdd(&de_ctx->ea->fp_pattern_stats[0], list_type, patlen);
287  } else {
288  fprintf(fp, " Final content: ");
289  PrintRawUriFp(fp, pat, patlen);
290  fprintf(fp, "\n");
291 
292  FpPatternStatsAdd(&de_ctx->ea->fp_pattern_stats[0], list_type, patlen);
293  }
294  SCFree(pat);
295 
296  fprintf(fp, "\n");
297 }
298 
299 /**
300  * \brief Sets up the fast pattern analyzer according to the config.
301  *
302  * \retval 1 If rule analyzer successfully enabled.
303  * \retval 0 If not enabled.
304  */
305 static int SetupFPAnalyzer(DetectEngineCtx *de_ctx)
306 {
307  int fp_engine_analysis_set = 0;
308 
309  if ((SCConfGetBool("engine-analysis.rules-fast-pattern", &fp_engine_analysis_set)) == 0) {
310  return false;
311  }
312 
313  if (fp_engine_analysis_set == 0)
314  return false;
315 
316  const char *log_dir = SCConfigGetLogDirectory();
317  char *log_path = SCMalloc(PATH_MAX);
318  if (log_path == NULL) {
319  FatalError("Unable to allocate scratch memory for rule filename");
320  }
321  snprintf(log_path, PATH_MAX, "%s/%s%s", log_dir,
322  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", "rules_fast_pattern.txt");
323 
324  FILE *fp = fopen(log_path, "w");
325  if (fp == NULL) {
326  SCLogError("failed to open %s: %s", log_path, strerror(errno));
327  SCFree(log_path);
328  return false;
329  }
330 
332 
333  SCLogInfo("Engine-Analysis for fast_pattern printed to file - %s",
334  log_path);
335  SCFree(log_path);
336 
337  struct timeval tval;
338  gettimeofday(&tval, NULL);
339  struct tm local_tm;
340  struct tm *tms = SCLocalTime(tval.tv_sec, &local_tm);
341  fprintf(fp, "----------------------------------------------"
342  "---------------------\n");
343  fprintf(fp,
344  "Date: %" PRId32 "/%" PRId32 "/%04d -- "
345  "%02d:%02d:%02d\n",
346  tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
347  tms->tm_sec);
348  fprintf(fp, "----------------------------------------------"
349  "---------------------\n");
350 
351  memset(&de_ctx->ea->fp_pattern_stats[0], 0, sizeof(de_ctx->ea->fp_pattern_stats));
352  return true;
353 }
354 
355 /**
356  * \brief Compiles regex for rule analysis
357  * \retval 1 if successful
358  * \retval 0 if on error
359  */
360 static bool PerCentEncodingSetup(EngineAnalysisCtx *ea_ctx)
361 {
362 #define DETECT_PERCENT_ENCODING_REGEX "%[0-9|a-f|A-F]{2}"
363  int en;
364  PCRE2_SIZE eo = 0;
365  int opts = 0; // PCRE2_NEWLINE_ANY??
366 
367  ea_ctx->percent_re = pcre2_compile((PCRE2_SPTR8)DETECT_PERCENT_ENCODING_REGEX,
368  PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
369  if (ea_ctx->percent_re == NULL) {
370  PCRE2_UCHAR errbuffer[256];
371  pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
372  SCLogError("Compile of \"%s\" failed at offset %d: %s", DETECT_PERCENT_ENCODING_REGEX,
373  (int)eo, errbuffer);
374  return false;
375  }
376 
377  return true;
378 }
379 /**
380  * \brief Sets up the rule analyzer according to the config
381  * \retval 1 if rule analyzer successfully enabled
382  * \retval 0 if not enabled
383  */
384 static int SetupRuleAnalyzer(DetectEngineCtx *de_ctx)
385 {
386  SCConfNode *conf = SCConfGetNode("engine-analysis");
387  int enabled = 0;
388  if (conf != NULL) {
389  const char *value = SCConfNodeLookupChildValue(conf, "rules");
390  if (value && SCConfValIsTrue(value)) {
391  enabled = 1;
392  } else if (value && strcasecmp(value, "warnings-only") == 0) {
393  enabled = 1;
394  rule_warnings_only = 1;
395  }
396  if (enabled) {
397  const char *log_dir;
398  log_dir = SCConfigGetLogDirectory();
399  char log_path[PATH_MAX];
400  snprintf(log_path, sizeof(log_path), "%s/%s%s", log_dir,
401  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", "rules_analysis.txt");
402  de_ctx->ea->rule_engine_analysis_fp = fopen(log_path, "w");
403  if (de_ctx->ea->rule_engine_analysis_fp == NULL) {
404  SCLogError("failed to open %s: %s", log_path, strerror(errno));
405  return 0;
406  }
407 
408  SCLogInfo("Engine-Analysis for rules printed to file - %s",
409  log_path);
410 
411  struct timeval tval;
412  gettimeofday(&tval, NULL);
413  struct tm local_tm;
414  struct tm *tms = SCLocalTime(tval.tv_sec, &local_tm);
416  "----------------------------------------------"
417  "---------------------\n");
419  "Date: %" PRId32 "/%" PRId32 "/%04d -- "
420  "%02d:%02d:%02d\n",
421  tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
422  tms->tm_sec);
424  "----------------------------------------------"
425  "---------------------\n");
426 
427  /*compile regex's for rule analysis*/
428  if (!PerCentEncodingSetup(de_ctx->ea)) {
430  "Error compiling regex; can't check for percent encoding in normalized "
431  "http content.\n");
432  }
433  }
434  }
435  else {
436  SCLogInfo("Conf parameter \"engine-analysis.rules\" not found. "
437  "Defaulting to not printing the rules analysis report.");
438  }
439  if (!enabled) {
440  SCLogInfo("Engine-Analysis for rules disabled in conf file.");
441  return 0;
442  }
443  return 1;
444 }
445 
446 static void CleanupFPAnalyzer(DetectEngineCtx *de_ctx)
447 {
448  FILE *fp = de_ctx->ea->fp_engine_analysis_fp;
449  if (fp == NULL) {
450  return;
451  }
452  fprintf(fp, "============\n"
453  "Summary:\n============\n");
454 
455  for (int i = 0; i < DETECT_SM_LIST_MAX; i++) {
457  if (f->cnt == 0)
458  continue;
459 
460  fprintf(fp,
461  "%s, smallest pattern %u byte(s), longest pattern %u byte(s), number of patterns "
462  "%u, avg pattern len %.2f byte(s)\n",
463  DetectSigmatchListEnumToString(i), f->min, f->max, f->cnt,
464  (float)((double)f->tot / (float)f->cnt));
465  }
466 
467  fclose(de_ctx->ea->fp_engine_analysis_fp);
469 }
470 
471 static void CleanupRuleAnalyzer(DetectEngineCtx *de_ctx)
472 {
473  if (de_ctx->ea->rule_engine_analysis_fp != NULL) {
476  }
477  if (de_ctx->ea->percent_re != NULL) {
478  pcre2_code_free(de_ctx->ea->percent_re);
479  }
480 }
481 
482 void SetupEngineAnalysis(DetectEngineCtx *de_ctx, bool *fp_analysis, bool *rule_analysis)
483 {
484  *fp_analysis = false;
485  *rule_analysis = false;
486 
487  EngineAnalysisCtx *ea = SCCalloc(1, sizeof(EngineAnalysisCtx));
488  if (ea == NULL) {
489  FatalError("Unable to allocate per-engine analysis context");
490  }
491 
492  ea->file_prefix = NULL;
493  size_t cfg_prefix_len = strlen(de_ctx->config_prefix);
494  if (cfg_prefix_len > 0) {
495  char prefix[sizeof(de_ctx->config_prefix) + 1];
496  snprintf(prefix, sizeof(prefix), "%s.", de_ctx->config_prefix);
497  ea->file_prefix = SCStrdup(prefix);
498  if (ea->file_prefix == NULL) {
499  FatalError("Unable to allocate per-engine analysis context name buffer");
500  }
501  }
502 
503  de_ctx->ea = ea;
504 
505  *fp_analysis = SetupFPAnalyzer(de_ctx);
506  *rule_analysis = SetupRuleAnalyzer(de_ctx);
507 
508  if (!(*fp_analysis || *rule_analysis)) {
509  if (ea->file_prefix)
510  SCFree(ea->file_prefix);
511  if (ea->analyzer_items)
512  SCFree(ea->analyzer_items);
513  SCFree(ea);
514  de_ctx->ea = NULL;
515  }
516 }
517 
519 {
520  if (de_ctx->ea) {
521  CleanupRuleAnalyzer(de_ctx);
522  CleanupFPAnalyzer(de_ctx);
523  if (de_ctx->ea->file_prefix)
525  if (de_ctx->ea->analyzer_items)
527  SCFree(de_ctx->ea);
528  de_ctx->ea = NULL;
529  }
530 }
531 
532 /**
533  * \brief Checks for % encoding in content.
534  * \param Pointer to content
535  * \retval number of matches if content has % encoding
536  * \retval 0 if it doesn't have % encoding
537  * \retval -1 on error
538  */
539 static int PerCentEncodingMatch(EngineAnalysisCtx *ea_ctx, uint8_t *content, uint16_t content_len)
540 {
541  int ret = 0;
542 
543  pcre2_match_data *match = pcre2_match_data_create_from_pattern(ea_ctx->percent_re, NULL);
544  ret = pcre2_match(ea_ctx->percent_re, (PCRE2_SPTR8)content, content_len, 0, 0, match, NULL);
545  if (ret == -1) {
546  return 0;
547  } else if (ret < -1) {
548  SCLogError("Error parsing content - %s; error code is %d", content, ret);
549  ret = -1;
550  }
551  pcre2_match_data_free(match);
552  return ret;
553 }
554 
555 static void EngineAnalysisRulesPrintFP(const DetectEngineCtx *de_ctx, const Signature *s)
556 {
557  const DetectContentData *fp_cd = NULL;
558  const SigMatch *mpm_sm = s->init_data->mpm_sm;
559  const int mpm_sm_list = s->init_data->mpm_sm_list;
560 
561  if (mpm_sm != NULL) {
562  fp_cd = (DetectContentData *)mpm_sm->ctx;
563  }
564 
565  if (fp_cd == NULL) {
566  return;
567  }
568 
569  uint16_t patlen = fp_cd->content_len;
570  uint8_t *pat = SCMalloc(fp_cd->content_len + 1);
571  if (unlikely(pat == NULL)) {
572  FatalError("Error allocating memory");
573  }
574 
575  EngineAnalysisCtx *ea_ctx = de_ctx->ea;
576 
577  memcpy(pat, fp_cd->content, fp_cd->content_len);
578  pat[fp_cd->content_len] = '\0';
579 
581  SCFree(pat);
582  patlen = fp_cd->fp_chop_len;
583  pat = SCMalloc(fp_cd->fp_chop_len + 1);
584  if (unlikely(pat == NULL)) {
585  exit(EXIT_FAILURE);
586  }
587  memcpy(pat, fp_cd->content + fp_cd->fp_chop_offset, fp_cd->fp_chop_len);
588  pat[fp_cd->fp_chop_len] = '\0';
589  fprintf(ea_ctx->rule_engine_analysis_fp, " Fast Pattern \"");
590  PrintRawUriFp(ea_ctx->rule_engine_analysis_fp, pat, patlen);
591  } else {
592  fprintf(ea_ctx->rule_engine_analysis_fp, " Fast Pattern \"");
593  PrintRawUriFp(ea_ctx->rule_engine_analysis_fp, pat, patlen);
594  }
595  SCFree(pat);
596 
597  fprintf(ea_ctx->rule_engine_analysis_fp, "\" on \"");
598 
599  const int list_type = mpm_sm_list;
600  if (list_type == DETECT_SM_LIST_PMATCH) {
601  int payload = 0;
602  int stream = 0;
604  payload = 1;
606  stream = 1;
607  fprintf(ea_ctx->rule_engine_analysis_fp, "%s",
608  payload ? (stream ? "payload and reassembled stream" : "payload")
609  : "reassembled stream");
610  }
611  else {
612  const char *desc = DetectEngineBufferTypeGetDescriptionById(de_ctx, list_type);
613  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, list_type);
614  if (desc && name) {
615  fprintf(ea_ctx->rule_engine_analysis_fp, "%s (%s)", desc, name);
616  } else if (desc || name) {
617  fprintf(ea_ctx->rule_engine_analysis_fp, "%s", desc ? desc : name);
618  }
619 
620  }
621 
622  fprintf(ea_ctx->rule_engine_analysis_fp, "\" ");
623  const DetectBufferType *bt = DetectEngineBufferTypeGetById(de_ctx, list_type);
624  if (bt && bt->transforms.cnt) {
625  fprintf(ea_ctx->rule_engine_analysis_fp, "(with %d transform(s)) ", bt->transforms.cnt);
626  }
627  fprintf(ea_ctx->rule_engine_analysis_fp, "buffer.\n");
628 }
629 
631  const DetectEngineCtx *de_ctx, const char *line, const char *file, int lineno)
632 {
635  if (tmp_fp) {
636  fprintf(tmp_fp, "== Sid: UNKNOWN ==\n");
637  fprintf(tmp_fp, "%s\n", line);
638  fprintf(tmp_fp, " FAILURE: invalid rule.\n");
639  fprintf(tmp_fp, " File: %s.\n", file);
640  fprintf(tmp_fp, " Line: %d.\n", lineno);
641  fprintf(tmp_fp, "\n");
642  }
643 }
644 
645 typedef struct RuleAnalyzer {
646  SCJsonBuilder *js; /* document root */
647 
651 
652 static void ATTR_FMT_PRINTF(2, 3) AnalyzerNote(RuleAnalyzer *ctx, char *fmt, ...)
653 {
654  va_list ap;
655  char str[1024];
656 
657  va_start(ap, fmt);
658  vsnprintf(str, sizeof(str), fmt, ap);
659  va_end(ap);
660 
661  if (!ctx->js_notes)
662  ctx->js_notes = SCJbNewArray();
663  if (ctx->js_notes)
664  SCJbAppendString(ctx->js_notes, str);
665 }
666 
667 static void ATTR_FMT_PRINTF(2, 3) AnalyzerWarning(RuleAnalyzer *ctx, char *fmt, ...)
668 {
669  va_list ap;
670  char str[1024];
671 
672  va_start(ap, fmt);
673  vsnprintf(str, sizeof(str), fmt, ap);
674  va_end(ap);
675 
676  if (!ctx->js_warnings)
677  ctx->js_warnings = SCJbNewArray();
678  if (ctx->js_warnings)
679  SCJbAppendString(ctx->js_warnings, str);
680 }
681 
682 #define CHECK(pat) if (strlen((pat)) <= len && memcmp((pat), buf, MIN(len, strlen((pat)))) == 0) return true;
683 
684 static bool LooksLikeHTTPMethod(const uint8_t *buf, uint16_t len)
685 {
686  CHECK("GET /");
687  CHECK("POST /");
688  CHECK("HEAD /");
689  CHECK("PUT /");
690  return false;
691 }
692 
693 static bool LooksLikeHTTPUA(const uint8_t *buf, uint16_t len)
694 {
695  CHECK("User-Agent: ");
696  CHECK("\nUser-Agent: ");
697  return false;
698 }
699 
700 static void DumpContent(SCJsonBuilder *js, const DetectContentData *cd)
701 {
702  char pattern_str[1024] = "";
703  DetectContentPatternPrettyPrint(cd->content, cd->content_len, pattern_str, sizeof(pattern_str));
704 
705  SCJbSetString(js, "pattern", pattern_str);
706  SCJbSetUint(js, "length", cd->content_len);
707  SCJbSetBool(js, "nocase", cd->flags & DETECT_CONTENT_NOCASE);
708  SCJbSetBool(js, "negated", cd->flags & DETECT_CONTENT_NEGATED);
709  SCJbSetBool(js, "starts_with", cd->flags & DETECT_CONTENT_STARTS_WITH);
710  SCJbSetBool(js, "ends_with", cd->flags & DETECT_CONTENT_ENDS_WITH);
711  SCJbSetBool(js, "is_mpm", cd->flags & DETECT_CONTENT_MPM);
712  SCJbSetBool(js, "no_double_inspect", cd->flags & DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED);
713  if (cd->flags & DETECT_CONTENT_OFFSET) {
714  SCJbSetUint(js, "offset", cd->offset);
715  }
716  if (cd->flags & DETECT_CONTENT_DEPTH) {
717  SCJbSetUint(js, "depth", cd->depth);
718  }
719  if (cd->flags & DETECT_CONTENT_DISTANCE) {
720  SCJbSetInt(js, "distance", cd->distance);
721  }
722  if (cd->flags & DETECT_CONTENT_WITHIN) {
723  SCJbSetInt(js, "within", cd->within);
724  }
725  SCJbSetBool(js, "fast_pattern", cd->flags & DETECT_CONTENT_FAST_PATTERN);
726  SCJbSetBool(js, "relative_next", cd->flags & DETECT_CONTENT_RELATIVE_NEXT);
727 }
728 
729 static void DumpPcre(SCJsonBuilder *js, const DetectPcreData *cd)
730 {
731  SCJbSetBool(js, "relative", cd->flags & DETECT_PCRE_RELATIVE);
732  SCJbSetBool(js, "relative_next", cd->flags & DETECT_PCRE_RELATIVE_NEXT);
733  SCJbSetBool(js, "nocase", cd->flags & DETECT_PCRE_CASELESS);
734  SCJbSetBool(js, "negated", cd->flags & DETECT_PCRE_NEGATE);
735 }
736 
737 static void DumpMatches(RuleAnalyzer *ctx, SCJsonBuilder *js, const SigMatchData *smd)
738 {
739  if (smd == NULL)
740  return;
741 
742  SCJbOpenArray(js, "matches");
743  do {
744  SCJbStartObject(js);
745  const char *mname = sigmatch_table[smd->type].name;
746  SCJbSetString(js, "name", mname);
747 
748  switch (smd->type) {
749  case DETECT_CONTENT: {
750  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
751 
752  SCJbOpenObject(js, "content");
753  DumpContent(js, cd);
755  AnalyzerNote(ctx, (char *)"'fast_pattern:only' option is silently ignored and "
756  "is interpreted as regular 'fast_pattern'");
757  }
758  if (LooksLikeHTTPMethod(cd->content, cd->content_len)) {
759  AnalyzerNote(ctx,
760  (char *)"pattern looks like it inspects HTTP, use http.request_line or "
761  "http.method and http.uri instead for improved performance");
762  }
763  if (LooksLikeHTTPUA(cd->content, cd->content_len)) {
764  AnalyzerNote(ctx,
765  (char *)"pattern looks like it inspects HTTP, use http.user_agent "
766  "or http.header for improved performance");
767  }
769  AnalyzerNote(ctx, (char *)"'within' option for pattern w/o previous content "
770  "was converted to 'depth'");
771  }
773  AnalyzerNote(ctx, (char *)"'distance' option for pattern w/o previous content "
774  "was converted to 'offset'");
775  }
776  SCJbClose(js);
777  break;
778  }
779  case DETECT_PCRE: {
780  const DetectPcreData *cd = (const DetectPcreData *)smd->ctx;
781 
782  SCJbOpenObject(js, "pcre");
783  DumpPcre(js, cd);
784  SCJbClose(js);
785  if (cd->flags & DETECT_PCRE_RAWBYTES) {
786  AnalyzerNote(ctx,
787  (char *)"'/B' (rawbytes) option is a no-op and is silently ignored");
788  }
790  AnalyzerNote(ctx, (char *)"pcre with \\X (Unicode extended grapheme cluster) "
791  "may be slow");
792  }
793  break;
794  }
795  case DETECT_BYTEJUMP: {
796  const DetectBytejumpData *cd = (const DetectBytejumpData *)smd->ctx;
797 
798  SCJbOpenObject(js, "byte_jump");
799  SCJbSetUint(js, "nbytes", cd->nbytes);
800  SCJbSetInt(js, "offset", cd->offset);
801  SCJbSetUint(js, "multiplier", cd->multiplier);
802  SCJbSetInt(js, "post_offset", cd->post_offset);
803  switch (cd->base) {
805  SCJbSetString(js, "base", "unset");
806  break;
808  SCJbSetString(js, "base", "oct");
809  break;
811  SCJbSetString(js, "base", "dec");
812  break;
814  SCJbSetString(js, "base", "hex");
815  break;
816  }
817  SCJbOpenArray(js, "flags");
818  if (cd->flags & DETECT_BYTEJUMP_BEGIN)
819  SCJbAppendString(js, "from_beginning");
820  if (cd->flags & DETECT_BYTEJUMP_LITTLE)
821  SCJbAppendString(js, "little_endian");
822  if (cd->flags & DETECT_BYTEJUMP_BIG)
823  SCJbAppendString(js, "big_endian");
824  if (cd->flags & DETECT_BYTEJUMP_STRING)
825  SCJbAppendString(js, "string");
827  SCJbAppendString(js, "relative");
828  if (cd->flags & DETECT_BYTEJUMP_ALIGN)
829  SCJbAppendString(js, "align");
830  if (cd->flags & DETECT_BYTEJUMP_DCE)
831  SCJbAppendString(js, "dce");
833  SCJbAppendString(js, "offset_be");
834  if (cd->flags & DETECT_BYTEJUMP_END)
835  SCJbAppendString(js, "from_end");
836  SCJbClose(js);
837  SCJbClose(js);
838  break;
839  }
840  case DETECT_BYTETEST: {
841  const DetectBytetestData *cd = (const DetectBytetestData *)smd->ctx;
842 
843  SCJbOpenObject(js, "byte_test");
844  SCJbSetUint(js, "nbytes", cd->nbytes);
845  SCJbSetInt(js, "offset", cd->offset);
846  switch (cd->base) {
848  SCJbSetString(js, "base", "unset");
849  break;
851  SCJbSetString(js, "base", "oct");
852  break;
854  SCJbSetString(js, "base", "dec");
855  break;
857  SCJbSetString(js, "base", "hex");
858  break;
859  }
860  SCJbOpenArray(js, "flags");
861  if (cd->flags & DETECT_BYTETEST_LITTLE)
862  SCJbAppendString(js, "little_endian");
863  if (cd->flags & DETECT_BYTETEST_BIG)
864  SCJbAppendString(js, "big_endian");
865  if (cd->flags & DETECT_BYTETEST_STRING)
866  SCJbAppendString(js, "string");
868  SCJbAppendString(js, "relative");
869  if (cd->flags & DETECT_BYTETEST_DCE)
870  SCJbAppendString(js, "dce");
871  SCJbClose(js);
872  SCJbClose(js);
873  break;
874  }
875  case DETECT_ABSENT: {
876  const DetectAbsentData *dad = (const DetectAbsentData *)smd->ctx;
877  SCJbOpenObject(js, "absent");
878  SCJbSetBool(js, "or_else", dad->or_else);
879  SCJbClose(js);
880  break;
881  }
882 
883  case DETECT_IPOPTS: {
884  const DetectIpOptsData *cd = (const DetectIpOptsData *)smd->ctx;
885 
886  SCJbOpenObject(js, "ipopts");
887  const char *flag = IpOptsFlagToString(cd->ipopt);
888  SCJbSetString(js, "option", flag);
889  SCJbClose(js);
890  break;
891  }
892  case DETECT_FLOWBITS: {
893  const DetectFlowbitsData *cd = (const DetectFlowbitsData *)smd->ctx;
894 
895  SCJbOpenObject(js, "flowbits");
896  switch (cd->cmd) {
898  SCJbSetString(js, "cmd", "isset");
899  break;
901  SCJbSetString(js, "cmd", "isnotset");
902  break;
904  SCJbSetString(js, "cmd", "set");
905  break;
907  SCJbSetString(js, "cmd", "unset");
908  break;
909  }
910  bool is_or = false;
911  SCJbOpenArray(js, "names");
912  if (cd->or_list_size == 0) {
913  SCJbAppendString(js, VarNameStoreSetupLookup(cd->idx, VAR_TYPE_FLOW_BIT));
914  } else if (cd->or_list_size > 0) {
915  is_or = true;
916  for (uint8_t i = 0; i < cd->or_list_size; i++) {
917  const char *varname =
919  SCJbAppendString(js, varname);
920  }
921  }
922  SCJbClose(js); // array
923  if (is_or) {
924  SCJbSetString(js, "operator", "or");
925  }
926  SCJbClose(js); // object
927  break;
928  }
929  case DETECT_XBITS: {
930  const DetectXbitsData *xd = (const DetectXbitsData *)smd->ctx;
931 
932  SCJbOpenObject(js, "xbits");
933  switch (xd->cmd) {
935  SCJbSetString(js, "cmd", "isset");
936  break;
938  SCJbSetString(js, "cmd", "isnotset");
939  break;
941  SCJbSetString(js, "cmd", "set");
942  break;
944  SCJbSetString(js, "cmd", "unset");
945  break;
947  SCJbSetString(js, "cmd", "toggle");
948  break;
949  }
950  SCJbSetString(js, "name", VarNameStoreSetupLookup(xd->idx, xd->type));
951  switch (xd->tracker) {
953  SCJbSetString(js, "track", "ip_src");
954  break;
956  SCJbSetString(js, "track", "ip_dst");
957  break;
959  SCJbSetString(js, "track", "ip_pair");
960  break;
962  SCJbSetString(js, "track", "tx");
963  break;
964  }
965  // always log expire value
966  SCJbSetUint(js, "expire", xd->expire);
967  SCJbClose(js); // object
968  break;
969  }
970  case DETECT_FLOWINT: {
971  const DetectFlowintData *cd = (const DetectFlowintData *)smd->ctx;
972 
973  SCJbOpenObject(js, "flowint");
974  switch (cd->modifier) {
976  SCJbSetString(js, "cmd", "set");
977  break;
979  SCJbSetString(js, "cmd", "add");
980  break;
982  SCJbSetString(js, "cmd", "sub");
983  break;
984  case FLOWINT_MODIFIER_LT:
985  SCJbSetString(js, "cmd", "lt");
986  break;
987  case FLOWINT_MODIFIER_LE:
988  SCJbSetString(js, "cmd", "lte");
989  break;
990  case FLOWINT_MODIFIER_EQ:
991  SCJbSetString(js, "cmd", "eq");
992  break;
993  case FLOWINT_MODIFIER_NE:
994  SCJbSetString(js, "cmd", "ne");
995  break;
996  case FLOWINT_MODIFIER_GE:
997  SCJbSetString(js, "cmd", "gte");
998  break;
999  case FLOWINT_MODIFIER_GT:
1000  SCJbSetString(js, "cmd", "gt");
1001  break;
1003  SCJbSetString(js, "cmd", "isset");
1004  break;
1006  SCJbSetString(js, "cmd", "isnotset");
1007  break;
1008  }
1009  const char *varname = VarNameStoreSetupLookup(cd->idx, VAR_TYPE_FLOW_INT);
1010  if (varname != NULL) {
1011  SCJbSetString(js, "var", varname);
1012  }
1013  if (cd->targettype == FLOWINT_TARGET_VAL) {
1014  SCJbSetUint(js, "value", cd->target.value);
1015  } else if (cd->targettype == FLOWINT_TARGET_VAR) {
1016  if (cd->target.tvar.name != NULL) {
1017  SCJbSetString(js, "target", cd->target.tvar.name);
1018  }
1019  }
1020  SCJbClose(js);
1021  break;
1022  }
1023  case DETECT_ACK: {
1024  const DetectU32Data *cd = (const DetectU32Data *)smd->ctx;
1025  SCJbOpenObject(js, "ack");
1026  SCDetectU32ToJson(js, cd);
1027  SCJbClose(js);
1028  break;
1029  }
1030  case DETECT_SEQ: {
1031  const DetectU32Data *cd = (const DetectU32Data *)smd->ctx;
1032  SCJbOpenObject(js, "seq");
1033  SCDetectU32ToJson(js, cd);
1034  SCJbClose(js);
1035  break;
1036  }
1037  case DETECT_TCPMSS: {
1038  const DetectU16Data *cd = (const DetectU16Data *)smd->ctx;
1039  SCJbOpenObject(js, "tcp_mss");
1040  SCDetectU16ToJson(js, cd);
1041  SCJbClose(js);
1042  break;
1043  }
1044  case DETECT_DSIZE: {
1045  const DetectU16Data *cd = (const DetectU16Data *)smd->ctx;
1046  SCJbOpenObject(js, "dsize");
1047  SCDetectU16ToJson(js, cd);
1048  SCJbClose(js);
1049  break;
1050  }
1051  case DETECT_ICODE: {
1052  const DetectU8Data *cd = (const DetectU8Data *)smd->ctx;
1053  SCJbOpenObject(js, "code");
1054  SCDetectU8ToJson(js, cd);
1055  SCJbClose(js);
1056  break;
1057  }
1058  case DETECT_TTL: {
1059  const DetectU8Data *cd = (const DetectU8Data *)smd->ctx;
1060  SCJbOpenObject(js, "ttl");
1061  SCDetectU8ToJson(js, cd);
1062  SCJbClose(js);
1063  break;
1064  }
1065  case DETECT_ICMP_ID: {
1066  const DetectU16Data *cd = (const DetectU16Data *)smd->ctx;
1067  SCJbOpenObject(js, "id");
1068  SCDetectU16ToJson(js, cd);
1069  SCJbClose(js);
1070  break;
1071  }
1072  case DETECT_WINDOW: {
1073  const DetectU16Data *cd = (const DetectU16Data *)smd->ctx;
1074  SCJbOpenObject(js, "window");
1075  SCDetectU16ToJson(js, cd);
1076  SCJbClose(js);
1077  break;
1078  }
1079  case DETECT_FLOW_AGE: {
1080  const DetectU32Data *cd = (const DetectU32Data *)smd->ctx;
1081  SCJbOpenObject(js, "flow_age");
1082  SCDetectU32ToJson(js, cd);
1083  SCJbClose(js);
1084  break;
1085  }
1086  case DETECT_FLOW_ELEPHANT: {
1087  const uint8_t *dfd = (const uint8_t *)smd->ctx;
1088  SCJbOpenObject(js, "flow_elephant");
1089  switch (*dfd) {
1090  case DETECT_FLOW_TOSERVER:
1091  SCJbSetString(js, "dir", "toserver");
1092  break;
1093  case DETECT_FLOW_TOCLIENT:
1094  SCJbSetString(js, "dir", "toclient");
1095  break;
1096  case DETECT_FLOW_TOEITHER:
1097  SCJbSetString(js, "dir", "either");
1098  break;
1099  case DETECT_FLOW_TOBOTH:
1100  SCJbSetString(js, "dir", "both");
1101  break;
1102  }
1103  SCJbClose(js);
1104  break;
1105  }
1107  const DetectAppLayerProtocolData *ad = (const DetectAppLayerProtocolData *)smd->ctx;
1108  SCJbOpenObject(js, "app_layer_protocol");
1109  AppProto vals[256];
1110  uint16_t n = DetectAppLayerProtocolGetValues(ad, vals, ARRAY_SIZE(vals));
1111  SCJbOpenArray(js, "protocols");
1112  for (uint16_t i = 0; i < n; i++) {
1113  SCJbAppendString(js, AppProtoToString(vals[i]));
1114  }
1115  SCJbClose(js);
1116  SCJbSetString(js, "mode", DetectAppLayerProtocolModeName(ad->mode));
1117  SCJbSetBool(js, "negated", ad->negated);
1118  SCJbClose(js);
1119  break;
1120  }
1121  case DETECT_TCP_SESSION: {
1122  const DetectTcpSessionData *tsd = (const DetectTcpSessionData *)smd->ctx;
1123  SCJbOpenObject(js, "tcp_session");
1124  SCJbOpenArray(js, "phases");
1126  SCJbAppendString(js, "setup");
1128  SCJbAppendString(js, "established");
1130  SCJbAppendString(js, "closing");
1131  SCJbClose(js); // phases
1132  SCJbClose(js); // tcp_session
1133  break;
1134  }
1135  }
1136  SCJbClose(js);
1137 
1138  if (smd->is_last)
1139  break;
1140  smd++;
1141  } while (1);
1142  SCJbClose(js);
1143 }
1144 
1147 {
1148  SCEnter();
1149 
1150  RuleAnalyzer ctx = { NULL, NULL, NULL };
1151 
1152  ctx.js = SCJbNewObject();
1153  if (ctx.js == NULL)
1154  SCReturn;
1155 
1156  if (s->init_data->firewall_rule) {
1157  JB_SET_STRING(ctx.js, "class", "firewall");
1158  } else {
1159  JB_SET_STRING(ctx.js, "class", "threat detection");
1160  }
1161 
1162  SCJbSetString(ctx.js, "raw", s->sig_str);
1163  SCJbSetUint(ctx.js, "id", s->id);
1164  SCJbSetUint(ctx.js, "gid", s->gid);
1165  SCJbSetUint(ctx.js, "rev", s->rev);
1166  SCJbSetString(ctx.js, "msg", s->msg);
1167 
1168  const char *alproto = AppProtoToString(s->alproto);
1169  SCJbSetString(ctx.js, "app_proto", alproto);
1170 
1171  SCJbOpenArray(ctx.js, "requirements");
1172  if (s->mask & SIG_MASK_REQUIRE_PAYLOAD) {
1173  SCJbAppendString(ctx.js, "payload");
1174  }
1175  if (s->mask & SIG_MASK_REQUIRE_NO_PAYLOAD) {
1176  SCJbAppendString(ctx.js, "no_payload");
1177  }
1178  if (s->mask & SIG_MASK_REQUIRE_FLOW) {
1179  SCJbAppendString(ctx.js, "flow");
1180  }
1182  SCJbAppendString(ctx.js, "tcp_flags_init_deinit");
1183  }
1185  SCJbAppendString(ctx.js, "tcp_flags_unusual");
1186  }
1188  SCJbAppendString(ctx.js, "engine_event");
1189  }
1190  if (s->mask & SIG_MASK_REQUIRE_REAL_PKT) {
1191  SCJbAppendString(ctx.js, "real_pkt");
1192  }
1193  SCJbClose(ctx.js);
1194 
1195  SCJbOpenObject(ctx.js, "match_policy");
1196  SCJbOpenArray(ctx.js, "actions");
1197  if (s->action & ACTION_ALERT) {
1198  SCJbAppendString(ctx.js, "alert");
1199  }
1200  if (s->action & ACTION_DROP) {
1201  SCJbAppendString(ctx.js, "drop");
1202  }
1203  if (s->action & ACTION_REJECT) {
1204  SCJbAppendString(ctx.js, "reject");
1205  }
1206  if (s->action & ACTION_REJECT_DST) {
1207  SCJbAppendString(ctx.js, "reject_dst");
1208  }
1209  if (s->action & ACTION_REJECT_BOTH) {
1210  SCJbAppendString(ctx.js, "reject_both");
1211  }
1212  if (s->action & ACTION_CONFIG) {
1213  SCJbAppendString(ctx.js, "config");
1214  }
1215  if (s->action & ACTION_PASS) {
1216  SCJbAppendString(ctx.js, "pass");
1217  }
1218  if (s->action & ACTION_ACCEPT) {
1219  SCJbAppendString(ctx.js, "accept");
1220  }
1221  SCJbClose(ctx.js);
1222 
1223  if (s->action_scope == ACTION_SCOPE_AUTO) {
1225  switch (flow_action) {
1227  SCJbSetString(ctx.js, "scope", "packet");
1228  break;
1230  SCJbSetString(ctx.js, "scope", "flow");
1231  break;
1233  SCJbSetString(ctx.js, "scope", "flow_if_stateful");
1234  break;
1235  }
1236  } else {
1237  enum ActionScope as = s->action_scope;
1238  switch (as) {
1239  case ACTION_SCOPE_PACKET:
1240  SCJbSetString(ctx.js, "scope", "packet");
1241  break;
1242  case ACTION_SCOPE_FLOW:
1243  SCJbSetString(ctx.js, "scope", "flow");
1244  break;
1245  case ACTION_SCOPE_HOOK:
1246  SCJbSetString(ctx.js, "scope", "hook");
1247  break;
1248  case ACTION_SCOPE_TX:
1249  SCJbSetString(ctx.js, "scope", "tx");
1250  break;
1251  case ACTION_SCOPE_AUTO: /* should be unreachable */
1252  break;
1253  }
1254  }
1255  SCJbClose(ctx.js);
1256 
1257  switch (s->type) {
1258  case SIG_TYPE_NOT_SET:
1259  SCJbSetString(ctx.js, "type", "unset");
1260  break;
1261  case SIG_TYPE_IPONLY:
1262  SCJbSetString(ctx.js, "type", "ip_only");
1263  break;
1264  case SIG_TYPE_LIKE_IPONLY:
1265  SCJbSetString(ctx.js, "type", "like_ip_only");
1266  break;
1267  case SIG_TYPE_PDONLY:
1268  SCJbSetString(ctx.js, "type", "pd_only");
1269  break;
1270  case SIG_TYPE_DEONLY:
1271  SCJbSetString(ctx.js, "type", "de_only");
1272  break;
1273  case SIG_TYPE_PKT:
1274  SCJbSetString(ctx.js, "type", "pkt");
1275  break;
1276  case SIG_TYPE_PKT_STREAM:
1277  SCJbSetString(ctx.js, "type", "pkt_stream");
1278  break;
1279  case SIG_TYPE_STREAM:
1280  SCJbSetString(ctx.js, "type", "stream");
1281  break;
1282  case SIG_TYPE_APPLAYER:
1283  SCJbSetString(ctx.js, "type", "app_layer");
1284  break;
1285  case SIG_TYPE_APP_TX:
1286  SCJbSetString(ctx.js, "type", "app_tx");
1287  break;
1288  case SIG_TYPE_MAX:
1289  SCJbSetString(ctx.js, "type", "error");
1290  break;
1291  }
1292 
1293  // dependencies object and its subfields only logged if we have values
1295  SCJbOpenObject(ctx.js, "dependencies");
1296  SCJbOpenObject(ctx.js, "flowbits");
1297  SCJbOpenObject(ctx.js, "upstream");
1299  SCJbOpenObject(ctx.js, "state_modifying_rules");
1300  SCJbOpenArray(ctx.js, "sids");
1301  for (uint32_t i = 0; i < s->init_data->rule_state_dependant_sids_idx; i++) {
1302  SCJbAppendUint(ctx.js, s->init_data->rule_state_dependant_sids_array[i]);
1303  }
1304  SCJbClose(ctx.js); // sids
1305  SCJbOpenArray(ctx.js, "names");
1306  for (uint32_t i = 0; i < s->init_data->rule_state_flowbits_ids_size - 1; i++) {
1307  if (s->init_data->rule_state_flowbits_ids_array[i] != 0) {
1308  SCJbAppendString(ctx.js,
1311  }
1312  }
1313  SCJbClose(ctx.js); // names
1314  SCJbClose(ctx.js); // state_modifying_rules
1315  }
1316  SCJbClose(ctx.js); // upstream
1317  SCJbClose(ctx.js); // flowbits
1318  SCJbClose(ctx.js); // dependencies
1319  }
1320 
1321  SCJbOpenArray(ctx.js, "flags");
1322  if (s->flags & SIG_FLAG_SRC_ANY) {
1323  SCJbAppendString(ctx.js, "src_any");
1324  }
1325  if (s->flags & SIG_FLAG_DST_ANY) {
1326  SCJbAppendString(ctx.js, "dst_any");
1327  }
1328  if (s->flags & SIG_FLAG_SP_ANY) {
1329  SCJbAppendString(ctx.js, "sp_any");
1330  }
1331  if (s->flags & SIG_FLAG_DP_ANY) {
1332  SCJbAppendString(ctx.js, "dp_any");
1333  }
1334  if ((s->action & ACTION_ALERT) == 0) {
1335  SCJbAppendString(ctx.js, "noalert");
1336  }
1337  if (s->flags & SIG_FLAG_DSIZE) {
1338  SCJbAppendString(ctx.js, "dsize");
1339  }
1340  if (s->flags & SIG_FLAG_APPLAYER) {
1341  SCJbAppendString(ctx.js, "applayer");
1342  }
1343  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
1344  SCJbAppendString(ctx.js, "need_packet");
1345  }
1346  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
1347  SCJbAppendString(ctx.js, "need_stream");
1348  }
1349  if (s->flags & SIG_FLAG_MPM_NEG) {
1350  SCJbAppendString(ctx.js, "negated_mpm");
1351  }
1352  if (s->flags & SIG_FLAG_FLUSH) {
1353  SCJbAppendString(ctx.js, "flush");
1354  }
1355  if (s->flags & SIG_FLAG_REQUIRE_FLOWVAR) {
1356  SCJbAppendString(ctx.js, "need_flowvar");
1357  }
1358  if (s->flags & SIG_FLAG_FILESTORE) {
1359  SCJbAppendString(ctx.js, "filestore");
1360  }
1361  if (s->flags & SIG_FLAG_TOSERVER) {
1362  SCJbAppendString(ctx.js, "toserver");
1363  }
1364  if (s->flags & SIG_FLAG_TOCLIENT) {
1365  SCJbAppendString(ctx.js, "toclient");
1366  }
1367  if (s->flags & SIG_FLAG_TLSSTORE) {
1368  SCJbAppendString(ctx.js, "tlsstore");
1369  }
1370  if (s->flags & SIG_FLAG_BYPASS) {
1371  SCJbAppendString(ctx.js, "bypass");
1372  }
1373  if (s->flags & SIG_FLAG_PREFILTER) {
1374  SCJbAppendString(ctx.js, "prefilter");
1375  }
1376  if (s->flags & SIG_FLAG_SRC_IS_TARGET) {
1377  SCJbAppendString(ctx.js, "src_is_target");
1378  }
1379  if (s->flags & SIG_FLAG_DEST_IS_TARGET) {
1380  SCJbAppendString(ctx.js, "dst_is_target");
1381  }
1382  SCJbClose(ctx.js);
1383 
1384  const DetectEnginePktInspectionEngine *pkt_mpm = NULL;
1385  const DetectEngineAppInspectionEngine *app_mpm = NULL;
1386 
1387  SCJbOpenArray(ctx.js, "pkt_engines");
1389  for ( ; pkt != NULL; pkt = pkt->next) {
1391  if (name == NULL) {
1392  switch (pkt->sm_list) {
1393  case DETECT_SM_LIST_PMATCH:
1394  name = "payload";
1395  break;
1396  case DETECT_SM_LIST_MATCH:
1397  name = "packet";
1398  break;
1399  default:
1400  name = "unknown";
1401  break;
1402  }
1403  }
1404  SCJbStartObject(ctx.js);
1405  SCJbSetString(ctx.js, "name", name);
1406  SCJbSetBool(ctx.js, "is_mpm", pkt->mpm);
1407  if (pkt->v1.transforms != NULL) {
1408  SCJbOpenArray(ctx.js, "transforms");
1409  for (int t = 0; t < pkt->v1.transforms->cnt; t++) {
1410  SCJbStartObject(ctx.js);
1411  SCJbSetString(ctx.js, "name",
1413  SCJbClose(ctx.js);
1414  }
1415  SCJbClose(ctx.js);
1416  }
1417  DumpMatches(&ctx, ctx.js, pkt->smd);
1418  SCJbClose(ctx.js);
1419  if (pkt->mpm) {
1420  pkt_mpm = pkt;
1421  }
1422  }
1423  SCJbClose(ctx.js);
1424  SCJbOpenArray(ctx.js, "frame_engines");
1426  for (; frame != NULL; frame = frame->next) {
1427  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, frame->sm_list);
1428  SCJbStartObject(ctx.js);
1429  SCJbSetString(ctx.js, "name", name);
1430  SCJbSetBool(ctx.js, "is_mpm", frame->mpm);
1431  if (frame->v1.transforms != NULL) {
1432  SCJbOpenArray(ctx.js, "transforms");
1433  for (int t = 0; t < frame->v1.transforms->cnt; t++) {
1434  SCJbStartObject(ctx.js);
1435  SCJbSetString(ctx.js, "name",
1437  SCJbClose(ctx.js);
1438  }
1439  SCJbClose(ctx.js);
1440  }
1441  DumpMatches(&ctx, ctx.js, frame->smd);
1442  SCJbClose(ctx.js);
1443  }
1444  SCJbClose(ctx.js);
1445 
1447  bool has_stream = false;
1448  bool has_client_body_mpm = false;
1449  bool has_file_data_mpm = false;
1450 
1451  SCJbOpenArray(ctx.js, "engines");
1453  for ( ; app != NULL; app = app->next) {
1455  if (name == NULL) {
1456  switch (app->sm_list) {
1457  case DETECT_SM_LIST_PMATCH:
1458  name = "stream";
1459  break;
1460  default:
1461  name = "unknown";
1462  break;
1463  }
1464  }
1465 
1466  if (app->sm_list == DETECT_SM_LIST_PMATCH && !app->mpm) {
1467  has_stream = true;
1468  } else if (app->mpm && strcmp(name, "http_client_body") == 0) {
1469  has_client_body_mpm = true;
1470  } else if (app->mpm && strcmp(name, "file_data") == 0) {
1471  has_file_data_mpm = true;
1472  }
1473 
1474  SCJbStartObject(ctx.js);
1475  SCJbSetString(ctx.js, "name", name);
1476  const char *direction = app->dir == 0 ? "toserver" : "toclient";
1477  SCJbSetString(ctx.js, "direction", direction);
1478  SCJbSetBool(ctx.js, "is_mpm", app->mpm);
1479  SCJbSetString(ctx.js, "app_proto", AppProtoToString(app->alproto));
1480  SCJbSetUint(ctx.js, "progress", app->progress);
1481  if (app->sub_state)
1482  SCJbSetString(ctx.js, "sub_state",
1484 
1485  if (app->v2.transforms != NULL) {
1486  SCJbOpenArray(ctx.js, "transforms");
1487  for (int t = 0; t < app->v2.transforms->cnt; t++) {
1488  SCJbStartObject(ctx.js);
1489  SCJbSetString(ctx.js, "name",
1491  SCJbClose(ctx.js);
1492  }
1493  SCJbClose(ctx.js);
1494  }
1495  DumpMatches(&ctx, ctx.js, app->smd);
1496  SCJbClose(ctx.js);
1497  if (app->mpm) {
1498  app_mpm = app;
1499  }
1500  }
1501  SCJbClose(ctx.js);
1502 
1503  if (has_stream && has_client_body_mpm)
1504  AnalyzerNote(&ctx, (char *)"mpm in http_client_body combined with stream match leads to stream buffering");
1505  if (has_stream && has_file_data_mpm)
1506  AnalyzerNote(&ctx, (char *)"mpm in file_data combined with stream match leads to stream buffering");
1507  }
1508 
1509  SCJbOpenObject(ctx.js, "lists");
1510  for (int i = 0; i < DETECT_SM_LIST_MAX; i++) {
1511  if (s->sm_arrays[i] != NULL) {
1512  SCJbOpenObject(ctx.js, DetectListToHumanString(i));
1513  DumpMatches(&ctx, ctx.js, s->sm_arrays[i]);
1514  SCJbClose(ctx.js);
1515  }
1516  }
1517  SCJbClose(ctx.js);
1518 
1519  if (pkt_mpm || app_mpm) {
1520  SCJbOpenObject(ctx.js, "mpm");
1521 
1522  int mpm_list = pkt_mpm ? DETECT_SM_LIST_PMATCH : app_mpm->sm_list;
1523  const char *name;
1524  if (mpm_list < DETECT_SM_LIST_DYNAMIC_START)
1525  name = DetectListToHumanString(mpm_list);
1526  else
1528  SCJbSetString(ctx.js, "buffer", name);
1529 
1530  SigMatchData *smd = pkt_mpm ? pkt_mpm->smd : app_mpm->smd;
1531  if (smd == NULL) {
1533  smd = s->sm_arrays[mpm_list];
1534  }
1535  do {
1536  switch (smd->type) {
1537  case DETECT_CONTENT: {
1538  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
1539  if (cd->flags & DETECT_CONTENT_MPM) {
1540  DumpContent(ctx.js, cd);
1541  }
1542  break;
1543  }
1544  }
1545 
1546  if (smd->is_last)
1547  break;
1548  smd++;
1549  } while (1);
1550  SCJbClose(ctx.js);
1551  } else if (s->init_data->prefilter_sm) {
1552  SCJbOpenObject(ctx.js, "prefilter");
1553  int prefilter_list = SigMatchListSMBelongsTo(s, s->init_data->prefilter_sm);
1554  const char *name;
1555  if (prefilter_list < DETECT_SM_LIST_DYNAMIC_START)
1556  name = DetectListToHumanString(prefilter_list);
1557  else
1558  name = DetectEngineBufferTypeGetNameById(de_ctx, prefilter_list);
1559  SCJbSetString(ctx.js, "buffer", name);
1560  const char *mname = sigmatch_table[s->init_data->prefilter_sm->type].name;
1561  SCJbSetString(ctx.js, "name", mname);
1562  SCJbClose(ctx.js);
1563  }
1564 
1565  if (ctx.js_warnings) {
1566  SCJbClose(ctx.js_warnings);
1567  SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
1568  SCJbFree(ctx.js_warnings);
1569  ctx.js_warnings = NULL;
1570  }
1571  if (ctx.js_notes) {
1572  SCJbClose(ctx.js_notes);
1573  SCJbSetObject(ctx.js, "notes", ctx.js_notes);
1574  SCJbFree(ctx.js_notes);
1575  ctx.js_notes = NULL;
1576  }
1577  SCJbClose(ctx.js);
1578 
1579  const char *filename = "rules.json";
1580  const char *log_dir = SCConfigGetLogDirectory();
1581  char json_path[PATH_MAX] = "";
1582  snprintf(json_path, sizeof(json_path), "%s/%s%s", log_dir,
1583  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", filename);
1584 
1586  FILE *fp = fopen(json_path, "a");
1587  if (fp != NULL) {
1588  fwrite(SCJbPtr(ctx.js), SCJbLen(ctx.js), 1, fp);
1589  fprintf(fp, "\n");
1590  fclose(fp);
1591  }
1593  SCJbFree(ctx.js);
1594  SCReturn;
1595 }
1596 
1598 {
1599  if (de_ctx->pattern_hash_table == NULL)
1600  return;
1601 
1602  SCJsonBuilder *root_jb = SCJbNewObject();
1603  if (root_jb == NULL) {
1604  return;
1605  }
1606  SCJsonBuilder **arrays = SCCalloc(de_ctx->buffer_type_id, sizeof(SCJsonBuilder *));
1607  if (arrays == NULL) {
1608  SCJbFree(root_jb);
1609  return;
1610  }
1611 
1612  SCJbOpenArray(root_jb, "buffers");
1613 
1615  htb != NULL; htb = HashListTableGetListNext(htb)) {
1616  char str[1024] = "";
1618  DetectContentPatternPrettyPrint(p->cd->content, p->cd->content_len, str, sizeof(str));
1619 
1620  SCJsonBuilder *jb = arrays[p->sm_list];
1621  if (arrays[p->sm_list] == NULL) {
1622  jb = arrays[p->sm_list] = SCJbNewObject();
1623  const char *name;
1624  if (p->sm_list < DETECT_SM_LIST_DYNAMIC_START)
1625  name = DetectListToHumanString(p->sm_list);
1626  else
1628  SCJbSetString(jb, "name", name);
1629  SCJbSetUint(jb, "list_id", p->sm_list);
1630 
1631  SCJbOpenArray(jb, "patterns");
1632  }
1633 
1634  SCJbStartObject(jb);
1635  SCJbSetString(jb, "pattern", str);
1636  SCJbSetUint(jb, "patlen", p->cd->content_len);
1637  SCJbSetUint(jb, "cnt", p->cnt);
1638  SCJbSetUint(jb, "mpm", p->mpm);
1639  SCJbOpenObject(jb, "flags");
1640  SCJbSetBool(jb, "nocase", p->cd->flags & DETECT_CONTENT_NOCASE);
1641  SCJbSetBool(jb, "negated", p->cd->flags & DETECT_CONTENT_NEGATED);
1642  SCJbSetBool(jb, "depth", p->cd->flags & DETECT_CONTENT_DEPTH);
1643  SCJbSetBool(jb, "offset", p->cd->flags & DETECT_CONTENT_OFFSET);
1644  SCJbSetBool(jb, "endswith", p->cd->flags & DETECT_CONTENT_ENDS_WITH);
1645  SCJbClose(jb);
1646  SCJbClose(jb);
1647  }
1648 
1649  for (uint32_t i = 0; i < de_ctx->buffer_type_id; i++) {
1650  SCJsonBuilder *jb = arrays[i];
1651  if (jb == NULL)
1652  continue;
1653 
1654  SCJbClose(jb); // array
1655  SCJbClose(jb); // object
1656 
1657  SCJbAppendObject(root_jb, jb);
1658  SCJbFree(jb);
1659  }
1660  SCJbClose(root_jb);
1661  SCJbClose(root_jb);
1662 
1663  const char *filename = "patterns.json";
1664  const char *log_dir = SCConfigGetLogDirectory();
1665  char json_path[PATH_MAX] = "";
1666  snprintf(json_path, sizeof(json_path), "%s/%s%s", log_dir,
1667  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", filename);
1668 
1670  FILE *fp = fopen(json_path, "a");
1671  if (fp != NULL) {
1672  fwrite(SCJbPtr(root_jb), SCJbLen(root_jb), 1, fp);
1673  fprintf(fp, "\n");
1674  fclose(fp);
1675  }
1677  SCJbFree(root_jb);
1678  SCFree(arrays);
1679 
1681  de_ctx->pattern_hash_table = NULL;
1682 }
1683 
1684 static void EngineAnalysisItemsReset(EngineAnalysisCtx *ea_ctx)
1685 {
1686  for (size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
1687  ea_ctx->analyzer_items[i].item_seen = false;
1688  }
1689 }
1690 
1691 static void EngineAnalysisItemsInit(EngineAnalysisCtx *ea_ctx)
1692 {
1693  if (ea_ctx->analyzer_initialized) {
1694  EngineAnalysisItemsReset(ea_ctx);
1695  return;
1696  }
1697 
1698  ea_ctx->exposed_item_seen_list[0].bufname = "http_method";
1699  ea_ctx->exposed_item_seen_list[1].bufname = "file_data";
1700  ea_ctx->analyzer_items = SCCalloc(1, sizeof(analyzer_items));
1701  if (!ea_ctx->analyzer_items) {
1702  FatalError("Unable to allocate analysis scratch pad");
1703  }
1704  memset(ea_ctx->analyzer_item_map, -1, sizeof(ea_ctx->analyzer_item_map));
1705 
1706  for (size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
1707  ea_ctx->analyzer_items[i] = analyzer_items[i];
1708  DetectEngineAnalyzerItems *analyzer_item = &ea_ctx->analyzer_items[i];
1709 
1710  int item_id = DetectBufferTypeGetByName(analyzer_item->item_name);
1711  DEBUG_VALIDATE_BUG_ON(item_id < 0 || item_id > UINT16_MAX);
1712  analyzer_item->item_id = (uint16_t)item_id;
1713  if (analyzer_item->item_id == -1) {
1714  /* Mismatch between the analyzer_items array and what's supported */
1715  FatalError("unable to initialize engine-analysis table: detect buffer \"%s\" not "
1716  "recognized.",
1717  analyzer_item->item_name);
1718  }
1719  analyzer_item->item_seen = false;
1720 
1721  if (analyzer_item->export_item_seen) {
1722  for (size_t k = 0; k < ARRAY_SIZE(ea_ctx->exposed_item_seen_list); k++) {
1723  if (0 ==
1724  strcmp(ea_ctx->exposed_item_seen_list[k].bufname, analyzer_item->item_name))
1725  ea_ctx->exposed_item_seen_list[k].item_seen_ptr = &analyzer_item->item_seen;
1726  }
1727  }
1728  ea_ctx->analyzer_item_map[analyzer_item->item_id] = (int16_t)i;
1729  }
1730 
1731  ea_ctx->analyzer_initialized = true;
1732 }
1733 
1734 /**
1735  * \brief Prints analysis of loaded rules.
1736  *
1737  * Warns if potential rule issues are detected. For example,
1738  * warns if a rule uses a construct that may perform poorly,
1739  * e.g. pcre without content or with http_method content only;
1740  * warns if a rule uses a construct that may not be consistent with intent,
1741  * e.g. client side ports only, http and content without any http_* modifiers, etc.
1742  *
1743  * \param s Pointer to the signature.
1744  */
1746  const Signature *s, const char *line)
1747 {
1748  uint32_t rule_bidirectional = 0;
1749  uint32_t rule_pcre = 0;
1750  uint32_t rule_pcre_http = 0;
1751  uint32_t rule_content = 0;
1752  uint32_t rule_flow = 0;
1753  uint32_t rule_flags = 0;
1754  uint32_t rule_flow_toserver = 0;
1755  uint32_t rule_flow_toclient = 0;
1756  uint32_t rule_flow_nostream = 0;
1757  uint32_t rule_ipv4_only = 0;
1758  uint32_t rule_ipv6_only = 0;
1759  uint32_t rule_flowbits = 0;
1760  uint32_t rule_flowint = 0;
1761  uint32_t rule_content_http = 0;
1762  uint32_t rule_content_offset_depth = 0;
1763  int32_t list_id = 0;
1764  uint32_t rule_warning = 0;
1765  uint32_t stream_buf = 0;
1766  uint32_t packet_buf = 0;
1767  uint32_t file_store = 0;
1768  uint32_t warn_pcre_no_content = 0;
1769  uint32_t warn_pcre_http_content = 0;
1770  uint32_t warn_pcre_http = 0;
1771  uint32_t warn_content_http_content = 0;
1772  uint32_t warn_content_http = 0;
1773  uint32_t warn_tcp_no_flow = 0;
1774  uint32_t warn_client_ports = 0;
1775  uint32_t warn_direction = 0;
1776  uint32_t warn_method_toclient = 0;
1777  uint32_t warn_method_serverbody = 0;
1778  uint32_t warn_pcre_method = 0;
1779  uint32_t warn_encoding_norm_http_buf = 0;
1780  uint32_t warn_file_store_not_present = 0;
1781  uint32_t warn_offset_depth_pkt_stream = 0;
1782  uint32_t warn_offset_depth_alproto = 0;
1783  uint32_t warn_non_alproto_fp_for_alproto_sig = 0;
1784  uint32_t warn_no_direction = 0;
1785  uint32_t warn_both_direction = 0;
1786 
1787  EngineAnalysisItemsInit(de_ctx->ea);
1788 
1789  bool *http_method_item_seen_ptr = de_ctx->ea->exposed_item_seen_list[0].item_seen_ptr;
1790  bool *http_server_body_item_seen_ptr = de_ctx->ea->exposed_item_seen_list[1].item_seen_ptr;
1791 
1793  rule_bidirectional = 1;
1794  }
1795 
1796  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
1797  packet_buf += 1;
1798  }
1799  if (s->flags & SIG_FLAG_FILESTORE) {
1800  file_store += 1;
1801  }
1802  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
1803  stream_buf += 1;
1804  }
1805 
1806  if (s->proto && s->proto->flags & DETECT_PROTO_IPV4) {
1807  rule_ipv4_only += 1;
1808  }
1809  if (s->proto && s->proto->flags & DETECT_PROTO_IPV6) {
1810  rule_ipv6_only += 1;
1811  }
1812 
1813  for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
1814  SigMatch *sm = NULL;
1815  for (sm = s->init_data->smlists[list_id]; sm != NULL; sm = sm->next) {
1816  int16_t item_slot = de_ctx->ea->analyzer_item_map[list_id];
1817  if (sm->type == DETECT_PCRE) {
1818  if (item_slot == -1) {
1819  rule_pcre++;
1820  continue;
1821  }
1822 
1823  rule_pcre_http++;
1824  de_ctx->ea->analyzer_items[item_slot].item_seen = true;
1825  } else if (sm->type == DETECT_CONTENT) {
1826  if (item_slot == -1) {
1827  rule_content++;
1828  if (list_id == DETECT_SM_LIST_PMATCH) {
1831  rule_content_offset_depth++;
1832  }
1833  }
1834  continue;
1835  }
1836 
1837  rule_content_http++;
1838  de_ctx->ea->analyzer_items[item_slot].item_seen = true;
1839 
1840  if (de_ctx->ea->analyzer_items[item_slot].check_encoding_match) {
1842  if (cd != NULL &&
1843  PerCentEncodingMatch(de_ctx->ea, cd->content, cd->content_len) > 0) {
1844  warn_encoding_norm_http_buf += 1;
1845  }
1846  }
1847  }
1848  else if (sm->type == DETECT_FLOW) {
1849  rule_flow += 1;
1850  if ((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_TOCLIENT)) {
1851  rule_flow_toserver = 1;
1852  }
1853  else if ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_TOSERVER)) {
1854  rule_flow_toclient = 1;
1855  }
1856  DetectFlowData *fd = (DetectFlowData *)sm->ctx;
1857  if (fd != NULL) {
1858  if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM)
1859  rule_flow_nostream = 1;
1860  }
1861  }
1862  else if (sm->type == DETECT_FLOWBITS) {
1863  if (list_id == DETECT_SM_LIST_MATCH) {
1864  rule_flowbits += 1;
1865  }
1866  }
1867  else if (sm->type == DETECT_FLOWINT) {
1868  if (list_id == DETECT_SM_LIST_MATCH) {
1869  rule_flowint += 1;
1870  }
1871  }
1872  else if (sm->type == DETECT_FLAGS) {
1873  if (sm->ctx != NULL) {
1874  rule_flags = 1;
1875  }
1876  }
1877  } /* for (sm = s->init_data->smlists[list_id]; sm != NULL; sm = sm->next) */
1878 
1879  } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */
1880 
1881  if (file_store && !SCRequiresFeature("output::file-store")) {
1882  rule_warning += 1;
1883  warn_file_store_not_present = 1;
1884  }
1885 
1886  if (rule_pcre > 0 && rule_content == 0 && rule_content_http == 0) {
1887  rule_warning += 1;
1888  warn_pcre_no_content = 1;
1889  }
1890 
1891  if (rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0) {
1892  rule_warning += 1;
1893  warn_pcre_http_content = 1;
1894  } else if (s->alproto == ALPROTO_HTTP1 && rule_pcre > 0 && rule_pcre_http == 0) {
1895  rule_warning += 1;
1896  warn_pcre_http = 1;
1897  }
1898 
1899  if (rule_content > 0 && rule_content_http > 0) {
1900  rule_warning += 1;
1901  warn_content_http_content = 1;
1902  }
1903  if (s->alproto == ALPROTO_HTTP1 && rule_content > 0 && rule_content_http == 0) {
1904  rule_warning += 1;
1905  warn_content_http = 1;
1906  }
1907  if (rule_content == 1) {
1908  //todo: warning if content is weak, separate warning for pcre + weak content
1909  }
1910  if (rule_flow == 0 && rule_flags == 0 && !(s->init_data->proto.flags & DETECT_PROTO_ANY) &&
1911  DetectProtoContainsProto(&s->init_data->proto, IPPROTO_TCP) &&
1912  (rule_content || rule_content_http || rule_pcre || rule_pcre_http || rule_flowbits ||
1913  rule_flowint)) {
1914  rule_warning += 1;
1915  warn_tcp_no_flow = 1;
1916  }
1917  if (rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)
1918  && !((s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))) {
1919  if (((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))
1920  || ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_DP_ANY) && (s->flags & SIG_FLAG_SP_ANY))) {
1921  rule_warning += 1;
1922  warn_client_ports = 1;
1923  }
1924  }
1925  if (rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)) {
1926  rule_warning += 1;
1927  warn_direction = 1;
1928  }
1929 
1930  if (*http_method_item_seen_ptr) {
1931  if (rule_flow && rule_flow_toclient) {
1932  rule_warning += 1;
1933  warn_method_toclient = 1;
1934  }
1935  if (*http_server_body_item_seen_ptr) {
1936  rule_warning += 1;
1937  warn_method_serverbody = 1;
1938  }
1939  if (rule_content == 0 && rule_content_http == 0 && (rule_pcre > 0 || rule_pcre_http > 0)) {
1940  rule_warning += 1;
1941  warn_pcre_method = 1;
1942  }
1943  }
1944  if (rule_content_offset_depth > 0 && stream_buf && packet_buf) {
1945  rule_warning += 1;
1946  warn_offset_depth_pkt_stream = 1;
1947  }
1948  if (rule_content_offset_depth > 0 && !stream_buf && packet_buf && s->alproto != ALPROTO_UNKNOWN) {
1949  rule_warning += 1;
1950  warn_offset_depth_alproto = 1;
1951  }
1952  if (s->init_data->mpm_sm != NULL && s->alproto == ALPROTO_HTTP1 &&
1954  rule_warning += 1;
1955  warn_non_alproto_fp_for_alproto_sig = 1;
1956  }
1957 
1958  if ((s->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) {
1959  warn_no_direction += 1;
1960  rule_warning += 1;
1961  }
1962 
1963  /* No warning about direction for ICMP protos */
1964  if (!(DetectProtoContainsProto(&s->init_data->proto, IPPROTO_ICMPV6) &&
1965  DetectProtoContainsProto(&s->init_data->proto, IPPROTO_ICMP))) {
1967  warn_both_direction += 1;
1968  rule_warning += 1;
1969  }
1970  }
1971 
1972  if (!rule_warnings_only || (rule_warnings_only && rule_warning > 0)) {
1973  FILE *fp = de_ctx->ea->rule_engine_analysis_fp;
1974  fprintf(fp, "== Sid: %u ==\n", s->id);
1975  fprintf(fp, "%s\n", line);
1976 
1977  switch (s->type) {
1978  case SIG_TYPE_NOT_SET:
1979  break;
1980  case SIG_TYPE_IPONLY:
1981  fprintf(fp, " Rule is ip only.\n");
1982  break;
1983  case SIG_TYPE_LIKE_IPONLY:
1984  fprintf(fp, " Rule is like ip only.\n");
1985  break;
1986  case SIG_TYPE_PDONLY:
1987  fprintf(fp, " Rule is PD only.\n");
1988  break;
1989  case SIG_TYPE_DEONLY:
1990  fprintf(fp, " Rule is DE only.\n");
1991  break;
1992  case SIG_TYPE_PKT:
1993  fprintf(fp, " Rule is packet inspecting.\n");
1994  break;
1995  case SIG_TYPE_PKT_STREAM:
1996  fprintf(fp, " Rule is packet and stream inspecting.\n");
1997  break;
1998  case SIG_TYPE_STREAM:
1999  fprintf(fp, " Rule is stream inspecting.\n");
2000  break;
2001  case SIG_TYPE_APPLAYER:
2002  fprintf(fp, " Rule is app-layer inspecting.\n");
2003  break;
2004  case SIG_TYPE_APP_TX:
2005  fprintf(fp, " Rule is App-layer TX inspecting.\n");
2006  break;
2007  case SIG_TYPE_MAX:
2008  break;
2009  }
2010  if (rule_ipv6_only)
2011  fprintf(fp, " Rule is IPv6 only.\n");
2012  if (rule_ipv4_only)
2013  fprintf(fp, " Rule is IPv4 only.\n");
2014  if (packet_buf)
2015  fprintf(fp, " Rule matches on packets.\n");
2016  if (!rule_flow_nostream && stream_buf &&
2017  (rule_flow || rule_flowbits || rule_flowint || rule_content || rule_pcre)) {
2018  fprintf(fp, " Rule matches on reassembled stream.\n");
2019  }
2020  for(size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
2022  if (ai->item_seen) {
2023  fprintf(fp, " Rule matches on %s buffer.\n", ai->display_name);
2024  }
2025  }
2026  if (s->alproto != ALPROTO_UNKNOWN) {
2027  fprintf(fp, " App layer protocol is %s.\n", AppProtoToString(s->alproto));
2028  }
2029  if (rule_content || rule_content_http || rule_pcre || rule_pcre_http) {
2030  fprintf(fp,
2031  " Rule contains %u content options, %u http content options, %u pcre "
2032  "options, and %u pcre options with http modifiers.\n",
2033  rule_content, rule_content_http, rule_pcre, rule_pcre_http);
2034  }
2035 
2036  /* print fast pattern info */
2037  if (s->init_data->prefilter_sm) {
2038  fprintf(fp, " Prefilter on: %s.\n",
2040  } else {
2041  EngineAnalysisRulesPrintFP(de_ctx, s);
2042  }
2043 
2044  /* this is where the warnings start */
2045  if (warn_pcre_no_content /*rule_pcre > 0 && rule_content == 0 && rule_content_http == 0*/) {
2046  fprintf(fp, " Warning: Rule uses pcre without a content option present.\n"
2047  " -Consider adding a content to improve performance of this "
2048  "rule.\n");
2049  }
2050  if (warn_pcre_http_content /*rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0*/) {
2051  fprintf(fp, " Warning: Rule uses content options with http_* and pcre options "
2052  "without http modifiers.\n"
2053  " -Consider adding http pcre modifier.\n");
2054  }
2055  else if (warn_pcre_http /*s->alproto == ALPROTO_HTTP1 && rule_pcre > 0 && rule_pcre_http == 0*/) {
2056  fprintf(fp, " Warning: Rule app layer protocol is http, but pcre options do not "
2057  "have http modifiers.\n"
2058  " -Consider adding http pcre modifiers.\n");
2059  }
2060  if (warn_content_http_content /*rule_content > 0 && rule_content_http > 0*/) {
2061  fprintf(fp,
2062  " Warning: Rule contains content with http_* and content without http_*.\n"
2063  " -Consider adding http content modifiers.\n");
2064  }
2065  if (warn_content_http /*s->alproto == ALPROTO_HTTP1 && rule_content > 0 && rule_content_http == 0*/) {
2066  fprintf(fp, " Warning: Rule app layer protocol is http, but content options do not "
2067  "have http_* modifiers.\n"
2068  " -Consider adding http content modifiers.\n");
2069  }
2070  if (rule_content == 1) {
2071  //todo: warning if content is weak, separate warning for pcre + weak content
2072  }
2073  if (warn_encoding_norm_http_buf) {
2074  fprintf(fp, " Warning: Rule may contain percent encoded content for a normalized "
2075  "http buffer match.\n");
2076  }
2077  if (warn_tcp_no_flow /*rule_flow == 0 && rule_flags == 0
2078  && !(s->proto.flags & DETECT_PROTO_ANY) && DetectProtoContainsProto(&s->proto, IPPROTO_TCP)*/) {
2079  fprintf(fp, " Warning: TCP rule without a flow or flags option.\n"
2080  " -Consider adding flow or flags to improve performance of "
2081  "this rule.\n");
2082  }
2083  if (warn_client_ports /*rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)
2084  && !((s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY)))
2085  if (((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))
2086  || ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_DP_ANY) && (s->flags & SIG_FLAG_SP_ANY))*/) {
2087  fprintf(fp,
2088  " Warning: Rule contains ports or port variables only on the client side.\n"
2089  " -Flow direction possibly inconsistent with rule.\n");
2090  }
2091  if (warn_direction /*rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)*/) {
2092  fprintf(fp, " Warning: Rule is bidirectional and has a flow option with a specific "
2093  "direction.\n");
2094  }
2095  if (warn_method_toclient /*http_method_buf && rule_flow && rule_flow_toclient*/) {
2096  fprintf(fp, " Warning: Rule uses content or pcre for http_method with "
2097  "flow:to_client or from_server\n");
2098  }
2099  if (warn_method_serverbody /*http_method_buf && http_server_body_buf*/) {
2100  fprintf(fp, " Warning: Rule uses content or pcre for http_method with content or "
2101  "pcre for http_server_body.\n");
2102  }
2103  if (warn_pcre_method /*http_method_buf && rule_content == 0 && rule_content_http == 0
2104  && (rule_pcre > 0 || rule_pcre_http > 0)*/) {
2105  fprintf(fp, " Warning: Rule uses pcre with only a http_method content; possible "
2106  "performance issue.\n");
2107  }
2108  if (warn_offset_depth_pkt_stream) {
2109  fprintf(fp, " Warning: Rule has depth"
2110  "/offset with raw content keywords. Please note the "
2111  "offset/depth will be checked against both packet "
2112  "payloads and stream. If you meant to have the offset/"
2113  "depth checked against just the payload, you can update "
2114  "the signature as \"alert tcp-pkt...\"\n");
2115  }
2116  if (warn_offset_depth_alproto) {
2117  fprintf(fp,
2118  " Warning: Rule has "
2119  "offset/depth set along with a match on a specific "
2120  "app layer protocol - %d. This can lead to FNs if we "
2121  "have a offset/depth content match on a packet payload "
2122  "before we can detect the app layer protocol for the "
2123  "flow.\n",
2124  s->alproto);
2125  }
2126  if (warn_non_alproto_fp_for_alproto_sig) {
2127  fprintf(fp, " Warning: Rule app layer "
2128  "protocol is http, but the fast_pattern is set on the raw "
2129  "stream. Consider adding fast_pattern over a http "
2130  "buffer for increased performance.");
2131  }
2132  if (warn_no_direction) {
2133  fprintf(fp, " Warning: Rule has no direction indicator.\n");
2134  }
2135  if (warn_both_direction) {
2136  fprintf(fp, " Warning: Rule is inspecting both the request and the response.\n");
2137  }
2138  if (warn_file_store_not_present) {
2139  fprintf(fp, " Warning: Rule requires file-store but the output file-store is not "
2140  "enabled.\n");
2141  }
2142  if (rule_warning == 0) {
2143  fprintf(fp, " No warnings for this rule.\n");
2144  }
2145  fprintf(fp, "\n");
2146  }
2147 }
2148 
2149 #include "app-layer-parser.h"
2150 
2151 /**
2152  * \brief Render a resolved firewall default policy as "<action>:<scope>".
2153  *
2154  * \retval true \p out holds the rendered policy
2155  * \retval false the policy could not be rendered
2156  */
2157 static bool FirewallPolicyToString(
2158  const struct DetectFirewallPolicy *p, char *out, const size_t out_size)
2159 {
2160  const char *as = ActionScopeToString(p->action_scope);
2161  DEBUG_VALIDATE_BUG_ON(as == NULL);
2162  if (as == NULL)
2163  return false;
2164  if (p->action & ACTION_REJECT_ANY) {
2165  if (p->action & ACTION_REJECT_DST) {
2166  snprintf(out, out_size, "rejectdst:%s", as);
2167  } else if (p->action & ACTION_REJECT_BOTH) {
2168  snprintf(out, out_size, "rejectboth:%s", as);
2169  } else {
2170  snprintf(out, out_size, "rejectsrc:%s", as);
2171  }
2172  } else if (p->action & ACTION_DROP) {
2173  snprintf(out, out_size, "drop:%s", as);
2174  } else if (p->action & ACTION_ACCEPT) {
2175  snprintf(out, out_size, "accept:%s", as);
2176  } else {
2178  return false;
2179  }
2180  if (p->action & ACTION_PASS) {
2181  if (p->action_scope == ACTION_SCOPE_FLOW || p->action_scope == ACTION_SCOPE_PACKET) {
2182  if (strlcat(out, ",pass:", out_size) >= out_size ||
2183  strlcat(out, as, out_size) >= out_size) {
2185  return false;
2186  }
2187  } else {
2189  return false;
2190  }
2191  }
2192  if (p->action & ACTION_ALERT) {
2193  if (strlcat(out, ",alert", out_size) >= out_size) {
2195  return false;
2196  }
2197  }
2198  return true;
2199 }
2200 
2201 static void AddPolicy(const DetectEngineCtx *de_ctx, RuleAnalyzer *ctx, const AppProto a,
2202  const uint8_t sub_state, const uint8_t state, const uint8_t direction)
2203 {
2204  char policy_string[64] = "";
2205  const struct DetectFirewallPolicies *fw_policies = de_ctx->fw_policies;
2206  const struct DetectFirewallAppPolicy lookup = {
2207  .alproto = a, .sub_state = sub_state, .progress = state, .direction = direction
2208  };
2209  const struct DetectFirewallAppPolicy *ap =
2210  HashTableLookup(fw_policies->app_policies, (void *)&lookup, 0);
2211  if (ap == NULL)
2212  return;
2213  if (!FirewallPolicyToString(&ap->policy, policy_string, sizeof(policy_string)))
2214  return;
2215  SCJbSetString(ctx->js, "policy", policy_string);
2216 }
2217 
2218 static void FirewallAddRulesForState(const DetectEngineCtx *de_ctx, const AppProto a,
2219  const uint8_t sub_state, const uint8_t state, const uint8_t direction, RuleAnalyzer *ctx)
2220 {
2221  uint32_t accept_rules = 0;
2222  AddPolicy(de_ctx, ctx, a, sub_state, state, direction);
2223  SCJbOpenArray(ctx->js, "rules");
2224  for (const Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2225  if ((s->flags & SIG_FLAG_FIREWALL) == 0)
2226  break;
2227  if (s->type != SIG_TYPE_APP_TX)
2228  continue;
2229  if (s->alproto != a)
2230  continue;
2231 
2232  if (direction == STREAM_TOSERVER) {
2233  if (s->flags & SIG_FLAG_TOCLIENT) {
2234  continue;
2235  }
2236  } else {
2237  if (s->flags & SIG_FLAG_TOSERVER) {
2238  continue;
2239  }
2240  }
2241 
2242  /* sig has no sub_state field, so check the app inspect engines (if any).
2243  * We assume that the only engines we have either:
2244  * - are unknown/substate 0
2245  * - matching the rule's substate */
2246  if (s->app_inspect != NULL) {
2247  bool skip_rule = false;
2248  for (const DetectEngineAppInspectionEngine *engine = s->app_inspect; engine != NULL;
2249  engine = engine->next) {
2250  if (engine->alproto == ALPROTO_UNKNOWN) {
2251  // skip engines targeting unknown, like stream or app-layer-event
2252  } else if (engine->sub_state != sub_state) {
2253  skip_rule = true;
2254  break;
2255  }
2256  }
2257  if (skip_rule) {
2258  continue;
2259  }
2260  }
2261  if ((s->flags & SIG_FLAG_FW_HOOK_LTE) && state < s->app_progress_hook) {
2262  SCJbAppendString(ctx->js, s->sig_str);
2263  accept_rules += ((s->action & ACTION_ACCEPT) != 0);
2264  }
2265 
2266  if (s->app_progress_hook == state) {
2267  SCJbAppendString(ctx->js, s->sig_str);
2268  accept_rules += ((s->action & ACTION_ACCEPT) != 0);
2269  }
2270  }
2271  SCJbClose(ctx->js);
2272 
2273  if (accept_rules == 0) {
2274  AnalyzerWarning(ctx, (char *)"no accept rules for state, default policy will be applied");
2275  }
2276 }
2277 
2279 {
2280  RuleAnalyzer ctx = { NULL, NULL, NULL };
2281  ctx.js = SCJbNewObject();
2282  if (ctx.js == NULL)
2283  return -1;
2284 
2285  SCJbOpenObject(ctx.js, "tables");
2286  SCJbOpenObject(ctx.js, "packet:filter");
2287  char pkt_policy[64] = "";
2288  if (FirewallPolicyToString(&de_ctx->fw_policies->pkt[DETECT_FIREWALL_POLICY_PACKET_FILTER],
2289  pkt_policy, sizeof(pkt_policy))) {
2290  SCJbSetString(ctx.js, "policy", pkt_policy);
2291  }
2292  SCJbOpenArray(ctx.js, "rules");
2293  uint32_t accept_rules = 0;
2294  uint32_t last_sid = 0;
2295  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2296  if ((s->flags & SIG_FLAG_FIREWALL) == 0)
2297  break;
2298  if (s->type != SIG_TYPE_PKT)
2299  continue;
2300  /* don't double list <> sigs */
2301  if (last_sid == s->id)
2302  continue;
2303  last_sid = s->id;
2304  SCJbAppendString(ctx.js, s->sig_str);
2305  accept_rules += ((s->action & ACTION_ACCEPT) != 0);
2306  }
2307  SCJbClose(ctx.js);
2308  if (accept_rules == 0) {
2309  AnalyzerWarning(&ctx,
2310  (char *)"no accept rules for \'packet:filter\', default policy will be applied");
2311  }
2312  if (ctx.js_warnings) {
2313  SCJbClose(ctx.js_warnings);
2314  SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
2315  SCJbFree(ctx.js_warnings);
2316  ctx.js_warnings = NULL;
2317  }
2318  SCJbClose(ctx.js); // packet_filter
2319 
2320  for (AppProto a = 0; a < g_alproto_max; a++) {
2321  if (!AppProtoIsValid(a))
2322  continue;
2323 
2325  SCJbOpenObject(ctx.js, AppProtoToString(a));
2326  const uint8_t max_sub_state = AppLayerParserGetMaxSubState(a);
2327  for (uint8_t sub_state = 1; sub_state <= max_sub_state; sub_state++) {
2328  const char *sub_state_name = AppLayerParserGetSubStateName(a, sub_state);
2329  const uint8_t max_progress = AppLayerParserGetSubStateCompletion(a, sub_state);
2330  for (uint8_t state = 0; state <= max_progress; state++) {
2332  a, sub_state, state, STREAM_TOSERVER);
2333  if (name == NULL)
2334  continue;
2335 
2336  char table_name[256];
2337  snprintf(table_name, sizeof(table_name), "app:%s:%s:%s", AppProtoToString(a),
2338  sub_state_name, name);
2339  SCJbOpenObject(ctx.js, table_name);
2340  FirewallAddRulesForState(de_ctx, a, sub_state, state, STREAM_TOSERVER, &ctx);
2341  if (ctx.js_warnings) {
2342  SCJbClose(ctx.js_warnings);
2343  SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
2344  SCJbFree(ctx.js_warnings);
2345  ctx.js_warnings = NULL;
2346  }
2347  SCJbClose(ctx.js);
2348  }
2349  for (uint8_t state = 0; state <= max_progress; state++) {
2351  a, sub_state, state, STREAM_TOCLIENT);
2352  if (name == NULL)
2353  continue;
2354 
2355  char table_name[256];
2356  snprintf(table_name, sizeof(table_name), "app:%s:%s:%s", AppProtoToString(a),
2357  sub_state_name, name);
2358  SCJbOpenObject(ctx.js, table_name);
2359  FirewallAddRulesForState(de_ctx, a, sub_state, state, STREAM_TOCLIENT, &ctx);
2360  if (ctx.js_warnings) {
2361  SCJbClose(ctx.js_warnings);
2362  SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
2363  SCJbFree(ctx.js_warnings);
2364  ctx.js_warnings = NULL;
2365  }
2366  SCJbClose(ctx.js);
2367  }
2368  }
2369  SCJbClose(ctx.js); // app layer
2370  continue;
2371  }
2372 
2373  /* no sub state follows */
2374 
2375  const uint8_t complete_state_ts =
2376  (const uint8_t)AppLayerParserGetStateProgressCompletionStatus(a, STREAM_TOSERVER);
2377  SCJbOpenObject(ctx.js, AppProtoToString(a));
2378  for (uint8_t state = 0; state <= complete_state_ts; state++) {
2379  const char *name =
2380  AppLayerParserGetStateNameById(IPPROTO_TCP, a, state, STREAM_TOSERVER);
2381  if (name == NULL) {
2382  name = DetectFirewallAppGenericHookName(state, complete_state_ts, STREAM_TOSERVER);
2383  if (name == NULL)
2384  name = "unknown";
2385  }
2386 
2387  char table_name[128];
2388  snprintf(table_name, sizeof(table_name), "app:%s:%s", AppProtoToString(a), name);
2389  SCJbOpenObject(ctx.js, table_name);
2390  FirewallAddRulesForState(de_ctx, a, 0, state, STREAM_TOSERVER, &ctx);
2391  if (ctx.js_warnings) {
2392  SCJbClose(ctx.js_warnings);
2393  SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
2394  SCJbFree(ctx.js_warnings);
2395  ctx.js_warnings = NULL;
2396  }
2397  SCJbClose(ctx.js);
2398  }
2399  const uint8_t complete_state_tc =
2400  (const uint8_t)AppLayerParserGetStateProgressCompletionStatus(a, STREAM_TOCLIENT);
2401  for (uint8_t state = 0; state <= complete_state_tc; state++) {
2402  const char *name =
2403  AppLayerParserGetStateNameById(IPPROTO_TCP, a, state, STREAM_TOCLIENT);
2404  if (name == NULL) {
2405  name = DetectFirewallAppGenericHookName(state, complete_state_tc, STREAM_TOCLIENT);
2406  if (name == NULL)
2407  name = "unknown";
2408  }
2409  char table_name[128];
2410  snprintf(table_name, sizeof(table_name), "app:%s:%s", AppProtoToString(a), name);
2411  SCJbOpenObject(ctx.js, table_name);
2412  FirewallAddRulesForState(de_ctx, a, 0, state, STREAM_TOCLIENT, &ctx);
2413  if (ctx.js_warnings) {
2414  SCJbClose(ctx.js_warnings);
2415  SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
2416  SCJbFree(ctx.js_warnings);
2417  ctx.js_warnings = NULL;
2418  }
2419  SCJbClose(ctx.js);
2420  }
2421  SCJbClose(ctx.js); // app layer
2422  }
2423  SCJbOpenObject(ctx.js, "packet:td");
2424  SCJbSetString(ctx.js, "policy", "accept:hook");
2425  last_sid = 0;
2426  SCJbOpenArray(ctx.js, "rules");
2427  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2428  if ((s->flags & SIG_FLAG_FIREWALL) != 0)
2429  continue;
2430  if (s->type == SIG_TYPE_APP_TX)
2431  continue;
2432  if (last_sid == s->id)
2433  continue;
2434  last_sid = s->id;
2435  SCJbAppendString(ctx.js, s->sig_str);
2436  }
2437  SCJbClose(ctx.js); // rules
2438  SCJbClose(ctx.js); // packet:td
2439  SCJbOpenObject(ctx.js, "app:td");
2440  SCJbSetString(ctx.js, "policy", "accept:hook");
2441  last_sid = 0;
2442  SCJbOpenArray(ctx.js, "rules");
2443  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2444  if ((s->flags & SIG_FLAG_FIREWALL) != 0)
2445  continue;
2446  if (s->type != SIG_TYPE_APP_TX)
2447  continue;
2448  if (last_sid == s->id)
2449  continue;
2450  last_sid = s->id;
2451  SCJbAppendString(ctx.js, s->sig_str);
2452  }
2453  SCJbClose(ctx.js); // rules
2454  SCJbClose(ctx.js); // app:td
2455  SCJbClose(ctx.js); // tables
2456 
2457  SCJbOpenObject(ctx.js, "lists");
2458  SCJbOpenObject(ctx.js, "firewall");
2459  last_sid = 0;
2460  SCJbOpenArray(ctx.js, "rules");
2461  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2462  if ((s->flags & SIG_FLAG_FIREWALL) == 0)
2463  continue;
2464  if (last_sid == s->id)
2465  continue;
2466  last_sid = s->id;
2467  SCJbAppendString(ctx.js, s->sig_str);
2468  }
2469  SCJbClose(ctx.js); // rules
2470  SCJbClose(ctx.js); // firewall
2471 
2472  SCJbOpenObject(ctx.js, "td");
2473  last_sid = 0;
2474  SCJbOpenArray(ctx.js, "rules");
2475  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2476  if ((s->flags & SIG_FLAG_FIREWALL) != 0)
2477  continue;
2478  if (last_sid == s->id)
2479  continue;
2480  last_sid = s->id;
2481  SCJbAppendString(ctx.js, s->sig_str);
2482  }
2483  SCJbClose(ctx.js); // rules
2484  SCJbClose(ctx.js); // td
2485 
2486  SCJbOpenObject(ctx.js, "all");
2487  last_sid = 0;
2488  SCJbOpenArray(ctx.js, "rules");
2489  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2490  if (last_sid == s->id)
2491  continue;
2492  last_sid = s->id;
2493  SCJbAppendString(ctx.js, s->sig_str);
2494  }
2495  SCJbClose(ctx.js); // rules
2496  SCJbClose(ctx.js); // all
2497 
2498  SCJbClose(ctx.js); // lists
2499 
2500  /* Per-rule keyword metadata for tcp.session */
2501  SCJbOpenObject(ctx.js, "keyword_info");
2502  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2503  const SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_MATCH];
2504  if (smd == NULL)
2505  continue;
2506  for (;;) {
2507  if (smd->type == DETECT_TCP_SESSION) {
2508  const DetectTcpSessionData *tsd = (const DetectTcpSessionData *)smd->ctx;
2509  if (tsd != NULL) {
2510  char sid_key[32];
2511  snprintf(sid_key, sizeof(sid_key), "%u", s->id);
2512  SCJbOpenObject(ctx.js, sid_key);
2513  SCJbOpenArray(ctx.js, "tcp_session");
2515  SCJbAppendString(ctx.js, "setup");
2517  SCJbAppendString(ctx.js, "established");
2519  SCJbAppendString(ctx.js, "closing");
2520  SCJbClose(ctx.js); // tcp_session
2521  SCJbClose(ctx.js); // sid_key
2522  }
2523  break;
2524  }
2525  if (smd->is_last)
2526  break;
2527  smd++;
2528  }
2529  }
2530  SCJbClose(ctx.js); // keyword_info
2531 
2532  SCJbClose(ctx.js); // top level object
2533 
2534  const char *filename = "firewall.json";
2535  const char *log_dir = SCConfigGetLogDirectory();
2536  char json_path[PATH_MAX] = "";
2537  snprintf(json_path, sizeof(json_path), "%s/%s", log_dir, filename);
2538 
2540  FILE *fp = fopen(json_path, "w");
2541  if (fp != NULL) {
2542  fwrite(SCJbPtr(ctx.js), SCJbLen(ctx.js), 1, fp);
2543  fprintf(fp, "\n");
2544  fclose(fp);
2545  }
2547  SCJbFree(ctx.js);
2548  return 0;
2549 }
detect-tcp-flags.h
DETECT_PCRE_CASELESS
#define DETECT_PCRE_CASELESS
Definition: detect-pcre.h:32
SCJsonBuilder
struct SCJsonBuilder SCJsonBuilder
Definition: detect-engine-helper.h:83
DETECT_CONTENT_NOCASE
#define DETECT_CONTENT_NOCASE
Definition: detect-content.h:29
SignatureHasPacketContent
int SignatureHasPacketContent(const Signature *s)
check if a signature has patterns that are to be inspected against a packets payload (as opposed to t...
Definition: detect-engine-mpm.c:878
DetectBytejumpData_::post_offset
int32_t post_offset
Definition: detect-bytejump.h:52
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:56
SIG_TYPE_STREAM
@ SIG_TYPE_STREAM
Definition: detect.h:75
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:107
DetectBytetestData_::flags
uint16_t flags
Definition: detect-bytetest.h:58
detect-engine-uint.h
DetectFirewallPolicies
Definition: detect.h:962
DetectPatternTracker
Definition: detect.h:838
SignatureInitData_::rule_state_dependant_sids_idx
uint32_t rule_state_dependant_sids_idx
Definition: detect.h:683
DetectEngineAppInspectionEngine_
Definition: detect.h:420
DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_RELATIVE_NEXT
Definition: detect-content.h:66
DetectEngineAppInspectionEngine_::mpm
bool mpm
Definition: detect.h:424
DETECT_TTL
@ DETECT_TTL
Definition: detect-engine-register.h:45
detect-content.h
DetectFlowbitsData_::or_list_size
uint8_t or_list_size
Definition: detect-flowbits.h:68
len
uint8_t len
Definition: app-layer-dnp3.h:2
DetectEngineAppInspectionEngine_::v2
struct DetectEngineAppInspectionEngine_::@82 v2
SCConfValIsTrue
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:577
detect-engine.h
detect-app-layer-protocol.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:120
SIG_MASK_REQUIRE_REAL_PKT
#define SIG_MASK_REQUIRE_REAL_PKT
Definition: detect.h:320
DETECT_CONTENT_FAST_PATTERN_CHOP
#define DETECT_CONTENT_FAST_PATTERN_CHOP
Definition: detect-content.h:36
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:666
DetectContentData_::fp_chop_len
uint16_t fp_chop_len
Definition: detect-content.h:98
SIG_FLAG_FW_HOOK_LTE
#define SIG_FLAG_FW_HOOK_LTE
Definition: detect.h:255
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:78
DetectXbitsData_::expire
uint32_t expire
Definition: detect-xbits.h:45
Signature_::sig_str
char * sig_str
Definition: detect.h:773
SIG_TYPE_APP_TX
@ SIG_TYPE_APP_TX
Definition: detect.h:78
AppLayerParserGetStateNameById
const char * AppLayerParserGetStateNameById(uint8_t ipproto, AppProto alproto, const int id, const uint8_t direction)
Definition: app-layer-parser.c:1847
DetectFirewallAppPolicy
Definition: detect.h:951
DetectEnginePktInspectionEngine
Definition: detect.h:492
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:446
DetectAppLayerProtocolData_::mode
uint8_t mode
Definition: detect-app-layer-protocol.h:50
DETECT_PROTO_IPV6
#define DETECT_PROTO_IPV6
Definition: detect-engine-proto.h:32
DetectFlowData_
Definition: detect-flow.h:37
DETECT_FLOW_FLAG_NOSTREAM
#define DETECT_FLOW_FLAG_NOSTREAM
Definition: detect-flow.h:33
SigTableElmt_::name
const char * name
Definition: detect.h:1542
DETECT_BYTEJUMP
@ DETECT_BYTEJUMP
Definition: detect-engine-register.h:92
DETECT_ABSENT
@ DETECT_ABSENT
Definition: detect-engine-register.h:104
DetectListToHumanString
const char * DetectListToHumanString(int list)
Definition: detect-parse.c:149
DetectEngineCtx_::pattern_hash_table
HashListTable * pattern_hash_table
Definition: detect.h:1032
DumpPatterns
void DumpPatterns(DetectEngineCtx *de_ctx)
Definition: detect-engine-analyzer.c:1597
FLOWINT_MODIFIER_ADD
@ FLOWINT_MODIFIER_ADD
Definition: detect-flowint.h:31
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectContentData_::within
int32_t within
Definition: detect-content.h:109
ACTION_PASS
#define ACTION_PASS
Definition: action-globals.h:34
ACTION_REJECT
#define ACTION_REJECT
Definition: action-globals.h:31
DETECT_BYTEJUMP_LITTLE
#define DETECT_BYTEJUMP_LITTLE
Definition: detect-bytejump.h:35
SetupEngineAnalysis
void SetupEngineAnalysis(DetectEngineCtx *de_ctx, bool *fp_analysis, bool *rule_analysis)
Definition: detect-engine-analyzer.c:482
Signature_::app_progress_hook
uint8_t app_progress_hook
Definition: detect.h:729
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:78
SignatureInitData_::prefilter_sm
SigMatch * prefilter_sm
Definition: detect.h:642
EngineAnalysisCtx_::rule_engine_analysis_fp
FILE * rule_engine_analysis_fp
Definition: detect-engine-analyzer.c:90
DETECT_FLOW
@ DETECT_FLOW
Definition: detect-engine-register.h:61
Signature_::alproto
AppProto alproto
Definition: detect.h:697
SignatureInitData_::is_rule_state_dependant
bool is_rule_state_dependant
Definition: detect.h:680
detect-isdataat.h
FLOWINT_MODIFIER_NE
@ FLOWINT_MODIFIER_NE
Definition: detect-flowint.h:38
DETECT_BYTETEST_BASE_HEX
#define DETECT_BYTETEST_BASE_HEX
Definition: detect-bytetest.h:40
SigMatchData_::is_last
bool is_last
Definition: detect.h:371
ActionScopeToString
const char * ActionScopeToString(enum ActionScope s)
Definition: detect-parse.c:4185
DetectAppLayerProtocolData_
Per-rule keyword data for app-layer-protocol:.
Definition: detect-app-layer-protocol.h:45
name
const char * name
Definition: detect-engine-proto.c:47
DetectContentPatternPrettyPrint
void DetectContentPatternPrettyPrint(const uint8_t *pat, const uint16_t pat_len, char *str, size_t str_len)
Definition: detect-content.c:742
g_rules_analyzer_write_m
SCMutex g_rules_analyzer_write_m
Definition: detect-engine-analyzer.c:1145
DetectEngineAnalyzerItems::display_name
const char * display_name
Definition: detect-engine-analyzer.c:72
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:87
DETECT_CONTENT_WITHIN2DEPTH
#define DETECT_CONTENT_WITHIN2DEPTH
Definition: detect-content.h:62
EngineAnalysisCtx_::percent_re
pcre2_code * percent_re
Definition: detect-engine-analyzer.c:95
DETECT_SM_LIST_DYNAMIC_START
@ DETECT_SM_LIST_DYNAMIC_START
Definition: detect.h:139
DETECT_FLOWBITS_CMD_ISNOTSET
#define DETECT_FLOWBITS_CMD_ISNOTSET
Definition: detect-flowbits.h:30
SIG_FLAG_DEST_IS_TARGET
#define SIG_FLAG_DEST_IS_TARGET
Definition: detect.h:288
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:372
DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED
#define DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED
Definition: detect-content.h:55
DetectFlowintData_::targettype
uint8_t targettype
Definition: detect-flowint.h:71
AppLayerParserGetStateProgressCompletionStatus
uint8_t AppLayerParserGetStateProgressCompletionStatus(AppProto alproto, uint8_t direction)
Definition: app-layer-parser.c:1226
action-globals.h
Packet_::flags
uint32_t flags
Definition: decode.h:562
Packet_::action
uint8_t action
Definition: decode.h:624
EngineAnalysisCtx_
Definition: detect-engine-analyzer.c:88
DETECT_IPOPTS
@ DETECT_IPOPTS
Definition: detect-engine-register.h:39
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its normalized string equivalent.
Definition: app-layer-protos.c:53
detect-tcp-session.h
tcp.session: keyword (Redmine #7704).
DetectFirewallAppPolicy::sub_state
uint8_t sub_state
Definition: detect.h:953
ctx
struct Thresholds ctx
DETECT_BYTEJUMP_BASE_OCT
#define DETECT_BYTEJUMP_BASE_OCT
Definition: detect-bytejump.h:29
DetectEngineFrameInspectionEngine::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:527
DetectFlowData_::flags
uint16_t flags
Definition: detect-flow.h:38
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:995
DETECT_PROTO_ANY
#define DETECT_PROTO_ANY
Definition: detect-engine-proto.h:28
DetectFlowintData_
Definition: detect-flowint.h:61
DetectXbitsData_::cmd
uint8_t cmd
Definition: detect-xbits.h:43
DetectEnginePktInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:493
SIG_TYPE_PKT_STREAM
@ SIG_TYPE_PKT_STREAM
Definition: detect.h:74
DetectFlowbitsData_::cmd
uint8_t cmd
Definition: detect-flowbits.h:67
DetectFirewallAppPolicy::policy
struct DetectFirewallPolicy policy
Definition: detect.h:956
DetectEngineFrameInspectionEngine::mpm
bool mpm
Definition: detect.h:521
DETECT_BYTETEST_DCE
#define DETECT_BYTETEST_DCE
Definition: detect-bytetest.h:47
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:286
detect-tcp-seq.h
EngineAnalysisCtx_::fp_pattern_stats
FpPatternStats fp_pattern_stats[DETECT_SM_LIST_MAX]
Definition: detect-engine-analyzer.c:107
DetectAppLayerProtocolModeName
const char * DetectAppLayerProtocolModeName(uint8_t mode)
Map a DETECT_ALPROTO_* mode value to its textual qualifier.
Definition: detect-app-layer-protocol.c:195
detect-flowint.h
DetectEngineBufferTypeGetNameById
const char * DetectEngineBufferTypeGetNameById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1482
SIG_FLAG_DST_ANY
#define SIG_FLAG_DST_ANY
Definition: detect.h:245
ACTION_SCOPE_FLOW
@ ACTION_SCOPE_FLOW
Definition: action-globals.h:45
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
util-var-name.h
SIG_FLAG_REQUIRE_STREAM
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:258
DETECT_XBITS_TRACK_IPDST
#define DETECT_XBITS_TRACK_IPDST
Definition: detect-xbits.h:35
rust.h
EngineAnalysisCtx_::fp_engine_analysis_fp
FILE * fp_engine_analysis_fp
Definition: detect-engine-analyzer.c:91
SCConfGetBool
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:523
EngineAnalysisCtx_::analyzer_initialized
bool analyzer_initialized
Definition: detect-engine-analyzer.c:114
ACTION_REJECT_ANY
#define ACTION_REJECT_ANY
Definition: action-globals.h:38
DetectEngineAnalyzerItems
Definition: detect-engine-analyzer.c:66
DETECT_BYTEJUMP_DCE
#define DETECT_BYTEJUMP_DCE
Definition: detect-bytejump.h:40
VarNameStoreSetupLookup
const char * VarNameStoreSetupLookup(const uint32_t id, const enum VarTypes type)
Definition: util-var-name.c:192
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:122
p
Packet * p
Definition: fuzz_dataset.c:30
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:759
FpPatternStats_::max
uint16_t max
Definition: detect-engine-analyzer.c:77
SignatureInitData_::init_flags
uint32_t init_flags
Definition: detect.h:625
DetectBufferType_
Definition: detect.h:454
DetectContentData_
Definition: detect-content.h:93
DETECT_FLOWBITS_CMD_ISSET
#define DETECT_FLOWBITS_CMD_ISSET
Definition: detect-flowbits.h:31
DetectPcreData_::flags
uint16_t flags
Definition: detect-pcre.h:52
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:877
DetectContentData_::fp_chop_offset
uint16_t fp_chop_offset
Definition: detect-content.h:100
DetectBytetestData_::nbytes
uint8_t nbytes
Definition: detect-bytetest.h:54
DetectBytetestData_
Definition: detect-bytetest.h:53
EngineAnalysisCtx_::analyzer_item_map
int16_t analyzer_item_map[256]
Definition: detect-engine-analyzer.c:106
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:275
DETECT_BYTEJUMP_BIG
#define DETECT_BYTEJUMP_BIG
Definition: detect-bytejump.h:36
SIG_FLAG_SRC_ANY
#define SIG_FLAG_SRC_ANY
Definition: detect.h:244
EngineAnalysisRulesFailure
void EngineAnalysisRulesFailure(const DetectEngineCtx *de_ctx, const char *line, const char *file, int lineno)
Definition: detect-engine-analyzer.c:630
SigMatchData_
Data needed for Match()
Definition: detect.h:369
DetectBytejumpData_::base
uint8_t base
Definition: detect-bytejump.h:49
detect-pcre.h
SIG_TYPE_APPLAYER
@ SIG_TYPE_APPLAYER
Definition: detect.h:77
SigMatchData_::type
uint16_t type
Definition: detect.h:370
DetectBytejumpData_
Definition: detect-bytejump.h:47
DetectXbitsData_
Definition: detect-xbits.h:41
DETECT_FLOW_ELEPHANT
@ DETECT_FLOW_ELEPHANT
Definition: detect-engine-register.h:145
Signature_::frame_inspect
DetectEngineFrameInspectionEngine * frame_inspect
Definition: detect.h:755
DetectBytejumpData_::offset
int32_t offset
Definition: detect-bytejump.h:51
DetectEnginePktInspectionEngine::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:501
EngineAnalysisCtx_::analyzer_items
DetectEngineAnalyzerItems * analyzer_items
Definition: detect-engine-analyzer.c:93
DETECT_PERCENT_ENCODING_REGEX
#define DETECT_PERCENT_ENCODING_REGEX
FirewallAnalyzer
int FirewallAnalyzer(const DetectEngineCtx *de_ctx)
Definition: detect-engine-analyzer.c:2278
DetectBytejumpData_::multiplier
uint16_t multiplier
Definition: detect-bytejump.h:55
SIG_FLAG_APPLAYER
#define SIG_FLAG_APPLAYER
Definition: detect.h:252
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1452
DetectAppLayerProtocolGetValues
uint16_t DetectAppLayerProtocolGetValues(const DetectAppLayerProtocolData *data, AppProto *out, uint16_t max)
Fill out[] with the keyword's set protocol values.
Definition: detect-app-layer-protocol.c:216
SIG_FLAG_FIREWALL
#define SIG_FLAG_FIREWALL
Definition: detect.h:249
Signature_::gid
uint32_t gid
Definition: detect.h:742
DetectFlowintData_::idx
uint32_t idx
Definition: detect-flowint.h:66
DetectFirewallAppGenericHookName
const char * DetectFirewallAppGenericHookName(const uint8_t state, const uint8_t complete_state, const int direction)
Generic start/complete hook alias for an app progress state, in config form (hyphens),...
Definition: detect-parse.c:1196
Signature_::next
struct Signature_ * next
Definition: detect.h:778
ACTION_REJECT_DST
#define ACTION_REJECT_DST
Definition: action-globals.h:32
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:428
ATTR_FMT_PRINTF
#define ATTR_FMT_PRINTF(x, y)
Definition: suricata-common.h:432
DetectFlowbitsData_
Definition: detect-flowbits.h:65
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:55
DETECT_APP_LAYER_PROTOCOL
@ DETECT_APP_LAYER_PROTOCOL
Definition: detect-engine-register.h:35
DetectEngineAnalyzerItems::export_item_seen
bool export_item_seen
Definition: detect-engine-analyzer.c:69
SignaturePropertyFlowAction
SignaturePropertyFlowAction
Definition: detect.h:84
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:274
detect-xbits.h
DETECT_XBITS_CMD_ISNOTSET
#define DETECT_XBITS_CMD_ISNOTSET
Definition: detect-xbits.h:30
DETECT_BYTETEST_RELATIVE
#define DETECT_BYTETEST_RELATIVE
Definition: detect-bytetest.h:46
SIG_TYPE_PKT
@ SIG_TYPE_PKT
Definition: detect.h:73
feature.h
AppLayerParserGetSubStateCompletion
uint8_t AppLayerParserGetSubStateCompletion(const AppProto alproto, const uint8_t sub_state)
Definition: app-layer-parser.c:1303
RuleAnalyzer::js
SCJsonBuilder * js
Definition: detect-engine-analyzer.c:646
IpOptsFlagToString
const char * IpOptsFlagToString(uint16_t flag)
Return human readable value for ipopts flag.
Definition: detect-ipopts.c:128
JB_SET_STRING
#define JB_SET_STRING(jb, key, val)
Definition: rust.h:36
EngineAnalysisCtx
struct EngineAnalysisCtx_ EngineAnalysisCtx
DetectEngineCtx_::fw_policies
struct DetectFirewallPolicies * fw_policies
Definition: detect.h:1026
DETECT_CONTENT_ENDS_WITH
#define DETECT_CONTENT_ENDS_WITH
Definition: detect-content.h:42
DETECT_PCRE_RAWBYTES
#define DETECT_PCRE_RAWBYTES
Definition: detect-pcre.h:31
DETECT_CONTENT_DISTANCE
#define DETECT_CONTENT_DISTANCE
Definition: detect-content.h:30
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
DetectEnginePktInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:495
SIG_FLAG_INIT_BIDIREC
#define SIG_FLAG_INIT_BIDIREC
Definition: detect.h:296
g_alproto_max
AppProto g_alproto_max
Definition: app-layer-protos.c:32
DETECT_FLOWINT
@ DETECT_FLOWINT
Definition: detect-engine-register.h:71
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
SIG_MASK_REQUIRE_ENGINE_EVENT
#define SIG_MASK_REQUIRE_ENGINE_EVENT
Definition: detect.h:322
DETECT_ICODE
@ DETECT_ICODE
Definition: detect-engine-register.h:48
DETECT_FLOW_AGE
@ DETECT_FLOW_AGE
Definition: detect-engine-register.h:138
DETECT_BYTETEST_BASE_UNSET
#define DETECT_BYTETEST_BASE_UNSET
Definition: detect-bytetest.h:37
SIG_TYPE_IPONLY
@ SIG_TYPE_IPONLY
Definition: detect.h:67
FLOWINT_TARGET_VAL
@ FLOWINT_TARGET_VAL
Definition: detect-flowint.h:50
DETECT_BYTEJUMP_ALIGN
#define DETECT_BYTEJUMP_ALIGN
Definition: detect-bytejump.h:39
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:640
DetectEngineBufferTypeGetDescriptionById
const char * DetectEngineBufferTypeGetDescriptionById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1580
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
SIG_FLAG_FLUSH
#define SIG_FLAG_FLUSH
Definition: detect.h:262
DetectIpOptsData_::ipopt
uint16_t ipopt
Definition: detect-ipopts.h:38
SignatureInitData_::mpm_sm_list
int mpm_sm_list
Definition: detect.h:638
DETECT_BYTETEST_BASE_DEC
#define DETECT_BYTETEST_BASE_DEC
Definition: detect-bytetest.h:39
SIG_MASK_REQUIRE_FLOW
#define SIG_MASK_REQUIRE_FLOW
Definition: detect.h:316
SIG_FLAG_BYPASS
#define SIG_FLAG_BYPASS
Definition: detect.h:279
DETECT_CONTENT_DEPTH
#define DETECT_CONTENT_DEPTH
Definition: detect-content.h:33
DETECT_CONTENT_DISTANCE2OFFSET
#define DETECT_CONTENT_DISTANCE2OFFSET
Definition: detect-content.h:63
RuleAnalyzer
Definition: detect-engine-analyzer.c:645
DETECT_BYTEJUMP_END
#define DETECT_BYTEJUMP_END
Definition: detect-bytejump.h:42
Signature_::pkt_inspect
DetectEnginePktInspectionEngine * pkt_inspect
Definition: detect.h:754
DetectEngineAnalyzerItems
struct DetectEngineAnalyzerItems DetectEngineAnalyzerItems
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
detect-engine-mpm.h
HashTableLookup
void * HashTableLookup(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:193
detect.h
SIG_MASK_REQUIRE_FLAGS_INITDEINIT
#define SIG_MASK_REQUIRE_FLAGS_INITDEINIT
Definition: detect.h:317
SignatureInitData_::rule_state_flowbits_ids_size
uint32_t rule_state_flowbits_ids_size
Definition: detect.h:685
DETECT_TCP_SESSION
@ DETECT_TCP_SESSION
Definition: detect-engine-register.h:64
DetectEngineFrameInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:522
DETECT_XBITS_TRACK_IPPAIR
#define DETECT_XBITS_TRACK_IPPAIR
Definition: detect-xbits.h:36
detect-tcp-window.h
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:364
DetectFirewallPolicies::pkt
struct DetectFirewallPolicy pkt[DETECT_FIREWALL_POLICY_SIZE]
Definition: detect.h:964
DetectEngineAnalyzerItems::item_seen
bool item_seen
Definition: detect-engine-analyzer.c:68
DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_NEGATED
Definition: detect-content.h:40
SignatureInitData_::proto
DetectProto proto
Definition: detect.h:655
DetectU8Data
DetectUintData_u8 DetectU8Data
Definition: detect-engine-uint.h:43
DETECT_ICMP_ID
@ DETECT_ICMP_ID
Definition: detect-engine-register.h:49
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:118
EngineAnalysisRules
void EngineAnalysisRules(const DetectEngineCtx *de_ctx, const Signature *s, const char *line)
Prints analysis of loaded rules.
Definition: detect-engine-analyzer.c:1745
app-layer-parser.h
Signature_::app_inspect
DetectEngineAppInspectionEngine * app_inspect
Definition: detect.h:753
DETECT_XBITS
@ DETECT_XBITS
Definition: detect-engine-register.h:73
DETECT_SEQ
@ DETECT_SEQ
Definition: detect-engine-register.h:37
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:363
DETECT_TCP_SESSION_PHASE_SETUP
#define DETECT_TCP_SESSION_PHASE_SETUP
Definition: detect-tcp-session.h:29
DETECT_ACK
@ DETECT_ACK
Definition: detect-engine-register.h:36
RuleAnalyzer::js_warnings
SCJsonBuilder * js_warnings
Definition: detect-engine-analyzer.c:648
SIG_FLAG_REQUIRE_FLOWVAR
#define SIG_FLAG_REQUIRE_FLOWVAR
Definition: detect.h:270
Signature_::action
uint8_t action
Definition: detect.h:707
FpPatternStats_::cnt
uint32_t cnt
Definition: detect-engine-analyzer.c:78
DetectXbitsData_::type
enum VarTypes type
Definition: detect-xbits.h:47
SCReturn
#define SCReturn
Definition: util-debug.h:286
Signature_::flags
uint32_t flags
Definition: detect.h:693
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:106
DetectEngineFrameInspectionEngine::v1
struct DetectEngineFrameInspectionEngine::@86 v1
ACTION_ALERT
#define ACTION_ALERT
Definition: action-globals.h:29
DETECT_BYTETEST_BIG
#define DETECT_BYTETEST_BIG
Definition: detect-bytetest.h:44
FLOWINT_MODIFIER_LE
@ FLOWINT_MODIFIER_LE
Definition: detect-flowint.h:36
SCLocalTime
struct tm * SCLocalTime(time_t timep, struct tm *result)
Definition: util-time.c:267
DetectTcpSessionData_::phase_flags
uint8_t phase_flags
Definition: detect-tcp-session.h:34
detect-bytejump.h
ACTION_SCOPE_TX
@ ACTION_SCOPE_TX
Definition: action-globals.h:47
SCConfigGetLogDirectory
const char * SCConfigGetLogDirectory(void)
Definition: util-conf.c:38
ACTION_SCOPE_AUTO
@ ACTION_SCOPE_AUTO
Definition: action-globals.h:43
conf.h
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:104
CHECK
#define CHECK(pat)
Definition: detect-engine-analyzer.c:682
DetectEngineFrameInspectionEngine
Definition: detect.h:517
DetectFlowbitsData_::idx
uint32_t idx
Definition: detect-flowbits.h:66
DetectEngineBufferTypeGetById
const DetectBufferType * DetectEngineBufferTypeGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1472
DETECT_BYTEJUMP_BASE_UNSET
#define DETECT_BYTEJUMP_BASE_UNSET
Definition: detect-bytejump.h:28
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:775
DetectFlowintData_::modifier
uint8_t modifier
Definition: detect-flowint.h:70
SIG_FLAG_SRC_IS_TARGET
#define SIG_FLAG_SRC_IS_TARGET
Definition: detect.h:286
SignatureInitData_::rule_state_dependant_sids_array
uint32_t * rule_state_dependant_sids_array
Definition: detect.h:681
fp_engine_analysis_set
bool fp_engine_analysis_set
Definition: fuzz_siginit.c:25
SignatureInitData_::rule_state_dependant_sids_size
uint32_t rule_state_dependant_sids_size
Definition: detect.h:682
DETECT_PCRE_HAS_UNICODE_CLUSTER
#define DETECT_PCRE_HAS_UNICODE_CLUSTER
Definition: detect-pcre.h:36
DetectEngineTransforms::transforms
TransformData transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:396
DETECT_BYTEJUMP_BASE_HEX
#define DETECT_BYTEJUMP_BASE_HEX
Definition: detect-bytejump.h:31
DetectTcpSessionData_
Definition: detect-tcp-session.h:33
SIG_TYPE_DEONLY
@ SIG_TYPE_DEONLY
Definition: detect.h:72
SIG_PROP_FLOW_ACTION_PACKET
@ SIG_PROP_FLOW_ACTION_PACKET
Definition: detect.h:85
signature_properties
const struct SignatureProperties signature_properties[SIG_TYPE_MAX]
Definition: detect-engine.c:118
detect-flowbits.h
SIG_MASK_REQUIRE_PAYLOAD
#define SIG_MASK_REQUIRE_PAYLOAD
Definition: detect.h:315
DETECT_TCP_SESSION_PHASE_ESTABLISHED
#define DETECT_TCP_SESSION_PHASE_ESTABLISHED
Definition: detect-tcp-session.h:30
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:232
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:80
DETECT_DSIZE
@ DETECT_DSIZE
Definition: detect-engine-register.h:59
SIG_TYPE_NOT_SET
@ SIG_TYPE_NOT_SET
Definition: detect.h:66
ExposedItemSeen::bufname
const char * bufname
Definition: detect-engine-analyzer.c:84
DETECT_BYTEJUMP_OFFSET_BE
#define DETECT_BYTEJUMP_OFFSET_BE
Definition: detect-bytejump.h:41
FLOWINT_MODIFIER_GT
@ FLOWINT_MODIFIER_GT
Definition: detect-flowint.h:40
detect-ttl.h
DetectEngineCtx_::config_prefix
char config_prefix[64]
Definition: detect.h:1121
DetectSigmatchListEnumToString
const char * DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type)
Definition: detect-engine.c:5298
analyzer_items
const DetectEngineAnalyzerItems analyzer_items[]
Definition: detect-engine-analyzer.c:117
DetectEngineAppInspectionEngine_::alproto
AppProto alproto
Definition: detect.h:421
SIG_FLAG_MPM_NEG
#define SIG_FLAG_MPM_NEG
Definition: detect.h:260
detect-engine-analyzer.h
SIG_FLAG_INIT_STATE_MATCH
#define SIG_FLAG_INIT_STATE_MATCH
Definition: detect.h:300
DetectEngineAnalyzerItems::item_id
int16_t item_id
Definition: detect-engine-analyzer.c:67
DETECT_XBITS_TRACK_TX
#define DETECT_XBITS_TRACK_TX
Definition: detect-xbits.h:37
DetectEngineAppInspectionEngine_::smd
SigMatchData * smd
Definition: detect.h:444
EngineAnalysisRules2
void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
Definition: detect-engine-analyzer.c:1146
ACTION_REJECT_BOTH
#define ACTION_REJECT_BOTH
Definition: action-globals.h:33
FLOWINT_MODIFIER_LT
@ FLOWINT_MODIFIER_LT
Definition: detect-flowint.h:35
DetectFlowintData_::target
union DetectFlowintData_::@68 target
ARRAY_SIZE
#define ARRAY_SIZE(arr)
Definition: suricata-common.h:563
DETECT_CONTENT_STARTS_WITH
#define DETECT_CONTENT_STARTS_WITH
Definition: detect-content.h:59
DetectProto_::flags
uint8_t flags
Definition: detect-engine-proto.h:40
DETECT_BYTETEST
@ DETECT_BYTETEST
Definition: detect-engine-register.h:91
DETECT_PROTO_IPV4
#define DETECT_PROTO_IPV4
Definition: detect-engine-proto.h:31
util-conf.h
DETECT_TCP_SESSION_PHASE_CLOSING
#define DETECT_TCP_SESSION_PHASE_CLOSING
Definition: detect-tcp-session.h:31
SignatureHasStreamContent
int SignatureHasStreamContent(const Signature *s)
check if a signature has patterns that are to be inspected against the stream payload (as opposed to ...
Definition: detect-engine-mpm.c:908
FpPatternStats_::min
uint16_t min
Definition: detect-engine-analyzer.c:76
VAR_TYPE_FLOW_BIT
@ VAR_TYPE_FLOW_BIT
Definition: util-var.h:36
FLOWINT_TARGET_VAR
@ FLOWINT_TARGET_VAR
Definition: detect-flowint.h:51
suricata-common.h
SIG_MASK_REQUIRE_NO_PAYLOAD
#define SIG_MASK_REQUIRE_NO_PAYLOAD
Definition: detect.h:319
FLOWINT_MODIFIER_SET
@ FLOWINT_MODIFIER_SET
Definition: detect-flowint.h:30
DetectEnginePktInspectionEngine::v1
struct DetectEnginePktInspectionEngine::@85 v1
SIG_FLAG_SP_ANY
#define SIG_FLAG_SP_ANY
Definition: detect.h:246
SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL
@ SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL
Definition: detect.h:87
ActionScope
ActionScope
Definition: action-globals.h:42
FLOWINT_MODIFIER_ISSET
@ FLOWINT_MODIFIER_ISSET
Definition: detect-flowint.h:42
DetectAbsentData_
Definition: detect-isdataat.h:37
ExposedItemSeen
Definition: detect-engine-analyzer.c:83
SigMatch_::type
uint16_t type
Definition: detect.h:361
DETECT_FIREWALL_POLICY_PACKET_FILTER
@ DETECT_FIREWALL_POLICY_PACKET_FILTER
Definition: detect.h:939
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:87
DetectEngineAnalyzerItems::check_encoding_match
bool check_encoding_match
Definition: detect-engine-analyzer.c:70
DetectContentData_::distance
int32_t distance
Definition: detect-content.h:108
ACTION_SCOPE_HOOK
@ ACTION_SCOPE_HOOK
Definition: action-globals.h:46
CleanupEngineAnalysis
void CleanupEngineAnalysis(DetectEngineCtx *de_ctx)
Definition: detect-engine-analyzer.c:518
DetectBytejumpData_::nbytes
uint8_t nbytes
Definition: detect-bytejump.h:48
Signature_::action_scope
uint8_t action_scope
Definition: detect.h:714
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:36
DetectEngineFrameInspectionEngine::next
struct DetectEngineFrameInspectionEngine * next
Definition: detect.h:530
DetectU32Data
DetectUintData_u32 DetectU32Data
Definition: detect-engine-uint.h:41
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
DetectEnginePktInspectionEngine::next
struct DetectEnginePktInspectionEngine * next
Definition: detect.h:503
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:94
DetectXbitsData_::idx
uint32_t idx
Definition: detect-xbits.h:42
Signature_::rev
uint32_t rev
Definition: detect.h:743
AppLayerParserGetSubStateProgressName
const char * AppLayerParserGetSubStateProgressName(const AppProto alproto, const uint8_t sub_state, const uint8_t state, const uint8_t dir_flag)
Definition: app-layer-parser.c:1277
Signature_::proto
DetectProto * proto
Definition: detect.h:711
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
FatalError
#define FatalError(...)
Definition: util-debug.h:517
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:1005
DETECT_BYTEJUMP_BASE_DEC
#define DETECT_BYTEJUMP_BASE_DEC
Definition: detect-bytejump.h:30
DetectIpOptsData_
Definition: detect-ipopts.h:37
ACTION_CONFIG
#define ACTION_CONFIG
Definition: action-globals.h:35
PrintRawUriFp
void PrintRawUriFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:69
SIG_MASK_REQUIRE_FLAGS_UNUSUAL
#define SIG_MASK_REQUIRE_FLAGS_UNUSUAL
Definition: detect.h:318
TransformData_::transform
int transform
Definition: detect.h:391
FLOWINT_MODIFIER_ISNOTSET
@ FLOWINT_MODIFIER_ISNOTSET
Definition: detect-flowint.h:43
DETECT_FLOWBITS
@ DETECT_FLOWBITS
Definition: detect-engine-register.h:68
SIG_TYPE_MAX
@ SIG_TYPE_MAX
Definition: detect.h:80
DetectEngineCtx_::ea
struct EngineAnalysisCtx_ * ea
Definition: detect.h:1199
DETECT_BYTETEST_BASE_OCT
#define DETECT_BYTETEST_BASE_OCT
Definition: detect-bytetest.h:38
util-validate.h
detect-flow.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
EngineAnalysisFP
void EngineAnalysisFP(const DetectEngineCtx *de_ctx, const Signature *s, const char *line)
Definition: detect-engine-analyzer.c:174
SignatureInitData_::firewall_rule
bool firewall_rule
Definition: detect.h:688
FpPatternStats
struct FpPatternStats_ FpPatternStats
detect-tcp-ack.h
DetectXbitsData_::tracker
uint8_t tracker
Definition: detect-xbits.h:44
str
#define str(s)
Definition: suricata-common.h:313
DetectFirewallPolicy
Definition: detect.h:946
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:183
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SigMatchListSMBelongsTo
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
Definition: detect-parse.c:799
SCFree
#define SCFree(p)
Definition: util-mem.h:61
AppLayerParserGetSubStateName
const char * AppLayerParserGetSubStateName(const AppProto alproto, const uint8_t sub_state)
Definition: app-layer-parser.c:1326
DetectFlowbitsData_::or_list
uint32_t * or_list
Definition: detect-flowbits.h:72
DetectEngineAppInspectionEngine_::sub_state
uint8_t sub_state
Definition: detect.h:431
Signature_::id
uint32_t id
Definition: detect.h:741
DETECT_CONTENT_OFFSET
#define DETECT_CONTENT_OFFSET
Definition: detect-content.h:32
HashListTableBucket_
Definition: util-hashlist.h:28
DETECT_XBITS_TRACK_IPSRC
#define DETECT_XBITS_TRACK_IPSRC
Definition: detect-xbits.h:34
DETECT_FLOWBITS_CMD_UNSET
#define DETECT_FLOWBITS_CMD_UNSET
Definition: detect-flowbits.h:29
DETECT_CONTENT_FAST_PATTERN_ONLY
#define DETECT_CONTENT_FAST_PATTERN_ONLY
Definition: detect-content.h:35
DETECT_CONTENT_MPM
#define DETECT_CONTENT_MPM
Definition: detect-content.h:61
ACTION_SCOPE_PACKET
@ ACTION_SCOPE_PACKET
Definition: action-globals.h:44
DetectBufferType_::transforms
DetectEngineTransforms transforms
Definition: detect.h:471
detect-parse.h
Signature_
Signature container.
Definition: detect.h:692
SigMatch_
a single match condition for a signature
Definition: detect.h:360
DetectEngineAppInspectionEngine_::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:441
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:136
SCRequiresFeature
bool SCRequiresFeature(const char *feature_name)
Definition: feature.c:121
FpPatternStats_::tot
uint64_t tot
Definition: detect-engine-analyzer.c:79
DetectFlowintData_::tvar
TargetVar tvar
Definition: detect-flowint.h:77
DETECT_XBITS_CMD_ISSET
#define DETECT_XBITS_CMD_ISSET
Definition: detect-xbits.h:31
DETECT_BYTETEST_STRING
#define DETECT_BYTETEST_STRING
Definition: detect-bytetest.h:45
DetectBytetestData_::offset
int32_t offset
Definition: detect-bytetest.h:60
VAR_TYPE_FLOW_INT
@ VAR_TYPE_FLOW_INT
Definition: util-var.h:37
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
DETECT_PCRE_RELATIVE_NEXT
#define DETECT_PCRE_RELATIVE_NEXT
Definition: detect-pcre.h:34
detect-icmp-id.h
ACTION_ACCEPT
#define ACTION_ACCEPT
Definition: action-globals.h:36
DetectAppLayerProtocolData_::negated
bool negated
Definition: detect-app-layer-protocol.h:47
detect-ipopts.h
suricata.h
DetectPcreData_
Definition: detect-pcre.h:48
DetectEngineAppInspectionEngine_::dir
uint8_t dir
Definition: detect.h:422
DetectEngineAnalyzerItems::item_name
const char * item_name
Definition: detect-engine-analyzer.c:71
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:95
ExposedItemSeen::item_seen_ptr
bool * item_seen_ptr
Definition: detect-engine-analyzer.c:85
DETECT_BYTEJUMP_STRING
#define DETECT_BYTEJUMP_STRING
Definition: detect-bytejump.h:37
DetectEngineCtx_::buffer_type_id
uint32_t buffer_type_id
Definition: detect.h:1151
AppLayerParserGetMaxSubState
uint8_t AppLayerParserGetMaxSubState(const AppProto alproto)
Definition: app-layer-parser.c:1349
EngineAnalysisCtx_::file_prefix
char * file_prefix
Definition: detect-engine-analyzer.c:94
DETECT_XBITS_CMD_SET
#define DETECT_XBITS_CMD_SET
Definition: detect-xbits.h:27
DetectEnginePktInspectionEngine::mpm
bool mpm
Definition: detect.h:494
DETECT_BYTEJUMP_BEGIN
#define DETECT_BYTEJUMP_BEGIN
Definition: detect-bytejump.h:34
SignatureInitData_::rule_state_flowbits_ids_array
uint32_t * rule_state_flowbits_ids_array
Definition: detect.h:684
AppLayerParserSupportsSubStates
bool AppLayerParserSupportsSubStates(const AppProto alproto)
Definition: app-layer-parser.c:1356
SIG_PROP_FLOW_ACTION_FLOW
@ SIG_PROP_FLOW_ACTION_FLOW
Definition: detect.h:86
DETECT_PCRE_RELATIVE
#define DETECT_PCRE_RELATIVE
Definition: detect-pcre.h:29
TargetVar_::name
char * name
Definition: detect-flowint.h:57
DetectFirewallAppPolicy::alproto
AppProto alproto
Definition: detect.h:952
DetectFirewallPolicies::app_policies
HashTable * app_policies
Definition: detect.h:968
FLOWINT_MODIFIER_EQ
@ FLOWINT_MODIFIER_EQ
Definition: detect-flowint.h:37
RuleAnalyzer
struct RuleAnalyzer RuleAnalyzer
DETECT_WINDOW
@ DETECT_WINDOW
Definition: detect-engine-register.h:38
SIG_FLAG_TLSSTORE
#define SIG_FLAG_TLSSTORE
Definition: detect.h:277
DETECT_XBITS_CMD_TOGGLE
#define DETECT_XBITS_CMD_TOGGLE
Definition: detect-xbits.h:28
DetectU16Data
DetectUintData_u16 DetectU16Data
Definition: detect-engine-uint.h:42
Signature_::msg
char * msg
Definition: detect.h:764
DETECT_XBITS_CMD_UNSET
#define DETECT_XBITS_CMD_UNSET
Definition: detect-xbits.h:29
DETECT_CONTENT_FAST_PATTERN
#define DETECT_CONTENT_FAST_PATTERN
Definition: detect-content.h:34
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DetectAbsentData_::or_else
bool or_else
Definition: detect-isdataat.h:39
RuleAnalyzer::js_notes
SCJsonBuilder * js_notes
Definition: detect-engine-analyzer.c:649
DETECT_FLAGS
@ DETECT_FLAGS
Definition: detect-engine-register.h:42
DETECT_PCRE_NEGATE
#define DETECT_PCRE_NEGATE
Definition: detect-pcre.h:35
EngineAnalysisCtx_::exposed_item_seen_list
struct ExposedItemSeen exposed_item_seen_list[2]
Definition: detect-engine-analyzer.c:112
Signature_::type
enum SignatureType type
Definition: detect.h:695
SCConfNode_
Definition: conf.h:37
FpPatternStats_
Definition: detect-engine-analyzer.c:75
DetectBytetestData_::base
uint8_t base
Definition: detect-bytetest.h:56
DetectFirewallAppPolicy::direction
uint8_t direction
Definition: detect.h:955
FLOWINT_MODIFIER_SUB
@ FLOWINT_MODIFIER_SUB
Definition: detect-flowint.h:32
DETECT_BYTETEST_LITTLE
#define DETECT_BYTETEST_LITTLE
Definition: detect-bytetest.h:43
SCMutex
#define SCMutex
Definition: threads-debug.h:114
SIG_TYPE_PDONLY
@ SIG_TYPE_PDONLY
Definition: detect.h:71
DetectEngineTransforms::cnt
uint8_t cnt
Definition: detect.h:397
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
SIG_FLAG_PREFILTER
#define SIG_FLAG_PREFILTER
Definition: detect.h:281
SignatureProperties::flow_action
enum SignaturePropertyFlowAction flow_action
Definition: detect.h:91
DETECT_TCPMSS
@ DETECT_TCPMSS
Definition: detect-engine-register.h:273
SIG_FLAG_FILESTORE
#define SIG_FLAG_FILESTORE
Definition: detect.h:272
DETECT_CONTENT_WITHIN
#define DETECT_CONTENT_WITHIN
Definition: detect-content.h:31
DETECT_BYTEJUMP_RELATIVE
#define DETECT_BYTEJUMP_RELATIVE
Definition: detect-bytejump.h:38
SIG_FLAG_DP_ANY
#define SIG_FLAG_DP_ANY
Definition: detect.h:247
DETECT_FLOWBITS_CMD_SET
#define DETECT_FLOWBITS_CMD_SET
Definition: detect-flowbits.h:28
SIG_FLAG_DSIZE
#define SIG_FLAG_DSIZE
Definition: detect.h:251
FLOWINT_MODIFIER_GE
@ FLOWINT_MODIFIER_GE
Definition: detect-flowint.h:39
DetectBytejumpData_::flags
uint16_t flags
Definition: detect-bytejump.h:50
Signature_::mask
SignatureMask mask
Definition: detect.h:703
SIG_TYPE_LIKE_IPONLY
@ SIG_TYPE_LIKE_IPONLY
Definition: detect.h:68
DetectEngineAppInspectionEngine_::progress
uint8_t progress
Definition: detect.h:430
detect-bytetest.h
DetectFlowintData_::value
uint32_t value
Definition: detect-flowint.h:75
f
Flow f
Definition: fuzz_dataset.c:32
DetectProtoContainsProto
int DetectProtoContainsProto(const DetectProto *dp, int proto)
see if a DetectProto contains a certain proto
Definition: detect-engine-proto.c:114
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:257
DetectEngineFrameInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:529