From: Philippe Antoine Date: Mon, 31 May 2021 09:40:42 +0000 (+0200) Subject: http2: generic http2_header_blocks X-Git-Tag: suricata-7.0.0-beta1~1428 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e3ff0e7731e8d652ee7f22945311674e65455a74;p=thirdparty%2Fsuricata.git http2: generic http2_header_blocks so as not to forget continuation and push promise when iterating over headers --- diff --git a/rust/src/http2/detect.rs b/rust/src/http2/detect.rs index 979c8c08a4..05ea3f8b94 100644 --- a/rust/src/http2/detect.rs +++ b/rust/src/http2/detect.rs @@ -341,38 +341,38 @@ pub unsafe extern "C" fn rs_detect_u64_free(ctx: *mut std::os::raw::c_void) { } fn http2_detect_sizeupdate_match( - hd: &parser::HTTP2FrameHeaders, ctx: &parser::DetectU64Data, + blocks: &Vec, ctx: &parser::DetectU64Data, ) -> std::os::raw::c_int { - for i in 0..hd.blocks.len() { + for i in 0..blocks.len() { match ctx.mode { parser::DetectUintMode::DetectUintModeEqual => { - if hd.blocks[i].sizeupdate == ctx.value - && hd.blocks[i].error + if blocks[i].sizeupdate == ctx.value + && blocks[i].error == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate { return 1; } } parser::DetectUintMode::DetectUintModeLt => { - if hd.blocks[i].sizeupdate <= ctx.value - && hd.blocks[i].error + if blocks[i].sizeupdate <= ctx.value + && blocks[i].error == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate { return 1; } } parser::DetectUintMode::DetectUintModeGt => { - if hd.blocks[i].sizeupdate >= ctx.value - && hd.blocks[i].error + if blocks[i].sizeupdate >= ctx.value + && blocks[i].error == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate { return 1; } } parser::DetectUintMode::DetectUintModeRange => { - if hd.blocks[i].sizeupdate <= ctx.value - && hd.blocks[i].sizeupdate >= ctx.valrange - && hd.blocks[i].error + if blocks[i].sizeupdate <= ctx.value + && blocks[i].sizeupdate >= ctx.valrange + && blocks[i].error == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate { return 1; @@ -383,29 +383,39 @@ fn http2_detect_sizeupdate_match( return 0; } +fn http2_header_blocks(frame: &HTTP2Frame) -> Option<&Vec> { + match &frame.data { + HTTP2FrameTypeData::HEADERS(hd) => { + return Some(&hd.blocks); + } + HTTP2FrameTypeData::CONTINUATION(hd) => { + return Some(&hd.blocks); + } + HTTP2FrameTypeData::PUSHPROMISE(hd) => { + return Some(&hd.blocks); + } + _ => {} + } + return None; +} + fn http2_detect_sizeupdatectx_match( ctx: &mut parser::DetectU64Data, tx: &mut HTTP2Transaction, direction: u8, ) -> std::os::raw::c_int { if direction & STREAM_TOSERVER != 0 { for i in 0..tx.frames_ts.len() { - match &tx.frames_ts[i].data { - HTTP2FrameTypeData::HEADERS(hd) => { - if http2_detect_sizeupdate_match(hd, ctx) != 0 { - return 1; - } + if let Some(blocks) = http2_header_blocks(&tx.frames_ts[i]) { + if http2_detect_sizeupdate_match(blocks, ctx) != 0 { + return 1; } - _ => {} } } } else { for i in 0..tx.frames_tc.len() { - match &tx.frames_tc[i].data { - HTTP2FrameTypeData::HEADERS(hd) => { - if http2_detect_sizeupdate_match(hd, ctx) != 0 { - return 1; - } + if let Some(blocks) = http2_header_blocks(&tx.frames_tc[i]) { + if http2_detect_sizeupdate_match(blocks, ctx) != 0 { + return 1; } - _ => {} } } } @@ -430,34 +440,28 @@ pub unsafe extern "C" fn rs_http2_tx_get_header_name( let mut pos = 0 as u32; if direction & STREAM_TOSERVER != 0 { for i in 0..tx.frames_ts.len() { - match &tx.frames_ts[i].data { - HTTP2FrameTypeData::HEADERS(hd) => { - if nb < pos + hd.blocks.len() as u32 { - let value = &hd.blocks[(nb - pos) as usize].name; - *buffer = value.as_ptr(); //unsafe - *buffer_len = value.len() as u32; - return 1; - } else { - pos = pos + hd.blocks.len() as u32; - } + if let Some(blocks) = http2_header_blocks(&tx.frames_ts[i]) { + if nb < pos + blocks.len() as u32 { + let value = &blocks[(nb - pos) as usize].name; + *buffer = value.as_ptr(); //unsafe + *buffer_len = value.len() as u32; + return 1; + } else { + pos = pos + blocks.len() as u32; } - _ => {} } } } else { for i in 0..tx.frames_tc.len() { - match &tx.frames_tc[i].data { - HTTP2FrameTypeData::HEADERS(hd) => { - if nb < pos + hd.blocks.len() as u32 { - let value = &hd.blocks[(nb - pos) as usize].name; - *buffer = value.as_ptr(); //unsafe - *buffer_len = value.len() as u32; - return 1; - } else { - pos = pos + hd.blocks.len() as u32; - } + if let Some(blocks) = http2_header_blocks(&tx.frames_tc[i]) { + if nb < pos + blocks.len() as u32 { + let value = &blocks[(nb - pos) as usize].name; + *buffer = value.as_ptr(); //unsafe + *buffer_len = value.len() as u32; + return 1; + } else { + pos = pos + blocks.len() as u32; } - _ => {} } } } @@ -479,23 +483,10 @@ fn http2_frames_get_header_value<'a>( frames: &'a Vec, name: &str, ) -> Result<&'a [u8], ()> { for i in 0..frames.len() { - match &frames[i].data { - HTTP2FrameTypeData::HEADERS(hd) => { - if let Ok(value) = http2_blocks_get_header_value(&hd.blocks, name) { - return Ok(value); - } + if let Some(blocks) = http2_header_blocks(&frames[i]) { + if let Ok(value) = http2_blocks_get_header_value(&blocks, name) { + return Ok(value); } - HTTP2FrameTypeData::PUSHPROMISE(hd) => { - if let Ok(value) = http2_blocks_get_header_value(&hd.blocks, name) { - return Ok(value); - } - } - HTTP2FrameTypeData::CONTINUATION(hd) => { - if let Ok(value) = http2_blocks_get_header_value(&hd.blocks, name) { - return Ok(value); - } - } - _ => {} } } @@ -657,21 +648,21 @@ pub unsafe extern "C" fn rs_http2_tx_get_header_value( return 0; } -fn http2_escape_header(hd: &parser::HTTP2FrameHeaders, i: u32) -> Vec { +fn http2_escape_header(blocks: &Vec, i: u32) -> Vec { //minimum size + 2 for escapes - let normalsize = hd.blocks[i as usize].value.len() + 2 + hd.blocks[i as usize].name.len() + 2; + let normalsize = blocks[i as usize].value.len() + 2 + blocks[i as usize].name.len() + 2; let mut vec = Vec::with_capacity(normalsize); - for j in 0..hd.blocks[i as usize].name.len() { - vec.push(hd.blocks[i as usize].name[j]); - if hd.blocks[i as usize].name[j] == ':' as u8 { + for j in 0..blocks[i as usize].name.len() { + vec.push(blocks[i as usize].name[j]); + if blocks[i as usize].name[j] == ':' as u8 { vec.push(':' as u8); } } vec.push(':' as u8); vec.push(' ' as u8); - for j in 0..hd.blocks[i as usize].value.len() { - vec.push(hd.blocks[i as usize].value[j]); - if hd.blocks[i as usize].value[j] == ':' as u8 { + for j in 0..blocks[i as usize].value.len() { + vec.push(blocks[i as usize].value[j]); + if blocks[i as usize].value[j] == ':' as u8 { vec.push(':' as u8); } } @@ -691,16 +682,13 @@ pub unsafe extern "C" fn rs_http2_tx_get_header_names( &tx.frames_tc }; for i in 0..frames.len() { - match &frames[i].data { - HTTP2FrameTypeData::HEADERS(hd) => { - for j in 0..hd.blocks.len() { - // we do not escape linefeeds in headers names - vec.extend_from_slice(&hd.blocks[j].name); - vec.push('\r' as u8); - vec.push('\n' as u8); - } + if let Some(blocks) = http2_header_blocks(&frames[i]) { + for j in 0..blocks.len() { + // we do not escape linefeeds in headers names + vec.extend_from_slice(&blocks[j].name); + vec.push('\r' as u8); + vec.push('\n' as u8); } - _ => {} } } if vec.len() > 2 { @@ -762,21 +750,18 @@ pub unsafe extern "C" fn rs_http2_tx_get_headers( &tx.frames_tc }; for i in 0..frames.len() { - match &frames[i].data { - HTTP2FrameTypeData::HEADERS(hd) => { - for j in 0..hd.blocks.len() { - if !http2_header_iscookie(direction, &hd.blocks[j].name) { - // we do not escape linefeeds nor : in headers names - vec.extend_from_slice(&hd.blocks[j].name); - vec.push(':' as u8); - vec.push(' ' as u8); - vec.extend_from_slice(http2_header_trimspaces(&hd.blocks[j].value)); - vec.push('\r' as u8); - vec.push('\n' as u8); - } + if let Some(blocks) = http2_header_blocks(&frames[i]) { + for j in 0..blocks.len() { + if !http2_header_iscookie(direction, &blocks[j].name) { + // we do not escape linefeeds nor : in headers names + vec.extend_from_slice(&blocks[j].name); + vec.push(':' as u8); + vec.push(' ' as u8); + vec.extend_from_slice(http2_header_trimspaces(&blocks[j].value)); + vec.push('\r' as u8); + vec.push('\n' as u8); } } - _ => {} } } if vec.len() > 0 { @@ -801,19 +786,16 @@ pub unsafe extern "C" fn rs_http2_tx_get_headers_raw( &tx.frames_tc }; for i in 0..frames.len() { - match &frames[i].data { - HTTP2FrameTypeData::HEADERS(hd) => { - for j in 0..hd.blocks.len() { - // we do not escape linefeeds nor : in headers names - vec.extend_from_slice(&hd.blocks[j].name); - vec.push(':' as u8); - vec.push(' ' as u8); - vec.extend_from_slice(&hd.blocks[j].value); - vec.push('\r' as u8); - vec.push('\n' as u8); - } + if let Some(blocks) = http2_header_blocks(&frames[i]) { + for j in 0..blocks.len() { + // we do not escape linefeeds nor : in headers names + vec.extend_from_slice(&blocks[j].name); + vec.push(':' as u8); + vec.push(' ' as u8); + vec.extend_from_slice(&blocks[j].value); + vec.push('\r' as u8); + vec.push('\n' as u8); } - _ => {} } } if vec.len() > 0 { @@ -834,40 +816,34 @@ pub unsafe extern "C" fn rs_http2_tx_get_header( let mut pos = 0 as u32; if direction & STREAM_TOSERVER != 0 { for i in 0..tx.frames_ts.len() { - match &tx.frames_ts[i].data { - HTTP2FrameTypeData::HEADERS(hd) => { - if nb < pos + hd.blocks.len() as u32 { - let ehdr = http2_escape_header(hd, nb - pos); - tx.escaped.push(ehdr); - let idx = tx.escaped.len() - 1; - let value = &tx.escaped[idx]; - *buffer = value.as_ptr(); //unsafe - *buffer_len = value.len() as u32; - return 1; - } else { - pos = pos + hd.blocks.len() as u32; - } + if let Some(blocks) = http2_header_blocks(&tx.frames_ts[i]) { + if nb < pos + blocks.len() as u32 { + let ehdr = http2_escape_header(&blocks, nb - pos); + tx.escaped.push(ehdr); + let idx = tx.escaped.len() - 1; + let value = &tx.escaped[idx]; + *buffer = value.as_ptr(); //unsafe + *buffer_len = value.len() as u32; + return 1; + } else { + pos = pos + blocks.len() as u32; } - _ => {} } } } else { for i in 0..tx.frames_tc.len() { - match &tx.frames_tc[i].data { - HTTP2FrameTypeData::HEADERS(hd) => { - if nb < pos + hd.blocks.len() as u32 { - let ehdr = http2_escape_header(hd, nb - pos); - tx.escaped.push(ehdr); - let idx = tx.escaped.len() - 1; - let value = &tx.escaped[idx]; - *buffer = value.as_ptr(); //unsafe - *buffer_len = value.len() as u32; - return 1; - } else { - pos = pos + hd.blocks.len() as u32; - } + if let Some(blocks) = http2_header_blocks(&tx.frames_tc[i]) { + if nb < pos + blocks.len() as u32 { + let ehdr = http2_escape_header(&blocks, nb - pos); + tx.escaped.push(ehdr); + let idx = tx.escaped.len() - 1; + let value = &tx.escaped[idx]; + *buffer = value.as_ptr(); //unsafe + *buffer_len = value.len() as u32; + return 1; + } else { + pos = pos + blocks.len() as u32; } - _ => {} } } }