]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
output/syslog: Convert syslog eve output to plugin
authorJeff Lucovsky <jeff@lucovsky.org>
Sat, 15 May 2021 14:08:33 +0000 (10:08 -0400)
committerVictor Julien <victor@inliniac.net>
Mon, 20 Sep 2021 15:31:15 +0000 (17:31 +0200)
This commit converts the "built-in" syslog eve output handler into an
internal plugin.

output-eve-syslog.c [new file with mode: 0644]
src/Makefile.am
src/output-eve-syslog.c [new file with mode: 0644]
src/output-eve-syslog.h [new file with mode: 0644]
src/util-logopenfile.c
src/util-logopenfile.h
src/util-plugin.c
src/util-plugin.h

diff --git a/output-eve-syslog.c b/output-eve-syslog.c
new file mode 100644 (file)
index 0000000..4c06f8d
--- /dev/null
@@ -0,0 +1,114 @@
+/* vi: set et ts=4: */
+/* Copyright (C) 2021 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 Mike Pomraning <mpomraning@qualys.com>
+ * \author Jeff Lucovsky <jeff@lucovsky.org>
+ *
+ * File-like output for logging:  syslog
+ */
+
+#ifndef OS_WIN32
+#include "suricata-plugin.h" /* errno.h, string.h, etc. */
+#include "conf.h"            /* ConfNode, etc. */
+#include "output.h"          /* DEFAULT_LOG_* */
+#include "output-eve-syslog.h"
+#include "util-syslog.h"
+
+#define DEFAULT_ALERT_SYSLOG_FACILITY_STR "local0"
+#define DEFAULT_ALERT_SYSLOG_FACILITY     LOG_LOCAL0
+#define DEFAULT_ALERT_SYSLOG_LEVEL        LOG_INFO
+
+#define OUTPUT_NAME "syslog"
+
+typedef struct Context_ {
+    int alert_syslog_level;
+} Context;
+
+static int SyslogInit(ConfNode *conf, bool threaded, void **init_data)
+{
+    Context *context = SCCalloc(1, sizeof(Context));
+    if (context == NULL) {
+        SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate context for %s", OUTPUT_NAME);
+        return -1;
+    }
+    const char *facility_s = ConfNodeLookupChildValue(conf, "facility");
+    if (facility_s == NULL) {
+        facility_s = DEFAULT_ALERT_SYSLOG_FACILITY_STR;
+    }
+
+    int facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap());
+    if (facility == -1) {
+        SCLogWarning(SC_ERR_INVALID_ARGUMENT,
+                "Invalid syslog facility: \"%s\","
+                " now using \"%s\" as syslog facility",
+                facility_s, DEFAULT_ALERT_SYSLOG_FACILITY_STR);
+        facility = DEFAULT_ALERT_SYSLOG_FACILITY;
+    }
+
+    const char *level_s = ConfNodeLookupChildValue(conf, "level");
+    if (level_s != NULL) {
+        int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap());
+        if (level != -1) {
+            context->alert_syslog_level = level;
+        }
+    }
+
+    const char *ident = ConfNodeLookupChildValue(conf, "identity");
+    /* if null we just pass that to openlog, which will then
+     * figure it out by itself. */
+
+    openlog(ident, LOG_PID | LOG_NDELAY, facility);
+    SCLogNotice("Syslog: facility %s, level %s, ident %s", facility_s, level_s, ident);
+    *init_data = context;
+    return 0;
+}
+
+static int SyslogWrite(const char *buffer, int buffer_len, void *init_data, void *thread_data)
+{
+    Context *context = init_data;
+    syslog(context->alert_syslog_level, "%s", (const char *)buffer);
+
+    return 0;
+}
+
+static void SyslogDeInit(void *init_data)
+{
+    if (init_data) {
+        closelog();
+        SCFree(init_data);
+    }
+}
+
+void SyslogInitialize(void)
+{
+    SCPluginFileType *plugin_data = SCCalloc(1, sizeof(SCPluginFileType));
+
+    if (plugin_data == NULL) {
+        FatalError(SC_ERR_MEM_ALLOC, "Unable to allocate memory for eve output %s", OUTPUT_NAME);
+    }
+
+    plugin_data->internal = true;
+    plugin_data->name = OUTPUT_NAME;
+    plugin_data->Init = SyslogInit;
+    plugin_data->Deinit = SyslogDeInit;
+    plugin_data->Write = SyslogWrite;
+}
+#endif /* !OS_WIN32 */
index a5c1a8714e936c3f34d51c6ea09acd95aa71f16c..b3c86be2352ab40a82da6003f4ff8f7e41790ec0 100755 (executable)
@@ -410,6 +410,7 @@ noinst_HEADERS = \
        output-json-template-rust.h \
        output-json-tftp.h \
        output-json-tls.h \
