]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
SNMP: add logger
authorPierre Chifflier <chifflier@wzdftpd.net>
Mon, 8 Oct 2018 08:36:39 +0000 (10:36 +0200)
committerPierre Chifflier <chifflier@wzdftpd.net>
Thu, 6 Jun 2019 08:15:59 +0000 (10:15 +0200)
rust/src/snmp/log.rs [new file with mode: 0644]
rust/src/snmp/mod.rs
src/Makefile.am
src/output-json-snmp.c [new file with mode: 0644]
src/output-json-snmp.h [new file with mode: 0644]
src/output.c
src/suricata-common.h
suricata.yaml.in

diff --git a/rust/src/snmp/log.rs b/rust/src/snmp/log.rs
new file mode 100644 (file)
index 0000000..9658161
--- /dev/null
@@ -0,0 +1,68 @@
+/* Copyright (C) 2018-2019 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.
+ */
+
+// written by Pierre Chifflier  <chifflier@wzdftpd.net>
+
+use json::*;
+use snmp::snmp::{SNMPState,SNMPTransaction};
+use snmp::snmp_parser::NetworkAddress;
+
+#[no_mangle]
+pub extern "C" fn rs_snmp_log_json_response(state: &mut SNMPState, tx: &mut SNMPTransaction) -> *mut JsonT
+{
+    let js = Json::object();
+    js.set_integer("version", state.version as u64);
+    if tx.encrypted {
+        js.set_string("pdu_type", "encrypted");
+    } else {
+        match tx.info {
+            Some(ref info) => {
+                js.set_string("pdu_type", &format!("{:?}", info.pdu_type));
+                if info.err.0 != 0 {
+                    js.set_string("error", &format!("{:?}", info.err));
+                }
+                match &info.trap_type {
+                    Some((trap_type, oid, address)) => {
+                        js.set_string("trap_type", &format!("{:?}", trap_type));
+                        js.set_string("trap_oid", &oid.to_string());
+                        match address {
+                            NetworkAddress::IPv4(ip) => js.set_string("trap_address", &ip.to_string())
+                        }
+                    },
+                    _ => ()
+                }
+                if info.vars.len() > 0 {
+                    let jsa = Json::array();
+                    for var in info.vars.iter() {
+                        jsa.array_append_string(&var.to_string());
+                    }
+                    js.set("vars", jsa);
+                }
+            },
+            _ => ()
+        }
+        match tx.community {
+            Some(ref c) => js.set_string("community", c),
+            _           => ()
+        }
+        match tx.usm {
+            Some(ref s) => js.set_string("usm", s),
+            _           => ()
+        }
+    }
+    js.unwrap()
+}
index 17a026ac4b5bc2a5aef8124480e0c12a6995b541..c3ccbbcb392a7468eb06adf8da10dbfdaf0be68d 100644 (file)
@@ -20,3 +20,4 @@
 extern crate snmp_parser;
 
 pub mod snmp;
+pub mod log;
index 9f0f489aacf7421f9f29390524aa644e672182f7..c80b71f229f44f74b189717ecab18b3208c4242d 100644 (file)
@@ -323,6 +323,7 @@ output-json-smb.c output-json-smb.h \
 output-json-ikev2.c output-json-ikev2.h \
 output-json-krb5.c output-json-krb5.h \
 output-json-dhcp.c output-json-dhcp.h \
+output-json-snmp.c output-json-snmp.h \
 output-json-template.c output-json-template.h \
 output-json-template-rust.c output-json-template-rust.h \
 output-json-metadata.c output-json-metadata.h \
