diff --git a/doc/userguide/rules/http2-keywords.rst b/doc/userguide/rules/http2-keywords.rst index c36e955ecc..05281d13e9 100644 --- a/doc/userguide/rules/http2-keywords.rst +++ b/doc/userguide/rules/http2-keywords.rst @@ -41,6 +41,8 @@ Match on the value of the HTTP2 priority field present in a PRIORITY or HEADERS http2.priority uses an :ref:`unsigned 8-bit integer `. +http2.priority is also a :ref:`multi-integer `. + This keyword takes a numeric argument after a colon and supports additional qualifiers, such as: * ``>`` (greater than) diff --git a/rust/src/detect/uint.rs b/rust/src/detect/uint.rs index 2f62fe0344..b956e23868 100644 --- a/rust/src/detect/uint.rs +++ b/rust/src/detect/uint.rs @@ -25,7 +25,7 @@ use nom7::IResult; use super::EnumString; -use std::ffi::{c_int, CStr}; +use std::ffi::{c_int, c_void, CStr}; use std::str::FromStr; #[derive(PartialEq, Eq, Clone, Debug)] @@ -52,14 +52,14 @@ pub struct DetectUintData { } #[derive(Debug, PartialEq)] -pub(crate) enum DetectUintIndex { +pub enum DetectUintIndex { Any, All, Index(i32), } #[derive(Debug, PartialEq)] -pub(crate) struct DetectUintArrayData { +pub struct DetectUintArrayData { pub du: DetectUintData, pub index: DetectUintIndex, } @@ -80,6 +80,18 @@ fn parse_uint_index(parts: &[&str]) -> Option { return Some(index); } +pub(crate) fn detect_parse_array_uint(s: &str) -> Option> { + let parts: Vec<&str> = s.split(',').collect(); + if parts.len() > 2 { + return None; + } + + let index = parse_uint_index(&parts)?; + let (_, du) = detect_parse_uint::(parts[0]).ok()?; + + Some(DetectUintArrayData { du, index }) +} + pub(crate) fn detect_parse_array_uint_enum>( s: &str, ) -> Option> { @@ -553,6 +565,24 @@ pub unsafe extern "C" fn SCDetectU8Free(ctx: &mut DetectUintData) { std::mem::drop(Box::from_raw(ctx)); } +#[no_mangle] +pub unsafe extern "C" fn SCDetectU8ArrayParse(ustr: *const std::os::raw::c_char) -> *mut c_void { + let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe + if let Ok(s) = ft_name.to_str() { + if let Some(ctx) = detect_parse_array_uint::(s) { + let boxed = Box::new(ctx); + // DetectUintArrayData cannot be cbindgend + return Box::into_raw(boxed) as *mut c_void; + } + } + return std::ptr::null_mut(); +} + +#[no_mangle] +pub unsafe extern "C" fn SCDetectU8ArrayFree(ctx: &mut DetectUintArrayData) { + std::mem::drop(Box::from_raw(ctx)); +} + #[no_mangle] pub unsafe extern "C" fn SCDetectU16Parse( ustr: *const std::os::raw::c_char, diff --git a/rust/src/http2/detect.rs b/rust/src/http2/detect.rs index d9a28f947b..bb5a113c17 100644 --- a/rust/src/http2/detect.rs +++ b/rust/src/http2/detect.rs @@ -19,7 +19,9 @@ use super::http2::{ HTTP2Event, HTTP2Frame, HTTP2FrameTypeData, HTTP2State, HTTP2Transaction, HTTP2TransactionState, }; use super::parser; -use crate::detect::uint::{detect_match_uint, DetectUintData}; +use crate::detect::uint::{ + detect_match_uint, detect_uint_match_at_index, DetectUintArrayData, DetectUintData, +}; use crate::direction::Direction; use base64::{engine::general_purpose::STANDARD, Engine}; use std::ffi::CStr; @@ -128,64 +130,38 @@ pub unsafe extern "C" fn SCHttp2ParseErrorCode( return -1; } -fn http2_tx_get_next_priority( - tx: &HTTP2Transaction, direction: Direction, nb: u32, -) -> std::os::raw::c_int { - let mut pos = 0_u32; - if direction == Direction::ToServer { - for i in 0..tx.frames_ts.len() { - match &tx.frames_ts[i].data { - HTTP2FrameTypeData::PRIORITY(prio) => { - if pos == nb { - return prio.weight as i32; - } else { - pos += 1; - } - } - HTTP2FrameTypeData::HEADERS(hd) => { - if let Some(prio) = hd.priority { - if pos == nb { - return prio.weight as i32; - } else { - pos += 1; - } - } - } - _ => {} +fn get_http2_priority(frame: &HTTP2Frame) -> Option { + return match &frame.data { + HTTP2FrameTypeData::PRIORITY(prio) => Some(prio.weight), + HTTP2FrameTypeData::HEADERS(hd) => { + if let Some(prio) = hd.priority { + return Some(prio.weight); } + None } + _ => None, + }; +} + +fn http2_match_priority( + tx: &HTTP2Transaction, direction: Direction, ctx: &DetectUintArrayData, +) -> std::os::raw::c_int { + let frames = if direction == Direction::ToServer { + &tx.frames_ts } else { - for i in 0..tx.frames_tc.len() { - match &tx.frames_tc[i].data { - HTTP2FrameTypeData::PRIORITY(prio) => { - if pos == nb { - return prio.weight as i32; - } else { - pos += 1; - } - } - HTTP2FrameTypeData::HEADERS(hd) => { - if let Some(prio) = hd.priority { - if pos == nb { - return prio.weight as i32; - } else { - pos += 1; - } - } - } - _ => {} - } - } - } - return -1; + &tx.frames_tc + }; + + return detect_uint_match_at_index::(frames, ctx, get_http2_priority); } #[no_mangle] -pub unsafe extern "C" fn SCHttp2TxGetNextPriority( - tx: *mut std::os::raw::c_void, direction: u8, nb: u32, +pub unsafe extern "C" fn SCHttp2PriorityMatch( + tx: *mut std::os::raw::c_void, direction: u8, ctx: *const std::os::raw::c_void, ) -> std::os::raw::c_int { let tx = cast_pointer!(tx, HTTP2Transaction); - return http2_tx_get_next_priority(tx, direction.into(), nb); + let ctx = cast_pointer!(ctx, DetectUintArrayData); + return http2_match_priority(tx, direction.into(), ctx); } fn http2_tx_get_next_window( diff --git a/src/detect-http2.c b/src/detect-http2.c index 181fdf537f..f56e0f1834 100644 --- a/src/detect-http2.c +++ b/src/detect-http2.c @@ -362,17 +362,7 @@ static int DetectHTTP2priorityMatch(DetectEngineThreadCtx *det_ctx, const SigMatchCtx *ctx) { - uint32_t nb = 0; - int value = SCHttp2TxGetNextPriority(txv, flags, nb); - const DetectU8Data *du8 = (const DetectU8Data *)ctx; - while (value >= 0) { - if (DetectU8Match((uint8_t)value, du8)) { - return 1; - } - nb++; - value = SCHttp2TxGetNextPriority(txv, flags, nb); - } - return 0; + return SCHttp2PriorityMatch(txv, flags, ctx); } /** @@ -390,7 +380,7 @@ static int DetectHTTP2prioritySetup (DetectEngineCtx *de_ctx, Signature *s, cons if (SCDetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0) return -1; - DetectU8Data *prio = DetectU8Parse(str); + DetectU8Data *prio = SCDetectU8ArrayParse(str); if (prio == NULL) return -1; @@ -410,7 +400,7 @@ static int DetectHTTP2prioritySetup (DetectEngineCtx *de_ctx, Signature *s, cons */ void DetectHTTP2priorityFree(DetectEngineCtx *de_ctx, void *ptr) { - SCDetectU8Free(ptr); + SCDetectU8ArrayFree(ptr); } /**