]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
http2: allow multiple size updates in one headers batch
authorPhilippe Antoine <contact@catenacyber.fr>
Tue, 10 Nov 2020 09:21:32 +0000 (10:21 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 3 Dec 2020 12:01:11 +0000 (13:01 +0100)
cf RFC 7541 section 4.2

rust/src/http2/http2.rs
rust/src/http2/parser.rs

index 8b4112ead6302b8a9b7d39112e36f83547622474..6886dfff98478c8e9697abbd46c9d3314d37153b 100644 (file)
@@ -438,6 +438,31 @@ impl HTTP2State {
         }
     }
 
+    fn process_headers(&mut self, blocks: &Vec<parser::HTTP2FrameHeaderBlock>, dir: u8) {
+        let (mut update, mut sizeup) = (false, 0);
+        for i in 0..blocks.len() {
+            if blocks[i].error >= parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeError {
+                self.set_event(HTTP2Event::InvalidHeader);
+            } else if blocks[i].error
+                == parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeSizeUpdate
+            {
+                update = true;
+                if blocks[i].sizeupdate > sizeup {
+                    sizeup = blocks[i].sizeupdate;
+                }
+            }
+        }
+        if update {
+            //borrow checker forbids to pass directly dyn_headers
+            let dyn_headers = if dir == STREAM_TOCLIENT {
+                &mut self.dynamic_headers_tc
+            } else {
+                &mut self.dynamic_headers_ts
+            };
+            dyn_headers.max_size = sizeup as usize;
+        }
+    }
+
     fn parse_frame_data(
         &mut self, ftype: u8, input: &[u8], complete: bool, hflags: u8, dir: u8,
     ) -> HTTP2FrameTypeData {
@@ -573,13 +598,7 @@ impl HTTP2State {
                 };
                 match parser::http2_parse_frame_push_promise(input, hflags, dyn_headers) {
                     Ok((_, hs)) => {
-                        for i in 0..hs.blocks.len() {
-                            if hs.blocks[i].error
-                                >= parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeError
-                            {
-                                self.set_event(HTTP2Event::InvalidHeader);
-                            }
-                        }
+                        self.process_headers(&hs.blocks, dir);
                         return HTTP2FrameTypeData::PUSHPROMISE(hs);
                     }
                     Err(nom::Err::Incomplete(_)) => {
@@ -613,13 +632,7 @@ impl HTTP2State {
                 };
                 match parser::http2_parse_frame_continuation(input, dyn_headers) {
                     Ok((_, hs)) => {
-                        for i in 0..hs.blocks.len() {
-                            if hs.blocks[i].error
-                                >= parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeError
-                            {
-                                self.set_event(HTTP2Event::InvalidHeader);
-                            }
-                        }
+                        self.process_headers(&hs.blocks, dir);
                         return HTTP2FrameTypeData::CONTINUATION(hs);
                     }
                     Err(nom::Err::Incomplete(_)) => {
@@ -650,13 +663,7 @@ impl HTTP2State {
                 };
                 match parser::http2_parse_frame_headers(input, hflags, dyn_headers) {
                     Ok((hrem, hs)) => {
-                        for i in 0..hs.blocks.len() {
-                            if hs.blocks[i].error
-                                >= parser::HTTP2HeaderDecodeStatus::HTTP2HeaderDecodeError
-                            {
-                                self.set_event(HTTP2Event::InvalidHeader);
-                            }
-                        }
+                        self.process_headers(&hs.blocks, dir);
                         if hrem.len() > 0 {
                             SCLogDebug!("Remaining data for HTTP2 headers");
                             self.set_event(HTTP2Event::ExtraHeaderData);
index 9ba2e5835d70235da9f7580b30e688d8be587e70..61e4557f6a5909f05503f6740117050d28501bdd 100644 (file)
@@ -562,9 +562,9 @@ fn http2_parse_headers_block_dynamic_size<'a>(
         ));
     }
     if (maxsize2 as usize) < dyn_headers.max_size {
-        dyn_headers.max_size = maxsize2 as usize;
+        //dyn_headers.max_size is updated later with all headers
         //may evict entries
-        while dyn_headers.current_size > dyn_headers.max_size {
+        while dyn_headers.current_size > (maxsize2 as usize) {
             dyn_headers.current_size -=
                 32 + dyn_headers.table[0].name.len() + dyn_headers.table[0].value.len();
             dyn_headers.table.remove(0);