]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
http2: StreamIdReuse frame types exceptions
authorPhilippe Antoine <contact@catenacyber.fr>
Wed, 30 Sep 2020 12:23:11 +0000 (14:23 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 30 Sep 2020 13:02:45 +0000 (15:02 +0200)
Also handles better the state so as not to revert from
HTTP2StateHalfClosedClient to HTTP2StateDataServer and not
go to final HTTP2StateClosed

rust/src/http2/http2.rs

index ece5d990f71a6a9118f4474b29139626faf26501..86218f923e4e5fa0ead834d9aa52127593cca793 100644 (file)
@@ -101,8 +101,8 @@ pub enum HTTP2TransactionState {
     HTTP2StateOpen = 1,
     HTTP2StateReserved = 2,
     HTTP2StateDataClient = 3,
-    HTTP2StateDataServer = 4,
-    HTTP2StateHalfClosedClient = 5,
+    HTTP2StateHalfClosedClient = 4,
+    HTTP2StateDataServer = 5,
     HTTP2StateHalfClosedServer = 6,
     HTTP2StateClosed = 7,
     //not a RFC-defined state, used for stream 0 frames appyling to the global connection
@@ -195,7 +195,8 @@ impl HTTP2Transaction {
             HTTP2FrameTypeData::HEADERS(_) | HTTP2FrameTypeData::DATA => {
                 if header.flags & parser::HTTP2_FLAG_HEADER_EOS != 0 {
                     match self.state {
-                        HTTP2TransactionState::HTTP2StateHalfClosedClient => {
+                        HTTP2TransactionState::HTTP2StateHalfClosedClient
+                        | HTTP2TransactionState::HTTP2StateDataServer => {
                             if dir == STREAM_TOCLIENT {
                                 self.state = HTTP2TransactionState::HTTP2StateClosed;
                             }
@@ -205,7 +206,7 @@ impl HTTP2Transaction {
                                 self.state = HTTP2TransactionState::HTTP2StateClosed;
                             }
                         }
-                        // do not revert back to a hald closed state
+                        // do not revert back to a half closed state
                         HTTP2TransactionState::HTTP2StateClosed => {}
                         HTTP2TransactionState::HTTP2StateGlobal => {}
                         _ => {
@@ -219,9 +220,13 @@ impl HTTP2Transaction {
                 } else if header.ftype == parser::HTTP2FrameType::DATA as u8 {
                     //not end of stream
                     if dir == STREAM_TOSERVER {
-                        self.state = HTTP2TransactionState::HTTP2StateDataClient;
+                        if self.state < HTTP2TransactionState::HTTP2StateDataClient {
+                            self.state = HTTP2TransactionState::HTTP2StateDataClient;
+                        }
                     } else {
-                        self.state = HTTP2TransactionState::HTTP2StateDataServer;
+                        if self.state < HTTP2TransactionState::HTTP2StateDataServer {
+                            self.state = HTTP2TransactionState::HTTP2StateDataServer;
+                        }
                     }
                 }
             }
@@ -336,14 +341,19 @@ impl HTTP2State {
         return None;
     }
 
-    fn find_tx_index(&mut self, sid: u32) -> usize {
+    fn find_tx_index(&mut self, sid: u32, header: &parser::HTTP2FrameHeader) -> usize {
         for i in 0..self.transactions.len() {
             //reverse order should be faster
             let idx = self.transactions.len() - 1 - i;
             if sid == self.transactions[idx].stream_id {
                 if self.transactions[idx].state == HTTP2TransactionState::HTTP2StateClosed {
-                    self.set_event(HTTP2Event::StreamIdReuse);
-                    return 0;
+                    //these frames can be received in this state for a short period
+                    if header.ftype != parser::HTTP2FrameType::RSTSTREAM as u8
+                        && header.ftype != parser::HTTP2FrameType::WINDOWUPDATE as u8
+                        && header.ftype != parser::HTTP2FrameType::PRIORITY as u8
+                    {
+                        self.set_event(HTTP2Event::StreamIdReuse);
+                    }
                 }
                 return idx + 1;
             }
@@ -394,7 +404,7 @@ impl HTTP2State {
             }
             _ => header.stream_id,
         };
-        let index = self.find_tx_index(sid);
+        let index = self.find_tx_index(sid, header);
         if index > 0 {
             return &mut self.transactions[index - 1];
         } else {