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