From 2d480bef72c63bf47b66da01dabb31c3ea701dcb Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Mon, 11 Nov 2024 07:21:03 +0100 Subject: [PATCH 1/3] app-layer: move ALPROTO_FAILED definition Because some alprotos will remain static and defined as a constant, such as ALPROTO_UNKNOWN=0, or ALPROTO_FAILED. The regular already used protocols keep for now their static identifier such as ALPROTO_SNMP, but this could be made more dynamic in a later commit. ALPROTO_FAILED was used in comparison and these needed to change to use either ALPROTO_MAX or use standard function AppProtoIsValid --- rust/src/core.rs | 3 +-- rust/src/ldap/ldap.rs | 4 ++-- rust/src/modbus/modbus.rs | 2 +- rust/src/ntp/ntp.rs | 2 +- rust/src/smb/smb.rs | 2 +- src/app-layer-detect-proto.c | 2 +- src/app-layer-protos.c | 2 +- src/app-layer-protos.h | 10 ++++++---- src/app-layer-register.c | 2 +- src/detect-engine-prefilter.c | 2 +- src/detect-engine.c | 2 +- src/detect-parse.c | 3 +-- src/util-profiling.c | 2 +- 13 files changed, 19 insertions(+), 19 deletions(-) diff --git a/rust/src/core.rs b/rust/src/core.rs index a628b300384a..8dafc73eec81 100644 --- a/rust/src/core.rs +++ b/rust/src/core.rs @@ -109,7 +109,7 @@ impl From for u8 { pub type AppProto = u16; pub const ALPROTO_UNKNOWN : AppProto = 0; -pub static mut ALPROTO_FAILED : AppProto = 0; // updated during init +pub const ALPROTO_FAILED : AppProto = 1; pub const IPPROTO_TCP : u8 = 6; pub const IPPROTO_UDP : u8 = 17; @@ -252,7 +252,6 @@ pub fn init_ffi(context: &'static SuricataContext) { unsafe { SC = Some(context); - ALPROTO_FAILED = StringToAppProto("failed\0".as_ptr()); } } diff --git a/rust/src/ldap/ldap.rs b/rust/src/ldap/ldap.rs index 267d1ed4c77b..1d6032f091f0 100644 --- a/rust/src/ldap/ldap.rs +++ b/rust/src/ldap/ldap.rs @@ -519,7 +519,7 @@ fn probe(input: &[u8], direction: Direction, rdir: *mut u8) -> AppProto { Ok((_, msg)) => { let ldap_msg = LdapMessage::from(msg); if ldap_msg.is_unknown() { - return unsafe { ALPROTO_FAILED }; + return ALPROTO_FAILED; } if direction == Direction::ToServer && !ldap_msg.is_request() { unsafe { @@ -537,7 +537,7 @@ fn probe(input: &[u8], direction: Direction, rdir: *mut u8) -> AppProto { return ALPROTO_UNKNOWN; } Err(_e) => { - return unsafe { ALPROTO_FAILED }; + return ALPROTO_FAILED; } } } diff --git a/rust/src/modbus/modbus.rs b/rust/src/modbus/modbus.rs index bbc191555696..56f9e6f1f567 100644 --- a/rust/src/modbus/modbus.rs +++ b/rust/src/modbus/modbus.rs @@ -289,7 +289,7 @@ pub extern "C" fn rs_modbus_probe( match MODBUS_PARSER.probe(slice, Direction::Unknown) { Status::Recognized => unsafe { ALPROTO_MODBUS }, Status::Incomplete => ALPROTO_UNKNOWN, - Status::Unrecognized => unsafe { ALPROTO_FAILED }, + Status::Unrecognized => ALPROTO_FAILED, } } diff --git a/rust/src/ntp/ntp.rs b/rust/src/ntp/ntp.rs index ae723bbb21cd..e17648c4c960 100644 --- a/rust/src/ntp/ntp.rs +++ b/rust/src/ntp/ntp.rs @@ -259,7 +259,7 @@ pub extern "C" fn ntp_probing_parser(_flow: *const Flow, return ALPROTO_UNKNOWN; }, Err(_) => { - return unsafe{ALPROTO_FAILED}; + return ALPROTO_FAILED; }, } } diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index 1b34d94462aa..6c7e7b67701b 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -2165,7 +2165,7 @@ fn smb_probe_tcp(flags: u8, slice: &[u8], rdir: *mut u8, begins: bool) -> AppPro } } SCLogDebug!("no smb"); - unsafe { return ALPROTO_FAILED; } + return ALPROTO_FAILED; } // probing confirmation parser diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index 52e1f2922c02..23630c76f5fc 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -694,7 +694,7 @@ static uint32_t AppLayerProtoDetectProbingParserGetMask(AppProto alproto) { SCEnter(); - if (!(alproto > ALPROTO_UNKNOWN && alproto < ALPROTO_FAILED)) { + if (!AppProtoIsValid(alproto)) { FatalError("Unknown protocol detected - %u", alproto); } diff --git a/src/app-layer-protos.c b/src/app-layer-protos.c index 03736554c7b6..999e4c52322e 100644 --- a/src/app-layer-protos.c +++ b/src/app-layer-protos.c @@ -32,6 +32,7 @@ typedef struct AppProtoStringTuple { const AppProtoStringTuple AppProtoStrings[ALPROTO_MAX] = { { ALPROTO_UNKNOWN, "unknown" }, + { ALPROTO_FAILED, "failed" }, { ALPROTO_HTTP1, "http1" }, { ALPROTO_FTP, "ftp" }, { ALPROTO_SMTP, "smtp" }, @@ -69,7 +70,6 @@ const AppProtoStringTuple AppProtoStrings[ALPROTO_MAX] = { { ALPROTO_BITTORRENT_DHT, "bittorrent-dht" }, { ALPROTO_POP3, "pop3" }, { ALPROTO_HTTP, "http" }, - { ALPROTO_FAILED, "failed" }, }; const char *AppProtoToString(AppProto alproto) diff --git a/src/app-layer-protos.h b/src/app-layer-protos.h index 10b8959772c4..6515571c68b7 100644 --- a/src/app-layer-protos.h +++ b/src/app-layer-protos.h @@ -27,6 +27,11 @@ enum AppProtoEnum { ALPROTO_UNKNOWN = 0, + /* used by the probing parser when alproto detection fails + * permanently for that particular stream */ + ALPROTO_FAILED = 1, + + // Beginning of real/normal protocols ALPROTO_HTTP1, ALPROTO_FTP, ALPROTO_SMTP, @@ -69,9 +74,6 @@ 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, /* keep last */ ALPROTO_MAX, }; @@ -82,7 +84,7 @@ typedef uint16_t AppProto; static inline bool AppProtoIsValid(AppProto a) { - return ((a > ALPROTO_UNKNOWN && a < ALPROTO_FAILED)); + return ((a > ALPROTO_FAILED && a < ALPROTO_MAX)); } // whether a signature AppProto matches a flow (or signature) AppProto diff --git a/src/app-layer-register.c b/src/app-layer-register.c index 1e4986b361ea..9a33a38eea76 100644 --- a/src/app-layer-register.c +++ b/src/app-layer-register.c @@ -101,7 +101,7 @@ int AppLayerRegisterParser(const struct AppLayerParser *p, AppProto alproto) if (p == NULL) FatalError("Call to %s with NULL pointer.", __FUNCTION__); - if (alproto == ALPROTO_UNKNOWN || alproto >= ALPROTO_FAILED) + if (!AppProtoIsValid(alproto)) FatalError("Unknown or invalid AppProto '%s'.", p->name); BUG_ON(strcmp(p->name, AppProtoToString(alproto)) != 0); diff --git a/src/detect-engine-prefilter.c b/src/detect-engine-prefilter.c index feff1251e4e2..e5bdbfd3d792 100644 --- a/src/detect-engine-prefilter.c +++ b/src/detect-engine-prefilter.c @@ -521,7 +521,7 @@ void PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh) /* per alproto to set is_last_for_progress per alproto because the inspect * loop skips over engines that are not the correct alproto */ - for (AppProto a = 1; a < ALPROTO_FAILED; a++) { + for (AppProto a = ALPROTO_FAILED + 1; a < ALPROTO_MAX; a++) { int last_tx_progress = 0; bool last_tx_progress_set = false; PrefilterEngine *prev_engine = NULL; diff --git a/src/detect-engine.c b/src/detect-engine.c index d77aa1a8db0a..d1429f19f3c0 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -181,7 +181,7 @@ static void AppLayerInspectEngineRegisterInternal(const char *name, AppProto alp } SCLogDebug("name %s id %d", name, sm_list); - if ((alproto >= ALPROTO_FAILED) || (!(dir == SIG_FLAG_TOSERVER || dir == SIG_FLAG_TOCLIENT)) || + if ((alproto == ALPROTO_FAILED) || (!(dir == SIG_FLAG_TOSERVER || dir == SIG_FLAG_TOCLIENT)) || (sm_list < DETECT_SM_LIST_MATCH) || (sm_list >= SHRT_MAX) || (progress < 0 || progress >= SHRT_MAX) || (Callback == NULL)) { SCLogError("Invalid arguments"); diff --git a/src/detect-parse.c b/src/detect-parse.c index 3b03dfb92b36..90d3b5706d3d 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -1737,8 +1737,7 @@ int DetectSignatureAddTransform(Signature *s, int transform, void *options) int DetectSignatureSetAppProto(Signature *s, AppProto alproto) { - if (alproto == ALPROTO_UNKNOWN || - alproto >= ALPROTO_FAILED) { + if (!AppProtoIsValid(alproto)) { SCLogError("invalid alproto %u", alproto); return -1; } diff --git a/src/util-profiling.c b/src/util-profiling.c index 20fcc7f98016..73e0c8489057 100644 --- a/src/util-profiling.c +++ b/src/util-profiling.c @@ -820,7 +820,7 @@ void SCProfilingPrintPacketProfile(Packet *p) /* count ticks for app layer */ uint64_t app_total = 0; - for (AppProto i = 1; i < ALPROTO_FAILED; i++) { + for (AppProto i = 0; i < ALPROTO_MAX; i++) { const PktProfilingAppData *pdt = &p->profile->app[i]; if (p->proto == IPPROTO_TCP) { From 4e001c22f75c5a7615beaff5f8909ace799e85fa Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Mon, 11 Nov 2024 07:26:11 +0100 Subject: [PATCH 2/3] app-layer: make number of alprotos dynamic Ticket: 5053 The names are now dynamically registered at runtime. The AppProto alproto enum identifiers are still static for now. This is the final step before app-layer plugins. --- scripts/setup-app-layer.py | 2 +- src/app-layer-detect-proto.c | 40 ++++++------ src/app-layer-frames.c | 8 +-- src/app-layer-parser.c | 16 ++--- src/app-layer-protos.c | 76 ++++++++++------------- src/app-layer-protos.h | 7 ++- src/app-layer.c | 59 +++++++++++++++--- src/detect-engine-build.c | 7 ++- src/detect-engine-mpm.c | 2 +- src/detect-engine-prefilter.c | 2 +- src/detect-file-data.c | 4 +- src/output-tx.c | 14 ++--- src/output.c | 4 +- src/runmodes.c | 8 +-- src/tests/fuzz/fuzz_applayerparserparse.c | 2 +- src/util-profiling.c | 16 ++--- src/util-profiling.h | 12 ++-- 17 files changed, 158 insertions(+), 121 deletions(-) diff --git a/scripts/setup-app-layer.py b/scripts/setup-app-layer.py index bb3d23e83944..f94e68ae7d7e 100755 --- a/scripts/setup-app-layer.py +++ b/scripts/setup-app-layer.py @@ -129,7 +129,7 @@ def patch_app_layer_protos_h(protoname): open(filename, "w").write(output.getvalue()) def patch_app_layer_protos_c(protoname): - filename = "src/app-layer-protos.c" + filename = "src/app-layer.c" print("Patching %s." % (filename)) output = io.StringIO() diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index 23630c76f5fc..76061c25dbd2 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -292,7 +292,7 @@ static inline int PMGetProtoInspect(AppLayerProtoDetectThreadCtx *tctx, } /* alproto bit field */ - uint8_t pm_results_bf[(ALPROTO_MAX / 8) + 1]; + uint8_t pm_results_bf[(AlprotoMax / 8) + 1]; memset(pm_results_bf, 0, sizeof(pm_results_bf)); /* loop through unique pattern id's. Can't use search_cnt here, @@ -324,7 +324,7 @@ static inline int PMGetProtoInspect(AppLayerProtoDetectThreadCtx *tctx, /** \internal * \brief Run Pattern Sigs against buffer * \param direction direction for the patterns - * \param pm_results[out] AppProto array of size ALPROTO_MAX */ + * \param pm_results[out] AppProto array of size AlprotoMax */ static AppProto AppLayerProtoDetectPMGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f, const uint8_t *buf, uint32_t buflen, uint8_t flags, AppProto *pm_results, bool *rflow) { @@ -804,7 +804,7 @@ static AppLayerProtoDetectProbingParserElement *AppLayerProtoDetectProbingParser "register the probing parser. min_depth >= max_depth"); goto error; } - if (alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_MAX) { + if (alproto <= ALPROTO_UNKNOWN || alproto >= AlprotoMax) { SCLogError("Invalid arguments sent to register " "the probing parser. Invalid alproto - %d", alproto); @@ -1411,7 +1411,7 @@ AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f AppProto pm_alproto = ALPROTO_UNKNOWN; if (!FLOW_IS_PM_DONE(f, flags)) { - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; uint16_t pm_matches = AppLayerProtoDetectPMGetProto( tctx, f, buf, buflen, flags, pm_results, reverse_flow); if (pm_matches > 0) { @@ -1725,12 +1725,12 @@ int AppLayerProtoDetectSetup(void) } } - alpd_ctx.alproto_names = SCCalloc(ALPROTO_MAX, sizeof(char *)); + alpd_ctx.alproto_names = SCCalloc(AlprotoMax, sizeof(char *)); if (unlikely(alpd_ctx.alproto_names == NULL)) { FatalError("Unable to alloc alproto_names."); } // to realloc when dynamic protos are added - alpd_ctx.expectation_proto = SCCalloc(ALPROTO_MAX, sizeof(uint8_t)); + alpd_ctx.expectation_proto = SCCalloc(AlprotoMax, sizeof(uint8_t)); if (unlikely(alpd_ctx.expectation_proto == NULL)) { FatalError("Unable to alloc expectation_proto."); } @@ -2090,7 +2090,7 @@ AppProto AppLayerProtoDetectGetProtoByName(const char *alproto_name) AppProto a; AppProto b = StringToAppProto(alproto_name); - for (a = 0; a < ALPROTO_MAX; a++) { + for (a = 0; a < AlprotoMax; a++) { if (alpd_ctx.alproto_names[a] != NULL && AppProtoEquals(b, a)) { // That means return HTTP_ANY if HTTP1 or HTTP2 is enabled SCReturnCT(b, "AppProto"); @@ -2121,11 +2121,11 @@ void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos) { SCEnter(); - memset(alprotos, 0, ALPROTO_MAX * sizeof(AppProto)); + memset(alprotos, 0, AlprotoMax * sizeof(AppProto)); int alproto; - for (alproto = 0; alproto != ALPROTO_MAX; alproto++) { + for (alproto = 0; alproto != AlprotoMax; alproto++) { if (alpd_ctx.alproto_names[alproto] != NULL) alprotos[alproto] = 1; } @@ -2229,7 +2229,7 @@ static int AppLayerProtoDetectTest03(void) AppLayerProtoDetectSetup(); uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n"; - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; memset(pm_results, 0, sizeof(pm_results)); Flow f; memset(&f, 0x00, sizeof(f)); @@ -2276,7 +2276,7 @@ static int AppLayerProtoDetectTest04(void) uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\n"; Flow f; memset(&f, 0x00, sizeof(f)); - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; memset(pm_results, 0, sizeof(pm_results)); f.protomap = FlowGetProtoMapping(IPPROTO_TCP); @@ -2314,7 +2314,7 @@ static int AppLayerProtoDetectTest05(void) AppLayerProtoDetectSetup(); uint8_t l7data[] = "HTTP/1.1 200 OK\r\nServer: Apache/1.0\r\n\r\nBlahblah"; - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; memset(pm_results, 0, sizeof(pm_results)); Flow f; memset(&f, 0x00, sizeof(f)); @@ -2358,7 +2358,7 @@ static int AppLayerProtoDetectTest06(void) AppLayerProtoDetectSetup(); uint8_t l7data[] = "220 Welcome to the OISF FTP server\r\n"; - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; memset(pm_results, 0, sizeof(pm_results)); Flow f; memset(&f, 0x00, sizeof(f)); @@ -2404,7 +2404,7 @@ static int AppLayerProtoDetectTest07(void) Flow f; memset(&f, 0x00, sizeof(f)); f.protomap = FlowGetProtoMapping(IPPROTO_TCP); - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; memset(pm_results, 0, sizeof(pm_results)); const char *buf = "HTTP"; @@ -2458,7 +2458,7 @@ static int AppLayerProtoDetectTest08(void) 0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x00 }; - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; memset(pm_results, 0, sizeof(pm_results)); Flow f; memset(&f, 0x00, sizeof(f)); @@ -2513,7 +2513,7 @@ static int AppLayerProtoDetectTest09(void) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02 }; - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; memset(pm_results, 0, sizeof(pm_results)); Flow f; memset(&f, 0x00, sizeof(f)); @@ -2563,7 +2563,7 @@ static int AppLayerProtoDetectTest10(void) 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 }; - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; memset(pm_results, 0, sizeof(pm_results)); Flow f; memset(&f, 0x00, sizeof(f)); @@ -2608,7 +2608,7 @@ static int AppLayerProtoDetectTest11(void) uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n"; uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n"; - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; memset(pm_results, 0, sizeof(pm_results)); Flow f; memset(&f, 0x00, sizeof(f)); @@ -2733,7 +2733,7 @@ static int AppLayerProtoDetectTest13(void) uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n"; uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n"; - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; Flow f; memset(&f, 0x00, sizeof(f)); @@ -2804,7 +2804,7 @@ static int AppLayerProtoDetectTest14(void) uint8_t l7data[] = "CONNECT www.ssllabs.com:443 HTTP/1.0\r\n"; uint8_t l7data_resp[] = "HTTP/1.1 405 Method Not Allowed\r\n"; - AppProto pm_results[ALPROTO_MAX]; + AppProto pm_results[AlprotoMax]; uint32_t cnt; Flow f; memset(&f, 0x00, sizeof(f)); diff --git a/src/app-layer-frames.c b/src/app-layer-frames.c index 3fa4c345474a..0ba738f8b19f 100644 --- a/src/app-layer-frames.c +++ b/src/app-layer-frames.c @@ -33,16 +33,16 @@ struct FrameConfig { SC_ATOMIC_DECLARE(uint64_t, types); }; -/* This array should be allocated to contain ALPROTO_MAX protocols. */ +/* This array should be allocated to contain AlprotoMax protocols. */ static struct FrameConfig *frame_config; void FrameConfigInit(void) { - frame_config = SCCalloc(ALPROTO_MAX, sizeof(struct FrameConfig)); + frame_config = SCCalloc(AlprotoMax, sizeof(struct FrameConfig)); if (unlikely(frame_config == NULL)) { FatalError("Unable to alloc frame_config."); } - for (AppProto p = 0; p < ALPROTO_MAX; p++) { + for (AppProto p = 0; p < AlprotoMax; p++) { SC_ATOMIC_INIT(frame_config[p].types); } } @@ -55,7 +55,7 @@ void FrameConfigDeInit(void) void FrameConfigEnableAll(void) { const uint64_t bits = UINT64_MAX; - for (AppProto p = 0; p < ALPROTO_MAX; p++) { + for (AppProto p = 0; p < AlprotoMax; p++) { struct FrameConfig *fc = &frame_config[p]; SC_ATOMIC_OR(fc->types, bits); } diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index d6a23d5390ad..010c40a04c1e 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -249,8 +249,8 @@ int AppLayerParserSetup(void) { SCEnter(); // initial allocation that will later be grown using realloc, - // when new protocols register themselves and make ALPROTO_MAX grow - alp_ctx.ctxs = SCCalloc(ALPROTO_MAX, sizeof(AppLayerParserProtoCtx[FLOW_PROTO_MAX])); + // when new protocols register themselves and make AlprotoMax grow + alp_ctx.ctxs = SCCalloc(AlprotoMax, sizeof(AppLayerParserProtoCtx[FLOW_PROTO_MAX])); if (unlikely(alp_ctx.ctxs == NULL)) { FatalError("Unable to alloc alp_ctx.ctxs."); } @@ -261,7 +261,7 @@ void AppLayerParserPostStreamSetup(void) { /* lets set a default value for stream_depth */ for (int flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) { - for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (AppProto alproto = 0; alproto < AlprotoMax; alproto++) { if (!(alp_ctx.ctxs[alproto][flow_proto].internal_flags & APP_LAYER_PARSER_INT_STREAM_DEPTH_SET)) { alp_ctx.ctxs[alproto][flow_proto].stream_depth = stream_config.reassembly_depth; @@ -290,14 +290,14 @@ AppLayerParserThreadCtx *AppLayerParserThreadCtxAlloc(void) if (tctx == NULL) goto end; - tctx->alproto_local_storage = SCCalloc(ALPROTO_MAX, sizeof(void *[FLOW_PROTO_MAX])); + tctx->alproto_local_storage = SCCalloc(AlprotoMax, sizeof(void *[FLOW_PROTO_MAX])); if (unlikely(tctx->alproto_local_storage == NULL)) { SCFree(tctx); tctx = NULL; goto end; } for (uint8_t flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) { - for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (AppProto alproto = 0; alproto < AlprotoMax; alproto++) { uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto); tctx->alproto_local_storage[alproto][flow_proto] = @@ -314,7 +314,7 @@ void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx) SCEnter(); for (uint8_t flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) { - for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (AppProto alproto = 0; alproto < AlprotoMax; alproto++) { uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto); AppLayerParserDestroyProtocolParserLocalStorage( @@ -1695,7 +1695,7 @@ static void ValidateParser(AppProto alproto) static void ValidateParsers(void) { AppProto p = 0; - for ( ; p < ALPROTO_MAX; p++) { + for (; p < AlprotoMax; p++) { ValidateParser(p); } } @@ -1795,7 +1795,7 @@ void AppLayerParserRegisterUnittests(void) AppLayerParserProtoCtx *ctx; for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) { - for (alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (alproto = 0; alproto < AlprotoMax; alproto++) { ctx = &alp_ctx.ctxs[alproto][ip]; if (ctx->RegisterUnittests == NULL) continue; diff --git a/src/app-layer-protos.c b/src/app-layer-protos.c index 999e4c52322e..e97d94ce12af 100644 --- a/src/app-layer-protos.c +++ b/src/app-layer-protos.c @@ -24,53 +24,18 @@ #include "suricata-common.h" #include "app-layer-protos.h" +#include "rust.h" + +AppProto AlprotoMax = ALPROTO_MAX_STATIC + 1; +#define ARRAY_CAP_STEP 16 +AppProto AppProtoStringsCap = ALPROTO_MAX_STATIC + 1; typedef struct AppProtoStringTuple { AppProto alproto; const char *str; } AppProtoStringTuple; -const AppProtoStringTuple AppProtoStrings[ALPROTO_MAX] = { - { ALPROTO_UNKNOWN, "unknown" }, - { ALPROTO_FAILED, "failed" }, - { ALPROTO_HTTP1, "http1" }, - { ALPROTO_FTP, "ftp" }, - { ALPROTO_SMTP, "smtp" }, - { ALPROTO_TLS, "tls" }, - { ALPROTO_SSH, "ssh" }, - { ALPROTO_IMAP, "imap" }, - { ALPROTO_JABBER, "jabber" }, - { ALPROTO_SMB, "smb" }, - { ALPROTO_DCERPC, "dcerpc" }, - { ALPROTO_IRC, "irc" }, - { ALPROTO_DNS, "dns" }, - { ALPROTO_MODBUS, "modbus" }, - { ALPROTO_ENIP, "enip" }, - { ALPROTO_DNP3, "dnp3" }, - { ALPROTO_NFS, "nfs" }, - { ALPROTO_NTP, "ntp" }, - { ALPROTO_FTPDATA, "ftp-data" }, - { ALPROTO_TFTP, "tftp" }, - { ALPROTO_IKE, "ike" }, - { ALPROTO_KRB5, "krb5" }, - { ALPROTO_QUIC, "quic" }, - { ALPROTO_DHCP, "dhcp" }, - { ALPROTO_SNMP, "snmp" }, - { ALPROTO_SIP, "sip" }, - { ALPROTO_RFB, "rfb" }, - { ALPROTO_MQTT, "mqtt" }, - { ALPROTO_PGSQL, "pgsql" }, - { ALPROTO_TELNET, "telnet" }, - { ALPROTO_WEBSOCKET, "websocket" }, - { ALPROTO_LDAP, "ldap" }, - { ALPROTO_DOH2, "doh2" }, - { ALPROTO_TEMPLATE, "template" }, - { ALPROTO_RDP, "rdp" }, - { ALPROTO_HTTP2, "http2" }, - { ALPROTO_BITTORRENT_DHT, "bittorrent-dht" }, - { ALPROTO_POP3, "pop3" }, - { ALPROTO_HTTP, "http" }, -}; +AppProtoStringTuple *AppProtoStrings = NULL; const char *AppProtoToString(AppProto alproto) { @@ -84,7 +49,7 @@ const char *AppProtoToString(AppProto alproto) proto_name = "http_any"; break; default: - if (alproto < ARRAY_SIZE(AppProtoStrings)) { + if (alproto < AlprotoMax) { BUG_ON(AppProtoStrings[alproto].alproto != alproto); proto_name = AppProtoStrings[alproto].str; } @@ -98,10 +63,35 @@ AppProto StringToAppProto(const char *proto_name) return ALPROTO_UNKNOWN; // We could use a Multi Pattern Matcher - for (size_t i = 0; i < ARRAY_SIZE(AppProtoStrings); i++) { + for (size_t i = 0; i < AlprotoMax; i++) { if (strcmp(proto_name, AppProtoStrings[i].str) == 0) return AppProtoStrings[i].alproto; } return ALPROTO_UNKNOWN; } + +void AppProtoRegisterProtoString(AppProto alproto, const char *proto_name) +{ + if (alproto < ALPROTO_MAX_STATIC) { + if (AppProtoStrings == NULL) { + AppProtoStrings = SCCalloc(AppProtoStringsCap, sizeof(AppProtoStringTuple)); + if (AppProtoStrings == NULL) { + FatalError("Unable to allocate AppProtoStrings"); + } + } + } else if (alproto + 1 == AlprotoMax) { + if (AlprotoMax == AppProtoStringsCap) { + void *tmp = SCRealloc(AppProtoStrings, + sizeof(AppProtoStringTuple) * (AppProtoStringsCap + ARRAY_CAP_STEP)); + if (tmp == NULL) { + FatalError("Unable to reallocate AppProtoStrings"); + } + AppProtoStringsCap += ARRAY_CAP_STEP; + AppProtoStrings = tmp; + } + AlprotoMax++; + } + AppProtoStrings[alproto].str = proto_name; + AppProtoStrings[alproto].alproto = alproto; +} diff --git a/src/app-layer-protos.h b/src/app-layer-protos.h index 6515571c68b7..79942c8f6b70 100644 --- a/src/app-layer-protos.h +++ b/src/app-layer-protos.h @@ -75,16 +75,17 @@ enum AppProtoEnum { ALPROTO_HTTP, /* keep last */ - ALPROTO_MAX, + ALPROTO_MAX_STATIC, }; // 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 AlprotoMax; static inline bool AppProtoIsValid(AppProto a) { - return ((a > ALPROTO_FAILED && a < ALPROTO_MAX)); + return ((a > ALPROTO_FAILED && a < AlprotoMax)); } // whether a signature AppProto matches a flow (or signature) AppProto @@ -172,4 +173,6 @@ const char *AppProtoToString(AppProto alproto); */ AppProto StringToAppProto(const char *proto_name); +void AppProtoRegisterProtoString(AppProto alproto, const char *proto_name); + #endif /* SURICATA_APP_LAYER_PROTOS_H */ diff --git a/src/app-layer.c b/src/app-layer.c index 3f33a96e64dc..6009a51deacf 100644 --- a/src/app-layer.c +++ b/src/app-layer.c @@ -1015,12 +1015,12 @@ void AppLayerListSupportedProtocols(void) SCEnter(); AppProto alproto; - AppProto alprotos[ALPROTO_MAX]; + AppProto alprotos[AlprotoMax]; AppLayerProtoDetectSupportedAppProtocols(alprotos); printf("=========Supported App Layer Protocols=========\n"); - for (alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (alproto = 0; alproto < AlprotoMax; alproto++) { if (alprotos[alproto] == 1) printf("%s\n", AppLayerGetProtoName(alproto)); } @@ -1029,11 +1029,54 @@ void AppLayerListSupportedProtocols(void) } /***** Setup/General Registration *****/ +static void AppLayerNamesSetup(void) +{ + AppProtoRegisterProtoString(ALPROTO_UNKNOWN, "unknown"); + AppProtoRegisterProtoString(ALPROTO_FAILED, "failed"); + AppProtoRegisterProtoString(ALPROTO_HTTP1, "http1"); + AppProtoRegisterProtoString(ALPROTO_FTP, "ftp"); + AppProtoRegisterProtoString(ALPROTO_SMTP, "smtp"); + AppProtoRegisterProtoString(ALPROTO_TLS, "tls"); + AppProtoRegisterProtoString(ALPROTO_SSH, "ssh"); + AppProtoRegisterProtoString(ALPROTO_IMAP, "imap"); + AppProtoRegisterProtoString(ALPROTO_JABBER, "jabber"); + AppProtoRegisterProtoString(ALPROTO_SMB, "smb"); + AppProtoRegisterProtoString(ALPROTO_DCERPC, "dcerpc"); + AppProtoRegisterProtoString(ALPROTO_IRC, "irc"); + AppProtoRegisterProtoString(ALPROTO_DNS, "dns"); + AppProtoRegisterProtoString(ALPROTO_MODBUS, "modbus"); + AppProtoRegisterProtoString(ALPROTO_ENIP, "enip"); + AppProtoRegisterProtoString(ALPROTO_DNP3, "dnp3"); + AppProtoRegisterProtoString(ALPROTO_NFS, "nfs"); + AppProtoRegisterProtoString(ALPROTO_NTP, "ntp"); + AppProtoRegisterProtoString(ALPROTO_FTPDATA, "ftp-data"); + AppProtoRegisterProtoString(ALPROTO_TFTP, "tftp"); + AppProtoRegisterProtoString(ALPROTO_IKE, "ike"); + AppProtoRegisterProtoString(ALPROTO_KRB5, "krb5"); + AppProtoRegisterProtoString(ALPROTO_QUIC, "quic"); + AppProtoRegisterProtoString(ALPROTO_DHCP, "dhcp"); + AppProtoRegisterProtoString(ALPROTO_SNMP, "snmp"); + AppProtoRegisterProtoString(ALPROTO_SIP, "sip"); + AppProtoRegisterProtoString(ALPROTO_RFB, "rfb"); + AppProtoRegisterProtoString(ALPROTO_MQTT, "mqtt"); + AppProtoRegisterProtoString(ALPROTO_PGSQL, "pgsql"); + AppProtoRegisterProtoString(ALPROTO_TELNET, "telnet"); + AppProtoRegisterProtoString(ALPROTO_WEBSOCKET, "websocket"); + AppProtoRegisterProtoString(ALPROTO_LDAP, "ldap"); + AppProtoRegisterProtoString(ALPROTO_DOH2, "doh2"); + AppProtoRegisterProtoString(ALPROTO_TEMPLATE, "template"); + AppProtoRegisterProtoString(ALPROTO_RDP, "rdp"); + AppProtoRegisterProtoString(ALPROTO_HTTP2, "http2"); + AppProtoRegisterProtoString(ALPROTO_BITTORRENT_DHT, "bittorrent-dht"); + AppProtoRegisterProtoString(ALPROTO_POP3, "pop3"); + AppProtoRegisterProtoString(ALPROTO_HTTP, "http"); +} int AppLayerSetup(void) { SCEnter(); + AppLayerNamesSetup(); AppLayerProtoDetectSetup(); AppLayerParserSetup(); @@ -1152,16 +1195,16 @@ static void AppLayerSetupExceptionPolicyPerProtoCounters( void AppLayerSetupCounters(void) { const uint8_t ipprotos[] = { IPPROTO_TCP, IPPROTO_UDP }; - AppProto alprotos[ALPROTO_MAX]; + AppProto alprotos[AlprotoMax]; const char *str = "app_layer.flow."; const char *estr = "app_layer.error."; applayer_counter_names = - SCCalloc(ALPROTO_MAX, sizeof(AppLayerCounterNames[FLOW_PROTO_APPLAYER_MAX])); + SCCalloc(AlprotoMax, sizeof(AppLayerCounterNames[FLOW_PROTO_APPLAYER_MAX])); if (unlikely(applayer_counter_names == NULL)) { FatalError("Unable to alloc applayer_counter_names."); } - applayer_counters = SCCalloc(ALPROTO_MAX, sizeof(AppLayerCounters[FLOW_PROTO_APPLAYER_MAX])); + applayer_counters = SCCalloc(AlprotoMax, sizeof(AppLayerCounters[FLOW_PROTO_APPLAYER_MAX])); if (unlikely(applayer_counters == NULL)) { FatalError("Unable to alloc applayer_counters."); } @@ -1186,7 +1229,7 @@ void AppLayerSetupCounters(void) const char *ipproto_suffix = (ipproto == IPPROTO_TCP) ? "_tcp" : "_udp"; uint8_t ipprotos_all[256 / 8]; - for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (AppProto alproto = 0; alproto < AlprotoMax; alproto++) { if (alprotos[alproto] == 1) { const char *tx_str = "app_layer.tx."; const char *alproto_str = AppLayerGetProtoName(alproto); @@ -1261,7 +1304,7 @@ void AppLayerSetupCounters(void) void AppLayerRegisterThreadCounters(ThreadVars *tv) { const uint8_t ipprotos[] = { IPPROTO_TCP, IPPROTO_UDP }; - AppProto alprotos[ALPROTO_MAX]; + AppProto alprotos[AlprotoMax]; AppLayerProtoDetectSupportedAppProtocols(alprotos); /* We don't log stats counters if exception policy is `ignore`/`not set` */ @@ -1279,7 +1322,7 @@ void AppLayerRegisterThreadCounters(ThreadVars *tv) const uint8_t ipproto = ipprotos[p]; const uint8_t ipproto_map = FlowGetProtoMapping(ipproto); - for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (AppProto alproto = 0; alproto < AlprotoMax; alproto++) { if (alprotos[alproto] == 1) { applayer_counters[alproto][ipproto_map].counter_id = StatsRegisterCounter(applayer_counter_names[alproto][ipproto_map].name, tv); diff --git a/src/detect-engine-build.c b/src/detect-engine-build.c index 6255ab49838b..4b93562d3ded 100644 --- a/src/detect-engine-build.c +++ b/src/detect-engine-build.c @@ -625,10 +625,11 @@ static json_t *RulesGroupPrintSghStats(const DetectEngineCtx *de_ctx, const SigG } mpm_stats[max_buffer_type_id]; memset(mpm_stats, 0x00, sizeof(mpm_stats)); - uint32_t alstats[ALPROTO_MAX] = {0}; + uint32_t alstats[AlprotoMax]; + memset(alstats, 0, AlprotoMax * sizeof(uint32_t)); uint32_t mpm_sizes[max_buffer_type_id][256]; memset(mpm_sizes, 0, sizeof(mpm_sizes)); - uint32_t alproto_mpm_bufs[ALPROTO_MAX][max_buffer_type_id]; + uint32_t alproto_mpm_bufs[AlprotoMax][max_buffer_type_id]; memset(alproto_mpm_bufs, 0, sizeof(alproto_mpm_bufs)); DEBUG_VALIDATE_BUG_ON(sgh->init == NULL); @@ -790,7 +791,7 @@ static json_t *RulesGroupPrintSghStats(const DetectEngineCtx *de_ctx, const SigG json_object_set_new(types, "any5", json_integer(any5_cnt)); json_object_set_new(stats, "types", types); - for (AppProto i = 0; i < ALPROTO_MAX; i++) { + for (AppProto i = 0; i < AlprotoMax; i++) { if (alstats[i] > 0) { json_t *app = json_object(); json_object_set_new(app, "total", json_integer(alstats[i])); diff --git a/src/detect-engine-mpm.c b/src/detect-engine-mpm.c index 1c9984ea9541..b1599cd21d53 100644 --- a/src/detect-engine-mpm.c +++ b/src/detect-engine-mpm.c @@ -1975,7 +1975,7 @@ static void PrepareMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh) const int max_buffer_id = de_ctx->buffer_type_id + 1; const uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1; - AppProto engines[max_buffer_id][ALPROTO_MAX]; + AppProto engines[max_buffer_id][AlprotoMax]; memset(engines, 0, sizeof(engines)); int engines_idx[max_buffer_id]; memset(engines_idx, 0, sizeof(engines_idx)); diff --git a/src/detect-engine-prefilter.c b/src/detect-engine-prefilter.c index e5bdbfd3d792..fef89e7c66bf 100644 --- a/src/detect-engine-prefilter.c +++ b/src/detect-engine-prefilter.c @@ -521,7 +521,7 @@ void PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh) /* per alproto to set is_last_for_progress per alproto because the inspect * loop skips over engines that are not the correct alproto */ - for (AppProto a = ALPROTO_FAILED + 1; a < ALPROTO_MAX; a++) { + for (AppProto a = ALPROTO_FAILED + 1; a < AlprotoMax; a++) { int last_tx_progress = 0; bool last_tx_progress_set = false; PrefilterEngine *prev_engine = NULL; diff --git a/src/detect-file-data.c b/src/detect-file-data.c index d976b51c00b4..b584fec76d2b 100644 --- a/src/detect-file-data.c +++ b/src/detect-file-data.c @@ -97,11 +97,11 @@ static void SetupDetectEngineConfig(DetectEngineCtx *de_ctx) { if (de_ctx->filedata_config) return; - de_ctx->filedata_config = SCMalloc(ALPROTO_MAX * sizeof(DetectFileDataCfg)); + de_ctx->filedata_config = SCMalloc(AlprotoMax * sizeof(DetectFileDataCfg)); if (unlikely(de_ctx->filedata_config == NULL)) return; /* initialize default */ - for (AppProto i = 0; i < ALPROTO_MAX; i++) { + for (AppProto i = 0; i < AlprotoMax; i++) { de_ctx->filedata_config[i].content_limit = FILEDATA_CONTENT_LIMIT; de_ctx->filedata_config[i].content_inspect_min_size = FILEDATA_CONTENT_INSPECT_MIN_SIZE; } diff --git a/src/output-tx.c b/src/output-tx.c index 8e37b1b5f2e2..07629793b356 100644 --- a/src/output-tx.c +++ b/src/output-tx.c @@ -67,7 +67,7 @@ int SCOutputRegisterTxLogger(LoggerId id, const char *name, AppProto alproto, Tx ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit) { if (list == NULL) { - list = SCCalloc(ALPROTO_MAX, sizeof(OutputTxLogger *)); + list = SCCalloc(AlprotoMax, sizeof(OutputTxLogger *)); if (unlikely(list == NULL)) { SCLogError("Failed to allocate OutputTx list"); return -1; @@ -547,14 +547,14 @@ static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data) static TmEcode OutputTxLogThreadInit(ThreadVars *tv, const void *_initdata, void **data) { OutputTxLoggerThreadData *td = - SCCalloc(1, sizeof(*td) + ALPROTO_MAX * sizeof(OutputLoggerThreadStore *)); + SCCalloc(1, sizeof(*td) + AlprotoMax * sizeof(OutputLoggerThreadStore *)); if (td == NULL) return TM_ECODE_FAILED; *data = (void *)td; SCLogDebug("OutputTxLogThreadInit happy (*data %p)", *data); - for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (AppProto alproto = 0; alproto < AlprotoMax; alproto++) { OutputTxLogger *logger = list[alproto]; while (logger) { if (logger->ThreadInit) { @@ -603,7 +603,7 @@ static TmEcode OutputTxLogThreadDeinit(ThreadVars *tv, void *thread_data) { OutputTxLoggerThreadData *op_thread_data = (OutputTxLoggerThreadData *)thread_data; - for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (AppProto alproto = 0; alproto < AlprotoMax; alproto++) { OutputLoggerThreadStore *store = op_thread_data->store[alproto]; OutputTxLogger *logger = list[alproto]; @@ -633,7 +633,7 @@ static TmEcode OutputTxLogThreadDeinit(ThreadVars *tv, void *thread_data) static uint32_t OutputTxLoggerGetActiveCount(void) { uint32_t cnt = 0; - for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (AppProto alproto = 0; alproto < AlprotoMax; alproto++) { for (OutputTxLogger *p = list[alproto]; p != NULL; p = p->next) { cnt++; } @@ -655,7 +655,7 @@ static uint32_t OutputTxLoggerGetActiveCount(void) void OutputTxLoggerRegister (void) { BUG_ON(list); - list = SCCalloc(ALPROTO_MAX, sizeof(OutputTxLogger *)); + list = SCCalloc(AlprotoMax, sizeof(OutputTxLogger *)); if (unlikely(list == NULL)) { FatalError("Failed to allocate OutputTx list"); } @@ -669,7 +669,7 @@ void OutputTxShutdown(void) if (list == NULL) { return; } - for (AppProto alproto = 0; alproto < ALPROTO_MAX; alproto++) { + for (AppProto alproto = 0; alproto < AlprotoMax; alproto++) { OutputTxLogger *logger = list[alproto]; while (logger) { OutputTxLogger *next_logger = logger->next; diff --git a/src/output.c b/src/output.c index b99897509c0f..ef9e396e3c03 100644 --- a/src/output.c +++ b/src/output.c @@ -835,7 +835,7 @@ void TmModuleLoggerRegister(void) EveJsonSimpleAppLayerLogger *SCEveJsonSimpleGetLogger(AppProto alproto) { - if (alproto < ALPROTO_MAX) { + if (alproto < AlprotoMax) { return &simple_json_applayer_loggers[alproto]; } return NULL; @@ -857,7 +857,7 @@ static void RegisterSimpleJsonApplayerLogger( */ void OutputRegisterRootLoggers(void) { - simple_json_applayer_loggers = SCCalloc(ALPROTO_MAX, sizeof(EveJsonSimpleAppLayerLogger)); + simple_json_applayer_loggers = SCCalloc(AlprotoMax, sizeof(EveJsonSimpleAppLayerLogger)); if (unlikely(simple_json_applayer_loggers == NULL)) { FatalError("Failed to allocate simple_json_applayer_loggers"); } diff --git a/src/runmodes.c b/src/runmodes.c index 006199bb94c6..af5215a3bb62 100644 --- a/src/runmodes.c +++ b/src/runmodes.c @@ -757,8 +757,9 @@ void RunModeInitializeOutputs(void) char tls_log_enabled = 0; char tls_store_present = 0; - // ALPROTO_MAX is set to its final value - LoggerId logger_bits[ALPROTO_MAX] = { 0 }; + // AlprotoMax is set to its final value + LoggerId logger_bits[AlprotoMax]; + memset(logger_bits, 0, AlprotoMax * sizeof(LoggerId)); TAILQ_FOREACH(output, &outputs->head, next) { output_config = ConfNodeLookupChild(output, output->val); @@ -884,7 +885,7 @@ void RunModeInitializeOutputs(void) /* register the logger bits to the app-layer */ AppProto a; - for (a = 0; a < ALPROTO_MAX; a++) { + for (a = 0; a < AlprotoMax; a++) { if (AppLayerParserSupportsFiles(IPPROTO_TCP, a)) { if (g_file_logger_enabled) logger_bits[a] |= BIT_U32(LOGGER_FILE); @@ -919,7 +920,6 @@ void RunModeInitializeOutputs(void) AppLayerParserRegisterLoggerBits(IPPROTO_TCP, a, logger_bits[a]); if (udp) AppLayerParserRegisterLoggerBits(IPPROTO_UDP, a, logger_bits[a]); - } OutputSetupActiveLoggers(); } diff --git a/src/tests/fuzz/fuzz_applayerparserparse.c b/src/tests/fuzz/fuzz_applayerparserparse.c index 5e71243e047f..bd2ecfae6ddb 100644 --- a/src/tests/fuzz/fuzz_applayerparserparse.c +++ b/src/tests/fuzz/fuzz_applayerparserparse.c @@ -96,7 +96,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) return 0; } - if (data[0] >= ALPROTO_MAX) { + if (data[0] >= AlprotoMax) { return 0; } //no UTHBuildFlow to have storage diff --git a/src/util-profiling.c b/src/util-profiling.c index 73e0c8489057..04ff786f726c 100644 --- a/src/util-profiling.c +++ b/src/util-profiling.c @@ -158,11 +158,11 @@ SCProfilingInit(void) memset(&packet_profile_data6, 0, sizeof(packet_profile_data6)); memset(&packet_profile_tmm_data4, 0, sizeof(packet_profile_tmm_data4)); memset(&packet_profile_tmm_data6, 0, sizeof(packet_profile_tmm_data6)); - packet_profile_app_data4 = SCCalloc(ALPROTO_MAX * 257, sizeof(SCProfilePacketData)); + packet_profile_app_data4 = SCCalloc(AlprotoMax * 257, sizeof(SCProfilePacketData)); if (packet_profile_app_data4 == NULL) { FatalError("Failed to allocate packet_profile_app_data4"); } - packet_profile_app_data6 = SCCalloc(ALPROTO_MAX * 257, sizeof(SCProfilePacketData)); + packet_profile_app_data6 = SCCalloc(AlprotoMax * 257, sizeof(SCProfilePacketData)); if (packet_profile_app_data6 == NULL) { FatalError("Failed to allocate packet_profile_app_data6"); } @@ -503,7 +503,7 @@ void SCProfilingDumpPacketStats(void) "--------------------", "------", "-----", "----------", "------------", "------------", "-----------"); total = 0; - for (AppProto a = 0; a < ALPROTO_MAX; a++) { + for (AppProto a = 0; a < AlprotoMax; a++) { for (int p = 0; p < 257; p++) { SCProfilePacketData *pd = &packet_profile_app_data4[a * 257 + p]; total += pd->tot; @@ -512,7 +512,7 @@ void SCProfilingDumpPacketStats(void) total += pd->tot; } } - for (AppProto a = 0; a < ALPROTO_MAX; a++) { + for (AppProto a = 0; a < AlprotoMax; a++) { for (int p = 0; p < 257; p++) { SCProfilePacketData *pd = &packet_profile_app_data4[a * 257 + p]; if (pd->cnt == 0) { @@ -531,7 +531,7 @@ void SCProfilingDumpPacketStats(void) } } - for (AppProto a = 0; a < ALPROTO_MAX; a++) { + for (AppProto a = 0; a < AlprotoMax; a++) { for (int p = 0; p < 257; p++) { SCProfilePacketData *pd = &packet_profile_app_data6[a * 257 + p]; if (pd->cnt == 0) { @@ -820,7 +820,7 @@ void SCProfilingPrintPacketProfile(Packet *p) /* count ticks for app layer */ uint64_t app_total = 0; - for (AppProto i = 0; i < ALPROTO_MAX; i++) { + for (AppProto i = 0; i < AlprotoMax; i++) { const PktProfilingAppData *pdt = &p->profile->app[i]; if (p->proto == IPPROTO_TCP) { @@ -951,7 +951,7 @@ static void SCProfilingUpdatePacketAppRecord(int alproto, uint8_t ipproto, PktPr static void SCProfilingUpdatePacketAppRecords(Packet *p) { int i; - for (i = 0; i < ALPROTO_MAX; i++) { + for (i = 0; i < AlprotoMax; i++) { PktProfilingAppData *pdt = &p->profile->app[i]; if (pdt->ticks_spent > 0) { @@ -1199,7 +1199,7 @@ PktProfiling *SCProfilePacketStart(void) { uint64_t sample = SC_ATOMIC_ADD(samples, 1); if (sample % rate == 0) - return SCCalloc(1, sizeof(PktProfiling) + ALPROTO_MAX * sizeof(PktProfilingAppData)); + return SCCalloc(1, sizeof(PktProfiling) + AlprotoMax * sizeof(PktProfilingAppData)); return NULL; } diff --git a/src/util-profiling.h b/src/util-profiling.h index 1c334bb34f27..284adcced795 100644 --- a/src/util-profiling.h +++ b/src/util-profiling.h @@ -203,12 +203,12 @@ PktProfiling *SCProfilePacketStart(void); (dp)->proto_detect_ticks_spent = 0; \ } -#define PACKET_PROFILING_APP_STORE(dp, p) \ - if (profiling_packets_enabled && (p)->profile != NULL) { \ - if ((dp)->alproto < ALPROTO_MAX) { \ - (p)->profile->app[(dp)->alproto].ticks_spent += (dp)->ticks_spent; \ - (p)->profile->proto_detect += (dp)->proto_detect_ticks_spent; \ - } \ +#define PACKET_PROFILING_APP_STORE(dp, p) \ + if (profiling_packets_enabled && (p)->profile != NULL) { \ + if ((dp)->alproto < AlprotoMax) { \ + (p)->profile->app[(dp)->alproto].ticks_spent += (dp)->ticks_spent; \ + (p)->profile->proto_detect += (dp)->proto_detect_ticks_spent; \ + } \ } #define PACKET_PROFILING_DETECT_START(p, id) \ From 404395b9901c2e18a51bafaac9a18c72e7fdd237 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Thu, 16 Nov 2023 14:35:49 +0100 Subject: [PATCH 3/3] plugins: app-layer plugins Ticket: 5053 --- src/app-layer-parser.c | 24 +++++++++++ src/app-layer-parser.h | 1 + src/app-layer-protos.c | 6 +-- src/detect-engine-file.h | 3 ++ src/detect-engine-register.c | 25 +++++++++++ src/detect-engine-register.h | 1 + src/detect-parse.c | 81 +++++++++++++++++++++++------------- src/output.c | 33 +++++++++++++++ src/output.h | 9 ++++ src/suricata-plugin.h | 16 +++++++ src/util-plugin.c | 36 ++++++++++++++++ 11 files changed, 204 insertions(+), 31 deletions(-) diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 010c40a04c1e..1abe2f9f2d45 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -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(); @@ -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(); } diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 58ad4333563c..d233edf9eb1f 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -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. * diff --git a/src/app-layer-protos.c b/src/app-layer-protos.c index e97d94ce12af..710f698fc725 100644 --- a/src/app-layer-protos.c +++ b/src/app-layer-protos.c @@ -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; @@ -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)); diff --git a/src/detect-engine-file.h b/src/detect-engine-file.h index 13aa7465f436..10bcf5ca7dbc 100644 --- a/src/detect-engine-file.h +++ b/src/detect-engine-file.h @@ -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 */ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 9bddf0fd8437..77defa2fbb89 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -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) { @@ -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(); } diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index b7a029998555..69ddcfa3a268 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -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); diff --git a/src/detect-parse.c b/src/detect-parse.c index 90d3b5706d3d..f59d8e1c67f5 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -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); } diff --git a/src/output.c b/src/output.c index ef9e396e3c03..d5b10c04cb21 100644 --- a/src/output.c +++ b/src/output.c @@ -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. */ @@ -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); + } } diff --git a/src/output.h b/src/output.h index 43bd9d8b8f74..3820ae1665d8 100644 --- a/src/output.h +++ b/src/output.h @@ -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 */ diff --git a/src/suricata-plugin.h b/src/suricata-plugin.h index 639dd7c7313e..8bc2183d70fd 100644 --- a/src/suricata-plugin.h +++ b/src/suricata-plugin.h @@ -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 */ diff --git a/src/util-plugin.c b/src/util-plugin.c index 7a9b467daaac..ebcaeace9dd3 100644 --- a/src/util-plugin.c +++ b/src/util-plugin.c @@ -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 typedef struct PluginListNode_ { @@ -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