]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
feature #558.
authorAnoop Saldanha <anoopsaldanha@gmail.com>
Mon, 15 Oct 2012 19:44:47 +0000 (01:14 +0530)
committerVictor Julien <victor@inliniac.net>
Wed, 31 Oct 2012 11:03:28 +0000 (12:03 +0100)
Print FP info in rule analysis + other cleanup.

src/detect-engine-analyzer.c
src/detect-engine-analyzer.h
src/detect-engine-mpm.c
src/detect-engine-mpm.h
src/detect.c

index 60efe1284b5a4555cd828ff78ed1b4ff6cbf280f..bcf548cda407dd9f0f1934f06f632e286b132dc6 100644 (file)
 #include "suricata-common.h"
 #include "suricata.h"
 #include "detect.h"
+#include "detect-parse.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];
 
+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_HSBDMATCH)
+        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");
+
+    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);
+    }
+    fprintf(fp_engine_analysis_FD, "        Content negated: %s\n",
+            (fp_cd->flags & DETECT_CONTENT_NEGATED) ? "yes" : "no");
+
+    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");
+    } else {
+        fprintf(fp_engine_analysis_FD, "        Final content: ");
+        PrintRawUriFp(fp_engine_analysis_FD, pat, patlen);
+        fprintf(fp_engine_analysis_FD, "\n");
+    }
+    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;
+    if (ConfGet("default-log-dir", &log_dir) != 1)
+        log_dir = DEFAULT_LOG_DIR;
+    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-Analyis for fast_pattern printed to file - %s",
+              log_path);
+
+    struct timeval tval;
+    struct tm *tms;
+    gettimeofday(&tval, NULL);
+    struct tm local_tm;
+    tms = (struct tm *)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");
+
+    return 1;
+}
+
 /**
  * \brief Sets up the rule analyzer according to the config
  * \retval 1 if rule analyzer successfully enabled
@@ -66,6 +225,9 @@ int SetupRuleAnalyzer(void)
                 return 0;
             }
 
+            SCLogInfo("Engine-Analyis for rules printed to file - %s",
+                      log_path);
+
             struct timeval tval;
             struct tm *tms;
             gettimeofday(&tval, NULL);
@@ -97,6 +259,17 @@ int SetupRuleAnalyzer(void)
     return 1;
 }
 
+void CleanupFPAnalyzer(void)
+{
+    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);
@@ -156,6 +329,86 @@ int PerCentEncodingMatch (uint8_t *content, uint8_t content_len)
     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_HSBDMATCH)
+        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");
+
+    fprintf(rule_engine_analysis_FD, "\" buffer.\n");
+
+    return;
+}
+
 /**
  * \brief Prints analysis of loaded rules.
  *
@@ -214,6 +467,7 @@ void EngineAnalysisRules(Signature *s, char *line)
     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;
@@ -454,6 +708,11 @@ void EngineAnalysisRules(Signature *s, char *line)
         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);
@@ -481,6 +740,11 @@ void EngineAnalysisRules(Signature *s, char *line)
         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");
@@ -548,6 +812,12 @@ void EngineAnalysisRules(Signature *s, char *line)
                     "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");
         }
index 93e491609a743243b7f77c0c2ec4b9e22748a845..2b1fc54a641e645a17e0b92f64220d7222537f3a 100644 (file)
 
 #include <stdint.h>
 
+int SetupFPAnalyzer(void);
+void CleanupFPAnalyzer(void);
+
 int SetupRuleAnalyzer(void);
 void CleanupRuleAnalyzer (void);
+
 int PerCentEncodingSetup ();
 int PerCentEncodingMatch (uint8_t *content, uint8_t content_len);
+
+void EngineAnalysisFP(Signature *s, char *line);
 void EngineAnalysisRules(Signature *s, char *line);
 
 #endif /* __DETECT_ENGINE_ANALYZER_H__ */
