diff --git a/doc/userguide/rules/http2-keywords.rst b/doc/userguide/rules/http2-keywords.rst index 05281d13e9..aefb701412 100644 --- a/doc/userguide/rules/http2-keywords.rst +++ b/doc/userguide/rules/http2-keywords.rst @@ -63,6 +63,8 @@ Match on the value of the HTTP2 value field present in a WINDOWUPDATE frame. http2.window uses an :ref:`unsigned 32-bit integer `. +http2.window 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 b956e23868..13cf48a22c 100644 --- a/rust/src/detect/uint.rs +++ b/rust/src/detect/uint.rs @@ -583,6 +583,24 @@ pub unsafe extern "C" fn SCDetectU8ArrayFree(ctx: &mut DetectUintArrayData) std::mem::drop(Box::from_raw(ctx)); } +#[no_mangle] +pub unsafe extern "C" fn SCDetectU32ArrayParse(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); + return Box::into_raw(boxed) as *mut c_void; + } + } + return std::ptr::null_mut(); +} + +#[no_mangle] +pub unsafe extern "C" fn SCDetectU32ArrayFree(ctx: &mut DetectUintData) { + // Just unbox... + 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 bb5a113c17..b1a1391b10 100644 --- a/rust/src/http2/detect.rs +++ b/rust/src/http2/detect.rs @@ -164,40 +164,31 @@ pub unsafe extern "C" fn SCHttp2PriorityMatch( return http2_match_priority(tx, direction.into(), ctx); } -fn http2_tx_get_next_window( - tx: &HTTP2Transaction, direction: Direction, nb: u32, +fn get_http2_window(frame: &HTTP2Frame) -> Option { + if let HTTP2FrameTypeData::WINDOWUPDATE(wu) = &frame.data { + return Some(wu.sizeinc); + } + return None; +} + +fn http2_match_window( + tx: &HTTP2Transaction, direction: Direction, ctx: &DetectUintArrayData, ) -> std::os::raw::c_int { - let mut pos = 0_u32; - if direction == Direction::ToServer { - for i in 0..tx.frames_ts.len() { - if let HTTP2FrameTypeData::WINDOWUPDATE(wu) = tx.frames_ts[i].data { - if pos == nb { - return wu.sizeinc as i32; - } else { - pos += 1; - } - } - } + let frames = if direction == Direction::ToServer { + &tx.frames_ts } else { - for i in 0..tx.frames_tc.len() { - if let HTTP2FrameTypeData::WINDOWUPDATE(wu) = tx.frames_tc[i].data { - if pos == nb { - return wu.sizeinc as i32; - } else { - pos += 1; - } - } - } - } - return -1; + &tx.frames_tc + }; + return detect_uint_match_at_index::(frames, ctx, get_http2_window); } #[no_mangle] -pub unsafe extern "C" fn SCHttp2TxGetNextWindow( - tx: *mut std::os::raw::c_void, direction: u8, nb: u32, +pub unsafe extern "C" fn SCHttp2WindowMatch( + 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_window(tx, direction.into(), nb); + let ctx = cast_pointer!(ctx, DetectUintArrayData); + return http2_match_window(tx, direction.into(), ctx); } #[no_mangle] diff --git a/src/detect-http2.c b/src/detect-http2.c index f56e0f1834..cde2e8eee2 100644 --- a/src/detect-http2.c +++ b/src/detect-http2.c @@ -94,6 +94,7 @@ void DetectHTTP2RegisterTests (void); #endif static int g_http2_match_buffer_id = 0; +static int g_http2_complete_buffer_id = 0; static int g_http2_header_name_buffer_id = 0; /** @@ -190,6 +191,13 @@ void DetectHttp2Register(void) "http2", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL); g_http2_match_buffer_id = DetectBufferTypeRegister("http2"); + + DetectAppLayerInspectEngineRegister("http2_complete", ALPROTO_HTTP2, SIG_FLAG_TOSERVER, + HTTP2StateClosed, DetectEngineInspectGenericList, NULL); + DetectAppLayerInspectEngineRegister("http2_complete", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, + HTTP2StateClosed, DetectEngineInspectGenericList, NULL); + + g_http2_complete_buffer_id = DetectBufferTypeRegister("http2_complete"); } /** @@ -414,17 +422,7 @@ static int DetectHTTP2windowMatch(DetectEngineThreadCtx *det_ctx, const SigMatchCtx *ctx) { - uint32_t nb = 0; - int value = SCHttp2TxGetNextWindow(txv, flags, nb); - const DetectU32Data *du32 = (const DetectU32Data *)ctx; - while (value >= 0) { - if (DetectU32Match(value, du32)) { - return 1; - } - nb++; - value = SCHttp2TxGetNextWindow(txv, flags, nb); - } - return 0; + return SCHttp2WindowMatch(txv, flags, ctx); } /** @@ -442,12 +440,13 @@ static int DetectHTTP2windowSetup (DetectEngineCtx *de_ctx, Signature *s, const if (SCDetectSignatureSetAppProto(s, ALPROTO_HTTP2) != 0) return -1; - DetectU32Data *wu = DetectU32Parse(str); + DetectU32Data *wu = SCDetectU32ArrayParse(str); if (wu == NULL) return -1; + // use g_http2_complete_buffer_id as we may have window changes in any state if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_HTTP2_WINDOW, (SigMatchCtx *)wu, - g_http2_match_buffer_id) == NULL) { + g_http2_complete_buffer_id) == NULL) { SCDetectU32Free(wu); return -1; } @@ -462,7 +461,7 @@ static int DetectHTTP2windowSetup (DetectEngineCtx *de_ctx, Signature *s, const */ void DetectHTTP2windowFree(DetectEngineCtx *de_ctx, void *ptr) { - SCDetectU32Free(ptr); + SCDetectU32ArrayFree(ptr); } /**