rust/http2: convert parser to nom7 functions (HTTP2 core functions)

pull/6802/head
Pierre Chifflier 4 years ago committed by Victor Julien
parent 52d8d35453
commit f8647b0ffb

@ -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(_) => {

@ -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<u8> {
match n {
@ -35,9 +37,9 @@ fn http2_huffman_table_len5(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -71,9 +73,9 @@ fn http2_huffman_table_len6(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -113,9 +115,9 @@ fn http2_huffman_table_len7(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -129,9 +131,9 @@ fn http2_huffman_table_len8(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -144,9 +146,9 @@ fn http2_huffman_table_len10(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -157,9 +159,9 @@ fn http2_huffman_table_len11(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -169,9 +171,9 @@ fn http2_huffman_table_len12(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -185,9 +187,9 @@ fn http2_huffman_table_len13(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -197,9 +199,9 @@ fn http2_huffman_table_len14(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -210,9 +212,9 @@ fn http2_huffman_table_len15(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -223,9 +225,9 @@ fn http2_huffman_table_len19(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -241,9 +243,9 @@ fn http2_huffman_table_len20(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -264,9 +266,9 @@ fn http2_huffman_table_len21(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -300,9 +302,9 @@ fn http2_huffman_table_len22(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -339,9 +341,9 @@ fn http2_huffman_table_len23(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -361,9 +363,9 @@ fn http2_huffman_table_len24(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -375,9 +377,9 @@ fn http2_huffman_table_len25(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -400,9 +402,9 @@ fn http2_huffman_table_len26(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -429,9 +431,9 @@ fn http2_huffman_table_len27(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -468,9 +470,9 @@ fn http2_huffman_table_len28(n: u32) -> Option<u8> {
}
}
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<u8> {
match n {
@ -482,23 +484,44 @@ fn http2_huffman_table_len30(n: u32) -> Option<u8> {
}
}
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)
}

@ -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<HTTP2FrameHeader>,
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<HTTP2FrameGoAway>,
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<HTTP2FrameRstStream>,
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<HTTP2FramePriority>,
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<HTTP2FrameWindowUpdate>,
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<HTTP2FrameHeadersPriority>,
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<u8>> {
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<DetectU32Data>, //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::<u32>().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::<u32>().ok()) >>
opt!( is_a!( " " ) ) >>
tag!("-") >>
opt!( is_a!( " " ) ) >>
valrange : map_opt!(digit1, |s: &str| s.parse::<u32>().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::<u32>().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::<u32>().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::<u32>().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::<u32>().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::<u32>().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::<u32>().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::<u32>().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::<u64>().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::<u64>().ok()) >>
opt!( is_a!( " " ) ) >>
tag!("-") >>
opt!( is_a!( " " ) ) >>
valrange : map_opt!(digit1, |s: &str| s.parse::<u64>().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::<u64>().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::<u64>().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::<u64>().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::<u64>().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::<u64>().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::<u64>().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::<u64>().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<HTTP2FrameSettings>,
do_parse!(
id: map_opt!(be_u16, num::FromPrimitive::from_u16)
>> value: be_u32
>> (HTTP2FrameSettings { id, value })
)
);
named!(pub http2_parse_frame_settings<Vec<HTTP2FrameSettings>>,
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<HTTP2FrameSettings>> {
many0(complete(http2_parse_frame_setting))(i)
}
#[cfg(test)]
mod tests {

Loading…
Cancel
Save