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

Address feedback and some simplification

This commit is contained in:
Viktor Söderqvist 2023-11-08 12:03:11 +01:00
parent 0f8b6a9fda
commit 80b2a5b86a
2 changed files with 23 additions and 29 deletions

View file

@ -201,8 +201,8 @@ similar to a supervisor restart intensity/period.
max_cancel_stream_rate ({500, 10000}):: max_cancel_stream_rate ({500, 10000})::
Maximum cancel stream rate per connection. This can be used to protect Maximum cancel stream rate per connection. This can be used to
against the rapid reset attack (CVE-2023-44487), by limiting the protect against misbehaving or malicious peers, by limiting the
number of streams that the peer can reset over a certain time period. number of streams that the peer can reset over a certain time period.
The rate is expressed as a tuple `{NumCancels, TimeMs}`. This is The rate is expressed as a tuple `{NumCancels, TimeMs}`. This is
similar to a supervisor restart intensity/period. similar to a supervisor restart intensity/period.

View file

@ -576,21 +576,30 @@ early_error(State0=#state{ref=Ref, opts=Opts, peer=Peer},
send_headers(State0, StreamID, fin, StatusCode0, RespHeaders0) send_headers(State0, StreamID, fin, StatusCode0, RespHeaders0)
end. end.
rst_stream_frame(State0=#state{streams=Streams0, children=Children0}, StreamID, Reason) -> rst_stream_frame(State=#state{streams=Streams0, children=Children0}, StreamID, Reason) ->
State1 = case maps:take(StreamID, Streams0) of case maps:take(StreamID, Streams0) of
{#stream{state=StreamState}, Streams} -> {#stream{state=StreamState}, Streams} ->
terminate_stream_handler(State0, StreamID, Reason, StreamState), terminate_stream_handler(State, StreamID, Reason, StreamState),
Children = cowboy_children:shutdown(Children0, StreamID), Children = cowboy_children:shutdown(Children0, StreamID),
State0#state{streams=Streams, children=Children}; cancel_rate_limit(State#state{streams=Streams, children=Children});
error -> error ->
State0 State
end, end.
case cancel_rate(State1) of
{ok, State} -> cancel_rate_limit(State0=#state{cancel_rate_num=Num0, cancel_rate_time=Time}) ->
State; case Num0 - 1 of
error -> 0 ->
terminate(State1, {connection_error, enhance_your_calm, CurrentTime = erlang:monotonic_time(millisecond),
'Stream cancel rate larger than configuration allows. Flood? (CVE-2023-44487)'}) if
CurrentTime < Time ->
terminate(State0, {connection_error, enhance_your_calm,
'Stream cancel rate larger than configuration allows. Flood? (CVE-2023-44487)'});
true ->
%% When the option has a period of infinity we cannot reach this clause.
init_cancel_rate_limiting(State0, CurrentTime)
end;
Num ->
State0#state{cancel_rate_num=Num}
end. end.
ignored_frame(State=#state{http2_machine=HTTP2Machine0}) -> ignored_frame(State=#state{http2_machine=HTTP2Machine0}) ->
@ -1157,21 +1166,6 @@ reset_rate(State0=#state{reset_rate_num=Num0, reset_rate_time=Time}) ->
{ok, State0#state{reset_rate_num=Num}} {ok, State0#state{reset_rate_num=Num}}
end. end.
cancel_rate(State0=#state{cancel_rate_num=Num0, cancel_rate_time=Time}) ->
case Num0 - 1 of
0 ->
CurrentTime = erlang:monotonic_time(millisecond),
if
CurrentTime < Time ->
error;
true ->
%% When the option has a period of infinity we cannot reach this clause.
{ok, init_cancel_rate_limiting(State0, CurrentTime)}
end;
Num ->
{ok, State0#state{cancel_rate_num=Num}}
end.
stop_stream(State=#state{http2_machine=HTTP2Machine}, StreamID) -> stop_stream(State=#state{http2_machine=HTTP2Machine}, StreamID) ->
case cow_http2_machine:get_stream_local_state(StreamID, HTTP2Machine) of case cow_http2_machine:get_stream_local_state(StreamID, HTTP2Machine) of
%% When the stream terminates normally (without sending RST_STREAM) %% When the stream terminates normally (without sending RST_STREAM)