index 139b2b15fd1f826b6b74d11f631611c5164fb9f5..aded0839152af93d68de0c51acc94ef75bc2b017 100644 (file)
@@ -1657,218 +1657,140 @@ static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx,
     return;
 }
 
-/**
- * \internal
- * \brief Setup the mpm content.
- *
- * \param de_ctx Pointer to the detect engine context.
- * \param sgh    Pointer to the signature group head against which we are
- *               adding patterns to the mpm ctx.
- *
- * \retval  0 Always.
- */
-static int PatternMatchPreparePopulateMpm(DetectEngineCtx *de_ctx,
-                                          SigGroupHead *sgh)
+SigMatch *RetrieveFPForSig(Signature *s)
 {
-    uint32_t sig;
-    uint8_t *fast_pattern = NULL;
-    uint8_t *has_non_negated_non_stream_pattern = NULL;
-
-    fast_pattern = (uint8_t *)SCMalloc(sgh->sig_cnt * sizeof(uint8_t));
-    if (fast_pattern == NULL) {
-        SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
-        exit(EXIT_FAILURE);
-    }
-    memset(fast_pattern, 0, sgh->sig_cnt * sizeof(uint8_t));
-    has_non_negated_non_stream_pattern = (uint8_t *)SCMalloc(sgh->sig_cnt * sizeof(uint8_t));
-    if (has_non_negated_non_stream_pattern == NULL) {
-        SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
-        exit(EXIT_FAILURE);
-    }
-    memset(has_non_negated_non_stream_pattern, 0, sgh->sig_cnt * sizeof(uint8_t));
+    SigMatch *mpm_sm = NULL;
+    uint8_t has_non_negated_non_stream_pattern = 0;
 
-    /* add all mpm candidates to a hash */
-    for (sig = 0; sig < sgh->sig_cnt; sig++) {
-        Signature *s = sgh->match_array[sig];
-        if (s == NULL)
-            continue;
+    if (s->mpm_sm != NULL)
+        return s->mpm_sm;
 
-        /* we already have a sm set as fp for this sig.  Add it to the current
-         * mpm context */
-        if (s->mpm_sm != NULL) {
-            PopulateMpmAddPatternToMpm(de_ctx, sgh, s, s->mpm_sm);
+    for (int list_id = 0 ; list_id < DETECT_SM_LIST_MAX; list_id++) {
+        /* we have no keywords that support fp in this Signature sm list */
+        if (!FastPatternSupportEnabledForSigMatchList(list_id))
             continue;
-        }
 
-        int list_id = 0;
-        for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) {
-            /* we have no keywords that support fp in this Signature sm list */
-            if (!FastPatternSupportEnabledForSigMatchList(list_id))
+        for (SigMatch *sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
+            /* this keyword isn't registered for fp support */
+            if (sm->type != DETECT_CONTENT)
                 continue;
 
-            SigMatch *sm = NULL;
-            /* get the total no of patterns in this Signature, as well as find out
-             * if we have a fast_pattern set in this Signature */
-            for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
-                /* this keyword isn't registered for fp support */
-                if (sm->type != DETECT_CONTENT)
-                    continue;
-
-                //if (PopulateMpmSkipContent(sgh, s, sm)) {
-                //    continue;
-                //}
-
-                DetectContentData *cd = (DetectContentData *)sm->ctx;
-                if (!(cd->flags & DETECT_CONTENT_NEGATED) &&
-                    list_id != DETECT_SM_LIST_PMATCH &&
-                    /* don't consider http_method, http_stat_msg, http_stat_code
-                     * to automatically override longest stream match */
-                    list_id != DETECT_SM_LIST_HMDMATCH &&
-                    list_id != DETECT_SM_LIST_HSMDMATCH &&
-                    list_id != DETECT_SM_LIST_HSCDMATCH) {
-                    has_non_negated_non_stream_pattern[sig] = 1;
-                }
-
-                if (cd->flags & DETECT_CONTENT_FAST_PATTERN) {
-                    fast_pattern[sig] = 1;
-                    break;
-                }
-            } /* for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) */
-
-            /* found a fast pattern for the sig.  Let's get outta here */
-            if (fast_pattern[sig])
-                break;
-        } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */
-    } /* for (sig = 0; sig < sgh->sig_cnt; sig++) { */
+            DetectContentData *cd = (DetectContentData *)sm->ctx;
+            if (cd->flags & DETECT_CONTENT_FAST_PATTERN)
+                return sm;
+            if (!(cd->flags & DETECT_CONTENT_NEGATED) &&
+                (list_id != DETECT_SM_LIST_PMATCH) &&
+                (list_id != DETECT_SM_LIST_HMDMATCH) &&
+                (list_id != DETECT_SM_LIST_HSMDMATCH) &&
+                (list_id != DETECT_SM_LIST_HSCDMATCH)) {
+                has_non_negated_non_stream_pattern = 1;
+            }
+        }
+    }
 
