diff options
Diffstat (limited to 'framework/src/suricata/src/detect-engine-analyzer.c')
-rw-r--r-- | framework/src/suricata/src/detect-engine-analyzer.c | 926 |
1 files changed, 0 insertions, 926 deletions
diff --git a/framework/src/suricata/src/detect-engine-analyzer.c b/framework/src/suricata/src/detect-engine-analyzer.c deleted file mode 100644 index 066d41c6..00000000 --- a/framework/src/suricata/src/detect-engine-analyzer.c +++ /dev/null @@ -1,926 +0,0 @@ -/* 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 <emdonlo@gmail.com> - * - * Rule analyzer for the detection engine - */ - -#include "suricata-common.h" -#include "suricata.h" -#include "detect.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-analyzer.h" -#include "detect-engine-mpm.h" -#include "conf.h" -#include "detect-content.h" -#include "detect-flow.h" -#include "detect-flags.h" -#include "util-print.h" - -static int rule_warnings_only = 0; -static FILE *rule_engine_analysis_FD = NULL; -static FILE *fp_engine_analysis_FD = NULL; -static pcre *percent_re = NULL; -static pcre_extra *percent_re_study = NULL; -static char log_path[PATH_MAX]; - -typedef struct FpPatternStats_ { - uint16_t min; - uint16_t max; - uint32_t cnt; - uint64_t tot; -} FpPatternStats; - -static FpPatternStats fp_pattern_stats[DETECT_SM_LIST_MAX]; - -static void FpPatternStatsAdd(int list, uint16_t patlen) -{ - if (list < 0 || list >= DETECT_SM_LIST_MAX) - return; - - FpPatternStats *f = &fp_pattern_stats[list]; - - if (f->min == 0) - f->min = patlen; - else if (patlen < f->min) - f->min = patlen; - - if (patlen > f->max) - f->max = patlen; - - f->cnt++; - f->tot += patlen; -} - -void EngineAnalysisFP(Signature *s, char *line) -{ - int fast_pattern_set = 0; - int fast_pattern_only_set = 0; - int fast_pattern_chop_set = 0; - DetectContentData *fp_cd = NULL; - SigMatch *mpm_sm = s->mpm_sm; - - if (mpm_sm != NULL) { - fp_cd = (DetectContentData *)mpm_sm->ctx; - if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN) { - fast_pattern_set = 1; - if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { - fast_pattern_only_set = 1; - } else if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) { - fast_pattern_chop_set = 1; - } - } - } - - fprintf(fp_engine_analysis_FD, "== Sid: %u ==\n", s->id); - fprintf(fp_engine_analysis_FD, "%s\n", line); - - fprintf(fp_engine_analysis_FD, " Fast Pattern analysis:\n"); - if (fp_cd == NULL) { - fprintf(fp_engine_analysis_FD, " No content present\n"); - fprintf(fp_engine_analysis_FD, "\n"); - return; - } - - fprintf(fp_engine_analysis_FD, " Fast pattern matcher: "); - int list_type = SigMatchListSMBelongsTo(s, mpm_sm); - if (list_type == DETECT_SM_LIST_PMATCH) - fprintf(fp_engine_analysis_FD, "content\n"); - else if (list_type == DETECT_SM_LIST_UMATCH) - fprintf(fp_engine_analysis_FD, "http uri content\n"); - else if (list_type == DETECT_SM_LIST_HRUDMATCH) - fprintf(fp_engine_analysis_FD, "http raw uri content\n"); - else if (list_type == DETECT_SM_LIST_HHDMATCH) - fprintf(fp_engine_analysis_FD, "http header content\n"); - else if (list_type == DETECT_SM_LIST_HRHDMATCH) - fprintf(fp_engine_analysis_FD, "http raw header content\n"); - else if (list_type == DETECT_SM_LIST_HMDMATCH) - fprintf(fp_engine_analysis_FD, "http method content\n"); - else if (list_type == DETECT_SM_LIST_HCDMATCH) - fprintf(fp_engine_analysis_FD, "http cookie content\n"); - else if (list_type == DETECT_SM_LIST_HCBDMATCH) - fprintf(fp_engine_analysis_FD, "http client body content\n"); - else if (list_type == DETECT_SM_LIST_FILEDATA) - fprintf(fp_engine_analysis_FD, "http server body content\n"); - else if (list_type == DETECT_SM_LIST_HSCDMATCH) - fprintf(fp_engine_analysis_FD, "http stat code content\n"); - else if (list_type == DETECT_SM_LIST_HSMDMATCH) - fprintf(fp_engine_analysis_FD, "http stat msg content\n"); - else if (list_type == DETECT_SM_LIST_HUADMATCH) - fprintf(fp_engine_analysis_FD, "http user agent content\n"); - - int flags_set = 0; - fprintf(fp_engine_analysis_FD, " Flags:"); - if (fp_cd->flags & DETECT_CONTENT_OFFSET) { - fprintf(fp_engine_analysis_FD, " Offset"); - flags_set = 1; - } if (fp_cd->flags & DETECT_CONTENT_DEPTH) { - fprintf(fp_engine_analysis_FD, " Depth"); - flags_set = 1; - } - if (fp_cd->flags & DETECT_CONTENT_WITHIN) { - fprintf(fp_engine_analysis_FD, " Within"); - flags_set = 1; - } - if (fp_cd->flags & DETECT_CONTENT_DISTANCE) { - fprintf(fp_engine_analysis_FD, " Distance"); - flags_set = 1; - } - if (fp_cd->flags & DETECT_CONTENT_NOCASE) { - fprintf(fp_engine_analysis_FD, " Nocase"); - flags_set = 1; - } - if (fp_cd->flags & DETECT_CONTENT_NEGATED) { - fprintf(fp_engine_analysis_FD, " Negated"); - flags_set = 1; - } - if (flags_set == 0) - fprintf(fp_engine_analysis_FD, " None"); - fprintf(fp_engine_analysis_FD, "\n"); - - fprintf(fp_engine_analysis_FD, " Fast pattern set: %s\n", fast_pattern_set ? "yes" : "no"); - fprintf(fp_engine_analysis_FD, " Fast pattern only set: %s\n", - fast_pattern_only_set ? "yes" : "no"); - fprintf(fp_engine_analysis_FD, " Fast pattern chop set: %s\n", - fast_pattern_chop_set ? "yes" : "no"); - if (fast_pattern_chop_set) { - fprintf(fp_engine_analysis_FD, " Fast pattern offset, length: %u, %u\n", - fp_cd->fp_chop_offset, fp_cd->fp_chop_len); - } - - uint16_t patlen = fp_cd->content_len; - uint8_t *pat = SCMalloc(fp_cd->content_len + 1); - if (unlikely(pat == NULL)) { - SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); - exit(EXIT_FAILURE); - } - memcpy(pat, fp_cd->content, fp_cd->content_len); - pat[fp_cd->content_len] = '\0'; - fprintf(fp_engine_analysis_FD, " Original content: "); - PrintRawUriFp(fp_engine_analysis_FD, pat, patlen); - fprintf(fp_engine_analysis_FD, "\n"); - - if (fast_pattern_chop_set) { - SCFree(pat); - patlen = fp_cd->fp_chop_len; - pat = SCMalloc(fp_cd->fp_chop_len + 1); - if (unlikely(pat == NULL)) { - exit(EXIT_FAILURE); - } - memcpy(pat, fp_cd->content + fp_cd->fp_chop_offset, fp_cd->fp_chop_len); - pat[fp_cd->fp_chop_len] = '\0'; - fprintf(fp_engine_analysis_FD, " Final content: "); - PrintRawUriFp(fp_engine_analysis_FD, pat, patlen); - fprintf(fp_engine_analysis_FD, "\n"); - - FpPatternStatsAdd(list_type, patlen); - } else { - fprintf(fp_engine_analysis_FD, " Final content: "); - PrintRawUriFp(fp_engine_analysis_FD, pat, patlen); - fprintf(fp_engine_analysis_FD, "\n"); - - FpPatternStatsAdd(list_type, patlen); - } - SCFree(pat); - - fprintf(fp_engine_analysis_FD, "\n"); - return; -} - -/** - * \brief Sets up the fast pattern analyzer according to the config. - * - * \retval 1 If rule analyzer successfully enabled. - * \retval 0 If not enabled. - */ -int SetupFPAnalyzer(void) -{ - int fp_engine_analysis_set = 0; - - if ((ConfGetBool("engine-analysis.rules-fast-pattern", - &fp_engine_analysis_set)) == 0) { - return 0; - } - - if (fp_engine_analysis_set == 0) - return 0; - - char *log_dir; - log_dir = ConfigGetLogDirectory(); - snprintf(log_path, sizeof(log_path), "%s/%s", log_dir, - "rules_fast_pattern.txt"); - - fp_engine_analysis_FD = fopen(log_path, "w"); - if (fp_engine_analysis_FD == NULL) { - SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", log_path, - strerror(errno)); - return 0; - } - - SCLogInfo("Engine-Analysis for fast_pattern printed to file - %s", - log_path); - - struct timeval tval; - struct tm *tms; - gettimeofday(&tval, NULL); - struct tm local_tm; - tms = SCLocalTime(tval.tv_sec, &local_tm); - fprintf(fp_engine_analysis_FD, "----------------------------------------------" - "---------------------\n"); - fprintf(fp_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(fp_engine_analysis_FD, "----------------------------------------------" - "---------------------\n"); - - memset(&fp_pattern_stats, 0, sizeof(fp_pattern_stats)); - return 1; -} - -/** - * \brief Sets up the rule analyzer according to the config - * \retval 1 if rule analyzer successfully enabled - * \retval 0 if not enabled - */ -int SetupRuleAnalyzer(void) -{ - ConfNode *conf = ConfGetNode("engine-analysis"); - int enabled = 0; - if (conf != NULL) { - const char *value = ConfNodeLookupChildValue(conf, "rules"); - if (value && ConfValIsTrue(value)) { - enabled = 1; - } else if (value && strcasecmp(value, "warnings-only") == 0) { - enabled = 1; - rule_warnings_only = 1; - } - if (enabled) { - char *log_dir; - log_dir = ConfigGetLogDirectory(); - snprintf(log_path, sizeof(log_path), "%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, "failed to open %s: %s", log_path, strerror(errno)); - return 0; - } - - SCLogInfo("Engine-Analysis for rules printed to file - %s", - log_path); - - struct timeval tval; - struct tm *tms; - gettimeofday(&tval, NULL); - struct tm local_tm; - tms = SCLocalTime(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; - } - return 1; -} - -void CleanupFPAnalyzer(void) -{ - fprintf(fp_engine_analysis_FD, "============\n" - "Summary:\n============\n"); - int i; - for (i = 0; i < DETECT_SM_LIST_MAX; i++) { - FpPatternStats *f = &fp_pattern_stats[i]; - if (f->cnt == 0) - continue; - - fprintf(fp_engine_analysis_FD, - "%s, smallest pattern %u byte(s), longest pattern %u byte(s), number of patterns %u, avg pattern len %.2f byte(s)\n", - DetectSigmatchListEnumToString(i), f->min, f->max, f->cnt, (float)((double)f->tot/(float)f->cnt)); - } - - if (fp_engine_analysis_FD != NULL) { - fclose(fp_engine_analysis_FD); - fp_engine_analysis_FD = NULL; - } - - return; -} - - -void CleanupRuleAnalyzer(void) -{ - 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; -} - -static void EngineAnalysisRulesPrintFP(Signature *s) -{ - DetectContentData *fp_cd = NULL; - SigMatch *mpm_sm = s->mpm_sm; - - if (mpm_sm != NULL) { - fp_cd = (DetectContentData *)mpm_sm->ctx; - } - - if (fp_cd == NULL) { - return; - } - - uint16_t patlen = fp_cd->content_len; - uint8_t *pat = SCMalloc(fp_cd->content_len + 1); - if (unlikely(pat == NULL)) { - SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); - exit(EXIT_FAILURE); - } - memcpy(pat, fp_cd->content, fp_cd->content_len); - pat[fp_cd->content_len] = '\0'; - - if (fp_cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) { - SCFree(pat); - patlen = fp_cd->fp_chop_len; - pat = SCMalloc(fp_cd->fp_chop_len + 1); - if (unlikely(pat == NULL)) { - exit(EXIT_FAILURE); - } - memcpy(pat, fp_cd->content + fp_cd->fp_chop_offset, fp_cd->fp_chop_len); - pat[fp_cd->fp_chop_len] = '\0'; - fprintf(rule_engine_analysis_FD, " Fast Pattern \""); - PrintRawUriFp(rule_engine_analysis_FD, pat, patlen); - } else { - fprintf(rule_engine_analysis_FD, " Fast Pattern \""); - PrintRawUriFp(rule_engine_analysis_FD, pat, patlen); - } - SCFree(pat); - - fprintf(rule_engine_analysis_FD, "\" on \""); - - int list_type = SigMatchListSMBelongsTo(s, mpm_sm); - if (list_type == DETECT_SM_LIST_PMATCH) { - int payload = 0; - int stream = 0; - if (SignatureHasPacketContent(s)) - payload = 1; - if (SignatureHasStreamContent(s)) - stream = 1; - fprintf(rule_engine_analysis_FD, "%s", - payload ? (stream ? "payload and reassembled stream" : "payload") : "reassembled stream"); - } - else if (list_type == DETECT_SM_LIST_UMATCH) - fprintf(rule_engine_analysis_FD, "http uri content"); - else if (list_type == DETECT_SM_LIST_HRUDMATCH) - fprintf(rule_engine_analysis_FD, "http raw uri content"); - else if (list_type == DETECT_SM_LIST_HHDMATCH) - fprintf(rule_engine_analysis_FD, "http header content"); - else if (list_type == DETECT_SM_LIST_HRHDMATCH) - fprintf(rule_engine_analysis_FD, "http raw header content"); - else if (list_type == DETECT_SM_LIST_HMDMATCH) - fprintf(rule_engine_analysis_FD, "http method content"); - else if (list_type == DETECT_SM_LIST_HCDMATCH) - fprintf(rule_engine_analysis_FD, "http cookie content"); - else if (list_type == DETECT_SM_LIST_HCBDMATCH) - fprintf(rule_engine_analysis_FD, "http client body content"); - else if (list_type == DETECT_SM_LIST_FILEDATA) - fprintf(rule_engine_analysis_FD, "http server body content"); - else if (list_type == DETECT_SM_LIST_HSCDMATCH) - fprintf(rule_engine_analysis_FD, "http stat code content"); - else if (list_type == DETECT_SM_LIST_HSMDMATCH) - fprintf(rule_engine_analysis_FD, "http stat msg content"); - else if (list_type == DETECT_SM_LIST_HUADMATCH) - fprintf(rule_engine_analysis_FD, "http user agent content"); - else if (list_type == DETECT_SM_LIST_DNSQUERYNAME_MATCH) - fprintf(rule_engine_analysis_FD, "dns query name content"); - - fprintf(rule_engine_analysis_FD, "\" buffer.\n"); - - return; -} - - -void EngineAnalysisRulesFailure(char *line, char *file, int lineno) -{ - fprintf(rule_engine_analysis_FD, "== Sid: UNKNOWN ==\n"); - fprintf(rule_engine_analysis_FD, "%s\n", line); - fprintf(rule_engine_analysis_FD, " FAILURE: invalid rule.\n"); - fprintf(rule_engine_analysis_FD, " File: %s.\n", file); - fprintf(rule_engine_analysis_FD, " Line: %d.\n", lineno); - fprintf(rule_engine_analysis_FD, "\n"); -} - -/** - * \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_ipv4_only = 0; - uint32_t rule_ipv6_only = 0; - uint32_t rule_flowbits = 0; - uint32_t rule_flowint = 0; - //uint32_t rule_flowvar = 0; - uint32_t rule_content_http = 0; - uint32_t rule_content_offset_depth = 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 http_ua_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; - uint32_t warn_offset_depth_pkt_stream = 0; - uint32_t warn_offset_depth_alproto = 0; - uint32_t warn_non_alproto_fp_for_alproto_sig = 0; - - if (s->init_flags & SIG_FLAG_INIT_BIDIREC) { - rule_bidirectional = 1; - } - - if (s->flags & SIG_FLAG_REQUIRE_PACKET) { - packet_buf += 1; - } - if (s->flags & SIG_FLAG_REQUIRE_STREAM) { - stream_buf += 1; - } - - if (s->proto.flags & DETECT_PROTO_IPV4) { - rule_ipv4_only += 1; - } - if (s->proto.flags & DETECT_PROTO_IPV6) { - rule_ipv6_only += 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_FILEDATA) { - 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 if (list_id == DETECT_SM_LIST_HUADMATCH) { - rule_pcre_http += 1; - norm_http_buf += 1; - http_ua_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; - raw_http_buf += 1; - http_client_body_buf += 1; - } - else if (list_id == DETECT_SM_LIST_FILEDATA) { - rule_content_http += 1; - raw_http_buf += 1; - http_server_body_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; - raw_http_buf += 1; - http_method_buf += 1; - } - else if (list_id == DETECT_SM_LIST_PMATCH) { - rule_content += 1; - DetectContentData *cd = (DetectContentData *)sm->ctx; - if (cd->flags & - (DETECT_CONTENT_OFFSET | DETECT_CONTENT_DEPTH)) { - rule_content_offset_depth++; - } - } - } - 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 & DETECT_FLOW_FLAG_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_content_offset_depth > 0 && stream_buf && packet_buf) { - rule_warning += 1; - warn_offset_depth_pkt_stream = 1; - } - if (rule_content_offset_depth > 0 && !stream_buf && packet_buf && s->alproto != ALPROTO_UNKNOWN) { - rule_warning += 1; - warn_offset_depth_alproto = 1; - } - if (s->mpm_sm != NULL && s->alproto == ALPROTO_HTTP && - SigMatchListSMBelongsTo(s, s->mpm_sm) == DETECT_SM_LIST_PMATCH) { - rule_warning += 1; - warn_non_alproto_fp_for_alproto_sig = 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 (rule_ipv6_only) fprintf(rule_engine_analysis_FD, " Rule is IPv6 only.\n"); - if (rule_ipv4_only) fprintf(rule_engine_analysis_FD, " Rule is IPv4 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 (http_ua_buf) fprintf(rule_engine_analysis_FD, " Rule matches on http user agent buffer.\n"); - if (s->alproto != ALPROTO_UNKNOWN) { - fprintf(rule_engine_analysis_FD, " App layer protocol is %s.\n", AppProtoToString(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); - } - - /* print fast pattern info */ - EngineAnalysisRulesPrintFP(s); - - /* this is where the warnings start */ - 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 (warn_offset_depth_pkt_stream) { - fprintf(rule_engine_analysis_FD, " Warning: Rule has depth" - "/offset with raw content keywords. Please note the " - "offset/depth will be checked against both packet " - "payloads and stream. If you meant to have the offset/" - "depth checked against just the payload, you can update " - "the signature as \"alert tcp-pkt...\"\n"); - } - if (warn_offset_depth_alproto) { - fprintf(rule_engine_analysis_FD, " Warning: Rule has " - "offset/depth set along with a match on a specific " - "app layer protocol - %d. This can lead to FNs if we " - "have a offset/depth content match on a packet payload " - "before we can detect the app layer protocol for the " - "flow.\n", s->alproto); - } - if (warn_non_alproto_fp_for_alproto_sig) { - fprintf(rule_engine_analysis_FD, " Warning: Rule app layer " - "protocol is http, but the fast_pattern is set on the raw " - "stream. Consider adding fast_pattern over a http " - "buffer for increased performance."); - } - if (rule_warning == 0) { - fprintf(rule_engine_analysis_FD, " No warnings for this rule.\n"); - } - fprintf(rule_engine_analysis_FD, "\n"); - } - return; -} |