aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2019-09-23 13:30:45 +0200
committerLoïc Hoguin <[email protected]>2019-09-23 13:30:45 +0200
commitcd6d550398fceafbcd47ff22534666bf21e9d8f1 (patch)
tree9605c7f20649827ac82b84e9d3ea3801e367c6d5
parent76665f40b15111842cc04d7c7c92e46d64220812 (diff)
downloadgun-cd6d550398fceafbcd47ff22534666bf21e9d8f1.tar.gz
gun-cd6d550398fceafbcd47ff22534666bf21e9d8f1.tar.bz2
gun-cd6d550398fceafbcd47ff22534666bf21e9d8f1.zip
Set server_name_indication for TLS handshakes
This essentially reverts to the old behavior for initial TLS handshakes, and improves TLS support for the Socks/HTTP proxy cases.
-rw-r--r--src/gun.erl22
1 files changed, 16 insertions, 6 deletions
diff --git a/src/gun.erl b/src/gun.erl
index 255e2ac..600327b 100644
--- a/src/gun.erl
+++ b/src/gun.erl
@@ -946,7 +946,7 @@ connecting(_, {retries, Retries, LookupInfo}, State=#state{opts=Opts,
initial_tls_handshake(_, {retries, Retries, Socket}, State0=#state{opts=Opts}) ->
Protocols = maps:get(protocols, Opts, [http2, http]),
HandshakeEvent = #{
- tls_opts => ensure_alpn(Protocols, maps:get(tls_opts, Opts, [])),
+ tls_opts => ensure_alpn_sni(Protocols, maps:get(tls_opts, Opts, []), State0),
timeout => maps:get(tls_handshake_timeout, Opts, infinity)
},
case normal_tls_handshake(Socket, State0, HandshakeEvent, Protocols) of
@@ -958,15 +958,25 @@ initial_tls_handshake(_, {retries, Retries, Socket}, State0=#state{opts=Opts}) -
{next_event, internal, {retries, Retries, Reason}}}
end.
-ensure_alpn(Protocols0, TransOpts) ->
+ensure_alpn_sni(Protocols0, TransOpts0, #state{origin_host=OriginHost}) ->
+ %% ALPN.
Protocols = [case P of
http -> <<"http/1.1">>;
http2 -> <<"h2">>
end || P <- Protocols0, is_atom(P)],
- [
+ TransOpts = [
{alpn_advertised_protocols, Protocols},
{client_preferred_next_protocols, {client, Protocols, <<"http/1.1">>}}
- |TransOpts].
+ |TransOpts0],
+ %% SNI.
+ %%
+ %% Normally only DNS hostnames are supported for SNI. However, the ssl
+ %% application itself allows any string through so we do the same.
+ if
+ is_list(OriginHost) -> [{server_name_indication, OriginHost}|TransOpts];
+ is_atom(OriginHost) -> [{server_name_indication, atom_to_list(OriginHost)}|TransOpts];
+ true -> TransOpts
+ end.
%% Normal TLS handshake.
tls_handshake(internal, {tls_handshake, HandshakeEvent, Protocols},
@@ -985,7 +995,7 @@ tls_handshake(internal, {tls_handshake,
HandshakeEvent0=#{tls_opts := TLSOpts0, timeout := TLSTimeout}, Protocols},
State=#state{socket=Socket, transport=Transport, origin_host=OriginHost, origin_port=OriginPort,
event_handler=EvHandler, event_handler_state=EvHandlerState0}) ->
- TLSOpts = ensure_alpn(Protocols, TLSOpts0),
+ TLSOpts = ensure_alpn_sni(Protocols, TLSOpts0, State),
HandshakeEvent = HandshakeEvent0#{
tls_opts => TLSOpts,
socket => Socket
@@ -1016,7 +1026,7 @@ tls_handshake(Type, Event, State) ->
normal_tls_handshake(Socket, State=#state{event_handler=EvHandler, event_handler_state=EvHandlerState0},
HandshakeEvent0=#{tls_opts := TLSOpts0, timeout := TLSTimeout}, Protocols) ->
- TLSOpts = ensure_alpn(Protocols, TLSOpts0),
+ TLSOpts = ensure_alpn_sni(Protocols, TLSOpts0, State),
HandshakeEvent = HandshakeEvent0#{
tls_opts => TLSOpts,
socket => Socket