]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
http2: makes some settings configurable
authorPhilippe Antoine <contact@catenacyber.fr>
Thu, 6 Jan 2022 15:04:17 +0000 (16:04 +0100)
committerVictor Julien <vjulien@oisf.net>
Tue, 1 Feb 2022 06:17:38 +0000 (07:17 +0100)
max-streams and max-table-size

Allows users to find balance between completeness of decoding
and increases resource consumption, which can DOS suricata.

rust/src/http2/http2.rs
rust/src/http2/parser.rs
suricata.yaml.in

index 7d9488519d4cd68cffc341b4577147b51faba83d..bf80379c2f16ddfa5ca253847a8f700f176286d5 100644 (file)
@@ -21,6 +21,7 @@ use super::parser;
 use super::range;
 
 use crate::applayer::{self, *};
+use crate::conf::conf_get;
 use crate::core::*;
 use crate::filecontainer::*;
 use crate::filetracker::*;
@@ -58,9 +59,8 @@ const HTTP2_FRAME_GOAWAY_LEN: usize = 4;
 const HTTP2_FRAME_RSTSTREAM_LEN: usize = 4;
 const HTTP2_FRAME_PRIORITY_LEN: usize = 5;
 const HTTP2_FRAME_WINDOWUPDATE_LEN: usize = 4;
-//TODO make these configurable
-pub const HTTP2_MAX_TABLESIZE: u32 = 0x10000; // 65536
-pub const HTTP2_MAX_STREAMS: usize = 0x1000; // 4096
+pub static mut HTTP2_MAX_TABLESIZE: u32 = 65536; // 0x10000
+static mut HTTP2_MAX_STREAMS: usize = 4096; // 0x1000
 
 #[repr(u8)]
 #[derive(Copy, Clone, PartialOrd, PartialEq, Debug)]
@@ -576,7 +576,7 @@ impl HTTP2State {
             tx.stream_id = sid;
             tx.state = HTTP2TransactionState::HTTP2StateOpen;
             // do not use SETTINGS_MAX_CONCURRENT_STREAMS as it can grow too much
-            if self.transactions.len() > HTTP2_MAX_STREAMS {
+            if self.transactions.len() > unsafe { HTTP2_MAX_STREAMS } {
                 // set at least one another transaction to the drop state
                 for tx_old in &mut self.transactions {
                     if tx_old.state != HTTP2TransactionState::HTTP2StateTodrop {
@@ -656,7 +656,7 @@ impl HTTP2State {
                                     &mut self.dynamic_headers_tc
                                 };
                                 dyn_headers.max_size = set[i].value as usize;
-                                if set[i].value > HTTP2_MAX_TABLESIZE {
+                                if set[i].value > unsafe { HTTP2_MAX_TABLESIZE } {
                                     //mark potential overflow
                                     dyn_headers.overflow = 1;
                                 } else {
@@ -1224,6 +1224,20 @@ pub unsafe extern "C" fn rs_http2_register_parser() {
         if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 {
             let _ = AppLayerRegisterParser(&parser, alproto);
         }
+        if let Some(val) = conf_get("app-layer.protocols.http2.max-streams") {
+            if let Ok(v) = val.parse::<usize>() {
+                HTTP2_MAX_STREAMS = v;
+            } else {
+                SCLogError!("Invalid value for http2.max-streams");
+            }
+        }
+        if let Some(val) = conf_get("app-layer.protocols.http2.max-table-size") {
+            if let Ok(v) = val.parse::<u32>() {
+                HTTP2_MAX_TABLESIZE = v;
+            } else {
+                SCLogError!("Invalid value for http2.max-table-size");
+            }
+        }
         SCLogDebug!("Rust http2 parser registered.");
     } else {
         SCLogNotice!("Protocol detector and parser disabled for HTTP2.");
index a4edd842358cd222214b573d6522acb8455ac07f..f768026547ed947b547a2c7fb54941ec38018f6d 100644 (file)
@@ -445,7 +445,7 @@ fn http2_parse_headers_block_literal_incindex<'a>(
                 //in case of overflow, best effort is to keep first headers
                 if dyn_headers.overflow > 0 {
                     if dyn_headers.overflow == 1 {
-                        if dyn_headers.current_size <= (HTTP2_MAX_TABLESIZE as usize) {
+                        if dyn_headers.current_size <= (unsafe { HTTP2_MAX_TABLESIZE } as usize) {
                             //overflow had not yet happened
                             dyn_headers.table.push(headcopy);
                         } else if dyn_headers.current_size > dyn_headers.max_size {
index d2a1f9f1e23de0f2cbe9901d8c611b65ef578512..479087a0e00ecb33097cb776ff5ae9bbbe99db33 100644 (file)
@@ -833,6 +833,10 @@ app-layer:
       #hassh: yes
     http2:
       enabled: yes
+      # Maximum number of live HTTP2 streams in a flow
+      #max-streams: 4096
+      # Maximum headers table size
+      #max-table-size: 65536
     smtp:
       enabled: yes
       raw-extraction: no