-    /* now determine which one to add to the mpm phase */
-    for (sig = 0; sig < sgh->sig_cnt; sig++) {
-        Signature *s = sgh->match_array[sig];
-        if (s == NULL)
+    int max_len = 0;
+    int max_len_negated = 0;
+    int max_len_non_negated = 0;
+    for (int list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
+        if (!FastPatternSupportEnabledForSigMatchList(list_id))
             continue;
-        /* have taken care of this in the previous loop.  move on to the next sig */
-        if (s->mpm_sm != NULL) {
+
+        if (has_non_negated_non_stream_pattern &&
+            ((list_id == DETECT_SM_LIST_PMATCH) ||
+             (list_id == DETECT_SM_LIST_HMDMATCH) ||
+             (list_id == DETECT_SM_LIST_HSMDMATCH) ||
+             (list_id == DETECT_SM_LIST_HSCDMATCH))) {
             continue;
         }
 
-        int max_len = 0;
-        int max_len_negated = 0;
-        int max_len_non_negated = 0;
-        /* get the longest pattern in the sig */
-        if (!fast_pattern[sig]) {
-            SigMatch *sm = NULL;
-            int list_id = 0;
-            for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) {
-                if (!FastPatternSupportEnabledForSigMatchList(list_id))
-                    continue;
+        for (SigMatch *sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
+            if (sm->type != DETECT_CONTENT)
+                continue;
 
-                if (list_id == DETECT_SM_LIST_PMATCH &&
-                    !fast_pattern[sig] &&
-                    has_non_negated_non_stream_pattern[sig]) {
-                    continue;
-                }
+            DetectContentData *cd = (DetectContentData *)sm->ctx;
+            if (cd->flags & DETECT_CONTENT_NEGATED) {
+                if (max_len_negated < cd->content_len)
+                    max_len_negated = cd->content_len;
+            } else {
+                if (max_len_non_negated < cd->content_len)
+                    max_len_non_negated = cd->content_len;
+            }
+        }
+    }
 
-                for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
-                    if (sm->type != DETECT_CONTENT)
-                        continue;
+    int skip_negated_content = 0;
+    if (max_len_non_negated == 0) {
+        max_len = max_len_negated;
+        skip_negated_content = 0;
+    } else {
+        max_len = max_len_non_negated;
+        skip_negated_content = 1;
+    }
 
-                    //if (PopulateMpmSkipContent(sgh, s, sm)) {
-                    //    continue;
-                    //}
+    for (int list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
+        if (!FastPatternSupportEnabledForSigMatchList(list_id))
+            continue;
 
-                    DetectContentData *cd = (DetectContentData *)sm->ctx;
-                    if (cd->flags & DETECT_CONTENT_NEGATED) {
-                        if (max_len_negated < cd->content_len)
-                            max_len_negated = cd->content_len;
-                    } else {
-                        if (max_len_non_negated < cd->content_len)
-                            max_len_non_negated = cd->content_len;
-                    }
-                } /* for ( ; list_id.. */
-            } /* for (sm = s->sm_lists.. */
-        } /* if */
-
-        int skip_negated_content = 0;
-        if (max_len_non_negated == 0) {
-            max_len = max_len_negated;
-            skip_negated_content = 0;
-        } else {
-            max_len = max_len_non_negated;
-            skip_negated_content = 1;
+        if (has_non_negated_non_stream_pattern &&
+            ((list_id == DETECT_SM_LIST_PMATCH) ||
+             (list_id == DETECT_SM_LIST_HMDMATCH) ||
+             (list_id == DETECT_SM_LIST_HSMDMATCH) ||
+             (list_id == DETECT_SM_LIST_HSCDMATCH))) {
+            continue;
         }
 
-        SigMatch *mpm_sm = NULL;
-        SigMatch *sm = NULL;
-        int list_id = 0;
-        for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) {
-            if (!FastPatternSupportEnabledForSigMatchList(list_id))
+        for (SigMatch *sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
+            if (sm->type != DETECT_CONTENT)
                 continue;
 
-            if (list_id == DETECT_SM_LIST_PMATCH &&
-                !fast_pattern[sig] &&
-                has_non_negated_non_stream_pattern[sig]) {
+            DetectContentData *cd = (DetectContentData *)sm->ctx;
+            if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
+                continue;
+            if (cd->content_len < max_len)
                 continue;
-            }
-
-            for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
-                if (sm->type != DETECT_CONTENT)
-                    continue;
-
-                /* skip in case of:
-                 * 1. we expect a fastpattern but this isn't it */
-                if (fast_pattern[sig]) {
-                    /* can be any content based keyword since all of them
-                     * now use a unified structure - DetectContentData */
-                    DetectContentData *cd = (DetectContentData *)sm->ctx;
-                    if (!(cd->flags & DETECT_CONTENT_FAST_PATTERN)) {
-                        SCLogDebug("not a fast pattern %"PRIu32"", cd->id);
-                        continue;
-                    }
-                    SCLogDebug("fast pattern %"PRIu32"", cd->id);
-                } else {
-                    //if (PopulateMpmSkipContent(sgh, s, sm)) {
-                    //    continue;
-                    //}
-
-                    DetectContentData *cd = (DetectContentData *)sm->ctx;
-                    if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
-                        continue;
-                    if (cd->content_len < max_len)
-                        continue;
-
-                } /* else - if (fast_pattern[sig] == 1) */
 
-                if (mpm_sm == NULL) {
+            if (mpm_sm == NULL) {
+                mpm_sm = sm;
+            } else {
+                DetectContentData *data1 = (DetectContentData *)sm->ctx;
+                DetectContentData *data2 = (DetectContentData *)mpm_sm->ctx;
+                uint32_t ls = PatternStrength(data1->content, data1->content_len);
+                uint32_t ss = PatternStrength(data2->content, data2->content_len);
+                if (ls > ss) {
                     mpm_sm = sm;
-                    if (fast_pattern[sig])
-                        break;
-                } else {
-                    DetectContentData *data1 = (DetectContentData *)sm->ctx;
-                    DetectContentData *data2 = (DetectContentData *)mpm_sm->ctx;
-                    uint32_t ls = PatternStrength(data1->content, data1->content_len);
-                    uint32_t ss = PatternStrength(data2->content, data2->content_len);
-                    if (ls > ss) {
+                } else if (ls == ss) {
+                    /* if 2 patterns are of equal strength, we pick the longest */
+                    if (data1->content_len > data2->content_len)
                         mpm_sm = sm;
-                    } else if (ls == ss) {
-                        /* if 2 patterns are of equal strength, we pick the longest */
-                        if (data1->content_len > data2->content_len)
-                            mpm_sm = sm;
-                    } else {
-                        SCLogDebug("sticking with mpm_sm");
-                    }
-                } /* else - if (mpm == NULL) */
-            } /* for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) */
-            if (mpm_sm != NULL && fast_pattern[sig])
-                break;
-        } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */
+                } else {
+                    SCLogDebug("sticking with mpm_sm");
+                }
+            } /* else - if (mpm == NULL) */
+        } /* for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) */
+    } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */
 
