}
}
+#define ARRAY_CAP_STEP 16
+static void (**PreRegisteredCallbacks)(void) = NULL;
+static size_t preregistered_callbacks_nb = 0;
+static size_t preregistered_callbacks_cap = 0;
+
+int AppLayerParserPreRegister(void (*Register)(void))
+{
+ if (preregistered_callbacks_nb == preregistered_callbacks_cap) {
+ void *tmp = SCRealloc(PreRegisteredCallbacks,
+ sizeof(void *) * (preregistered_callbacks_cap + ARRAY_CAP_STEP));
+ if (tmp == NULL) {
+ return 1;
+ }
+ preregistered_callbacks_cap += ARRAY_CAP_STEP;
+ PreRegisteredCallbacks = tmp;
+ }
+ PreRegisteredCallbacks[preregistered_callbacks_nb] = Register;
+ preregistered_callbacks_nb++;
+ return 0;
+}
+
void AppLayerParserRegisterProtocolParsers(void)
{
SCEnter();
} else {
SCLogInfo("Protocol detection and parser disabled for pop3 protocol.");
}
+ for (size_t i = 0; i < preregistered_callbacks_nb; i++) {
+ PreRegisteredCallbacks[i]();
+ }
ValidateParsers();
}
typedef int (*AppLayerParserGetFrameIdByNameFn)(const char *frame_name);
typedef const char *(*AppLayerParserGetFrameNameByIdFn)(const uint8_t id);
+int AppLayerParserPreRegister(void (*Register)(void));
/**
* \brief Register app layer parser for the protocol.
*
#include "app-layer-protos.h"
#include "rust.h"
-AppProto g_alproto_max = ALPROTO_MAX_STATIC + 1;
+AppProto g_alproto_max = ALPROTO_MAX_STATIC;
#define ARRAY_CAP_STEP 16
-AppProto g_alproto_strings_cap = ALPROTO_MAX_STATIC + 1;
+AppProto g_alproto_strings_cap = ALPROTO_MAX_STATIC;
typedef struct AppProtoStringTuple {
AppProto alproto;
FatalError("Unable to allocate g_alproto_strings");
}
}
- } else if (alproto + 1 == g_alproto_max) {
+ } else if (alproto == g_alproto_max) {
if (g_alproto_max == g_alproto_strings_cap) {
void *tmp = SCRealloc(g_alproto_strings,
sizeof(AppProtoStringTuple) * (g_alproto_strings_cap + ARRAY_CAP_STEP));
const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f,
uint8_t flags, void *_alstate, void *tx, uint64_t tx_id);
+void DetectFileRegisterProto(
+ AppProto alproto, int direction, int to_client_progress, int to_server_progress);
+
#endif /* SURICATA_DETECT_ENGINE_FILE_H */
}
}
+#define ARRAY_CAP_STEP 16
+static void (**PreregisteredCallbacks)(void) = NULL;
+static size_t preregistered_callbacks_nb = 0;
+static size_t preregistered_callbacks_cap = 0;
+
+// Plugins can preregister keywords with this function :
+// When an app-layer plugin is loaded, it wants to register its keywords
+// But the plugin is loaded before keywords can register
+// The preregistration callbacks will later be called by SigTableSetup
+int SigTablePreRegister(void (*KeywordsRegister)(void))
+{
+ if (preregistered_callbacks_nb == preregistered_callbacks_cap) {
+ void *tmp = SCRealloc(PreregisteredCallbacks,
+ sizeof(void *) * (preregistered_callbacks_cap + ARRAY_CAP_STEP));
+ if (tmp == NULL) {
+ return 1;
+ }
+ preregistered_callbacks_cap += ARRAY_CAP_STEP;
+ PreregisteredCallbacks = tmp;
+ }
+ PreregisteredCallbacks[preregistered_callbacks_nb] = KeywordsRegister;
+ preregistered_callbacks_nb++;
+ return 0;
+}
+
void SigTableInit(void)
{
if (sigmatch_table == NULL) {
ScDetectSipRegister();
ScDetectTemplateRegister();
+ for (size_t i = 0; i < preregistered_callbacks_nb; i++) {
+ PreregisteredCallbacks[i]();
+ }
+
/* close keyword registration */
DetectBufferTypeCloseRegistration();
}
void SigTableCleanup(void);
void SigTableInit(void);
void SigTableSetup(void);
+int SigTablePreRegister(void (*KeywordsRegister)(void));
void SigTableRegisterTests(void);
bool SigTableHasKeyword(const char *keyword);
#include "string.h"
#include "detect-parse.h"
#include "detect-engine-iponly.h"
+#include "detect-engine-file.h"
#include "app-layer-detect-proto.h"
#include "action-globals.h"
#include "util-validate.h"
+// file protocols with common file handling
+typedef struct {
+ AppProto alproto;
+ int direction;
+ int to_client_progress;
+ int to_server_progress;
+} DetectFileHandlerProtocol_t;
+
/* Table with all filehandler registrations */
DetectFileHandlerTableElmt filehandler_table[DETECT_TBLSIZE_STATIC];
+#define ALPROTO_WITHFILES_MAX 16
+
+// file protocols with common file handling
+DetectFileHandlerProtocol_t al_protocols[ALPROTO_WITHFILES_MAX] = {
+ { .alproto = ALPROTO_NFS, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
+ { .alproto = ALPROTO_SMB, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
+ { .alproto = ALPROTO_FTP, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
+ { .alproto = ALPROTO_FTPDATA, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
+ { .alproto = ALPROTO_HTTP1,
+ .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT,
+ .to_client_progress = HTP_RESPONSE_BODY,
+ .to_server_progress = HTP_REQUEST_BODY },
+ { .alproto = ALPROTO_HTTP2,
+ .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT,
+ .to_client_progress = HTTP2StateDataServer,
+ .to_server_progress = HTTP2StateDataClient },
+ { .alproto = ALPROTO_SMTP, .direction = SIG_FLAG_TOSERVER }, { .alproto = ALPROTO_UNKNOWN }
+};
+
+void DetectFileRegisterProto(
+ AppProto alproto, int direction, int to_client_progress, int to_server_progress)
+{
+ size_t i = 0;
+ while (i < ALPROTO_WITHFILES_MAX && al_protocols[i].alproto != ALPROTO_UNKNOWN) {
+ i++;
+ }
+ if (i == ALPROTO_WITHFILES_MAX) {
+ return;
+ }
+ al_protocols[i].alproto = alproto;
+ al_protocols[i].direction = direction;
+ al_protocols[i].to_client_progress = to_client_progress;
+ al_protocols[i].to_server_progress = to_server_progress;
+ al_protocols[i + 1].alproto = ALPROTO_UNKNOWN;
+}
+
void DetectFileRegisterFileProtocols(DetectFileHandlerTableElmt *reg)
{
- // file protocols with common file handling
- typedef struct {
- AppProto al_proto;
- int direction;
- int to_client_progress;
- int to_server_progress;
- } DetectFileHandlerProtocol_t;
- static DetectFileHandlerProtocol_t al_protocols[] = {
- { .al_proto = ALPROTO_NFS, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
- { .al_proto = ALPROTO_SMB, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
- { .al_proto = ALPROTO_FTP, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
- { .al_proto = ALPROTO_FTPDATA, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
- { .al_proto = ALPROTO_HTTP1,
- .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT,
- .to_client_progress = HTP_RESPONSE_BODY,
- .to_server_progress = HTP_REQUEST_BODY },
- { .al_proto = ALPROTO_HTTP2,
- .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT,
- .to_client_progress = HTTP2StateDataServer,
- .to_server_progress = HTTP2StateDataClient },
- { .al_proto = ALPROTO_SMTP, .direction = SIG_FLAG_TOSERVER }
- };
-
- for (size_t i = 0; i < ARRAY_SIZE(al_protocols); i++) {
+ for (size_t i = 0; i < g_alproto_max; i++) {
+ if (al_protocols[i].alproto == ALPROTO_UNKNOWN) {
+ break;
+ }
int direction = al_protocols[i].direction == 0
? (int)(SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT)
: al_protocols[i].direction;
if (direction & SIG_FLAG_TOCLIENT) {
DetectAppLayerMpmRegister(reg->name, SIG_FLAG_TOCLIENT, reg->priority, reg->PrefilterFn,
- reg->GetData, al_protocols[i].al_proto, al_protocols[i].to_client_progress);
- DetectAppLayerInspectEngineRegister(reg->name, al_protocols[i].al_proto,
+ reg->GetData, al_protocols[i].alproto, al_protocols[i].to_client_progress);
+ DetectAppLayerInspectEngineRegister(reg->name, al_protocols[i].alproto,
SIG_FLAG_TOCLIENT, al_protocols[i].to_client_progress, reg->Callback,
reg->GetData);
}
if (direction & SIG_FLAG_TOSERVER) {
DetectAppLayerMpmRegister(reg->name, SIG_FLAG_TOSERVER, reg->priority, reg->PrefilterFn,
- reg->GetData, al_protocols[i].al_proto, al_protocols[i].to_server_progress);
- DetectAppLayerInspectEngineRegister(reg->name, al_protocols[i].al_proto,
+ reg->GetData, al_protocols[i].alproto, al_protocols[i].to_server_progress);
+ DetectAppLayerInspectEngineRegister(reg->name, al_protocols[i].alproto,
SIG_FLAG_TOSERVER, al_protocols[i].to_server_progress, reg->Callback,
reg->GetData);
}
return JsonGenericLogger(tv, thread_data, p, f, state, tx, tx_id, LOG_DIR_FLOW);
}
+#define ARRAY_CAP_STEP 16
+static EveJsonTxLoggerRegistrationData *preregistered_loggers = NULL;
+static size_t preregistered_loggers_nb = 0;
+static size_t preregistered_loggers_cap = 0;
+
+// Plugins can preregister logger with this function :
+// When an app-layer plugin is loaded, it wants to register its logger
+// But the plugin is loaded before loggers can register
+// The preregistration data will later be used by OutputRegisterLoggers
+int OutputPreRegisterLogger(EveJsonTxLoggerRegistrationData reg_data)
+{
+ if (preregistered_loggers_nb == preregistered_loggers_cap) {
+ void *tmp = SCRealloc(
+ preregistered_loggers, sizeof(EveJsonTxLoggerRegistrationData) *
+ (preregistered_loggers_cap + ARRAY_CAP_STEP));
+ if (tmp == NULL) {
+ return 1;
+ }
+ preregistered_loggers_cap += ARRAY_CAP_STEP;
+ preregistered_loggers = tmp;
+ }
+ preregistered_loggers[preregistered_loggers_nb] = reg_data;
+ preregistered_loggers_nb++;
+ return 0;
+}
+
/**
* \brief Register all non-root logging modules.
*/
}
/* ARP JSON logger */
JsonArpLogRegister();
+
+ for (size_t i = 0; i < preregistered_loggers_nb; i++) {
+ OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", preregistered_loggers[i].logname,
+ preregistered_loggers[i].confname, OutputJsonLogInitSub,
+ preregistered_loggers[i].alproto, JsonGenericDirFlowLogger, JsonLogThreadInit,
+ JsonLogThreadDeinit);
+ SCLogDebug(
+ "%s JSON logger registered.", AppProtoToString(preregistered_loggers[i].alproto));
+ RegisterSimpleJsonApplayerLogger(
+ preregistered_loggers[i].alproto, preregistered_loggers[i].LogTx, NULL);
+ }
}
EveJsonSimpleAppLayerLogger *SCEveJsonSimpleGetLogger(AppProto alproto);
+typedef struct EveJsonTxLoggerRegistrationData {
+ const char *confname;
+ const char *logname;
+ AppProto alproto;
+ EveJsonSimpleTxLogFunc LogTx;
+} EveJsonTxLoggerRegistrationData;
+
+int OutputPreRegisterLogger(EveJsonTxLoggerRegistrationData reg_data);
+
#endif /* ! SURICATA_OUTPUT_H */
int SCPluginRegisterCapture(SCCapturePlugin *);
+// Every change in the API used by plugins should change this number
+#define SC_PLUGIN_API_VERSION 8
+
+typedef struct SCAppLayerPlugin_ {
+ // versioning to check suricata/plugin API compatibility
+ uint64_t version;
+ char *name;
+ void (*Register)(void);
+ void (*KeywordsRegister)(void);
+ char *logname;
+ char *confname;
+ bool (*Logger)(void *tx, void *jb);
+} SCAppLayerPlugin;
+
+int SCPluginRegisterAppLayer(SCAppLayerPlugin *);
+
#endif /* __SURICATA_PLUGIN_H */
#ifdef HAVE_PLUGINS
+#include "app-layer-protos.h"
+#include "app-layer-parser.h"
+#include "detect-engine-register.h"
+#include "output.h"
+
#include <dlfcn.h>
typedef struct PluginListNode_ {
}
return plugin;
}
+
+int SCPluginRegisterAppLayer(SCAppLayerPlugin *plugin)
+{
+ if (plugin->version != SC_PLUGIN_API_VERSION) {
+ return 1;
+ }
+ AppProto alproto = g_alproto_max;
+ AppProtoRegisterProtoString(alproto, plugin->name);
+ if (plugin->Register) {
+ if (AppLayerParserPreRegister(plugin->Register) != 0) {
+ return 1;
+ }
+ }
+ if (plugin->KeywordsRegister) {
+ if (SigTablePreRegister(plugin->KeywordsRegister) != 0) {
+ return 1;
+ }
+ }
+ if (plugin->Logger) {
+ EveJsonTxLoggerRegistrationData reg_data = {
+ .confname = plugin->confname,
+ .logname = plugin->logname,
+ .alproto = alproto,
+ .LogTx = (EveJsonSimpleTxLogFunc)plugin->Logger,
+ };
+ if (OutputPreRegisterLogger(reg_data) != 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
#endif