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