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