From e3fefcf55cdb0f40eac2ddef2b2d964beadc41d6 Mon Sep 17 00:00:00 2001 From: Giuseppe Longo Date: Sat, 10 Aug 2024 13:52:07 +0200 Subject: [PATCH] sip: add sip.from sticky buffer This adds a sticky (multi) buffer to match the "From" header field in both requests and responses. Ticket #6374 --- rust/src/sip/detect.rs | 95 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/rust/src/sip/detect.rs b/rust/src/sip/detect.rs index c90ff65b78..6e75060c15 100644 --- a/rust/src/sip/detect.rs +++ b/rust/src/sip/detect.rs @@ -19,13 +19,13 @@ 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, + ); }