suricata
detect-engine-analyzer.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2020 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 "detect.h"
30 #include "detect-parse.h"
31 #include "detect-engine.h"
32 #include "detect-engine-analyzer.h"
33 #include "detect-engine-mpm.h"
34 #include "conf.h"
35 #include "detect-content.h"
36 #include "detect-flow.h"
37 #include "detect-tcp-flags.h"
38 #include "feature.h"
39 #include "util-print.h"
40 
41 static int rule_warnings_only = 0;
42 static FILE *rule_engine_analysis_FD = NULL;
43 static FILE *fp_engine_analysis_FD = NULL;
44 static pcre *percent_re = NULL;
45 static pcre_extra *percent_re_study = NULL;
46 static char log_path[PATH_MAX];
47 
48 typedef struct FpPatternStats_ {
49  uint16_t min;
50  uint16_t max;
51  uint32_t cnt;
52  uint64_t tot;
54 
55 /* Details for each buffer being tracked */
56 typedef struct DetectEngineAnalyzerItems {
57  int16_t item_id;
58  bool item_seen;
61  const char *item_name;
62  const char *display_name;
64 
65 /* Track which items require the item_seen value to be exposed */
67  const char *bufname;
69 };
70 
72  /* request keywords */
73  { 0, false, false, true, "http_uri", "http uri" },
74  { 0, false, false, false, "http_raw_uri", "http raw uri" },
75  { 0, false, true, false, "http_method", "http method" },
76  { 0, false, false, false, "http_request_line", "http request line" },
77  { 0, false, false, false, "http_client_body", "http client body" },
78  { 0, false, false, true, "http_header", "http header" },
79  { 0, false, false, false, "http_raw_header", "http raw header" },
80  { 0, false, false, true, "http_cookie", "http cookie" },
81  { 0, false, false, false, "http_user_agent", "http user agent" },
82  { 0, false, false, false, "http_host", "http host" },
83  { 0, false, false, false, "http_raw_host", "http raw host" },
84  { 0, false, false, false, "http_accept_enc", "http accept enc" },
85  { 0, false, false, false, "http_referer", "http referer" },
86  { 0, false, false, false, "http_content_type", "http content type" },
87  { 0, false, false, false, "http_header_names", "http header names" },
88 
89  /* response keywords not listed above */
90  { 0, false, false, false, "http_stat_msg", "http stat msg" },
91  { 0, false, false, false, "http_stat_code", "http stat code" },
92  { 0, false, true, false, "file_data", "http server body"},
93 
94  /* missing request keywords */
95  { 0, false, false, false, "http_request_line", "http request line" },
96  { 0, false, false, false, "http_accept", "http accept" },
97  { 0, false, false, false, "http_accept_lang", "http accept lang" },
98  { 0, false, false, false, "http_connection", "http connection" },
99  { 0, false, false, false, "http_content_len", "http content len" },
100  { 0, false, false, false, "http_protocol", "http protocol" },
101  { 0, false, false, false, "http_start", "http start" },
102 
103  /* missing response keywords; some of the missing are listed above*/
104  { 0, false, false, false, "http_response_line", "http response line" },
105  { 0, false, false, false, "http.server", "http server" },
106  { 0, false, false, false, "http.location", "http location" },
107 };
108 
109 /*
110  * This array contains the map between the `analyzer_items` array listed above and
111  * the item ids returned by DetectBufferTypeGetByName. Iterating signature's sigmatch
112  * array provides list_ids. The map converts those ids into elements of the
113  * analyzer items array.
114  *
115  * Ultimately, the g_buffer_type_hash is searched for each buffer name. The size of that
116  * hashlist is 256, so that's the value we use here.
117  */
118 int16_t analyzer_item_map[256];
119 
120 /*
121  * Certain values must be directly accessible. This array contains items that are directly
122  * accessed when checking if they've been seen or not.
123  */
125  { .bufname = "http_method"},
126  { .bufname = "file_data"}
127 };
128 
129 static FpPatternStats fp_pattern_stats[DETECT_SM_LIST_MAX];
130 
131 static void FpPatternStatsAdd(int list, uint16_t patlen)
132 {
133  if (list < 0 || list >= DETECT_SM_LIST_MAX)
134  return;
135 
136  FpPatternStats *f = &fp_pattern_stats[list];
137 
138  if (f->min == 0)
139  f->min = patlen;
140  else if (patlen < f->min)
141  f->min = patlen;
142 
143  if (patlen > f->max)
144  f->max = patlen;
145 
146  f->cnt++;
147  f->tot += patlen;
148 }
149 
150 void EngineAnalysisFP(const DetectEngineCtx *de_ctx, const Signature *s, char *line)
151 {
152  int fast_pattern_set = 0;
153  int fast_pattern_only_set = 0;
154  int fast_pattern_chop_set = 0;
155  DetectContentData *fp_cd = NULL;
156  SigMatch *mpm_sm = s->init_data->mpm_sm;
157 
158  if (mpm_sm != NULL) {
159  fp_cd = (DetectContentData *)mpm_sm->ctx;
160  if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN) {
161  fast_pattern_set = 1;
163  fast_pattern_only_set = 1;
164  } else if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
165  fast_pattern_chop_set = 1;
166  }
167  }
168  }
169 
170  fprintf(fp_engine_analysis_FD, "== Sid: %u ==\n", s->id);
171  fprintf(fp_engine_analysis_FD, "%s\n", line);
172 
173  fprintf(fp_engine_analysis_FD, " Fast Pattern analysis:\n");
174  if (s->init_data->prefilter_sm != NULL) {
175  fprintf(fp_engine_analysis_FD, " Prefilter on: %s\n",
177  fprintf(fp_engine_analysis_FD, "\n");
178  return;
179  }
180 
181  if (fp_cd == NULL) {
182  fprintf(fp_engine_analysis_FD, " No content present\n");
183  fprintf(fp_engine_analysis_FD, "\n");
184  return;
185  }
186 
187  fprintf(fp_engine_analysis_FD, " Fast pattern matcher: ");
188  int list_type = SigMatchListSMBelongsTo(s, mpm_sm);
189  if (list_type == DETECT_SM_LIST_PMATCH)
190  fprintf(fp_engine_analysis_FD, "content\n");
191  else {
192  const char *desc = DetectBufferTypeGetDescriptionById(de_ctx, list_type);
193  const char *name = DetectBufferTypeGetNameById(de_ctx, list_type);
194  if (desc && name) {
195  fprintf(fp_engine_analysis_FD, "%s (%s)\n", desc, name);
196  }
197  }
198 
199  int flags_set = 0;
200  fprintf(fp_engine_analysis_FD, " Flags:");
201  if (fp_cd->flags & DETECT_CONTENT_OFFSET) {
202  fprintf(fp_engine_analysis_FD, " Offset");
203  flags_set = 1;
204  } if (fp_cd->flags & DETECT_CONTENT_DEPTH) {
205  fprintf(fp_engine_analysis_FD, " Depth");
206  flags_set = 1;
207  }
208  if (fp_cd->flags & DETECT_CONTENT_WITHIN) {
209  fprintf(fp_engine_analysis_FD, " Within");
210  flags_set = 1;
211  }
212  if (fp_cd->flags & DETECT_CONTENT_DISTANCE) {
213  fprintf(fp_engine_analysis_FD, " Distance");
214  flags_set = 1;
215  }
216  if (fp_cd->flags & DETECT_CONTENT_NOCASE) {
217  fprintf(fp_engine_analysis_FD, " Nocase");
218  flags_set = 1;
219  }
220  if (fp_cd->flags & DETECT_CONTENT_NEGATED) {
221  fprintf(fp_engine_analysis_FD, " Negated");
222  flags_set = 1;
223  }
224  if (flags_set == 0)
225  fprintf(fp_engine_analysis_FD, " None");
226  fprintf(fp_engine_analysis_FD, "\n");
227 
228  fprintf(fp_engine_analysis_FD, " Fast pattern set: %s\n", fast_pattern_set ? "yes" : "no");
229  fprintf(fp_engine_analysis_FD, " Fast pattern only set: %s\n",
230  fast_pattern_only_set ? "yes" : "no");
231  fprintf(fp_engine_analysis_FD, " Fast pattern chop set: %s\n",
232  fast_pattern_chop_set ? "yes" : "no");
233  if (fast_pattern_chop_set) {
234  fprintf(fp_engine_analysis_FD, " Fast pattern offset, length: %u, %u\n",
235  fp_cd->fp_chop_offset, fp_cd->fp_chop_len);
236  }
237 
238  uint16_t patlen = fp_cd->content_len;
239  uint8_t *pat = SCMalloc(fp_cd->content_len + 1);
240  if (unlikely(pat == NULL)) {
241  SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
242  exit(EXIT_FAILURE);
243  }
244  memcpy(pat, fp_cd->content, fp_cd->content_len);
245  pat[fp_cd->content_len] = '\0';
246  fprintf(fp_engine_analysis_FD, " Original content: ");
247  PrintRawUriFp(fp_engine_analysis_FD, pat, patlen);
248  fprintf(fp_engine_analysis_FD, "\n");
249 
250  if (fast_pattern_chop_set) {
251  SCFree(pat);
252  patlen = fp_cd->fp_chop_len;
253  pat = SCMalloc(fp_cd->fp_chop_len + 1);
254  if (unlikely(pat == NULL)) {
255  exit(EXIT_FAILURE);
256  }
257  memcpy(pat, fp_cd->content + fp_cd->fp_chop_offset, fp_cd->fp_chop_len);
258  pat[fp_cd->fp_chop_len] = '\0';
259  fprintf(fp_engine_analysis_FD, " Final content: ");
260  PrintRawUriFp(fp_engine_analysis_FD, pat, patlen);
261  fprintf(fp_engine_analysis_FD, "\n");
262 
263  FpPatternStatsAdd(list_type, patlen);
264  } else {
265  fprintf(fp_engine_analysis_FD, " Final content: ");
266  PrintRawUriFp(fp_engine_analysis_FD, pat, patlen);
267  fprintf(fp_engine_analysis_FD, "\n");
268 
269  FpPatternStatsAdd(list_type, patlen);
270  }
271  SCFree(pat);
272 
273  fprintf(fp_engine_analysis_FD, "\n");
274  return;
275 }
276 
277 /**
278  * \brief Sets up the fast pattern analyzer according to the config.
279  *
280  * \retval 1 If rule analyzer successfully enabled.
281  * \retval 0 If not enabled.
282  */
284 {
285  int fp_engine_analysis_set = 0;
286 
287  if ((ConfGetBool("engine-analysis.rules-fast-pattern",
288  &fp_engine_analysis_set)) == 0) {
289  return 0;
290  }
291 
292  if (fp_engine_analysis_set == 0)
293  return 0;
294 
295  const char *log_dir;
296  log_dir = ConfigGetLogDirectory();
297  snprintf(log_path, sizeof(log_path), "%s/%s", log_dir,
298  "rules_fast_pattern.txt");
299 
300  fp_engine_analysis_FD = fopen(log_path, "w");
301  if (fp_engine_analysis_FD == NULL) {
302  SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", log_path,
303  strerror(errno));
304  return 0;
305  }
306 
307  SCLogInfo("Engine-Analysis for fast_pattern printed to file - %s",
308  log_path);
309 
310  struct timeval tval;
311  struct tm *tms;
312  gettimeofday(&tval, NULL);
313  struct tm local_tm;
314  tms = SCLocalTime(tval.tv_sec, &local_tm);
315  fprintf(fp_engine_analysis_FD, "----------------------------------------------"
316  "---------------------\n");
317  fprintf(fp_engine_analysis_FD, "Date: %" PRId32 "/%" PRId32 "/%04d -- "
318  "%02d:%02d:%02d\n",
319  tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour,
320  tms->tm_min, tms->tm_sec);
321  fprintf(fp_engine_analysis_FD, "----------------------------------------------"
322  "---------------------\n");
323 
324  memset(&fp_pattern_stats, 0, sizeof(fp_pattern_stats));
325  return 1;
326 }
327 
328 /**
329  * \brief Sets up the rule analyzer according to the config
330  * \retval 1 if rule analyzer successfully enabled
331  * \retval 0 if not enabled
332  */
334 {
335  ConfNode *conf = ConfGetNode("engine-analysis");
336  int enabled = 0;
337  if (conf != NULL) {
338  const char *value = ConfNodeLookupChildValue(conf, "rules");
339  if (value && ConfValIsTrue(value)) {
340  enabled = 1;
341  } else if (value && strcasecmp(value, "warnings-only") == 0) {
342  enabled = 1;
343  rule_warnings_only = 1;
344  }
345  if (enabled) {
346  const char *log_dir;
347  log_dir = ConfigGetLogDirectory();
348  snprintf(log_path, sizeof(log_path), "%s/%s", log_dir, "rules_analysis.txt");
349  rule_engine_analysis_FD = fopen(log_path, "w");
350  if (rule_engine_analysis_FD == NULL) {
351  SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", log_path, strerror(errno));
352  return 0;
353  }
354 
355  SCLogInfo("Engine-Analysis for rules printed to file - %s",
356  log_path);
357 
358  struct timeval tval;
359  struct tm *tms;
360  gettimeofday(&tval, NULL);
361  struct tm local_tm;
362  tms = SCLocalTime(tval.tv_sec, &local_tm);
363  fprintf(rule_engine_analysis_FD, "----------------------------------------------"
364  "---------------------\n");
365  fprintf(rule_engine_analysis_FD, "Date: %" PRId32 "/%" PRId32 "/%04d -- "
366  "%02d:%02d:%02d\n",
367  tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour,
368  tms->tm_min, tms->tm_sec);
369  fprintf(rule_engine_analysis_FD, "----------------------------------------------"
370  "---------------------\n");
371 
372  /*compile regex's for rule analysis*/
373  if (PerCentEncodingSetup()== 0) {
374  fprintf(rule_engine_analysis_FD, "Error compiling regex; can't check for percent encoding in normalized http content.\n");
375  }
376  }
377  }
378  else {
379  SCLogInfo("Conf parameter \"engine-analysis.rules\" not found. "
380  "Defaulting to not printing the rules analysis report.");
381  }
382  if (!enabled) {
383  SCLogInfo("Engine-Analysis for rules disabled in conf file.");
384  return 0;
385  }
386  return 1;
387 }
388 
390 {
391  fprintf(fp_engine_analysis_FD, "============\n"
392  "Summary:\n============\n");
393  int i;
394  for (i = 0; i < DETECT_SM_LIST_MAX; i++) {
395  FpPatternStats *f = &fp_pattern_stats[i];
396  if (f->cnt == 0)
397  continue;
398 
399  fprintf(fp_engine_analysis_FD,
400  "%s, smallest pattern %u byte(s), longest pattern %u byte(s), number of patterns %u, avg pattern len %.2f byte(s)\n",
401  DetectSigmatchListEnumToString(i), f->min, f->max, f->cnt, (float)((double)f->tot/(float)f->cnt));
402  }
403 
404  if (fp_engine_analysis_FD != NULL) {
405  fclose(fp_engine_analysis_FD);
406  fp_engine_analysis_FD = NULL;
407  }
408 
409  return;
410 }
411 
412 
414 {
415  if (rule_engine_analysis_FD != NULL) {
416  SCLogInfo("Engine-Analysis for rules printed to file - %s", log_path);
417  fclose(rule_engine_analysis_FD);
418  rule_engine_analysis_FD = NULL;
419  }
420 }
421 
422 /**
423  * \brief Compiles regex for rule analysis
424  * \retval 1 if successful
425  * \retval 0 if on error
426  */
428 {
429 #define DETECT_PERCENT_ENCODING_REGEX "%[0-9|a-f|A-F]{2}"
430  const char *eb = NULL;
431  int eo = 0;
432  int opts = 0; //PCRE_NEWLINE_ANY??
433 
434  percent_re = pcre_compile(DETECT_PERCENT_ENCODING_REGEX, opts, &eb, &eo, NULL);
435  if (percent_re == NULL) {
436  SCLogError(SC_ERR_PCRE_COMPILE, "Compile of \"%s\" failed at offset %" PRId32 ": %s",
438  return 0;
439  }
440 
441  percent_re_study = pcre_study(percent_re, 0, &eb);
442  if (eb != NULL) {
443  SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb);
444  return 0;
445  }
446  return 1;
447 }
448 
449 /**
450  * \brief Checks for % encoding in content.
451  * \param Pointer to content
452  * \retval number of matches if content has % encoding
453  * \retval 0 if it doesn't have % encoding
454  * \retval -1 on error
455  */
456 int PerCentEncodingMatch (uint8_t *content, uint8_t content_len)
457 {
458 #define MAX_ENCODED_CHARS 240
459  int ret = 0;
460  int ov[MAX_ENCODED_CHARS];
461 
462  ret = pcre_exec(percent_re, percent_re_study, (char *)content, content_len, 0, 0, ov, MAX_ENCODED_CHARS);
463  if (ret == -1) {
464  return 0;
465  }
466  else if (ret < -1) {
467  SCLogError(SC_ERR_PCRE_MATCH, "Error parsing content - %s; error code is %d", content, ret);
468  return -1;
469  }
470  return ret;
471 }
472 
473 static void EngineAnalysisRulesPrintFP(const DetectEngineCtx *de_ctx, const Signature *s)
474 {
475  DetectContentData *fp_cd = NULL;
476  SigMatch *mpm_sm = s->init_data->mpm_sm;
477 
478  if (mpm_sm != NULL) {
479  fp_cd = (DetectContentData *)mpm_sm->ctx;
480  }
481 
482  if (fp_cd == NULL) {
483  return;
484  }
485 
486  uint16_t patlen = fp_cd->content_len;
487  uint8_t *pat = SCMalloc(fp_cd->content_len + 1);
488  if (unlikely(pat == NULL)) {
489  SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
490  exit(EXIT_FAILURE);
491  }
492  memcpy(pat, fp_cd->content, fp_cd->content_len);
493  pat[fp_cd->content_len] = '\0';
494 
496  SCFree(pat);
497  patlen = fp_cd->fp_chop_len;
498  pat = SCMalloc(fp_cd->fp_chop_len + 1);
499  if (unlikely(pat == NULL)) {
500  exit(EXIT_FAILURE);
501  }
502  memcpy(pat, fp_cd->content + fp_cd->fp_chop_offset, fp_cd->fp_chop_len);
503  pat[fp_cd->fp_chop_len] = '\0';
504  fprintf(rule_engine_analysis_FD, " Fast Pattern \"");
505  PrintRawUriFp(rule_engine_analysis_FD, pat, patlen);
506  } else {
507  fprintf(rule_engine_analysis_FD, " Fast Pattern \"");
508  PrintRawUriFp(rule_engine_analysis_FD, pat, patlen);
509  }
510  SCFree(pat);
511 
512  fprintf(rule_engine_analysis_FD, "\" on \"");
513 
514  int list_type = SigMatchListSMBelongsTo(s, mpm_sm);
515  if (list_type == DETECT_SM_LIST_PMATCH) {
516  int payload = 0;
517  int stream = 0;
519  payload = 1;
521  stream = 1;
522  fprintf(rule_engine_analysis_FD, "%s",
523  payload ? (stream ? "payload and reassembled stream" : "payload") : "reassembled stream");
524  }
525  else {
526  const char *desc = DetectBufferTypeGetDescriptionById(de_ctx, list_type);
527  const char *name = DetectBufferTypeGetNameById(de_ctx, list_type);
528  if (desc && name) {
529  fprintf(rule_engine_analysis_FD, "%s (%s)", desc, name);
530  } else if (desc || name) {
531  fprintf(rule_engine_analysis_FD, "%s", desc ? desc : name);
532  }
533 
534  }
535 
536  fprintf(rule_engine_analysis_FD, "\" ");
537  if (de_ctx->buffer_type_map[list_type] && de_ctx->buffer_type_map[list_type]->transforms.cnt) {
538  fprintf(rule_engine_analysis_FD, "(with %d transform(s)) ",
539  de_ctx->buffer_type_map[list_type]->transforms.cnt);
540  }
541  fprintf(rule_engine_analysis_FD, "buffer.\n");
542 
543  return;
544 }
545 
546 
547 void EngineAnalysisRulesFailure(char *line, char *file, int lineno)
548 {
549  fprintf(rule_engine_analysis_FD, "== Sid: UNKNOWN ==\n");
550  fprintf(rule_engine_analysis_FD, "%s\n", line);
551  fprintf(rule_engine_analysis_FD, " FAILURE: invalid rule.\n");
552  fprintf(rule_engine_analysis_FD, " File: %s.\n", file);
553  fprintf(rule_engine_analysis_FD, " Line: %d.\n", lineno);
554  fprintf(rule_engine_analysis_FD, "\n");
555 }
556 
557 #include "util-buffer.h"
558 #include "output-json.h"
559 
560 typedef struct RuleAnalyzer {
561  json_t *js; /* document root */
562 
563  json_t *js_warnings;
564  json_t *js_notes;
566 
567 static void __attribute__ ((format (printf, 2, 3)))
568 AnalyzerNote(RuleAnalyzer *ctx, char *fmt, ...)
569 {
570  va_list ap;
571  char str[1024];
572 
573  va_start(ap, fmt);
574  vsnprintf(str, sizeof(str), fmt, ap);
575  va_end(ap);
576 
577  if (!ctx->js_notes)
578  ctx->js_notes = json_array();
579  if (ctx->js_notes)
580  json_array_append_new(ctx->js_notes, json_string(str));
581 }
582 
583 static void __attribute__ ((format (printf, 2, 3)))
584 AnalyzerWarning(RuleAnalyzer *ctx, char *fmt, ...)
585 {
586  va_list ap;
587  char str[1024];
588 
589  va_start(ap, fmt);
590  vsnprintf(str, sizeof(str), fmt, ap);
591  va_end(ap);
592 
593  if (!ctx->js_warnings)
594  ctx->js_warnings = json_array();
595  if (ctx->js_warnings)
596  json_array_append_new(ctx->js_warnings, json_string(str));
597 }
598 
599 #define CHECK(pat) if (strlen((pat)) <= len && memcmp((pat), buf, MIN(len, strlen((pat)))) == 0) return true;
600 
601 static bool LooksLikeHTTPMethod(const uint8_t *buf, uint16_t len)
602 {
603  CHECK("GET /");
604  CHECK("POST /");
605  CHECK("HEAD /");
606  CHECK("PUT /");
607  return false;
608 }
609 
610 static bool LooksLikeHTTPUA(const uint8_t *buf, uint16_t len)
611 {
612  CHECK("User-Agent: ");
613  CHECK("\nUser-Agent: ");
614  return false;
615 }
616 
617 static void DumpMatches(RuleAnalyzer *ctx, json_t *js, const SigMatchData *smd)
618 {
619  if (smd == NULL)
620  return;
621 
622  json_t *js_matches = json_array();
623  if (js_matches == NULL) {
624  return;
625  }
626  do {
627  json_t *js_match = json_object();
628  if (js_match != NULL) {
629  const char *mname = sigmatch_table[smd->type].name;
630  json_object_set_new(js_match, "name", json_string(mname));
631 
632  switch (smd->type) {
633  case DETECT_CONTENT: {
634  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
635  uint8_t *pat = SCMalloc(cd->content_len + 1);
636  if (unlikely(pat == NULL)) {
637  SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
638  exit(EXIT_FAILURE);
639  }
640  memcpy(pat, cd->content, cd->content_len);
641  pat[cd->content_len] = '\0';
642 
643  json_t *js_match_content = json_object();
644  if (js_match_content != NULL) {
645  json_object_set_new(js_match_content, "pattern", SCJsonString((const char *)pat));
646  json_object_set_new(js_match_content, "nocase", json_boolean(cd->flags & DETECT_CONTENT_NOCASE));
647  json_object_set_new(js_match_content, "negated", json_boolean(cd->flags & DETECT_CONTENT_NEGATED));
648  json_object_set_new(js_match_content, "starts_with", json_boolean(cd->flags & DETECT_CONTENT_STARTS_WITH));
649  json_object_set_new(js_match_content, "ends_with", json_boolean(cd->flags & DETECT_CONTENT_ENDS_WITH));
650  json_object_set_new(js_match_content, "is_mpm", json_boolean(cd->flags & DETECT_CONTENT_MPM));
651  if (cd->flags & DETECT_CONTENT_OFFSET) {
652  json_object_set_new(js_match_content, "offset", json_integer(cd->offset));
653  }
654  if (cd->flags & DETECT_CONTENT_DEPTH) {
655  json_object_set_new(js_match_content, "depth", json_integer(cd->depth));
656  }
657  if (cd->flags & DETECT_CONTENT_DISTANCE) {
658  json_object_set_new(js_match_content, "distance", json_integer(cd->distance));
659  }
660  if (cd->flags & DETECT_CONTENT_WITHIN) {
661  json_object_set_new(js_match_content, "within", json_integer(cd->within));
662  }
663 
664  json_object_set_new(js_match_content, "fast_pattern", json_boolean(cd->flags & DETECT_CONTENT_FAST_PATTERN));
666  AnalyzerNote(ctx, (char *)"'fast_pattern:only' option is silently ignored and is interpreted as regular 'fast_pattern'");
667  }
668 
669  json_object_set_new(js_match, "content", js_match_content);
670  }
671 
672  if (LooksLikeHTTPMethod(cd->content, cd->content_len)) {
673  AnalyzerWarning(ctx, (char *)"pattern looks like it inspects HTTP, use http_request_line or http_method and http_uri instead for improved performance");
674  }
675  if (LooksLikeHTTPUA(cd->content, cd->content_len)) {
676  AnalyzerWarning(ctx, (char *)"pattern looks like it inspects HTTP, use http_user_agent or http_header for improved performance");
677  }
678 
679  SCFree(pat);
680  break;
681  }
682  }
683  }
684  json_array_append_new(js_matches, js_match);
685 
686  if (smd->is_last)
687  break;
688  smd++;
689  } while (1);
690  json_object_set_new(js, "matches", js_matches);
691 }
692 
695 {
696  SCEnter();
697 
698  RuleAnalyzer ctx = { NULL, NULL, NULL };
699 
700  ctx.js = json_object();
701  if (ctx.js == NULL)
702  SCReturn;
703 
704  json_object_set_new(ctx.js, "raw", json_string(s->sig_str));
705  json_object_set_new(ctx.js, "id", json_integer(s->id));
706  json_object_set_new(ctx.js, "gid", json_integer(s->gid));
707  json_object_set_new(ctx.js, "rev", json_integer(s->rev));
708  json_object_set_new(ctx.js, "msg", json_string(s->msg));
709 
710  const char *alproto = AppProtoToString(s->alproto);
711  json_object_set_new(ctx.js, "app_proto", json_string(alproto));
712 
713  json_t *js_flags = json_array();
714  if (js_flags != NULL) {
715  if (s->mask & SIG_MASK_REQUIRE_PAYLOAD) {
716  json_array_append_new(js_flags, json_string("payload"));
717  }
719  json_array_append_new(js_flags, json_string("no_payload"));
720  }
721  if (s->mask & SIG_MASK_REQUIRE_FLOW) {
722  json_array_append_new(js_flags, json_string("flow"));
723  }
725  json_array_append_new(js_flags, json_string("tcp_flags_init_deinit"));
726  }
728  json_array_append_new(js_flags, json_string("tcp_flags_unusual"));
729  }
730  if (s->mask & SIG_MASK_REQUIRE_DCERPC) {
731  json_array_append_new(js_flags, json_string("dcerpc"));
732  }
734  json_array_append_new(js_flags, json_string("engine_event"));
735  }
736  json_object_set_new(ctx.js, "requirements", js_flags);
737  }
738 
739  js_flags = json_array();
740  if (js_flags != NULL) {
741  if (s->flags & SIG_FLAG_SRC_ANY) {
742  json_array_append_new(js_flags, json_string("src_any"));
743  }
744  if (s->flags & SIG_FLAG_DST_ANY) {
745  json_array_append_new(js_flags, json_string("dst_any"));
746  }
747  if (s->flags & SIG_FLAG_SP_ANY) {
748  json_array_append_new(js_flags, json_string("sp_any"));
749  }
750  if (s->flags & SIG_FLAG_DP_ANY) {
751  json_array_append_new(js_flags, json_string("dp_any"));
752  }
753  if (s->flags & SIG_FLAG_NOALERT) {
754  json_array_append_new(js_flags, json_string("noalert"));
755  }
756  if (s->flags & SIG_FLAG_DSIZE) {
757  json_array_append_new(js_flags, json_string("dsize"));
758  }
759  if (s->flags & SIG_FLAG_APPLAYER) {
760  json_array_append_new(js_flags, json_string("applayer"));
761  }
762  if (s->flags & SIG_FLAG_IPONLY) {
763  json_array_append_new(js_flags, json_string("ip_only"));
764  }
765  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
766  json_array_append_new(js_flags, json_string("need_packet"));
767  }
768  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
769  json_array_append_new(js_flags, json_string("need_stream"));
770  }
771  if (s->flags & SIG_FLAG_MPM_NEG) {
772  json_array_append_new(js_flags, json_string("negated_mpm"));
773  }
774  if (s->flags & SIG_FLAG_FLUSH) {
775  json_array_append_new(js_flags, json_string("flush"));
776  }
777  if (s->flags & SIG_FLAG_REQUIRE_FLOWVAR) {
778  json_array_append_new(js_flags, json_string("need_flowvar"));
779  }
780  if (s->flags & SIG_FLAG_FILESTORE) {
781  json_array_append_new(js_flags, json_string("filestore"));
782  }
783  if (s->flags & SIG_FLAG_TOSERVER) {
784  json_array_append_new(js_flags, json_string("toserver"));
785  }
786  if (s->flags & SIG_FLAG_TOCLIENT) {
787  json_array_append_new(js_flags, json_string("toclient"));
788  }
789  if (s->flags & SIG_FLAG_TLSSTORE) {
790  json_array_append_new(js_flags, json_string("tlsstore"));
791  }
792  if (s->flags & SIG_FLAG_BYPASS) {
793  json_array_append_new(js_flags, json_string("bypass"));
794  }
795  if (s->flags & SIG_FLAG_PREFILTER) {
796  json_array_append_new(js_flags, json_string("prefilter"));
797  }
798  if (s->flags & SIG_FLAG_PDONLY) {
799  json_array_append_new(js_flags, json_string("proto_detect_only"));
800  }
801  if (s->flags & SIG_FLAG_SRC_IS_TARGET) {
802  json_array_append_new(js_flags, json_string("src_is_target"));
803  }
804  if (s->flags & SIG_FLAG_DEST_IS_TARGET) {
805  json_array_append_new(js_flags, json_string("dst_is_target"));
806  }
807  json_object_set_new(ctx.js, "flags", js_flags);
808  }
809 
810  json_t *js_pkt_array = json_array();
812  for ( ; pkt != NULL; pkt = pkt->next) {
813  const char *name = DetectBufferTypeGetNameById(de_ctx, pkt->sm_list);
814  if (name == NULL) {
815  switch (pkt->sm_list) {
817  name = "payload";
818  break;
820  name = "packet";
821  break;
822  default:
823  name = "unknown";
824  break;
825  }
826  }
827  json_t *js_engine = json_object();
828  if (js_engine != NULL) {
829  json_object_set_new(js_engine, "name", json_string(name));
830 
831  json_object_set_new(js_engine, "is_mpm", json_boolean(pkt->mpm));
832 
833  DumpMatches(&ctx, js_engine, pkt->smd);
834 
835  json_array_append_new(js_pkt_array, js_engine);
836  }
837  }
838  json_object_set_new(ctx.js, "pkt_engines", js_pkt_array);
839 
841  bool has_stream = false;
842  bool has_client_body_mpm = false;
843  bool has_file_data_mpm = false;
844 
845  json_t *js_array = json_array();
847  for ( ; app != NULL; app = app->next) {
848  const char *name = DetectBufferTypeGetNameById(de_ctx, app->sm_list);
849  if (name == NULL) {
850  switch (app->sm_list) {
852  name = "stream";
853  break;
854  default:
855  name = "unknown";
856  break;
857  }
858  }
859 
860  if (app->sm_list == DETECT_SM_LIST_PMATCH && !app->mpm) {
861  has_stream = true;
862  } else if (app->mpm && strcmp(name, "http_client_body") == 0) {
863  has_client_body_mpm = true;
864  } else if (app->mpm && strcmp(name, "file_data") == 0) {
865  has_file_data_mpm = true;
866  }
867 
868  json_t *js_engine = json_object();
869  if (js_engine != NULL) {
870  json_object_set_new(js_engine, "name", json_string(name));
871 
872  const char *direction = app->dir == 0 ? "toserver" : "toclient";
873  json_object_set_new(js_engine, "direction", json_string(direction));
874  json_object_set_new(js_engine, "is_mpm", json_boolean(app->mpm));
875  json_object_set_new(js_engine, "app_proto", json_string(AppProtoToString(app->alproto)));
876  json_object_set_new(js_engine, "progress", json_integer(app->progress));
877 
878  DumpMatches(&ctx, js_engine, app->smd);
879 
880  json_array_append_new(js_array, js_engine);
881  }
882  }
883  json_object_set_new(ctx.js, "engines", js_array);
884 
885  if (has_stream && has_client_body_mpm)
886  AnalyzerNote(&ctx, (char *)"mpm in http_client_body combined with stream match leads to stream buffering");
887  if (has_stream && has_file_data_mpm)
888  AnalyzerNote(&ctx, (char *)"mpm in file_data combined with stream match leads to stream buffering");
889  }
890 
891  json_t *js_lists = json_object();
892  for (int i = 0; i < DETECT_SM_LIST_MAX; i++) {
893  if (s->sm_arrays[i] != NULL) {
894  json_t *js_list = json_object();
895  if (js_list != NULL) {
896  DumpMatches(&ctx, js_list, s->sm_arrays[i]);
897  json_object_set_new(js_lists, DetectSigmatchListEnumToString(i), js_list);
898  }
899  }
900  }
901  json_object_set_new(ctx.js, "lists", js_lists);
902 
903  if (ctx.js_warnings) {
904  json_object_set_new(ctx.js, "warnings", ctx.js_warnings);
905  }
906  if (ctx.js_notes) {
907  json_object_set_new(ctx.js, "notes", ctx.js_notes);
908  }
909 
910  const char *filename = "rules.json";
911  const char *log_dir = ConfigGetLogDirectory();
912  char json_path[PATH_MAX] = "";
913  snprintf(json_path, sizeof(json_path), "%s/%s", log_dir, filename);
914 
915  MemBuffer *mbuf = MemBufferCreateNew(4096);
916  if (mbuf != NULL) {
917  OutputJSONMemBufferWrapper wrapper = {
918  .buffer = &mbuf,
919  .expand_by = 4096,
920  };
921 
922  int r = json_dump_callback(ctx.js, OutputJSONMemBufferCallback, &wrapper,
923  JSON_PRESERVE_ORDER|JSON_COMPACT|JSON_ENSURE_ASCII|
925  if (r != 0) {
926  SCLogWarning(SC_ERR_SOCKET, "unable to serialize JSON object");
927  } else {
928  MemBufferWriteString(mbuf, "\n");
930  FILE *fp = fopen(json_path, "a");
931  if (fp != NULL) {
932  MemBufferPrintToFPAsString(mbuf, fp);
933  fclose(fp);
934  }
936  }
937 
938  MemBufferFree(mbuf);
939  }
940  json_object_clear(ctx.js);
941  json_decref(ctx.js);
942  SCReturn;
943 }
944 
945 static void EngineAnalysisItemsReset(void)
946 {
947  for (size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
948  analyzer_items[i].item_seen = false;
949  }
950 }
951 
952 static void EngineAnalysisItemsInit(void)
953 {
954  static bool analyzer_init = false;
955 
956  if (analyzer_init) {
957  EngineAnalysisItemsReset();
958  return;
959  }
960 
961  memset(analyzer_item_map, -1, sizeof(analyzer_item_map));
962 
963  for (size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
964  DetectEngineAnalyzerItems *analyzer_item = &analyzer_items[i];
965 
966  analyzer_item->item_id = DetectBufferTypeGetByName(analyzer_item->item_name);
967  if (analyzer_item->item_id == -1) {
968  /* Mismatch between the analyzer_items array and what's supported */
970  "unable to initialize engine-analysis table: detect buffer \"%s\" not recognized.",
971  analyzer_item->item_name);
972  }
973  analyzer_item->item_seen = false;
974 
975  if (analyzer_item->export_item_seen) {
976  for (size_t k = 0; k < ARRAY_SIZE(exposed_item_seen_list); k++) {
977  if (0 == strcmp(exposed_item_seen_list[k].bufname, analyzer_item->item_name))
978  exposed_item_seen_list[k].item_seen_ptr = &analyzer_item->item_seen;
979  }
980 
981  }
982  analyzer_item_map[analyzer_item->item_id] = (int16_t) i;
983  }
984 
985  analyzer_init = true;
986 }
987 
988 /**
989  * \brief Prints analysis of loaded rules.
990  *
991  * Warns if potential rule issues are detected. For example,
992  * warns if a rule uses a construct that may perform poorly,
993  * e.g. pcre without content or with http_method content only;
994  * warns if a rule uses a construct that may not be consistent with intent,
995  * e.g. client side ports only, http and content without any http_* modifiers, etc.
996  *
997  * \param s Pointer to the signature.
998  */
1000  const Signature *s, const char *line)
1001 {
1002  uint32_t rule_bidirectional = 0;
1003  uint32_t rule_pcre = 0;
1004  uint32_t rule_pcre_http = 0;
1005  uint32_t rule_content = 0;
1006  uint32_t rule_flow = 0;
1007  uint32_t rule_flags = 0;
1008  uint32_t rule_flow_toserver = 0;
1009  uint32_t rule_flow_toclient = 0;
1010  uint32_t rule_flow_nostream = 0;
1011  uint32_t rule_ipv4_only = 0;
1012  uint32_t rule_ipv6_only = 0;
1013  uint32_t rule_flowbits = 0;
1014  uint32_t rule_flowint = 0;
1015  uint32_t rule_content_http = 0;
1016  uint32_t rule_content_offset_depth = 0;
1017  int32_t list_id = 0;
1018  uint32_t rule_warning = 0;
1019  uint32_t stream_buf = 0;
1020  uint32_t packet_buf = 0;
1021  uint32_t file_store = 0;
1022  uint32_t warn_pcre_no_content = 0;
1023  uint32_t warn_pcre_http_content = 0;
1024  uint32_t warn_pcre_http = 0;
1025  uint32_t warn_content_http_content = 0;
1026  uint32_t warn_content_http = 0;
1027  uint32_t warn_tcp_no_flow = 0;
1028  uint32_t warn_client_ports = 0;
1029  uint32_t warn_direction = 0;
1030  uint32_t warn_method_toclient = 0;
1031  uint32_t warn_method_serverbody = 0;
1032  uint32_t warn_pcre_method = 0;
1033  uint32_t warn_encoding_norm_http_buf = 0;
1034  uint32_t warn_file_store_not_present = 0;
1035  uint32_t warn_offset_depth_pkt_stream = 0;
1036  uint32_t warn_offset_depth_alproto = 0;
1037  uint32_t warn_non_alproto_fp_for_alproto_sig = 0;
1038  uint32_t warn_no_direction = 0;
1039  uint32_t warn_both_direction = 0;
1040 
1041  EngineAnalysisItemsInit();
1042 
1043  bool *http_method_item_seen_ptr = exposed_item_seen_list[0].item_seen_ptr;
1044  bool *http_server_body_item_seen_ptr = exposed_item_seen_list[1].item_seen_ptr;
1045 
1047  rule_bidirectional = 1;
1048  }
1049 
1050  if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
1051  packet_buf += 1;
1052  }
1053  if (s->flags & SIG_FLAG_FILESTORE) {
1054  file_store += 1;
1055  }
1056  if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
1057  stream_buf += 1;
1058  }
1059 
1060  if (s->proto.flags & DETECT_PROTO_IPV4) {
1061  rule_ipv4_only += 1;
1062  }
1063  if (s->proto.flags & DETECT_PROTO_IPV6) {
1064  rule_ipv6_only += 1;
1065  }
1066 
1067  for (list_id = 0; list_id < (int)s->init_data->smlists_array_size; list_id++) {
1068  SigMatch *sm = NULL;
1069  for (sm = s->init_data->smlists[list_id]; sm != NULL; sm = sm->next) {
1070  int16_t item_slot = analyzer_item_map[list_id];
1071  if (sm->type == DETECT_PCRE) {
1072  if (item_slot == -1) {
1073  rule_pcre++;
1074  continue;
1075  }
1076 
1077  rule_pcre_http++;
1078  analyzer_items[item_slot].item_seen = true;
1079  } else if (sm->type == DETECT_CONTENT) {
1080  if (item_slot == -1) {
1081  rule_content++;
1082  if (list_id == DETECT_SM_LIST_PMATCH) {
1085  rule_content_offset_depth++;
1086  }
1087  }
1088  continue;
1089  }
1090 
1091  rule_content_http++;
1092  analyzer_items[item_slot].item_seen = true;
1093 
1094  if (analyzer_items[item_slot].check_encoding_match) {
1096  if (cd != NULL && PerCentEncodingMatch(cd->content, cd->content_len) > 0) {
1097  warn_encoding_norm_http_buf += 1;
1098  }
1099  }
1100  }
1101  else if (sm->type == DETECT_FLOW) {
1102  rule_flow += 1;
1103  if ((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_TOCLIENT)) {
1104  rule_flow_toserver = 1;
1105  }
1106  else if ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_TOSERVER)) {
1107  rule_flow_toclient = 1;
1108  }
1109  DetectFlowData *fd = (DetectFlowData *)sm->ctx;
1110  if (fd != NULL) {
1111  if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM)
1112  rule_flow_nostream = 1;
1113  }
1114  }
1115  else if (sm->type == DETECT_FLOWBITS) {
1116  if (list_id == DETECT_SM_LIST_MATCH) {
1117  rule_flowbits += 1;
1118  }
1119  }
1120  else if (sm->type == DETECT_FLOWINT) {
1121  if (list_id == DETECT_SM_LIST_MATCH) {
1122  rule_flowint += 1;
1123  }
1124  }
1125  else if (sm->type == DETECT_FLAGS) {
1126  DetectFlagsData *fd = (DetectFlagsData *)sm->ctx;
1127  if (fd != NULL) {
1128  rule_flags = 1;
1129  }
1130  }
1131  } /* for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) */
1132 
1133  } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */
1134 
1135 
1136  if (file_store && !RequiresFeature("output::file-store")) {
1137  rule_warning += 1;
1138  warn_file_store_not_present = 1;
1139  }
1140 
1141  if (rule_pcre > 0 && rule_content == 0 && rule_content_http == 0) {
1142  rule_warning += 1;
1143  warn_pcre_no_content = 1;
1144  }
1145 
1146  if (rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0) {
1147  rule_warning += 1;
1148  warn_pcre_http_content = 1;
1149  }
1150  else if (s->alproto == ALPROTO_HTTP && rule_pcre > 0 && rule_pcre_http == 0) {
1151  rule_warning += 1;
1152  warn_pcre_http = 1;
1153  }
1154 
1155  if (rule_content > 0 && rule_content_http > 0) {
1156  rule_warning += 1;
1157  warn_content_http_content = 1;
1158  }
1159  if (s->alproto == ALPROTO_HTTP && rule_content > 0 && rule_content_http == 0) {
1160  rule_warning += 1;
1161  warn_content_http = 1;
1162  }
1163  if (rule_content == 1) {
1164  //todo: warning if content is weak, separate warning for pcre + weak content
1165  }
1166  if (rule_flow == 0 && rule_flags == 0
1167  && !(s->proto.flags & DETECT_PROTO_ANY) && DetectProtoContainsProto(&s->proto, IPPROTO_TCP)
1168  && (rule_content || rule_content_http || rule_pcre || rule_pcre_http || rule_flowbits)) {
1169  rule_warning += 1;
1170  warn_tcp_no_flow = 1;
1171  }
1172  if (rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)
1173  && !((s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))) {
1174  if (((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))
1175  || ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_DP_ANY) && (s->flags & SIG_FLAG_SP_ANY))) {
1176  rule_warning += 1;
1177  warn_client_ports = 1;
1178  }
1179  }
1180  if (rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)) {
1181  rule_warning += 1;
1182  warn_direction = 1;
1183  }
1184 
1185  if (*http_method_item_seen_ptr) {
1186  if (rule_flow && rule_flow_toclient) {
1187  rule_warning += 1;
1188  warn_method_toclient = 1;
1189  }
1190  if (*http_server_body_item_seen_ptr) {
1191  rule_warning += 1;
1192  warn_method_serverbody = 1;
1193  }
1194  if (rule_content == 0 && rule_content_http == 0 && (rule_pcre > 0 || rule_pcre_http > 0)) {
1195  rule_warning += 1;
1196  warn_pcre_method = 1;
1197  }
1198  }
1199  if (rule_content_offset_depth > 0 && stream_buf && packet_buf) {
1200  rule_warning += 1;
1201  warn_offset_depth_pkt_stream = 1;
1202  }
1203  if (rule_content_offset_depth > 0 && !stream_buf && packet_buf && s->alproto != ALPROTO_UNKNOWN) {
1204  rule_warning += 1;
1205  warn_offset_depth_alproto = 1;
1206  }
1207  if (s->init_data->mpm_sm != NULL && s->alproto == ALPROTO_HTTP &&
1209  rule_warning += 1;
1210  warn_non_alproto_fp_for_alproto_sig = 1;
1211  }
1212 
1213  if ((s->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) {
1214  warn_no_direction += 1;
1215  rule_warning += 1;
1216  }
1217 
1218  /* No warning about direction for ICMP protos */
1219  if (!(DetectProtoContainsProto(&s->proto, IPPROTO_ICMPV6) && DetectProtoContainsProto(&s->proto, IPPROTO_ICMP))) {
1221  warn_both_direction += 1;
1222  rule_warning += 1;
1223  }
1224  }
1225 
1226  if (!rule_warnings_only || (rule_warnings_only && rule_warning > 0)) {
1227  fprintf(rule_engine_analysis_FD, "== Sid: %u ==\n", s->id);
1228  fprintf(rule_engine_analysis_FD, "%s\n", line);
1229 
1230  if (s->flags & SIG_FLAG_IPONLY) fprintf(rule_engine_analysis_FD, " Rule is ip only.\n");
1231  if (s->flags & SIG_FLAG_PDONLY) fprintf(rule_engine_analysis_FD, " Rule is PD only.\n");
1232  if (rule_ipv6_only) fprintf(rule_engine_analysis_FD, " Rule is IPv6 only.\n");
1233  if (rule_ipv4_only) fprintf(rule_engine_analysis_FD, " Rule is IPv4 only.\n");
1234  if (packet_buf) fprintf(rule_engine_analysis_FD, " Rule matches on packets.\n");
1235  if (!rule_flow_nostream && stream_buf && (rule_flow || rule_flowbits || rule_content || rule_pcre)) {
1236  fprintf(rule_engine_analysis_FD, " Rule matches on reassembled stream.\n");
1237  }
1238  for(size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {
1240  if (ai->item_seen) {
1241  fprintf(rule_engine_analysis_FD, " Rule matches on %s buffer.\n", ai->display_name);
1242  }
1243  }
1244  if (s->alproto != ALPROTO_UNKNOWN) {
1245  fprintf(rule_engine_analysis_FD, " App layer protocol is %s.\n", AppProtoToString(s->alproto));
1246  }
1247  if (rule_content || rule_content_http || rule_pcre || rule_pcre_http) {
1248  fprintf(rule_engine_analysis_FD, " Rule contains %d content options, %d http content options, %d pcre options, and %d pcre options with http modifiers.\n", rule_content, rule_content_http, rule_pcre, rule_pcre_http);
1249  }
1250 
1251  /* print fast pattern info */
1252  if (s->init_data->prefilter_sm) {
1253  fprintf(rule_engine_analysis_FD, " Prefilter on: %s.\n",
1255  } else {
1256  EngineAnalysisRulesPrintFP(de_ctx, s);
1257  }
1258 
1259  /* this is where the warnings start */
1260  if (warn_pcre_no_content /*rule_pcre > 0 && rule_content == 0 && rule_content_http == 0*/) {
1261  fprintf(rule_engine_analysis_FD, " Warning: Rule uses pcre without a content option present.\n"
1262  " -Consider adding a content to improve performance of this rule.\n");
1263  }
1264  if (warn_pcre_http_content /*rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0*/) {
1265  fprintf(rule_engine_analysis_FD, " Warning: Rule uses content options with http_* and pcre options without http modifiers.\n"
1266  " -Consider adding http pcre modifier.\n");
1267  }
1268  else if (warn_pcre_http /*s->alproto == ALPROTO_HTTP && rule_pcre > 0 && rule_pcre_http == 0*/) {
1269  fprintf(rule_engine_analysis_FD, " Warning: Rule app layer protocol is http, but pcre options do not have http modifiers.\n"
1270  " -Consider adding http pcre modifiers.\n");
1271  }
1272  if (warn_content_http_content /*rule_content > 0 && rule_content_http > 0*/) {
1273  fprintf(rule_engine_analysis_FD, " Warning: Rule contains content with http_* and content without http_*.\n"
1274  " -Consider adding http content modifiers.\n");
1275  }
1276  if (warn_content_http /*s->alproto == ALPROTO_HTTP && rule_content > 0 && rule_content_http == 0*/) {
1277  fprintf(rule_engine_analysis_FD, " Warning: Rule app layer protocol is http, but content options do not have http_* modifiers.\n"
1278  " -Consider adding http content modifiers.\n");
1279  }
1280  if (rule_content == 1) {
1281  //todo: warning if content is weak, separate warning for pcre + weak content
1282  }
1283  if (warn_encoding_norm_http_buf) {
1284  fprintf(rule_engine_analysis_FD, " Warning: Rule may contain percent encoded content for a normalized http buffer match.\n");
1285  }
1286  if (warn_tcp_no_flow /*rule_flow == 0 && rule_flags == 0
1287  && !(s->proto.flags & DETECT_PROTO_ANY) && DetectProtoContainsProto(&s->proto, IPPROTO_TCP)*/) {
1288  fprintf(rule_engine_analysis_FD, " Warning: TCP rule without a flow or flags option.\n"
1289  " -Consider adding flow or flags to improve performance of this rule.\n");
1290  }
1291  if (warn_client_ports /*rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)
1292  && !((s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY)))
1293  if (((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))
1294  || ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_DP_ANY) && (s->flags & SIG_FLAG_SP_ANY))*/) {
1295  fprintf(rule_engine_analysis_FD, " Warning: Rule contains ports or port variables only on the client side.\n"
1296  " -Flow direction possibly inconsistent with rule.\n");
1297  }
1298  if (warn_direction /*rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)*/) {
1299  fprintf(rule_engine_analysis_FD, " Warning: Rule is bidirectional and has a flow option with a specific direction.\n");
1300  }
1301  if (warn_method_toclient /*http_method_buf && rule_flow && rule_flow_toclient*/) {
1302  fprintf(rule_engine_analysis_FD, " Warning: Rule uses content or pcre for http_method with flow:to_client or from_server\n");
1303  }
1304  if (warn_method_serverbody /*http_method_buf && http_server_body_buf*/) {
1305  fprintf(rule_engine_analysis_FD, " Warning: Rule uses content or pcre for http_method with content or pcre for http_server_body.\n");
1306  }
1307  if (warn_pcre_method /*http_method_buf && rule_content == 0 && rule_content_http == 0
1308  && (rule_pcre > 0 || rule_pcre_http > 0)*/) {
1309  fprintf(rule_engine_analysis_FD, " Warning: Rule uses pcre with only a http_method content; possible performance issue.\n");
1310  }
1311  if (warn_offset_depth_pkt_stream) {
1312  fprintf(rule_engine_analysis_FD, " Warning: Rule has depth"
1313  "/offset with raw content keywords. Please note the "
1314  "offset/depth will be checked against both packet "
1315  "payloads and stream. If you meant to have the offset/"
1316  "depth checked against just the payload, you can update "
1317  "the signature as \"alert tcp-pkt...\"\n");
1318  }
1319  if (warn_offset_depth_alproto) {
1320  fprintf(rule_engine_analysis_FD, " Warning: Rule has "
1321  "offset/depth set along with a match on a specific "
1322  "app layer protocol - %d. This can lead to FNs if we "
1323  "have a offset/depth content match on a packet payload "
1324  "before we can detect the app layer protocol for the "
1325  "flow.\n", s->alproto);
1326  }
1327  if (warn_non_alproto_fp_for_alproto_sig) {
1328  fprintf(rule_engine_analysis_FD, " Warning: Rule app layer "
1329  "protocol is http, but the fast_pattern is set on the raw "
1330  "stream. Consider adding fast_pattern over a http "
1331  "buffer for increased performance.");
1332  }
1333  if (warn_no_direction) {
1334  fprintf(rule_engine_analysis_FD, " Warning: Rule has no direction indicator.\n");
1335  }
1336  if (warn_both_direction) {
1337  fprintf(rule_engine_analysis_FD, " Warning: Rule is inspecting both the request and the response.\n");
1338  }
1339  if (warn_file_store_not_present) {
1340  fprintf(rule_engine_analysis_FD, " Warning: Rule requires file-store but the output file-store is not enabled.\n");
1341  }
1342  if (rule_warning == 0) {
1343  fprintf(rule_engine_analysis_FD, " No warnings for this rule.\n");
1344  }
1345  fprintf(rule_engine_analysis_FD, "\n");
1346  }
1347  return;
1348 }
detect-tcp-flags.h
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:545
RuleAnalyzer::js_warnings
json_t * js_warnings
Definition: detect-engine-analyzer.c:563
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:100
DetectEngineAppInspectionEngine_
Definition: detect.h:401
detect-content.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
SC_ERR_PCRE_COMPILE
@ SC_ERR_PCRE_COMPILE
Definition: util-error.h:35
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:90
DETECT_CONTENT_FAST_PATTERN_CHOP
#define DETECT_CONTENT_FAST_PATTERN_CHOP
Definition: detect-content.h:36
DetectContentData_::fp_chop_len
uint16_t fp_chop_len
Definition: detect-content.h:91
Signature_::sig_str
char * sig_str
Definition: detect.h:594
RuleAnalyzer::js_notes
json_t * js_notes
Definition: detect-engine-analyzer.c:564
DetectEnginePktInspectionEngine
Definition: detect.h:460
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:427
PerCentEncodingMatch
int PerCentEncodingMatch(uint8_t *content, uint8_t content_len)
Checks for % encoding in content.
Definition: detect-engine-analyzer.c:456
DETECT_PROTO_IPV6
#define DETECT_PROTO_IPV6
Definition: detect-engine-proto.h:34
SIG_FLAG_PDONLY
#define SIG_FLAG_PDONLY
Definition: detect.h:247
DetectFlowData_
Definition: detect-flow.h:37
SC_ERR_SOCKET
@ SC_ERR_SOCKET
Definition: util-error.h:232
DETECT_FLOW_FLAG_NOSTREAM
#define DETECT_FLOW_FLAG_NOSTREAM
Definition: detect-flow.h:33
SigTableElmt_::name
const char * name
Definition: detect.h:1209
ConfGetBool
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as an boolen.
Definition: conf.c:517
DetectEnginePktInspectionEngine::mpm
uint16_t mpm
Definition: detect.h:462
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectContentData_::within
int32_t within
Definition: detect-content.h:102
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:59
SignatureInitData_::prefilter_sm
SigMatch * prefilter_sm
Definition: detect.h:501
DETECT_FLOW
@ DETECT_FLOW
Definition: detect-engine-register.h:51
Signature_::alproto
AppProto alproto
Definition: detect.h:531
CleanupFPAnalyzer
void CleanupFPAnalyzer(void)
Definition: detect-engine-analyzer.c:389
g_rules_analyzer_write_m
SCMutex g_rules_analyzer_write_m
Definition: detect-engine-analyzer.c:693
DetectEngineAnalyzerItems::display_name
const char * display_name
Definition: detect-engine-analyzer.c:62
SIG_FLAG_DEST_IS_TARGET
#define SIG_FLAG_DEST_IS_TARGET
Definition: detect.h:251
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:331
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
json_boolean
#define json_boolean(val)
Definition: suricata-common.h:262
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:30
DetectFlowData_::flags
uint16_t flags
Definition: detect-flow.h:38
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:766
DETECT_PROTO_ANY
#define DETECT_PROTO_ANY
Definition: detect-engine-proto.h:27
DetectEnginePktInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:461
RuleAnalyzer::js
json_t * js
Definition: detect-engine-analyzer.c:561
SIG_FLAG_DST_ANY
#define SIG_FLAG_DST_ANY
Definition: detect.h:212
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
SIG_FLAG_REQUIRE_STREAM
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:224
DetectEngineAnalyzerItems
Definition: detect-engine-analyzer.c:56
OutputJSONMemBufferWrapper_::buffer
MemBuffer ** buffer
Definition: output-json.h:66
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:580
FpPatternStats_::max
uint16_t max
Definition: detect-engine-analyzer.c:50
SignatureInitData_::init_flags
uint32_t init_flags
Definition: detect.h:492
JSON_ESCAPE_SLASH
#define JSON_ESCAPE_SLASH
Definition: suricata-common.h:258
DetectContentData_
Definition: detect-content.h:86
DetectContentData_::fp_chop_offset
uint16_t fp_chop_offset
Definition: detect-content.h:93
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:237
SIG_FLAG_SRC_ANY
#define SIG_FLAG_SRC_ANY
Definition: detect.h:211
SigMatchData_
Data needed for Match()
Definition: detect.h:328
SCJsonString
json_t * SCJsonString(const char *val)
Definition: output-json.c:110
CleanupRuleAnalyzer
void CleanupRuleAnalyzer(void)
Definition: detect-engine-analyzer.c:413
ConfValIsTrue
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:566
DETECT_PERCENT_ENCODING_REGEX
#define DETECT_PERCENT_ENCODING_REGEX
SIG_FLAG_APPLAYER
#define SIG_FLAG_APPLAYER
Definition: detect.h:218
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:876
analyzer_item_map
int16_t analyzer_item_map[256]
Definition: detect-engine-analyzer.c:118
Signature_::gid
uint32_t gid
Definition: detect.h:561
__attribute__
enum @31 __attribute__
DNP3 application header.
Definition: detect-engine-analyzer.c:583
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:407
DetectEngineAnalyzerItems::export_item_seen
bool export_item_seen
Definition: detect-engine-analyzer.c:59
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:236
RequiresFeature
bool RequiresFeature(const char *feature_name)
Definition: feature.c:124
feature.h
SC_ERR_PCRE_MATCH
@ SC_ERR_PCRE_MATCH
Definition: util-error.h:32
DETECT_CONTENT_ENDS_WITH
#define DETECT_CONTENT_ENDS_WITH
Definition: detect-content.h:42
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:463
SIG_FLAG_INIT_BIDIREC
#define SIG_FLAG_INIT_BIDIREC
Definition: detect.h:259
DETECT_FLOWINT
@ DETECT_FLOWINT
Definition: detect-engine-register.h:83
SIG_MASK_REQUIRE_ENGINE_EVENT
#define SIG_MASK_REQUIRE_ENGINE_EVENT
Definition: detect.h:276
output-json.h
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:499
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
SIG_FLAG_FLUSH
#define SIG_FLAG_FLUSH
Definition: detect.h:228
SIG_MASK_REQUIRE_FLOW
#define SIG_MASK_REQUIRE_FLOW
Definition: detect.h:270
SIG_FLAG_BYPASS
#define SIG_FLAG_BYPASS
Definition: detect.h:241
DETECT_CONTENT_DEPTH
#define DETECT_CONTENT_DEPTH
Definition: detect-content.h:33
RuleAnalyzer
Definition: detect-engine-analyzer.c:560
Signature_::pkt_inspect
DetectEnginePktInspectionEngine * pkt_inspect
Definition: detect.h:576
DetectEngineAnalyzerItems
struct DetectEngineAnalyzerItems DetectEngineAnalyzerItems
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
detect-engine-mpm.h
detect.h
SIG_MASK_REQUIRE_FLAGS_INITDEINIT
#define SIG_MASK_REQUIRE_FLAGS_INITDEINIT
Definition: detect.h:271
DetectEngineAppInspectionEngine_::mpm
uint16_t mpm
Definition: detect.h:405
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:323
SigMatchData_::type
uint8_t type
Definition: detect.h:329
DetectEngineAnalyzerItems::item_seen
bool item_seen
Definition: detect-engine-analyzer.c:58
DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_NEGATED
Definition: detect-content.h:40
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:89
EngineAnalysisRules
void EngineAnalysisRules(const DetectEngineCtx *de_ctx, const Signature *s, const char *line)
Prints analysis of loaded rules.
Definition: detect-engine-analyzer.c:999
Signature_::app_inspect
DetectEngineAppInspectionEngine * app_inspect
Definition: detect.h:575
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:322
SIG_FLAG_REQUIRE_FLOWVAR
#define SIG_FLAG_REQUIRE_FLOWVAR
Definition: detect.h:232
FpPatternStats_::cnt
uint32_t cnt
Definition: detect-engine-analyzer.c:51
SCReturn
#define SCReturn
Definition: util-debug.h:302
Signature_::flags
uint32_t flags
Definition: detect.h:528
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:99
SC_ERR_FOPEN
@ SC_ERR_FOPEN
Definition: util-error.h:74
MemBufferPrintToFPAsString
#define MemBufferPrintToFPAsString(mem_buffer, fp)
Write a buffer to the file pointer as a printable char string.
Definition: util-buffer.h:93
OutputJSONMemBufferWrapper_
Definition: output-json.h:65
SIG_FLAG_IPONLY
#define SIG_FLAG_IPONLY
Definition: detect.h:219
SCLocalTime
struct tm * SCLocalTime(time_t timep, struct tm *result)
Definition: util-time.c:270
PerCentEncodingSetup
int PerCentEncodingSetup()
Compiles regex for rule analysis.
Definition: detect-engine-analyzer.c:427
conf.h
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:97
CHECK
#define CHECK(pat)
Definition: detect-engine-analyzer.c:599
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:596
SIG_FLAG_SRC_IS_TARGET
#define SIG_FLAG_SRC_IS_TARGET
Definition: detect.h:249
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:521
SC_ERR_PCRE_STUDY
@ SC_ERR_PCRE_STUDY
Definition: util-error.h:36
MemBuffer_
Definition: util-buffer.h:27
SIG_MASK_REQUIRE_PAYLOAD
#define SIG_MASK_REQUIRE_PAYLOAD
Definition: detect.h:269
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:217
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:61
ExposedItemSeen::bufname
const char * bufname
Definition: detect-engine-analyzer.c:67
DetectSigmatchListEnumToString
const char * DetectSigmatchListEnumToString(enum DetectSigmatchListEnum type)
Definition: detect-engine.c:4230
SigMatch_::type
uint8_t type
Definition: detect.h:320
DetectEngineAppInspectionEngine_::alproto
AppProto alproto
Definition: detect.h:402
SIG_FLAG_MPM_NEG
#define SIG_FLAG_MPM_NEG
Definition: detect.h:226
detect-engine-analyzer.h
SIG_FLAG_INIT_STATE_MATCH
#define SIG_FLAG_INIT_STATE_MATCH
Definition: detect.h:262
DetectEngineAnalyzerItems::item_id
int16_t item_id
Definition: detect-engine-analyzer.c:57
MAX_ENCODED_CHARS
#define MAX_ENCODED_CHARS
DetectEngineAppInspectionEngine_::smd
SigMatchData * smd
Definition: detect.h:425
EngineAnalysisRules2
void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
Definition: detect-engine-analyzer.c:694
ARRAY_SIZE
#define ARRAY_SIZE(arr)
Definition: suricata-common.h:526
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_PROTO_IPV4
#define DETECT_PROTO_IPV4
Definition: detect-engine-proto.h:33
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:581
EngineAnalysisFP
void EngineAnalysisFP(const DetectEngineCtx *de_ctx, const Signature *s, char *line)
Definition: detect-engine-analyzer.c:150
FpPatternStats_::min
uint16_t min
Definition: detect-engine-analyzer.c:49
Signature_::proto
DetectProto proto
Definition: detect.h:544
SigMatchData_::is_last
uint8_t is_last
Definition: detect.h:330
suricata-common.h
SIG_MASK_REQUIRE_NO_PAYLOAD
#define SIG_MASK_REQUIRE_NO_PAYLOAD
Definition: detect.h:273
SIG_FLAG_SP_ANY
#define SIG_FLAG_SP_ANY
Definition: detect.h:213
ExposedItemSeen
Definition: detect-engine-analyzer.c:66
DetectEngineAnalyzerItems::check_encoding_match
bool check_encoding_match
Definition: detect-engine-analyzer.c:60
DetectContentData_::distance
int32_t distance
Definition: detect-content.h:101
MemBufferFree
void MemBufferFree(MemBuffer *buffer)
Definition: util-buffer.c:82
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
MemBufferWriteString
#define MemBufferWriteString(dst,...)
Write a string buffer to the Membuffer dst.
Definition: util-buffer.h:162
DetectEnginePktInspectionEngine::next
struct DetectEnginePktInspectionEngine * next
Definition: detect.h:470
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:87
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
Signature_::rev
uint32_t rev
Definition: detect.h:562
SetupFPAnalyzer
int SetupFPAnalyzer(void)
Sets up the fast pattern analyzer according to the config.
Definition: detect-engine-analyzer.c:283
DetectEngineCtx_::buffer_type_map
DetectBufferType ** buffer_type_map
Definition: detect.h:923
FatalError
#define FatalError(x,...)
Definition: util-debug.h:532
SIG_FLAG_NOALERT
#define SIG_FLAG_NOALERT
Definition: detect.h:216
SIG_MASK_REQUIRE_FLAGS_UNUSUAL
#define SIG_MASK_REQUIRE_FLAGS_UNUSUAL
Definition: detect.h:272
EngineAnalysisRulesFailure
void EngineAnalysisRulesFailure(char *line, char *file, int lineno)
Definition: detect-engine-analyzer.c:547
DETECT_FLOWBITS
@ DETECT_FLOWBITS
Definition: detect-engine-register.h:86
DetectEngineAppInspectionEngine_::progress
int16_t progress
Definition: detect.h:408
detect-flow.h
PrintRawUriFp
void PrintRawUriFp(FILE *fp, uint8_t *buf, uint32_t buflen)
Definition: util-print.c:93
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
FpPatternStats
struct FpPatternStats_ FpPatternStats
str
#define str(s)
Definition: suricata-common.h:273
ConfigGetLogDirectory
const char * ConfigGetLogDirectory()
Definition: util-conf.c:36
SigMatchListSMBelongsTo
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
Definition: detect-parse.c:622
SCLogWarning
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:244
SCFree
#define SCFree(p)
Definition: util-mem.h:61
ConfNode_
Definition: conf.h:32
Signature_::id
uint32_t id
Definition: detect.h:560
DETECT_CONTENT_OFFSET
#define DETECT_CONTENT_OFFSET
Definition: detect-content.h:32
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:440
detect-parse.h
util-buffer.h
Signature_
Signature container.
Definition: detect.h:527
SigMatch_
a single match condition for a signature
Definition: detect.h:319
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:106
ALPROTO_HTTP
@ ALPROTO_HTTP
Definition: app-layer-protos.h:30
FpPatternStats_::tot
uint64_t tot
Definition: detect-engine-analyzer.c:52
DetectFlagsData_
Definition: detect-tcp-flags.h:41
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
OutputJSONMemBufferCallback
int OutputJSONMemBufferCallback(const char *str, size_t size, void *data)
Definition: output-json.c:1389
exposed_item_seen_list
struct ExposedItemSeen exposed_item_seen_list[]
Definition: detect-engine-analyzer.c:124
SC_ERR_MEM_ALLOC
@ SC_ERR_MEM_ALLOC
Definition: util-error.h:31
DetectEngineTransforms::cnt
int cnt
Definition: detect.h:377
suricata.h
SetupRuleAnalyzer
int SetupRuleAnalyzer(void)
Sets up the rule analyzer according to the config.
Definition: detect-engine-analyzer.c:333
DetectBufferTypeGetDescriptionById
const char * DetectBufferTypeGetDescriptionById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:913
DetectEngineAppInspectionEngine_::dir
uint8_t dir
Definition: detect.h:403
DetectEngineAnalyzerItems::item_name
const char * item_name
Definition: detect-engine-analyzer.c:61
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:88
ExposedItemSeen::item_seen_ptr
bool * item_seen_ptr
Definition: detect-engine-analyzer.c:68
DetectBufferTypeGetNameById
const char * DetectBufferTypeGetNameById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:885
SC_ERR_INITIALIZATION
@ SC_ERR_INITIALIZATION
Definition: util-error.h:75
RuleAnalyzer
struct RuleAnalyzer RuleAnalyzer
SIG_FLAG_TLSSTORE
#define SIG_FLAG_TLSSTORE
Definition: detect.h:239
Signature_::msg
char * msg
Definition: detect.h:585
DETECT_CONTENT_FAST_PATTERN
#define DETECT_CONTENT_FAST_PATTERN
Definition: detect-content.h:34
DETECT_FLAGS
@ DETECT_FLAGS
Definition: detect-engine-register.h:40
FpPatternStats_
Definition: detect-engine-analyzer.c:48
analyzer_items
DetectEngineAnalyzerItems analyzer_items[]
Definition: detect-engine-analyzer.c:71
SCMutex
#define SCMutex
Definition: threads-debug.h:114
SIG_FLAG_PREFILTER
#define SIG_FLAG_PREFILTER
Definition: detect.h:243
SIG_MASK_REQUIRE_DCERPC
#define SIG_MASK_REQUIRE_DCERPC
Definition: detect.h:274
SIG_FLAG_FILESTORE
#define SIG_FLAG_FILESTORE
Definition: detect.h:234
DETECT_CONTENT_WITHIN
#define DETECT_CONTENT_WITHIN
Definition: detect-content.h:31
MemBufferCreateNew
MemBuffer * MemBufferCreateNew(uint32_t size)
Definition: util-buffer.c:32
SIG_FLAG_DP_ANY
#define SIG_FLAG_DP_ANY
Definition: detect.h:214
SIG_FLAG_DSIZE
#define SIG_FLAG_DSIZE
Definition: detect.h:217
Signature_::mask
SignatureMask mask
Definition: detect.h:536
SignatureInitData_::smlists_array_size
uint32_t smlists_array_size
Definition: detect.h:519
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:223
ConfNodeLookupChildValue
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:843