]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: rust helper to register sticky buffer 13053/head
authorPhilippe Antoine <pantoine@oisf.net>
Mon, 17 Feb 2025 20:13:54 +0000 (21:13 +0100)
committerVictor Julien <victor@inliniac.net>
Sat, 19 Apr 2025 16:20:02 +0000 (18:20 +0200)
rust/src/detect/mod.rs
rust/src/dns/detect.rs
src/detect-engine-register.c
src/detect-engine-register.h
src/detect.h

index cf9c384f90663149d13fafe6ef6c641be4fa6d8e..78c6ecb7e9bcf2a4df3097c41258c4d9ff154e2c 100644 (file)
@@ -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<T> {
     fn from_str(s: &str) -> Option<Self> 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,
index 3129516ccd0b5579e80f937e791976dddcec419b..7236704be3040e9c415d45c5a3d68ae254798eda 100644 (file)
@@ -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,
index 00644e1e97b362b42ce51002407b746c9ac8425a..8a5710be5096dd48ded44ca7a2c88fd6d5c5664a 100644 (file)
@@ -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;
index ad726bb3cd327913e1353be4beb89dbc0d57cce9..d67d57e0ced6bc40a97dc7e46044600e08b71c1f 100644 (file)
@@ -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 */
index e84c4ba90d7a8d24947ea8bf4057f25c2fa29227..d927744354de7acf7a5af9444e0d5d71d4cff729 100644 (file)
@@ -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 */