diff --git a/src/output-json-snmp.c b/src/output-json-snmp.c
new file mode 100644 (file)
index 0000000..3803512
--- /dev/null
@@ -0,0 +1,198 @@
+/* Copyright (C) 2018-2019 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 Pierre Chifflier <chifflier@wzdftpd.net>
+ *
+ * Implement JSON/eve logging app-layer SNMP.
+ */
+
+#include "suricata-common.h"
+#include "debug.h"
+#include "detect.h"
+#include "pkt-var.h"
+#include "conf.h"
+
+#include "threads.h"
+#include "threadvars.h"
+#include "tm-threads.h"
+
+#include "util-unittest.h"
+#include "util-buffer.h"
+#include "util-debug.h"
+#include "util-byte.h"
+
+#include "output.h"
+#include "output-json.h"
+
+#include "app-layer.h"
+#include "app-layer-parser.h"
+
+#include "app-layer-snmp.h"
+#include "output-json-snmp.h"
+
+#ifdef HAVE_RUST
+#ifdef HAVE_LIBJANSSON
+
+#include "rust.h"
+#include "rust-snmp-log-gen.h"
+
+typedef struct LogSNMPFileCtx_ {
+    LogFileCtx *file_ctx;
+    OutputJsonCommonSettings cfg;
+} LogSNMPFileCtx;
+
+typedef struct LogSNMPLogThread_ {
+    LogSNMPFileCtx *snmplog_ctx;
+    MemBuffer          *buffer;
+} LogSNMPLogThread;
+
+static int JsonSNMPLogger(ThreadVars *tv, void *thread_data,
+    const Packet *p, Flow *f, void *state, void *tx, uint64_t tx_id)
+{
+    SNMPTransaction *snmptx = tx;
+    LogSNMPLogThread *thread = thread_data;
+    json_t *js, *snmpjs;
+
+    js = CreateJSONHeader(p, LOG_DIR_PACKET, "snmp");
+    if (unlikely(js == NULL)) {
+        return TM_ECODE_FAILED;
+    }
+
+    JsonAddCommonOptions(&thread->snmplog_ctx->cfg, p, f, js);
+
+    snmpjs = rs_snmp_log_json_response(state, snmptx);
+    if (unlikely(snmpjs == NULL)) {
+        goto error;
+    }
+    json_object_set_new(js, "snmp", snmpjs);
+
+    MemBufferReset(thread->buffer);
+    OutputJSONBuffer(js, thread->snmplog_ctx->file_ctx, &thread->buffer);
+
+    json_decref(js);
+    return TM_ECODE_OK;
+
+error:
+    json_decref(js);
+    return TM_ECODE_FAILED;
+}
+
+static void OutputSNMPLogDeInitCtxSub(OutputCtx *output_ctx)
+{
+    LogSNMPFileCtx *snmplog_ctx = (LogSNMPFileCtx *)output_ctx->data;
+    SCFree(snmplog_ctx);
+    SCFree(output_ctx);
+}
+
+static OutputInitResult OutputSNMPLogInitSub(ConfNode *conf,
+    OutputCtx *parent_ctx)
+{
+    OutputInitResult result = { NULL, false };
+    OutputJsonCtx *ajt = parent_ctx->data;
+
+    LogSNMPFileCtx *snmplog_ctx = SCCalloc(1, sizeof(*snmplog_ctx));
+    if (unlikely(snmplog_ctx == NULL)) {
+        return result;
+    }
+    snmplog_ctx->file_ctx = ajt->file_ctx;
+    snmplog_ctx->cfg = ajt->cfg;
+
+    OutputCtx *output_ctx = SCCalloc(1, sizeof(*output_ctx));
+    if (unlikely(output_ctx == NULL)) {
+        SCFree(snmplog_ctx);
+        return result;
+    }
+    output_ctx->data = snmplog_ctx;
+    output_ctx->DeInit = OutputSNMPLogDeInitCtxSub;
+
+    SCLogDebug("SNMP log sub-module initialized.");
+
+    AppLayerParserRegisterLogger(IPPROTO_UDP, ALPROTO_SNMP);
+
+    result.ctx = output_ctx;
+    result.ok = true;
+    return result;
+}
+
+#define OUTPUT_BUFFER_SIZE 65535
+
+static TmEcode JsonSNMPLogThreadInit(ThreadVars *t, const void *initdata, void **data)
+{
+    LogSNMPLogThread *thread = SCCalloc(1, sizeof(*thread));
+    if (unlikely(thread == NULL)) {
+        return TM_ECODE_FAILED;
+    }
+
+    if (initdata == NULL) {
+        SCLogDebug("Error getting context for EveLogSNMP.  \"initdata\" is NULL.");
+        SCFree(thread);
+        return TM_ECODE_FAILED;
+    }
+
+    thread->buffer = MemBufferCreateNew(OUTPUT_BUFFER_SIZE);
+    if (unlikely(thread->buffer == NULL)) {
+        SCFree(thread);
+        return TM_ECODE_FAILED;
+    }
+
+    thread->snmplog_ctx = ((OutputCtx *)initdata)->data;
+    *data = (void *)thread;
+
+    return TM_ECODE_OK;
+}
+
+static TmEcode JsonSNMPLogThreadDeinit(ThreadVars *t, void *data)
+{
+    LogSNMPLogThread *thread = (LogSNMPLogThread *)data;
+    if (thread == NULL) {
+        return TM_ECODE_OK;
+    }
+    if (thread->buffer != NULL) {
+        MemBufferFree(thread->buffer);
+    }
+    SCFree(thread);
+    return TM_ECODE_OK;
+}
+
+void JsonSNMPLogRegister(void)
+{
+    /* Register as an eve sub-module. */
+    OutputRegisterTxSubModule(LOGGER_JSON_SNMP, "eve-log", "JsonSNMPLog",
+        "eve-log.snmp", OutputSNMPLogInitSub, ALPROTO_SNMP,
+        JsonSNMPLogger, JsonSNMPLogThreadInit,
+        JsonSNMPLogThreadDeinit, NULL);
+
+    SCLogDebug("SNMP JSON logger registered.");
+}
+
+#else /* No JSON support. */
+
+void JsonSNMPLogRegister(void)
+{
+}
+
+#endif /* HAVE_LIBJANSSON */
+#else /* No rust support. */
+
+void JsonSNMPLogRegister(void)
+{
+}
+
+#endif /* HAVE_RUST */
diff --git a/src/output-json-snmp.h b/src/output-json-snmp.h
new file mode 100644 (file)
index 0000000..4c88db3
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (C) 2015-2019 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 Pierre Chifflier <chifflier@wzdftpd.net>
+ */
+
+#ifndef __OUTPUT_JSON_SNMP_H__
+#define __OUTPUT_JSON_SNMP_H__
+
+void JsonSNMPLogRegister(void);
+
+#endif /* __OUTPUT_JSON_SNMP_H__ */
index 576183b35c6b5a22e78fe970ce2a8d6826274088..154319ac10ef679818cbc392d546898e20732baa 100644 (file)
@@ -73,6 +73,7 @@
 #include "output-json-ikev2.h"
 #include "output-json-krb5.h"
 #include "output-json-dhcp.h"