+       output-eve-syslog.h \
        output-lua.h \
        output-packet.h \
        output-stats.h \
@@ -984,6 +985,7 @@ libsuricata_c_a_SOURCES = \
        output-json-template-rust.c \
        output-json-tftp.c \
        output-json-tls.c \
+       output-eve-syslog.c \
        output-lua.c \
        output-packet.c \
        output-stats.c \
diff --git a/src/output-eve-syslog.c b/src/output-eve-syslog.c
new file mode 100644 (file)
index 0000000..1501fe0
--- /dev/null
@@ -0,0 +1,120 @@
+/* vi: set et ts=4: */
+/* Copyright (C) 2021 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 Mike Pomraning <mpomraning@qualys.com>
+ * \author Jeff Lucovsky <jeff@lucovsky.org>
+ *
+ * File-like output for logging:  syslog
+ */
+
+#include "suricata-common.h" /* errno.h, string.h, etc. */
+#include "output.h"          /* DEFAULT_LOG_* */
+#include "output-eve-syslog.h"
+#include "util-syslog.h"
+
+#define DEFAULT_ALERT_SYSLOG_FACILITY_STR "local0"
+#define DEFAULT_ALERT_SYSLOG_FACILITY     LOG_LOCAL0
+#define DEFAULT_ALERT_SYSLOG_LEVEL        LOG_INFO
+
+#ifdef OS_WIN32
+void SyslogInitialize(void)
+{
+}
+#else /* !OS_WIN32 */
+#define OUTPUT_NAME "syslog"
+
+typedef struct Context_ {
+    int alert_syslog_level;
+} Context;
+
+static int SyslogInit(ConfNode *conf, bool threaded, void **init_data)
+{
+    Context *context = SCCalloc(1, sizeof(Context));
+    if (context == NULL) {
+        SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate context for %s", OUTPUT_NAME);
+        return -1;
+    }
+    const char *facility_s = ConfNodeLookupChildValue(conf, "facility");
+    if (facility_s == NULL) {
+        facility_s = DEFAULT_ALERT_SYSLOG_FACILITY_STR;
+    }
+
+    int facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap());
+    if (facility == -1) {
+        SCLogWarning(SC_ERR_INVALID_ARGUMENT,
+                "Invalid syslog facility: \"%s\","
+                " now using \"%s\" as syslog facility",
+                facility_s, DEFAULT_ALERT_SYSLOG_FACILITY_STR);
+        facility = DEFAULT_ALERT_SYSLOG_FACILITY;
+    }
+
+    const char *level_s = ConfNodeLookupChildValue(conf, "level");
+    if (level_s != NULL) {
+        int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap());
+        if (level != -1) {
+            context->alert_syslog_level = level;
+        }
+    }
+
+    const char *ident = ConfNodeLookupChildValue(conf, "identity");
+    /* if null we just pass that to openlog, which will then
+     * figure it out by itself. */
+
+    openlog(ident, LOG_PID | LOG_NDELAY, facility);
+    SCLogNotice("Syslog: facility %s, level %s, ident %s", facility_s, level_s, ident);
+    *init_data = context;
+    return 0;
+}
+
+static int SyslogWrite(const char *buffer, int buffer_len, void *init_data, void *thread_data)
+{
+    Context *context = init_data;
+    syslog(context->alert_syslog_level, "%s", (const char *)buffer);
+
+    return 0;
+}
+
+static void SyslogDeInit(void *init_data)
+{
+    if (init_data) {
+        closelog();
+        SCFree(init_data);
+    }
+}
+
+void SyslogInitialize(void)
+{
+    SCPluginFileType *plugin_data = SCCalloc(1, sizeof(SCPluginFileType));
+
+    if (plugin_data == NULL) {
+        FatalError(SC_ERR_MEM_ALLOC, "Unable to allocate memory for eve output %s", OUTPUT_NAME);
+    }
+
+    plugin_data->internal = true;
+    plugin_data->name = OUTPUT_NAME;
+    plugin_data->Init = SyslogInit;
+    plugin_data->Deinit = SyslogDeInit;
+    plugin_data->Write = SyslogWrite;
+    if (!SCRegisterEveFileType(plugin_data)) {
+        FatalError(SC_ERR_PLUGIN, "Failed to register EVE output: %s", OUTPUT_NAME);
+    }
+}
+#endif /* !OS_WIN32 */
diff --git a/src/output-eve-syslog.h b/src/output-eve-syslog.h
new file mode 100644 (file)
index 0000000..03d5f3e
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (C) 2021 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 Jeff Lucovsky <jeff@lucovsky.org>
+ */
+
+#ifndef __OUTPUT_EVE_SYSLOG_H__
+#define __OUTPUT_EVE_SYSLOG_H__
+
+void SyslogInitialize(void);
+
+#endif /* __OUTPUT_EVE_SYSLOG_H__ */
index a68cef887de961c2c6a3e00d051f13a0d852a130..c7ef24ff96ef90eb7d7e72a7474ec699f163ca2b 100644 (file)
@@ -884,13 +884,8 @@ int LogFileFreeCtx(LogFileCtx *lf_ctx)
 
 int LogFileWrite(LogFileCtx *file_ctx, MemBuffer *buffer)
 {
-    if (file_ctx->type == LOGFILE_TYPE_SYSLOG) {
-        syslog(file_ctx->syslog_setup.alert_syslog_level, "%s",
-                (const char *)MEMBUFFER_BUFFER(buffer));
-    } else if (file_ctx->type == LOGFILE_TYPE_FILE ||
-               file_ctx->type == LOGFILE_TYPE_UNIX_DGRAM ||
-               file_ctx->type == LOGFILE_TYPE_UNIX_STREAM)
-    {
+    if (file_ctx->type == LOGFILE_TYPE_FILE || file_ctx->type == LOGFILE_TYPE_UNIX_DGRAM ||
+            file_ctx->type == LOGFILE_TYPE_UNIX_STREAM) {
         /* append \n for files only */
         MemBufferWriteString(buffer, "\n");
         file_ctx->Write((const char *)MEMBUFFER_BUFFER(buffer),
index e8b4499607020c23acc71c8fbe3e614006022e42..4cc2a28921f7a37fbde624503c1defc539aad81e 100644 (file)
@@ -35,7 +35,6 @@
 
 enum LogFileType {
     LOGFILE_TYPE_FILE,
-    LOGFILE_TYPE_SYSLOG,
     LOGFILE_TYPE_UNIX_DGRAM,
     LOGFILE_TYPE_UNIX_STREAM,
     LOGFILE_TYPE_REDIS,
@@ -73,7 +72,6 @@ typedef struct LogFileCtx_ {
     LogThreadedFileCtx *threads;
 
     union {
-        SyslogSetup syslog_setup;
 #ifdef HAVE_LIBHIREDIS
         RedisSetup redis_setup;
 #endif
index 0ed9ce225cd6aad3212da64e12b6d0c065edac6f..7e7eb595b3f8009fb17630e84fde609ee2e14945 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020 Open Information Security Foundation
+/* Copyright (C) 2020-2021 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
@@ -93,6 +93,7 @@ static void InitPlugin(char *path)
  */
 void SCInternalLoad(void)
 {
+    SyslogInitialize();
 }
 
 void SCPluginsLoad(const char *capture_plugin_name, const char *capture_plugin_args)
index 7415eb68e4f4586aa93e9453a660fe228d2a161d..8d87da760ee58b81cf6314dc9c4165d1713dab12 100644 (file)
@@ -19,6 +19,7 @@
 #define __UTIL_PLUGIN_H__
 
 #include "suricata-plugin.h"
+#include "output-eve-syslog.h"
 
 void SCInternalLoad(void);
 void SCPluginsLoad(const char *capture_plugin_name, const char *capture_plugin_args);