http2/detect: http2.priority can now use index

Ticket: 7480
pull/13878/head
Philippe Antoine 2 months ago committed by Victor Julien
parent 9fc407fd75
commit 83868778b9

@ -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 <rules-integer-keywords>`.
http2.priority is also a :ref:`multi-integer <multi-integers>`.
This keyword takes a numeric argument after a colon and supports additional qualifiers, such as:
* ``>`` (greater than)

@ -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<T> {
}
#[derive(Debug, PartialEq)]
pub(crate) enum DetectUintIndex {
pub enum DetectUintIndex {
Any,
All,
Index(i32),
}
#[derive(Debug, PartialEq)]
pub(crate) struct DetectUintArrayData<T> {
pub struct DetectUintArrayData<T> {
pub du: DetectUintData<T>,
pub index: DetectUintIndex,
}
@ -80,6 +80,18 @@ fn parse_uint_index(parts: &[&str]) -> Option<DetectUintIndex> {
return Some(index);
}
pub(crate) fn detect_parse_array_uint<T: DetectIntType>(s: &str) -> Option<DetectUintArrayData<T>> {
let parts: Vec<&str> = s.split(',').collect();
if parts.len() > 2 {
return None;
}
let index = parse_uint_index(&parts)?;
let (_, du) = detect_parse_uint::<T>(parts[0]).ok()?;
Some(DetectUintArrayData { du, index })
}
pub(crate) fn detect_parse_array_uint_enum<T1: DetectIntType, T2: EnumString<T1>>(
s: &str,
) -> Option<DetectUintArrayData<T1>> {
@ -553,6 +565,24 @@ pub unsafe extern "C" fn SCDetectU8Free(ctx: &mut DetectUintData<u8>) {
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::<u8>(s) {
let boxed = Box::new(ctx);
// DetectUintArrayData<u8> 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<u8>) {
std::mem::drop(Box::from_raw(ctx));
}
#[no_mangle]
pub unsafe extern "C" fn SCDetectU16Parse(
ustr: *const std::os::raw::c_char,

@ -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<u8> {
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<u8>,
) -> 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::<HTTP2Frame, u8>(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<u8>);
return http2_match_priority(tx, direction.into(), ctx);
}
fn http2_tx_get_next_window(

@ -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);
}
/**

Loading…
Cancel
Save