+#include "output-json-snmp.h"
 #include "output-json-template.h"
 #include "output-json-template-rust.h"
 #include "output-lua.h"
@@ -1103,6 +1104,8 @@ void OutputRegisterLoggers(void)
     JsonKRB5LogRegister();
     /* DHCP JSON logger. */
     JsonDHCPLogRegister();
+    /* SNMP JSON logger. */
+    JsonSNMPLogRegister();
     /* Template JSON logger. */
     JsonTemplateLogRegister();
     /* Template Rust JSON logger. */
index 788e6037c2468c075b2ff35dfdb0c4e1c3dc01c3..dc05e19d0ae7267857da8ec0c135de574fb7a352 100644 (file)
@@ -438,6 +438,7 @@ typedef enum {
     LOGGER_JSON_IKEV2,
     LOGGER_JSON_KRB5,
     LOGGER_JSON_DHCP,
+    LOGGER_JSON_SNMP,
     LOGGER_JSON_TEMPLATE_RUST,
     LOGGER_JSON_TEMPLATE,
 
index b4f2d91c38c0374837d8bbe40c44fa223f8bae12..f88d73ae9c1e1ba32b4eda6a14794088a73dbecd 100644 (file)
@@ -236,6 +236,7 @@ outputs:
         - tftp
         - ikev2
         - krb5
+        - snmp
         - dhcp:
             enabled: yes
             # When extended mode is on, all DHCP messages are logged