diff --git a/rust/src/http2/http2.rs b/rust/src/http2/http2.rs index ba5b44e7f0..821921c5c7 100644 --- a/rust/src/http2/http2.rs +++ b/rust/src/http2/http2.rs @@ -24,7 +24,7 @@ use crate::applayer::{self, *}; use crate::core::*; use crate::filecontainer::*; use crate::filetracker::*; -use nom; +use nom7::Err; use std; use std::ffi::CString; use std::fmt; @@ -647,7 +647,7 @@ impl HTTP2State { //we could set an event on remaining data return HTTP2FrameTypeData::SETTINGS(set); } - Err(nom::Err::Incomplete(_)) => { + Err(Err::Incomplete(_)) => { if complete { self.set_event(HTTP2Event::InvalidFrameData); return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled { @@ -738,7 +738,7 @@ impl HTTP2State { self.process_headers(&hs.blocks, dir); return HTTP2FrameTypeData::PUSHPROMISE(hs); } - Err(nom::Err::Incomplete(_)) => { + Err(Err::Incomplete(_)) => { if complete { self.set_event(HTTP2Event::InvalidFrameData); return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled { @@ -772,7 +772,7 @@ impl HTTP2State { self.process_headers(&hs.blocks, dir); return HTTP2FrameTypeData::CONTINUATION(hs); } - Err(nom::Err::Incomplete(_)) => { + Err(Err::Incomplete(_)) => { if complete { self.set_event(HTTP2Event::InvalidFrameData); return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled { @@ -807,7 +807,7 @@ impl HTTP2State { } return HTTP2FrameTypeData::HEADERS(hs); } - Err(nom::Err::Incomplete(_)) => { + Err(Err::Incomplete(_)) => { if complete { self.set_event(HTTP2Event::InvalidFrameData); return HTTP2FrameTypeData::UNHANDLED(HTTP2FrameUnhandled { @@ -929,7 +929,7 @@ impl HTTP2State { } input = &rem[hlsafe..]; } - Err(nom::Err::Incomplete(_)) => { + Err(Err::Incomplete(_)) => { //we may have consumed data from previous records return AppLayerResult::incomplete( (il - input.len()) as u32, @@ -1035,7 +1035,7 @@ pub unsafe extern "C" fn rs_http2_probing_parser_tc( } return ALPROTO_HTTP2; } - Err(nom::Err::Incomplete(_)) => { + Err(Err::Incomplete(_)) => { return ALPROTO_UNKNOWN; } Err(_) => { diff --git a/rust/src/http2/huffman.rs b/rust/src/http2/huffman.rs index 05ec03a5f0..b03fcf3b88 100644 --- a/rust/src/http2/huffman.rs +++ b/rust/src/http2/huffman.rs @@ -15,9 +15,11 @@ * 02110-1301, USA. */ -use nom::error::ErrorKind; -use nom::Err; -use nom::IResult; +use nom7::bits::streaming::take as take_bits; +use nom7::branch::alt; +use nom7::combinator::{complete, map_opt}; +use nom7::error::{make_error, ErrorKind}; +use nom7::{Err, IResult}; fn http2_huffman_table_len5(n: u32) -> Option { match n { @@ -35,9 +37,9 @@ fn http2_huffman_table_len5(n: u32) -> Option { } } -named!(http2_decode_huffman_len5<(&[u8], usize), u8>, - complete!( map_opt!(take_bits!(5u32), http2_huffman_table_len5) ) -); +fn http2_decode_huffman_len5(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(5u32), http2_huffman_table_len5))(input) +} fn http2_huffman_table_len6(n: u32) -> Option { match n { @@ -71,9 +73,9 @@ fn http2_huffman_table_len6(n: u32) -> Option { } } -named!(http2_decode_huffman_len6<(&[u8], usize), u8>, - complete!( map_opt!(take_bits!(6u32), http2_huffman_table_len6)) -); +fn http2_decode_huffman_len6(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(6u32), http2_huffman_table_len6))(input) +} fn http2_huffman_table_len7(n: u32) -> Option { match n { @@ -113,9 +115,9 @@ fn http2_huffman_table_len7(n: u32) -> Option { } } -named!(http2_decode_huffman_len7<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(7u32), http2_huffman_table_len7)) -); +fn http2_decode_huffman_len7(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(7u32), http2_huffman_table_len7))(input) +} fn http2_huffman_table_len8(n: u32) -> Option { match n { @@ -129,9 +131,9 @@ fn http2_huffman_table_len8(n: u32) -> Option { } } -named!(http2_decode_huffman_len8<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(8u32), http2_huffman_table_len8)) -); +fn http2_decode_huffman_len8(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(8u32), http2_huffman_table_len8))(input) +} fn http2_huffman_table_len10(n: u32) -> Option { match n { @@ -144,9 +146,9 @@ fn http2_huffman_table_len10(n: u32) -> Option { } } -named!(http2_decode_huffman_len10<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(10u32), http2_huffman_table_len10)) -); +fn http2_decode_huffman_len10(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(10u32), http2_huffman_table_len10))(input) +} fn http2_huffman_table_len11(n: u32) -> Option { match n { @@ -157,9 +159,9 @@ fn http2_huffman_table_len11(n: u32) -> Option { } } -named!(http2_decode_huffman_len11<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(11u32), http2_huffman_table_len11)) -); +fn http2_decode_huffman_len11(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(11u32), http2_huffman_table_len11))(input) +} fn http2_huffman_table_len12(n: u32) -> Option { match n { @@ -169,9 +171,9 @@ fn http2_huffman_table_len12(n: u32) -> Option { } } -named!(http2_decode_huffman_len12<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(12u32), http2_huffman_table_len12)) -); +fn http2_decode_huffman_len12(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(12u32), http2_huffman_table_len12))(input) +} fn http2_huffman_table_len13(n: u32) -> Option { match n { @@ -185,9 +187,9 @@ fn http2_huffman_table_len13(n: u32) -> Option { } } -named!(http2_decode_huffman_len13<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(13u32), http2_huffman_table_len13)) -); +fn http2_decode_huffman_len13(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(13u32), http2_huffman_table_len13))(input) +} fn http2_huffman_table_len14(n: u32) -> Option { match n { @@ -197,9 +199,9 @@ fn http2_huffman_table_len14(n: u32) -> Option { } } -named!(http2_decode_huffman_len14<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(14u32), http2_huffman_table_len14)) -); +fn http2_decode_huffman_len14(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(14u32), http2_huffman_table_len14))(input) +} fn http2_huffman_table_len15(n: u32) -> Option { match n { @@ -210,9 +212,9 @@ fn http2_huffman_table_len15(n: u32) -> Option { } } -named!(http2_decode_huffman_len15<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(15u32), http2_huffman_table_len15)) -); +fn http2_decode_huffman_len15(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(15u32), http2_huffman_table_len15))(input) +} fn http2_huffman_table_len19(n: u32) -> Option { match n { @@ -223,9 +225,9 @@ fn http2_huffman_table_len19(n: u32) -> Option { } } -named!(http2_decode_huffman_len19<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(19u32), http2_huffman_table_len19)) -); +fn http2_decode_huffman_len19(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(19u32), http2_huffman_table_len19))(input) +} fn http2_huffman_table_len20(n: u32) -> Option { match n { @@ -241,9 +243,9 @@ fn http2_huffman_table_len20(n: u32) -> Option { } } -named!(http2_decode_huffman_len20<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(20u32), http2_huffman_table_len20)) -); +fn http2_decode_huffman_len20(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(20u32), http2_huffman_table_len20))(input) +} fn http2_huffman_table_len21(n: u32) -> Option { match n { @@ -264,9 +266,9 @@ fn http2_huffman_table_len21(n: u32) -> Option { } } -named!(http2_decode_huffman_len21<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(21u32), http2_huffman_table_len21)) -); +fn http2_decode_huffman_len21(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(21u32), http2_huffman_table_len21))(input) +} fn http2_huffman_table_len22(n: u32) -> Option { match n { @@ -300,9 +302,9 @@ fn http2_huffman_table_len22(n: u32) -> Option { } } -named!(http2_decode_huffman_len22<(&[u8], usize), u8>, -complete!( map_opt!(take_bits!(22u32), http2_huffman_table_len22)) -); +fn http2_decode_huffman_len22(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(22u32), http2_huffman_table_len22))(input) +} fn http2_huffman_table_len23(n: u32) -> Option { match n { @@ -339,9 +341,9 @@ fn http2_huffman_table_len23(n: u32) -> Option { } } -named!(http2_decode_huffman_len23<(&[u8], usize), u8>, - complete!( map_opt!(take_bits!(23u32), http2_huffman_table_len23)) -); +fn http2_decode_huffman_len23(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(23u32), http2_huffman_table_len23))(input) +} fn http2_huffman_table_len24(n: u32) -> Option { match n { @@ -361,9 +363,9 @@ fn http2_huffman_table_len24(n: u32) -> Option { } } -named!(http2_decode_huffman_len24<(&[u8], usize), u8>, - complete!( map_opt!(take_bits!(24u32), http2_huffman_table_len24)) -); +fn http2_decode_huffman_len24(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(24u32), http2_huffman_table_len24))(input) +} fn http2_huffman_table_len25(n: u32) -> Option { match n { @@ -375,9 +377,9 @@ fn http2_huffman_table_len25(n: u32) -> Option { } } -named!(http2_decode_huffman_len25<(&[u8], usize), u8>, - complete!( map_opt!(take_bits!(25u32), http2_huffman_table_len25)) -); +fn http2_decode_huffman_len25(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(25u32), http2_huffman_table_len25))(input) +} fn http2_huffman_table_len26(n: u32) -> Option { match n { @@ -400,9 +402,9 @@ fn http2_huffman_table_len26(n: u32) -> Option { } } -named!(http2_decode_huffman_len26<(&[u8], usize), u8>, - complete!( map_opt!(take_bits!(26u32), http2_huffman_table_len26)) -); +fn http2_decode_huffman_len26((i, bit_offset): (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(26u32), http2_huffman_table_len26))((i, bit_offset)) +} fn http2_huffman_table_len27(n: u32) -> Option { match n { @@ -429,9 +431,9 @@ fn http2_huffman_table_len27(n: u32) -> Option { } } -named!(http2_decode_huffman_len27<(&[u8], usize), u8>, - complete!( map_opt!(take_bits!(27u32), http2_huffman_table_len27)) -); +fn http2_decode_huffman_len27(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(27u32), http2_huffman_table_len27))(input) +} fn http2_huffman_table_len28(n: u32) -> Option { match n { @@ -468,9 +470,9 @@ fn http2_huffman_table_len28(n: u32) -> Option { } } -named!(http2_decode_huffman_len28<(&[u8], usize), u8>, - complete!( map_opt!(take_bits!(28u32), http2_huffman_table_len28)) -); +fn http2_decode_huffman_len28(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(28u32), http2_huffman_table_len28))(input) +} fn http2_huffman_table_len30(n: u32) -> Option { match n { @@ -482,23 +484,44 @@ fn http2_huffman_table_len30(n: u32) -> Option { } } -named!(http2_decode_huffman_len30<(&[u8], usize), u8>, - complete!( map_opt!(take_bits!(30u32), http2_huffman_table_len30)) -); +fn http2_decode_huffman_len30(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + complete(map_opt(take_bits(30u32), http2_huffman_table_len30))(input) +} //hack to end many0 even if some bits are remaining fn http2_decode_huffman_end(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { - return Err(Err::Error((input, ErrorKind::Eof))); + return Err(Err::Error(make_error(input, ErrorKind::Eof))); } //we could profile and optimize performance here -named!(pub http2_decode_huffman<(&[u8], usize), u8>, - alt!(http2_decode_huffman_len5 | http2_decode_huffman_len6 | http2_decode_huffman_len7 | - http2_decode_huffman_len8 | http2_decode_huffman_len10 | http2_decode_huffman_len11 | - http2_decode_huffman_len12 | http2_decode_huffman_len13 | http2_decode_huffman_len14 | - http2_decode_huffman_len15 | http2_decode_huffman_len19 | http2_decode_huffman_len20 | - http2_decode_huffman_len21 | http2_decode_huffman_len22 | http2_decode_huffman_len23 | - http2_decode_huffman_len24 | http2_decode_huffman_len25 | http2_decode_huffman_len26 | - http2_decode_huffman_len27 | http2_decode_huffman_len28 | http2_decode_huffman_len30 | - http2_decode_huffman_end) -); +pub fn http2_decode_huffman(input: (&[u8], usize)) -> IResult<(&[u8], usize), u8> { + // trait nom::branch::Alt is implemented for lists up to size 20, + // so use nested `alt` as a workaround (see nom documentation for `alt`) + alt(( + http2_decode_huffman_len5, + http2_decode_huffman_len6, + http2_decode_huffman_len7, + http2_decode_huffman_len8, + http2_decode_huffman_len10, + http2_decode_huffman_len11, + http2_decode_huffman_len12, + http2_decode_huffman_len13, + http2_decode_huffman_len14, + http2_decode_huffman_len15, + http2_decode_huffman_len19, + http2_decode_huffman_len20, + http2_decode_huffman_len21, + http2_decode_huffman_len21, + http2_decode_huffman_len22, + http2_decode_huffman_len23, + http2_decode_huffman_len24, + http2_decode_huffman_len25, + http2_decode_huffman_len26, + http2_decode_huffman_len27, + alt(( + http2_decode_huffman_len28, + http2_decode_huffman_len30, + http2_decode_huffman_end, + )), + ))(input) +} diff --git a/rust/src/http2/parser.rs b/rust/src/http2/parser.rs index 87e9883895..77caa5684c 100644 --- a/rust/src/http2/parser.rs +++ b/rust/src/http2/parser.rs @@ -17,12 +17,16 @@ use super::huffman; use crate::http2::http2::{HTTP2DynTable, HTTP2_MAX_TABLESIZE}; -use nom::character::complete::digit1; -use nom::combinator::rest; -use nom::error::ErrorKind; -use nom::number::streaming::{be_u16, be_u32, be_u8}; -use nom::Err; -use nom::IResult; +use nom7::bits::{bits, streaming::take as take_bits}; +use nom7::branch::alt; +use nom7::bytes::streaming::{is_a, is_not, tag, take, take_while}; +use nom7::character::complete::digit1; +use nom7::combinator::{complete, cond, map_opt, opt, rest, verify}; +use nom7::error::{make_error, Error, ErrorKind}; +use nom7::multi::many0; +use nom7::number::streaming::{be_u16, be_u24, be_u32, be_u8}; +use nom7::sequence::tuple; +use nom7::{Err, IResult}; use std::fmt; use std::str::FromStr; @@ -79,18 +83,23 @@ pub struct HTTP2FrameHeader { pub stream_id: u32, } -named!(pub http2_parse_frame_header, - do_parse!( - length: bits!( take_bits!(24u32) ) >> - ftype: be_u8 >> - flags: be_u8 >> - stream_id: bits!( tuple!( take_bits!(1u8), - take_bits!(31u32) ) ) >> - (HTTP2FrameHeader{length, ftype, flags, - reserved:stream_id.0, - stream_id:stream_id.1}) - ) -); +pub fn http2_parse_frame_header(i: &[u8]) -> IResult<&[u8], HTTP2FrameHeader> { + let (i, length) = be_u24(i)?; + let (i, ftype) = be_u8(i)?; + let (i, flags) = be_u8(i)?; + let (i, b) = be_u32(i)?; + let (reserved, stream_id) = ((b >> 31) as u8, b & 0x7fff_ffff); + Ok(( + i, + HTTP2FrameHeader { + length, + ftype, + flags, + reserved, + stream_id, + }, + )) +} #[repr(u32)] #[derive(Clone, Copy, PartialEq, FromPrimitive, Debug)] @@ -147,24 +156,20 @@ pub struct HTTP2FrameGoAway { pub errorcode: u32, //HTTP2ErrorCode } -named!(pub http2_parse_frame_goaway, - do_parse!( - errorcode: be_u32 >> - (HTTP2FrameGoAway{errorcode}) - ) -); +pub fn http2_parse_frame_goaway(i: &[u8]) -> IResult<&[u8], HTTP2FrameGoAway> { + let (i, errorcode) = be_u32(i)?; + Ok((i, HTTP2FrameGoAway { errorcode })) +} #[derive(Clone, Copy, Debug)] pub struct HTTP2FrameRstStream { pub errorcode: u32, ////HTTP2ErrorCode } -named!(pub http2_parse_frame_rststream, - do_parse!( - errorcode: be_u32 >> - (HTTP2FrameRstStream{errorcode}) - ) -); +pub fn http2_parse_frame_rststream(i: &[u8]) -> IResult<&[u8], HTTP2FrameRstStream> { + let (i, errorcode) = be_u32(i)?; + Ok((i, HTTP2FrameRstStream { errorcode })) +} #[derive(Clone, Copy, Debug)] pub struct HTTP2FramePriority { @@ -173,14 +178,19 @@ pub struct HTTP2FramePriority { pub weight: u8, } -named!(pub http2_parse_frame_priority, - do_parse!( - sid: bits!( tuple!( take_bits!(1u8), - take_bits!(31u32) ) ) >> - weight: be_u8 >> - (HTTP2FramePriority{exclusive:sid.0, dependency:sid.1, weight}) - ) -); +pub fn http2_parse_frame_priority(i: &[u8]) -> IResult<&[u8], HTTP2FramePriority> { + let (i, b) = be_u32(i)?; + let (exclusive, dependency) = ((b >> 31) as u8, b & 0x7fff_ffff); + let (i, weight) = be_u8(i)?; + Ok(( + i, + HTTP2FramePriority { + exclusive, + dependency, + weight, + }, + )) +} #[derive(Clone, Copy, Debug)] pub struct HTTP2FrameWindowUpdate { @@ -188,13 +198,11 @@ pub struct HTTP2FrameWindowUpdate { pub sizeinc: u32, } -named!(pub http2_parse_frame_windowupdate, - do_parse!( - sizeinc: bits!( tuple!( take_bits!(1u8), - take_bits!(31u32) ) ) >> - (HTTP2FrameWindowUpdate{reserved:sizeinc.0, sizeinc:sizeinc.1}) - ) -); +pub fn http2_parse_frame_windowupdate(i: &[u8]) -> IResult<&[u8], HTTP2FrameWindowUpdate> { + let (i, b) = be_u32(i)?; + let (reserved, sizeinc) = ((b >> 31) as u8, b & 0x7fff_ffff); + Ok((i, HTTP2FrameWindowUpdate { reserved, sizeinc })) +} #[derive(Clone, Copy, Debug)] pub struct HTTP2FrameHeadersPriority { @@ -203,14 +211,19 @@ pub struct HTTP2FrameHeadersPriority { pub weight: u8, } -named!(pub http2_parse_headers_priority, - do_parse!( - sid: bits!( tuple!( take_bits!(1u8), - take_bits!(31u32) ) ) >> - weight: be_u8 >> - (HTTP2FrameHeadersPriority{exclusive:sid.0, dependency:sid.1, weight}) - ) -); +pub fn http2_parse_headers_priority(i: &[u8]) -> IResult<&[u8], HTTP2FrameHeadersPriority> { + let (i, b) = be_u32(i)?; + let (exclusive, dependency) = ((b >> 31) as u8, b & 0x7fff_ffff); + let (i, weight) = be_u8(i)?; + Ok(( + i, + HTTP2FrameHeadersPriority { + exclusive, + dependency, + weight, + }, + )) +} pub const HTTP2_STATIC_HEADERS_NUMBER: usize = 61; @@ -344,39 +357,38 @@ fn http2_parse_headers_block_indexed<'a>( input: &'a [u8], dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> { fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> { - bits!( - input, - complete!(tuple!( - verify!(take_bits!(1u8), |&x| x == 1), - take_bits!(7u8) - )) - ) + bits::<_, _, Error<(&[u8], usize)>, _, _>(complete(tuple(( + verify(take_bits(1u8), |&x| x == 1), + take_bits(7u8), + ))))(input) } let (i2, indexed) = parser(input)?; let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0x7F)?; if indexreal == 0 && indexed.1 == 0x7F { - return Err(Err::Error((i3, ErrorKind::LengthValue))); + return Err(Err::Error(make_error(i3, ErrorKind::LengthValue))); } match http2_frame_header_static(indexreal, dyn_headers) { Some(h) => Ok((i3, h)), - _ => Err(Err::Error((i3, ErrorKind::MapOpt))), + _ => Err(Err::Error(make_error(i3, ErrorKind::MapOpt))), } } fn http2_parse_headers_block_string(input: &[u8]) -> IResult<&[u8], Vec> { fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> { - bits!(input, tuple!(take_bits!(1u8), take_bits!(7u8))) + let (i, b) = be_u8(input)?; + Ok((i, (b >> 7, b & 0x7f))) } let (i1, huffslen) = parser(input)?; let (i2, stringlen) = http2_parse_var_uint(i1, huffslen.1 as u64, 0x7F)?; if stringlen == 0 && huffslen.1 == 0x7F { - return Err(Err::Error((i2, ErrorKind::LengthValue))); + return Err(Err::Error(make_error(i2, ErrorKind::LengthValue))); } - let (i3, data) = take!(i2, stringlen as usize)?; + let (i3, data) = take(stringlen as usize)(i2)?; if huffslen.0 == 0 { return Ok((i3, data.to_vec())); } else { - let (_, val) = bits!(data, many0!(huffman::http2_decode_huffman))?; + let (_, val) = + bits::<_, _, Error<(&[u8], usize)>, _, _>(many0(huffman::http2_decode_huffman))(data)?; return Ok((i3, val)); } } @@ -419,18 +431,15 @@ fn http2_parse_headers_block_literal_incindex<'a>( input: &'a [u8], dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> { fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> { - bits!( - input, - complete!(tuple!( - verify!(take_bits!(2u8), |&x| x == 1), - take_bits!(6u8) - )) - ) + bits::<_, _, Error<(&[u8], usize)>, _, _>(complete(tuple(( + verify(take_bits(2u8), |&x| x == 1), + take_bits(6u8), + ))))(input) } let (i2, indexed) = parser(input)?; let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0x3F)?; if indexreal == 0 && indexed.1 == 0x3F { - return Err(Err::Error((i3, ErrorKind::LengthValue))); + return Err(Err::Error(make_error(i3, ErrorKind::LengthValue))); } let r = http2_parse_headers_block_literal_common(i3, indexreal, dyn_headers); match r { @@ -476,18 +485,15 @@ fn http2_parse_headers_block_literal_noindex<'a>( input: &'a [u8], dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> { fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> { - bits!( - input, - complete!(tuple!( - verify!(take_bits!(4u8), |&x| x == 0), - take_bits!(4u8) - )) - ) + bits::<_, _, Error<(&[u8], usize)>, _, _>(complete(tuple(( + verify(take_bits(4u8), |&x| x == 0), + take_bits(4u8), + ))))(input) } let (i2, indexed) = parser(input)?; let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0xF)?; if indexreal == 0 && indexed.1 == 0xF { - return Err(Err::Error((i3, ErrorKind::LengthValue))); + return Err(Err::Error(make_error(i3, ErrorKind::LengthValue))); } let r = http2_parse_headers_block_literal_common(i3, indexreal, dyn_headers); return r; @@ -497,18 +503,15 @@ fn http2_parse_headers_block_literal_neverindex<'a>( input: &'a [u8], dyn_headers: &HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> { fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> { - bits!( - input, - complete!(tuple!( - verify!(take_bits!(4u8), |&x| x == 1), - take_bits!(4u8) - )) - ) + bits::<_, _, Error<(&[u8], usize)>, _, _>(complete(tuple(( + verify(take_bits(4u8), |&x| x == 1), + take_bits(4u8), + ))))(input) } let (i2, indexed) = parser(input)?; let (i3, indexreal) = http2_parse_var_uint(i2, indexed.1 as u64, 0xF)?; if indexreal == 0 && indexed.1 == 0xF { - return Err(Err::Error((i3, ErrorKind::LengthValue))); + return Err(Err::Error(make_error(i3, ErrorKind::LengthValue))); } let r = http2_parse_headers_block_literal_common(i3, indexreal, dyn_headers); return r; @@ -518,7 +521,7 @@ fn http2_parse_var_uint(input: &[u8], value: u64, max: u64) -> IResult<&[u8], u6 if value < max { return Ok((input, value)); } - let (i2, varia) = take_while!(input, |ch| (ch & 0x80) != 0)?; + let (i2, varia) = take_while(|ch| (ch & 0x80) != 0)(input)?; let (i3, finalv) = be_u8(i2)?; if varia.len() > 9 || (varia.len() == 9 && finalv > 1) { // this will overflow u64 @@ -540,13 +543,10 @@ fn http2_parse_headers_block_dynamic_size<'a>( input: &'a [u8], dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaderBlock> { fn parser(input: &[u8]) -> IResult<&[u8], (u8, u8)> { - bits!( - input, - complete!(tuple!( - verify!(take_bits!(3u8), |&x| x == 1), - take_bits!(5u8) - )) - ) + bits::<_, _, Error<(&[u8], usize)>, _, _>(complete(tuple(( + verify(take_bits(3u8), |&x| x == 1), + take_bits(5u8), + ))))(input) } let (i2, maxsize) = parser(input)?; let (i3, maxsize2) = http2_parse_var_uint(i2, maxsize.1 as u64, 0x1F)?; @@ -616,12 +616,11 @@ const HTTP2_FLAG_HEADER_PRIORITY: u8 = 0x20; pub fn http2_parse_frame_headers<'a>( input: &'a [u8], flags: u8, dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FrameHeaders> { - let (i2, padlength) = cond!(input, flags & HTTP2_FLAG_HEADER_PADDED != 0, be_u8)?; - let (mut i3, priority) = cond!( - i2, + let (i2, padlength) = cond(flags & HTTP2_FLAG_HEADER_PADDED != 0, be_u8)(input)?; + let (mut i3, priority) = cond( flags & HTTP2_FLAG_HEADER_PRIORITY != 0, - http2_parse_headers_priority - )?; + http2_parse_headers_priority, + )(i2)?; let mut blocks = Vec::new(); while i3.len() > 0 { match http2_parse_headers_block(i3, dyn_headers) { @@ -630,7 +629,7 @@ pub fn http2_parse_frame_headers<'a>( debug_validate_bug_on!(i3.len() == rem.len()); if i3.len() == rem.len() { //infinite loop - return Err(Err::Error((input, ErrorKind::Eof))); + return Err(Err::Error(make_error(input, ErrorKind::Eof))); } i3 = rem; } @@ -660,8 +659,9 @@ pub struct HTTP2FramePushPromise { pub fn http2_parse_frame_push_promise<'a>( input: &'a [u8], flags: u8, dyn_headers: &mut HTTP2DynTable, ) -> IResult<&'a [u8], HTTP2FramePushPromise> { - let (i2, padlength) = cond!(input, flags & HTTP2_FLAG_HEADER_PADDED != 0, be_u8)?; - let (mut i3, stream_id) = bits!(i2, tuple!(take_bits!(1u8), take_bits!(31u32)))?; + let (i2, padlength) = cond(flags & HTTP2_FLAG_HEADER_PADDED != 0, be_u8)(input)?; + let (mut i3, stream_id) = + bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take_bits(1u8), take_bits(31u32))))(i2)?; let mut blocks = Vec::new(); while i3.len() > 0 { match http2_parse_headers_block(i3, dyn_headers) { @@ -670,7 +670,7 @@ pub fn http2_parse_frame_push_promise<'a>( debug_validate_bug_on!(i3.len() == rem.len()); if i3.len() == rem.len() { //infinite loop - return Err(Err::Error((input, ErrorKind::Eof))); + return Err(Err::Error(make_error(input, ErrorKind::Eof))); } i3 = rem; } @@ -707,7 +707,7 @@ pub fn http2_parse_frame_continuation<'a>( debug_validate_bug_on!(i3.len() == rem.len()); if i3.len() == rem.len() { //infinite loop - return Err(Err::Error((input, ErrorKind::Eof))); + return Err(Err::Error(make_error(input, ErrorKind::Eof))); } i3 = rem; } @@ -774,69 +774,86 @@ pub struct DetectHTTP2settingsSigCtx { pub value: Option, //optional value } -named!(detect_parse_u32_start_equal<&str,DetectU32Data>, - do_parse!( - opt!( is_a!( " " ) ) >> - opt! (tag!("=") ) >> - opt!( is_a!( " " ) ) >> - value : map_opt!(digit1, |s: &str| s.parse::().ok()) >> - (DetectU32Data{value, valrange:0, mode:DetectUintMode::DetectUintModeEqual}) - ) -); - -named!(detect_parse_u32_start_interval<&str,DetectU32Data>, - do_parse!( - opt!( is_a!( " " ) ) >> - value : map_opt!(digit1, |s: &str| s.parse::().ok()) >> - opt!( is_a!( " " ) ) >> - tag!("-") >> - opt!( is_a!( " " ) ) >> - valrange : map_opt!(digit1, |s: &str| s.parse::().ok()) >> - (DetectU32Data{value, valrange, mode:DetectUintMode::DetectUintModeRange}) - ) -); - -named!(detect_parse_u32_start_lesser<&str,DetectU32Data>, - do_parse!( - opt!( is_a!( " " ) ) >> - tag!("<") >> - opt!( is_a!( " " ) ) >> - value : map_opt!(digit1, |s: &str| s.parse::().ok()) >> - (DetectU32Data{value, valrange:0, mode:DetectUintMode::DetectUintModeLt}) - ) -); - -named!(detect_parse_u32_start_greater<&str,DetectU32Data>, - do_parse!( - opt!( is_a!( " " ) ) >> - tag!(">") >> - opt!( is_a!( " " ) ) >> - value : map_opt!(digit1, |s: &str| s.parse::().ok()) >> - (DetectU32Data{value, valrange:0, mode:DetectUintMode::DetectUintModeGt}) - ) -); - -named!(detect_parse_u32<&str,DetectU32Data>, - do_parse!( - u32 : alt! ( - detect_parse_u32_start_lesser | - detect_parse_u32_start_greater | - complete!( detect_parse_u32_start_interval ) | - detect_parse_u32_start_equal - ) >> - (u32) - ) -); - -named!(pub http2_parse_settingsctx<&str,DetectHTTP2settingsSigCtx>, - do_parse!( - opt!( is_a!( " " ) ) >> - id: map_opt!( alt! ( complete!( is_not!( " <>=" ) ) | rest ), - |s: &str| HTTP2SettingsId::from_str(s).ok() ) >> - value: opt!( complete!( detect_parse_u32 ) ) >> - (DetectHTTP2settingsSigCtx{id, value}) - ) -); +fn detect_parse_u32_start_equal(i: &str) -> IResult<&str, DetectU32Data> { + let (i, _) = opt(is_a(" "))(i)?; + let (i, _) = opt(tag("="))(i)?; + let (i, _) = opt(is_a(" "))(i)?; + let (i, value) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + Ok(( + i, + DetectU32Data { + value, + valrange: 0, + mode: DetectUintMode::DetectUintModeEqual, + }, + )) +} + +fn detect_parse_u32_start_interval(i: &str) -> IResult<&str, DetectU32Data> { + let (i, _) = opt(is_a(" "))(i)?; + let (i, value) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + let (i, _) = opt(is_a(" "))(i)?; + let (i, _) = tag("-")(i)?; + let (i, _) = opt(is_a(" "))(i)?; + let (i, valrange) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + Ok(( + i, + DetectU32Data { + value, + valrange, + mode: DetectUintMode::DetectUintModeRange, + }, + )) +} + +fn detect_parse_u32_start_lesser(i: &str) -> IResult<&str, DetectU32Data> { + let (i, _) = opt(is_a(" "))(i)?; + let (i, _) = tag("<")(i)?; + let (i, _) = opt(is_a(" "))(i)?; + let (i, value) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + Ok(( + i, + DetectU32Data { + value, + valrange: 0, + mode: DetectUintMode::DetectUintModeLt, + }, + )) +} + +fn detect_parse_u32_start_greater(i: &str) -> IResult<&str, DetectU32Data> { + let (i, _) = opt(is_a(" "))(i)?; + let (i, _) = tag(">")(i)?; + let (i, _) = opt(is_a(" "))(i)?; + let (i, value) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + Ok(( + i, + DetectU32Data { + value, + valrange: 0, + mode: DetectUintMode::DetectUintModeGt, + }, + )) +} + +fn detect_parse_u32(i: &str) -> IResult<&str, DetectU32Data> { + let (i, u32) = alt(( + detect_parse_u32_start_lesser, + detect_parse_u32_start_greater, + complete(detect_parse_u32_start_interval), + detect_parse_u32_start_equal, + ))(i)?; + Ok((i, u32)) +} + +pub fn http2_parse_settingsctx(i: &str) -> IResult<&str, DetectHTTP2settingsSigCtx> { + let (i, _) = opt(is_a(" "))(i)?; + let (i, id) = map_opt(alt((complete(is_not(" <>=")), rest)), |s: &str| { + HTTP2SettingsId::from_str(s).ok() + })(i)?; + let (i, value) = opt(complete(detect_parse_u32))(i)?; + Ok((i, DetectHTTP2settingsSigCtx { id, value })) +} pub struct DetectU64Data { pub value: u64, @@ -844,59 +861,77 @@ pub struct DetectU64Data { pub mode: DetectUintMode, } -named!(detect_parse_u64_start_equal<&str,DetectU64Data>, - do_parse!( - opt!( is_a!( " " ) ) >> - opt! (tag!("=") ) >> - opt!( is_a!( " " ) ) >> - value : map_opt!(digit1, |s: &str| s.parse::().ok()) >> - (DetectU64Data{value, valrange:0, mode:DetectUintMode::DetectUintModeEqual}) - ) -); - -named!(detect_parse_u64_start_interval<&str,DetectU64Data>, - do_parse!( - opt!( is_a!( " " ) ) >> - value : map_opt!(digit1, |s: &str| s.parse::().ok()) >> - opt!( is_a!( " " ) ) >> - tag!("-") >> - opt!( is_a!( " " ) ) >> - valrange : map_opt!(digit1, |s: &str| s.parse::().ok()) >> - (DetectU64Data{value, valrange, mode:DetectUintMode::DetectUintModeRange}) - ) -); - -named!(detect_parse_u64_start_lesser<&str,DetectU64Data>, - do_parse!( - opt!( is_a!( " " ) ) >> - tag!("<") >> - opt!( is_a!( " " ) ) >> - value : map_opt!(digit1, |s: &str| s.parse::().ok()) >> - (DetectU64Data{value, valrange:0, mode:DetectUintMode::DetectUintModeLt}) - ) -); - -named!(detect_parse_u64_start_greater<&str,DetectU64Data>, - do_parse!( - opt!( is_a!( " " ) ) >> - tag!(">") >> - opt!( is_a!( " " ) ) >> - value : map_opt!(digit1, |s: &str| s.parse::().ok()) >> - (DetectU64Data{value, valrange:0, mode:DetectUintMode::DetectUintModeGt}) - ) -); - -named!(pub detect_parse_u64<&str,DetectU64Data>, - do_parse!( - u64 : alt! ( - detect_parse_u64_start_lesser | - detect_parse_u64_start_greater | - complete!( detect_parse_u64_start_interval ) | - detect_parse_u64_start_equal - ) >> - (u64) - ) -); +fn detect_parse_u64_start_equal(i: &str) -> IResult<&str, DetectU64Data> { + let (i, _) = opt(is_a(" "))(i)?; + let (i, _) = opt(tag("="))(i)?; + let (i, _) = opt(is_a(" "))(i)?; + let (i, value) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + Ok(( + i, + DetectU64Data { + value, + valrange: 0, + mode: DetectUintMode::DetectUintModeEqual, + }, + )) +} + +fn detect_parse_u64_start_interval(i: &str) -> IResult<&str, DetectU64Data> { + let (i, _) = opt(is_a(" "))(i)?; + let (i, value) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + let (i, _) = opt(is_a(" "))(i)?; + let (i, _) = tag("-")(i)?; + let (i, _) = opt(is_a(" "))(i)?; + let (i, valrange) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + Ok(( + i, + DetectU64Data { + value, + valrange, + mode: DetectUintMode::DetectUintModeRange, + }, + )) +} + +fn detect_parse_u64_start_lesser(i: &str) -> IResult<&str, DetectU64Data> { + let (i, _) = opt(is_a(" "))(i)?; + let (i, _) = tag("<")(i)?; + let (i, _) = opt(is_a(" "))(i)?; + let (i, value) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + Ok(( + i, + DetectU64Data { + value, + valrange: 0, + mode: DetectUintMode::DetectUintModeLt, + }, + )) +} + +fn detect_parse_u64_start_greater(i: &str) -> IResult<&str, DetectU64Data> { + let (i, _) = opt(is_a(" "))(i)?; + let (i, _) = tag(">")(i)?; + let (i, _) = opt(is_a(" "))(i)?; + let (i, value) = map_opt(digit1, |s: &str| s.parse::().ok())(i)?; + Ok(( + i, + DetectU64Data { + value, + valrange: 0, + mode: DetectUintMode::DetectUintModeGt, + }, + )) +} + +pub fn detect_parse_u64(i: &str) -> IResult<&str, DetectU64Data> { + let (i, u64) = alt(( + detect_parse_u64_start_lesser, + detect_parse_u64_start_greater, + complete(detect_parse_u64_start_interval), + detect_parse_u64_start_equal, + ))(i)?; + Ok((i, u64)) +} #[derive(Clone, Copy, Debug)] pub struct HTTP2FrameSettings { @@ -904,18 +939,15 @@ pub struct HTTP2FrameSettings { pub value: u32, } -named!( - http2_parse_frame_setting, - do_parse!( - id: map_opt!(be_u16, num::FromPrimitive::from_u16) - >> value: be_u32 - >> (HTTP2FrameSettings { id, value }) - ) -); - -named!(pub http2_parse_frame_settings>, - many0!( complete!(http2_parse_frame_setting) ) -); +fn http2_parse_frame_setting(i: &[u8]) -> IResult<&[u8], HTTP2FrameSettings> { + let (i, id) = map_opt(be_u16, num::FromPrimitive::from_u16)(i)?; + let (i, value) = be_u32(i)?; + Ok((i, HTTP2FrameSettings { id, value })) +} + +pub fn http2_parse_frame_settings(i: &[u8]) -> IResult<&[u8], Vec> { + many0(complete(http2_parse_frame_setting))(i) +} #[cfg(test)] mod tests {