From d44e7a16f7d2823cc658e39b5d953ba0850e47ba Mon Sep 17 00:00:00 2001 From: juhlig Date: Tue, 17 Sep 2019 17:55:25 +0200 Subject: Enable multiple steps handshake Also fix some Protocol:start_link/4 into start_link/3 left over in the documentation. --- test/acceptor_SUITE.erl | 30 ++++++++++++++++++++++++++++++ test/handshake_protocol.erl | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 test/handshake_protocol.erl (limited to 'test') diff --git a/test/acceptor_SUITE.erl b/test/acceptor_SUITE.erl index 2c8b9e2..7fc26f4 100644 --- a/test/acceptor_SUITE.erl +++ b/test/acceptor_SUITE.erl @@ -57,6 +57,7 @@ groups() -> ssl_echo, ssl_local_echo, ssl_graceful, + ssl_handshake, ssl_sni_echo, ssl_sni_fail, ssl_upgrade_from_tcp, @@ -533,6 +534,35 @@ ssl_echo(_) -> {'EXIT', _} = begin catch ranch:get_port(Name) end, ok. +ssl_handshake(_) -> + doc("Ensure that multiple steps handshake works with SSL transport."), + Name = name(), + {CaCert1, Cert1, Key1} = ct_helper:make_certs(), + {CaCert2, Cert2, Key2} = ct_helper:make_certs(), + Opts1 = [{cert, Cert1}, {key, Key1}, {cacerts, [CaCert1]}, {verify, verify_peer}], + Opts2 = [{cert, Cert2}, {key, Key2}, {cacerts, [CaCert2]}, {verify, verify_peer}], + DefaultOpts = ct_helper:get_certs_from_ets(), + {ok, _} = ranch:start_listener(Name, + ranch_ssl, [{handshake, hello}|DefaultOpts], + handshake_protocol, #{"ranch1" => Opts1, "ranch2" => Opts2}), + Port = ranch:get_port(Name), + {ok, Socket1} = ssl:connect("localhost", Port, [binary, {active, false}, {packet, raw}, + {server_name_indication, "ranch1"}], 5000), + {ok, Cert1} = ssl:peercert(Socket1), + ok = ssl:send(Socket1, <<"SSL Ranch is working!">>), + {ok, <<"SSL Ranch is working!">>} = ssl:recv(Socket1, 21, 1000), + {ok, Socket2} = ssl:connect("localhost", Port, [binary, {active, false}, {packet, raw}, + {server_name_indication, "ranch2"}], 5000), + {ok, Cert2} = ssl:peercert(Socket2), + ok = ssl:send(Socket2, <<"SSL Ranch is working!">>), + {ok, <<"SSL Ranch is working!">>} = ssl:recv(Socket2, 21, 1000), + ok = ranch:stop_listener(Name), + {error, closed} = ssl:recv(Socket1, 0, 1000), + {error, closed} = ssl:recv(Socket2, 0, 1000), + %% 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 -> diff --git a/test/handshake_protocol.erl b/test/handshake_protocol.erl new file mode 100644 index 0000000..cedbe2d --- /dev/null +++ b/test/handshake_protocol.erl @@ -0,0 +1,32 @@ +-module(handshake_protocol). +-behaviour(ranch_protocol). + +-export([start_link/3]). +-export([init/3]). + +start_link(Ref, Transport, Opts) -> + Pid = spawn_link(?MODULE, init, [Ref, Transport, Opts]), + {ok, Pid}. + +init(Ref, Transport, Opts) -> + SniHost = case ranch:handshake(Ref) of + %% Due to a bug in ssl (https://bugs.erlang.org/browse/ERL-951, + %% fixed in OTP 22.0.3) the value for sni may be {sni, Hostname} + %% instead of Hostname. + {continue, #{sni := {sni, Hostname}}} -> + Hostname; + {continue, #{sni := Hostname}} -> + Hostname + end, + SniHostOpts = maps:get(SniHost, Opts), + {ok, Socket} = ranch:handshake_continue(Ref, SniHostOpts), + loop(Socket, Transport). + +loop(Socket, Transport) -> + case Transport:recv(Socket, 0, 5000) of + {ok, Data} -> + Transport:send(Socket, Data), + loop(Socket, Transport); + _ -> + ok = Transport:close(Socket) + end. -- cgit v1.2.3