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-tcp-flags.h"
45 #include "detect-tcp-ack.h"
46 #include "detect-ipopts.h"
47 #include "detect-tcp-seq.h"
48 #include "feature.h"
49 #include "util-print.h"
50 #include "util-time.h"
51 #include "util-validate.h"
52 #include "util-conf.h"
53 #include "detect-flowbits.h"
54 #include "util-var-name.h"
55 #include "detect-icmp-id.h"
56 #include "detect-tcp-window.h"
57 
58 static int rule_warnings_only = 0;
59 
60 /* Details for each buffer being tracked */
61 typedef struct DetectEngineAnalyzerItems {
62  int16_t item_id;
63  bool item_seen;
66  const char *item_name;
67  const char *display_name;
69 
70 typedef struct FpPatternStats_ {
71  uint16_t min;
72  uint16_t max;
73  uint32_t cnt;
74  uint64_t tot;
76 
77 /* Track which items require the item_seen value to be exposed */
79  const char *bufname;
81 };
82 
83 typedef struct EngineAnalysisCtx_ {
84 
87 
89  char *file_prefix;
90  pcre2_code *percent_re;
91 
92  /*
93  * This array contains the map between the `analyzer_items` array listed above and
94  * the item ids returned by DetectBufferTypeGetByName. Iterating signature's sigmatch
95  * array provides list_ids. The map converts those ids into elements of the
96  * analyzer items array.
97  *
98  * Ultimately, the g_buffer_type_hash is searched for each buffer name. The size of that
99  * hashlist is 256, so that's the value we use here.
100  */
101  int16_t analyzer_item_map[256];
103  /*
104  * Certain values must be directly accessible. This array contains items that are directly
105  * accessed when checking if they've been seen or not.
106  */
108 
111 
113  /* request keywords */
114  { 0, false, false, true, "http_uri", "http uri" },
115  { 0, false, false, false, "http_raw_uri", "http raw uri" },
116  { 0, false, true, false, "http_method", "http method" },
117  { 0, false, false, false, "http_request_line", "http request line" },
118  { 0, false, false, false, "http_client_body", "http client body" },
119  { 0, false, false, true, "http_header", "http header" },
120  { 0, false, false, false, "http_raw_header", "http raw header" },
121  { 0, false, false, true, "http_cookie", "http cookie" },
122  { 0, false, false, false, "http_user_agent", "http user agent" },
123  { 0, false, false, false, "http_host", "http host" },
124  { 0, false, false, false, "http_raw_host", "http raw host" },
125  { 0, false, false, false, "http_accept_enc", "http accept enc" },
126  { 0, false, false, false, "http_referer", "http referer" },
127  { 0, false, false, false, "http_content_type", "http content type" },
128  { 0, false, false, false, "http_header_names", "http header names" },
129 
130  /* response keywords not listed above */
131  { 0, false, false, false, "http_stat_msg", "http stat msg" },
132  { 0, false, false, false, "http_stat_code", "http stat code" },
133  { 0, false, true, false, "file_data", "http server body" },
134 
135  /* missing request keywords */
136  { 0, false, false, false, "http_request_line", "http request line" },
137  { 0, false, false, false, "http_accept", "http accept" },
138  { 0, false, false, false, "http_accept_lang", "http accept lang" },
139  { 0, false, false, false, "http_connection", "http connection" },
140  { 0, false, false, false, "http_content_len", "http content len" },
141  { 0, false, false, false, "http_protocol", "http protocol" },
142  { 0, false, false, false, "http_start", "http start" },
143 
144  /* missing response keywords; some of the missing are listed above*/
145  { 0, false, false, false, "http_response_line", "http response line" },
146  { 0, false, false, false, "http.server", "http server" },
147  { 0, false, false, false, "http.location", "http location" },
148 };
149 
150 static void FpPatternStatsAdd(FpPatternStats *fp, int list, uint16_t patlen)
151 {
152  if (list < 0 || list >= DETECT_SM_LIST_MAX)
153  return;
154 
155  FpPatternStats *f = &fp[list];
156 
157  if (f->min == 0)
158  f->min = patlen;
159  else if (patlen < f->min)
160  f->min = patlen;
161 
162  if (patlen > f->max)
163  f->max = patlen;
164 
165  f->cnt++;
166  f->tot += patlen;
167 }
168 
169 void EngineAnalysisFP(const DetectEngineCtx *de_ctx, const Signature *s, const char *line)
170 {
171  int fast_pattern_set = 0;
172  int fast_pattern_only_set = 0;
173  int fast_pattern_chop_set = 0;
174  const DetectContentData *fp_cd = NULL;
175  const SigMatch *mpm_sm = s->init_data->mpm_sm;
176  const int mpm_sm_list = s->init_data->mpm_sm_list;
177 
178  if (mpm_sm != NULL) {
179  fp_cd = (DetectContentData *)mpm_sm->ctx;
180  if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN) {
181  fast_pattern_set = 1;
183  fast_pattern_only_set = 1;
184  } else if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
185  fast_pattern_chop_set = 1;
186  }
187  }
188  }
189 
190  FILE *fp = de_ctx->ea->rule_engine_analysis_fp;
191  fprintf(fp, "== Sid: %u ==\n", s->id);
192  fprintf(fp, "%s\n", line);
193 
194  fprintf(fp, " Fast Pattern analysis:\n");
195  if (s->init_data->prefilter_sm != NULL) {
196  fprintf(fp, " Prefilter on: %s\n",
198  fprintf(fp, "\n");
199  return;
200  }
201 
202  if (fp_cd == NULL) {
203  fprintf(fp, " No content present\n");
204  fprintf(fp, "\n");
205  return;
206  }
207 
208  fprintf(fp, " Fast pattern matcher: ");
209  int list_type = mpm_sm_list;
210  if (list_type == DETECT_SM_LIST_PMATCH)
211  fprintf(fp, "content\n");
212  else {
213  const char *desc = DetectEngineBufferTypeGetDescriptionById(de_ctx, list_type);
214  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, list_type);
215  if (desc && name) {
216  fprintf(fp, "%s (%s)\n", desc, name);
217  }
218  }
219 
220  int flags_set = 0;
221  fprintf(fp, " Flags:");
222  if (fp_cd->flags & DETECT_CONTENT_OFFSET) {
223  fprintf(fp, " Offset");
224  flags_set = 1;
225  } if (fp_cd->flags & DETECT_CONTENT_DEPTH) {
226  fprintf(fp, " Depth");
227  flags_set = 1;
228  }
229  if (fp_cd->flags & DETECT_CONTENT_WITHIN) {
230  fprintf(fp, " Within");
231  flags_set = 1;
232  }
233  if (fp_cd->flags & DETECT_CONTENT_DISTANCE) {
234  fprintf(fp, " Distance");
235  flags_set = 1;
236  }
237  if (fp_cd->flags & DETECT_CONTENT_NOCASE) {
238  fprintf(fp, " Nocase");
239  flags_set = 1;
240  }
241  if (fp_cd->flags & DETECT_CONTENT_NEGATED) {
242  fprintf(fp, " Negated");
243  flags_set = 1;
244  }
245  if (flags_set == 0)
246  fprintf(fp, " None");
247  fprintf(fp, "\n");
248 
249  fprintf(fp, " Fast pattern set: %s\n", fast_pattern_set ? "yes" : "no");
250  fprintf(fp, " Fast pattern only set: %s\n", fast_pattern_only_set ? "yes" : "no");
251  fprintf(fp, " Fast pattern chop set: %s\n", fast_pattern_chop_set ? "yes" : "no");
252  if (fast_pattern_chop_set) {
253  fprintf(fp, " Fast pattern offset, length: %u, %u\n", fp_cd->fp_chop_offset,
254  fp_cd->fp_chop_len);
255  }
256 
257  uint16_t patlen = fp_cd->content_len;
258  uint8_t *pat = SCMalloc(fp_cd->content_len + 1);
259  if (unlikely(pat == NULL)) {
260  FatalError("Error allocating memory");
261  }
262  memcpy(pat, fp_cd->content, fp_cd->content_len);
263  pat[fp_cd->content_len] = '\0';
264  fprintf(fp, " Original content: ");
265  PrintRawUriFp(fp, pat, patlen);
266  fprintf(fp, "\n");
267 
268  if (fast_pattern_chop_set) {
269  SCFree(pat);
270  patlen = fp_cd->fp_chop_len;
271  pat = SCMalloc(fp_cd->fp_chop_len + 1);
272  if (unlikely(pat == NULL)) {
273  exit(EXIT_FAILURE);
274  }
275  memcpy(pat, fp_cd->content + fp_cd->fp_chop_offset, fp_cd->fp_chop_len);
276  pat[fp_cd->fp_chop_len] = '\0';
277  fprintf(fp, " Final content: ");
278  PrintRawUriFp(fp, pat, patlen);
279  fprintf(fp, "\n");
280 
281  FpPatternStatsAdd(&de_ctx->ea->fp_pattern_stats[0], list_type, patlen);
282  } else {
283  fprintf(fp, " Final content: ");
284  PrintRawUriFp(fp, pat, patlen);
285  fprintf(fp, "\n");
286 
287  FpPatternStatsAdd(&de_ctx->ea->fp_pattern_stats[0], list_type, patlen);
288  }
289  SCFree(pat);
290 
291  fprintf(fp, "\n");
292 }
293 
294 /**
295  * \brief Sets up the fast pattern analyzer according to the config.
296  *
297  * \retval 1 If rule analyzer successfully enabled.
298  * \retval 0 If not enabled.
299  */
300 static int SetupFPAnalyzer(DetectEngineCtx *de_ctx)
301 {
302  int fp_engine_analysis_set = 0;
303 
304  if ((SCConfGetBool("engine-analysis.rules-fast-pattern", &fp_engine_analysis_set)) == 0) {
305  return false;
306  }
307 
308  if (fp_engine_analysis_set == 0)
309  return false;
310 
311  const char *log_dir = SCConfigGetLogDirectory();
312  char *log_path = SCMalloc(PATH_MAX);
313  if (log_path == NULL) {
314  FatalError("Unable to allocate scratch memory for rule filename");
315  }
316  snprintf(log_path, PATH_MAX, "%s/%s%s", log_dir,
317  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", "rules_fast_pattern.txt");
318 
319  FILE *fp = fopen(log_path, "w");
320  if (fp == NULL) {
321  SCLogError("failed to open %s: %s", log_path, strerror(errno));
322  SCFree(log_path);
323  return false;
324  }
325 
327 
328  SCLogInfo("Engine-Analysis for fast_pattern printed to file - %s",
329  log_path);
330  SCFree(log_path);
331 
332  struct timeval tval;
333  gettimeofday(&tval, NULL);
334  struct tm local_tm;
335  struct tm *tms = SCLocalTime(tval.tv_sec, &local_tm);
336  fprintf(fp, "----------------------------------------------"
337  "---------------------\n");
338  fprintf(fp,
339  "Date: %" PRId32 "/%" PRId32 "/%04d -- "
340  "%02d:%02d:%02d\n",
341  tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
342  tms->tm_sec);
343  fprintf(fp, "----------------------------------------------"
344  "---------------------\n");
345 
346  memset(&de_ctx->ea->fp_pattern_stats[0], 0, sizeof(de_ctx->ea->fp_pattern_stats));
347  return true;
348 }
349 
350 /**
351  * \brief Compiles regex for rule analysis
352  * \retval 1 if successful
353  * \retval 0 if on error
354  */
355 static bool PerCentEncodingSetup(EngineAnalysisCtx *ea_ctx)
356 {
357 #define DETECT_PERCENT_ENCODING_REGEX "%[0-9|a-f|A-F]{2}"
358  int en;
359  PCRE2_SIZE eo = 0;
360  int opts = 0; // PCRE2_NEWLINE_ANY??
361 
362  ea_ctx->percent_re = pcre2_compile((PCRE2_SPTR8)DETECT_PERCENT_ENCODING_REGEX,
363  PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
364  if (ea_ctx->percent_re == NULL) {
365  PCRE2_UCHAR errbuffer[256];
366  pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
367  SCLogError("Compile of \"%s\" failed at offset %d: %s", DETECT_PERCENT_ENCODING_REGEX,
368  (int)eo, errbuffer);
369  return false;
370  }
371 
372  return true;
373 }
374 /**
375  * \brief Sets up the rule analyzer according to the config
376  * \retval 1 if rule analyzer successfully enabled
377  * \retval 0 if not enabled
378  */
379 static int SetupRuleAnalyzer(DetectEngineCtx *de_ctx)
380 {
381  SCConfNode *conf = SCConfGetNode("engine-analysis");
382  int enabled = 0;
383  if (conf != NULL) {
384  const char *value = SCConfNodeLookupChildValue(conf, "rules");
385  if (value && SCConfValIsTrue(value)) {
386  enabled = 1;
387  } else if (value && strcasecmp(value, "warnings-only") == 0) {
388  enabled = 1;
389  rule_warnings_only = 1;
390  }
391  if (enabled) {
392  const char *log_dir;
393  log_dir = SCConfigGetLogDirectory();
394  char log_path[PATH_MAX];
395  snprintf(log_path, sizeof(log_path), "%s/%s%s", log_dir,
396  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", "rules_analysis.txt");
397  de_ctx->ea->rule_engine_analysis_fp = fopen(log_path, "w");
398  if (de_ctx->ea->rule_engine_analysis_fp == NULL) {
399  SCLogError("failed to open %s: %s", log_path, strerror(errno));
400  return 0;
401  }
402 
403  SCLogInfo("Engine-Analysis for rules printed to file - %s",
404  log_path);
405 
406  struct timeval tval;
407  gettimeofday(&tval, NULL);
408  struct tm local_tm;
409  struct tm *tms = SCLocalTime(tval.tv_sec, &local_tm);
411  "----------------------------------------------"
412  "---------------------\n");
414  "Date: %" PRId32 "/%" PRId32 "/%04d -- "
415  "%02d:%02d:%02d\n",
416  tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
417  tms->tm_sec);
419  "----------------------------------------------"
420  "---------------------\n");
421 
422  /*compile regex's for rule analysis*/
423  if (!PerCentEncodingSetup(de_ctx->ea)) {
425  "Error compiling regex; can't check for percent encoding in normalized "
426  "http content.\n");
427  }
428  }
429  }
430  else {
431  SCLogInfo("Conf parameter \"engine-analysis.rules\" not found. "
432  "Defaulting to not printing the rules analysis report.");
433  }
434  if (!enabled) {
435  SCLogInfo("Engine-Analysis for rules disabled in conf file.");
436  return 0;
437  }
438  return 1;
439 }
440 
441 static void CleanupFPAnalyzer(DetectEngineCtx *de_ctx)
442 {
443  FILE *fp = de_ctx->ea->rule_engine_analysis_fp;
444  fprintf(fp, "============\n"
445  "Summary:\n============\n");
446 
447  for (int i = 0; i < DETECT_SM_LIST_MAX; i++) {
449  if (f->cnt == 0)
450  continue;
451 
452  fprintf(fp,
453  "%s, smallest pattern %u byte(s), longest pattern %u byte(s), number of patterns "
454  "%u, avg pattern len %.2f byte(s)\n",
455  DetectSigmatchListEnumToString(i), f->min, f->max, f->cnt,
456  (float)((double)f->tot / (float)f->cnt));
457  }
458 
461 }
462 
463 static void CleanupRuleAnalyzer(DetectEngineCtx *de_ctx)
464 {
465  if (de_ctx->ea->fp_engine_analysis_fp != NULL) {
466  fclose(de_ctx->ea->fp_engine_analysis_fp);
468  }
469  if (de_ctx->ea->percent_re != NULL) {
470  pcre2_code_free(de_ctx->ea->percent_re);
471  }
472 }
473 
474 void SetupEngineAnalysis(DetectEngineCtx *de_ctx, bool *fp_analysis, bool *rule_analysis)
475 {
476  *fp_analysis = false;
477  *rule_analysis = false;
478 
479  EngineAnalysisCtx *ea = SCCalloc(1, sizeof(EngineAnalysisCtx));
480  if (ea == NULL) {
481  FatalError("Unable to allocate per-engine analysis context");
482  }
483 
484  ea->file_prefix = NULL;
485  size_t cfg_prefix_len = strlen(de_ctx->config_prefix);
486  if (cfg_prefix_len > 0) {
487  char prefix[sizeof(de_ctx->config_prefix) + 1];
488  snprintf(prefix, sizeof(prefix), "%s.", de_ctx->config_prefix);
489  ea->file_prefix = SCStrdup(prefix);
490  if (ea->file_prefix == NULL) {
491  FatalError("Unable to allocate per-engine analysis context name buffer");
492  }
493  }
494 
495  de_ctx->ea = ea;
496 
497  *fp_analysis = SetupFPAnalyzer(de_ctx);
498  *rule_analysis = SetupRuleAnalyzer(de_ctx);
499 
500  if (!(*fp_analysis || *rule_analysis)) {
501  if (ea->file_prefix)
502  SCFree(ea->file_prefix);
503  if (ea->analyzer_items)
504  SCFree(ea->analyzer_items);
505  SCFree(ea);
506  }
507 }
508 
510 {
511  if (de_ctx->ea) {
512  CleanupRuleAnalyzer(de_ctx);
513  CleanupFPAnalyzer(de_ctx);
514  if (de_ctx->ea->file_prefix)
516  if (de_ctx->ea->analyzer_items)
518  SCFree(de_ctx->ea);
519  de_ctx->ea = NULL;
520  }
521 }
522 
523 /**
524  * \brief Checks for % encoding in content.
525  * \param Pointer to content
526  * \retval number of matches if content has % encoding
527  * \retval 0 if it doesn't have % encoding
528  * \retval -1 on error
529  */
530 static int PerCentEncodingMatch(EngineAnalysisCtx *ea_ctx, uint8_t *content, uint16_t content_len)
531 {
532  int ret = 0;
533 
534  pcre2_match_data *match = pcre2_match_data_create_from_pattern(ea_ctx->percent_re, NULL);
535  ret = pcre2_match(ea_ctx->percent_re, (PCRE2_SPTR8)content, content_len, 0, 0, match, NULL);
536  if (ret == -1) {
537  return 0;
538  } else if (ret < -1) {
539  SCLogError("Error parsing content - %s; error code is %d", content, ret);
540  ret = -1;
541  }
542  pcre2_match_data_free(match);
543  return ret;
544 }
545 
546 static void EngineAnalysisRulesPrintFP(const DetectEngineCtx *de_ctx, const Signature *s)
547 {
548  const DetectContentData *fp_cd = NULL;
549  const SigMatch *mpm_sm = s->init_data->mpm_sm;
550  const int mpm_sm_list = s->init_data->mpm_sm_list;
551 
552  if (mpm_sm != NULL) {
553  fp_cd = (DetectContentData *)mpm_sm->ctx;
554  }
555 
556  if (fp_cd == NULL) {
557  return;
558  }
559 
560  uint16_t patlen = fp_cd->content_len;
561  uint8_t *pat = SCMalloc(fp_cd->content_len + 1);
562  if (unlikely(pat == NULL)) {
563  FatalError("Error allocating memory");
564  }
565 
566  EngineAnalysisCtx *ea_ctx = de_ctx->ea;
567 
568  memcpy(pat, fp_cd->content, fp_cd->content_len);
569  pat[fp_cd->content_len] = '\0';
570 
572  SCFree(pat);
573  patlen = fp_cd->fp_chop_len;
574  pat = SCMalloc(fp_cd->fp_chop_len + 1);
575  if (unlikely(pat == NULL)) {
576  exit(EXIT_FAILURE);
577  }
578  memcpy(pat, fp_cd->content + fp_cd->fp_chop_offset, fp_cd->fp_chop_len);
579  pat[fp_cd->fp_chop_len] = '\0';
580  fprintf(ea_ctx->rule_engine_analysis_fp, " Fast Pattern \"");
581  PrintRawUriFp(ea_ctx->rule_engine_analysis_fp, pat, patlen);
582  } else {
583  fprintf(ea_ctx->rule_engine_analysis_fp, " Fast Pattern \"");
584  PrintRawUriFp(ea_ctx->rule_engine_analysis_fp, pat, patlen);
585  }
586  SCFree(pat);
587 
588  fprintf(ea_ctx->rule_engine_analysis_fp, "\" on \"");
589 
590  const int list_type = mpm_sm_list;
591  if (list_type == DETECT_SM_LIST_PMATCH) {
592  int payload = 0;
593  int stream = 0;
595  payload = 1;
597  stream = 1;
598  fprintf(ea_ctx->rule_engine_analysis_fp, "%s",
599  payload ? (stream ? "payload and reassembled stream" : "payload")
600  : "reassembled stream");
601  }
602  else {
603  const char *desc = DetectEngineBufferTypeGetDescriptionById(de_ctx, list_type);
604  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, list_type);
605  if (desc && name) {
606  fprintf(ea_ctx->rule_engine_analysis_fp, "%s (%s)", desc, name);
607  } else if (desc || name) {
608  fprintf(ea_ctx->rule_engine_analysis_fp, "%s", desc ? desc : name);
609  }
610 
611  }
612 
613  fprintf(ea_ctx->rule_engine_analysis_fp, "\" ");
614  const DetectBufferType *bt = DetectEngineBufferTypeGetById(de_ctx, list_type);
615  if (bt && bt->transforms.cnt) {
616  fprintf(ea_ctx->rule_engine_analysis_fp, "(with %d transform(s)) ", bt->transforms.cnt);
617  }
618  fprintf(ea_ctx->rule_engine_analysis_fp, "buffer.\n");
619 }
620 
622  const DetectEngineCtx *de_ctx, const char *line, const char *file, int lineno)
623 {
626  if (tmp_fp) {
627  fprintf(tmp_fp, "== Sid: UNKNOWN ==\n");
628  fprintf(tmp_fp, "%s\n", line);
629  fprintf(tmp_fp, " FAILURE: invalid rule.\n");
630  fprintf(tmp_fp, " File: %s.\n", file);
631  fprintf(tmp_fp, " Line: %d.\n", lineno);
632  fprintf(tmp_fp, "\n");
633  }
634 }
635 
636 typedef struct RuleAnalyzer {
637  SCJsonBuilder *js; /* document root */
638 
639  SCJsonBuilder *js_warnings;
640  SCJsonBuilder *js_notes;
642 
643 static void ATTR_FMT_PRINTF(2, 3) AnalyzerNote(RuleAnalyzer *ctx, char *fmt, ...)
644 {
645  va_list ap;
646  char str[1024];
647 
648  va_start(ap, fmt);
649  vsnprintf(str, sizeof(str), fmt, ap);
650  va_end(ap);
651 
652  if (!ctx->js_notes)
653  ctx->js_notes = SCJbNewArray();
654  if (ctx->js_notes)
655  SCJbAppendString(ctx->js_notes, str);
656 }
657 
658 static void ATTR_FMT_PRINTF(2, 3) AnalyzerWarning(RuleAnalyzer *ctx, char *fmt, ...)
659 {
660  va_list ap;
661  char str[1024];
662 
663  va_start(ap, fmt);
664  vsnprintf(str, sizeof(str), fmt, ap);
665  va_end(ap);
666 
667  if (!ctx->js_warnings)
668  ctx->js_warnings = SCJbNewArray();
669  if (ctx->js_warnings)
670  SCJbAppendString(ctx->js_warnings, str);
671 }
672 
673 #define CHECK(pat) if (strlen((pat)) <= len && memcmp((pat), buf, MIN(len, strlen((pat)))) == 0) return true;
674 
675 static bool LooksLikeHTTPMethod(const uint8_t *buf, uint16_t len)
676 {
677  CHECK("GET /");
678  CHECK("POST /");
679  CHECK("HEAD /");
680  CHECK("PUT /");
681  return false;
682 }
683 
684 static bool LooksLikeHTTPUA(const uint8_t *buf, uint16_t len)
685 {
686  CHECK("User-Agent: ");
687  CHECK("\nUser-Agent: ");
688  return false;
689 }
690 
691 static void DumpContent(SCJsonBuilder *js, const DetectContentData *cd)
692 {
693  char pattern_str[1024] = "";
694  DetectContentPatternPrettyPrint(cd, pattern_str, sizeof(pattern_str));
695 
696  SCJbSetString(js, "pattern", pattern_str);
697  SCJbSetUint(js, "length", cd->content_len);
698  SCJbSetBool(js, "nocase", cd->flags & DETECT_CONTENT_NOCASE);
699  SCJbSetBool(js, "negated", cd->flags & DETECT_CONTENT_NEGATED);
700  SCJbSetBool(js, "starts_with", cd->flags & DETECT_CONTENT_STARTS_WITH);
701  SCJbSetBool(js, "ends_with", cd->flags & DETECT_CONTENT_ENDS_WITH);
702  SCJbSetBool(js, "is_mpm", cd->flags & DETECT_CONTENT_MPM);
703  SCJbSetBool(js, "no_double_inspect", cd->flags & DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED);
704  if (cd->flags & DETECT_CONTENT_OFFSET) {
705  SCJbSetUint(js, "offset", cd->offset);
706  }
707  if (cd->flags & DETECT_CONTENT_DEPTH) {
708  SCJbSetUint(js, "depth", cd->depth);
709  }
710  if (cd->flags & DETECT_CONTENT_DISTANCE) {
711  SCJbSetInt(js, "distance", cd->distance);
712  }
713  if (cd->flags & DETECT_CONTENT_WITHIN) {
714  SCJbSetInt(js, "within", cd->within);
715  }
716  SCJbSetBool(js, "fast_pattern", cd->flags & DETECT_CONTENT_FAST_PATTERN);
717  SCJbSetBool(js, "relative_next", cd->flags & DETECT_CONTENT_RELATIVE_NEXT);
718 }
719 
720 static void DumpPcre(SCJsonBuilder *js, const DetectPcreData *cd)
721 {
722  SCJbSetBool(js, "relative", cd->flags & DETECT_PCRE_RELATIVE);
723  SCJbSetBool(js, "relative_next", cd->flags & DETECT_PCRE_RELATIVE_NEXT);
724  SCJbSetBool(js, "nocase", cd->flags & DETECT_PCRE_CASELESS);
725  SCJbSetBool(js, "negated", cd->flags & DETECT_PCRE_NEGATE);
726 }
727 
728 static void DumpMatches(RuleAnalyzer *ctx, SCJsonBuilder *js, const SigMatchData *smd)
729 {
730  if (smd == NULL)
731  return;
732 
733  SCJbOpenArray(js, "matches");
734  do {
735  SCJbStartObject(js);
736  const char *mname = sigmatch_table[smd->type].name;
737  SCJbSetString(js, "name", mname);
738 
739  switch (smd->type) {
740  case DETECT_CONTENT: {
741  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
742 
743  SCJbOpenObject(js, "content");
744  DumpContent(js, cd);
746  AnalyzerNote(ctx, (char *)"'fast_pattern:only' option is silently ignored and "
747  "is interpreted as regular 'fast_pattern'");
748  }
749  if (LooksLikeHTTPMethod(cd->content, cd->content_len)) {
750  AnalyzerNote(ctx,
751  (char *)"pattern looks like it inspects HTTP, use http.request_line or "
752  "http.method and http.uri instead for improved performance");
753  }
754  if (LooksLikeHTTPUA(cd->content, cd->content_len)) {
755  AnalyzerNote(ctx,
756  (char *)"pattern looks like it inspects HTTP, use http.user_agent "
757  "or http.header for improved performance");
758  }
760  AnalyzerNote(ctx, (char *)"'within' option for pattern w/o previous content "
761  "was converted to 'depth'");
762  }
764  AnalyzerNote(ctx, (char *)"'distance' option for pattern w/o previous content "
765  "was converted to 'offset'");
766  }
767  SCJbClose(js);
768  break;
769  }
770  case DETECT_PCRE: {
771  const DetectPcreData *cd = (const DetectPcreData *)smd->ctx;
772 
773  SCJbOpenObject(js, "pcre");
774  DumpPcre(js, cd);
775  SCJbClose(js);
776  if (cd->flags & DETECT_PCRE_RAWBYTES) {
777  AnalyzerNote(ctx,
778  (char *)"'/B' (rawbytes) option is a no-op and is silently ignored");
779  }
780  break;
781  }
782  case DETECT_BYTEJUMP: {
783  const DetectBytejumpData *cd = (const DetectBytejumpData *)smd->ctx;
784 
785  SCJbOpenObject(js, "byte_jump");
786  SCJbSetUint(js, "nbytes", cd->nbytes);
787  SCJbSetInt(js, "offset", cd->offset);
788  SCJbSetUint(js, "multiplier", cd->multiplier);
789  SCJbSetInt(js, "post_offset", cd->post_offset);
790  switch (cd->base) {
792  SCJbSetString(js, "base", "unset");
793  break;
795  SCJbSetString(js, "base", "oct");
796  break;
798  SCJbSetString(js, "base", "dec");
799  break;
801  SCJbSetString(js, "base", "hex");
802  break;
803  }
804  SCJbOpenArray(js, "flags");
805  if (cd->flags & DETECT_BYTEJUMP_BEGIN)
806  SCJbAppendString(js, "from_beginning");
807  if (cd->flags & DETECT_BYTEJUMP_LITTLE)
808  SCJbAppendString(js, "little_endian");
809  if (cd->flags & DETECT_BYTEJUMP_BIG)
810  SCJbAppendString(js, "big_endian");
811  if (cd->flags & DETECT_BYTEJUMP_STRING)
812  SCJbAppendString(js, "string");
814  SCJbAppendString(js, "relative");
815  if (cd->flags & DETECT_BYTEJUMP_ALIGN)
816  SCJbAppendString(js, "align");
817  if (cd->flags & DETECT_BYTEJUMP_DCE)
818  SCJbAppendString(js, "dce");
820  SCJbAppendString(js, "offset_be");
821  if (cd->flags & DETECT_BYTEJUMP_END)
822  SCJbAppendString(js, "from_end");
823  SCJbClose(js);
824  SCJbClose(js);
825  break;
826  }
827  case DETECT_BYTETEST: {
828  const DetectBytetestData *cd = (const DetectBytetestData *)smd->ctx;
829 
830  SCJbOpenObject(js, "byte_test");
831  SCJbSetUint(js, "nbytes", cd->nbytes);
832  SCJbSetInt(js, "offset", cd->offset);
833  switch (cd->base) {
835  SCJbSetString(js, "base", "unset");
836  break;
838  SCJbSetString(js, "base", "oct");
839  break;
841  SCJbSetString(js, "base", "dec");
842  break;
844  SCJbSetString(js, "base", "hex");
845  break;
846  }
847  SCJbOpenArray(js, "flags");
848  if (cd->flags & DETECT_BYTETEST_LITTLE)
849  SCJbAppendString(js, "little_endian");
850  if (cd->flags & DETECT_BYTETEST_BIG)
851  SCJbAppendString(js, "big_endian");
852  if (cd->flags & DETECT_BYTETEST_STRING)
853  SCJbAppendString(js, "string");
855  SCJbAppendString(js, "relative");
856  if (cd->flags & DETECT_BYTETEST_DCE)
857  SCJbAppendString(js, "dce");
858  SCJbClose(js);
859  SCJbClose(js);
860  break;
861  }
862  case DETECT_ABSENT: {
863  const DetectAbsentData *dad = (const DetectAbsentData *)smd->ctx;
864  SCJbOpenObject(js, "absent");
865  SCJbSetBool(js, "or_else", dad->or_else);
866  SCJbClose(js);
867  break;
868  }
869 
870  case DETECT_IPOPTS: {
871  const DetectIpOptsData *cd = (const DetectIpOptsData *)smd->ctx;
872 
873  SCJbOpenObject(js, "ipopts");
874  const char *flag = IpOptsFlagToString(cd->ipopt);
875  SCJbSetString(js, "option", flag);
876  SCJbClose(js);
877  break;
878  }
879  case DETECT_FLOWBITS: {
880  const DetectFlowbitsData *cd = (const DetectFlowbitsData *)smd->ctx;
881 
882  SCJbOpenObject(js, "flowbits");
883  switch (cd->cmd) {
885  SCJbSetString(js, "cmd", "isset");
886  break;
888  SCJbSetString(js, "cmd", "isnotset");
889  break;
891  SCJbSetString(js, "cmd", "set");
892  break;
894  SCJbSetString(js, "cmd", "unset");
895  break;
897  SCJbSetString(js, "cmd", "toggle");
898  break;
899  }
900  bool is_or = false;
901  SCJbOpenArray(js, "names");
902  if (cd->or_list_size == 0) {
903  SCJbAppendString(js, VarNameStoreSetupLookup(cd->idx, VAR_TYPE_FLOW_BIT));
904  } else if (cd->or_list_size > 0) {
905  is_or = true;
906  for (uint8_t i = 0; i < cd->or_list_size; i++) {
907  const char *varname =
909  SCJbAppendString(js, varname);
910  }
911  }
912  SCJbClose(js); // array
913  if (is_or) {
914  SCJbSetString(js, "operator", "or");
915  }
916  SCJbClose(js); // object
917  break;
918  }
919  case DETECT_ACK: {
920  const DetectAckData *cd = (const DetectAckData *)smd->ctx;
921 
922  SCJbOpenObject(js, "ack");
923  SCJbSetUint(js, "number", cd->ack);
924  SCJbClose(js);
925  break;
926  }
927  case DETECT_SEQ: {
928  const DetectSeqData *cd = (const DetectSeqData *)smd->ctx;
929  SCJbOpenObject(js, "seq");
930  SCJbSetUint(js, "number", cd->seq);
931  SCJbClose(js);
932  break;
933  }
934  case DETECT_TCPMSS: {
935  const DetectU16Data *cd = (const DetectU16Data *)smd->ctx;
936  SCJbOpenObject(js, "tcp_mss");
937  SCDetectU16ToJson(js, cd);
938  SCJbClose(js);
939  break;
940  }
941  case DETECT_DSIZE: {
942  const DetectU16Data *cd = (const DetectU16Data *)smd->ctx;
943  SCJbOpenObject(js, "dsize");
944  SCDetectU16ToJson(js, cd);
945  SCJbClose(js);
946  break;
947  }
948  case DETECT_ICODE: {
949  const DetectU8Data *cd = (const DetectU8Data *)smd->ctx;
950  SCJbOpenObject(js, "code");
951  SCDetectU8ToJson(js, cd);
952  SCJbClose(js);
953  break;
954  }
955  case DETECT_ICMP_ID: {
956  const DetectIcmpIdData *cd = (const DetectIcmpIdData *)smd->ctx;
957  SCJbOpenObject(js, "id");
958  SCJbSetUint(js, "number", SCNtohs(cd->id));
959  SCJbClose(js);
960  break;
961  }
962  case DETECT_WINDOW: {
963  const DetectWindowData *wd = (const DetectWindowData *)smd->ctx;
964  SCJbOpenObject(js, "window");
965  SCJbSetUint(js, "size", wd->size);
966  SCJbSetBool(js, "negated", wd->negated);
967  SCJbClose(js);
968  break;
969  }
970  case DETECT_FLOW_AGE: {
971  const DetectU32Data *cd = (const DetectU32Data *)smd->ctx;
972  SCJbOpenObject(js, "flow_age");
973  SCDetectU32ToJson(js, cd);
974  SCJbClose(js);
975  break;
976  }
977  }
978  SCJbClose(js);
979 
980  if (smd->is_last)
981  break;
982  smd++;
983  } while (1);
984  SCJbClose(js);
985 }
986 
989 {
990  SCEnter();
991 
992  RuleAnalyzer ctx = { NULL, NULL, NULL };
993 
994  ctx.js = SCJbNewObject();
995  if (ctx.js == NULL)
996  SCReturn;
997 
998  if (s->init_data->firewall_rule) {
999  JB_SET_STRING(ctx.js, "class", "firewall");
1000  } else {
1001  JB_SET_STRING(ctx.js, "class", "threat detection");
1002  }
1003 
1004  SCJbSetString(ctx.js, "raw", s->sig_str);
1005  SCJbSetUint(ctx.js, "id", s->id);
1006  SCJbSetUint(ctx.js, "gid", s->gid);
1007  SCJbSetUint(ctx.js, "rev", s->rev);
1008  SCJbSetString(ctx.js, "msg", s->msg);
1009 
1010  const char *alproto = AppProtoToString(s->alproto);
1011  SCJbSetString(ctx.js, "app_proto", alproto);
1012 
1013  SCJbOpenArray(ctx.js, "requirements");
1014  if (s->mask & SIG_MASK_REQUIRE_PAYLOAD) {
1015  SCJbAppendString(ctx.js, "payload");
1016  }
1017  if (s->mask & SIG_MASK_REQUIRE_NO_PAYLOAD) {
1018  SCJbAppendString(ctx.js, "no_payload");
1019  }
1020  if (s->mask & SIG_MASK_REQUIRE_FLOW) {
1021  SCJbAppendString(ctx.js, "flow");
1022  }
1024  SCJbAppendString(ctx.js, "tcp_flags_init_deinit");
1025  }
1027  SCJbAppendString(ctx.js, "tcp_flags_unusual");
1028  }
1030  SCJbAppendString(ctx.js, "engine_event");
1031  }
1032  if (s->mask & SIG_MASK_REQUIRE_REAL_PKT) {
1033  SCJbAppendString(ctx.js, "real_pkt");
1034  }
1035  SCJbClose(ctx.js);
1036 
1037  SCJbOpenObject(ctx.js, "match_policy");
1038  SCJbOpenArray(ctx.js, "actions");
1039  if (s->action & ACTION_ALERT) {
1040  SCJbAppendString(ctx.js, "alert");
1041  }
1042  if (s->action & ACTION_DROP) {
1043  SCJbAppendString(ctx.js, "drop");
1044  }
1045  if (s->action & ACTION_REJECT) {
1046  SCJbAppendString(ctx.js, "reject");
1047  }
1048  if (s->action & ACTION_REJECT_DST) {
1049  SCJbAppendString(ctx.js, "reject_dst");
1050  }
1051  if (s->action & ACTION_REJECT_BOTH) {
1052  SCJbAppendString(ctx.js, "reject_both");
1053  }
1054  if (s->action & ACTION_CONFIG) {
1055  SCJbAppendString(ctx.js, "config");
1056  }
1057  if (s->action & ACTION_PASS) {
1058  SCJbAppendString(ctx.js, "pass");
1059  }
1060  if (s->action & ACTION_ACCEPT) {
1061  SCJbAppendString(ctx.js, "accept");
1062  }
1063  SCJbClose(ctx.js);
1064 
1065  if (s->action_scope == ACTION_SCOPE_AUTO) {
1067  switch (flow_action) {
1069  SCJbSetString(ctx.js, "scope", "packet");
1070  break;
1072  SCJbSetString(ctx.js, "scope", "flow");
1073  break;
1075  SCJbSetString(ctx.js, "scope", "flow_if_stateful");
1076  break;
1077  }
1078  } else {
1079  enum ActionScope as = s->action_scope;
1080  switch (as) {
1081  case ACTION_SCOPE_PACKET:
1082  SCJbSetString(ctx.js, "scope", "packet");
1083  break;
1084  case ACTION_SCOPE_FLOW:
1085  SCJbSetString(ctx.js, "scope", "flow");
1086  break;
1087  case ACTION_SCOPE_HOOK:
1088  SCJbSetString(ctx.js, "scope", "hook");
1089  break;
1090  case ACTION_SCOPE_TX:
1091  SCJbSetString(ctx.js, "scope", "tx");
1092  break;
1093  case ACTION_SCOPE_AUTO: /* should be unreachable */
1094  break;
1095  }
1096  }
1097  SCJbClose(ctx.js);
1098 
1099  switch (s->type) {
1100  case SIG_TYPE_NOT_SET:
1101  SCJbSetString(ctx.js, "type", "unset");
1102  break;
1103  case SIG_TYPE_IPONLY:
1104  SCJbSetString(ctx.js, "type", "ip_only");
1105  break;
1106  case SIG_TYPE_LIKE_IPONLY:
1107  SCJbSetString(ctx.js, "type", "like_ip_only");
1108  break;
1109  case SIG_TYPE_PDONLY:
1110  SCJbSetString(ctx.js, "type", "pd_only");
1111  break;
1112  case SIG_TYPE_DEONLY:
1113  SCJbSetString(ctx.js, "type", "de_only");
1114  break;
1115  case SIG_TYPE_PKT:
1116  SCJbSetString(ctx.js, "type", "pkt");
1117  break;
1118  case SIG_TYPE_PKT_STREAM:
1119  SCJbSetString(ctx.js, "type", "pkt_stream");
1120  break;
1121  case SIG_TYPE_STREAM:
1122  SCJbSetString(ctx.js, "type", "stream");
1123  break;
1124  case SIG_TYPE_APPLAYER:
1125  SCJbSetString(ctx.js, "type", "app_layer");
1126  break;
1127  case SIG_TYPE_APP_TX:
1128  SCJbSetString(ctx.js, "type", "app_tx");
1129  break;
1130  case SIG_TYPE_MAX:
1131  SCJbSetString(ctx.js, "type", "error");
1132  break;
1133  }
1134 
1135  // dependencies object and its subfields only logged if we have values
1137  SCJbOpenObject(ctx.js, "dependencies");
1138  SCJbOpenObject(ctx.js, "flowbits");
1139  SCJbOpenObject(ctx.js, "upstream");
1141  SCJbOpenObject(ctx.js, "state_modifying_rules");
1142  SCJbOpenArray(ctx.js, "sids");
1143  for (uint32_t i = 0; i < s->init_data->rule_state_dependant_sids_idx; i++) {
1144  SCJbAppendUint(ctx.js, s->init_data->rule_state_dependant_sids_array[i]);
1145  }
1146  SCJbClose(ctx.js); // sids
1147  SCJbOpenArray(ctx.js, "names");
1148  for (uint32_t i = 0; i < s->init_data->rule_state_flowbits_ids_size - 1; i++) {
1149  if (s->init_data->rule_state_flowbits_ids_array[i] != 0) {
1150  SCJbAppendString(ctx.js,
1153  }
1154  }
1155  SCJbClose(ctx.js); // names
1156  SCJbClose(ctx.js); // state_modifying_rules
1157  }
1158  SCJbClose(ctx.js); // upstream
1159  SCJbClose(ctx.js); // flowbits
1160  SCJbClose(ctx.js); // dependencies
1161  }
1162 
1163  SCJbOpenArray(ctx.js, "flags");
1164  if (s->flags & SIG_FLAG_SRC_ANY) {
1165  SCJbAppendString(ctx.js, "src_any");
1166  }
1167  if (s->flags & SIG_FLAG_DST_ANY) {
1168  SCJbAppendString(ctx.js, "dst_any");
1169  }
1170  if (s->flags & SIG_FLAG_SP_ANY) {
1171  SCJbAppendString(ctx.js, "sp_any");
1172  }
1173  if (s->flags & SIG_FLAG_DP_ANY) {
1174  SCJbAppendString(ctx.js, "dp_any");
1175  }
1176  if ((s->action & ACTION_ALERT) == 0) {
1177  SCJbAppendString(ctx.js, "noalert");
1178  }
1179  if (s->flags & SIG_FLAG_DSIZE) {
1180  SCJbAppendString(ctx.js, "dsize");
1181  }
1182  if (s->flags & SIG_FLAG_APPLAYER) {
1183  SCJbAppendString(ctx.js, "applayer");
1184  }
1185  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
1186  SCJbAppendString(ctx.js, "need_packet");
1187  }
1188  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
1189  SCJbAppendString(ctx.js, "need_stream");
1190  }
1191  if (s->flags & SIG_FLAG_MPM_NEG) {
1192  SCJbAppendString(ctx.js, "negated_mpm");
1193  }
1194  if (s->flags & SIG_FLAG_FLUSH) {
1195  SCJbAppendString(ctx.js, "flush");
1196  }
1197  if (s->flags & SIG_FLAG_REQUIRE_FLOWVAR) {
1198  SCJbAppendString(ctx.js, "need_flowvar");
1199  }
1200  if (s->flags & SIG_FLAG_FILESTORE) {
1201  SCJbAppendString(ctx.js, "filestore");
1202  }
1203  if (s->flags & SIG_FLAG_TOSERVER) {
1204  SCJbAppendString(ctx.js, "toserver");
1205  }
1206  if (s->flags & SIG_FLAG_TOCLIENT) {
1207  SCJbAppendString(ctx.js, "toclient");
1208  }
1209  if (s->flags & SIG_FLAG_TLSSTORE) {
1210  SCJbAppendString(ctx.js, "tlsstore");
1211  }
1212  if (s->flags & SIG_FLAG_BYPASS) {
1213  SCJbAppendString(ctx.js, "bypass");
1214  }
1215  if (s->flags & SIG_FLAG_PREFILTER) {
1216  SCJbAppendString(ctx.js, "prefilter");
1217  }
1218  if (s->flags & SIG_FLAG_SRC_IS_TARGET) {
1219  SCJbAppendString(ctx.js, "src_is_target");
1220  }
1221  if (s->flags & SIG_FLAG_DEST_IS_TARGET) {
1222  SCJbAppendString(ctx.js, "dst_is_target");
1223  }
1224  SCJbClose(ctx.js);
1225 
1226  const DetectEnginePktInspectionEngine *pkt_mpm = NULL;
1227  const DetectEngineAppInspectionEngine *app_mpm = NULL;
1228 
1229  SCJbOpenArray(ctx.js, "pkt_engines");
1231  for ( ; pkt != NULL; pkt = pkt->next) {
1233  if (name == NULL) {
1234  switch (pkt->sm_list) {
1235  case DETECT_SM_LIST_PMATCH:
1236  name = "payload";
1237  break;
1238  case DETECT_SM_LIST_MATCH:
1239  name = "packet";
1240  break;
1241  default:
1242  name = "unknown";
1243  break;
1244  }
1245  }
1246  SCJbStartObject(ctx.js);
1247  SCJbSetString(ctx.js, "name", name);
1248  SCJbSetBool(ctx.js, "is_mpm", pkt->mpm);
1249  if (pkt->v1.transforms != NULL) {
1250  SCJbOpenArray(ctx.js, "transforms");
1251  for (int t = 0; t < pkt->v1.transforms->cnt; t++) {
1252  SCJbStartObject(ctx.js);
1253  SCJbSetString(ctx.js, "name",
1255  SCJbClose(ctx.js);
1256  }
1257  SCJbClose(ctx.js);
1258  }
1259  DumpMatches(&ctx, ctx.js, pkt->smd);
1260  SCJbClose(ctx.js);
1261  if (pkt->mpm) {
1262  pkt_mpm = pkt;
1263  }
1264  }
1265  SCJbClose(ctx.js);
1266  SCJbOpenArray(ctx.js, "frame_engines");
1268  for (; frame != NULL; frame = frame->next) {
1269  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, frame->sm_list);
1270  SCJbStartObject(ctx.js);
1271  SCJbSetString(ctx.js, "name", name);
1272  SCJbSetBool(ctx.js, "is_mpm", frame->mpm);
1273  if (frame->v1.transforms != NULL) {
1274  SCJbOpenArray(ctx.js, "transforms");
1275  for (int t = 0; t < frame->v1.transforms->cnt; t++) {
1276  SCJbStartObject(ctx.js);
1277  SCJbSetString(ctx.js, "name",
1279  SCJbClose(ctx.js);
1280  }
1281  SCJbClose(ctx.js);
1282  }
1283  DumpMatches(&ctx, ctx.js, frame->smd);
1284  SCJbClose(ctx.js);
1285  }
1286  SCJbClose(ctx.js);
1287 
1289  bool has_stream = false;
1290  bool has_client_body_mpm = false;
1291  bool has_file_data_mpm = false;
1292 
1293  SCJbOpenArray(ctx.js, "engines");
1295  for ( ; app != NULL; app = app->next) {
1297  if (name == NULL) {
1298  switch (app->sm_list) {
1299  case DETECT_SM_LIST_PMATCH:
1300  name = "stream";
1301  break;
1302  default:
1303  name = "unknown";
1304  break;
1305  }
1306  }
1307 
1308  if (app->sm_list == DETECT_SM_LIST_PMATCH && !app->mpm) {
1309  has_stream = true;
1310  } else if (app->mpm && strcmp(name, "http_client_body") == 0) {
1311  has_client_body_mpm = true;
1312  } else if (app->mpm && strcmp(name, "file_data") == 0) {
1313  has_file_data_mpm = true;
1314  }
1315 
1316  SCJbStartObject(ctx.js);
1317  SCJbSetString(ctx.js, "name", name);
1318  const char *direction = app->dir == 0 ? "toserver" : "toclient";
1319  SCJbSetString(ctx.js, "direction", direction);
1320  SCJbSetBool(ctx.js, "is_mpm", app->mpm);
1321  SCJbSetString(ctx.js, "app_proto", AppProtoToString(app->alproto));
1322  SCJbSetUint(ctx.js, "progress", app->progress);
1323 
1324  if (app->v2.transforms != NULL) {
1325  SCJbOpenArray(ctx.js, "transforms");
1326  for (int t = 0; t < app->v2.transforms->cnt; t++) {
1327  SCJbStartObject(ctx.js);
1328  SCJbSetString(ctx.js, "name",
1330  SCJbClose(ctx.js);
1331  }
1332  SCJbClose(ctx.js);
1333  }
1334  DumpMatches(&ctx, ctx.js, app->smd);
1335  SCJbClose(ctx.js);
1336  if (app->mpm) {
1337  app_mpm = app;
1338  }
1339  }
1340  SCJbClose(ctx.js);
1341 
1342  if (has_stream && has_client_body_mpm)
1343  AnalyzerNote(&ctx, (char *)"mpm in http_client_body combined with stream match leads to stream buffering");
1344  if (has_stream && has_file_data_mpm)
1345  AnalyzerNote(&ctx, (char *)"mpm in file_data combined with stream match leads to stream buffering");
1346  }
1347 
1348  SCJbOpenObject(ctx.js, "lists");
1349  for (int i = 0; i < DETECT_SM_LIST_MAX; i++) {
1350  if (s->sm_arrays[i] != NULL) {
1351  SCJbOpenObject(ctx.js, DetectListToHumanString(i));
1352  DumpMatches(&ctx, ctx.js, s->sm_arrays[i]);
1353  SCJbClose(ctx.js);
1354  }
1355  }
1356  SCJbClose(ctx.js);
1357 
1358  if (pkt_mpm || app_mpm) {
1359  SCJbOpenObject(ctx.js, "mpm");
1360 
1361  int mpm_list = pkt_mpm ? DETECT_SM_LIST_PMATCH : app_mpm->sm_list;
1362  const char *name;
1363  if (mpm_list < DETECT_SM_LIST_DYNAMIC_START)
1364  name = DetectListToHumanString(mpm_list);
1365  else
1367  SCJbSetString(ctx.js, "buffer", name);
1368 
1369  SigMatchData *smd = pkt_mpm ? pkt_mpm->smd : app_mpm->smd;
1370  if (smd == NULL && mpm_list == DETECT_SM_LIST_PMATCH) {
1371  smd = s->sm_arrays[mpm_list];
1372  }
1373  do {
1374  switch (smd->type) {
1375  case DETECT_CONTENT: {
1376  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
1377  if (cd->flags & DETECT_CONTENT_MPM) {
1378  DumpContent(ctx.js, cd);
1379  }
1380  break;
1381  }
1382  }
1383 
1384  if (smd->is_last)
1385  break;
1386  smd++;
1387  } while (1);
1388  SCJbClose(ctx.js);
1389  } else if (s->init_data->prefilter_sm) {
1390  SCJbOpenObject(ctx.js, "prefilter");
1391  int prefilter_list = SigMatchListSMBelongsTo(s, s->init_data->prefilter_sm);
1392  const char *name;
1393  if (prefilter_list < DETECT_SM_LIST_DYNAMIC_START)
1394  name = DetectListToHumanString(prefilter_list);
1395  else
1396  name = DetectEngineBufferTypeGetNameById(de_ctx, prefilter_list);
1397  SCJbSetString(ctx.js, "buffer", name);
1398  const char *mname = sigmatch_table[s->init_data->prefilter_sm->type].name;
1399  SCJbSetString(ctx.js, "name", mname);
1400  SCJbClose(ctx.js);
1401  }
1402 
1403  if (ctx.js_warnings) {
1404  SCJbClose(ctx.js_warnings);
1405  SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
1406  SCJbFree(ctx.js_warnings);
1407  ctx.js_warnings = NULL;
1408  }
1409  if (ctx.js_notes) {
1410  SCJbClose(ctx.js_notes);
1411  SCJbSetObject(ctx.js, "notes", ctx.js_notes);
1412  SCJbFree(ctx.js_notes);
1413  ctx.js_notes = NULL;
1414  }
1415  SCJbClose(ctx.js);
1416 
1417  const char *filename = "rules.json";
1418  const char *log_dir = SCConfigGetLogDirectory();
1419  char json_path[PATH_MAX] = "";
1420  snprintf(json_path, sizeof(json_path), "%s/%s%s", log_dir,
1421  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", filename);
1422 
1424  FILE *fp = fopen(json_path, "a");
1425  if (fp != NULL) {
1426  fwrite(SCJbPtr(ctx.js), SCJbLen(ctx.js), 1, fp);
1427  fprintf(fp, "\n");
1428  fclose(fp);
1429  }
1431  SCJbFree(ctx.js);
1432  SCReturn;
1433 }
1434 
1436 {
1437  if (de_ctx->pattern_hash_table == NULL)
1438  return;
1439 
1440  SCJsonBuilder *root_jb = SCJbNewObject();
1441  SCJsonBuilder *arrays[de_ctx->buffer_type_id];
1442  memset(&arrays, 0, sizeof(SCJsonBuilder *) * de_ctx->buffer_type_id);
1443 
1444  SCJbOpenArray(root_jb, "buffers");
1445 
1447  htb != NULL; htb = HashListTableGetListNext(htb)) {
1448  char str[1024] = "";
1450  DetectContentPatternPrettyPrint(p->cd, str, sizeof(str));
1451 
1452  SCJsonBuilder *jb = arrays[p->sm_list];
1453  if (arrays[p->sm_list] == NULL) {
1454  jb = arrays[p->sm_list] = SCJbNewObject();
1455  const char *name;
1458  else
1460  SCJbSetString(jb, "name", name);
1461  SCJbSetUint(jb, "list_id", p->sm_list);
1462 
1463  SCJbOpenArray(jb, "patterns");
1464  }
1465 
1466  SCJbStartObject(jb);
1467  SCJbSetString(jb, "pattern", str);
1468  SCJbSetUint(jb, "patlen", p->cd->content_len);
1469  SCJbSetUint(jb, "cnt", p->cnt);
1470  SCJbSetUint(jb, "mpm", p->mpm);
1471  SCJbOpenObject(jb, "flags");
1472  SCJbSetBool(jb, "nocase", p->cd->flags & DETECT_CONTENT_NOCASE);
1473  SCJbSetBool(jb, "negated", p->cd->flags & DETECT_CONTENT_NEGATED);
1474  SCJbSetBool(jb, "depth", p->cd->flags & DETECT_CONTENT_DEPTH);
1475  SCJbSetBool(jb, "offset", p->cd->flags & DETECT_CONTENT_OFFSET);
1476  SCJbSetBool(jb, "endswith", p->cd->flags & DETECT_CONTENT_ENDS_WITH);
1477  SCJbClose(jb);
1478  SCJbClose(jb);
1479  }
1480 
1481  for (uint32_t i = 0; i < de_ctx->buffer_type_id; i++) {
1482  SCJsonBuilder *jb = arrays[i];
1483  if (jb == NULL)
1484  continue;
1485 
1486  SCJbClose(jb); // array
1487  SCJbClose(jb); // object
1488 
1489  SCJbAppendObject(root_jb, jb);
1490  SCJbFree(jb);
1491  }
1492  SCJbClose(root_jb);
1493  SCJbClose(root_jb);
1494 
1495  const char *filename = "patterns.json";
1496  const char *log_dir = SCConfigGetLogDirectory();
1497  char json_path[PATH_MAX] = "";
1498  snprintf(json_path, sizeof(json_path), "%s/%s%s", log_dir,
1499  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", filename);
1500 
1502  FILE *fp = fopen(json_path, "a");
1503  if (fp != NULL) {
1504  fwrite(SCJbPtr(root_jb), SCJbLen(root_jb), 1, fp);
1505  fprintf(fp, "\n");
1506  fclose(fp);
1507  }
1509  SCJbFree(root_jb);
1510 
1512  de_ctx->pattern_hash_table = NULL;
1513 }
1514 
1515 static void EngineAnalysisItemsReset(EngineAnalysisCtx *ea_ctx)
1516 {
1517  for (size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
1518  ea_ctx->analyzer_items[i].item_seen = false;
1519  }
1520 }
1521 
1522 static void EngineAnalysisItemsInit(EngineAnalysisCtx *ea_ctx)
1523 {
1524  if (ea_ctx->analyzer_initialized) {
1525  EngineAnalysisItemsReset(ea_ctx);
1526  return;
1527  }
1528 
1529  ea_ctx->exposed_item_seen_list[0].bufname = "http_method";
1530  ea_ctx->exposed_item_seen_list[1].bufname = "file_data";
1531  ea_ctx->analyzer_items = SCCalloc(1, sizeof(analyzer_items));
1532  if (!ea_ctx->analyzer_items) {
1533  FatalError("Unable to allocate analysis scratch pad");
1534  }
1535  memset(ea_ctx->analyzer_item_map, -1, sizeof(ea_ctx->analyzer_item_map));
1536 
1537  for (size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
1538  ea_ctx->analyzer_items[i] = analyzer_items[i];
1539  DetectEngineAnalyzerItems *analyzer_item = &ea_ctx->analyzer_items[i];
1540 
1541  int item_id = DetectBufferTypeGetByName(analyzer_item->item_name);
1542  DEBUG_VALIDATE_BUG_ON(item_id < 0 || item_id > UINT16_MAX);
1543  analyzer_item->item_id = (uint16_t)item_id;
1544  if (analyzer_item->item_id == -1) {
1545  /* Mismatch between the analyzer_items array and what's supported */
1546  FatalError("unable to initialize engine-analysis table: detect buffer \"%s\" not "
1547  "recognized.",
1548  analyzer_item->item_name);
1549  }
1550  analyzer_item->item_seen = false;
1551 
1552  if (analyzer_item->export_item_seen) {
1553  for (size_t k = 0; k < ARRAY_SIZE(ea_ctx->exposed_item_seen_list); k++) {
1554  if (0 ==
1555  strcmp(ea_ctx->exposed_item_seen_list[k].bufname, analyzer_item->item_name))
1556  ea_ctx->exposed_item_seen_list[k].item_seen_ptr = &analyzer_item->item_seen;
1557  }
1558  }
1559  ea_ctx->analyzer_item_map[analyzer_item->item_id] = (int16_t)i;
1560  }
1561 
1562  ea_ctx->analyzer_initialized = true;
1563 }
1564 
1565 /**
1566  * \brief Prints analysis of loaded rules.
1567  *
1568  * Warns if potential rule issues are detected. For example,
1569  * warns if a rule uses a construct that may perform poorly,
1570  * e.g. pcre without content or with http_method content only;
1571  * warns if a rule uses a construct that may not be consistent with intent,
1572  * e.g. client side ports only, http and content without any http_* modifiers, etc.
1573  *
1574  * \param s Pointer to the signature.
1575  */
1577  const Signature *s, const char *line)
1578 {
1579  uint32_t rule_bidirectional = 0;
1580  uint32_t rule_pcre = 0;
1581  uint32_t rule_pcre_http = 0;
1582  uint32_t rule_content = 0;
1583  uint32_t rule_flow = 0;
1584  uint32_t rule_flags = 0;
1585  uint32_t rule_flow_toserver = 0;
1586  uint32_t rule_flow_toclient = 0;
1587  uint32_t rule_flow_nostream = 0;
1588  uint32_t rule_ipv4_only = 0;
1589  uint32_t rule_ipv6_only = 0;
1590  uint32_t rule_flowbits = 0;
1591  uint32_t rule_flowint = 0;
1592  uint32_t rule_content_http = 0;
1593  uint32_t rule_content_offset_depth = 0;
1594  int32_t list_id = 0;
1595  uint32_t rule_warning = 0;
1596  uint32_t stream_buf = 0;
1597  uint32_t packet_buf = 0;
1598  uint32_t file_store = 0;
1599  uint32_t warn_pcre_no_content = 0;
1600  uint32_t warn_pcre_http_content = 0;
1601  uint32_t warn_pcre_http = 0;
1602  uint32_t warn_content_http_content = 0;
1603  uint32_t warn_content_http = 0;
1604  uint32_t warn_tcp_no_flow = 0;
1605  uint32_t warn_client_ports = 0;
1606  uint32_t warn_direction = 0;
1607  uint32_t warn_method_toclient = 0;
1608  uint32_t warn_method_serverbody = 0;
1609  uint32_t warn_pcre_method = 0;
1610  uint32_t warn_encoding_norm_http_buf = 0;
1611  uint32_t warn_file_store_not_present = 0;
1612  uint32_t warn_offset_depth_pkt_stream = 0;
1613  uint32_t warn_offset_depth_alproto = 0;
1614  uint32_t warn_non_alproto_fp_for_alproto_sig = 0;
1615  uint32_t warn_no_direction = 0;
1616  uint32_t warn_both_direction = 0;
1617 
1618  EngineAnalysisItemsInit(de_ctx->ea);
1619 
1620  bool *http_method_item_seen_ptr = de_ctx->ea->exposed_item_seen_list[0].item_seen_ptr;
1621  bool *http_server_body_item_seen_ptr = de_ctx->ea->exposed_item_seen_list[1].item_seen_ptr;
1622 
1624  rule_bidirectional = 1;
1625  }
1626 
1627  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
1628  packet_buf += 1;
1629  }
1630  if (s->flags & SIG_FLAG_FILESTORE) {
1631  file_store += 1;
1632  }
1633  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
1634  stream_buf += 1;
1635  }
1636 
1637  if (s->proto.flags & DETECT_PROTO_IPV4) {
1638  rule_ipv4_only += 1;
1639  }
1640  if (s->proto.flags & DETECT_PROTO_IPV6) {
1641  rule_ipv6_only += 1;
1642  }
1643 
1644  for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
1645  SigMatch *sm = NULL;
1646  for (sm = s->init_data->smlists[list_id]; sm != NULL; sm = sm->next) {
1647  int16_t item_slot = de_ctx->ea->analyzer_item_map[list_id];
1648  if (sm->type == DETECT_PCRE) {
1649  if (item_slot == -1) {
1650  rule_pcre++;
1651  continue;
1652  }
1653 
1654  rule_pcre_http++;
1655  de_ctx->ea->analyzer_items[item_slot].item_seen = true;
1656  } else if (sm->type == DETECT_CONTENT) {
1657  if (item_slot == -1) {
1658  rule_content++;
1659  if (list_id == DETECT_SM_LIST_PMATCH) {
1662  rule_content_offset_depth++;
1663  }
1664  }
1665  continue;
1666  }
1667 
1668  rule_content_http++;
1669  de_ctx->ea->analyzer_items[item_slot].item_seen = true;
1670 
1671  if (de_ctx->ea->analyzer_items[item_slot].check_encoding_match) {
1673  if (cd != NULL &&
1674  PerCentEncodingMatch(de_ctx->ea, cd->content, cd->content_len) > 0) {
1675  warn_encoding_norm_http_buf += 1;
1676  }
1677  }
1678  }
1679  else if (sm->type == DETECT_FLOW) {
1680  rule_flow += 1;
1681  if ((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_TOCLIENT)) {
1682  rule_flow_toserver = 1;
1683  }
1684  else if ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_TOSERVER)) {
1685  rule_flow_toclient = 1;
1686  }
1687  DetectFlowData *fd = (DetectFlowData *)sm->ctx;
1688  if (fd != NULL) {
1689  if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM)
1690  rule_flow_nostream = 1;
1691  }
1692  }
1693  else if (sm->type == DETECT_FLOWBITS) {
1694  if (list_id == DETECT_SM_LIST_MATCH) {
1695  rule_flowbits += 1;
1696  }
1697  }
1698  else if (sm->type == DETECT_FLOWINT) {
1699  if (list_id == DETECT_SM_LIST_MATCH) {
1700  rule_flowint += 1;
1701  }
1702  }
1703  else if (sm->type == DETECT_FLAGS) {
1704  DetectFlagsData *fd = (DetectFlagsData *)sm->ctx;
1705  if (fd != NULL) {
1706  rule_flags = 1;
1707  }
1708  }
1709  } /* for (sm = s->init_data->smlists[list_id]; sm != NULL; sm = sm->next) */
1710 
1711  } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */
1712 
1713  if (file_store && !RequiresFeature("output::file-store")) {
1714  rule_warning += 1;
1715  warn_file_store_not_present = 1;
1716  }
1717 
1718  if (rule_pcre > 0 && rule_content == 0 && rule_content_http == 0) {
1719  rule_warning += 1;
1720  warn_pcre_no_content = 1;
1721  }
1722 
1723  if (rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0) {
1724  rule_warning += 1;
1725  warn_pcre_http_content = 1;
1726  } else if (s->alproto == ALPROTO_HTTP1 && rule_pcre > 0 && rule_pcre_http == 0) {
1727  rule_warning += 1;
1728  warn_pcre_http = 1;
1729  }
1730 
1731  if (rule_content > 0 && rule_content_http > 0) {
1732  rule_warning += 1;
1733  warn_content_http_content = 1;
1734  }
1735  if (s->alproto == ALPROTO_HTTP1 && rule_content > 0 && rule_content_http == 0) {
1736  rule_warning += 1;
1737  warn_content_http = 1;
1738  }
1739  if (rule_content == 1) {
1740  //todo: warning if content is weak, separate warning for pcre + weak content
1741  }
1742  if (rule_flow == 0 && rule_flags == 0 && !(s->proto.flags & DETECT_PROTO_ANY) &&
1743  DetectProtoContainsProto(&s->proto, IPPROTO_TCP) &&
1744  (rule_content || rule_content_http || rule_pcre || rule_pcre_http || rule_flowbits ||
1745  rule_flowint)) {
1746  rule_warning += 1;
1747  warn_tcp_no_flow = 1;
1748  }
1749  if (rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)
1750  && !((s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))) {
1751  if (((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))
1752  || ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_DP_ANY) && (s->flags & SIG_FLAG_SP_ANY))) {
1753  rule_warning += 1;
1754  warn_client_ports = 1;
1755  }
1756  }
1757  if (rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)) {
1758  rule_warning += 1;
1759  warn_direction = 1;
1760  }
1761 
1762  if (*http_method_item_seen_ptr) {
1763  if (rule_flow && rule_flow_toclient) {
1764  rule_warning += 1;
1765  warn_method_toclient = 1;
1766  }
1767  if (*http_server_body_item_seen_ptr) {
1768  rule_warning += 1;
1769  warn_method_serverbody = 1;
1770  }
1771  if (rule_content == 0 && rule_content_http == 0 && (rule_pcre > 0 || rule_pcre_http > 0)) {
1772  rule_warning += 1;
1773  warn_pcre_method = 1;
1774  }
1775  }
1776  if (rule_content_offset_depth > 0 && stream_buf && packet_buf) {
1777  rule_warning += 1;
1778  warn_offset_depth_pkt_stream = 1;
1779  }
1780  if (rule_content_offset_depth > 0 && !stream_buf && packet_buf && s->alproto != ALPROTO_UNKNOWN) {
1781  rule_warning += 1;
1782  warn_offset_depth_alproto = 1;
1783  }
1784  if (s->init_data->mpm_sm != NULL && s->alproto == ALPROTO_HTTP1 &&
1786  rule_warning += 1;
1787  warn_non_alproto_fp_for_alproto_sig = 1;
1788  }
1789 
1790  if ((s->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) {
1791  warn_no_direction += 1;
1792  rule_warning += 1;
1793  }
1794 
1795  /* No warning about direction for ICMP protos */
1796  if (!(DetectProtoContainsProto(&s->proto, IPPROTO_ICMPV6) && DetectProtoContainsProto(&s->proto, IPPROTO_ICMP))) {
1798  warn_both_direction += 1;
1799  rule_warning += 1;
1800  }
1801  }
1802 
1803  if (!rule_warnings_only || (rule_warnings_only && rule_warning > 0)) {
1804  FILE *fp = de_ctx->ea->rule_engine_analysis_fp;
1805  fprintf(fp, "== Sid: %u ==\n", s->id);
1806  fprintf(fp, "%s\n", line);
1807 
1808  switch (s->type) {
1809  case SIG_TYPE_NOT_SET:
1810  break;
1811  case SIG_TYPE_IPONLY:
1812  fprintf(fp, " Rule is ip only.\n");
1813  break;
1814  case SIG_TYPE_LIKE_IPONLY:
1815  fprintf(fp, " Rule is like ip only.\n");
1816  break;
1817  case SIG_TYPE_PDONLY:
1818  fprintf(fp, " Rule is PD only.\n");
1819  break;
1820  case SIG_TYPE_DEONLY:
1821  fprintf(fp, " Rule is DE only.\n");
1822  break;
1823  case SIG_TYPE_PKT:
1824  fprintf(fp, " Rule is packet inspecting.\n");
1825  break;
1826  case SIG_TYPE_PKT_STREAM:
1827  fprintf(fp, " Rule is packet and stream inspecting.\n");
1828  break;
1829  case SIG_TYPE_STREAM:
1830  fprintf(fp, " Rule is stream inspecting.\n");
1831  break;
1832  case SIG_TYPE_APPLAYER:
1833  fprintf(fp, " Rule is app-layer inspecting.\n");
1834  break;
1835  case SIG_TYPE_APP_TX:
1836  fprintf(fp, " Rule is App-layer TX inspecting.\n");
1837  break;
1838  case SIG_TYPE_MAX:
1839  break;
1840  }
1841  if (rule_ipv6_only)
1842  fprintf(fp, " Rule is IPv6 only.\n");
1843  if (rule_ipv4_only)
1844  fprintf(fp, " Rule is IPv4 only.\n");
1845  if (packet_buf)
1846  fprintf(fp, " Rule matches on packets.\n");
1847  if (!rule_flow_nostream && stream_buf &&
1848  (rule_flow || rule_flowbits || rule_flowint || rule_content || rule_pcre)) {
1849  fprintf(fp, " Rule matches on reassembled stream.\n");
1850  }
1851  for(size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
1853  if (ai->item_seen) {
1854  fprintf(fp, " Rule matches on %s buffer.\n", ai->display_name);
1855  }
1856  }
1857  if (s->alproto != ALPROTO_UNKNOWN) {
1858  fprintf(fp, " App layer protocol is %s.\n", AppProtoToString(s->alproto));
1859  }
1860  if (rule_content || rule_content_http || rule_pcre || rule_pcre_http) {
1861  fprintf(fp,
1862  " Rule contains %u content options, %u http content options, %u pcre "
1863  "options, and %u pcre options with http modifiers.\n",
1864  rule_content, rule_content_http, rule_pcre, rule_pcre_http);
1865  }
1866 
1867  /* print fast pattern info */
1868  if (s->init_data->prefilter_sm) {
1869  fprintf(fp, " Prefilter on: %s.\n",
1871  } else {
1872  EngineAnalysisRulesPrintFP(de_ctx, s);
1873  }
1874 
1875  /* this is where the warnings start */
1876  if (warn_pcre_no_content /*rule_pcre > 0 && rule_content == 0 && rule_content_http == 0*/) {
1877  fprintf(fp, " Warning: Rule uses pcre without a content option present.\n"
1878  " -Consider adding a content to improve performance of this "
1879  "rule.\n");
1880  }
1881  if (warn_pcre_http_content /*rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0*/) {
1882  fprintf(fp, " Warning: Rule uses content options with http_* and pcre options "
1883  "without http modifiers.\n"
1884  " -Consider adding http pcre modifier.\n");
1885  }
1886  else if (warn_pcre_http /*s->alproto == ALPROTO_HTTP1 && rule_pcre > 0 && rule_pcre_http == 0*/) {
1887  fprintf(fp, " Warning: Rule app layer protocol is http, but pcre options do not "
1888  "have http modifiers.\n"
1889  " -Consider adding http pcre modifiers.\n");
1890  }
1891  if (warn_content_http_content /*rule_content > 0 && rule_content_http > 0*/) {
1892  fprintf(fp,
1893  " Warning: Rule contains content with http_* and content without http_*.\n"
1894  " -Consider adding http content modifiers.\n");
1895  }
1896  if (warn_content_http /*s->alproto == ALPROTO_HTTP1 && rule_content > 0 && rule_content_http == 0*/) {
1897  fprintf(fp, " Warning: Rule app layer protocol is http, but content options do not "
1898  "have http_* modifiers.\n"
1899  " -Consider adding http content modifiers.\n");
1900  }
1901  if (rule_content == 1) {
1902  //todo: warning if content is weak, separate warning for pcre + weak content
1903  }
1904  if (warn_encoding_norm_http_buf) {
1905  fprintf(fp, " Warning: Rule may contain percent encoded content for a normalized "
1906  "http buffer match.\n");
1907  }
1908  if (warn_tcp_no_flow /*rule_flow == 0 && rule_flags == 0
1909  && !(s->proto.flags & DETECT_PROTO_ANY) && DetectProtoContainsProto(&s->proto, IPPROTO_TCP)*/) {
1910  fprintf(fp, " Warning: TCP rule without a flow or flags option.\n"
1911  " -Consider adding flow or flags to improve performance of "
1912  "this rule.\n");
1913  }
1914  if (warn_client_ports /*rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)
1915  && !((s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY)))
1916  if (((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))
1917  || ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_DP_ANY) && (s->flags & SIG_FLAG_SP_ANY))*/) {
1918  fprintf(fp,
1919  " Warning: Rule contains ports or port variables only on the client side.\n"
1920  " -Flow direction possibly inconsistent with rule.\n");
1921  }
1922  if (warn_direction /*rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)*/) {
1923  fprintf(fp, " Warning: Rule is bidirectional and has a flow option with a specific "
1924  "direction.\n");
1925  }
1926  if (warn_method_toclient /*http_method_buf && rule_flow && rule_flow_toclient*/) {
1927  fprintf(fp, " Warning: Rule uses content or pcre for http_method with "
1928  "flow:to_client or from_server\n");
1929  }
1930  if (warn_method_serverbody /*http_method_buf && http_server_body_buf*/) {
1931  fprintf(fp, " Warning: Rule uses content or pcre for http_method with content or "
1932  "pcre for http_server_body.\n");
1933  }
1934  if (warn_pcre_method /*http_method_buf && rule_content == 0 && rule_content_http == 0
1935  && (rule_pcre > 0 || rule_pcre_http > 0)*/) {
1936  fprintf(fp, " Warning: Rule uses pcre with only a http_method content; possible "
1937  "performance issue.\n");
1938  }
1939  if (warn_offset_depth_pkt_stream) {
1940  fprintf(fp, " Warning: Rule has depth"
1941  "/offset with raw content keywords. Please note the "
1942  "offset/depth will be checked against both packet "
1943  "payloads and stream. If you meant to have the offset/"
1944  "depth checked against just the payload, you can update "
1945  "the signature as \"alert tcp-pkt...\"\n");
1946  }
1947  if (warn_offset_depth_alproto) {
1948  fprintf(fp,
1949  " Warning: Rule has "
1950  "offset/depth set along with a match on a specific "
1951  "app layer protocol - %d. This can lead to FNs if we "
1952  "have a offset/depth content match on a packet payload "
1953  "before we can detect the app layer protocol for the "
1954  "flow.\n",
1955  s->alproto);
1956  }
1957  if (warn_non_alproto_fp_for_alproto_sig) {
1958  fprintf(fp, " Warning: Rule app layer "
1959  "protocol is http, but the fast_pattern is set on the raw "
1960  "stream. Consider adding fast_pattern over a http "
1961  "buffer for increased performance.");
1962  }
1963  if (warn_no_direction) {
1964  fprintf(fp, " Warning: Rule has no direction indicator.\n");
1965  }
1966  if (warn_both_direction) {
1967  fprintf(fp, " Warning: Rule is inspecting both the request and the response.\n");
1968  }
1969  if (warn_file_store_not_present) {
1970  fprintf(fp, " Warning: Rule requires file-store but the output file-store is not "
1971  "enabled.\n");
1972  }
1973  if (rule_warning == 0) {
1974  fprintf(fp, " No warnings for this rule.\n");
1975  }
1976  fprintf(fp, "\n");
1977  }
1978 }
1979 
1980 #include "app-layer-parser.h"
1981 
1982 static void FirewallAddRulesForState(const DetectEngineCtx *de_ctx, const AppProto a,
1983  const uint8_t state, const uint8_t direction, RuleAnalyzer *ctx)
1984 {
1985  uint32_t accept_rules = 0;
1986  SCJbSetString(ctx->js, "policy", "drop:flow");
1987  SCJbOpenArray(ctx->js, "rules");
1988  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
1989  if ((s->flags & SIG_FLAG_FIREWALL) == 0)
1990  break;
1991  if (s->type != SIG_TYPE_APP_TX)
1992  continue;
1993  if (s->alproto != a)
1994  continue;
1995 
1996  if (direction == STREAM_TOSERVER) {
1997  if (s->flags & SIG_FLAG_TOCLIENT) {
1998  continue;
1999  }
2000  } else {
2001  if (s->flags & SIG_FLAG_TOSERVER) {
2002  continue;
2003  }
2004  }
2005 
2006  if (s->app_progress_hook == state) {
2007  SCJbAppendString(ctx->js, s->sig_str);
2008  accept_rules += ((s->action & ACTION_ACCEPT) != 0);
2009  }
2010  }
2011  SCJbClose(ctx->js);
2012 
2013  if (accept_rules == 0) {
2014  AnalyzerWarning(ctx, (char *)"no accept rules for state, default policy will be applied");
2015  }
2016 }
2017 
2019 {
2020  RuleAnalyzer ctx = { NULL, NULL, NULL };
2021  ctx.js = SCJbNewObject();
2022  if (ctx.js == NULL)
2023  return -1;
2024 
2025  SCJbOpenObject(ctx.js, "tables");
2026  SCJbOpenObject(ctx.js, "packet:filter");
2027  SCJbSetString(ctx.js, "policy", "drop:packet");
2028  SCJbOpenArray(ctx.js, "rules");
2029  uint32_t accept_rules = 0;
2030  uint32_t last_sid = 0;
2031  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2032  if ((s->flags & SIG_FLAG_FIREWALL) == 0)
2033  break;
2034  if (s->type != SIG_TYPE_PKT)
2035  continue;
2036  /* don't double list <> sigs */
2037  if (last_sid == s->id)
2038  continue;
2039  last_sid = s->id;
2040  SCJbAppendString(ctx.js, s->sig_str);
2041  accept_rules += ((s->action & ACTION_ACCEPT) != 0);
2042  }
2043  SCJbClose(ctx.js);
2044  if (accept_rules == 0) {
2045  AnalyzerWarning(&ctx,
2046  (char *)"no accept rules for \'packet:filter\', default policy will be applied");
2047  }
2048  if (ctx.js_warnings) {
2049  SCJbClose(ctx.js_warnings);
2050  SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
2051  SCJbFree(ctx.js_warnings);
2052  ctx.js_warnings = NULL;
2053  }
2054  SCJbClose(ctx.js); // packet_filter
2055 
2056  for (AppProto a = 0; a < g_alproto_max; a++) {
2057  if (!AppProtoIsValid(a))
2058  continue;
2059 
2060  // HACK not all protocols have named states yet
2061  const char *hack = AppLayerParserGetStateNameById(IPPROTO_TCP, a, 0, STREAM_TOSERVER);
2062  if (!hack)
2063  continue;
2064 
2065  SCJbOpenObject(ctx.js, AppProtoToString(a));
2066  const uint8_t complete_state_ts =
2067  (const uint8_t)AppLayerParserGetStateProgressCompletionStatus(a, STREAM_TOSERVER);
2068  for (uint8_t state = 0; state < complete_state_ts; state++) {
2069  const char *name =
2070  AppLayerParserGetStateNameById(IPPROTO_TCP, a, state, STREAM_TOSERVER);
2071  char table_name[128];
2072  snprintf(table_name, sizeof(table_name), "app:%s:%s", AppProtoToString(a), name);
2073  SCJbOpenObject(ctx.js, table_name);
2074  FirewallAddRulesForState(de_ctx, a, state, STREAM_TOSERVER, &ctx);
2075  if (ctx.js_warnings) {
2076  SCJbClose(ctx.js_warnings);
2077  SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
2078  SCJbFree(ctx.js_warnings);
2079  ctx.js_warnings = NULL;
2080  }
2081  SCJbClose(ctx.js);
2082  }
2083  const uint8_t complete_state_tc =
2084  (const uint8_t)AppLayerParserGetStateProgressCompletionStatus(a, STREAM_TOCLIENT);
2085  for (uint8_t state = 0; state < complete_state_tc; state++) {
2086  const char *name =
2087  AppLayerParserGetStateNameById(IPPROTO_TCP, a, state, STREAM_TOCLIENT);
2088  char table_name[128];
2089  snprintf(table_name, sizeof(table_name), "app:%s:%s", AppProtoToString(a), name);
2090  SCJbOpenObject(ctx.js, table_name);
2091  FirewallAddRulesForState(de_ctx, a, state, STREAM_TOCLIENT, &ctx);
2092  if (ctx.js_warnings) {
2093  SCJbClose(ctx.js_warnings);
2094  SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
2095  SCJbFree(ctx.js_warnings);
2096  ctx.js_warnings = NULL;
2097  }
2098  SCJbClose(ctx.js);
2099  }
2100  SCJbClose(ctx.js); // app layer
2101  }
2102  SCJbOpenObject(ctx.js, "packet:td");
2103  SCJbSetString(ctx.js, "policy", "accept:hook");
2104  last_sid = 0;
2105  SCJbOpenArray(ctx.js, "rules");
2106  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2107  if ((s->flags & SIG_FLAG_FIREWALL) != 0)
2108  continue;
2109  if (s->type == SIG_TYPE_APP_TX)
2110  continue;
2111  if (last_sid == s->id)
2112  continue;
2113  last_sid = s->id;
2114  SCJbAppendString(ctx.js, s->sig_str);
2115  }
2116  SCJbClose(ctx.js); // rules
2117  SCJbClose(ctx.js); // packet:td
2118  SCJbOpenObject(ctx.js, "app:td");
2119  SCJbSetString(ctx.js, "policy", "accept:hook");
2120  last_sid = 0;
2121  SCJbOpenArray(ctx.js, "rules");
2122  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2123  if ((s->flags & SIG_FLAG_FIREWALL) != 0)
2124  continue;
2125  if (s->type != SIG_TYPE_APP_TX)
2126  continue;
2127  if (last_sid == s->id)
2128  continue;
2129  last_sid = s->id;
2130  SCJbAppendString(ctx.js, s->sig_str);
2131  }
2132  SCJbClose(ctx.js); // rules
2133  SCJbClose(ctx.js); // app:td
2134  SCJbClose(ctx.js); // tables
2135 
2136  SCJbOpenObject(ctx.js, "lists");
2137  SCJbOpenObject(ctx.js, "firewall");
2138  last_sid = 0;
2139  SCJbOpenArray(ctx.js, "rules");
2140  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2141  if ((s->flags & SIG_FLAG_FIREWALL) == 0)
2142  continue;
2143  if (last_sid == s->id)
2144  continue;
2145  last_sid = s->id;
2146  SCJbAppendString(ctx.js, s->sig_str);
2147  }
2148  SCJbClose(ctx.js); // rules
2149  SCJbClose(ctx.js); // firewall
2150 
2151  SCJbOpenObject(ctx.js, "td");
2152  last_sid = 0;
2153  SCJbOpenArray(ctx.js, "rules");
2154  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2155  if ((s->flags & SIG_FLAG_FIREWALL) != 0)
2156  continue;
2157  if (last_sid == s->id)
2158  continue;
2159  last_sid = s->id;
2160  SCJbAppendString(ctx.js, s->sig_str);
2161  }
2162  SCJbClose(ctx.js); // rules
2163  SCJbClose(ctx.js); // td
2164 
2165  SCJbOpenObject(ctx.js, "all");
2166  last_sid = 0;
2167  SCJbOpenArray(ctx.js, "rules");
2168  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2169  if (last_sid == s->id)
2170  continue;
2171  last_sid = s->id;
2172  SCJbAppendString(ctx.js, s->sig_str);
2173  }
2174  SCJbClose(ctx.js); // rules
2175  SCJbClose(ctx.js); // all
2176 
2177  SCJbClose(ctx.js); // lists
2178 
2179  SCJbClose(ctx.js); // top level object
2180 
2181  const char *filename = "firewall.json";
2182  const char *log_dir = SCConfigGetLogDirectory();
2183  char json_path[PATH_MAX] = "";
2184  snprintf(json_path, sizeof(json_path), "%s/%s", log_dir, filename);
2185 
2187  FILE *fp = fopen(json_path, "w");
2188  if (fp != NULL) {
2189  fwrite(SCJbPtr(ctx.js), SCJbLen(ctx.js), 1, fp);
2190  fprintf(fp, "\n");
2191  fclose(fp);
2192  }
2194  SCJbFree(ctx.js);
2195  return 0;
2196 }
detect-tcp-flags.h
DETECT_PCRE_CASELESS
#define DETECT_PCRE_CASELESS
Definition: detect-pcre.h:32
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:853
DetectBytejumpData_::post_offset
int32_t post_offset
Definition: detect-bytejump.h:51
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:56
SIG_TYPE_STREAM
@ SIG_TYPE_STREAM
Definition: detect.h:74
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:107
DetectBytetestData_::flags
uint16_t flags
Definition: detect-bytetest.h:58
detect-engine-uint.h
DetectPatternTracker
Definition: detect.h:808
SignatureInitData_::rule_state_dependant_sids_idx
uint32_t rule_state_dependant_sids_idx
Definition: detect.h:659
DetectEngineAppInspectionEngine_
Definition: detect.h:416
DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_RELATIVE_NEXT
Definition: detect-content.h:66
DetectEngineAppInspectionEngine_::mpm
bool mpm
Definition: detect.h:420
detect-content.h
DetectFlowbitsData_::or_list_size
uint8_t or_list_size
Definition: detect-flowbits.h:38
len
uint8_t len
Definition: app-layer-dnp3.h:2
SCConfValIsTrue
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:551
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:119
SIG_MASK_REQUIRE_REAL_PKT
#define SIG_MASK_REQUIRE_REAL_PKT
Definition: detect.h:316
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:642
DetectContentData_::fp_chop_len
uint16_t fp_chop_len
Definition: detect-content.h:98
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
Signature_::sig_str
char * sig_str
Definition: detect.h:745
SIG_TYPE_APP_TX
@ SIG_TYPE_APP_TX
Definition: detect.h:77
DetectSeqData_::seq
uint32_t seq
Definition: detect-tcp-seq.h:31
AppLayerParserGetStateNameById
const char * AppLayerParserGetStateNameById(uint8_t ipproto, AppProto alproto, const int id, const uint8_t direction)
Definition: app-layer-parser.c:1617
DetectIcmpIdData_
Definition: detect-icmp-id.h:27
DetectEnginePktInspectionEngine
Definition: detect.h:483
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:441
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:1457
DETECT_BYTEJUMP
@ DETECT_BYTEJUMP
Definition: detect-engine-register.h:83
DetectPatternTracker::mpm
uint32_t mpm
Definition: detect.h:812
DETECT_ABSENT
@ DETECT_ABSENT
Definition: detect-engine-register.h:95
DetectListToHumanString
const char * DetectListToHumanString(int list)
Definition: detect-parse.c:112
DetectEngineCtx_::pattern_hash_table
HashListTable * pattern_hash_table
Definition: detect.h:965
DumpPatterns
void DumpPatterns(DetectEngineCtx *de_ctx)
Definition: detect-engine-analyzer.c:1435
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:474
Signature_::app_progress_hook
uint8_t app_progress_hook
Definition: detect.h:705
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:69
SignatureInitData_::prefilter_sm
SigMatch * prefilter_sm
Definition: detect.h:625
EngineAnalysisCtx_::rule_engine_analysis_fp
FILE * rule_engine_analysis_fp
Definition: detect-engine-analyzer.c:85
DETECT_FLOW
@ DETECT_FLOW
Definition: detect-engine-register.h:54
Signature_::alproto
AppProto alproto
Definition: detect.h:673
SignatureInitData_::is_rule_state_dependant
bool is_rule_state_dependant
Definition: detect.h:656
detect-isdataat.h
DETECT_BYTETEST_BASE_HEX
#define DETECT_BYTETEST_BASE_HEX
Definition: detect-bytetest.h:40
SigMatchData_::is_last
bool is_last
Definition: detect.h:367
g_rules_analyzer_write_m
SCMutex g_rules_analyzer_write_m
Definition: detect-engine-analyzer.c:987
DetectEngineAnalyzerItems::display_name
const char * display_name
Definition: detect-engine-analyzer.c:67
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:86
DETECT_CONTENT_WITHIN2DEPTH
#define DETECT_CONTENT_WITHIN2DEPTH
Definition: detect-content.h:62
EngineAnalysisCtx_::percent_re
pcre2_code * percent_re
Definition: detect-engine-analyzer.c:90
DETECT_SM_LIST_DYNAMIC_START
@ DETECT_SM_LIST_DYNAMIC_START
Definition: detect.h:138
DETECT_FLOWBITS_CMD_ISNOTSET
#define DETECT_FLOWBITS_CMD_ISNOTSET
Definition: detect-flowbits.h:31
SIG_FLAG_DEST_IS_TARGET
#define SIG_FLAG_DEST_IS_TARGET
Definition: detect.h:285
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:368
DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED
#define DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED
Definition: detect-content.h:55
action-globals.h
EngineAnalysisCtx_
Definition: detect-engine-analyzer.c:83
DETECT_IPOPTS
@ DETECT_IPOPTS
Definition: detect-engine-register.h:39
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:40
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:518
DetectFlowData_::flags
uint16_t flags
Definition: detect-flow.h:38
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:932
DETECT_PROTO_ANY
#define DETECT_PROTO_ANY
Definition: detect-engine-proto.h:28
DetectEnginePktInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:484
AppLayerParserGetStateProgressCompletionStatus
int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto, uint8_t direction)
Definition: app-layer-parser.c:1116
SIG_TYPE_PKT_STREAM
@ SIG_TYPE_PKT_STREAM
Definition: detect.h:73
DetectFlowbitsData_::cmd
uint8_t cmd
Definition: detect-flowbits.h:37
DetectEngineFrameInspectionEngine::mpm
bool mpm
Definition: detect.h:512
DETECT_BYTETEST_DCE
#define DETECT_BYTETEST_DCE
Definition: detect-bytetest.h:47
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:287
detect-tcp-seq.h
EngineAnalysisCtx_::fp_pattern_stats
FpPatternStats fp_pattern_stats[DETECT_SM_LIST_MAX]
Definition: detect-engine-analyzer.c:102
DetectEngineBufferTypeGetNameById
const char * DetectEngineBufferTypeGetNameById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1308
SIG_FLAG_DST_ANY
#define SIG_FLAG_DST_ANY
Definition: detect.h:242
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:255
DetectPatternTracker::cnt
uint32_t cnt
Definition: detect.h:811
rust.h
EngineAnalysisCtx_::fp_engine_analysis_fp
FILE * fp_engine_analysis_fp
Definition: detect-engine-analyzer.c:86
SCConfGetBool
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:497
EngineAnalysisCtx_::analyzer_initialized
bool analyzer_initialized
Definition: detect-engine-analyzer.c:109
DetectEngineAnalyzerItems
Definition: detect-engine-analyzer.c:61
DETECT_BYTEJUMP_DCE
#define DETECT_BYTEJUMP_DCE
Definition: detect-bytejump.h:40
DetectPatternTracker::cd
const struct DetectContentData_ * cd
Definition: detect.h:809
VarNameStoreSetupLookup
const char * VarNameStoreSetupLookup(const uint32_t id, const enum VarTypes type)
Definition: util-var-name.c:188
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:731
FpPatternStats_::max
uint16_t max
Definition: detect-engine-analyzer.c:72
SignatureInitData_::init_flags
uint32_t init_flags
Definition: detect.h:608
DetectBufferType_
Definition: detect.h:449
DETECT_FLOWBITS_CMD_TOGGLE
#define DETECT_FLOWBITS_CMD_TOGGLE
Definition: detect-flowbits.h:29
DetectContentData_
Definition: detect-content.h:93
DETECT_FLOWBITS_CMD_ISSET
#define DETECT_FLOWBITS_CMD_ISSET
Definition: detect-flowbits.h:32
DetectPcreData_::flags
uint16_t flags
Definition: detect-pcre.h:51
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:824
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:101
DetectWindowData_
Definition: detect-tcp-window.h:21
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:272
DETECT_BYTEJUMP_BIG
#define DETECT_BYTEJUMP_BIG
Definition: detect-bytejump.h:36
SIG_FLAG_SRC_ANY
#define SIG_FLAG_SRC_ANY
Definition: detect.h:241
EngineAnalysisRulesFailure
void EngineAnalysisRulesFailure(const DetectEngineCtx *de_ctx, const char *line, const char *file, int lineno)
Definition: detect-engine-analyzer.c:621
SigMatchData_
Data needed for Match()
Definition: detect.h:365
DetectBytejumpData_::base
uint8_t base
Definition: detect-bytejump.h:48
detect-pcre.h
SIG_TYPE_APPLAYER
@ SIG_TYPE_APPLAYER
Definition: detect.h:76
SigMatchData_::type
uint16_t type
Definition: detect.h:366
DetectBytejumpData_
Definition: detect-bytejump.h:46
Signature_::frame_inspect
DetectEngineFrameInspectionEngine * frame_inspect
Definition: detect.h:727
DetectBytejumpData_::offset
int32_t offset
Definition: detect-bytejump.h:50
DetectEngineFrameInspectionEngine::v1
struct DetectEngineFrameInspectionEngine::@92 v1
DetectEnginePktInspectionEngine::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:492
EngineAnalysisCtx_::analyzer_items
DetectEngineAnalyzerItems * analyzer_items
Definition: detect-engine-analyzer.c:88
DETECT_PERCENT_ENCODING_REGEX
#define DETECT_PERCENT_ENCODING_REGEX
FirewallAnalyzer
int FirewallAnalyzer(const DetectEngineCtx *de_ctx)
Definition: detect-engine-analyzer.c:2018
DetectBytejumpData_::multiplier
uint16_t multiplier
Definition: detect-bytejump.h:52
SIG_FLAG_APPLAYER
#define SIG_FLAG_APPLAYER
Definition: detect.h:249
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1278
SIG_FLAG_FIREWALL
#define SIG_FLAG_FIREWALL
Definition: detect.h:246
Signature_::gid
uint32_t gid
Definition: detect.h:714
Signature_::next
struct Signature_ * next
Definition: detect.h:750
ACTION_REJECT_DST
#define ACTION_REJECT_DST
Definition: action-globals.h:32
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:424
ATTR_FMT_PRINTF
#define ATTR_FMT_PRINTF(x, y)
Definition: suricata-common.h:427
DetectFlowbitsData_
Definition: detect-flowbits.h:35
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:55
DetectEngineAnalyzerItems::export_item_seen
bool export_item_seen
Definition: detect-engine-analyzer.c:64
SignaturePropertyFlowAction
SignaturePropertyFlowAction
Definition: detect.h:83
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:271
RequiresFeature
bool RequiresFeature(const char *feature_name)
Definition: feature.c:126
DETECT_BYTETEST_RELATIVE
#define DETECT_BYTETEST_RELATIVE
Definition: detect-bytetest.h:46
SIG_TYPE_PKT
@ SIG_TYPE_PKT
Definition: detect.h:72
DetectSeqData_
seq data
Definition: detect-tcp-seq.h:30
feature.h
RuleAnalyzer::js
SCJsonBuilder * js
Definition: detect-engine-analyzer.c:637
IpOptsFlagToString
const char * IpOptsFlagToString(uint16_t flag)
Return human readable value for ipopts flag.
Definition: detect-ipopts.c:117
JB_SET_STRING
#define JB_SET_STRING(jb, key, val)
Definition: rust.h:31
EngineAnalysisCtx
struct EngineAnalysisCtx_ EngineAnalysisCtx
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:18
DetectEnginePktInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:486
SIG_FLAG_INIT_BIDIREC
#define SIG_FLAG_INIT_BIDIREC
Definition: detect.h:293
g_alproto_max
AppProto g_alproto_max
Definition: app-layer-protos.c:29
DETECT_FLOWINT
@ DETECT_FLOWINT
Definition: detect-engine-register.h:62
SIG_MASK_REQUIRE_ENGINE_EVENT
#define SIG_MASK_REQUIRE_ENGINE_EVENT
Definition: detect.h:318
DETECT_ICODE
@ DETECT_ICODE
Definition: detect-engine-register.h:48
DETECT_FLOW_AGE
@ DETECT_FLOW_AGE
Definition: detect-engine-register.h:128
DETECT_BYTETEST_BASE_UNSET
#define DETECT_BYTETEST_BASE_UNSET
Definition: detect-bytetest.h:37
SIG_TYPE_IPONLY
@ SIG_TYPE_IPONLY
Definition: detect.h:66
DETECT_BYTEJUMP_ALIGN
#define DETECT_BYTEJUMP_ALIGN
Definition: detect-bytejump.h:39
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:623
DetectEngineBufferTypeGetDescriptionById
const char * DetectEngineBufferTypeGetDescriptionById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1386
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
SIG_FLAG_FLUSH
#define SIG_FLAG_FLUSH
Definition: detect.h:259
DetectIpOptsData_::ipopt
uint16_t ipopt
Definition: detect-ipopts.h:38
SignatureInitData_::mpm_sm_list
int mpm_sm_list
Definition: detect.h:621
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:312
SIG_FLAG_BYPASS
#define SIG_FLAG_BYPASS
Definition: detect.h:276
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:636
DETECT_BYTEJUMP_END
#define DETECT_BYTEJUMP_END
Definition: detect-bytejump.h:42
Signature_::pkt_inspect
DetectEnginePktInspectionEngine * pkt_inspect
Definition: detect.h:726
DetectEngineAnalyzerItems
struct DetectEngineAnalyzerItems DetectEngineAnalyzerItems
util-print.h
DetectWindowData_::negated
uint8_t negated
Definition: detect-tcp-window.h:22
SCEnter
#define SCEnter(...)
Definition: util-debug.h:281
detect-engine-mpm.h
detect.h
SIG_MASK_REQUIRE_FLAGS_INITDEINIT
#define SIG_MASK_REQUIRE_FLAGS_INITDEINIT
Definition: detect.h:313
SignatureInitData_::rule_state_flowbits_ids_size
uint32_t rule_state_flowbits_ids_size
Definition: detect.h:661
DetectEngineFrameInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:513
detect-tcp-window.h
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:360
DetectEngineAnalyzerItems::item_seen
bool item_seen
Definition: detect-engine-analyzer.c:63
DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_NEGATED
Definition: detect-content.h:40
DetectU8Data
DetectUintData_u8 DetectU8Data
Definition: detect-engine-uint.h:43
util-time.h
DETECT_ICMP_ID
@ DETECT_ICMP_ID
Definition: detect-engine-register.h:49
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:117
DetectAckData_::ack
uint32_t ack
Definition: detect-tcp-ack.h:31
EngineAnalysisRules
void EngineAnalysisRules(const DetectEngineCtx *de_ctx, const Signature *s, const char *line)
Prints analysis of loaded rules.
Definition: detect-engine-analyzer.c:1576
app-layer-parser.h
Signature_::app_inspect
DetectEngineAppInspectionEngine * app_inspect
Definition: detect.h:725
DETECT_SEQ
@ DETECT_SEQ
Definition: detect-engine-register.h:37
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:359
DETECT_ACK
@ DETECT_ACK
Definition: detect-engine-register.h:36
RuleAnalyzer::js_warnings
SCJsonBuilder * js_warnings
Definition: detect-engine-analyzer.c:639
SIG_FLAG_REQUIRE_FLOWVAR
#define SIG_FLAG_REQUIRE_FLOWVAR
Definition: detect.h:267
Signature_::action
uint8_t action
Definition: detect.h:683
FpPatternStats_::cnt
uint32_t cnt
Definition: detect-engine-analyzer.c:73
SCReturn
#define SCReturn
Definition: util-debug.h:283
Signature_::flags
uint32_t flags
Definition: detect.h:669
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:106
ACTION_ALERT
#define ACTION_ALERT
Definition: action-globals.h:29
DETECT_BYTETEST_BIG
#define DETECT_BYTETEST_BIG
Definition: detect-bytetest.h:44
SCLocalTime
struct tm * SCLocalTime(time_t timep, struct tm *result)
Definition: util-time.c:267
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:673
DetectEngineFrameInspectionEngine
Definition: detect.h:508
DetectFlowbitsData_::idx
uint32_t idx
Definition: detect-flowbits.h:36
DetectEngineBufferTypeGetById
const DetectBufferType * DetectEngineBufferTypeGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1298
DETECT_BYTEJUMP_BASE_UNSET
#define DETECT_BYTEJUMP_BASE_UNSET
Definition: detect-bytejump.h:28
name
const char * name
Definition: tm-threads.c:2163
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:747
SIG_FLAG_SRC_IS_TARGET
#define SIG_FLAG_SRC_IS_TARGET
Definition: detect.h:283
SignatureInitData_::rule_state_dependant_sids_array
uint32_t * rule_state_dependant_sids_array
Definition: detect.h:657
DetectContentPatternPrettyPrint
void DetectContentPatternPrettyPrint(const DetectContentData *cd, char *str, size_t str_len)
Definition: detect-content.c:748
SignatureInitData_::rule_state_dependant_sids_size
uint32_t rule_state_dependant_sids_size
Definition: detect.h:658
DetectIcmpIdData_::id
uint16_t id
Definition: detect-icmp-id.h:28
DetectEngineTransforms::transforms
TransformData transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:392
DETECT_BYTEJUMP_BASE_HEX
#define DETECT_BYTEJUMP_BASE_HEX
Definition: detect-bytejump.h:31
SIG_TYPE_DEONLY
@ SIG_TYPE_DEONLY
Definition: detect.h:71
SIG_PROP_FLOW_ACTION_PACKET
@ SIG_PROP_FLOW_ACTION_PACKET
Definition: detect.h:84
signature_properties
const struct SignatureProperties signature_properties[SIG_TYPE_MAX]
Definition: detect-engine.c:116
detect-flowbits.h
SIG_MASK_REQUIRE_PAYLOAD
#define SIG_MASK_REQUIRE_PAYLOAD
Definition: detect.h:311
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:229
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:71
DetectWindowData_::size
uint16_t size
Definition: detect-tcp-window.h:23
DETECT_DSIZE
@ DETECT_DSIZE
Definition: detect-engine-register.h:52
SIG_TYPE_NOT_SET
@ SIG_TYPE_NOT_SET
Definition: detect.h:65
ExposedItemSeen::bufname
const char * bufname
Definition: detect-engine-analyzer.c:79
DETECT_BYTEJUMP_OFFSET_BE
#define DETECT_BYTEJUMP_OFFSET_BE
Definition: detect-bytejump.h:41
DetectEngineCtx_::config_prefix
char config_prefix[64]
Definition: detect.h:1051
DetectSigmatchListEnumToString
const char * DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type)
Definition: detect-engine.c:4978
analyzer_items
const DetectEngineAnalyzerItems analyzer_items[]
Definition: detect-engine-analyzer.c:112
DetectEngineAppInspectionEngine_::alproto
AppProto alproto
Definition: detect.h:417
SIG_FLAG_MPM_NEG
#define SIG_FLAG_MPM_NEG
Definition: detect.h:257
detect-engine-analyzer.h
SIG_FLAG_INIT_STATE_MATCH
#define SIG_FLAG_INIT_STATE_MATCH
Definition: detect.h:296
DetectEngineAnalyzerItems::item_id
int16_t item_id
Definition: detect-engine-analyzer.c:62
DetectPatternTracker::sm_list
int sm_list
Definition: detect.h:810
DetectEngineAppInspectionEngine_::smd
SigMatchData * smd
Definition: detect.h:439
EngineAnalysisRules2
void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
Definition: detect-engine-analyzer.c:988
ACTION_REJECT_BOTH
#define ACTION_REJECT_BOTH
Definition: action-globals.h:33
ARRAY_SIZE
#define ARRAY_SIZE(arr)
Definition: suricata-common.h:562
DETECT_CONTENT_STARTS_WITH
#define DETECT_CONTENT_STARTS_WITH
Definition: detect-content.h:59
DetectProto_::flags
uint8_t flags
Definition: detect-engine-proto.h:37
DETECT_BYTETEST
@ DETECT_BYTETEST
Definition: detect-engine-register.h:82
DETECT_PROTO_IPV4
#define DETECT_PROTO_IPV4
Definition: detect-engine-proto.h:31
util-conf.h
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:883
FpPatternStats_::min
uint16_t min
Definition: detect-engine-analyzer.c:71
VAR_TYPE_FLOW_BIT
@ VAR_TYPE_FLOW_BIT
Definition: util-var.h:36
Signature_::proto
DetectProto proto
Definition: detect.h:687
SCNtohs
#define SCNtohs(x)
Definition: suricata-common.h:431
suricata-common.h
SIG_MASK_REQUIRE_NO_PAYLOAD
#define SIG_MASK_REQUIRE_NO_PAYLOAD
Definition: detect.h:315
SIG_FLAG_SP_ANY
#define SIG_FLAG_SP_ANY
Definition: detect.h:243
SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL
@ SIG_PROP_FLOW_ACTION_FLOW_IF_STATEFUL
Definition: detect.h:86
ActionScope
ActionScope
Definition: action-globals.h:42
DetectAbsentData_
Definition: detect-isdataat.h:37
ExposedItemSeen
Definition: detect-engine-analyzer.c:78
SigMatch_::type
uint16_t type
Definition: detect.h:357
DetectEngineAppInspectionEngine_::v2
struct DetectEngineAppInspectionEngine_::@88 v2
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:88
DetectEngineAnalyzerItems::check_encoding_match
bool check_encoding_match
Definition: detect-engine-analyzer.c:65
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:509
DetectBytejumpData_::nbytes
uint8_t nbytes
Definition: detect-bytejump.h:47
Signature_::action_scope
uint8_t action_scope
Definition: detect.h:690
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:36
DetectEngineFrameInspectionEngine::next
struct DetectEngineFrameInspectionEngine * next
Definition: detect.h:521
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:494
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:94
Signature_::rev
uint32_t rev
Definition: detect.h:715
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
FatalError
#define FatalError(...)
Definition: util-debug.h:514
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:941
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:314
TransformData_::transform
int transform
Definition: detect.h:387
DETECT_FLOWBITS
@ DETECT_FLOWBITS
Definition: detect-engine-register.h:59
SIG_TYPE_MAX
@ SIG_TYPE_MAX
Definition: detect.h:79
DetectEngineCtx_::ea
struct EngineAnalysisCtx_ * ea
Definition: detect.h:1129
DetectEngineAppInspectionEngine_::progress
int16_t progress
Definition: detect.h:426
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:169
SignatureInitData_::firewall_rule
bool firewall_rule
Definition: detect.h:664
FpPatternStats
struct FpPatternStats_ FpPatternStats
detect-tcp-ack.h
str
#define str(s)
Definition: suricata-common.h:308
SCConfGetNode
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition: conf.c:181
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:271
SigMatchListSMBelongsTo
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
Definition: detect-parse.c:763
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DetectFlowbitsData_::or_list
uint32_t * or_list
Definition: detect-flowbits.h:42
Signature_::id
uint32_t id
Definition: detect.h:713
DETECT_CONTENT_OFFSET
#define DETECT_CONTENT_OFFSET
Definition: detect-content.h:32
HashListTableBucket_
Definition: util-hashlist.h:28
DETECT_FLOWBITS_CMD_UNSET
#define DETECT_FLOWBITS_CMD_UNSET
Definition: detect-flowbits.h:30
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:462
detect-parse.h
Signature_
Signature container.
Definition: detect.h:668
SigMatch_
a single match condition for a signature
Definition: detect.h:356
DetectEngineAppInspectionEngine_::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:436
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:135
FpPatternStats_::tot
uint64_t tot
Definition: detect-engine-analyzer.c:74
DETECT_BYTETEST_STRING
#define DETECT_BYTETEST_STRING
Definition: detect-bytetest.h:45
DetectBytetestData_::offset
int32_t offset
Definition: detect-bytetest.h:60
DetectFlagsData_
Definition: detect-tcp-flags.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
detect-ipopts.h
DetectEngineTransforms::cnt
int cnt
Definition: detect.h:393
suricata.h
DetectPcreData_
Definition: detect-pcre.h:47
DetectEngineAppInspectionEngine_::dir
uint8_t dir
Definition: detect.h:418
DetectEngineAnalyzerItems::item_name
const char * item_name
Definition: detect-engine-analyzer.c:66
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:80
DETECT_BYTEJUMP_STRING
#define DETECT_BYTEJUMP_STRING
Definition: detect-bytejump.h:37
DetectEngineCtx_::buffer_type_id
uint32_t buffer_type_id
Definition: detect.h:1081
EngineAnalysisCtx_::file_prefix
char * file_prefix
Definition: detect-engine-analyzer.c:89
DetectEnginePktInspectionEngine::mpm
bool mpm
Definition: detect.h:485
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:660
SIG_PROP_FLOW_ACTION_FLOW
@ SIG_PROP_FLOW_ACTION_FLOW
Definition: detect.h:85
DETECT_PCRE_RELATIVE
#define DETECT_PCRE_RELATIVE
Definition: detect-pcre.h:29
RuleAnalyzer
struct RuleAnalyzer RuleAnalyzer
DETECT_WINDOW
@ DETECT_WINDOW
Definition: detect-engine-register.h:38
SIG_FLAG_TLSSTORE
#define SIG_FLAG_TLSSTORE
Definition: detect.h:274
DetectU16Data
DetectUintData_u16 DetectU16Data
Definition: detect-engine-uint.h:42
Signature_::msg
char * msg
Definition: detect.h:736
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:640
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:107
Signature_::type
enum SignatureType type
Definition: detect.h:671
SCConfNode_
Definition: conf.h:37
FpPatternStats_
Definition: detect-engine-analyzer.c:70
DetectBytetestData_::base
uint8_t base
Definition: detect-bytetest.h:56
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:70
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
SIG_FLAG_PREFILTER
#define SIG_FLAG_PREFILTER
Definition: detect.h:278
SignatureProperties::flow_action
enum SignaturePropertyFlowAction flow_action
Definition: detect.h:90
DETECT_TCPMSS
@ DETECT_TCPMSS
Definition: detect-engine-register.h:289
DetectAckData_
ack data
Definition: detect-tcp-ack.h:30
SIG_FLAG_FILESTORE
#define SIG_FLAG_FILESTORE
Definition: detect.h:269
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:244
DetectEnginePktInspectionEngine::v1
struct DetectEnginePktInspectionEngine::@91 v1
DETECT_FLOWBITS_CMD_SET
#define DETECT_FLOWBITS_CMD_SET
Definition: detect-flowbits.h:28
SIG_FLAG_DSIZE
#define SIG_FLAG_DSIZE
Definition: detect.h:248
DetectBytejumpData_::flags
uint16_t flags
Definition: detect-bytejump.h:49
Signature_::mask
SignatureMask mask
Definition: detect.h:679
SIG_TYPE_LIKE_IPONLY
@ SIG_TYPE_LIKE_IPONLY
Definition: detect.h:67
detect-bytetest.h
DetectProtoContainsProto
int DetectProtoContainsProto(const DetectProto *dp, int proto)
see if a DetectProto contains a certain proto
Definition: detect-engine-proto.c:135
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:254
DetectEngineFrameInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:520