From aa7f926ff4fc196c92c3a42c34853e03fd93efde Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Mon, 17 Feb 2025 21:13:54 +0100 Subject: [PATCH] detect: rust helper to register sticky buffer --- rust/src/detect/mod.rs | 57 ++++++++++++++++++++++++++++++++++++ rust/src/dns/detect.rs | 51 +++++++++++++------------------- src/detect-engine-register.c | 21 +++++++++++++ src/detect-engine-register.h | 1 + src/detect.h | 2 ++ 5 files changed, 102 insertions(+), 30 deletions(-) diff --git a/rust/src/detect/mod.rs b/rust/src/detect/mod.rs index cf9c384f90..78c6ecb7e9 100644 --- a/rust/src/detect/mod.rs +++ b/rust/src/detect/mod.rs @@ -36,6 +36,7 @@ pub mod vlan; pub mod datasets; use std::os::raw::{c_char, c_int, c_void}; +use std::ffi::CString; use suricata_sys::sys::AppProto; @@ -55,6 +56,61 @@ pub trait EnumString { fn from_str(s: &str) -> Option where Self: Sized; } +/// Rust app-layer light version of SigTableElmt for simple sticky buffer +pub struct SigTableElmtStickyBuffer { + /// keyword name + pub name: String, + /// keyword description + pub desc: String, + /// keyword documentation url + pub url: String, + /// function callback to parse and setup keyword in rule + pub setup: unsafe extern "C" fn( + de: *mut c_void, + s: *mut c_void, + raw: *const std::os::raw::c_char, + ) -> c_int, +} + +pub fn helper_keyword_register_sticky_buffer(kw: &SigTableElmtStickyBuffer) -> c_int { + let name = CString::new(kw.name.as_bytes()).unwrap().into_raw(); + let desc = CString::new(kw.desc.as_bytes()).unwrap().into_raw(); + let url = CString::new(kw.url.as_bytes()).unwrap().into_raw(); + let st = SCSigTableAppLiteElmt { + name, + desc, + url, + Setup: kw.setup, + flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER, + AppLayerTxMatch: None, + Free: None, + }; + unsafe { + let r = DetectHelperKeywordRegister(&st); + DetectHelperKeywordSetCleanCString(r); + return r; + } +} + +#[repr(C)] +#[allow(non_snake_case)] +/// Names of SigTableElmt for release by rust +pub struct SCSigTableNamesElmt { + /// keyword name + pub name: *mut libc::c_char, + /// keyword description + pub desc: *mut libc::c_char, + /// keyword documentation url + pub url: *mut libc::c_char, +} + +#[no_mangle] +pub unsafe extern "C" fn SCDetectSigMatchNamesFree(kw: &mut SCSigTableNamesElmt) { + let _ = CString::from_raw(kw.name); + let _ = CString::from_raw(kw.desc); + let _ = CString::from_raw(kw.url); +} + #[repr(C)] #[allow(non_snake_case)] /// App-layer light version of SigTableElmt @@ -95,6 +151,7 @@ pub const SIGMATCH_INFO_STICKY_BUFFER: u16 = 0x200; // BIT_U16(9) /// cbindgen:ignore extern "C" { + pub fn DetectHelperKeywordSetCleanCString(id: c_int); pub fn DetectBufferSetActiveList(de: *mut c_void, s: *mut c_void, bufid: c_int) -> c_int; pub fn DetectHelperGetData( de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8, diff --git a/rust/src/dns/detect.rs b/rust/src/dns/detect.rs index 3129516ccd..7236704be3 100644 --- a/rust/src/dns/detect.rs +++ b/rust/src/dns/detect.rs @@ -21,10 +21,10 @@ use crate::detect::uint::{ SCDetectU8Parse, }; use crate::detect::{ - DetectBufferSetActiveList, DetectHelperBufferRegister, DetectHelperGetMultiData, - DetectHelperKeywordAliasRegister, DetectHelperKeywordRegister, + helper_keyword_register_sticky_buffer, DetectBufferSetActiveList, DetectHelperBufferRegister, + DetectHelperGetMultiData, DetectHelperKeywordAliasRegister, DetectHelperKeywordRegister, DetectHelperMultiBufferProgressMpmRegister, DetectSignatureSetAppProto, SCSigTableAppLiteElmt, - SigMatchAppendSMToList, SIGMATCH_INFO_STICKY_BUFFER, SIGMATCH_NOOPT, + SigMatchAppendSMToList, SigTableElmtStickyBuffer, }; use crate::direction::Direction; use std::ffi::CStr; @@ -366,16 +366,13 @@ unsafe extern "C" fn dns_query_get_data_wrapper( #[no_mangle] pub unsafe extern "C" fn SCDetectDNSRegister() { - let kw = SCSigTableAppLiteElmt { - name: b"dns.answer.name\0".as_ptr() as *const libc::c_char, - desc: b"DNS answer name sticky buffer\0".as_ptr() as *const libc::c_char, - url: b"/rules/dns-keywords.html#dns-answer-name\0".as_ptr() as *const libc::c_char, - Setup: dns_detect_answer_name_setup, - flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER, - AppLayerTxMatch: None, - Free: None, + let kw = SigTableElmtStickyBuffer { + name: String::from("dns.answer.name"), + desc: String::from("DNS answer name sticky buffer"), + url: String::from("/rules/dns-keywords.html#dns-answer-name"), + setup: dns_detect_answer_name_setup, }; - let _g_dns_answer_name_kw_id = DetectHelperKeywordRegister(&kw); + let _g_dns_answer_name_kw_id = helper_keyword_register_sticky_buffer(&kw); G_DNS_ANSWER_NAME_BUFFER_ID = DetectHelperMultiBufferProgressMpmRegister( b"dns.answer.name\0".as_ptr() as *const libc::c_char, b"dns answer name\0".as_ptr() as *const libc::c_char, @@ -403,16 +400,13 @@ pub unsafe extern "C" fn SCDetectDNSRegister() { true, true, ); - let kw = SCSigTableAppLiteElmt { - name: b"dns.query.name\0".as_ptr() as *const libc::c_char, - desc: b"DNS query name sticky buffer\0".as_ptr() as *const libc::c_char, - url: b"/rules/dns-keywords.html#dns-query-name\0".as_ptr() as *const libc::c_char, - Setup: dns_detect_query_name_setup, - flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER, - AppLayerTxMatch: None, - Free: None, + let kw = SigTableElmtStickyBuffer { + name: String::from("dns.query.name"), + desc: String::from("DNS query name sticky buffer"), + url: String::from("/rules/dns-keywords.html#dns-query-name"), + setup: dns_detect_query_name_setup, }; - let _g_dns_query_name_kw_id = DetectHelperKeywordRegister(&kw); + let _g_dns_query_name_kw_id = helper_keyword_register_sticky_buffer(&kw); G_DNS_QUERY_NAME_BUFFER_ID = DetectHelperMultiBufferProgressMpmRegister( b"dns.query.name\0".as_ptr() as *const libc::c_char, b"dns query name\0".as_ptr() as *const libc::c_char, @@ -456,16 +450,13 @@ pub unsafe extern "C" fn SCDetectDNSRegister() { true, true, ); - let kw = SCSigTableAppLiteElmt { - name: b"dns.query\0".as_ptr() as *const libc::c_char, - desc: b"sticky buffer to match DNS query-buffer\0".as_ptr() as *const libc::c_char, - url: b"/rules/dns-keywords.html#dns-query\0".as_ptr() as *const libc::c_char, - Setup: dns_detect_query_setup, - flags: SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER, - AppLayerTxMatch: None, - Free: None, + let kw = SigTableElmtStickyBuffer { + name: String::from("dns.query"), + desc: String::from("sticky buffer to match DNS query-buffer"), + url: String::from("/rules/dns-keywords.html#dns-query"), + setup: dns_detect_query_setup, }; - let g_dns_query_name_kw_id = DetectHelperKeywordRegister(&kw); + let g_dns_query_name_kw_id = helper_keyword_register_sticky_buffer(&kw); DetectHelperKeywordAliasRegister( g_dns_query_name_kw_id, b"dns_query\0".as_ptr() as *const libc::c_char, diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 00644e1e97..8a5710be50 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -447,9 +447,30 @@ static void DetectFileHandlerRegister(void) } } +static void SigCleanCString(SigTableElmt *base) +{ + SCSigTableNamesElmt kw; + // remove const for mut to release + kw.name = (char *)base->name; + kw.desc = (char *)base->desc; + kw.url = (char *)base->url; + SCDetectSigMatchNamesFree(&kw); +} + +void DetectHelperKeywordSetCleanCString(int id) +{ + sigmatch_table[id].Cleanup = SigCleanCString; +} + void SigTableCleanup(void) { if (sigmatch_table != NULL) { + for (int i = 0; i < DETECT_TBLSIZE; i++) { + if ((sigmatch_table[i].Cleanup) == NULL) { + continue; + } + sigmatch_table[i].Cleanup(&sigmatch_table[i]); + } SCFree(sigmatch_table); sigmatch_table = NULL; DETECT_TBLSIZE = 0; diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index ad726bb3cd..d67d57e0ce 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -349,5 +349,6 @@ void SigTableSetup(void); int SCSigTablePreRegister(void (*KeywordsRegister)(void)); void SigTableRegisterTests(void); bool SigTableHasKeyword(const char *keyword); +void DetectHelperKeywordSetCleanCString(int id); #endif /* SURICATA_DETECT_ENGINE_REGISTER_H */ diff --git a/src/detect.h b/src/detect.h index e84c4ba90d..d927744354 100644 --- a/src/detect.h +++ b/src/detect.h @@ -1404,6 +1404,8 @@ typedef struct SigTableElmt_ { const char *desc; const char *url; + // Cleanup function for freeing rust allocated name or such + void (*Cleanup)(struct SigTableElmt_ *); } SigTableElmt; /* event code */ -- 2.47.2