]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rule analyzer: simple rules to json dumper
authorVictor Julien <victor@inliniac.net>
Fri, 3 Nov 2017 11:33:53 +0000 (12:33 +0100)
committerVictor Julien <victor@inliniac.net>
Wed, 14 Feb 2018 13:25:46 +0000 (14:25 +0100)
src/detect-engine-analyzer.c
src/detect-engine-analyzer.h
src/detect-engine-build.c

index a03c14d6958f1799c329f7c5f2a7a71be5e508c7..5bcf15f6b837e1fd84b3c1b597b4ce274c7f62bd 100644 (file)
@@ -470,6 +470,147 @@ void EngineAnalysisRulesFailure(char *line, char *file, int lineno)
     fprintf(rule_engine_analysis_FD, "\n");
 }
 
+#ifdef HAVE_LIBJANSSON
+#include "util-buffer.h"
+#include "output-json.h"
+
+SCMutex g_rules_analyzer_write_m = SCMUTEX_INITIALIZER;
+void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
+{
+    json_t *js = json_object();
+    if (js == NULL)
+        return;
+
+    json_object_set_new(js, "raw", json_string(s->sig_str));
+    json_object_set_new(js, "id", json_integer(s->id));
+    json_object_set_new(js, "gid", json_integer(s->gid));
+    json_object_set_new(js, "rev", json_integer(s->rev));
+    json_object_set_new(js, "msg", json_string(s->msg));
+
+    const char *alproto = AppProtoToString(s->alproto);
+    json_object_set_new(js, "app_proto", json_string(alproto));
+
+    if (s->flags & SIG_FLAG_STATE_MATCH) {
+        json_t *js_array = json_array();
+        const DetectEngineAppInspectionEngine *app = s->app_inspect;
+        for ( ; app != NULL; app = app->next) {
+            const char *name = DetectBufferTypeGetNameById(de_ctx, app->sm_list);
+            if (name == NULL) {
+                switch (app->sm_list) {
+                    case DETECT_SM_LIST_PMATCH:
+                        name = "stream";
+                        break;
+                    default:
+                        break;
+                }
+            }
+            json_t *js_engine = json_object();
+            if (js_engine != NULL) {
+                json_object_set_new(js_engine, "name", json_string(name));
+
+                const char *direction = app->dir == 0 ? "toserver" : "toclient";
+                json_object_set_new(js_engine, "direction", json_string(direction));
+                json_object_set_new(js_engine, "is_mpm", json_boolean(app->mpm));
+
+                json_t *js_matches = json_array();
+                if (js_matches != NULL) {
+                    const SigMatchData *smd = app->smd;
+                    do {
+                        json_t *js_match = json_object();
+                        if (js_match != NULL) {
+                            const char *mname = sigmatch_table[smd->type].name;
+                            json_object_set_new(js_match, "name", json_string(mname));
+
+                            switch (smd->type) {
+                                case DETECT_CONTENT: {
+                                    const DetectContentData *cd = (const DetectContentData *)smd->ctx;
+                                    uint8_t *pat = SCMalloc(cd->content_len + 1);
+                                    if (unlikely(pat == NULL)) {
+                                        SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
+                                        exit(EXIT_FAILURE);
+                                    }
+                                    memcpy(pat, cd->content, cd->content_len);
+                                    pat[cd->content_len] = '\0';
+
+                                    json_t *js_match_content = json_object();
+                                    if (js_match_content != NULL) {
+                                        json_object_set_new(js_match_content, "pattern", json_string((const char *)pat));
+                                        json_object_set_new(js_match_content, "nocase", json_boolean(cd->flags & DETECT_CONTENT_NOCASE));
+                                        json_object_set_new(js_match_content, "negated", json_boolean(cd->flags & DETECT_CONTENT_NEGATED));
+                                        json_object_set_new(js_match_content, "starts_with", json_boolean(cd->flags & DETECT_CONTENT_STARTS_WITH));
+                                        json_object_set_new(js_match_content, "ends_with", json_boolean(cd->flags & DETECT_CONTENT_ENDS_WITH));
+                                        if (cd->flags & DETECT_CONTENT_OFFSET) {
+                                            json_object_set_new(js_match_content, "offset", json_integer(cd->offset));
+                                        }
+                                        if (cd->flags & DETECT_CONTENT_DEPTH) {
+                                            json_object_set_new(js_match_content, "depth", json_integer(cd->depth));
+                                        }
+                                        if (cd->flags & DETECT_CONTENT_DISTANCE) {
+                                            json_object_set_new(js_match_content, "distance", json_integer(cd->distance));
+                                        }
+                                        if (cd->flags & DETECT_CONTENT_WITHIN) {
+                                            json_object_set_new(js_match_content, "within", json_integer(cd->within));
+                                        }
+
+                                        json_object_set_new(js_match, "content", js_match_content);
+                                    }
+                                    SCFree(pat);
+                                    break;
+                                }
+                            }
+                        }
+                        json_array_append_new(js_matches, js_match);
+
+                        if (smd->is_last)
+                            break;
+                        smd++;
+                    } while (1);
+                    json_object_set_new(js_engine, "matches", js_matches);
+                }
+
+                json_array_append_new(js_array, js_engine);
+            }
+        }
+        json_object_set_new(js, "engines", js_array);
+    }
+
+    const char *filename = "rules.json";
+    const char *log_dir = ConfigGetLogDirectory();
+    char json_path[PATH_MAX] = "";
+    snprintf(json_path, sizeof(json_path), "%s/%s", log_dir, filename);
+
+    MemBuffer *mbuf = NULL;
+    mbuf = MemBufferCreateNew(4096);
+    BUG_ON(mbuf == NULL);
+
+    OutputJSONMemBufferWrapper wrapper = {
+        .buffer = &mbuf,
+        .expand_by = 4096,
+    };
+
+    int r = json_dump_callback(js, OutputJSONMemBufferCallback, &wrapper,
+            JSON_PRESERVE_ORDER|JSON_COMPACT|JSON_ENSURE_ASCII|
+            JSON_ESCAPE_SLASH);
+    if (r != 0) {
+        SCLogWarning(SC_ERR_SOCKET, "unable to serialize JSON object");
+    } else {
+        MemBufferWriteString(mbuf, "\n");
+        SCMutexLock(&g_rules_analyzer_write_m);
+        FILE *fp = fopen(json_path, "a");
+        if (fp != NULL) {
+            MemBufferPrintToFPAsString(mbuf, fp);
+            fclose(fp);
+        }
+        SCMutexUnlock(&g_rules_analyzer_write_m);
+    }
+
+    MemBufferFree(mbuf);
+    json_object_clear(js);
+    json_decref(js);
+    return;
+}
+#endif /* HAVE_LIBJANSSON */
+
 /**
  * \brief Prints analysis of loaded rules.
  *
index 87143e0f48b01b10fdc8c58e8ef6da3ab854b681..c72815d41c9c8e49a27edddb5875e25187c7267d 100644 (file)
@@ -41,4 +41,8 @@ void EngineAnalysisRules(const DetectEngineCtx *de_ctx,
         const Signature *s, const char *line);
 void EngineAnalysisRulesFailure(char *line, char *file, int lineno);
 
+#ifdef HAVE_LIBJANSSON
+void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s);
+#endif
+
 #endif /* __DETECT_ENGINE_ANALYZER_H__ */
index 681ce4d9a190e8bb2b4209b937f373d80851a289..69da24498894ba7984f19d06d71baef111b9f0b1 100644 (file)
@@ -21,6 +21,7 @@
 #include "detect-parse.h"
 
 #include "detect-engine-address.h"
+#include "detect-engine-analyzer.h"
 #include "detect-engine-iponly.h"
 #include "detect-engine-mpm.h"
 #include "detect-engine-siggroup.h"
@@ -1819,7 +1820,9 @@ static int SigMatchPrepare(DetectEngineCtx *de_ctx)
             SigMatch *sm = s->init_data->smlists[type];
             s->sm_arrays[type] = SigMatchList2DataArray(sm);
         }
-
+#ifdef HAVE_LIBJANSSON
+        EngineAnalysisRules2(de_ctx, s);
+#endif
         /* free lists. Ctx' are xferred to sm_arrays so won't get freed */
         uint32_t i;
         for (i = 0; i < s->init_data->smlists_array_size; i++) {