0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 12:20:24 +00:00

Add max_fragmented_header_block_size HTTP/2 option

This commit is contained in:
Loïc Hoguin 2024-03-14 12:36:54 +01:00
parent 81f3a21474
commit cf71c742d6
No known key found for this signature in database
GPG key ID: 8A9DF795F6FED764
5 changed files with 46 additions and 3 deletions

View file

@ -15,7 +15,7 @@ CT_OPTS += -ct_hooks cowboy_ct_hook [] # -boot start_sasl
LOCAL_DEPS = crypto LOCAL_DEPS = crypto
DEPS = cowlib ranch DEPS = cowlib ranch
dep_cowlib = git https://github.com/ninenines/cowlib 2.12.1 dep_cowlib = git https://github.com/ninenines/cowlib 2.13.0
dep_ranch = git https://github.com/ninenines/ranch 1.8.0 dep_ranch = git https://github.com/ninenines/ranch 1.8.0
DOC_DEPS = asciideck DOC_DEPS = asciideck

View file

@ -35,6 +35,7 @@ opts() :: #{
max_connection_window_size => 0..16#7fffffff, max_connection_window_size => 0..16#7fffffff,
max_decode_table_size => non_neg_integer(), max_decode_table_size => non_neg_integer(),
max_encode_table_size => non_neg_integer(), max_encode_table_size => non_neg_integer(),
max_fragmented_header_block_size => 16384..16#7fffffff,
max_frame_size_received => 16384..16777215, max_frame_size_received => 16384..16777215,
max_frame_size_sent => 16384..16777215 | infinity, max_frame_size_sent => 16384..16777215 | infinity,
max_received_frame_rate => {pos_integer(), timeout()}, max_received_frame_rate => {pos_integer(), timeout()},
@ -172,6 +173,14 @@ Maximum header table size in bytes used by the encoder. The server will
compare this value to what the client advertises and choose the smallest compare this value to what the client advertises and choose the smallest
one as the encoder's header table size. one as the encoder's header table size.
max_fragmented_header_block_size (32768)::
Maximum header block size when headers are split over multiple HEADERS
and CONTINUATION frames. Clients that attempt to send header blocks
larger than this value will receive an ENHANCE_YOUR_CALM connection
error. Note that this value is not advertised and should be large
enough for legitimate requests.
max_frame_size_received (16384):: max_frame_size_received (16384)::
Maximum size in bytes of the frames received by the server. This value is Maximum size in bytes of the frames received by the server. This value is

View file

@ -1,4 +1,4 @@
{deps, [ {deps, [
{cowlib,".*",{git,"https://github.com/ninenines/cowlib","2.12.1"}},{ranch,".*",{git,"https://github.com/ninenines/ranch","1.8.0"}} {cowlib,".*",{git,"https://github.com/ninenines/cowlib","2.13.0"}},{ranch,".*",{git,"https://github.com/ninenines/ranch","1.8.0"}}
]}. ]}.
{erl_opts, [debug_info,warn_export_vars,warn_shadow_vars,warn_obsolete_guard,warn_missing_spec,warn_untyped_record]}. {erl_opts, [debug_info,warn_export_vars,warn_shadow_vars,warn_obsolete_guard,warn_missing_spec,warn_untyped_record]}.

View file

@ -44,6 +44,7 @@
max_connection_window_size => 0..16#7fffffff, max_connection_window_size => 0..16#7fffffff,
max_decode_table_size => non_neg_integer(), max_decode_table_size => non_neg_integer(),
max_encode_table_size => non_neg_integer(), max_encode_table_size => non_neg_integer(),
max_fragmented_header_block_size => 16384..16#7fffffff,
max_frame_size_received => 16384..16777215, max_frame_size_received => 16384..16777215,
max_frame_size_sent => 16384..16777215 | infinity, max_frame_size_sent => 16384..16777215 | infinity,
max_received_frame_rate => {pos_integer(), timeout()}, max_received_frame_rate => {pos_integer(), timeout()},

View file

@ -33,13 +33,14 @@ groups() ->
Tests = [nc_rand, nc_zero], Tests = [nc_rand, nc_zero],
H1Tests = [slowloris, slowloris_chunks], H1Tests = [slowloris, slowloris_chunks],
H2CTests = [ H2CTests = [
http2_cancel_flood,
http2_data_dribble, http2_data_dribble,
http2_empty_frame_flooding_data, http2_empty_frame_flooding_data,
http2_empty_frame_flooding_headers_continuation, http2_empty_frame_flooding_headers_continuation,
http2_empty_frame_flooding_push_promise, http2_empty_frame_flooding_push_promise,
http2_infinite_continuations,
http2_ping_flood, http2_ping_flood,
http2_reset_flood, http2_reset_flood,
http2_cancel_flood,
http2_settings_flood, http2_settings_flood,
http2_zero_length_header_leak http2_zero_length_header_leak
], ],
@ -219,6 +220,38 @@ http2_empty_frame_flooding_push_promise(Config) ->
{ok, <<_:24, 7:8, _:72, 1:32>>} = gen_tcp:recv(Socket, 17, 6000), {ok, <<_:24, 7:8, _:72, 1:32>>} = gen_tcp:recv(Socket, 17, 6000),
ok. ok.
http2_infinite_continuations(Config) ->
doc("Confirm that Cowboy rejects CONTINUATION frames when the "
"total size of HEADERS + CONTINUATION(s) exceeds the limit."),
{ok, Socket} = rfc7540_SUITE:do_handshake(Config),
%% Send a HEADERS frame followed by a large number
%% of continuation frames.
{HeadersBlock, _} = cow_hpack:encode([
{<<":method">>, <<"GET">>},
{<<":scheme">>, <<"http">>},
{<<":authority">>, <<"localhost">>}, %% @todo Correct port number.
{<<":path">>, <<"/">>}
]),
HeadersBlockLen = iolist_size(HeadersBlock),
ok = gen_tcp:send(Socket, [
%% HEADERS frame.
<<
HeadersBlockLen:24, 1:8, 0:5,
0:1, %% END_HEADERS
0:1,
1:1, %% END_STREAM
0:1,
1:31 %% Stream ID.
>>,
HeadersBlock,
%% CONTINUATION frames.
[<<1024:24, 9:8, 0:8, 0:1, 1:31, 0:1024/unit:8>>
|| _ <- lists:seq(1, 100)]
]),
%% Receive an ENHANCE_YOUR_CALM connection error.
{ok, <<_:24, 7:8, _:72, 11:32>>} = gen_tcp:recv(Socket, 17, 6000),
ok.
%% @todo http2_internal_data_buffering(Config) -> I do not know how to test this. %% @todo http2_internal_data_buffering(Config) -> I do not know how to test this.
% doc("Request many very large responses, with a larger than necessary window size, " % doc("Request many very large responses, with a larger than necessary window size, "
% "but do not attempt to read from the socket. (CVE-2019-9517)"), % "but do not attempt to read from the socket. (CVE-2019-9517)"),