suricata
detect-engine-analyzer.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2023 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 "detect.h"
31 #include "detect-parse.h"
32 #include "detect-engine.h"
33 #include "detect-engine-analyzer.h"
34 #include "detect-engine-mpm.h"
35 #include "conf.h"
36 #include "detect-content.h"
37 #include "detect-pcre.h"
38 #include "detect-bytejump.h"
39 #include "detect-bytetest.h"
40 #include "detect-flow.h"
41 #include "detect-tcp-flags.h"
42 #include "detect-ipopts.h"
43 #include "feature.h"
44 #include "util-print.h"
45 #include "util-time.h"
46 #include "util-validate.h"
47 #include "util-conf.h"
48 #include "detect-flowbits.h"
49 #include "util-var-name.h"
50 
51 static int rule_warnings_only = 0;
52 
53 /* Details for each buffer being tracked */
54 typedef struct DetectEngineAnalyzerItems {
55  int16_t item_id;
56  bool item_seen;
59  const char *item_name;
60  const char *display_name;
62 
63 typedef struct FpPatternStats_ {
64  uint16_t min;
65  uint16_t max;
66  uint32_t cnt;
67  uint64_t tot;
69 
70 /* Track which items require the item_seen value to be exposed */
72  const char *bufname;
74 };
75 
76 typedef struct EngineAnalysisCtx_ {
77 
80 
82  char *file_prefix;
83  pcre2_code *percent_re;
84 
85  /*
86  * This array contains the map between the `analyzer_items` array listed above and
87  * the item ids returned by DetectBufferTypeGetByName. Iterating signature's sigmatch
88  * array provides list_ids. The map converts those ids into elements of the
89  * analyzer items array.
90  *
91  * Ultimately, the g_buffer_type_hash is searched for each buffer name. The size of that
92  * hashlist is 256, so that's the value we use here.
93  */
94  int16_t analyzer_item_map[256];
96  /*
97  * Certain values must be directly accessible. This array contains items that are directly
98  * accessed when checking if they've been seen or not.
99  */
101 
104 
106  /* request keywords */
107  { 0, false, false, true, "http_uri", "http uri" },
108  { 0, false, false, false, "http_raw_uri", "http raw uri" },
109  { 0, false, true, false, "http_method", "http method" },
110  { 0, false, false, false, "http_request_line", "http request line" },
111  { 0, false, false, false, "http_client_body", "http client body" },
112  { 0, false, false, true, "http_header", "http header" },
113  { 0, false, false, false, "http_raw_header", "http raw header" },
114  { 0, false, false, true, "http_cookie", "http cookie" },
115  { 0, false, false, false, "http_user_agent", "http user agent" },
116  { 0, false, false, false, "http_host", "http host" },
117  { 0, false, false, false, "http_raw_host", "http raw host" },
118  { 0, false, false, false, "http_accept_enc", "http accept enc" },
119  { 0, false, false, false, "http_referer", "http referer" },
120  { 0, false, false, false, "http_content_type", "http content type" },
121  { 0, false, false, false, "http_header_names", "http header names" },
122 
123  /* response keywords not listed above */
124  { 0, false, false, false, "http_stat_msg", "http stat msg" },
125  { 0, false, false, false, "http_stat_code", "http stat code" },
126  { 0, false, true, false, "file_data", "http server body" },
127 
128  /* missing request keywords */
129  { 0, false, false, false, "http_request_line", "http request line" },
130  { 0, false, false, false, "http_accept", "http accept" },
131  { 0, false, false, false, "http_accept_lang", "http accept lang" },
132  { 0, false, false, false, "http_connection", "http connection" },
133  { 0, false, false, false, "http_content_len", "http content len" },
134  { 0, false, false, false, "http_protocol", "http protocol" },
135  { 0, false, false, false, "http_start", "http start" },
136 
137  /* missing response keywords; some of the missing are listed above*/
138  { 0, false, false, false, "http_response_line", "http response line" },
139  { 0, false, false, false, "http.server", "http server" },
140  { 0, false, false, false, "http.location", "http location" },
141 };
142 
143 static void FpPatternStatsAdd(FpPatternStats *fp, int list, uint16_t patlen)
144 {
145  if (list < 0 || list >= DETECT_SM_LIST_MAX)
146  return;
147 
148  FpPatternStats *f = &fp[list];
149 
150  if (f->min == 0)
151  f->min = patlen;
152  else if (patlen < f->min)
153  f->min = patlen;
154 
155  if (patlen > f->max)
156  f->max = patlen;
157 
158  f->cnt++;
159  f->tot += patlen;
160 }
161 
162 void EngineAnalysisFP(const DetectEngineCtx *de_ctx, const Signature *s, char *line)
163 {
164  int fast_pattern_set = 0;
165  int fast_pattern_only_set = 0;
166  int fast_pattern_chop_set = 0;
167  const DetectContentData *fp_cd = NULL;
168  const SigMatch *mpm_sm = s->init_data->mpm_sm;
169  const int mpm_sm_list = s->init_data->mpm_sm_list;
170 
171  if (mpm_sm != NULL) {
172  fp_cd = (DetectContentData *)mpm_sm->ctx;
173  if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN) {
174  fast_pattern_set = 1;
176  fast_pattern_only_set = 1;
177  } else if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
178  fast_pattern_chop_set = 1;
179  }
180  }
181  }
182 
183  FILE *fp = de_ctx->ea->rule_engine_analysis_fp;
184  fprintf(fp, "== Sid: %u ==\n", s->id);
185  fprintf(fp, "%s\n", line);
186 
187  fprintf(fp, " Fast Pattern analysis:\n");
188  if (s->init_data->prefilter_sm != NULL) {
189  fprintf(fp, " Prefilter on: %s\n",
191  fprintf(fp, "\n");
192  return;
193  }
194 
195  if (fp_cd == NULL) {
196  fprintf(fp, " No content present\n");
197  fprintf(fp, "\n");
198  return;
199  }
200 
201  fprintf(fp, " Fast pattern matcher: ");
202  int list_type = mpm_sm_list;
203  if (list_type == DETECT_SM_LIST_PMATCH)
204  fprintf(fp, "content\n");
205  else {
206  const char *desc = DetectEngineBufferTypeGetDescriptionById(de_ctx, list_type);
207  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, list_type);
208  if (desc && name) {
209  fprintf(fp, "%s (%s)\n", desc, name);
210  }
211  }
212 
213  int flags_set = 0;
214  fprintf(fp, " Flags:");
215  if (fp_cd->flags & DETECT_CONTENT_OFFSET) {
216  fprintf(fp, " Offset");
217  flags_set = 1;
218  } if (fp_cd->flags & DETECT_CONTENT_DEPTH) {
219  fprintf(fp, " Depth");
220  flags_set = 1;
221  }
222  if (fp_cd->flags & DETECT_CONTENT_WITHIN) {
223  fprintf(fp, " Within");
224  flags_set = 1;
225  }
226  if (fp_cd->flags & DETECT_CONTENT_DISTANCE) {
227  fprintf(fp, " Distance");
228  flags_set = 1;
229  }
230  if (fp_cd->flags & DETECT_CONTENT_NOCASE) {
231  fprintf(fp, " Nocase");
232  flags_set = 1;
233  }
234  if (fp_cd->flags & DETECT_CONTENT_NEGATED) {
235  fprintf(fp, " Negated");
236  flags_set = 1;
237  }
238  if (flags_set == 0)
239  fprintf(fp, " None");
240  fprintf(fp, "\n");
241 
242  fprintf(fp, " Fast pattern set: %s\n", fast_pattern_set ? "yes" : "no");
243  fprintf(fp, " Fast pattern only set: %s\n", fast_pattern_only_set ? "yes" : "no");
244  fprintf(fp, " Fast pattern chop set: %s\n", fast_pattern_chop_set ? "yes" : "no");
245  if (fast_pattern_chop_set) {
246  fprintf(fp, " Fast pattern offset, length: %u, %u\n", fp_cd->fp_chop_offset,
247  fp_cd->fp_chop_len);
248  }
249 
250  uint16_t patlen = fp_cd->content_len;
251  uint8_t *pat = SCMalloc(fp_cd->content_len + 1);
252  if (unlikely(pat == NULL)) {
253  FatalError("Error allocating memory");
254  }
255  memcpy(pat, fp_cd->content, fp_cd->content_len);
256  pat[fp_cd->content_len] = '\0';
257  fprintf(fp, " Original content: ");
258  PrintRawUriFp(fp, pat, patlen);
259  fprintf(fp, "\n");
260 
261  if (fast_pattern_chop_set) {
262  SCFree(pat);
263  patlen = fp_cd->fp_chop_len;
264  pat = SCMalloc(fp_cd->fp_chop_len + 1);
265  if (unlikely(pat == NULL)) {
266  exit(EXIT_FAILURE);
267  }
268  memcpy(pat, fp_cd->content + fp_cd->fp_chop_offset, fp_cd->fp_chop_len);
269  pat[fp_cd->fp_chop_len] = '\0';
270  fprintf(fp, " Final content: ");
271  PrintRawUriFp(fp, pat, patlen);
272  fprintf(fp, "\n");
273 
274  FpPatternStatsAdd(&de_ctx->ea->fp_pattern_stats[0], list_type, patlen);
275  } else {
276  fprintf(fp, " Final content: ");
277  PrintRawUriFp(fp, pat, patlen);
278  fprintf(fp, "\n");
279 
280  FpPatternStatsAdd(&de_ctx->ea->fp_pattern_stats[0], list_type, patlen);
281  }
282  SCFree(pat);
283 
284  fprintf(fp, "\n");
285  return;
286 }
287 
288 /**
289  * \brief Sets up the fast pattern analyzer according to the config.
290  *
291  * \retval 1 If rule analyzer successfully enabled.
292  * \retval 0 If not enabled.
293  */
294 static int SetupFPAnalyzer(DetectEngineCtx *de_ctx)
295 {
296  int fp_engine_analysis_set = 0;
297 
298  if ((ConfGetBool("engine-analysis.rules-fast-pattern",
299  &fp_engine_analysis_set)) == 0) {
300  return false;
301  }
302 
303  if (fp_engine_analysis_set == 0)
304  return false;
305 
306  const char *log_dir = ConfigGetLogDirectory();
307  char *log_path = SCMalloc(PATH_MAX);
308  if (log_path == NULL) {
309  FatalError("Unable to allocate scratch memory for rule filename");
310  }
311  snprintf(log_path, PATH_MAX, "%s/%s%s", log_dir,
312  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", "rules_fast_pattern.txt");
313 
314  FILE *fp = fopen(log_path, "w");
315  if (fp == NULL) {
316  SCLogError("failed to open %s: %s", log_path, strerror(errno));
317  SCFree(log_path);
318  return false;
319  }
320 
322 
323  SCLogInfo("Engine-Analysis for fast_pattern printed to file - %s",
324  log_path);
325  SCFree(log_path);
326 
327  struct timeval tval;
328  gettimeofday(&tval, NULL);
329  struct tm local_tm;
330  struct tm *tms = SCLocalTime(tval.tv_sec, &local_tm);
331  fprintf(fp, "----------------------------------------------"
332  "---------------------\n");
333  fprintf(fp,
334  "Date: %" PRId32 "/%" PRId32 "/%04d -- "
335  "%02d:%02d:%02d\n",
336  tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
337  tms->tm_sec);
338  fprintf(fp, "----------------------------------------------"
339  "---------------------\n");
340 
341  memset(&de_ctx->ea->fp_pattern_stats[0], 0, sizeof(de_ctx->ea->fp_pattern_stats));
342  return true;
343 }
344 
345 /**
346  * \brief Compiles regex for rule analysis
347  * \retval 1 if successful
348  * \retval 0 if on error
349  */
350 static bool PerCentEncodingSetup(EngineAnalysisCtx *ea_ctx)
351 {
352 #define DETECT_PERCENT_ENCODING_REGEX "%[0-9|a-f|A-F]{2}"
353  int en;
354  PCRE2_SIZE eo = 0;
355  int opts = 0; // PCRE2_NEWLINE_ANY??
356 
357  ea_ctx->percent_re = pcre2_compile((PCRE2_SPTR8)DETECT_PERCENT_ENCODING_REGEX,
358  PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
359  if (ea_ctx->percent_re == NULL) {
360  PCRE2_UCHAR errbuffer[256];
361  pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
362  SCLogError("Compile of \"%s\" failed at offset %d: %s", DETECT_PERCENT_ENCODING_REGEX,
363  (int)eo, errbuffer);
364  return false;
365  }
366 
367  return true;
368 }
369 /**
370  * \brief Sets up the rule analyzer according to the config
371  * \retval 1 if rule analyzer successfully enabled
372  * \retval 0 if not enabled
373  */
374 static int SetupRuleAnalyzer(DetectEngineCtx *de_ctx)
375 {
376  ConfNode *conf = ConfGetNode("engine-analysis");
377  int enabled = 0;
378  if (conf != NULL) {
379  const char *value = ConfNodeLookupChildValue(conf, "rules");
380  if (value && ConfValIsTrue(value)) {
381  enabled = 1;
382  } else if (value && strcasecmp(value, "warnings-only") == 0) {
383  enabled = 1;
384  rule_warnings_only = 1;
385  }
386  if (enabled) {
387  const char *log_dir;
388  log_dir = ConfigGetLogDirectory();
389  char log_path[PATH_MAX];
390  snprintf(log_path, sizeof(log_path), "%s/%s%s", log_dir,
391  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", "rules_analysis.txt");
392  de_ctx->ea->rule_engine_analysis_fp = fopen(log_path, "w");
393  if (de_ctx->ea->rule_engine_analysis_fp == NULL) {
394  SCLogError("failed to open %s: %s", log_path, strerror(errno));
395  return 0;
396  }
397 
398  SCLogInfo("Engine-Analysis for rules printed to file - %s",
399  log_path);
400 
401  struct timeval tval;
402  gettimeofday(&tval, NULL);
403  struct tm local_tm;
404  struct tm *tms = SCLocalTime(tval.tv_sec, &local_tm);
406  "----------------------------------------------"
407  "---------------------\n");
409  "Date: %" PRId32 "/%" PRId32 "/%04d -- "
410  "%02d:%02d:%02d\n",
411  tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min,
412  tms->tm_sec);
414  "----------------------------------------------"
415  "---------------------\n");
416 
417  /*compile regex's for rule analysis*/
418  if (!PerCentEncodingSetup(de_ctx->ea)) {
420  "Error compiling regex; can't check for percent encoding in normalized "
421  "http content.\n");
422  }
423  }
424  }
425  else {
426  SCLogInfo("Conf parameter \"engine-analysis.rules\" not found. "
427  "Defaulting to not printing the rules analysis report.");
428  }
429  if (!enabled) {
430  SCLogInfo("Engine-Analysis for rules disabled in conf file.");
431  return 0;
432  }
433  return 1;
434 }
435 
436 static void CleanupFPAnalyzer(DetectEngineCtx *de_ctx)
437 {
438  FILE *fp = de_ctx->ea->rule_engine_analysis_fp;
439  fprintf(fp, "============\n"
440  "Summary:\n============\n");
441 
442  for (int i = 0; i < DETECT_SM_LIST_MAX; i++) {
444  if (f->cnt == 0)
445  continue;
446 
447  fprintf(fp,
448  "%s, smallest pattern %u byte(s), longest pattern %u byte(s), number of patterns "
449  "%u, avg pattern len %.2f byte(s)\n",
450  DetectSigmatchListEnumToString(i), f->min, f->max, f->cnt,
451  (float)((double)f->tot / (float)f->cnt));
452  }
453 
456 
457  return;
458 }
459 
460 static void CleanupRuleAnalyzer(DetectEngineCtx *de_ctx)
461 {
462  if (de_ctx->ea->fp_engine_analysis_fp != NULL) {
463  fclose(de_ctx->ea->fp_engine_analysis_fp);
465  }
466  if (de_ctx->ea->percent_re != NULL) {
467  pcre2_code_free(de_ctx->ea->percent_re);
468  }
469 }
470 
471 void SetupEngineAnalysis(DetectEngineCtx *de_ctx, bool *fp_analysis, bool *rule_analysis)
472 {
473  *fp_analysis = false;
474  *rule_analysis = false;
475 
476  EngineAnalysisCtx *ea = SCCalloc(1, sizeof(EngineAnalysisCtx));
477  if (ea == NULL) {
478  FatalError("Unable to allocate per-engine analysis context");
479  }
480 
481  ea->file_prefix = NULL;
482  int cfg_prefix_len = strlen(de_ctx->config_prefix);
483  if (cfg_prefix_len > 0) {
484  /* length of prefix + NULL + "." */
485  ea->file_prefix = SCCalloc(1, cfg_prefix_len + 1 + 1);
486  if (ea->file_prefix == NULL) {
487  FatalError("Unable to allocate per-engine analysis context name buffer");
488  }
489 
490  snprintf(ea->file_prefix, cfg_prefix_len + 1 + 1, "%s.", de_ctx->config_prefix);
491  }
492 
493  de_ctx->ea = ea;
494 
495  *fp_analysis = SetupFPAnalyzer(de_ctx);
496  *rule_analysis = SetupRuleAnalyzer(de_ctx);
497 
498  if (!(*fp_analysis || *rule_analysis)) {
499  if (ea->file_prefix)
500  SCFree(ea->file_prefix);
501  if (ea->analyzer_items)
502  SCFree(ea->analyzer_items);
503  SCFree(ea);
504  }
505 }
506 
508 {
509  if (de_ctx->ea) {
510  CleanupRuleAnalyzer(de_ctx);
511  CleanupFPAnalyzer(de_ctx);
512  if (de_ctx->ea->file_prefix)
514  if (de_ctx->ea->analyzer_items)
516  SCFree(de_ctx->ea);
517  de_ctx->ea = NULL;
518  }
519 }
520 
521 /**
522  * \brief Checks for % encoding in content.
523  * \param Pointer to content
524  * \retval number of matches if content has % encoding
525  * \retval 0 if it doesn't have % encoding
526  * \retval -1 on error
527  */
528 static int PerCentEncodingMatch(EngineAnalysisCtx *ea_ctx, uint8_t *content, uint16_t content_len)
529 {
530  int ret = 0;
531 
532  pcre2_match_data *match = pcre2_match_data_create_from_pattern(ea_ctx->percent_re, NULL);
533  ret = pcre2_match(ea_ctx->percent_re, (PCRE2_SPTR8)content, content_len, 0, 0, match, NULL);
534  if (ret == -1) {
535  return 0;
536  } else if (ret < -1) {
537  SCLogError("Error parsing content - %s; error code is %d", content, ret);
538  ret = -1;
539  }
540  pcre2_match_data_free(match);
541  return ret;
542 }
543 
544 static void EngineAnalysisRulesPrintFP(const DetectEngineCtx *de_ctx, const Signature *s)
545 {
546  const DetectContentData *fp_cd = NULL;
547  const SigMatch *mpm_sm = s->init_data->mpm_sm;
548  const int mpm_sm_list = s->init_data->mpm_sm_list;
549 
550  if (mpm_sm != NULL) {
551  fp_cd = (DetectContentData *)mpm_sm->ctx;
552  }
553 
554  if (fp_cd == NULL) {
555  return;
556  }
557 
558  uint16_t patlen = fp_cd->content_len;
559  uint8_t *pat = SCMalloc(fp_cd->content_len + 1);
560  if (unlikely(pat == NULL)) {
561  FatalError("Error allocating memory");
562  }
563 
564  EngineAnalysisCtx *ea_ctx = de_ctx->ea;
565 
566  memcpy(pat, fp_cd->content, fp_cd->content_len);
567  pat[fp_cd->content_len] = '\0';
568 
570  SCFree(pat);
571  patlen = fp_cd->fp_chop_len;
572  pat = SCMalloc(fp_cd->fp_chop_len + 1);
573  if (unlikely(pat == NULL)) {
574  exit(EXIT_FAILURE);
575  }
576  memcpy(pat, fp_cd->content + fp_cd->fp_chop_offset, fp_cd->fp_chop_len);
577  pat[fp_cd->fp_chop_len] = '\0';
578  fprintf(ea_ctx->rule_engine_analysis_fp, " Fast Pattern \"");
579  PrintRawUriFp(ea_ctx->rule_engine_analysis_fp, pat, patlen);
580  } else {
581  fprintf(ea_ctx->rule_engine_analysis_fp, " Fast Pattern \"");
582  PrintRawUriFp(ea_ctx->rule_engine_analysis_fp, pat, patlen);
583  }
584  SCFree(pat);
585 
586  fprintf(ea_ctx->rule_engine_analysis_fp, "\" on \"");
587 
588  const int list_type = mpm_sm_list;
589  if (list_type == DETECT_SM_LIST_PMATCH) {
590  int payload = 0;
591  int stream = 0;
593  payload = 1;
595  stream = 1;
596  fprintf(ea_ctx->rule_engine_analysis_fp, "%s",
597  payload ? (stream ? "payload and reassembled stream" : "payload")
598  : "reassembled stream");
599  }
600  else {
601  const char *desc = DetectEngineBufferTypeGetDescriptionById(de_ctx, list_type);
602  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, list_type);
603  if (desc && name) {
604  fprintf(ea_ctx->rule_engine_analysis_fp, "%s (%s)", desc, name);
605  } else if (desc || name) {
606  fprintf(ea_ctx->rule_engine_analysis_fp, "%s", desc ? desc : name);
607  }
608 
609  }
610 
611  fprintf(ea_ctx->rule_engine_analysis_fp, "\" ");
612  const DetectBufferType *bt = DetectEngineBufferTypeGetById(de_ctx, list_type);
613  if (bt && bt->transforms.cnt) {
614  fprintf(ea_ctx->rule_engine_analysis_fp, "(with %d transform(s)) ", bt->transforms.cnt);
615  }
616  fprintf(ea_ctx->rule_engine_analysis_fp, "buffer.\n");
617 
618  return;
619 }
620 
621 void EngineAnalysisRulesFailure(const DetectEngineCtx *de_ctx, char *line, char *file, int lineno)
622 {
623  fprintf(de_ctx->ea->fp_engine_analysis_fp, "== Sid: UNKNOWN ==\n");
624  fprintf(de_ctx->ea->fp_engine_analysis_fp, "%s\n", line);
625  fprintf(de_ctx->ea->fp_engine_analysis_fp, " FAILURE: invalid rule.\n");
626  fprintf(de_ctx->ea->fp_engine_analysis_fp, " File: %s.\n", file);
627  fprintf(de_ctx->ea->fp_engine_analysis_fp, " Line: %d.\n", lineno);
628  fprintf(de_ctx->ea->fp_engine_analysis_fp, "\n");
629 }
630 
631 typedef struct RuleAnalyzer {
632  JsonBuilder *js; /* document root */
633 
634  JsonBuilder *js_warnings;
635  JsonBuilder *js_notes;
637 
638 static void ATTR_FMT_PRINTF(2, 3) AnalyzerNote(RuleAnalyzer *ctx, char *fmt, ...)
639 {
640  va_list ap;
641  char str[1024];
642 
643  va_start(ap, fmt);
644  vsnprintf(str, sizeof(str), fmt, ap);
645  va_end(ap);
646 
647  if (!ctx->js_notes)
648  ctx->js_notes = jb_new_array();
649  if (ctx->js_notes)
650  jb_append_string(ctx->js_notes, str);
651 }
652 
653 static void ATTR_FMT_PRINTF(2, 3) AnalyzerWarning(RuleAnalyzer *ctx, char *fmt, ...)
654 {
655  va_list ap;
656  char str[1024];
657 
658  va_start(ap, fmt);
659  vsnprintf(str, sizeof(str), fmt, ap);
660  va_end(ap);
661 
662  if (!ctx->js_warnings)
663  ctx->js_warnings = jb_new_array();
664  if (ctx->js_warnings)
665  jb_append_string(ctx->js_warnings, str);
666 }
667 
668 #define CHECK(pat) if (strlen((pat)) <= len && memcmp((pat), buf, MIN(len, strlen((pat)))) == 0) return true;
669 
670 static bool LooksLikeHTTPMethod(const uint8_t *buf, uint16_t len)
671 {
672  CHECK("GET /");
673  CHECK("POST /");
674  CHECK("HEAD /");
675  CHECK("PUT /");
676  return false;
677 }
678 
679 static bool LooksLikeHTTPUA(const uint8_t *buf, uint16_t len)
680 {
681  CHECK("User-Agent: ");
682  CHECK("\nUser-Agent: ");
683  return false;
684 }
685 
686 static void DumpContent(JsonBuilder *js, const DetectContentData *cd)
687 {
688  char pattern_str[1024] = "";
689  DetectContentPatternPrettyPrint(cd, pattern_str, sizeof(pattern_str));
690 
691  jb_set_string(js, "pattern", pattern_str);
692  jb_set_uint(js, "length", cd->content_len);
693  jb_set_bool(js, "nocase", cd->flags & DETECT_CONTENT_NOCASE);
694  jb_set_bool(js, "negated", cd->flags & DETECT_CONTENT_NEGATED);
695  jb_set_bool(js, "starts_with", cd->flags & DETECT_CONTENT_STARTS_WITH);
696  jb_set_bool(js, "ends_with", cd->flags & DETECT_CONTENT_ENDS_WITH);
697  jb_set_bool(js, "is_mpm", cd->flags & DETECT_CONTENT_MPM);
698  jb_set_bool(js, "no_double_inspect", cd->flags & DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED);
699  if (cd->flags & DETECT_CONTENT_OFFSET) {
700  jb_set_uint(js, "offset", cd->offset);
701  }
702  if (cd->flags & DETECT_CONTENT_DEPTH) {
703  jb_set_uint(js, "depth", cd->depth);
704  }
705  if (cd->flags & DETECT_CONTENT_DISTANCE) {
706  jb_set_int(js, "distance", cd->distance);
707  }
708  if (cd->flags & DETECT_CONTENT_WITHIN) {
709  jb_set_int(js, "within", cd->within);
710  }
711  jb_set_bool(js, "fast_pattern", cd->flags & DETECT_CONTENT_FAST_PATTERN);
712  jb_set_bool(js, "relative_next", cd->flags & DETECT_CONTENT_RELATIVE_NEXT);
713 }
714 
715 static void DumpPcre(JsonBuilder *js, const DetectPcreData *cd)
716 {
717  jb_set_bool(js, "relative", cd->flags & DETECT_PCRE_RELATIVE);
718  jb_set_bool(js, "relative_next", cd->flags & DETECT_PCRE_RELATIVE_NEXT);
719  jb_set_bool(js, "nocase", cd->flags & DETECT_PCRE_CASELESS);
720  jb_set_bool(js, "negated", cd->flags & DETECT_PCRE_NEGATE);
721 }
722 
723 static void DumpMatches(RuleAnalyzer *ctx, JsonBuilder *js, const SigMatchData *smd)
724 {
725  if (smd == NULL)
726  return;
727 
728  jb_open_array(js, "matches");
729  do {
730  jb_start_object(js);
731  const char *mname = sigmatch_table[smd->type].name;
732  jb_set_string(js, "name", mname);
733 
734  switch (smd->type) {
735  case DETECT_CONTENT: {
736  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
737 
738  jb_open_object(js, "content");
739  DumpContent(js, cd);
741  AnalyzerNote(ctx, (char *)"'fast_pattern:only' option is silently ignored and "
742  "is interpreted as regular 'fast_pattern'");
743  }
744  if (LooksLikeHTTPMethod(cd->content, cd->content_len)) {
745  AnalyzerWarning(ctx,
746  (char *)"pattern looks like it inspects HTTP, use http.request_line or "
747  "http.method and http.uri instead for improved performance");
748  }
749  if (LooksLikeHTTPUA(cd->content, cd->content_len)) {
750  AnalyzerWarning(ctx,
751  (char *)"pattern looks like it inspects HTTP, use http.user_agent "
752  "or http.header for improved performance");
753  }
755  AnalyzerNote(ctx, (char *)"'within' option for pattern w/o previous content "
756  "was converted to 'depth'");
757  }
759  AnalyzerNote(ctx, (char *)"'distance' option for pattern w/o previous content "
760  "was converted to 'offset'");
761  }
762  jb_close(js);
763  break;
764  }
765  case DETECT_PCRE: {
766  const DetectPcreData *cd = (const DetectPcreData *)smd->ctx;
767 
768  jb_open_object(js, "pcre");
769  DumpPcre(js, cd);
770  jb_close(js);
771  if (cd->flags & DETECT_PCRE_RAWBYTES) {
772  AnalyzerNote(ctx,
773  (char *)"'/B' (rawbytes) option is a no-op and is silently ignored");
774  }
775  break;
776  }
777  case DETECT_BYTEJUMP: {
778  const DetectBytejumpData *cd = (const DetectBytejumpData *)smd->ctx;
779 
780  jb_open_object(js, "byte_jump");
781  jb_set_uint(js, "nbytes", cd->nbytes);
782  jb_set_int(js, "offset", cd->offset);
783  jb_set_uint(js, "multiplier", cd->multiplier);
784  jb_set_int(js, "post_offset", cd->post_offset);
785  switch (cd->base) {
787  jb_set_string(js, "base", "unset");
788  break;
790  jb_set_string(js, "base", "oct");
791  break;
793  jb_set_string(js, "base", "dec");
794  break;
796  jb_set_string(js, "base", "hex");
797  break;
798  }
799  jb_open_array(js, "flags");
800  if (cd->flags & DETECT_BYTEJUMP_BEGIN)
801  jb_append_string(js, "from_beginning");
802  if (cd->flags & DETECT_BYTEJUMP_LITTLE)
803  jb_append_string(js, "little_endian");
804  if (cd->flags & DETECT_BYTEJUMP_BIG)
805  jb_append_string(js, "big_endian");
806  if (cd->flags & DETECT_BYTEJUMP_STRING)
807  jb_append_string(js, "string");
809  jb_append_string(js, "relative");
810  if (cd->flags & DETECT_BYTEJUMP_ALIGN)
811  jb_append_string(js, "align");
812  if (cd->flags & DETECT_BYTEJUMP_DCE)
813  jb_append_string(js, "dce");
815  jb_append_string(js, "offset_be");
816  if (cd->flags & DETECT_BYTEJUMP_END)
817  jb_append_string(js, "from_end");
818  jb_close(js);
819  jb_close(js);
820  break;
821  }
822  case DETECT_BYTETEST: {
823  const DetectBytetestData *cd = (const DetectBytetestData *)smd->ctx;
824 
825  jb_open_object(js, "byte_test");
826  jb_set_uint(js, "nbytes", cd->nbytes);
827  jb_set_int(js, "offset", cd->offset);
828  switch (cd->base) {
830  jb_set_string(js, "base", "unset");
831  break;
833  jb_set_string(js, "base", "oct");
834  break;
836  jb_set_string(js, "base", "dec");
837  break;
839  jb_set_string(js, "base", "hex");
840  break;
841  }
842  jb_open_array(js, "flags");
843  if (cd->flags & DETECT_BYTETEST_LITTLE)
844  jb_append_string(js, "little_endian");
845  if (cd->flags & DETECT_BYTETEST_BIG)
846  jb_append_string(js, "big_endian");
847  if (cd->flags & DETECT_BYTETEST_STRING)
848  jb_append_string(js, "string");
850  jb_append_string(js, "relative");
851  if (cd->flags & DETECT_BYTETEST_DCE)
852  jb_append_string(js, "dce");
853  jb_close(js);
854  jb_close(js);
855  break;
856  }
857  case DETECT_IPOPTS: {
858  const DetectIpOptsData *cd = (const DetectIpOptsData *)smd->ctx;
859 
860  jb_open_object(js, "ipopts");
861  const char *flag = IpOptsFlagToString(cd->ipopt);
862  jb_set_string(js, "option", flag);
863  jb_close(js);
864  break;
865  }
866  case DETECT_FLOWBITS: {
867  const DetectFlowbitsData *cd = (const DetectFlowbitsData *)smd->ctx;
868 
869  jb_open_object(js, "flowbits");
870  switch (cd->cmd) {
872  jb_set_string(js, "cmd", "isset");
873  break;
875  jb_set_string(js, "cmd", "isnotset");
876  break;
878  jb_set_string(js, "cmd", "set");
879  break;
881  jb_set_string(js, "cmd", "unset");
882  break;
884  jb_set_string(js, "cmd", "toggle");
885  break;
886  }
887  bool is_or = false;
888  jb_open_array(js, "names");
889  if (cd->or_list_size == 0) {
890  jb_append_string(js, VarNameStoreSetupLookup(cd->idx, VAR_TYPE_FLOW_BIT));
891  } else if (cd->or_list_size > 0) {
892  is_or = true;
893  for (uint8_t i = 0; i < cd->or_list_size; i++) {
894  const char *varname =
896  jb_append_string(js, varname);
897  }
898  }
899  jb_close(js); // array
900  if (is_or) {
901  jb_set_string(js, "operator", "or");
902  }
903  jb_close(js); // object
904  break;
905  }
906  }
907  jb_close(js);
908 
909  if (smd->is_last)
910  break;
911  smd++;
912  } while (1);
913  jb_close(js);
914 }
915 
918 {
919  SCEnter();
920 
921  RuleAnalyzer ctx = { NULL, NULL, NULL };
922 
923  ctx.js = jb_new_object();
924  if (ctx.js == NULL)
925  SCReturn;
926 
927  jb_set_string(ctx.js, "raw", s->sig_str);
928  jb_set_uint(ctx.js, "id", s->id);
929  jb_set_uint(ctx.js, "gid", s->gid);
930  jb_set_uint(ctx.js, "rev", s->rev);
931  jb_set_string(ctx.js, "msg", s->msg);
932 
933  const char *alproto = AppProtoToString(s->alproto);
934  jb_set_string(ctx.js, "app_proto", alproto);
935 
936  jb_open_array(ctx.js, "requirements");
937  if (s->mask & SIG_MASK_REQUIRE_PAYLOAD) {
938  jb_append_string(ctx.js, "payload");
939  }
941  jb_append_string(ctx.js, "no_payload");
942  }
943  if (s->mask & SIG_MASK_REQUIRE_FLOW) {
944  jb_append_string(ctx.js, "flow");
945  }
947  jb_append_string(ctx.js, "tcp_flags_init_deinit");
948  }
950  jb_append_string(ctx.js, "tcp_flags_unusual");
951  }
953  jb_append_string(ctx.js, "engine_event");
954  }
955  jb_close(ctx.js);
956 
957  switch (s->type) {
958  case SIG_TYPE_NOT_SET:
959  jb_set_string(ctx.js, "type", "unset");
960  break;
961  case SIG_TYPE_IPONLY:
962  jb_set_string(ctx.js, "type", "ip_only");
963  break;
965  jb_set_string(ctx.js, "type", "like_ip_only");
966  break;
967  case SIG_TYPE_PDONLY:
968  jb_set_string(ctx.js, "type", "pd_only");
969  break;
970  case SIG_TYPE_DEONLY:
971  jb_set_string(ctx.js, "type", "de_only");
972  break;
973  case SIG_TYPE_PKT:
974  jb_set_string(ctx.js, "type", "pkt");
975  break;
976  case SIG_TYPE_PKT_STREAM:
977  jb_set_string(ctx.js, "type", "pkt_stream");
978  break;
979  case SIG_TYPE_STREAM:
980  jb_set_string(ctx.js, "type", "stream");
981  break;
982  case SIG_TYPE_APPLAYER:
983  jb_set_string(ctx.js, "type", "app_layer");
984  break;
985  case SIG_TYPE_APP_TX:
986  jb_set_string(ctx.js, "type", "app_tx");
987  break;
988  case SIG_TYPE_MAX:
989  jb_set_string(ctx.js, "type", "error");
990  break;
991  }
992 
993  jb_open_array(ctx.js, "flags");
994  if (s->flags & SIG_FLAG_SRC_ANY) {
995  jb_append_string(ctx.js, "src_any");
996  }
997  if (s->flags & SIG_FLAG_DST_ANY) {
998  jb_append_string(ctx.js, "dst_any");
999  }
1000  if (s->flags & SIG_FLAG_SP_ANY) {
1001  jb_append_string(ctx.js, "sp_any");
1002  }
1003  if (s->flags & SIG_FLAG_DP_ANY) {
1004  jb_append_string(ctx.js, "dp_any");
1005  }
1006  if (s->flags & SIG_FLAG_NOALERT) {
1007  jb_append_string(ctx.js, "noalert");
1008  }
1009  if (s->flags & SIG_FLAG_DSIZE) {
1010  jb_append_string(ctx.js, "dsize");
1011  }
1012  if (s->flags & SIG_FLAG_APPLAYER) {
1013  jb_append_string(ctx.js, "applayer");
1014  }
1015  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
1016  jb_append_string(ctx.js, "need_packet");
1017  }
1018  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
1019  jb_append_string(ctx.js, "need_stream");
1020  }
1021  if (s->flags & SIG_FLAG_MPM_NEG) {
1022  jb_append_string(ctx.js, "negated_mpm");
1023  }
1024  if (s->flags & SIG_FLAG_FLUSH) {
1025  jb_append_string(ctx.js, "flush");
1026  }
1027  if (s->flags & SIG_FLAG_REQUIRE_FLOWVAR) {
1028  jb_append_string(ctx.js, "need_flowvar");
1029  }
1030  if (s->flags & SIG_FLAG_FILESTORE) {
1031  jb_append_string(ctx.js, "filestore");
1032  }
1033  if (s->flags & SIG_FLAG_TOSERVER) {
1034  jb_append_string(ctx.js, "toserver");
1035  }
1036  if (s->flags & SIG_FLAG_TOCLIENT) {
1037  jb_append_string(ctx.js, "toclient");
1038  }
1039  if (s->flags & SIG_FLAG_TLSSTORE) {
1040  jb_append_string(ctx.js, "tlsstore");
1041  }
1042  if (s->flags & SIG_FLAG_BYPASS) {
1043  jb_append_string(ctx.js, "bypass");
1044  }
1045  if (s->flags & SIG_FLAG_PREFILTER) {
1046  jb_append_string(ctx.js, "prefilter");
1047  }
1048  if (s->flags & SIG_FLAG_SRC_IS_TARGET) {
1049  jb_append_string(ctx.js, "src_is_target");
1050  }
1051  if (s->flags & SIG_FLAG_DEST_IS_TARGET) {
1052  jb_append_string(ctx.js, "dst_is_target");
1053  }
1054  jb_close(ctx.js);
1055 
1056  const DetectEnginePktInspectionEngine *pkt_mpm = NULL;
1057  const DetectEngineAppInspectionEngine *app_mpm = NULL;
1058 
1059  jb_open_array(ctx.js, "pkt_engines");
1061  for ( ; pkt != NULL; pkt = pkt->next) {
1062  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, pkt->sm_list);
1063  if (name == NULL) {
1064  switch (pkt->sm_list) {
1065  case DETECT_SM_LIST_PMATCH:
1066  name = "payload";
1067  break;
1068  case DETECT_SM_LIST_MATCH:
1069  name = "packet";
1070  break;
1071  default:
1072  name = "unknown";
1073  break;
1074  }
1075  }
1076  jb_start_object(ctx.js);
1077  jb_set_string(ctx.js, "name", name);
1078  jb_set_bool(ctx.js, "is_mpm", pkt->mpm);
1079  if (pkt->v1.transforms != NULL) {
1080  jb_open_array(ctx.js, "transforms");
1081  for (int t = 0; t < pkt->v1.transforms->cnt; t++) {
1082  jb_start_object(ctx.js);
1083  jb_set_string(ctx.js, "name",
1085  jb_close(ctx.js);
1086  }
1087  jb_close(ctx.js);
1088  }
1089  DumpMatches(&ctx, ctx.js, pkt->smd);
1090  jb_close(ctx.js);
1091  if (pkt->mpm) {
1092  pkt_mpm = pkt;
1093  }
1094  }
1095  jb_close(ctx.js);
1096  jb_open_array(ctx.js, "frame_engines");
1098  for (; frame != NULL; frame = frame->next) {
1099  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, frame->sm_list);
1100  jb_start_object(ctx.js);
1101  jb_set_string(ctx.js, "name", name);
1102  jb_set_bool(ctx.js, "is_mpm", frame->mpm);
1103  if (frame->v1.transforms != NULL) {
1104  jb_open_array(ctx.js, "transforms");
1105  for (int t = 0; t < frame->v1.transforms->cnt; t++) {
1106  jb_start_object(ctx.js);
1107  jb_set_string(ctx.js, "name",
1109  jb_close(ctx.js);
1110  }
1111  jb_close(ctx.js);
1112  }
1113  DumpMatches(&ctx, ctx.js, frame->smd);
1114  jb_close(ctx.js);
1115  }
1116  jb_close(ctx.js);
1117 
1119  bool has_stream = false;
1120  bool has_client_body_mpm = false;
1121  bool has_file_data_mpm = false;
1122 
1123  jb_open_array(ctx.js, "engines");
1125  for ( ; app != NULL; app = app->next) {
1126  const char *name = DetectEngineBufferTypeGetNameById(de_ctx, app->sm_list);
1127  if (name == NULL) {
1128  switch (app->sm_list) {
1129  case DETECT_SM_LIST_PMATCH:
1130  name = "stream";
1131  break;
1132  default:
1133  name = "unknown";
1134  break;
1135  }
1136  }
1137 
1138  if (app->sm_list == DETECT_SM_LIST_PMATCH && !app->mpm) {
1139  has_stream = true;
1140  } else if (app->mpm && strcmp(name, "http_client_body") == 0) {
1141  has_client_body_mpm = true;
1142  } else if (app->mpm && strcmp(name, "file_data") == 0) {
1143  has_file_data_mpm = true;
1144  }
1145 
1146  jb_start_object(ctx.js);
1147  jb_set_string(ctx.js, "name", name);
1148  const char *direction = app->dir == 0 ? "toserver" : "toclient";
1149  jb_set_string(ctx.js, "direction", direction);
1150  jb_set_bool(ctx.js, "is_mpm", app->mpm);
1151  jb_set_string(ctx.js, "app_proto", AppProtoToString(app->alproto));
1152  jb_set_uint(ctx.js, "progress", app->progress);
1153 
1154  if (app->v2.transforms != NULL) {
1155  jb_open_array(ctx.js, "transforms");
1156  for (int t = 0; t < app->v2.transforms->cnt; t++) {
1157  jb_start_object(ctx.js);
1158  jb_set_string(ctx.js, "name",
1160  jb_close(ctx.js);
1161  }
1162  jb_close(ctx.js);
1163  }
1164  DumpMatches(&ctx, ctx.js, app->smd);
1165  jb_close(ctx.js);
1166  if (app->mpm) {
1167  app_mpm = app;
1168  }
1169  }
1170  jb_close(ctx.js);
1171 
1172  if (has_stream && has_client_body_mpm)
1173  AnalyzerNote(&ctx, (char *)"mpm in http_client_body combined with stream match leads to stream buffering");
1174  if (has_stream && has_file_data_mpm)
1175  AnalyzerNote(&ctx, (char *)"mpm in file_data combined with stream match leads to stream buffering");
1176  }
1177 
1178  jb_open_object(ctx.js, "lists");
1179  for (int i = 0; i < DETECT_SM_LIST_MAX; i++) {
1180  if (s->sm_arrays[i] != NULL) {
1181  jb_open_object(ctx.js, DetectListToHumanString(i));
1182  DumpMatches(&ctx, ctx.js, s->sm_arrays[i]);
1183  jb_close(ctx.js);
1184  }
1185  }
1186  jb_close(ctx.js);
1187 
1188  if (pkt_mpm || app_mpm) {
1189  jb_open_object(ctx.js, "mpm");
1190 
1191  int mpm_list = pkt_mpm ? DETECT_SM_LIST_PMATCH : app_mpm->sm_list;
1192  const char *name;
1193  if (mpm_list < DETECT_SM_LIST_DYNAMIC_START)
1194  name = DetectListToHumanString(mpm_list);
1195  else
1196  name = DetectEngineBufferTypeGetNameById(de_ctx, mpm_list);
1197  jb_set_string(ctx.js, "buffer", name);
1198 
1199  SigMatchData *smd = pkt_mpm ? pkt_mpm->smd : app_mpm->smd;
1200  if (smd == NULL && mpm_list == DETECT_SM_LIST_PMATCH) {
1201  smd = s->sm_arrays[mpm_list];
1202  }
1203  do {
1204  switch (smd->type) {
1205  case DETECT_CONTENT: {
1206  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
1207  if (cd->flags & DETECT_CONTENT_MPM) {
1208  DumpContent(ctx.js, cd);
1209  }
1210  break;
1211  }
1212  }
1213 
1214  if (smd->is_last)
1215  break;
1216  smd++;
1217  } while (1);
1218  jb_close(ctx.js);
1219  } else if (s->init_data->prefilter_sm) {
1220  jb_open_object(ctx.js, "prefilter");
1221  int prefilter_list = SigMatchListSMBelongsTo(s, s->init_data->prefilter_sm);
1222  const char *name;
1223  if (prefilter_list < DETECT_SM_LIST_DYNAMIC_START)
1224  name = DetectListToHumanString(prefilter_list);
1225  else
1226  name = DetectEngineBufferTypeGetNameById(de_ctx, prefilter_list);
1227  jb_set_string(ctx.js, "buffer", name);
1228  const char *mname = sigmatch_table[s->init_data->prefilter_sm->type].name;
1229  jb_set_string(ctx.js, "name", mname);
1230  jb_close(ctx.js);
1231  }
1232 
1233  if (ctx.js_warnings) {
1234  jb_close(ctx.js_warnings);
1235  jb_set_object(ctx.js, "warnings", ctx.js_warnings);
1236  jb_free(ctx.js_warnings);
1237  ctx.js_warnings = NULL;
1238  }
1239  if (ctx.js_notes) {
1240  jb_close(ctx.js_notes);
1241  jb_set_object(ctx.js, "notes", ctx.js_notes);
1242  jb_free(ctx.js_notes);
1243  ctx.js_notes = NULL;
1244  }
1245  jb_close(ctx.js);
1246 
1247  const char *filename = "rules.json";
1248  const char *log_dir = ConfigGetLogDirectory();
1249  char json_path[PATH_MAX] = "";
1250  snprintf(json_path, sizeof(json_path), "%s/%s%s", log_dir,
1251  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", filename);
1252 
1254  FILE *fp = fopen(json_path, "a");
1255  if (fp != NULL) {
1256  fwrite(jb_ptr(ctx.js), jb_len(ctx.js), 1, fp);
1257  fprintf(fp, "\n");
1258  fclose(fp);
1259  }
1261  jb_free(ctx.js);
1262  SCReturn;
1263 }
1264 
1266 {
1267  if (de_ctx->pattern_hash_table == NULL)
1268  return;
1269 
1270  JsonBuilder *root_jb = jb_new_object();
1271  JsonBuilder *arrays[de_ctx->buffer_type_id];
1272  memset(&arrays, 0, sizeof(JsonBuilder *) * de_ctx->buffer_type_id);
1273 
1274  jb_open_array(root_jb, "buffers");
1275 
1277  htb != NULL; htb = HashListTableGetListNext(htb)) {
1278  char str[1024] = "";
1280  DetectContentPatternPrettyPrint(p->cd, str, sizeof(str));
1281 
1282  JsonBuilder *jb = arrays[p->sm_list];
1283  if (arrays[p->sm_list] == NULL) {
1284  jb = arrays[p->sm_list] = jb_new_object();
1285  const char *name;
1287  name = DetectListToHumanString(p->sm_list);
1288  else
1290  jb_set_string(jb, "name", name);
1291  jb_set_uint(jb, "list_id", p->sm_list);
1292 
1293  jb_open_array(jb, "patterns");
1294  }
1295 
1296  jb_start_object(jb);
1297  jb_set_string(jb, "pattern", str);
1298  jb_set_uint(jb, "patlen", p->cd->content_len);
1299  jb_set_uint(jb, "cnt", p->cnt);
1300  jb_set_uint(jb, "mpm", p->mpm);
1301  jb_open_object(jb, "flags");
1302  jb_set_bool(jb, "nocase", p->cd->flags & DETECT_CONTENT_NOCASE);
1303  jb_set_bool(jb, "negated", p->cd->flags & DETECT_CONTENT_NEGATED);
1304  jb_set_bool(jb, "depth", p->cd->flags & DETECT_CONTENT_DEPTH);
1305  jb_set_bool(jb, "offset", p->cd->flags & DETECT_CONTENT_OFFSET);
1306  jb_set_bool(jb, "endswith", p->cd->flags & DETECT_CONTENT_ENDS_WITH);
1307  jb_close(jb);
1308  jb_close(jb);
1309  }
1310 
1311  for (uint32_t i = 0; i < de_ctx->buffer_type_id; i++) {
1312  JsonBuilder *jb = arrays[i];
1313  if (jb == NULL)
1314  continue;
1315 
1316  jb_close(jb); // array
1317  jb_close(jb); // object
1318 
1319  jb_append_object(root_jb, jb);
1320  jb_free(jb);
1321  }
1322  jb_close(root_jb);
1323  jb_close(root_jb);
1324 
1325  const char *filename = "patterns.json";
1326  const char *log_dir = ConfigGetLogDirectory();
1327  char json_path[PATH_MAX] = "";
1328  snprintf(json_path, sizeof(json_path), "%s/%s%s", log_dir,
1329  de_ctx->ea->file_prefix ? de_ctx->ea->file_prefix : "", filename);
1330 
1332  FILE *fp = fopen(json_path, "a");
1333  if (fp != NULL) {
1334  fwrite(jb_ptr(root_jb), jb_len(root_jb), 1, fp);
1335  fprintf(fp, "\n");
1336  fclose(fp);
1337  }
1339  jb_free(root_jb);
1340 
1342  de_ctx->pattern_hash_table = NULL;
1343 }
1344 
1345 static void EngineAnalysisItemsReset(EngineAnalysisCtx *ea_ctx)
1346 {
1347  for (size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
1348  ea_ctx->analyzer_items[i].item_seen = false;
1349  }
1350 }
1351 
1352 static void EngineAnalysisItemsInit(EngineAnalysisCtx *ea_ctx)
1353 {
1354  if (ea_ctx->analyzer_initialized) {
1355  EngineAnalysisItemsReset(ea_ctx);
1356  return;
1357  }
1358 
1359  ea_ctx->exposed_item_seen_list[0].bufname = "http_method";
1360  ea_ctx->exposed_item_seen_list[1].bufname = "file_data";
1361  ea_ctx->analyzer_items = SCCalloc(1, sizeof(analyzer_items));
1362  if (!ea_ctx->analyzer_items) {
1363  FatalError("Unable to allocate analysis scratch pad");
1364  }
1365  memset(ea_ctx->analyzer_item_map, -1, sizeof(ea_ctx->analyzer_item_map));
1366 
1367  for (size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
1368  ea_ctx->analyzer_items[i] = analyzer_items[i];
1369  DetectEngineAnalyzerItems *analyzer_item = &ea_ctx->analyzer_items[i];
1370 
1371  int item_id = DetectBufferTypeGetByName(analyzer_item->item_name);
1372  DEBUG_VALIDATE_BUG_ON(item_id < 0 || item_id > UINT16_MAX);
1373  analyzer_item->item_id = (uint16_t)item_id;
1374  if (analyzer_item->item_id == -1) {
1375  /* Mismatch between the analyzer_items array and what's supported */
1376  FatalError("unable to initialize engine-analysis table: detect buffer \"%s\" not "
1377  "recognized.",
1378  analyzer_item->item_name);
1379  }
1380  analyzer_item->item_seen = false;
1381 
1382  if (analyzer_item->export_item_seen) {
1383  for (size_t k = 0; k < ARRAY_SIZE(ea_ctx->exposed_item_seen_list); k++) {
1384  if (0 ==
1385  strcmp(ea_ctx->exposed_item_seen_list[k].bufname, analyzer_item->item_name))
1386  ea_ctx->exposed_item_seen_list[k].item_seen_ptr = &analyzer_item->item_seen;
1387  }
1388  }
1389  ea_ctx->analyzer_item_map[analyzer_item->item_id] = (int16_t)i;
1390  }
1391 
1392  ea_ctx->analyzer_initialized = true;
1393 }
1394 
1395 /**
1396  * \brief Prints analysis of loaded rules.
1397  *
1398  * Warns if potential rule issues are detected. For example,
1399  * warns if a rule uses a construct that may perform poorly,
1400  * e.g. pcre without content or with http_method content only;
1401  * warns if a rule uses a construct that may not be consistent with intent,
1402  * e.g. client side ports only, http and content without any http_* modifiers, etc.
1403  *
1404  * \param s Pointer to the signature.
1405  */
1407  const Signature *s, const char *line)
1408 {
1409  uint32_t rule_bidirectional = 0;
1410  uint32_t rule_pcre = 0;
1411  uint32_t rule_pcre_http = 0;
1412  uint32_t rule_content = 0;
1413  uint32_t rule_flow = 0;
1414  uint32_t rule_flags = 0;
1415  uint32_t rule_flow_toserver = 0;
1416  uint32_t rule_flow_toclient = 0;
1417  uint32_t rule_flow_nostream = 0;
1418  uint32_t rule_ipv4_only = 0;
1419  uint32_t rule_ipv6_only = 0;
1420  uint32_t rule_flowbits = 0;
1421  uint32_t rule_flowint = 0;
1422  uint32_t rule_content_http = 0;
1423  uint32_t rule_content_offset_depth = 0;
1424  int32_t list_id = 0;
1425  uint32_t rule_warning = 0;
1426  uint32_t stream_buf = 0;
1427  uint32_t packet_buf = 0;
1428  uint32_t file_store = 0;
1429  uint32_t warn_pcre_no_content = 0;
1430  uint32_t warn_pcre_http_content = 0;
1431  uint32_t warn_pcre_http = 0;
1432  uint32_t warn_content_http_content = 0;
1433  uint32_t warn_content_http = 0;
1434  uint32_t warn_tcp_no_flow = 0;
1435  uint32_t warn_client_ports = 0;
1436  uint32_t warn_direction = 0;
1437  uint32_t warn_method_toclient = 0;
1438  uint32_t warn_method_serverbody = 0;
1439  uint32_t warn_pcre_method = 0;
1440  uint32_t warn_encoding_norm_http_buf = 0;
1441  uint32_t warn_file_store_not_present = 0;
1442  uint32_t warn_offset_depth_pkt_stream = 0;
1443  uint32_t warn_offset_depth_alproto = 0;
1444  uint32_t warn_non_alproto_fp_for_alproto_sig = 0;
1445  uint32_t warn_no_direction = 0;
1446  uint32_t warn_both_direction = 0;
1447 
1448  EngineAnalysisItemsInit(de_ctx->ea);
1449 
1450  bool *http_method_item_seen_ptr = de_ctx->ea->exposed_item_seen_list[0].item_seen_ptr;
1451  bool *http_server_body_item_seen_ptr = de_ctx->ea->exposed_item_seen_list[1].item_seen_ptr;
1452 
1454  rule_bidirectional = 1;
1455  }
1456 
1457  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
1458  packet_buf += 1;
1459  }
1460  if (s->flags & SIG_FLAG_FILESTORE) {
1461  file_store += 1;
1462  }
1463  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
1464  stream_buf += 1;
1465  }
1466 
1467  if (s->proto.flags & DETECT_PROTO_IPV4) {
1468  rule_ipv4_only += 1;
1469  }
1470  if (s->proto.flags & DETECT_PROTO_IPV6) {
1471  rule_ipv6_only += 1;
1472  }
1473 
1474  for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
1475  SigMatch *sm = NULL;
1476  for (sm = s->init_data->smlists[list_id]; sm != NULL; sm = sm->next) {
1477  int16_t item_slot = de_ctx->ea->analyzer_item_map[list_id];
1478  if (sm->type == DETECT_PCRE) {
1479  if (item_slot == -1) {
1480  rule_pcre++;
1481  continue;
1482  }
1483 
1484  rule_pcre_http++;
1485  de_ctx->ea->analyzer_items[item_slot].item_seen = true;
1486  } else if (sm->type == DETECT_CONTENT) {
1487  if (item_slot == -1) {
1488  rule_content++;
1489  if (list_id == DETECT_SM_LIST_PMATCH) {
1492  rule_content_offset_depth++;
1493  }
1494  }
1495  continue;
1496  }
1497 
1498  rule_content_http++;
1499  de_ctx->ea->analyzer_items[item_slot].item_seen = true;
1500 
1501  if (de_ctx->ea->analyzer_items[item_slot].check_encoding_match) {
1503  if (cd != NULL &&
1504  PerCentEncodingMatch(de_ctx->ea, cd->content, cd->content_len) > 0) {
1505  warn_encoding_norm_http_buf += 1;
1506  }
1507  }
1508  }
1509  else if (sm->type == DETECT_FLOW) {
1510  rule_flow += 1;
1511  if ((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_TOCLIENT)) {
1512  rule_flow_toserver = 1;
1513  }
1514  else if ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_TOSERVER)) {
1515  rule_flow_toclient = 1;
1516  }
1517  DetectFlowData *fd = (DetectFlowData *)sm->ctx;
1518  if (fd != NULL) {
1519  if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM)
1520  rule_flow_nostream = 1;
1521  }
1522  }
1523  else if (sm->type == DETECT_FLOWBITS) {
1524  if (list_id == DETECT_SM_LIST_MATCH) {
1525  rule_flowbits += 1;
1526  }
1527  }
1528  else if (sm->type == DETECT_FLOWINT) {
1529  if (list_id == DETECT_SM_LIST_MATCH) {
1530  rule_flowint += 1;
1531  }
1532  }
1533  else if (sm->type == DETECT_FLAGS) {
1534  DetectFlagsData *fd = (DetectFlagsData *)sm->ctx;
1535  if (fd != NULL) {
1536  rule_flags = 1;
1537  }
1538  }
1539  } /* for (sm = s->init_data->smlists[list_id]; sm != NULL; sm = sm->next) */
1540 
1541  } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */
1542 
1543  if (file_store && !RequiresFeature("output::file-store")) {
1544  rule_warning += 1;
1545  warn_file_store_not_present = 1;
1546  }
1547 
1548  if (rule_pcre > 0 && rule_content == 0 && rule_content_http == 0) {
1549  rule_warning += 1;
1550  warn_pcre_no_content = 1;
1551  }
1552 
1553  if (rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0) {
1554  rule_warning += 1;
1555  warn_pcre_http_content = 1;
1556  } else if (s->alproto == ALPROTO_HTTP1 && rule_pcre > 0 && rule_pcre_http == 0) {
1557  rule_warning += 1;
1558  warn_pcre_http = 1;
1559  }
1560 
1561  if (rule_content > 0 && rule_content_http > 0) {
1562  rule_warning += 1;
1563  warn_content_http_content = 1;
1564  }
1565  if (s->alproto == ALPROTO_HTTP1 && rule_content > 0 && rule_content_http == 0) {
1566  rule_warning += 1;
1567  warn_content_http = 1;
1568  }
1569  if (rule_content == 1) {
1570  //todo: warning if content is weak, separate warning for pcre + weak content
1571  }
1572  if (rule_flow == 0 && rule_flags == 0 && !(s->proto.flags & DETECT_PROTO_ANY) &&
1573  DetectProtoContainsProto(&s->proto, IPPROTO_TCP) &&
1574  (rule_content || rule_content_http || rule_pcre || rule_pcre_http || rule_flowbits ||
1575  rule_flowint)) {
1576  rule_warning += 1;
1577  warn_tcp_no_flow = 1;
1578  }
1579  if (rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)
1580  && !((s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))) {
1581  if (((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))
1582  || ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_DP_ANY) && (s->flags & SIG_FLAG_SP_ANY))) {
1583  rule_warning += 1;
1584  warn_client_ports = 1;
1585  }
1586  }
1587  if (rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)) {
1588  rule_warning += 1;
1589  warn_direction = 1;
1590  }
1591 
1592  if (*http_method_item_seen_ptr) {
1593  if (rule_flow && rule_flow_toclient) {
1594  rule_warning += 1;
1595  warn_method_toclient = 1;
1596  }
1597  if (*http_server_body_item_seen_ptr) {
1598  rule_warning += 1;
1599  warn_method_serverbody = 1;
1600  }
1601  if (rule_content == 0 && rule_content_http == 0 && (rule_pcre > 0 || rule_pcre_http > 0)) {
1602  rule_warning += 1;
1603  warn_pcre_method = 1;
1604  }
1605  }
1606  if (rule_content_offset_depth > 0 && stream_buf && packet_buf) {
1607  rule_warning += 1;
1608  warn_offset_depth_pkt_stream = 1;
1609  }
1610  if (rule_content_offset_depth > 0 && !stream_buf && packet_buf && s->alproto != ALPROTO_UNKNOWN) {
1611  rule_warning += 1;
1612  warn_offset_depth_alproto = 1;
1613  }
1614  if (s->init_data->mpm_sm != NULL && s->alproto == ALPROTO_HTTP1 &&
1616  rule_warning += 1;
1617  warn_non_alproto_fp_for_alproto_sig = 1;
1618  }
1619 
1620  if ((s->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) {
1621  warn_no_direction += 1;
1622  rule_warning += 1;
1623  }
1624 
1625  /* No warning about direction for ICMP protos */
1626  if (!(DetectProtoContainsProto(&s->proto, IPPROTO_ICMPV6) && DetectProtoContainsProto(&s->proto, IPPROTO_ICMP))) {
1628  warn_both_direction += 1;
1629  rule_warning += 1;
1630  }
1631  }
1632 
1633  if (!rule_warnings_only || (rule_warnings_only && rule_warning > 0)) {
1634  FILE *fp = de_ctx->ea->rule_engine_analysis_fp;
1635  fprintf(fp, "== Sid: %u ==\n", s->id);
1636  fprintf(fp, "%s\n", line);
1637 
1638  switch (s->type) {
1639  case SIG_TYPE_NOT_SET:
1640  break;
1641  case SIG_TYPE_IPONLY:
1642  fprintf(fp, " Rule is ip only.\n");
1643  break;
1644  case SIG_TYPE_LIKE_IPONLY:
1645  fprintf(fp, " Rule is like ip only.\n");
1646  break;
1647  case SIG_TYPE_PDONLY:
1648  fprintf(fp, " Rule is PD only.\n");
1649  break;
1650  case SIG_TYPE_DEONLY:
1651  fprintf(fp, " Rule is DE only.\n");
1652  break;
1653  case SIG_TYPE_PKT:
1654  fprintf(fp, " Rule is packet inspecting.\n");
1655  break;
1656  case SIG_TYPE_PKT_STREAM:
1657  fprintf(fp, " Rule is packet and stream inspecting.\n");
1658  break;
1659  case SIG_TYPE_STREAM:
1660  fprintf(fp, " Rule is stream inspecting.\n");
1661  break;
1662  case SIG_TYPE_APPLAYER:
1663  fprintf(fp, " Rule is app-layer inspecting.\n");
1664  break;
1665  case SIG_TYPE_APP_TX:
1666  fprintf(fp, " Rule is App-layer TX inspecting.\n");
1667  break;
1668  case SIG_TYPE_MAX:
1669  break;
1670  }
1671  if (rule_ipv6_only)
1672  fprintf(fp, " Rule is IPv6 only.\n");
1673  if (rule_ipv4_only)
1674  fprintf(fp, " Rule is IPv4 only.\n");
1675  if (packet_buf)
1676  fprintf(fp, " Rule matches on packets.\n");
1677  if (!rule_flow_nostream && stream_buf &&
1678  (rule_flow || rule_flowbits || rule_flowint || rule_content || rule_pcre)) {
1679  fprintf(fp, " Rule matches on reassembled stream.\n");
1680  }
1681  for(size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
1683  if (ai->item_seen) {
1684  fprintf(fp, " Rule matches on %s buffer.\n", ai->display_name);
1685  }
1686  }
1687  if (s->alproto != ALPROTO_UNKNOWN) {
1688  fprintf(fp, " App layer protocol is %s.\n", AppProtoToString(s->alproto));
1689  }
1690  if (rule_content || rule_content_http || rule_pcre || rule_pcre_http) {
1691  fprintf(fp,
1692  " Rule contains %u content options, %u http content options, %u pcre "
1693  "options, and %u pcre options with http modifiers.\n",
1694  rule_content, rule_content_http, rule_pcre, rule_pcre_http);
1695  }
1696 
1697  /* print fast pattern info */
1698  if (s->init_data->prefilter_sm) {
1699  fprintf(fp, " Prefilter on: %s.\n",
1701  } else {
1702  EngineAnalysisRulesPrintFP(de_ctx, s);
1703  }
1704 
1705  /* this is where the warnings start */
1706  if (warn_pcre_no_content /*rule_pcre > 0 && rule_content == 0 && rule_content_http == 0*/) {
1707  fprintf(fp, " Warning: Rule uses pcre without a content option present.\n"
1708  " -Consider adding a content to improve performance of this "
1709  "rule.\n");
1710  }
1711  if (warn_pcre_http_content /*rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0*/) {
1712  fprintf(fp, " Warning: Rule uses content options with http_* and pcre options "
1713  "without http modifiers.\n"
1714  " -Consider adding http pcre modifier.\n");
1715  }
1716  else if (warn_pcre_http /*s->alproto == ALPROTO_HTTP1 && rule_pcre > 0 && rule_pcre_http == 0*/) {
1717  fprintf(fp, " Warning: Rule app layer protocol is http, but pcre options do not "
1718  "have http modifiers.\n"
1719  " -Consider adding http pcre modifiers.\n");
1720  }
1721  if (warn_content_http_content /*rule_content > 0 && rule_content_http > 0*/) {
1722  fprintf(fp,
1723  " Warning: Rule contains content with http_* and content without http_*.\n"
1724  " -Consider adding http content modifiers.\n");
1725  }
1726  if (warn_content_http /*s->alproto == ALPROTO_HTTP1 && rule_content > 0 && rule_content_http == 0*/) {
1727  fprintf(fp, " Warning: Rule app layer protocol is http, but content options do not "
1728  "have http_* modifiers.\n"
1729  " -Consider adding http content modifiers.\n");
1730  }
1731  if (rule_content == 1) {
1732  //todo: warning if content is weak, separate warning for pcre + weak content
1733  }
1734  if (warn_encoding_norm_http_buf) {
1735  fprintf(fp, " Warning: Rule may contain percent encoded content for a normalized "
1736  "http buffer match.\n");
1737  }
1738  if (warn_tcp_no_flow /*rule_flow == 0 && rule_flags == 0
1739  && !(s->proto.flags & DETECT_PROTO_ANY) && DetectProtoContainsProto(&s->proto, IPPROTO_TCP)*/) {
1740  fprintf(fp, " Warning: TCP rule without a flow or flags option.\n"
1741  " -Consider adding flow or flags to improve performance of "
1742  "this rule.\n");
1743  }
1744  if (warn_client_ports /*rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)
1745  && !((s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY)))
1746  if (((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))
1747  || ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_DP_ANY) && (s->flags & SIG_FLAG_SP_ANY))*/) {
1748  fprintf(fp,
1749  " Warning: Rule contains ports or port variables only on the client side.\n"
1750  " -Flow direction possibly inconsistent with rule.\n");
1751  }
1752  if (warn_direction /*rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)*/) {
1753  fprintf(fp, " Warning: Rule is bidirectional and has a flow option with a specific "
1754  "direction.\n");
1755  }
1756  if (warn_method_toclient /*http_method_buf && rule_flow && rule_flow_toclient*/) {
1757  fprintf(fp, " Warning: Rule uses content or pcre for http_method with "
1758  "flow:to_client or from_server\n");
1759  }
1760  if (warn_method_serverbody /*http_method_buf && http_server_body_buf*/) {
1761  fprintf(fp, " Warning: Rule uses content or pcre for http_method with content or "
1762  "pcre for http_server_body.\n");
1763  }
1764  if (warn_pcre_method /*http_method_buf && rule_content == 0 && rule_content_http == 0
1765  && (rule_pcre > 0 || rule_pcre_http > 0)*/) {
1766  fprintf(fp, " Warning: Rule uses pcre with only a http_method content; possible "
1767  "performance issue.\n");
1768  }
1769  if (warn_offset_depth_pkt_stream) {
1770  fprintf(fp, " Warning: Rule has depth"
1771  "/offset with raw content keywords. Please note the "
1772  "offset/depth will be checked against both packet "
1773  "payloads and stream. If you meant to have the offset/"
1774  "depth checked against just the payload, you can update "
1775  "the signature as \"alert tcp-pkt...\"\n");
1776  }
1777  if (warn_offset_depth_alproto) {
1778  fprintf(fp,
1779  " Warning: Rule has "
1780  "offset/depth set along with a match on a specific "
1781  "app layer protocol - %d. This can lead to FNs if we "
1782  "have a offset/depth content match on a packet payload "
1783  "before we can detect the app layer protocol for the "
1784  "flow.\n",
1785  s->alproto);
1786  }
1787  if (warn_non_alproto_fp_for_alproto_sig) {
1788  fprintf(fp, " Warning: Rule app layer "
1789  "protocol is http, but the fast_pattern is set on the raw "
1790  "stream. Consider adding fast_pattern over a http "
1791  "buffer for increased performance.");
1792  }
1793  if (warn_no_direction) {
1794  fprintf(fp, " Warning: Rule has no direction indicator.\n");
1795  }
1796  if (warn_both_direction) {
1797  fprintf(fp, " Warning: Rule is inspecting both the request and the response.\n");
1798  }
1799  if (warn_file_store_not_present) {
1800  fprintf(fp, " Warning: Rule requires file-store but the output file-store is not "
1801  "enabled.\n");
1802  }
1803  if (rule_warning == 0) {
1804  fprintf(fp, " No warnings for this rule.\n");
1805  }
1806  fprintf(fp, "\n");
1807  }
1808  return;
1809 }
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:771
RuleAnalyzer::js
JsonBuilder * js
Definition: detect-engine-analyzer.c:632
DetectBytejumpData_::post_offset
int32_t post_offset
Definition: detect-bytejump.h:51
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:57
SIG_TYPE_STREAM
@ SIG_TYPE_STREAM
Definition: detect.h:69
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:107
DetectBytetestData_::flags
uint16_t flags
Definition: detect-bytetest.h:58
DetectPatternTracker
Definition: detect.h:718
DetectEngineAppInspectionEngine_
Definition: detect.h:423
DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_RELATIVE_NEXT
Definition: detect-content.h:66
DetectEngineAppInspectionEngine_::mpm
bool mpm
Definition: detect.h:427
detect-content.h
DetectFlowbitsData_::or_list_size
uint8_t or_list_size
Definition: detect-flowbits.h:38
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:113
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:577
DetectContentData_::fp_chop_len
uint16_t fp_chop_len
Definition: detect-content.h:98
Signature_::sig_str
char * sig_str
Definition: detect.h:659
SIG_TYPE_APP_TX
@ SIG_TYPE_APP_TX
Definition: detect.h:72
DetectEnginePktInspectionEngine
Definition: detect.h:477
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:442
DETECT_PROTO_IPV6
#define DETECT_PROTO_IPV6
Definition: detect-engine-proto.h:34
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:1292
DETECT_BYTEJUMP
@ DETECT_BYTEJUMP
Definition: detect-engine-register.h:76
DetectPatternTracker::mpm
uint32_t mpm
Definition: detect.h:722
ConfGetBool
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:483
DetectListToHumanString
const char * DetectListToHumanString(int list)
Definition: detect-parse.c:171
DetectEnginePktInspectionEngine::v1
struct DetectEnginePktInspectionEngine::@86 v1
DetectEngineCtx_::pattern_hash_table
HashListTable * pattern_hash_table
Definition: detect.h:871
DumpPatterns
void DumpPatterns(DetectEngineCtx *de_ctx)
Definition: detect-engine-analyzer.c:1265
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectContentData_::within
int32_t within
Definition: detect-content.h:109
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:471
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:62
SignatureInitData_::prefilter_sm
SigMatch * prefilter_sm
Definition: detect.h:558
EngineAnalysisCtx_::rule_engine_analysis_fp
FILE * rule_engine_analysis_fp
Definition: detect-engine-analyzer.c:78
DETECT_FLOW
@ DETECT_FLOW
Definition: detect-engine-register.h:54
Signature_::alproto
AppProto alproto
Definition: detect.h:597
RuleAnalyzer::js_warnings
JsonBuilder * js_warnings
Definition: detect-engine-analyzer.c:634
DETECT_BYTETEST_BASE_HEX
#define DETECT_BYTETEST_BASE_HEX
Definition: detect-bytetest.h:40
SigMatchData_::is_last
bool is_last
Definition: detect.h:357
g_rules_analyzer_write_m
SCMutex g_rules_analyzer_write_m
Definition: detect-engine-analyzer.c:916
DetectEngineAnalyzerItems::display_name
const char * display_name
Definition: detect-engine-analyzer.c:60
DETECT_CONTENT_WITHIN2DEPTH
#define DETECT_CONTENT_WITHIN2DEPTH
Definition: detect-content.h:62
EngineAnalysisCtx_::percent_re
pcre2_code * percent_re
Definition: detect-engine-analyzer.c:83
DETECT_SM_LIST_DYNAMIC_START
@ DETECT_SM_LIST_DYNAMIC_START
Definition: detect.h:132
DETECT_FLOWBITS_CMD_ISNOTSET
#define DETECT_FLOWBITS_CMD_ISNOTSET
Definition: detect-flowbits.h:31
SIG_FLAG_DEST_IS_TARGET
#define SIG_FLAG_DEST_IS_TARGET
Definition: detect.h:276
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:358
DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED
#define DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED
Definition: detect-content.h:55
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:181
EngineAnalysisCtx_
Definition: detect-engine-analyzer.c:76
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:74
DETECT_BYTEJUMP_BASE_OCT
#define DETECT_BYTEJUMP_BASE_OCT
Definition: detect-bytejump.h:29
DetectEngineFrameInspectionEngine::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:512
DetectFlowData_::flags
uint16_t flags
Definition: detect-flow.h:38
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:835
DETECT_PROTO_ANY
#define DETECT_PROTO_ANY
Definition: detect-engine-proto.h:27
DetectEnginePktInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:478
SIG_TYPE_PKT_STREAM
@ SIG_TYPE_PKT_STREAM
Definition: detect.h:68
DetectFlowbitsData_::cmd
uint8_t cmd
Definition: detect-flowbits.h:37
DetectEngineFrameInspectionEngine::mpm
bool mpm
Definition: detect.h:506
DETECT_BYTETEST_DCE
#define DETECT_BYTETEST_DCE
Definition: detect-bytetest.h:47
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:295
EngineAnalysisCtx_::fp_pattern_stats
FpPatternStats fp_pattern_stats[DETECT_SM_LIST_MAX]
Definition: detect-engine-analyzer.c:95
DetectEngineBufferTypeGetNameById
const char * DetectEngineBufferTypeGetNameById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1149
SIG_FLAG_DST_ANY
#define SIG_FLAG_DST_ANY
Definition: detect.h:235
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:246
DetectPatternTracker::cnt
uint32_t cnt
Definition: detect.h:721
rust.h
EngineAnalysisCtx_::fp_engine_analysis_fp
FILE * fp_engine_analysis_fp
Definition: detect-engine-analyzer.c:79
EngineAnalysisCtx_::analyzer_initialized
bool analyzer_initialized
Definition: detect-engine-analyzer.c:102
DetectEngineAnalyzerItems
Definition: detect-engine-analyzer.c:54
DETECT_BYTEJUMP_DCE
#define DETECT_BYTEJUMP_DCE
Definition: detect-bytejump.h:40
DetectPatternTracker::cd
const struct DetectContentData_ * cd
Definition: detect.h:719
VarNameStoreSetupLookup
const char * VarNameStoreSetupLookup(const uint32_t id, const enum VarTypes type)
Definition: util-var-name.c:188
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:645
FpPatternStats_::max
uint16_t max
Definition: detect-engine-analyzer.c:65
SignatureInitData_::init_flags
uint32_t init_flags
Definition: detect.h:544
DetectBufferType_
Definition: detect.h:445
DETECT_FLOWBITS_CMD_TOGGLE
#define DETECT_FLOWBITS_CMD_TOGGLE
Definition: detect-flowbits.h:29
DetectContentData_
Definition: detect-content.h:93
DETECT_FLOWBITS_CMD_ISSET
#define DETECT_FLOWBITS_CMD_ISSET
Definition: detect-flowbits.h:32
DetectPcreData_::flags
uint16_t flags
Definition: detect-pcre.h:46
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:94
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:263
DETECT_BYTEJUMP_BIG
#define DETECT_BYTEJUMP_BIG
Definition: detect-bytejump.h:36
SIG_FLAG_SRC_ANY
#define SIG_FLAG_SRC_ANY
Definition: detect.h:234
SigMatchData_
Data needed for Match()
Definition: detect.h:355
DetectBytejumpData_::base
uint8_t base
Definition: detect-bytejump.h:48
detect-pcre.h
SIG_TYPE_APPLAYER
@ SIG_TYPE_APPLAYER
Definition: detect.h:71
SigMatchData_::type
uint16_t type
Definition: detect.h:356
DetectBytejumpData_
Definition: detect-bytejump.h:46
Signature_::frame_inspect
DetectEngineFrameInspectionEngine * frame_inspect
Definition: detect.h:641
DetectBytejumpData_::offset
int32_t offset
Definition: detect-bytejump.h:50
DetectEnginePktInspectionEngine::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:486
ConfValIsTrue
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:537
EngineAnalysisCtx_::analyzer_items
DetectEngineAnalyzerItems * analyzer_items
Definition: detect-engine-analyzer.c:81
DETECT_PERCENT_ENCODING_REGEX
#define DETECT_PERCENT_ENCODING_REGEX
DetectEngineBufferTypeGetById
const DetectBufferType * DetectEngineBufferTypeGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1139
DetectBytejumpData_::multiplier
uint16_t multiplier
Definition: detect-bytejump.h:52
SIG_FLAG_APPLAYER
#define SIG_FLAG_APPLAYER
Definition: detect.h:241
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1119
Signature_::gid
uint32_t gid
Definition: detect.h:628
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:429
ATTR_FMT_PRINTF
#define ATTR_FMT_PRINTF(x, y)
Definition: suricata-common.h:410
DetectFlowbitsData_
Definition: detect-flowbits.h:35
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:56
DetectEngineAnalyzerItems::export_item_seen
bool export_item_seen
Definition: detect-engine-analyzer.c:57
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:262
RequiresFeature
bool RequiresFeature(const char *feature_name)
Definition: feature.c:126
DETECT_BYTETEST_RELATIVE
#define DETECT_BYTETEST_RELATIVE
Definition: detect-bytetest.h:46
SIG_TYPE_PKT
@ SIG_TYPE_PKT
Definition: detect.h:67
feature.h
IpOptsFlagToString
const char * IpOptsFlagToString(uint16_t flag)
Return human readable value for ipopts flag.
Definition: detect-ipopts.c:127
EngineAnalysisCtx
struct EngineAnalysisCtx_ EngineAnalysisCtx
DETECT_CONTENT_ENDS_WITH
#define DETECT_CONTENT_ENDS_WITH
Definition: detect-content.h:42
DETECT_PCRE_RAWBYTES
#define DETECT_PCRE_RAWBYTES
Definition: detect-pcre.h:31
DETECT_CONTENT_DISTANCE
#define DETECT_CONTENT_DISTANCE
Definition: detect-content.h:30
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEnginePktInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:480
SIG_FLAG_INIT_BIDIREC
#define SIG_FLAG_INIT_BIDIREC
Definition: detect.h:284
DETECT_FLOWINT
@ DETECT_FLOWINT
Definition: detect-engine-register.h:87
SIG_MASK_REQUIRE_ENGINE_EVENT
#define SIG_MASK_REQUIRE_ENGINE_EVENT
Definition: detect.h:302
DETECT_BYTETEST_BASE_UNSET
#define DETECT_BYTETEST_BASE_UNSET
Definition: detect-bytetest.h:37
SIG_TYPE_IPONLY
@ SIG_TYPE_IPONLY
Definition: detect.h:61
DETECT_BYTEJUMP_ALIGN
#define DETECT_BYTEJUMP_ALIGN
Definition: detect-bytejump.h:39
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:556
DetectEngineBufferTypeGetDescriptionById
const char * DetectEngineBufferTypeGetDescriptionById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1227
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
SIG_FLAG_FLUSH
#define SIG_FLAG_FLUSH
Definition: detect.h:250
DetectIpOptsData_::ipopt
uint16_t ipopt
Definition: detect-ipopts.h:39
SignatureInitData_::mpm_sm_list
int mpm_sm_list
Definition: detect.h:554
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:297
SIG_FLAG_BYPASS
#define SIG_FLAG_BYPASS
Definition: detect.h:267
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:631
DETECT_BYTEJUMP_END
#define DETECT_BYTEJUMP_END
Definition: detect-bytejump.h:42
Signature_::pkt_inspect
DetectEnginePktInspectionEngine * pkt_inspect
Definition: detect.h:640
DetectEngineAnalyzerItems
struct DetectEngineAnalyzerItems DetectEngineAnalyzerItems
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect-engine-mpm.h
detect.h
SIG_MASK_REQUIRE_FLAGS_INITDEINIT
#define SIG_MASK_REQUIRE_FLAGS_INITDEINIT
Definition: detect.h:298
DetectEngineFrameInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:507
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:350
DetectEngineAnalyzerItems::item_seen
bool item_seen
Definition: detect-engine-analyzer.c:56
DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_NEGATED
Definition: detect-content.h:40
util-time.h
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:111
EngineAnalysisRules
void EngineAnalysisRules(const DetectEngineCtx *de_ctx, const Signature *s, const char *line)
Prints analysis of loaded rules.
Definition: detect-engine-analyzer.c:1406
Signature_::app_inspect
DetectEngineAppInspectionEngine * app_inspect
Definition: detect.h:639
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:349
SIG_FLAG_REQUIRE_FLOWVAR
#define SIG_FLAG_REQUIRE_FLOWVAR
Definition: detect.h:258
FpPatternStats_::cnt
uint32_t cnt
Definition: detect-engine-analyzer.c:66
SCReturn
#define SCReturn
Definition: util-debug.h:273
Signature_::flags
uint32_t flags
Definition: detect.h:593
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:106
DETECT_BYTETEST_BIG
#define DETECT_BYTETEST_BIG
Definition: detect-bytetest.h:44
SCLocalTime
struct tm * SCLocalTime(time_t timep, struct tm *result)
Definition: util-time.c:267
detect-bytejump.h
conf.h
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:104
CHECK
#define CHECK(pat)
Definition: detect-engine-analyzer.c:668
DetectEngineFrameInspectionEngine
Definition: detect.h:502
DetectFlowbitsData_::idx
uint32_t idx
Definition: detect-flowbits.h:36
DETECT_BYTEJUMP_BASE_UNSET
#define DETECT_BYTEJUMP_BASE_UNSET
Definition: detect-bytejump.h:28
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:661
SIG_FLAG_SRC_IS_TARGET
#define SIG_FLAG_SRC_IS_TARGET
Definition: detect.h:274
DetectContentPatternPrettyPrint
void DetectContentPatternPrettyPrint(const DetectContentData *cd, char *str, size_t str_len)
Definition: detect-content.c:744
DetectEngineTransforms::transforms
TransformData transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:406
DETECT_BYTEJUMP_BASE_HEX
#define DETECT_BYTEJUMP_BASE_HEX
Definition: detect-bytejump.h:31
SIG_TYPE_DEONLY
@ SIG_TYPE_DEONLY
Definition: detect.h:66
detect-flowbits.h
SIG_MASK_REQUIRE_PAYLOAD
#define SIG_MASK_REQUIRE_PAYLOAD
Definition: detect.h:296
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:64
DetectEngineAppInspectionEngine_::v2
struct DetectEngineAppInspectionEngine_::@85 v2
SIG_TYPE_NOT_SET
@ SIG_TYPE_NOT_SET
Definition: detect.h:60
ExposedItemSeen::bufname
const char * bufname
Definition: detect-engine-analyzer.c:72
EngineAnalysisRulesFailure
void EngineAnalysisRulesFailure(const DetectEngineCtx *de_ctx, char *line, char *file, int lineno)
Definition: detect-engine-analyzer.c:621
DETECT_BYTEJUMP_OFFSET_BE
#define DETECT_BYTEJUMP_OFFSET_BE
Definition: detect-bytejump.h:41
DetectEngineCtx_::config_prefix
char config_prefix[64]
Definition: detect.h:958
DetectSigmatchListEnumToString
const char * DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type)
Definition: detect-engine.c:4874
analyzer_items
const DetectEngineAnalyzerItems analyzer_items[]
Definition: detect-engine-analyzer.c:105
DetectEngineAppInspectionEngine_::alproto
AppProto alproto
Definition: detect.h:424
SIG_FLAG_MPM_NEG
#define SIG_FLAG_MPM_NEG
Definition: detect.h:248
detect-engine-analyzer.h
SIG_FLAG_INIT_STATE_MATCH
#define SIG_FLAG_INIT_STATE_MATCH
Definition: detect.h:287
DetectEngineAnalyzerItems::item_id
int16_t item_id
Definition: detect-engine-analyzer.c:55
DetectPatternTracker::sm_list
int sm_list
Definition: detect.h:720
DetectEngineAppInspectionEngine_::smd
SigMatchData * smd
Definition: detect.h:440
EngineAnalysisRules2
void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
Definition: detect-engine-analyzer.c:917
ARRAY_SIZE
#define ARRAY_SIZE(arr)
Definition: suricata-common.h:547
DETECT_CONTENT_STARTS_WITH
#define DETECT_CONTENT_STARTS_WITH
Definition: detect-content.h:59
DetectProto_::flags
uint8_t flags
Definition: detect-engine-proto.h:38
DETECT_BYTETEST
@ DETECT_BYTETEST
Definition: detect-engine-register.h:75
DETECT_PROTO_IPV4
#define DETECT_PROTO_IPV4
Definition: detect-engine-proto.h:33
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:801
RuleAnalyzer::js_notes
JsonBuilder * js_notes
Definition: detect-engine-analyzer.c:635
EngineAnalysisFP
void EngineAnalysisFP(const DetectEngineCtx *de_ctx, const Signature *s, char *line)
Definition: detect-engine-analyzer.c:162
FpPatternStats_::min
uint16_t min
Definition: detect-engine-analyzer.c:64
VAR_TYPE_FLOW_BIT
@ VAR_TYPE_FLOW_BIT
Definition: util-var.h:35
Signature_::proto
DetectProto proto
Definition: detect.h:611
suricata-common.h
SIG_MASK_REQUIRE_NO_PAYLOAD
#define SIG_MASK_REQUIRE_NO_PAYLOAD
Definition: detect.h:300
SIG_FLAG_SP_ANY
#define SIG_FLAG_SP_ANY
Definition: detect.h:236
ExposedItemSeen
Definition: detect-engine-analyzer.c:71
SigMatch_::type
uint16_t type
Definition: detect.h:347
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:88
DetectEngineAnalyzerItems::check_encoding_match
bool check_encoding_match
Definition: detect-engine-analyzer.c:58
DetectContentData_::distance
int32_t distance
Definition: detect-content.h:108
CleanupEngineAnalysis
void CleanupEngineAnalysis(DetectEngineCtx *de_ctx)
Definition: detect-engine-analyzer.c:507
DetectBytejumpData_::nbytes
uint8_t nbytes
Definition: detect-bytejump.h:47
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:30
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:127
DetectEngineFrameInspectionEngine::next
struct DetectEngineFrameInspectionEngine * next
Definition: detect.h:515
DetectEnginePktInspectionEngine::next
struct DetectEnginePktInspectionEngine * next
Definition: detect.h:488
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:94
Signature_::rev
uint32_t rev
Definition: detect.h:629
FatalError
#define FatalError(...)
Definition: util-debug.h:502
DETECT_BYTEJUMP_BASE_DEC
#define DETECT_BYTEJUMP_BASE_DEC
Definition: detect-bytejump.h:30
DetectIpOptsData_
Definition: detect-ipopts.h:38
SIG_FLAG_NOALERT
#define SIG_FLAG_NOALERT
Definition: detect.h:239
SIG_MASK_REQUIRE_FLAGS_UNUSUAL
#define SIG_MASK_REQUIRE_FLAGS_UNUSUAL
Definition: detect.h:299
TransformData_::transform
int transform
Definition: detect.h:401
DETECT_FLOWBITS
@ DETECT_FLOWBITS
Definition: detect-engine-register.h:90
SIG_TYPE_MAX
@ SIG_TYPE_MAX
Definition: detect.h:74
DetectEngineCtx_::ea
struct EngineAnalysisCtx_ * ea
Definition: detect.h:1036
DetectEngineAppInspectionEngine_::progress
int16_t progress
Definition: detect.h:431
DETECT_BYTETEST_BASE_OCT
#define DETECT_BYTETEST_BASE_OCT
Definition: detect-bytetest.h:38
util-validate.h
detect-flow.h
PrintRawUriFp
void PrintRawUriFp(FILE *fp, uint8_t *buf, uint32_t buflen)
Definition: util-print.c:90
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
ConfigGetLogDirectory
const char * ConfigGetLogDirectory(void)
Definition: util-conf.c:38
FpPatternStats
struct FpPatternStats_ FpPatternStats
str
#define str(s)
Definition: suricata-common.h:291
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SigMatchListSMBelongsTo
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
Definition: detect-parse.c:820
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DetectFlowbitsData_::or_list
uint32_t * or_list
Definition: detect-flowbits.h:39
ConfNode_
Definition: conf.h:32
Signature_::id
uint32_t id
Definition: detect.h:627
DETECT_CONTENT_OFFSET
#define DETECT_CONTENT_OFFSET
Definition: detect-content.h:32
HashListTableBucket_
Definition: util-hashlist.h:28
DETECT_FLOWBITS_CMD_UNSET
#define DETECT_FLOWBITS_CMD_UNSET
Definition: detect-flowbits.h:30
DETECT_CONTENT_FAST_PATTERN_ONLY
#define DETECT_CONTENT_FAST_PATTERN_ONLY
Definition: detect-content.h:35
DETECT_CONTENT_MPM
#define DETECT_CONTENT_MPM
Definition: detect-content.h:61
DetectBufferType_::transforms
DetectEngineTransforms transforms
Definition: detect.h:457
detect-parse.h
Signature_
Signature container.
Definition: detect.h:592
SigMatch_
a single match condition for a signature
Definition: detect.h:346
DetectEngineAppInspectionEngine_::transforms
const DetectEngineTransforms * transforms
Definition: detect.h:437
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:129
FpPatternStats_::tot
uint64_t tot
Definition: detect-engine-analyzer.c:67
DETECT_BYTETEST_STRING
#define DETECT_BYTETEST_STRING
Definition: detect-bytetest.h:45
DetectBytetestData_::offset
int32_t offset
Definition: detect-bytetest.h:60
DetectFlagsData_
Definition: detect-tcp-flags.h:38
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-ipopts.h
DetectEngineTransforms::cnt
int cnt
Definition: detect.h:407
suricata.h
DetectPcreData_
Definition: detect-pcre.h:42
DetectEngineAppInspectionEngine_::dir
uint8_t dir
Definition: detect.h:425
DetectEngineAnalyzerItems::item_name
const char * item_name
Definition: detect-engine-analyzer.c:59
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:73
DETECT_BYTEJUMP_STRING
#define DETECT_BYTEJUMP_STRING
Definition: detect-bytejump.h:37
DetectEngineCtx_::buffer_type_id
uint32_t buffer_type_id
Definition: detect.h:988
EngineAnalysisCtx_::file_prefix
char * file_prefix
Definition: detect-engine-analyzer.c:82
DetectEnginePktInspectionEngine::mpm
bool mpm
Definition: detect.h:479
DETECT_BYTEJUMP_BEGIN
#define DETECT_BYTEJUMP_BEGIN
Definition: detect-bytejump.h:34
DETECT_PCRE_RELATIVE
#define DETECT_PCRE_RELATIVE
Definition: detect-pcre.h:29
RuleAnalyzer
struct RuleAnalyzer RuleAnalyzer
SIG_FLAG_TLSSTORE
#define SIG_FLAG_TLSSTORE
Definition: detect.h:265
Signature_::msg
char * msg
Definition: detect.h:650
DETECT_CONTENT_FAST_PATTERN
#define DETECT_CONTENT_FAST_PATTERN
Definition: detect-content.h:34
DetectEngineFrameInspectionEngine::v1
struct DetectEngineFrameInspectionEngine::@87 v1
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
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:100
Signature_::type
enum SignatureType type
Definition: detect.h:595
FpPatternStats_
Definition: detect-engine-analyzer.c:63
DetectBytetestData_::base
uint8_t base
Definition: detect-bytetest.h:56
DETECT_BYTETEST_LITTLE
#define DETECT_BYTETEST_LITTLE
Definition: detect-bytetest.h:43
SCMutex
#define SCMutex
Definition: threads-debug.h:114
SIG_TYPE_PDONLY
@ SIG_TYPE_PDONLY
Definition: detect.h:65
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:104
SIG_FLAG_PREFILTER
#define SIG_FLAG_PREFILTER
Definition: detect.h:269
SIG_FLAG_FILESTORE
#define SIG_FLAG_FILESTORE
Definition: detect.h:260
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:237
DETECT_FLOWBITS_CMD_SET
#define DETECT_FLOWBITS_CMD_SET
Definition: detect-flowbits.h:28
SIG_FLAG_DSIZE
#define SIG_FLAG_DSIZE
Definition: detect.h:240
DetectBytejumpData_::flags
uint16_t flags
Definition: detect-bytejump.h:49
Signature_::mask
SignatureMask mask
Definition: detect.h:603
SIG_TYPE_LIKE_IPONLY
@ SIG_TYPE_LIKE_IPONLY
Definition: detect.h:62
detect-bytetest.h
DetectProtoContainsProto
int DetectProtoContainsProto(const DetectProto *dp, int proto)
see if a DetectProto contains a certain proto
Definition: detect-engine-proto.c:135
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:245
DetectEngineFrameInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:514
ConfNodeLookupChildValue
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:814