-        PopulateMpmAddPatternToMpm(de_ctx, sgh, s, mpm_sm);
-    } /* for (sig = 0; sig < sgh->sig_cnt; sig++) */
+    return mpm_sm;
+}
 
-    if (fast_pattern != NULL)
-        SCFree(fast_pattern);
-    if (has_non_negated_non_stream_pattern != NULL)
-        SCFree(has_non_negated_non_stream_pattern);
+/**
+ * \internal
+ * \brief Setup the mpm content.
+ *
+ * \param de_ctx Pointer to the detect engine context.
+ * \param sgh    Pointer to the signature group head against which we are
+ *               adding patterns to the mpm ctx.
+ *
+ * \retval  0 Always.
+ */
+static int PatternMatchPreparePopulateMpm(DetectEngineCtx *de_ctx,
+                                          SigGroupHead *sgh)
+{
+    for (uint32_t sig = 0; sig < sgh->sig_cnt; sig++) {
+        Signature *s = sgh->match_array[sig];
+        if (s == NULL)
+            continue;
+        PopulateMpmAddPatternToMpm(de_ctx, sgh, s, RetrieveFPForSig(s));
+    } /* for (sig = 0; sig < sgh->sig_cnt; sig++) */
 
     return 0;
 }
index d89b510a012aa39505acc399008aa54205657343..3033ab2a1dc88361c3abcaf8973d5500da091dd3 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "tm-threads.h"
 
