From c81020e9a3de851ff76d2266a28526e2a18c858f Mon Sep 17 00:00:00 2001 From: Eileen Donlon Date: Mon, 30 Apr 2012 19:23:23 -0400 Subject: [PATCH] feature 349 rule analyzer v1 --- src/Makefile.am | 1 + src/detect-engine-analyzer.c | 513 +++++++++++++++++++++++++++++++++++ src/detect-engine-analyzer.h | 35 +++ src/detect.c | 15 +- 4 files changed, 561 insertions(+), 3 deletions(-) create mode 100644 src/detect-engine-analyzer.c create mode 100644 src/detect-engine-analyzer.h diff --git a/src/Makefile.am b/src/Makefile.am index 363f0b9539..7cc62503ee 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -94,6 +94,7 @@ detect-engine-hsmd.c detect-engine-hsmd.h \ detect-engine-hscd.c detect-engine-hscd.h \ detect-engine-state.c detect-engine-state.h \ detect-engine-file.c detect-engine-file.h \ +detect-engine-analyzer.c detect-engine-analyzer.h \ detect-parse.c detect-parse.h \ detect-ack.c detect-ack.h \ detect-seq.c detect-seq.h \ diff --git a/src/detect-engine-analyzer.c b/src/detect-engine-analyzer.c new file mode 100644 index 0000000000..9486e87553 --- /dev/null +++ b/src/detect-engine-analyzer.c @@ -0,0 +1,513 @@ +/* Copyright (C) 2007-2012 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Eileen Donlon + * + * Rule analyzer for the detection engine + */ + +#include "suricata-common.h" +#include "suricata.h" +#include "detect.h" +#include "detect-engine-analyzer.h" +#include "conf.h" +#include "detect-content.h" +#include "detect-flow.h" +#include "detect-flags.h" + +static int rule_warnings_only = 0; +static FILE *rule_engine_analysis_FD = NULL; +static pcre *percent_re = NULL; +static pcre_extra *percent_re_study = NULL; + +/** + * \brief Sets up the rule analyzer according to the config + * \retval 1 if rule analyzer successfully enabled + * \retval 0 if not enabled + */ +int SetupRuleAnalyzer(char *log_path) +{ + ConfNode *conf = ConfGetNode("engine-analysis.rules"); + int enabled = 0; + if (conf != NULL) { + ConfGetChildValueBool(conf, "enabled", &enabled); + if (enabled) { + //rule_engine_analysis_set = 1; + ConfGetChildValueBool(conf, "warnings-only", &rule_warnings_only); + char *log_dir; + if (ConfGet("default-log-dir", &log_dir) != 1) + log_dir = DEFAULT_LOG_DIR; + snprintf(log_path, 256, "%s/%s", log_dir, "rules_analysis.txt"); + rule_engine_analysis_FD = fopen(log_path, "w"); + if (rule_engine_analysis_FD == NULL) { + SCLogError(SC_ERR_FOPEN, "ERROR: failed to open %s: %s", log_path, strerror(errno)); + return 0; + } + + struct timeval tval; + struct tm *tms; + gettimeofday(&tval, NULL); + struct tm local_tm; + tms = (struct tm *)localtime_r(&tval.tv_sec, &local_tm); + fprintf(rule_engine_analysis_FD, "----------------------------------------------" + "---------------------\n"); + fprintf(rule_engine_analysis_FD, "Date: %" PRId32 "/%" PRId32 "/%04d -- " + "%02d:%02d:%02d\n", + tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, + tms->tm_min, tms->tm_sec); + fprintf(rule_engine_analysis_FD, "----------------------------------------------" + "---------------------\n"); + + /*compile regex's for rule analysis*/ + if (PerCentEncodingSetup()== 0) { + fprintf(rule_engine_analysis_FD, "Error compiling regex; can't check for percent encoding in normalized http content.\n"); + } + } + } + else { + SCLogInfo("Conf parameter \"engine-analysis.rules\" not found. " + "Defaulting to not printing the rules analysis report."); + } + if (!enabled) { + SCLogInfo("Engine-Analysis for rules disabled in conf file."); + return 0; + } + else return 1; +} + +void CleanupRuleAnalyzer(char *log_path) { + if (rule_engine_analysis_FD != NULL) { + SCLogInfo("Engine-Analyis for rules printed to file - %s", log_path); + fclose(rule_engine_analysis_FD); + rule_engine_analysis_FD = NULL; + } +} + +/** + * \brief Compiles regex for rule analysis + * \retval 1 if successful + * \retval 0 if on error + */ +int PerCentEncodingSetup () +{ +#define DETECT_PERCENT_ENCODING_REGEX "%[0-9|a-f|A-F]{2}" + const char *eb = NULL; + int eo = 0; + int opts = 0; //PCRE_NEWLINE_ANY?? + + percent_re = pcre_compile(DETECT_PERCENT_ENCODING_REGEX, opts, &eb, &eo, NULL); + if (percent_re == NULL) { + SCLogError(SC_ERR_PCRE_COMPILE, "Compile of \"%s\" failed at offset %" PRId32 ": %s", + DETECT_PERCENT_ENCODING_REGEX, eo, eb); + return 0; + } + + percent_re_study = pcre_study(percent_re, 0, &eb); + if (eb != NULL) { + SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb); + return 0; + } + return 1; +} + +/** + * \brief Checks for % encoding in content. + * \param Pointer to content + * \retval number of matches if content has % encoding + * \retval 0 if it doesn't have % encoding + * \retval -1 on error + */ +int PerCentEncodingMatch (uint8_t *content, uint8_t content_len) +{ +#define MAX_ENCODED_CHARS 240 + int ret = 0; + int ov[MAX_ENCODED_CHARS]; + + ret = pcre_exec(percent_re, percent_re_study, (char *)content, content_len, 0, 0, ov, MAX_ENCODED_CHARS); + if (ret == -1) { + return 0; + } + else if (ret < -1) { + SCLogError(SC_ERR_PCRE_MATCH, "Error parsing content - %s; error code is %d", content, ret); + return -1; + } + return ret; +} + +/** + * \brief Prints analysis of loaded rules. + * + * Warns if potential rule issues are detected. For example, + * warns if a rule uses a construct that may perform poorly, + * e.g. pcre without content or with http_method content only; + * warns if a rule uses a construct that may not be consistent with intent, + * e.g. client side ports only, http and content without any http_* modifiers, etc. + * + * \param s Pointer to the signature. + */ +void EngineAnalysisRules(Signature *s, char *line) +{ + uint32_t rule_bidirectional = 0; + uint32_t rule_pcre = 0; + uint32_t rule_pcre_http = 0; + uint32_t rule_content = 0; + uint32_t rule_flow = 0; + uint32_t rule_flags = 0; + uint32_t rule_flow_toserver = 0; + uint32_t rule_flow_toclient = 0; + uint32_t rule_flow_nostream = 0; + uint32_t rule_flowbits = 0; + uint32_t rule_flowint = 0; + uint32_t rule_flowvar = 0; + uint32_t rule_content_http = 0; + uint32_t list_id = 0; + uint32_t rule_warning = 0; + uint32_t raw_http_buf = 0; + uint32_t norm_http_buf = 0; + uint32_t stream_buf = 0; + uint32_t packet_buf = 0; + uint32_t http_header_buf = 0; + uint32_t http_uri_buf = 0; + uint32_t http_method_buf = 0; + uint32_t http_cookie_buf = 0; + uint32_t http_client_body_buf = 0; + uint32_t http_server_body_buf = 0; + uint32_t http_stat_code_buf = 0; + uint32_t http_stat_msg_buf = 0; + uint32_t http_raw_header_buf = 0; + uint32_t http_raw_uri_buf = 0; + uint32_t warn_pcre_no_content = 0; + uint32_t warn_pcre_http_content = 0; + uint32_t warn_pcre_http = 0; + uint32_t warn_content_http_content = 0; + uint32_t warn_content_http = 0; + uint32_t warn_tcp_no_flow = 0; + uint32_t warn_client_ports = 0; + uint32_t warn_direction = 0; + uint32_t warn_method_toclient = 0; + uint32_t warn_method_serverbody = 0; + uint32_t warn_pcre_method = 0; + uint32_t warn_encoding_norm_http_buf = 0; + + if (s->init_flags & SIG_FLAG_INIT_BIDIREC) { + rule_bidirectional = 1; + } + + if (s->flags & SIG_FLAG_REQUIRE_PACKET) { + packet_buf += 1; + } + else { + stream_buf += 1; + } + for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) { + + SigMatch *sm = NULL; + for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) { + if (sm->type == DETECT_PCRE) { + if (list_id == DETECT_SM_LIST_HCBDMATCH) { + rule_pcre_http += 1; + http_client_body_buf += 1; + raw_http_buf += 1; + } + else if (list_id == DETECT_SM_LIST_UMATCH) { + rule_pcre_http += 1; + norm_http_buf += 1; + http_uri_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HHDMATCH) { + rule_pcre_http += 1; + norm_http_buf += 1; + http_header_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HCDMATCH) { + rule_pcre_http += 1; + norm_http_buf += 1; + http_cookie_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HSBDMATCH) { + rule_pcre_http += 1; + http_server_body_buf += 1; + raw_http_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HRHDMATCH) { + rule_pcre_http += 1; + raw_http_buf += 1; + http_raw_header_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HMDMATCH) { + rule_pcre_http += 1; + raw_http_buf += 1; + http_method_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HRUDMATCH) { + rule_pcre_http += 1; + raw_http_buf += 1; + http_raw_uri_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HSMDMATCH) { + rule_pcre_http += 1; + raw_http_buf += 1; + http_stat_msg_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HSCDMATCH) { + rule_pcre_http += 1; + raw_http_buf += 1; + http_stat_code_buf += 1; + } + else { + rule_pcre += 1; + } + } + else if (sm->type == DETECT_CONTENT) { + + if (list_id == DETECT_SM_LIST_UMATCH + || list_id == DETECT_SM_LIST_HHDMATCH + || list_id == DETECT_SM_LIST_HCDMATCH) { + rule_content_http += 1; + norm_http_buf += 1; + DetectContentData *cd = (DetectContentData *)sm->ctx; + if (cd != NULL && PerCentEncodingMatch(cd->content, cd->content_len) > 0) { + warn_encoding_norm_http_buf += 1; + rule_warning += 1; + } + if (list_id == DETECT_SM_LIST_UMATCH) { + http_uri_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HHDMATCH) { + http_header_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HCDMATCH) { + http_cookie_buf += 1; + } + } + else if (list_id == DETECT_SM_LIST_HCBDMATCH) { + rule_content_http += 1; + http_client_body_buf += 1; + raw_http_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HSBDMATCH) { + rule_content_http += 1; + http_server_body_buf += 1; + raw_http_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HRHDMATCH) { + rule_content_http += 1; + raw_http_buf += 1; + http_raw_header_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HRUDMATCH) { + rule_content_http += 1; + raw_http_buf += 1; + http_raw_uri_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HSMDMATCH) { + rule_content_http += 1; + raw_http_buf += 1; + http_stat_msg_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HSCDMATCH) { + rule_content_http += 1; + raw_http_buf += 1; + http_stat_code_buf += 1; + } + else if (list_id == DETECT_SM_LIST_HMDMATCH) { + rule_content_http += 1; + http_method_buf += 1; + raw_http_buf += 1; + } + else { + rule_content += 1; + } + } + else if (sm->type == DETECT_FLOW) { + rule_flow += 1; + if (s->flags & SIG_FLAG_TOSERVER && !(s->flags & SIG_FLAG_TOCLIENT)) { + rule_flow_toserver = 1; + } + else if (s->flags & SIG_FLAG_TOCLIENT && !(s->flags & SIG_FLAG_TOSERVER)) { + rule_flow_toclient = 1; + } + DetectFlowData *fd = (DetectFlowData *)sm->ctx; + if (fd != NULL) { + if (fd->flags & FLOW_PKT_NOSTREAM) rule_flow_nostream = 1; + } + } + else if (sm->type == DETECT_FLOWBITS) { + if (list_id == DETECT_SM_LIST_MATCH) { + rule_flowbits += 1; + } + } + else if (sm->type == DETECT_FLOWINT) { + if (list_id == DETECT_SM_LIST_MATCH) { + rule_flowint += 1; + } + } + else if (sm->type == DETECT_FLAGS) { + DetectFlagsData *fd = (DetectFlagsData *)sm->ctx; + if (fd != NULL) { + rule_flags = 1; + } + } + } /* for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) */ + + } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */ + + + if (rule_pcre > 0 && rule_content == 0 && rule_content_http == 0) { + rule_warning += 1; + warn_pcre_no_content = 1; + } + + if (rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0) { + rule_warning += 1; + warn_pcre_http_content = 1; + } + else if (s->alproto == ALPROTO_HTTP && rule_pcre > 0 && rule_pcre_http == 0) { + rule_warning += 1; + warn_pcre_http = 1; + } + + if (rule_content > 0 && rule_content_http > 0) { + rule_warning += 1; + warn_content_http_content = 1; + } + if (s->alproto == ALPROTO_HTTP && rule_content > 0 && rule_content_http == 0) { + rule_warning += 1; + warn_content_http = 1; + } + if (rule_content == 1) { + //todo: warning if content is weak, separate warning for pcre + weak content + } + if (rule_flow == 0 && rule_flags == 0 + && !(s->proto.flags & DETECT_PROTO_ANY) && DetectProtoContainsProto(&s->proto, IPPROTO_TCP) + && (rule_content || rule_content_http || rule_pcre || rule_pcre_http || rule_flowbits)) { + rule_warning += 1; + warn_tcp_no_flow = 1; + } + if (rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient) + && !((s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))) { + if (((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY)) + || ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_DP_ANY) && (s->flags & SIG_FLAG_SP_ANY))) { + rule_warning += 1; + warn_client_ports = 1; + } + } + if (rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)) { + rule_warning += 1; + warn_direction = 1; + } + if (http_method_buf) { + if (rule_flow && rule_flow_toclient) { + rule_warning += 1; + warn_method_toclient = 1; + } + if (http_server_body_buf) { + rule_warning += 1; + warn_method_serverbody = 1; + } + if (rule_content == 0 && rule_content_http == 0 && (rule_pcre > 0 || rule_pcre_http > 0)) { + rule_warning += 1; + warn_pcre_method = 1; + } + } + + if (!rule_warnings_only || (rule_warnings_only && rule_warning > 0)) { + fprintf(rule_engine_analysis_FD, "== Sid: %u ==\n", s->id); + fprintf(rule_engine_analysis_FD, "%s\n", line); + + if (s->flags & SIG_FLAG_IPONLY) fprintf(rule_engine_analysis_FD, " Rule is ip only.\n"); + if (packet_buf) fprintf(rule_engine_analysis_FD, " Rule matches on packets.\n"); + if (!rule_flow_nostream && stream_buf && (rule_flow || rule_flowbits || rule_content || rule_pcre)) { + fprintf(rule_engine_analysis_FD, " Rule matches on reassembled stream.\n"); + } + if (http_uri_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http uri buffer.\n"); + if (http_header_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http header buffer.\n"); + if (http_cookie_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http cookie buffer.\n"); + if (http_raw_uri_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http raw uri buffer.\n"); + if (http_raw_header_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http raw header buffer.\n"); + if (http_method_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http method buffer.\n"); + if (http_server_body_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http server body buffer.\n"); + if (http_client_body_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http client body buffer.\n"); + if (http_stat_msg_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http stat msg buffer.\n"); + if (http_stat_code_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http stat code buffer.\n"); + if (s->alproto != ALPROTO_UNKNOWN) { + fprintf(rule_engine_analysis_FD, " App layer protocol is %s.\n", TmModuleAlprotoToString(s->alproto)); + } + if (rule_content || rule_content_http || rule_pcre || rule_pcre_http) { + 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); + } + if (warn_pcre_no_content /*rule_pcre > 0 && rule_content == 0 && rule_content_http == 0*/) { + fprintf(rule_engine_analysis_FD, " Warning: Rule uses pcre without a content option present.\n" + " -Consider adding a content to improve performance of this rule.\n"); + } + if (warn_pcre_http_content /*rule_content_http > 0 && rule_pcre > 0 && rule_pcre_http == 0*/) { + fprintf(rule_engine_analysis_FD, " Warning: Rule uses content options with http_* and pcre options without http modifiers.\n" + " -Consider adding http pcre modifier.\n"); + } + else if (warn_pcre_http /*s->alproto == ALPROTO_HTTP && rule_pcre > 0 && rule_pcre_http == 0*/) { + fprintf(rule_engine_analysis_FD, " Warning: Rule app layer protocol is http, but pcre options do not have http modifiers.\n" + " -Consider adding http pcre modifiers.\n"); + } + if (warn_content_http_content /*rule_content > 0 && rule_content_http > 0*/) { + fprintf(rule_engine_analysis_FD, " Warning: Rule contains content with http_* and content without http_*.\n" + " -Consider adding http content modifiers.\n"); + } + if (warn_content_http /*s->alproto == ALPROTO_HTTP && rule_content > 0 && rule_content_http == 0*/) { + fprintf(rule_engine_analysis_FD, " Warning: Rule app layer protocol is http, but content options do not have http_* modifiers.\n" + " -Consider adding http content modifiers.\n"); + } + if (rule_content == 1) { + //todo: warning if content is weak, separate warning for pcre + weak content + } + if (warn_encoding_norm_http_buf) { + fprintf(rule_engine_analysis_FD, " Warning: Rule may contain percent encoded content for a normalized http buffer match.\n"); + } + if (warn_tcp_no_flow /*rule_flow == 0 && rule_flow == 0 + && !(s->proto.flags & DETECT_PROTO_ANY) && DetectProtoContainsProto(&s->proto, IPPROTO_TCP)*/) { + fprintf(rule_engine_analysis_FD, " Warning: TCP rule without a flow or flags option.\n" + " -Consider adding flow or flags to improve performance of this rule.\n"); + } + if (warn_client_ports /*rule_flow && !rule_bidirectional && (rule_flow_toserver || rule_flow_toclient) + && !((s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY))) + if (((s->flags & SIG_FLAG_TOSERVER) && !(s->flags & SIG_FLAG_SP_ANY) && (s->flags & SIG_FLAG_DP_ANY)) + || ((s->flags & SIG_FLAG_TOCLIENT) && !(s->flags & SIG_FLAG_DP_ANY) && (s->flags & SIG_FLAG_SP_ANY))*/) { + fprintf(rule_engine_analysis_FD, " Warning: Rule contains ports or port variables only on the client side.\n" + " -Flow direction possibly inconsistent with rule.\n"); + } + if (warn_direction /*rule_flow && rule_bidirectional && (rule_flow_toserver || rule_flow_toclient)*/) { + fprintf(rule_engine_analysis_FD, " Warning: Rule is bidirectional and has a flow option with a specific direction.\n"); + } + if (warn_method_toclient /*http_method_buf && rule_flow && rule_flow_toclient*/) { + fprintf(rule_engine_analysis_FD, " Warning: Rule uses content or pcre for http_method with flow:to_client or from_server\n"); + } + if (warn_method_serverbody /*http_method_buf && http_server_body_buf*/) { + fprintf(rule_engine_analysis_FD, " Warning: Rule uses content or pcre for http_method with content or pcre for http_server_body.\n"); + } + if (warn_pcre_method /*http_method_buf && rule_content == 0 && rule_content_http == 0 + && (rule_pcre > 0 || rule_pcre_http > 0)*/) { + fprintf(rule_engine_analysis_FD, " Warning: Rule uses pcre with only a http_method content; possible performance issue.\n"); + } + if (rule_warning == 0) { + fprintf(rule_engine_analysis_FD, " No warnings for this rule.\n"); + } + fprintf(rule_engine_analysis_FD, "\n"); + } + return; +} diff --git a/src/detect-engine-analyzer.h b/src/detect-engine-analyzer.h new file mode 100644 index 0000000000..f3941767a1 --- /dev/null +++ b/src/detect-engine-analyzer.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2007-2012 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Eileen Donlon + */ + +#ifndef __DETECT_ENGINE_ANALYZER_H__ +#define __DETECT_ENGINE_ANALYZER_H__ + +#include + +int SetupRuleAnalyzer(char *log_path); +void CleanupRuleAnalyzer (char *log_path); +int PerCentEncodingSetup (); +int PerCentEncodingMatch (uint8_t *content, uint8_t content_len); +void EngineAnalysisRules(Signature *s, char *line); + +#endif /* __DETECT_ENGINE_ANALYZER_H__ */ diff --git a/src/detect.c b/src/detect.c index 64ecc3d6b1..00aac168e6 100644 --- a/src/detect.c +++ b/src/detect.c @@ -46,6 +46,7 @@ #include "detect-engine-dcepayload.h" #include "detect-engine-uri.h" #include "detect-engine-state.h" +#include "detect-engine-analyzer.h" #include "detect-http-cookie.h" #include "detect-http-method.h" @@ -182,6 +183,7 @@ extern uint8_t engine_mode; extern int engine_analysis; static int fp_engine_analysis_set = 0; +static int rule_engine_analysis_set = 0; static FILE *fp_engine_analysis_FD = NULL; SigMatch *SigMatchAlloc(void); @@ -523,6 +525,9 @@ int DetectLoadSigFile(DetectEngineCtx *de_ctx, char *sig_file, int *sigs_tot) { if (fp_engine_analysis_set) { EngineAnalysisFastPattern(sig); } + if (rule_engine_analysis_set) { + EngineAnalysisRules(sig, line); + } SCLogDebug("signature %"PRIu32" loaded", sig->id); good++; } else { @@ -571,7 +576,6 @@ int SigLoadSignatures(DetectEngineCtx *de_ctx, char *sig_file, int sig_file_excl "report."); fp_engine_analysis_set = 0; } - if (fp_engine_analysis_set) { char *log_dir; if (ConfGet("default-log-dir", &log_dir) != 1) @@ -597,9 +601,11 @@ int SigLoadSignatures(DetectEngineCtx *de_ctx, char *sig_file, int sig_file_excl tms->tm_min, tms->tm_sec); fprintf(fp_engine_analysis_FD, "----------------------------------------------" "---------------------\n"); - } else { + } + else { SCLogInfo("Engine-Analysis for fast_pattern disabled in conf file."); } + rule_engine_analysis_set = SetupRuleAnalyzer(log_path); } /* ok, let's load signature files from the general config */ @@ -698,6 +704,9 @@ int SigLoadSignatures(DetectEngineCtx *de_ctx, char *sig_file, int sig_file_excl fp_engine_analysis_FD = NULL; } } + if (rule_engine_analysis_set) { + CleanupRuleAnalyzer(log_path); + } } DetectParseDupSigHashFree(de_ctx); @@ -2061,7 +2070,7 @@ static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, Signature *s) { SCReturnInt(0); } - /* need at least one decode event keyword to be condered decode event. */ + /* need at least one decode event keyword to be considered decode event. */ sm = s->sm_lists[DETECT_SM_LIST_MATCH]; for ( ;sm != NULL; sm = sm->next) { if (sm->type == DETECT_DECODE_EVENT)