]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
sdp: add sdp.bandwidth sticky buffer
authorGiuseppe Longo <giuseppe@glongo.it>
Mon, 30 Sep 2024 13:30:07 +0000 (15:30 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 2 Apr 2025 20:36:16 +0000 (22:36 +0200)
This adds a sticky (multi) buffer to match the "Bandwidth" field in both
requests and responses.

Ticket #7291

rust/src/sdp/detect.rs

index 5cf7d1253c0ba41d3e4cc7c2002c114421d0df1c..a0997330d82c3a7d13aa18424dd7fd8cac5afff2 100644 (file)
@@ -19,7 +19,8 @@
 
 use crate::detect::{
     DetectBufferSetActiveList, DetectHelperBufferMpmRegister, DetectHelperGetData,
-    DetectHelperKeywordRegister, DetectSignatureSetAppProto, SCSigTableElmt, SIGMATCH_NOOPT,
+    DetectHelperGetMultiData, DetectHelperKeywordRegister, DetectHelperMultiBufferMpmRegister,
+    DetectSignatureSetAppProto, SCSigTableElmt, SIGMATCH_NOOPT,
 };
 use crate::direction::Direction;
 use crate::sip::sip::{SIPTransaction, ALPROTO_SIP};
@@ -33,6 +34,7 @@ static mut G_SDP_URI_BUFFER_ID: c_int = 0;
 static mut G_SDP_EMAIL_BUFFER_ID: c_int = 0;
 static mut G_SDP_PHONE_NUMBER_BUFFER_ID: c_int = 0;
 static mut G_SDP_CONNECTION_DATA_BUFFER_ID: c_int = 0;
+static mut G_SDP_BANDWIDTH_BUFFER_ID: c_int = 0;
 
 unsafe extern "C" fn sdp_session_name_setup(
     de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
@@ -365,6 +367,58 @@ unsafe extern "C" fn sdp_conn_data_get_data(
     false
 }
 
+unsafe extern "C" fn sdp_bandwidth_setup(
+    de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char,
+) -> c_int {
+    if DetectSignatureSetAppProto(s, ALPROTO_SIP) != 0 {
+        return -1;
+    }
+    if DetectBufferSetActiveList(de, s, G_SDP_BANDWIDTH_BUFFER_ID) < 0 {
+        return -1;
+    }
+    return 0;
+}
+
+unsafe extern "C" fn sdp_bandwidth_get(
+    de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8,
+    tx: *const c_void, list_id: c_int, local_id: u32,
+) -> *mut c_void {
+    return DetectHelperGetMultiData(
+        de,
+        transforms,
+        flow,
+        flow_flags,
+        tx,
+        list_id,
+        local_id,
+        sip_bandwidth_get_data,
+    );
+}
+
+unsafe extern "C" fn sip_bandwidth_get_data(
+    tx: *const c_void, flow_flags: u8, local_id: u32, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+    let tx = cast_pointer!(tx, SIPTransaction);
+    let direction = flow_flags.into();
+    let sdp_option = match direction {
+        Direction::ToServer => tx.request.as_ref().and_then(|req| req.body.as_ref()),
+        Direction::ToClient => tx.response.as_ref().and_then(|resp| resp.body.as_ref()),
+    };
+    if let Some(sdp) = sdp_option {
+        if let Some(ref b) = sdp.bandwidths {
+            if (local_id as usize) < b.len() {
+                let val = &b[local_id as usize];
+                *buffer = val.as_ptr();
+                *buffer_len = val.len() as u32;
+                return true;
+            }
+        }
+    }
+    *buffer = ptr::null();
+    *buffer_len = 0;
+    false
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn ScDetectSdpRegister() {
     let kw = SCSigTableElmt {
@@ -497,4 +551,23 @@ pub unsafe extern "C" fn ScDetectSdpRegister() {
         true,
         sdp_conn_data_get,
     );
+    let kw = SCSigTableElmt {
+        name: b"sdp.bandwidth\0".as_ptr() as *const libc::c_char,
+        desc: b"sticky buffer to match on the SDP bandwidth field\0".as_ptr()
+            as *const libc::c_char,
+        url: b"/rules/sdp-keywords.html#sdp-bandwidth\0".as_ptr() as *const libc::c_char,
+        Setup: sdp_bandwidth_setup,
+        flags: SIGMATCH_NOOPT,
+        AppLayerTxMatch: None,
+        Free: None,
+    };
+    let _ = DetectHelperKeywordRegister(&kw);
+    G_SDP_BANDWIDTH_BUFFER_ID = DetectHelperMultiBufferMpmRegister(
+        b"sdp.bandwidth\0".as_ptr() as *const libc::c_char,
+        b"sdp.bandwidth\0".as_ptr() as *const libc::c_char,
+        ALPROTO_SIP,
+        true,
+        true,
+        sdp_bandwidth_get,
+    );
 }