From c8c61def68fc962040cec7f03db48c050abb5c6d Mon Sep 17 00:00:00 2001 From: Maria Scott Date: Tue, 7 May 2024 14:33:47 +0200 Subject: [PATCH 1/3] Extend error reason in case of failed handshake --- src/ranch.erl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ranch.erl b/src/ranch.erl index d48c18a6fc..8093b292cd 100644 --- a/src/ranch.erl +++ b/src/ranch.erl @@ -317,15 +317,13 @@ handshake_result(Result, Ref, Transport, CSocket, Timeout) -> {ok, CSocket2, Info} -> self() ! {handshake_continue, Ref, Transport, CSocket2, Timeout}, {continue, Info}; - {error, {tls_alert, _}} -> - ok = Transport:close(CSocket), - exit(normal); - {error, Reason} when Reason =:= timeout; Reason =:= closed -> - ok = Transport:close(CSocket), - exit(normal); {error, Reason} -> + PeerInfo = case Transport:peername(CSocket) of + {ok, Peer} -> Peer; + {error, _} -> undefined + end, ok = Transport:close(CSocket), - error(Reason) + exit({shutdown, {Reason, PeerInfo}}) end. -spec handshake_cancel(ref()) -> ok. From f0c163819463d5a28ed4c6ebb6de21eecc47c9a1 Mon Sep 17 00:00:00 2001 From: Jan Uhlig Date: Thu, 7 Nov 2024 08:23:17 +0100 Subject: [PATCH 2/3] Improve peer info detection for extended error reason --- src/ranch.erl | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/ranch.erl b/src/ranch.erl index 8093b292cd..b3d6bfdd65 100644 --- a/src/ranch.erl +++ b/src/ranch.erl @@ -287,8 +287,9 @@ handshake(Ref, Opts) -> handshake1(Ref, Opts) -> receive {handshake, Ref, Transport, CSocket, Timeout} -> + PeerInfo = get_peer_info(Transport, CSocket, undefined), Handshake = handshake_transport(Transport, handshake, CSocket, Opts, Timeout), - handshake_result(Handshake, Ref, Transport, CSocket, Timeout) + handshake_result(Handshake, Ref, Transport, CSocket, PeerInfo, Timeout) end. -spec handshake_continue(ref()) -> {ok, ranch_transport:socket()}. @@ -301,8 +302,9 @@ handshake_continue(Ref, Opts) -> handshake_continue1(Ref, Opts) -> receive {handshake_continue, Ref, Transport, CSocket, Timeout} -> + PeerInfo = get_peer_info(Transport, CSocket, undefined), Handshake = handshake_transport(Transport, handshake_continue, CSocket, Opts, Timeout), - handshake_result(Handshake, Ref, Transport, CSocket, Timeout) + handshake_result(Handshake, Ref, Transport, CSocket, PeerInfo, Timeout) end. handshake_transport(Transport, Fun, CSocket, undefined, Timeout) -> @@ -310,7 +312,7 @@ handshake_transport(Transport, Fun, CSocket, undefined, Timeout) -> handshake_transport(Transport, Fun, CSocket, {opts, Opts}, Timeout) -> Transport:Fun(CSocket, Opts, Timeout). -handshake_result(Result, Ref, Transport, CSocket, Timeout) -> +handshake_result(Result, Ref, Transport, CSocket, PeerInfo0, Timeout) -> case Result of OK = {ok, _} -> OK; @@ -318,10 +320,7 @@ handshake_result(Result, Ref, Transport, CSocket, Timeout) -> self() ! {handshake_continue, Ref, Transport, CSocket2, Timeout}, {continue, Info}; {error, Reason} -> - PeerInfo = case Transport:peername(CSocket) of - {ok, Peer} -> Peer; - {error, _} -> undefined - end, + PeerInfo = get_peer_info(Transport, CSocket, PeerInfo0), ok = Transport:close(CSocket), exit({shutdown, {Reason, PeerInfo}}) end. @@ -332,6 +331,12 @@ handshake_cancel(Ref) -> Transport:handshake_cancel(CSocket) end. +get_peer_info(Transport, Socket, Default) -> + case Transport:peername(Socket) of + {ok, Peer} -> Peer; + {error, _} -> Default + end. + %% Unlike handshake/2 this function always return errors because %% the communication between the proxy and the server are expected %% to be reliable. If there is a problem while receiving the proxy From fa138ab6316f3bf684d088ab47a0a54e122937a2 Mon Sep 17 00:00:00 2001 From: Jan Uhlig Date: Thu, 7 Nov 2024 08:23:52 +0100 Subject: [PATCH 3/3] Test for extended handshake error reason --- test/acceptor_SUITE.erl | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/acceptor_SUITE.erl b/test/acceptor_SUITE.erl index ba096975a1..df12712e85 100644 --- a/test/acceptor_SUITE.erl +++ b/test/acceptor_SUITE.erl @@ -85,6 +85,7 @@ groups() -> ssl_local_echo, ssl_graceful, ssl_handshake, + ssl_handshake_error, ssl_sni_echo, ssl_sni_fail, ssl_tls_psk, @@ -834,6 +835,32 @@ ssl_handshake(_) -> {'EXIT', _} = begin catch ranch:get_port(Name) end, ok. +ssl_handshake_error(_) -> + doc("Acceptor must not crash if client disconnects in the middle of SSL handshake."), + Name = name(), + Opts = ct_helper:get_certs_from_ets(), + {ok, _} = ranch:start_listener(Name, + ranch_ssl, #{num_acceptors => 1, socket_opts => Opts}, + echo_protocol, []), + Port = ranch:get_port(Name), + {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), + receive after 500 -> ok end, + [ConnPid] = ranch:procs(Name, connections), + ConnMon = monitor(process, ConnPid), + ok = gen_tcp:send(Socket, <<"GARBAGE">>), + ok = gen_tcp:close(Socket), + receive + {'DOWN', ConnMon, process, ConnPid, R} -> + {shutdown, {_, _}} = R + after 1000 -> + error(timeout) + end, + receive after 500 -> ok end, + ok = ranch:stop_listener(Name), + %% Make sure the listener stopped. + {'EXIT', _} = begin catch ranch:get_port(Name) end, + ok. + ssl_local_echo(_) -> case do_os_supports_local_sockets() of true ->