+#include "detect.h"
 #include "detect-content.h"
 #include "detect-uricontent.h"
 
@@ -78,5 +79,7 @@ uint32_t DetectPatternGetId(MpmPatternIdStore *, void *, uint8_t);
 int SignatureHasPacketContent(Signature *);
 int SignatureHasStreamContent(Signature *);
 
+SigMatch *RetrieveFPForSig(Signature *s);
+
 #endif /* __DETECT_ENGINE_MPM_H__ */
 
index 8fbbafa77bf311079b9e2b9069e448753744cd9a..dab006c030475308aed326638d7e9cd7f0b78536 100644 (file)
@@ -194,7 +194,6 @@ extern int rule_reload;
 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);
 void DetectExitPrintStats(ThreadVars *tv, void *data);
@@ -268,236 +267,6 @@ char *DetectLoadCompleteSigPath(char *sig_file)
     return path;
 }
 
-static inline void EngineAnalysisWriteFastPattern(Signature *s, SigMatch *mpm_sm)
-{
-    int fast_pattern_set = 0;
-    int fast_pattern_only_set = 0;
-    int fast_pattern_chop_set = 0;
-    DetectContentData *fp_cd = NULL;
-
-    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;
-            }
-        }
-    }
-
-    if (fp_cd == NULL) {
-        fprintf(fp_engine_analysis_FD, "== Sid: %u ==\n", s->id);
-        fprintf(fp_engine_analysis_FD, "    No content present\n");
-        return;
-    }
-
-    fprintf(fp_engine_analysis_FD, "== Sid: %u ==\n", s->id);
-    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_HSBDMATCH)
-        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");
-
-    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);
-    }
-    fprintf(fp_engine_analysis_FD, "    Content negated: %s\n",
-            (fp_cd->flags & DETECT_CONTENT_NEGATED) ? "yes" : "no");
-
-    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");
-    } else {
-        fprintf(fp_engine_analysis_FD, "    Final content: ");
-        PrintRawUriFp(fp_engine_analysis_FD, pat, patlen);
-        fprintf(fp_engine_analysis_FD, "\n");
-    }
-    SCFree(pat);
-
-    return;
-}
-
-/**
- * \brief Prints analysis of fast pattern for a signature.
- *
- *        The code here mimics the logic to select fast_pattern from staging.
- *        If any changes are made to the staging logic, this should follow suit.
- *
- * \param s Pointer to the signature.
- */
-void EngineAnalysisFastPattern(Signature *s)
-{
-    SigMatch *mpm_sm = NULL;
-    uint32_t fast_pattern = 0;
-    int list_id = 0;
-
-    for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
-        /* we have no keywords that support fp in this Signature sm list */
-        if (!FastPatternSupportEnabledForSigMatchList(list_id))
-            continue;
-
-        SigMatch *sm = NULL;
-        /* get the total no of patterns in this Signature, as well as find out
-         * if we have a fast_pattern set in this Signature */
-        for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
-            /* this keyword isn't registered for fp support */
-            if (sm->type != DETECT_CONTENT)
-                continue;
-
-            DetectContentData *cd = (DetectContentData *)sm->ctx;
-            if (cd->flags & DETECT_CONTENT_FAST_PATTERN) {
-                fast_pattern = 1;
-                break;
-            }
-        } /* for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) */
-
-        /* found a fast pattern for the sig.  Let's get outta here */
-        if (fast_pattern)
-            break;
-    } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */
-
-    int max_len = 0;
-    int max_len_negated = 0;
-    int max_len_non_negated = 0;
-    /* get the longest pattern in the sig */
-    if (!fast_pattern) {
-        SigMatch *sm = NULL;
-        for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
-            if (!FastPatternSupportEnabledForSigMatchList(list_id))
-                continue;
-
-            for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
-                if (sm->type != DETECT_CONTENT)
-                    continue;
-
-                DetectContentData *cd = (DetectContentData *)sm->ctx;
-                if (cd->flags & DETECT_CONTENT_NEGATED) {
-                    if (max_len_negated < cd->content_len)
-                        max_len_negated = cd->content_len;
-                } else {
-                    if (max_len_non_negated < cd->content_len)
-                        max_len_non_negated = cd->content_len;
-                }
-            }
-        }
-    }
-
-    int skip_negated_content = 0;
-    if (max_len_non_negated == 0) {
-        max_len = max_len_negated;
-        skip_negated_content = 0;
-    } else {
-        max_len = max_len_non_negated;
-        skip_negated_content = 1;
-    }
-
-    SigMatch *sm = NULL;
-    for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
-        if (!FastPatternSupportEnabledForSigMatchList(list_id))
-            continue;
-
-        for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
-            if (sm->type != DETECT_CONTENT)
-                continue;
-
-            /* skip in case of:
-             * 1. we expect a fastpattern but this isn't it */
-            if (fast_pattern) {
-                /* can be any content based keyword since all of them
-                 * now use a unified structure - DetectContentData */
-                DetectContentData *cd = (DetectContentData *)sm->ctx;
-                if (!(cd->flags & DETECT_CONTENT_FAST_PATTERN)) {
-                    SCLogDebug("not a fast pattern %"PRIu32"", cd->id);
-                    continue;
-                }
-                SCLogDebug("fast pattern %"PRIu32"", cd->id);
-            } else {
-                DetectContentData *cd = (DetectContentData *)sm->ctx;
-                if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
-                    continue;
-                if (cd->content_len < max_len)
-                    continue;
-
-            } /* else - if (fast_pattern[sig] == 1) */
-
-            if (mpm_sm == NULL) {
-                mpm_sm = sm;
-                if (fast_pattern)
-                    break;
-            } else {
-                DetectContentData *data1 = (DetectContentData *)sm->ctx;
-                DetectContentData *data2 = (DetectContentData *)mpm_sm->ctx;
-                uint32_t ls = PatternStrength(data1->content, data1->content_len);
-                uint32_t ss = PatternStrength(data2->content, data2->content_len);
-                if (ls > ss) {
-                    mpm_sm = sm;
-                } else if (ls == ss) {
-                    /* if 2 patterns are of equal strength, we pick the longest */
-                    if (data1->content_len > data2->content_len)
-                        mpm_sm = sm;
-                } else {
-                    SCLogDebug("sticking with mpm_sm");
-                }
-            } /* else - if (mpm == NULL) */
-        } /* for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) */
-        if (mpm_sm != NULL && fast_pattern)
-            break;
-    } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */
-
-    /* output result to file */
-    EngineAnalysisWriteFastPattern(s, mpm_sm);
-
-    return;
-}
-
 /**
  *  \brief Load a file with signatures
  *  \param de_ctx Pointer to the detection engine context
@@ -560,11 +329,14 @@ int DetectLoadSigFile(DetectEngineCtx *de_ctx, char *sig_file, int *sigs_tot) {
         sig = DetectEngineAppendSig(de_ctx, line);
         (*sigs_tot)++;
         if (sig != NULL) {
-            if (fp_engine_analysis_set) {
-                EngineAnalysisFastPattern(sig);
-            }
-            if (rule_engine_analysis_set) {
-                EngineAnalysisRules(sig, line);
+            if (rule_engine_analysis_set || fp_engine_analysis_set) {
+                sig->mpm_sm = RetrieveFPForSig(sig);
+                if (fp_engine_analysis_set) {
+                    EngineAnalysisFP(sig, line);
+                }
+                if (rule_engine_analysis_set) {
+                    EngineAnalysisRules(sig, line);
+                }
             }
             SCLogDebug("signature %"PRIu32" loaded", sig->id);
             good++;
@@ -603,46 +375,8 @@ int SigLoadSignatures(DetectEngineCtx *de_ctx, char *sig_file, int sig_file_excl
     int sigtotal = 0;
     char *sfile = NULL;
 
-    /* needed by engine_analysis */
-    char log_path[PATH_MAX];
-
     if (engine_analysis) {
-        if ((ConfGetBool("engine-analysis.rules-fast-pattern",
-                         &fp_engine_analysis_set)) == 0) {
-            SCLogInfo("Conf parameter \"engine-analysis.rules-fast-pattern\" not "
-                      "found.  Defaulting to not printing the fast_pattern "
-                      "report.");
-            fp_engine_analysis_set = 0;
-        }
-        if (fp_engine_analysis_set) {
-            char *log_dir;
-            if (ConfGet("default-log-dir", &log_dir) != 1)
-                log_dir = DEFAULT_LOG_DIR;
-            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 -1;
-            }
-            struct timeval tval;
-            struct tm *tms;
-            gettimeofday(&tval, NULL);
-            struct tm local_tm;
-            tms = (struct tm *)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");
-        }
-        else {
-            SCLogInfo("Engine-Analysis for fast_pattern disabled in conf file.");
-        }
+        fp_engine_analysis_set = SetupFPAnalyzer();
         rule_engine_analysis_set = SetupRuleAnalyzer();
     }
 
@@ -734,17 +468,12 @@ int SigLoadSignatures(DetectEngineCtx *de_ctx, char *sig_file, int sig_file_excl
 
  end:
     if (engine_analysis) {
-        if (fp_engine_analysis_set) {
-            if (fp_engine_analysis_FD != NULL) {
-                SCLogInfo("Engine-Analyis for fast_pattern printed to file - %s",
-                          log_path);
-                fclose(fp_engine_analysis_FD);
-                fp_engine_analysis_FD = NULL;
-            }
-        }
         if (rule_engine_analysis_set) {
             CleanupRuleAnalyzer();
         }
+        if (fp_engine_analysis_set) {
+            CleanupFPAnalyzer();
+        }
     }
 
     DetectParseDupSigHashFree(de_ctx);