Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Applayer plugin 5053 v1 #11321

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions rust/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,13 @@ pub extern "C" fn rs_init(context: &'static SuricataContext)
init_ffi(context);
}

#[no_mangle]
pub extern "C" fn rs_update_alproto_failed(alproto: AppProto) {
unsafe {
ALPROTO_FAILED = alproto;
}
}

/// DetectEngineStateFree wrapper.
pub fn sc_detect_engine_state_free(state: *mut DetectEngineState)
{
Expand Down
4 changes: 2 additions & 2 deletions src/app-layer-detect-proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,8 +491,8 @@ static inline AppProto PPGetProto(const AppLayerProtoDetectProbingParserElement
if (AppProtoIsValid(alproto)) {
SCReturnUInt(alproto);
}
if (alproto == ALPROTO_FAILED ||
(pe->max_depth != 0 && buflen > pe->max_depth)) {
if (alproto == ALPROTO_FAILED || alproto == ALPROTO_INVALID ||
(pe->max_depth != 0 && buflen > pe->max_depth)) {
alproto_masks[0] |= pe->alproto_mask;
}
pe = pe->next;
Expand Down
13 changes: 13 additions & 0 deletions src/app-layer-parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
#include "app-layer-rfb.h"
#include "app-layer-http2.h"

#ifdef ALPROTO_DYNAMIC_NB
#include "util-plugin.h"
#endif

struct AppLayerParserThreadCtx_ {
void *alproto_local_storage[FLOW_PROTO_MAX][ALPROTO_MAX];
};
Expand Down Expand Up @@ -1776,6 +1780,15 @@ void AppLayerParserRegisterProtocolParsers(void)
} else {
SCLogInfo("Protocol detection and parser disabled for pop3 protocol.");
}
#ifdef ALPROTO_DYNAMIC_NB
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would not be something that should be compile time optional?

for (size_t i = 0; i < ALPROTO_DYNAMIC_NB; i++) {
SCAppLayerPlugin *app_layer_plugin = SCPluginFindAppLayerByIndex(i);
if (app_layer_plugin == NULL) {
break;
}
app_layer_plugin->Register();
}
#endif

ValidateParsers();
}
Expand Down
21 changes: 18 additions & 3 deletions src/app-layer-protos.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@

#include "suricata-common.h"
#include "app-layer-protos.h"
#include "rust.h"

AppProto ALPROTO_FAILED = ALPROTO_MAX_STATIC;

typedef struct AppProtoStringTuple {
AppProto alproto;
const char *str;
} AppProtoStringTuple;

const AppProtoStringTuple AppProtoStrings[ALPROTO_MAX] = {
AppProtoStringTuple AppProtoStrings[ALPROTO_MAX] = {
{ ALPROTO_UNKNOWN, "unknown" },
{ ALPROTO_HTTP1, "http1" },
{ ALPROTO_FTP, "ftp" },
Expand Down Expand Up @@ -67,10 +70,10 @@ const AppProtoStringTuple AppProtoStrings[ALPROTO_MAX] = {
{ ALPROTO_BITTORRENT_DHT, "bittorrent-dht" },
{ ALPROTO_POP3, "pop3" },
{ ALPROTO_HTTP, "http" },
{ ALPROTO_FAILED, "failed" },
#ifdef UNITTESTS
{ ALPROTO_TEST, "test" },
#endif
{ ALPROTO_MAX_STATIC, "failed" },
};

const char *AppProtoToString(AppProto alproto)
Expand Down Expand Up @@ -100,9 +103,21 @@ AppProto StringToAppProto(const char *proto_name)

// We could use a Multi Pattern Matcher
for (size_t i = 0; i < ARRAY_SIZE(AppProtoStrings); i++) {
if (strcmp(proto_name, AppProtoStrings[i].str) == 0)
if (AppProtoStrings[i].str != NULL && strcmp(proto_name, AppProtoStrings[i].str) == 0)
return AppProtoStrings[i].alproto;
}

return ALPROTO_UNKNOWN;
}

void RegisterAppProtoString(AppProto alproto, const char *proto_name)
{
if (alproto == ALPROTO_FAILED && alproto + 1 < ALPROTO_MAX) {
AppProtoStrings[alproto].str = proto_name;
AppProtoStrings[alproto].alproto = alproto;
ALPROTO_FAILED++;
rs_update_alproto_failed(ALPROTO_FAILED);
AppProtoStrings[ALPROTO_FAILED].str = "failed";
AppProtoStrings[ALPROTO_FAILED].alproto = ALPROTO_FAILED;
}
}
14 changes: 10 additions & 4 deletions src/app-layer-protos.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,24 @@ enum AppProtoEnum {
// HTTP for any version (ALPROTO_HTTP1 (version 1) or ALPROTO_HTTP2)
ALPROTO_HTTP,

/* used by the probing parser when alproto detection fails
* permanently for that particular stream */
ALPROTO_FAILED,
#ifdef UNITTESTS
ALPROTO_TEST,
#endif /* UNITESTS */
/* keep last */
ALPROTO_MAX,
ALPROTO_MAX_STATIC,
ALPROTO_INVALID = 0xffff,
};
// NOTE: if ALPROTO's get >= 256, update SignatureNonPrefilterStore

/* not using the enum as that is a unsigned int, so 4 bytes */
typedef uint16_t AppProto;
extern AppProto ALPROTO_FAILED;

#ifdef ALPROTO_DYNAMIC_NB
#define ALPROTO_MAX (ALPROTO_MAX_STATIC + 1 + ALPROTO_DYNAMIC_NB)
#else
#define ALPROTO_MAX (ALPROTO_MAX_STATIC + 1)
#endif
static inline bool AppProtoIsValid(AppProto a)
{
return ((a > ALPROTO_UNKNOWN && a < ALPROTO_FAILED));
Expand Down Expand Up @@ -119,4 +123,6 @@ const char *AppProtoToString(AppProto alproto);
*/
AppProto StringToAppProto(const char *proto_name);

void RegisterAppProtoString(AppProto alproto, const char *proto_name);

#endif /* SURICATA_APP_LAYER_PROTOS_H */
63 changes: 30 additions & 33 deletions src/app-layer.c
Original file line number Diff line number Diff line change
Expand Up @@ -905,42 +905,39 @@ int AppLayerHandleUdp(ThreadVars *tv, AppLayerThreadCtx *tctx, Packet *p, Flow *
tctx->alpd_tctx, f, p->payload, p->payload_len, IPPROTO_UDP, flags, &reverse_flow);
PACKET_PROFILING_APP_PD_END(tctx);

switch (*alproto) {
case ALPROTO_UNKNOWN:
if (*alproto_otherdir != ALPROTO_UNKNOWN) {
// Use recognized side
f->alproto = *alproto_otherdir;
// do not keep ALPROTO_UNKNOWN for this side so as not to loop
*alproto = *alproto_otherdir;
if (*alproto_otherdir == ALPROTO_FAILED) {
SCLogDebug("ALPROTO_UNKNOWN flow %p", f);
}
} else {
// First side of protocol is unknown
*alproto = ALPROTO_FAILED;
if (*alproto == ALPROTO_UNKNOWN) {
if (*alproto_otherdir != ALPROTO_UNKNOWN) {
// Use recognized side
f->alproto = *alproto_otherdir;
// do not keep ALPROTO_UNKNOWN for this side so as not to loop
*alproto = *alproto_otherdir;
if (*alproto_otherdir == ALPROTO_FAILED) {
SCLogDebug("ALPROTO_UNKNOWN flow %p", f);
}
break;
case ALPROTO_FAILED:
if (*alproto_otherdir != ALPROTO_UNKNOWN) {
// Use recognized side
f->alproto = *alproto_otherdir;
if (*alproto_otherdir == ALPROTO_FAILED) {
SCLogDebug("ALPROTO_UNKNOWN flow %p", f);
}
} else {
// First side of protocol is unknown
*alproto = ALPROTO_FAILED;
}
} else if (*alproto == ALPROTO_FAILED) {
if (*alproto_otherdir != ALPROTO_UNKNOWN) {
// Use recognized side
f->alproto = *alproto_otherdir;
if (*alproto_otherdir == ALPROTO_FAILED) {
SCLogDebug("ALPROTO_UNKNOWN flow %p", f);
}
// else wait for second side of protocol
break;
default:
if (*alproto_otherdir != ALPROTO_UNKNOWN && *alproto_otherdir != ALPROTO_FAILED) {
if (*alproto_otherdir != *alproto) {
AppLayerDecoderEventsSetEventRaw(
&p->app_layer_events, APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS);
// data already sent to parser, we cannot change the protocol to use the one
// of the server
}
} else {
f->alproto = *alproto;
}
// else wait for second side of protocol
} else {
if (*alproto_otherdir != ALPROTO_UNKNOWN && *alproto_otherdir != ALPROTO_FAILED) {
if (*alproto_otherdir != *alproto) {
AppLayerDecoderEventsSetEventRaw(
&p->app_layer_events, APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS);
// data already sent to parser, we cannot change the protocol to use the one
// of the server
}
} else {
f->alproto = *alproto;
}
}
if (*alproto_otherdir == ALPROTO_UNKNOWN) {
if (f->alproto == ALPROTO_UNKNOWN) {
Expand Down
16 changes: 16 additions & 0 deletions src/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,22 @@ ConfNode *ConfGetNode(const char *name)
return node;
}

ConfNode * ConfGetFirstNode(const ConfNode *parent) {
return TAILQ_FIRST(&parent->head);
}

ConfNode * ConfGetNextNode(const ConfNode *node) {
return TAILQ_NEXT(node, next);
}

const char * ConfGetNameNode(const ConfNode *node) {
return node->name;
}

const char * ConfGetValueNode(const ConfNode *node) {
return node->val;
}

/**
* \brief Get the root configuration node.
*/
Expand Down
5 changes: 5 additions & 0 deletions src/conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ void ConfNodePrune(ConfNode *node);
int ConfRemove(const char *name);
bool ConfNodeHasChildren(const ConfNode *node);

ConfNode * ConfGetFirstNode(const ConfNode *parent);
ConfNode * ConfGetNextNode(const ConfNode *node);
const char * ConfGetNameNode(const ConfNode *node);
const char * ConfGetValueNode(const ConfNode *node);

ConfNode *ConfGetChildWithDefault(const ConfNode *base, const ConfNode *dflt, const char *name);
ConfNode *ConfNodeLookupKeyValue(const ConfNode *base, const char *key, const char *value);
int ConfGetChildValue(const ConfNode *base, const char *name, const char **vptr);
Expand Down
11 changes: 11 additions & 0 deletions src/detect-engine-file.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,15 @@ 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);

// file protocols with common file handling
typedef struct {
AppProto al_proto;
int direction;
int to_client_progress;
int to_server_progress;
} DetectFileHandlerProtocol_t;

void DetectFileRegisterProto(
AppProto alproto, int direction, int to_client_progress, int to_server_progress);

#endif /* SURICATA_DETECT_ENGINE_FILE_H */
59 changes: 54 additions & 5 deletions src/detect-engine-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "detect-engine-mpm.h"
#include "detect-engine-prefilter.h"
#include "detect-parse.h"
#include "detect-engine-content-inspection.h"

int DetectHelperBufferRegister(const char *name, AppProto alproto, bool toclient, bool toserver)
{
Expand Down Expand Up @@ -84,24 +85,72 @@ int DetectHelperKeywordRegister(const SCSigTableElmt *kw)
{
if (DETECT_TBLSIZE_IDX >= DETECT_TBLSIZE) {
void *tmp = SCRealloc(
sigmatch_table, (DETECT_TBLSIZE + DETECT_TBLSIZE_STEP) * sizeof(SigTableElmt));
sigmatch_table, (DETECT_TBLSIZE + DETECT_TBLSIZE_STEP) * sizeof(SigTableElmt));
if (unlikely(tmp == NULL)) {
return -1;
}
sigmatch_table = tmp;
DETECT_TBLSIZE += DETECT_TBLSIZE_STEP;
}

sigmatch_table[DETECT_TBLSIZE_IDX].name = kw->name;
sigmatch_table[DETECT_TBLSIZE_IDX].desc = kw->desc;
sigmatch_table[DETECT_TBLSIZE_IDX].url = kw->url;
sigmatch_table[DETECT_TBLSIZE_IDX].flags = kw->flags;
sigmatch_table[DETECT_TBLSIZE_IDX].AppLayerTxMatch =
(int (*)(DetectEngineThreadCtx * det_ctx, Flow * f, uint8_t flags, void *alstate,
void *txv, const Signature *s, const SigMatchCtx *ctx)) kw->AppLayerTxMatch;
(int (*)(DetectEngineThreadCtx * det_ctx, Flow * f, uint8_t flags, void *alstate,
void *txv, const Signature *s, const SigMatchCtx *ctx)) kw->AppLayerTxMatch;
sigmatch_table[DETECT_TBLSIZE_IDX].Setup =
(int (*)(DetectEngineCtx * de, Signature * s, const char *raw)) kw->Setup;
(int (*)(DetectEngineCtx * de, Signature * s, const char *raw)) kw->Setup;
sigmatch_table[DETECT_TBLSIZE_IDX].Free = (void (*)(DetectEngineCtx * de, void *ptr)) kw->Free;
DETECT_TBLSIZE_IDX++;
return DETECT_TBLSIZE_IDX - 1;
}

int DetectHelperTransformRegister(const SCPluginTransformTableElmt *kw)
{
if (DETECT_TBLSIZE_IDX < DETECT_TBLSIZE) {
sigmatch_table[DETECT_TBLSIZE_IDX].name = kw->name;
sigmatch_table[DETECT_TBLSIZE_IDX].desc = kw->desc;
sigmatch_table[DETECT_TBLSIZE_IDX].flags = kw->flags;
sigmatch_table[DETECT_TBLSIZE_IDX].Transform = kw->Transform;
sigmatch_table[DETECT_TBLSIZE_IDX].Setup = kw->Setup;
sigmatch_table[DETECT_TBLSIZE_IDX].Free = kw->Free;
DETECT_TBLSIZE_IDX++;
return DETECT_TBLSIZE_IDX - 1;
}
return -1;
}

InspectionBuffer *DetectHelperGetMultiData(struct DetectEngineThreadCtx_ *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
const int list_id, uint32_t index,
bool (*GetBuf)(void *txv, const uint8_t flow_flags, uint32_t index, const uint8_t **buf, uint32_t *buf_len))
{
InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, index);
if (buffer == NULL) {
return NULL;
}
if (buffer->initialized) {
return buffer;
}

const uint8_t *data = NULL;
uint32_t data_len = 0;

if (!GetBuf(txv, flow_flags, index, &data, &data_len)) {
InspectionBufferSetupMultiEmpty(buffer);
return NULL;
}
InspectionBufferSetupMulti(buffer, transforms, data, data_len);
buffer->flags = DETECT_CI_FLAGS_SINGLE;
return buffer;
}

uint8_t * InspectionBufferPtr(InspectionBuffer *buf) {
return buf->inspect;
}

uint32_t InspectionBufferLength(InspectionBuffer *buf) {
return buf->inspect_len;
}
20 changes: 20 additions & 0 deletions src/detect-engine-helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,33 @@
#include "rust.h"

int DetectHelperKeywordRegister(const SCSigTableElmt *kw);

typedef struct SCPluginTransformTableElmt {
const char *name;
const char *desc;
uint16_t flags;
int (*Setup)(DetectEngineCtx *, Signature *, const char *);
void (*Free)(DetectEngineCtx *, void *);
void (*Transform)(InspectionBuffer *buffer, void *options);
} SCPluginTransformTableElmt;

int DetectHelperTransformRegister(const SCPluginTransformTableElmt *kw);
int DetectHelperBufferRegister(const char *name, AppProto alproto, bool toclient, bool toserver);

typedef bool (*SimpleGetTxBuffer)(void *, uint8_t, const uint8_t **, uint32_t *);
typedef bool (*MultiGetTxBuffer)(void *, uint8_t, uint32_t, const uint8_t **, uint32_t *);

InspectionBuffer *DetectHelperGetData(struct DetectEngineThreadCtx_ *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
const int list_id, SimpleGetTxBuffer GetBuf);
int DetectHelperBufferMpmRegister(const char *name, const char *desc, AppProto alproto,
bool toclient, bool toserver, InspectionBufferGetDataPtr GetData);

InspectionBuffer *DetectHelperGetMultiData(struct DetectEngineThreadCtx_ *det_ctx,
const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
const int list_id, uint32_t index, MultiGetTxBuffer GetBuf);

uint8_t * InspectionBufferPtr(InspectionBuffer *buf);
uint32_t InspectionBufferLength(InspectionBuffer *buf);

#endif /* SURICATA_DETECT_ENGINE_HELPER_H */
Loading
Loading