mirror of https://github.com/OISF/suricata
plugins: initial support for a filetype plugin
A filetype plugin is a plugin that implements an eve filetype. Most of the current filetypes could likely be implemented as such a plugin. Such a plugin must implement Open, Close and Write, where Write is provided the formatted JSON to be logged. This commit also includes the plumbing for plugin loading. Example plugin to come. Plugins are loaded by the "plugin" section in the configuration file: plugins: - /path/to/directory/plugins - /path/to/plugin_file.so This can also be done on the command line with: --set plugins.0=/path/plugin_file.sopull/5282/head
parent
f35c25cef2
commit
8fb35236e6
@ -0,0 +1,53 @@
|
||||
/* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef __SURICATA_PLUGIN_H__
|
||||
#define __SURICATA_PLUGIN_H__
|
||||
|
||||
#include "autoconf.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
/**
|
||||
* Structure to define a Suricata plugin.
|
||||
*/
|
||||
typedef struct SCPlugin_ {
|
||||
const char *name;
|
||||
const char *license;
|
||||
const char *author;
|
||||
void (*Init)(void);
|
||||
} SCPlugin;
|
||||
|
||||
/**
|
||||
* Structure used to define a file type plugin.
|
||||
*
|
||||
* Currently only used by the Eve output type.
|
||||
*/
|
||||
typedef struct SCPluginFileType_ {
|
||||
char *name;
|
||||
int (*Open)(ConfNode *conf, void **data);
|
||||
int (*Write)(const char *buffer, int buffer_len, void *ctx);
|
||||
void (*Close)(void *ctx);
|
||||
TAILQ_ENTRY(SCPluginFileType_) entries;
|
||||
} SCPluginFileType;
|
||||
|
||||
bool SCPluginRegisterFileType(SCPluginFileType *);
|
||||
|
||||
#endif /* __SURICATA_PLUGIN_H */
|
@ -0,0 +1,148 @@
|
||||
/* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "suricata-plugin.h"
|
||||
#include "util-plugin.h"
|
||||
|
||||
#ifdef HAVE_PLUGINS
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
static TAILQ_HEAD(, SCPluginFileType_) output_types =
|
||||
TAILQ_HEAD_INITIALIZER(output_types);
|
||||
|
||||
static void InitPlugin(char *path)
|
||||
{
|
||||
void *lib = dlopen(path, RTLD_NOW);
|
||||
if (lib == NULL) {
|
||||
SCLogNotice("Failed to open %s as a plugin: %s", path, dlerror());
|
||||
} else {
|
||||
SCLogNotice("Loading plugin %s", path);
|
||||
SCPlugin *plugin = dlsym(lib, "PluginSpec");
|
||||
if (plugin == NULL) {
|
||||
SCLogError(SC_ERR_PLUGIN, "Plugin does not export a plugin specification: %s", path);
|
||||
} else {
|
||||
BUG_ON(plugin->name == NULL);
|
||||
BUG_ON(plugin->author == NULL);
|
||||
BUG_ON(plugin->license == NULL);
|
||||
BUG_ON(plugin->Init == NULL);
|
||||
SCLogNotice("Initializing plugin %s; author=%s; license=%s",
|
||||
plugin->name, plugin->author, plugin->license);
|
||||
(*plugin->Init)();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SCPluginsLoad(void)
|
||||
{
|
||||
ConfNode *conf = ConfGetNode("plugins");
|
||||
if (conf == NULL) {
|
||||
return;
|
||||
}
|
||||
ConfNode *plugin = NULL;
|
||||
TAILQ_FOREACH(plugin, &conf->head, next) {
|
||||
struct stat statbuf;
|
||||
if (stat(plugin->val, &statbuf) == -1) {
|
||||
SCLogError(SC_ERR_STAT, "Bad plugin path: %s: %s",
|
||||
plugin->val, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
DIR *dir = opendir(plugin->val);
|
||||
if (dir == NULL) {
|
||||
SCLogError(SC_ERR_DIR_OPEN, "Failed to open plugin directory %s: %s",
|
||||
plugin->val, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
struct dirent *entry = NULL;
|
||||
char path[PATH_MAX];
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (strstr(entry->d_name, ".so") != NULL) {
|
||||
snprintf(path, sizeof(path), "%s/%s", plugin->val, entry->d_name);
|
||||
InitPlugin(path);
|
||||
}
|
||||
}
|
||||
free(dir);
|
||||
} else {
|
||||
InitPlugin(plugin->val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Register an Eve/JSON file type plugin.
|
||||
*
|
||||
* \retval true if registered successfully, false if the plugin name
|
||||
* conflicts with a built-in or previously registered
|
||||
* plugin file type.
|
||||
*
|
||||
* TODO: As this is Eve specific, perhaps Eve should be in the filename.
|
||||
*/
|
||||
bool SCPluginRegisterFileType(SCPluginFileType *plugin)
|
||||
{
|
||||
const char *builtin[] = {
|
||||
"regular",
|
||||
"syslog",
|
||||
"unix_dgram",
|
||||
"unix_stream",
|
||||
"redis",
|
||||
NULL,
|
||||
};
|
||||
for (int i = 0;; i++) {
|
||||
if (builtin[i] == NULL) {
|
||||
break;
|
||||
}
|
||||
if (strcmp(builtin[i], plugin->name) == 0) {
|
||||
SCLogNotice("Eve filetype plugin name \"%s\" conflicts "
|
||||
"with built-in name", plugin->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SCPluginFileType *existing = NULL;
|
||||
TAILQ_FOREACH(existing, &output_types, entries) {
|
||||
if (strcmp(existing->name, plugin->name) == 0) {
|
||||
SCLogNotice("Eve filetype plugin name conflicts with previously "
|
||||
"registered plugin: %s", plugin->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SCLogNotice("Registering JSON file type plugin %s", plugin->name);
|
||||
TAILQ_INSERT_TAIL(&output_types, plugin, entries);
|
||||
return true;
|
||||
}
|
||||
|
||||
SCPluginFileType *SCPluginFindFileType(const char *name)
|
||||
{
|
||||
SCPluginFileType *plugin = NULL;
|
||||
TAILQ_FOREACH(plugin, &output_types, entries) {
|
||||
if (strcmp(name, plugin->name) == 0) {
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void PluginsLoad(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,26 @@
|
||||
/* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_PLUGIN_H__
|
||||
#define __UTIL_PLUGIN_H__
|
||||
|
||||
#include "suricata-plugin.h"
|
||||
|
||||
void SCPluginsLoad(void);
|
||||
SCPluginFileType *SCPluginFindFileType(const char *name);
|
||||
|
||||
#endif /* __UTIL_PLUGIN_H__ */
|
Loading…
Reference in New Issue