Skip to content

Commit

Permalink
plugins: app-layer plugins
Browse files Browse the repository at this point in the history
Ticket: 5053
  • Loading branch information
catenacyber committed Jan 9, 2025
1 parent 4e001c2 commit 404395b
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 31 deletions.
24 changes: 24 additions & 0 deletions src/app-layer-parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -1700,6 +1700,27 @@ static void ValidateParsers(void)
}
}

#define ARRAY_CAP_STEP 16
static void (**preregistered_callbacks)(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(preregistered_callbacks,
sizeof(void *) * (preregistered_callbacks_cap + ARRAY_CAP_STEP));
if (tmp == NULL) {
return 1;
}
preregistered_callbacks_cap += ARRAY_CAP_STEP;
preregistered_callbacks = tmp;
}
preregistered_callbacks[preregistered_callbacks_nb] = Register;
preregistered_callbacks_nb++;
return 0;
}

void AppLayerParserRegisterProtocolParsers(void)
{
SCEnter();
Expand Down Expand Up @@ -1752,6 +1773,9 @@ void AppLayerParserRegisterProtocolParsers(void)
} else {
SCLogInfo("Protocol detection and parser disabled for pop3 protocol.");
}
for (size_t i = 0; i < preregistered_callbacks_nb; i++) {
preregistered_callbacks[i]();
}

ValidateParsers();
}
Expand Down
1 change: 1 addition & 0 deletions src/app-layer-parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ typedef AppLayerGetTxIterTuple (*AppLayerGetTxIteratorFunc)
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.
*
Expand Down
6 changes: 3 additions & 3 deletions src/app-layer-protos.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
#include "app-layer-protos.h"
#include "rust.h"

AppProto AlprotoMax = ALPROTO_MAX_STATIC + 1;
AppProto AlprotoMax = ALPROTO_MAX_STATIC;
#define ARRAY_CAP_STEP 16
AppProto AppProtoStringsCap = ALPROTO_MAX_STATIC + 1;
AppProto AppProtoStringsCap = ALPROTO_MAX_STATIC;

typedef struct AppProtoStringTuple {
AppProto alproto;
Expand Down Expand Up @@ -80,7 +80,7 @@ void AppProtoRegisterProtoString(AppProto alproto, const char *proto_name)
FatalError("Unable to allocate AppProtoStrings");
}
}
} else if (alproto + 1 == AlprotoMax) {
} else if (alproto == AlprotoMax) {
if (AlprotoMax == AppProtoStringsCap) {
void *tmp = SCRealloc(AppProtoStrings,
sizeof(AppProtoStringTuple) * (AppProtoStringsCap + ARRAY_CAP_STEP));
Expand Down
3 changes: 3 additions & 0 deletions src/detect-engine-file.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ uint8_t DetectFileInspectGeneric(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
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 */
25 changes: 25 additions & 0 deletions src/detect-engine-register.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,27 @@ void SigTableCleanup(void)
}
}

#define ARRAY_CAP_STEP 16
static void (**preregistered_callbacks)(void) = NULL;
static size_t preregistered_callbacks_nb = 0;
static size_t preregistered_callbacks_cap = 0;

int SigTablePreRegister(void (*KeywordsRegister)(void))
{
if (preregistered_callbacks_nb == preregistered_callbacks_cap) {
void *tmp = SCRealloc(preregistered_callbacks,
sizeof(void *) * (preregistered_callbacks_cap + ARRAY_CAP_STEP));
if (tmp == NULL) {
return 1;
}
preregistered_callbacks_cap += ARRAY_CAP_STEP;
preregistered_callbacks = tmp;
}
preregistered_callbacks[preregistered_callbacks_nb] = KeywordsRegister;
preregistered_callbacks_nb++;
return 0;
}

void SigTableInit(void)
{
if (sigmatch_table == NULL) {
Expand Down Expand Up @@ -708,6 +729,10 @@ void SigTableSetup(void)
ScDetectSipRegister();
ScDetectTemplateRegister();

for (size_t i = 0; i < preregistered_callbacks_nb; i++) {
preregistered_callbacks[i]();
}

/* close keyword registration */
DetectBufferTypeCloseRegistration();
}
Expand Down
1 change: 1 addition & 0 deletions src/detect-engine-register.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ int SigTableList(const char *keyword);
void SigTableCleanup(void);
void SigTableInit(void);
void SigTableSetup(void);
int SigTablePreRegister(void (*KeywordsRegister)(void));
void SigTableRegisterTests(void);
bool SigTableHasKeyword(const char *keyword);

Expand Down
81 changes: 53 additions & 28 deletions src/detect-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,55 +69,80 @@
#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 < AlprotoMax; 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);
}
Expand Down
33 changes: 33 additions & 0 deletions src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,28 @@ static int JsonGenericDirFlowLogger(ThreadVars *tv, void *thread_data, const Pac
return JsonGenericLogger(tv, thread_data, p, f, state, tx, tx_id, LOG_DIR_FLOW);
}

#define ARRAY_CAP_STEP 16
static EveJsonLoggerRegistrationData *preregistered_loggers = NULL;
static size_t preregistered_loggers_nb = 0;
static size_t preregistered_loggers_cap = 0;

int OutputPreRegisterLogger(EveJsonLoggerRegistrationData reg_data)
{
if (preregistered_loggers_nb == preregistered_loggers_cap) {
void *tmp = SCRealloc(
preregistered_loggers, sizeof(EveJsonLoggerRegistrationData) *
(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.
*/
Expand Down Expand Up @@ -1105,4 +1127,15 @@ void OutputRegisterLoggers(void)
}
/* 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);
SCLogNotice(
"%s JSON logger registered.", AppProtoToString(preregistered_loggers[i].alproto));
RegisterSimpleJsonApplayerLogger(
preregistered_loggers[i].alproto, preregistered_loggers[i].LogTx, NULL);
}
}
9 changes: 9 additions & 0 deletions src/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,13 @@ typedef struct EveJsonSimpleAppLayerLogger {

EveJsonSimpleAppLayerLogger *SCEveJsonSimpleGetLogger(AppProto alproto);

typedef struct EveJsonLoggerRegistrationData {
const char *confname;
const char *logname;
AppProto alproto;
EveJsonSimpleTxLogFunc LogTx;
} EveJsonLoggerRegistrationData;

int OutputPreRegisterLogger(EveJsonLoggerRegistrationData reg_data);

#endif /* ! SURICATA_OUTPUT_H */
16 changes: 16 additions & 0 deletions src/suricata-plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,20 @@ typedef struct SCCapturePlugin_ {

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 */
36 changes: 36 additions & 0 deletions src/util-plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@

#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_ {
Expand Down Expand Up @@ -148,4 +153,35 @@ SCCapturePlugin *SCPluginFindCaptureByName(const char *name)
}
return plugin;
}

int SCPluginRegisterAppLayer(SCAppLayerPlugin *plugin)
{
if (plugin->version != SC_PLUGIN_API_VERSION) {
return 1;
}
AppProto alproto = AlprotoMax;
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) {
EveJsonLoggerRegistrationData reg_data = {
.confname = plugin->confname,
.logname = plugin->logname,
.alproto = alproto,
.LogTx = (EveJsonSimpleTxLogFunc)plugin->Logger,
};
if (OutputPreRegisterLogger(reg_data) != 0) {
return 1;
}
}
return 0;
}
#endif

0 comments on commit 404395b

Please sign in to comment.