From eeb7442df92b2c458542fd8d2c21aafe8a5e18fa Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Wed, 4 Sep 2024 22:17:08 +0200 Subject: [PATCH 1/2] template: move detect keywords to pure rust Ticket: 3195 Also remove unused src/tests/detect-template-buffer.c Completes commit 4a7567b3f04075f02543762717dbff9dd5b5c1f3 to remove references to template-rust --- rust/src/applayertemplate/detect.rs | 111 +++++++++++++++ rust/src/applayertemplate/mod.rs | 1 + rust/src/applayertemplate/template.rs | 37 +---- scripts/setup-app-layer.py | 70 +++------- src/Makefile.am | 3 - src/detect-engine-register.c | 3 +- src/detect-engine-register.h | 1 - src/detect-template-rust-buffer.c | 192 -------------------------- src/detect-template-rust-buffer.h | 29 ---- src/tests/detect-template-buffer.c | 104 -------------- src/tests/fuzz/confyaml.c | 2 - 11 files changed, 131 insertions(+), 422 deletions(-) create mode 100644 rust/src/applayertemplate/detect.rs delete mode 100644 src/detect-template-rust-buffer.c delete mode 100644 src/detect-template-rust-buffer.h delete mode 100644 src/tests/detect-template-buffer.c diff --git a/rust/src/applayertemplate/detect.rs b/rust/src/applayertemplate/detect.rs new file mode 100644 index 000000000000..4ec628b3aa89 --- /dev/null +++ b/rust/src/applayertemplate/detect.rs @@ -0,0 +1,111 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use super::template::{TemplateTransaction, ALPROTO_TEMPLATE}; +/* TEMPLATE_START_REMOVE */ +use crate::conf::conf_get_node; +/* TEMPLATE_END_REMOVE */ +use crate::core::Direction; +use crate::detect::{ + DetectBufferSetActiveList, DetectHelperBufferMpmRegister, DetectHelperGetData, + DetectHelperKeywordRegister, DetectSignatureSetAppProto, SCSigTableElmt, + SIGMATCH_INFO_STICKY_BUFFER, SIGMATCH_NOOPT, +}; +use std::os::raw::{c_int, c_void}; + +static mut G_TEMPLATE_BUFFER_BUFFER_ID: c_int = 0; + +unsafe extern "C" fn template_buffer_setup( + de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_TEMPLATE) != 0 { + return -1; + } + if DetectBufferSetActiveList(de, s, G_TEMPLATE_BUFFER_BUFFER_ID) < 0 { + return -1; + } + return 0; +} + +/// Get the request/response buffer for a transaction from C. +unsafe extern "C" fn template_buffer_get_data( + tx: *const c_void, flags: u8, buf: *mut *const u8, len: *mut u32, +) -> bool { + let tx = cast_pointer!(tx, TemplateTransaction); + if flags & Direction::ToClient as u8 != 0 { + if let Some(ref response) = tx.response { + if !response.is_empty() { + *len = response.len() as u32; + *buf = response.as_ptr(); + return true; + } + } + } else if let Some(ref request) = tx.request { + if !request.is_empty() { + *len = request.len() as u32; + *buf = request.as_ptr(); + return true; + } + } + return false; +} + +unsafe extern "C" fn template_buffer_get( + de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8, + tx: *const c_void, list_id: c_int, +) -> *mut c_void { + return DetectHelperGetData( + de, + transforms, + flow, + flow_flags, + tx, + list_id, + template_buffer_get_data, + ); +} + +#[no_mangle] +pub unsafe extern "C" fn ScDetectTemplateRegister() { + /* TEMPLATE_START_REMOVE */ + if conf_get_node("app-layer.protocols.template").is_none() { + return; + } + /* TEMPLATE_END_REMOVE */ + // TODO create a suricata-verify test + // Setup a keyword structure and register it + let kw = SCSigTableElmt { + name: b"template.buffer\0".as_ptr() as *const libc::c_char, + desc: b"Template content modifier to match on the template buffer\0".as_ptr() + as *const libc::c_char, + // TODO use the right anchor for url and write doc + url: b"/rules/template-keywords.html#buffer\0".as_ptr() as *const libc::c_char, + Setup: template_buffer_setup, + flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER, + AppLayerTxMatch: None, + Free: None, + }; + let _g_template_buffer_kw_id = DetectHelperKeywordRegister(&kw); + G_TEMPLATE_BUFFER_BUFFER_ID = DetectHelperBufferMpmRegister( + b"template.buffer\0".as_ptr() as *const libc::c_char, + b"template.buffer intern description\0".as_ptr() as *const libc::c_char, + ALPROTO_TEMPLATE, + true, //toclient + true, //toserver + template_buffer_get, + ); +} diff --git a/rust/src/applayertemplate/mod.rs b/rust/src/applayertemplate/mod.rs index e22bd68e391b..ae7005a09d0e 100644 --- a/rust/src/applayertemplate/mod.rs +++ b/rust/src/applayertemplate/mod.rs @@ -21,4 +21,5 @@ mod parser; pub mod template; /* TEMPLATE_START_REMOVE */ pub mod logger; +pub mod detect; /* TEMPLATE_END_REMOVE */ diff --git a/rust/src/applayertemplate/template.rs b/rust/src/applayertemplate/template.rs index 43a8bf940006..1580c4fdf3dd 100644 --- a/rust/src/applayertemplate/template.rs +++ b/rust/src/applayertemplate/template.rs @@ -27,7 +27,7 @@ use std::os::raw::{c_char, c_int, c_void}; static mut TEMPLATE_MAX_TX: usize = 256; -static mut ALPROTO_TEMPLATE: AppProto = ALPROTO_UNKNOWN; +pub(super) static mut ALPROTO_TEMPLATE: AppProto = ALPROTO_UNKNOWN; #[derive(AppLayerEvent)] enum TemplateEvent { @@ -347,41 +347,6 @@ unsafe extern "C" fn rs_template_tx_get_alstate_progress(tx: *mut c_void, _direc return 0; } -/// Get the request buffer for a transaction from C. -/// -/// No required for parsing, but an example function for retrieving a -/// pointer to the request buffer from C for detection. -#[no_mangle] -pub unsafe extern "C" fn rs_template_get_request_buffer( - tx: *mut c_void, buf: *mut *const u8, len: *mut u32, -) -> u8 { - let tx = cast_pointer!(tx, TemplateTransaction); - if let Some(ref request) = tx.request { - if !request.is_empty() { - *len = request.len() as u32; - *buf = request.as_ptr(); - return 1; - } - } - return 0; -} - -/// Get the response buffer for a transaction from C. -#[no_mangle] -pub unsafe extern "C" fn rs_template_get_response_buffer( - tx: *mut c_void, buf: *mut *const u8, len: *mut u32, -) -> u8 { - let tx = cast_pointer!(tx, TemplateTransaction); - if let Some(ref response) = tx.response { - if !response.is_empty() { - *len = response.len() as u32; - *buf = response.as_ptr(); - return 1; - } - } - return 0; -} - export_tx_data_get!(rs_template_get_tx_data, TemplateTransaction); export_state_data_get!(rs_template_get_state_data, TemplateState); diff --git a/scripts/setup-app-layer.py b/scripts/setup-app-layer.py index 26d9892b87f7..bb3d23e83944 100755 --- a/scripts/setup-app-layer.py +++ b/scripts/setup-app-layer.py @@ -101,7 +101,8 @@ def patch_rust_lib_rs(protoname): output.write(line) open(filename, "w").write(output.getvalue()) -def patch_rust_applayer_mod_rs(protoname): +# arg is the name of the new module to add +def patch_rust_applayer_mod_rs(protoname, arg): lower = protoname.lower() filename = "rust/src/applayer%s/mod.rs" % (lower) print("Patching %s." % (filename)) @@ -110,7 +111,7 @@ def patch_rust_applayer_mod_rs(protoname): with open(filename) as infile: for line in infile: if not done and line.find("mod parser") > -1: - output.write("pub mod logger;\n") + output.write("pub mod %s;\n" % arg) done = True output.write(line) open(filename, "w").write(output.getvalue()) @@ -234,68 +235,32 @@ def detect_copy_templates(proto, buffername): buffername_lower = buffername.lower() pairs = ( - ("src/detect-template-rust-buffer.h", - "src/detect-%s-%s.h" % (lower, buffername_lower)), - ("src/detect-template-rust-buffer.c", - "src/detect-%s-%s.c" % (lower, buffername_lower)), + ("rust/src/applayertemplate/detect.rs", + "rust/src/applayer%s/detect.rs" % (lower)), ) replacements = ( - ("TEMPLATE_RUST_BUFFER", "%s_%s" % ( + ("TEMPLATE_BUFFER", "%s_%s" % ( proto.upper(), buffername.upper())), - ("template-rust-buffer", "%s-%s" % ( + ("template.buffer", "%s.%s" % ( proto.lower(), buffername.lower())), - ("template_rust_buffer", "%s_%s" % ( + ("template_buffer", "%s_%s" % ( proto.lower(), buffername.lower())), - ("TemplateRustBuffer", "%s%s" % (proto, buffername)), ) common_copy_templates(proto, pairs, replacements) -def detect_patch_makefile_am(protoname, buffername): - filename = "src/Makefile.am" - print("Patching %s." % (filename)) - output = io.StringIO() - with open(filename) as infile: - for line in infile: - if line.lstrip().startswith("detect-template-buffer."): - new = line.replace("template-buffer", "%s-%s" % ( - protoname.lower(), buffername.lower())) - output.write(new) - output.write(line) - open(filename, "w").write(output.getvalue()) - -def detect_patch_detect_engine_register_c(protoname, buffername): +def detect_patch_detect_engine_register_c(protoname): filename = "src/detect-engine-register.c" print("Patching %s." % (filename)) output = io.StringIO() with open(filename) as infile: for line in infile: - - if line.find("detect-template-buffer.h") > -1: - new = line.replace("template-buffer", "%s-%s" % ( - protoname.lower(), buffername.lower())) - output.write(new) - - if line.find("DetectTemplateBufferRegister") > -1: - new = line.replace("TemplateBuffer", "%s%s" % ( - protoname, buffername)) - output.write(new) - - output.write(line) - open(filename, "w").write(output.getvalue()) - -def detect_patch_detect_engine_register_h(protoname, buffername): - filename = "src/detect-engine-register.h" - print("Patching %s." % (filename)) - output = io.StringIO() - with open(filename) as infile: - for line in infile: - - if line.find("DETECT_AL_TEMPLATE_BUFFER") > -1: - new = line.replace("TEMPLATE_BUFFER", "%s_%s" % ( - protoname.upper(), buffername.upper())) + if line.find("ScDetect%sRegister" % protoname) > -1: + # patch already applied + return + if line.find("ScDetectTemplateRegister") > -1: + new = line.replace("Template", "%s" % protoname) output.write(new) - output.write(line) open(filename, "w").write(output.getvalue()) @@ -388,7 +353,7 @@ def main(): if not proto_exists(proto): raise SetupError("no app-layer parser exists for %s" % (proto)) logger_copy_templates(proto) - patch_rust_applayer_mod_rs(proto) + patch_rust_applayer_mod_rs(proto, "logger") logger_patch_output_c(proto) logger_patch_suricata_yaml_in(proto) @@ -396,9 +361,8 @@ def main(): if not proto_exists(proto): raise SetupError("no app-layer parser exists for %s" % (proto)) detect_copy_templates(proto, args.buffer) - detect_patch_makefile_am(proto, args.buffer) - detect_patch_detect_engine_register_c(proto, args.buffer) - detect_patch_detect_engine_register_h(proto, args.buffer) + detect_patch_detect_engine_register_c(proto) + patch_rust_applayer_mod_rs(proto, "detect") if parser: print(""" diff --git a/src/Makefile.am b/src/Makefile.am index e409ce492ca4..5a60170fd369 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -287,7 +287,6 @@ noinst_HEADERS = \ detect-tcp-window.h \ detect-template2.h \ detect-template.h \ - detect-template-rust-buffer.h \ detect-threshold.h \ detect-tls-alpn.h \ detect-tls-cert-fingerprint.h \ @@ -860,7 +859,6 @@ libsuricata_c_a_SOURCES = \ detect-tcp-window.c \ detect-template2.c \ detect-template.c \ - detect-template-rust-buffer.c \ detect-threshold.c \ detect-tls.c \ detect-tls-alpn.c \ @@ -1182,7 +1180,6 @@ EXTRA_DIST = \ tests/detect-http-user-agent.c \ tests/detect-ssl-state.c \ tests/detect-ssl-version.c \ - tests/detect-template-buffer.c \ tests/detect-tls-cert-fingerprint.c \ tests/detect-tls-cert-issuer.c \ tests/detect-tls-cert-serial.c \ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 794f680dd46f..6ea3698c2c93 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -204,7 +204,6 @@ #include "detect-sip-method.h" #include "detect-sip-uri.h" #include "detect-target.h" -#include "detect-template-rust-buffer.h" #include "detect-quic-sni.h" #include "detect-quic-ua.h" #include "detect-quic-version.h" @@ -660,7 +659,6 @@ void SigTableSetup(void) DetectSipMethodRegister(); DetectSipUriRegister(); DetectTargetRegister(); - DetectTemplateRustBufferRegister(); DetectQuicSniRegister(); DetectQuicUaRegister(); DetectQuicVersionRegister(); @@ -695,6 +693,7 @@ void SigTableSetup(void) ScDetectMqttRegister(); ScDetectRfbRegister(); ScDetectSipRegister(); + ScDetectTemplateRegister(); /* close keyword registration */ DetectBufferTypeCloseRegistration(); diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index 7c3b5b4514b0..c9134c77b83a 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -291,7 +291,6 @@ enum DetectKeywordId { DETECT_TCPMSS, DETECT_FTPDATA, DETECT_TARGET, - DETECT_AL_TEMPLATE_BUFFER, DETECT_AL_QUIC_VERSION, DETECT_AL_QUIC_SNI, DETECT_AL_QUIC_UA, diff --git a/src/detect-template-rust-buffer.c b/src/detect-template-rust-buffer.c deleted file mode 100644 index 16dcbf0c6dfc..000000000000 --- a/src/detect-template-rust-buffer.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright (C) 2015-2022 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/* - * TODO: Update the \author in this file and detect-template.h. - * TODO: Update description in the \file section below. - * TODO: Remove SCLogNotice statements or convert to debug. - */ - -/** - * \file - * - * \author FirstName LastName - * - * Set up of the "template_rust" keyword to allow content - * inspections on the decoded template application layer buffers. - */ - -#include "suricata-common.h" -#include "conf.h" -#include "detect.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-content-inspection.h" -#include "detect-template-rust-buffer.h" -#include "app-layer-parser.h" -#include "detect-engine-build.h" -#include "rust.h" - -#ifdef UNITTESTS -static void DetectTemplateRustBufferRegisterTests(void); -#endif -static int g_template_rust_id = 0; - -static int DetectTemplateRustBufferSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str) -{ - s->init_data->list = g_template_rust_id; - - if (DetectSignatureSetAppProto(s, ALPROTO_TEMPLATE) != 0) - return -1; - - return 0; -} - -static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx, - const DetectEngineTransforms *transforms, Flow *_f, const uint8_t flags, void *txv, - const int list_id) -{ - InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); - if (!buffer->initialized) { - uint32_t data_len = 0; - const uint8_t *data = NULL; - if (flags & STREAM_TOSERVER) { - rs_template_get_request_buffer(txv, &data, &data_len); - } else { - rs_template_get_response_buffer(txv, &data, &data_len); - } - InspectionBufferSetup(det_ctx, list_id, buffer, data, data_len); - InspectionBufferApplyTransforms(buffer, transforms); - } - return buffer; -} - -void DetectTemplateRustBufferRegister(void) -{ - /* TEMPLATE_START_REMOVE */ - if (ConfGetNode("app-layer.protocols.template-rust") == NULL) { - return; - } - /* TEMPLATE_END_REMOVE */ - sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].name = "template_rust_buffer"; - sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].desc = - "Template content modifier to match on the template buffers"; - sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].Setup = DetectTemplateRustBufferSetup; -#ifdef UNITTESTS - sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].RegisterTests = DetectTemplateRustBufferRegisterTests; -#endif - sigmatch_table[DETECT_AL_TEMPLATE_BUFFER].flags |= SIGMATCH_NOOPT; - - /* register inspect engines */ - DetectAppLayerInspectEngineRegister("template_buffer", ALPROTO_TEMPLATE, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectBufferGeneric, GetData); - DetectAppLayerInspectEngineRegister("template_buffer", ALPROTO_TEMPLATE, SIG_FLAG_TOCLIENT, 0, - DetectEngineInspectBufferGeneric, GetData); - - g_template_rust_id = DetectBufferTypeGetByName("template_buffer"); - - SCLogNotice("Template application layer detect registered."); -} - -#ifdef UNITTESTS - -#include "util-unittest.h" -#include "util-unittest-helper.h" -#include "flow-util.h" -#include "stream-tcp.h" -#include "detect-engine-alert.h" - -static int DetectTemplateRustBufferTest(void) -{ - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - DetectEngineThreadCtx *det_ctx = NULL; - DetectEngineCtx *de_ctx = NULL; - Flow f; - Packet *p; - TcpSession tcp; - ThreadVars tv; - Signature *s; - - uint8_t request[] = "12:Hello World!"; - - /* Setup flow. */ - memset(&f, 0, sizeof(Flow)); - memset(&tcp, 0, sizeof(TcpSession)); - memset(&tv, 0, sizeof(ThreadVars)); - p = UTHBuildPacket(request, sizeof(request), IPPROTO_TCP); - FLOW_INITIALIZE(&f); - f.alproto = ALPROTO_TEMPLATE; - f.protoctx = (void *)&tcp; - f.proto = IPPROTO_TCP; - f.flags |= FLOW_IPV4; - p->flow = &f; - p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST; - p->flowflags |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED; - StreamTcpInitConfig(true); - - de_ctx = DetectEngineCtxInit(); - FAIL_IF_NULL(de_ctx); - - /* This rule should match. */ - s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (" - "msg:\"TEMPLATE Test Rule\"; " - "template_rust_buffer; content:\"World!\"; " - "sid:1; rev:1;)"); - FAIL_IF_NULL(s); - - /* This rule should not match. */ - s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (" - "msg:\"TEMPLATE Test Rule\"; " - "template_rust_buffer; content:\"W0rld!\"; " - "sid:2; rev:1;)"); - FAIL_IF_NULL(s); - - SigGroupBuild(de_ctx); - DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); - - AppLayerParserParse( - NULL, alp_tctx, &f, ALPROTO_TEMPLATE, STREAM_TOSERVER, request, sizeof(request)); - - /* Check that we have app-layer state. */ - FAIL_IF_NULL(f.alstate); - - SigMatchSignatures(&tv, de_ctx, det_ctx, p); - FAIL_IF(!PacketAlertCheck(p, 1)); - FAIL_IF(PacketAlertCheck(p, 2)); - - /* Cleanup. */ - if (alp_tctx != NULL) - AppLayerParserThreadCtxFree(alp_tctx); - if (det_ctx != NULL) - DetectEngineThreadCtxDeinit(&tv, det_ctx); - if (de_ctx != NULL) - SigGroupCleanup(de_ctx); - if (de_ctx != NULL) - DetectEngineCtxFree(de_ctx); - StreamTcpFreeConfig(true); - FLOW_DESTROY(&f); - UTHFreePacket(p); - - PASS; -} - -static void DetectTemplateRustBufferRegisterTests(void) -{ - UtRegisterTest("DetectTemplateRustBufferTest", - DetectTemplateRustBufferTest); -} -#endif /* UNITTESTS */ diff --git a/src/detect-template-rust-buffer.h b/src/detect-template-rust-buffer.h deleted file mode 100644 index 3713ac4c4c71..000000000000 --- a/src/detect-template-rust-buffer.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2015-2017 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author FirstName LastName - */ - -#ifndef SURICATA_DETECT_TEMPLATE_RUST_BUFFER_H -#define SURICATA_DETECT_TEMPLATE_RUST_BUFFER_H - -void DetectTemplateRustBufferRegister(void); - -#endif /* SURICATA_DETECT_TEMPLATE_RUST_BUFFER_H */ diff --git a/src/tests/detect-template-buffer.c b/src/tests/detect-template-buffer.c deleted file mode 100644 index 7e04025a96da..000000000000 --- a/src/tests/detect-template-buffer.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2015-2018 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#include "../util-unittest.h" -#include "../util-unittest-helper.h" -#include "../app-layer-parser.h" -#include "../detect-engine.h" -#include "../detect-parse.h" -#include "../flow-util.h" -#include "../stream-tcp.h" -#include "../detect-engine-build.h" - -static int DetectTemplateBufferTest(void) -{ - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - FAIL_IF_NULL(alp_tctx); - - Flow f; - Packet *p; - TcpSession tcp; - ThreadVars tv; - Signature *s; - - uint8_t request[] = "Hello World!"; - - /* Setup flow. */ - memset(&f, 0, sizeof(Flow)); - memset(&tcp, 0, sizeof(TcpSession)); - memset(&tv, 0, sizeof(ThreadVars)); - p = UTHBuildPacket(request, sizeof(request), IPPROTO_TCP); - FLOW_INITIALIZE(&f); - f.alproto = ALPROTO_TEMPLATE; - f.protoctx = (void *)&tcp; - f.proto = IPPROTO_TCP; - f.flags |= FLOW_IPV4; - p->flow = &f; - p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST; - p->flowflags |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED; - StreamTcpInitConfig(true); - - DetectEngineCtx *de_ctx = DetectEngineCtxInit(); - FAIL_IF_NULL(de_ctx); - - /* This rule should match. */ - s = DetectEngineAppendSig(de_ctx, - "alert tcp any any -> any any (" - "msg:\"TEMPLATE Test Rule\"; " - "template_buffer; content:\"World!\"; " - "sid:1; rev:1;)"); - FAIL_IF_NULL(s); - - /* This rule should not match. */ - s = DetectEngineAppendSig(de_ctx, - "alert tcp any any -> any any (" - "msg:\"TEMPLATE Test Rule\"; " - "template_buffer; content:\"W0rld!\"; " - "sid:2; rev:1;)"); - FAIL_IF_NULL(s); - - SigGroupBuild(de_ctx); - - DetectEngineThreadCtx *det_ctx = NULL; - DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); - FAIL_IF_NULL(det_ctx); - - AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TEMPLATE, - STREAM_TOSERVER, request, sizeof(request)); - - /* Check that we have app-layer state. */ - FAIL_IF_NULL(f.alstate); - - SigMatchSignatures(&tv, de_ctx, det_ctx, p); - FAIL_IF(!PacketAlertCheck(p, 1)); - FAIL_IF(PacketAlertCheck(p, 2)); - - /* Cleanup. */ - AppLayerParserThreadCtxFree(alp_tctx); - DetectEngineThreadCtxDeinit(&tv, det_ctx); - DetectEngineCtxFree(de_ctx); - StreamTcpFreeConfig(true); - FLOW_DESTROY(&f); - UTHFreePacket(p); - - PASS; -} - -static void DetectTemplateBufferRegisterTests(void) -{ - UtRegisterTest("DetectTemplateBufferTest", DetectTemplateBufferTest); -} diff --git a/src/tests/fuzz/confyaml.c b/src/tests/fuzz/confyaml.c index e67e40a34727..f538f32871f7 100644 --- a/src/tests/fuzz/confyaml.c +++ b/src/tests/fuzz/confyaml.c @@ -85,8 +85,6 @@ app-layer:\n\ enabled: yes\n\ template:\n\ enabled: yes\n\ - template-rust:\n\ - enabled: yes\n\ modbus:\n\ enabled: yes\n\ detection-ports:\n\ From 4fdeb451defed73df2023384786454391c52cd97 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Tue, 8 Oct 2024 21:36:59 +0200 Subject: [PATCH 2/2] template/detect: allow empty buffers --- rust/src/applayertemplate/detect.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/rust/src/applayertemplate/detect.rs b/rust/src/applayertemplate/detect.rs index 4ec628b3aa89..5cfa364bd82c 100644 --- a/rust/src/applayertemplate/detect.rs +++ b/rust/src/applayertemplate/detect.rs @@ -48,18 +48,14 @@ unsafe extern "C" fn template_buffer_get_data( let tx = cast_pointer!(tx, TemplateTransaction); if flags & Direction::ToClient as u8 != 0 { if let Some(ref response) = tx.response { - if !response.is_empty() { - *len = response.len() as u32; - *buf = response.as_ptr(); - return true; - } - } - } else if let Some(ref request) = tx.request { - if !request.is_empty() { - *len = request.len() as u32; - *buf = request.as_ptr(); + *len = response.len() as u32; + *buf = response.as_ptr(); return true; } + } else if let Some(ref request) = tx.request { + *len = request.len() as u32; + *buf = request.as_ptr(); + return true; } return false; }