]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
sip: add sip.from sticky buffer
authorGiuseppe Longo <giuseppe@glongo.it>
Sat, 10 Aug 2024 11:52:07 +0000 (13:52 +0200)
committerVictor Julien <victor@inliniac.net>
Sun, 22 Sep 2024 04:45:36 +0000 (06:45 +0200)
This adds a sticky (multi) buffer to match the "From" header field
in both requests and responses.

Ticket #6374

rust/src/sip/detect.rs

index c90ff65b7807bf800e37e9094ee0bacc8b4778ac..6e75060c158667f624a7e1eceea355ea9bda74f7 100644 (file)
 
 use crate::core::Direction;
 use crate::detect::{
-    DetectBufferSetActiveList, DetectHelperBufferMpmRegister, DetectHelperBufferRegister,
-    DetectHelperGetData, DetectHelperKeywordRegister, DetectSignatureSetAppProto, SCSigTableElmt,
-    SigMatchAppendSMToList, SIGMATCH_INFO_STICKY_BUFFER, SIGMATCH_NOOPT,
+    DetectBufferSetActiveList, DetectHelperBufferMpmRegister, DetectHelperGetData,
+    DetectHelperGetMultiData, DetectHelperKeywordRegister, DetectHelperMultiBufferMpmRegister,
+    DetectSignatureSetAppProto, SCSigTableElmt, SIGMATCH_NOOPT,
 };
 use crate::sip::sip::{SIPTransaction, ALPROTO_SIP};
 use std::ffi::CStr;
-use std::os::raw::{c_int, c_void};
+use std::os::raw::{c_char, c_int, c_void};
 use std::ptr;
 
 static mut G_SIP_PROTOCOL_BUFFER_ID: c_int = 0;
@@ -33,6 +33,7 @@ static mut G_SIP_STAT_CODE_BUFFER_ID: c_int = 0;
 static mut G_SIP_STAT_MSG_BUFFER_ID: c_int = 0;
 static mut G_SIP_REQUEST_LINE_BUFFER_ID: c_int = 0;
 static mut G_SIP_RESPONSE_LINE_BUFFER_ID: c_int = 0;
+static mut G_SIP_FROM_HDR_BUFFER_ID: c_int = 0;
 
 #[no_mangle]
 pub unsafe extern "C" fn rs_sip_tx_get_method(
@@ -303,6 +304,74 @@ unsafe extern "C" fn sip_response_line_get_data(
     return false;
 }
 
+unsafe extern "C" fn sip_get_header_value(
+    tx: *const c_void, i: u32, direction: u8, buffer: *mut *const u8, buffer_len: *mut u32,
+    strname: *const c_char,
+) -> bool {
+    let tx = cast_pointer!(tx, SIPTransaction);
+    let hname: &CStr = CStr::from_ptr(strname);
+    if let Ok(s) = hname.to_str() {
+        let headers = match direction.into() {
+            Direction::ToServer => tx.request.as_ref().map(|r| &r.headers),
+            Direction::ToClient => tx.response.as_ref().map(|r| &r.headers),
+        };
+        if let Some(headers) = headers {
+            if let Some(header_vals) = headers.get(s) {
+                if (i as usize) < header_vals.len() {
+                    let value = &header_vals[i as usize];
+                    *buffer = value.as_ptr();
+                    *buffer_len = value.len() as u32;
+                    return true;
+                }
+            }
+        }
+    }
+    *buffer = ptr::null();
+    *buffer_len = 0;
+    return false;
+}
+
+unsafe extern "C" fn sip_from_hdr_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_SIP_FROM_HDR_BUFFER_ID) < 0 {
+        return -1;
+    }
+    return 0;
+}
+
+unsafe extern "C" fn sip_from_hdr_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_from_hdr_get_data,
+    );
+}
+
+unsafe extern "C" fn sip_from_hdr_get_data(
+    tx: *const c_void, flow_flags: u8, local_id: u32, buffer: *mut *const u8, buffer_len: *mut u32,
+) -> bool {
+    sip_get_header_value(
+        tx,
+        local_id,
+        flow_flags,
+        buffer,
+        buffer_len,
+        "From\0".as_ptr() as *const c_char,
+    )
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn ScDetectSipRegister() {
     let kw = SCSigTableElmt {
@@ -395,4 +464,22 @@ pub unsafe extern "C" fn ScDetectSipRegister() {
         false,
         sip_response_line_get,
     );
+    let kw = SCSigTableElmt {
+        name: b"sip.from\0".as_ptr() as *const libc::c_char,
+        desc: b"sticky buffer to match on the SIP From header\0".as_ptr() as *const libc::c_char,
+        url: b"/rules/sip-keywords.html#sip-from\0".as_ptr() as *const libc::c_char,
+        Setup: sip_from_hdr_setup,
+        flags: SIGMATCH_NOOPT,
+        AppLayerTxMatch: None,
+        Free: None,
+    };
+    let _g_sip_from_hdr_kw_id = DetectHelperKeywordRegister(&kw);
+    G_SIP_FROM_HDR_BUFFER_ID = DetectHelperMultiBufferMpmRegister(
+        b"sip.from\0".as_ptr() as *const libc::c_char,
+        b"sip.from\0".as_ptr() as *const libc::c_char,
+        ALPROTO_SIP,
+        true,
+        true,
+        sip_from_hdr_get,
+    );
 }