aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2024-03-14 15:41:30 +0100
committerLoïc Hoguin <[email protected]>2024-03-14 15:41:30 +0100
commit8b5f1609faffcf1166ca54c08df4ca9216c51993 (patch)
tree8360c67d59714c1641764debc2c074e4eaa90604
parent5e177270a2be530bbec55381d0fe66a252c3a998 (diff)
downloadgun-8b5f1609faffcf1166ca54c08df4ca9216c51993.tar.gz
gun-8b5f1609faffcf1166ca54c08df4ca9216c51993.tar.bz2
gun-8b5f1609faffcf1166ca54c08df4ca9216c51993.zip
Use public_key:cacerts_get/0 when possible
Also "fix" many TLS test failures due to yet more changes in the default options for TLS. Also small changes to make Dialyzer happy.
-rw-r--r--Makefile3
-rw-r--r--ebin/gun.app2
-rw-r--r--src/gun.erl80
-rw-r--r--src/gun_http2.erl2
-rw-r--r--src/gun_tunnel.erl2
-rw-r--r--test/event_SUITE.erl4
-rw-r--r--test/gun_SUITE.erl10
-rw-r--r--test/gun_test.erl7
-rw-r--r--test/rfc7231_SUITE.erl3
-rw-r--r--test/rfc7540_SUITE.erl4
-rw-r--r--test/socks_SUITE.erl3
11 files changed, 78 insertions, 42 deletions
diff --git a/Makefile b/Makefile
index cee6ce0..ca63664 100644
--- a/Makefile
+++ b/Makefile
@@ -7,11 +7,12 @@ PROJECT_VERSION = 2.0.1
# Options.
# ERLC_OPTS = -DDEBUG_PROXY=1
+PLT_APPS = crypto runtime_tools
CT_OPTS += -ct_hooks gun_ct_hook [] # -boot start_sasl
# Dependencies.
-LOCAL_DEPS = ssl
+LOCAL_DEPS = public_key ssl
DEPS = cowlib
dep_cowlib = git https://github.com/ninenines/cowlib 2.13.0
diff --git a/ebin/gun.app b/ebin/gun.app
index fdc9302..0e1338e 100644
--- a/ebin/gun.app
+++ b/ebin/gun.app
@@ -3,7 +3,7 @@
{vsn, "2.0.1"},
{modules, ['gun','gun_app','gun_conns_sup','gun_content_handler','gun_cookies','gun_cookies_list','gun_data_h','gun_default_event_h','gun_event','gun_http','gun_http2','gun_pool','gun_pool_events_h','gun_pools_sup','gun_protocols','gun_public_suffix','gun_raw','gun_socks','gun_sse_h','gun_sup','gun_tcp','gun_tcp_proxy','gun_tls','gun_tls_proxy','gun_tls_proxy_cb','gun_tls_proxy_http2_connect','gun_tunnel','gun_ws','gun_ws_h','gun_ws_protocol']},
{registered, [gun_sup]},
- {applications, [kernel,stdlib,ssl,cowlib]},
+ {applications, [kernel,stdlib,public_key,ssl,cowlib]},
{optional_applications, []},
{mod, {gun_app, []}},
{env, []}
diff --git a/src/gun.erl b/src/gun.erl
index 31833f5..b4c1686 100644
--- a/src/gun.erl
+++ b/src/gun.erl
@@ -103,7 +103,7 @@
-export([domain_lookup/3]).
-export([connecting/3]).
-export([initial_tls_handshake/3]).
--export([ensure_alpn_sni/3]).
+-export([ensure_tls_opts/3]).
-export([tls_handshake/3]).
-export([connected_protocol_init/3]).
-export([connected/3]).
@@ -281,6 +281,26 @@
}.
-export_type([ws_opts/0]).
+-type resp_headers() :: [{binary(), binary()}].
+
+-type await_result() :: {inform, 100..199, resp_headers()}
+ | {response, fin | nofin, non_neg_integer(), resp_headers()}
+ | {data, fin | nofin, binary()}
+ | {sse, cow_sse:event() | fin}
+ | {trailers, resp_headers()}
+ | {push, stream_ref(), binary(), binary(), resp_headers()}
+ | {upgrade, [binary()], resp_headers()}
+ | {ws, ws_frame()}
+ | {up, http | http2 | raw | socks}
+ | {notify, settings_changed, map()}
+ | {error, {stream_error | connection_error | down, any()} | timeout}.
+-export_type([await_result/0]).
+
+-type await_body_result() :: {ok, binary()}
+ | {ok, binary(), resp_headers()}
+ | {error, {stream_error | connection_error | down, any()} | timeout}.
+-export_type([await_body_result/0]).
+
-record(state, {
owner :: pid(),
status :: {up, reference()} | {down, any()} | shutdown,
@@ -445,12 +465,12 @@ check_protocols_opt(Protocols) ->
consider_tracing(ServerPid, #{trace := true}) ->
dbg:tracer(),
- dbg:tpl(gun, [{'_', [], [{return_trace}]}]),
- dbg:tpl(gun_http, [{'_', [], [{return_trace}]}]),
- dbg:tpl(gun_http2, [{'_', [], [{return_trace}]}]),
- dbg:tpl(gun_raw, [{'_', [], [{return_trace}]}]),
- dbg:tpl(gun_socks, [{'_', [], [{return_trace}]}]),
- dbg:tpl(gun_ws, [{'_', [], [{return_trace}]}]),
+ _ = dbg:tpl(gun, [{'_', [], [{return_trace}]}]),
+ _ = dbg:tpl(gun_http, [{'_', [], [{return_trace}]}]),
+ _ = dbg:tpl(gun_http2, [{'_', [], [{return_trace}]}]),
+ _ = dbg:tpl(gun_raw, [{'_', [], [{return_trace}]}]),
+ _ = dbg:tpl(gun_socks, [{'_', [], [{return_trace}]}]),
+ _ = dbg:tpl(gun_ws, [{'_', [], [{return_trace}]}]),
dbg:p(ServerPid, all);
consider_tracing(_, _) ->
ok.
@@ -707,19 +727,6 @@ connect(ServerPid, Destination, Headers, ReqOpts) ->
%% Awaiting gun messages.
--type resp_headers() :: [{binary(), binary()}].
--type await_result() :: {inform, 100..199, resp_headers()}
- | {response, fin | nofin, non_neg_integer(), resp_headers()}
- | {data, fin | nofin, binary()}
- | {sse, cow_sse:event() | fin}
- | {trailers, resp_headers()}
- | {push, stream_ref(), binary(), binary(), resp_headers()}
- | {upgrade, [binary()], resp_headers()}
- | {ws, ws_frame()}
- | {up, http | http2 | raw | socks}
- | {notify, settings_changed, map()}
- | {error, {stream_error | connection_error | down, any()} | timeout}.
-
-spec await(pid(), stream_ref()) -> await_result().
await(ServerPid, StreamRef) ->
MRef = monitor(process, ServerPid),
@@ -769,10 +776,6 @@ await(ServerPid, StreamRef, Timeout, MRef) ->
{error, timeout}
end.
--type await_body_result() :: {ok, binary()}
- | {ok, binary(), resp_headers()}
- | {error, {stream_error | connection_error | down, any()} | timeout}.
-
-spec await_body(pid(), stream_ref()) -> await_body_result().
await_body(ServerPid, StreamRef) ->
MRef = monitor(process, ServerPid),
@@ -1097,7 +1100,7 @@ connecting(_, {retries, Retries, LookupInfo}, State=#state{opts=Opts,
initial_tls_handshake(_, {retries, Retries, Socket}, State0=#state{opts=Opts, origin_host=OriginHost}) ->
Protocols = maps:get(protocols, Opts, [http2, http]),
HandshakeEvent = #{
- tls_opts => ensure_alpn_sni(Protocols, maps:get(tls_opts, Opts, []), OriginHost),
+ tls_opts => ensure_tls_opts(Protocols, maps:get(tls_opts, Opts, []), OriginHost),
timeout => maps:get(tls_handshake_timeout, Opts, infinity)
},
case normal_tls_handshake(Socket, State0, HandshakeEvent, Protocols) of
@@ -1109,7 +1112,26 @@ initial_tls_handshake(_, {retries, Retries, Socket}, State0=#state{opts=Opts, or
{next_event, internal, {retries, Retries, Reason}}}
end.
-ensure_alpn_sni(Protocols0, TransOpts0, OriginHost) ->
+ensure_tls_opts(Protocols0, TransOpts0, OriginHost) ->
+ %% CA certificates.
+ TransOpts1 = case lists:keymember(cacerts, 1, TransOpts0) of
+ true ->
+ TransOpts0;
+ false ->
+ case lists:keymember(cacertfile, 1, TransOpts0) of
+ true ->
+ TransOpts0;
+ false ->
+ %% This function was added in OTP-25. We use it when it is
+ %% available and keep the previous behavior when it isn't.
+ case erlang:function_exported(public_key, cacerts_get, 0) of
+ true ->
+ [{cacerts, public_key:cacerts_get()}|TransOpts0];
+ false ->
+ TransOpts0
+ end
+ end
+ end,
%% ALPN.
Protocols = lists:foldl(fun
(http, Acc) -> [<<"http/1.1">>|Acc];
@@ -1120,7 +1142,7 @@ ensure_alpn_sni(Protocols0, TransOpts0, OriginHost) ->
end, [], Protocols0),
TransOpts = [
{alpn_advertised_protocols, Protocols}
- |TransOpts0],
+ |TransOpts1],
%% SNI.
%%
%% Normally only DNS hostnames are supported for SNI. However, the ssl
@@ -1161,7 +1183,7 @@ tls_handshake(internal, {tls_handshake,
HandshakeEvent0=#{tls_opts := TLSOpts0, timeout := TLSTimeout}, Protocols, ReplyTo},
State=#state{socket=Socket, transport=Transport, origin_host=OriginHost, origin_port=OriginPort,
event_handler=EvHandler, event_handler_state=EvHandlerState0}) ->
- TLSOpts = ensure_alpn_sni(Protocols, TLSOpts0, OriginHost),
+ TLSOpts = ensure_tls_opts(Protocols, TLSOpts0, OriginHost),
HandshakeEvent = HandshakeEvent0#{
tls_opts => TLSOpts,
socket => Socket
@@ -1201,7 +1223,7 @@ tls_handshake(Type, Event, State) ->
normal_tls_handshake(Socket, State=#state{
origin_host=OriginHost, event_handler=EvHandler, event_handler_state=EvHandlerState0},
HandshakeEvent0=#{tls_opts := TLSOpts0, timeout := TLSTimeout}, Protocols) ->
- TLSOpts = ensure_alpn_sni(Protocols, TLSOpts0, OriginHost),
+ TLSOpts = ensure_tls_opts(Protocols, TLSOpts0, OriginHost),
HandshakeEvent = HandshakeEvent0#{
tls_opts => TLSOpts,
socket => Socket
diff --git a/src/gun_http2.erl b/src/gun_http2.erl
index 71e01d4..bfd2d31 100644
--- a/src/gun_http2.erl
+++ b/src/gun_http2.erl
@@ -585,7 +585,7 @@ headers_frame_connect(State=#http2_state{transport=Transport, opts=Opts, tunnel_
ProtoOpts = case Destination of
#{transport := tls} ->
Protocols = maps:get(protocols, Destination, [http2, http]),
- TLSOpts = gun:ensure_alpn_sni(Protocols, maps:get(tls_opts, Destination, []), DestHost),
+ TLSOpts = gun:ensure_tls_opts(Protocols, maps:get(tls_opts, Destination, []), DestHost),
HandshakeEvent = #{
stream_ref => RealStreamRef,
reply_to => ReplyTo,
diff --git a/src/gun_tunnel.erl b/src/gun_tunnel.erl
index c7fecc7..789d1e3 100644
--- a/src/gun_tunnel.erl
+++ b/src/gun_tunnel.erl
@@ -565,7 +565,7 @@ commands([{tls_handshake, HandshakeEvent0, Protocols, ReplyTo}|Tail],
stream_ref := StreamRef,
tls_opts := TLSOpts0
} = HandshakeEvent0,
- TLSOpts = gun:ensure_alpn_sni(Protocols, TLSOpts0, OriginHost),
+ TLSOpts = gun:ensure_tls_opts(Protocols, TLSOpts0, OriginHost),
HandshakeEvent = HandshakeEvent0#{
tls_opts => TLSOpts
},
diff --git a/test/event_SUITE.erl b/test/event_SUITE.erl
index e7def6e..81cdf09 100644
--- a/test/event_SUITE.erl
+++ b/test/event_SUITE.erl
@@ -55,7 +55,9 @@ init_per_suite(Config) ->
},
{ok, _} = cowboy:start_clear({?MODULE, tcp}, [], ProtoOpts),
TCPOriginPort = ranch:get_port({?MODULE, tcp}),
- {ok, _} = cowboy:start_tls({?MODULE, tls}, ct_helper:get_certs_from_ets(), ProtoOpts),
+ {ok, _} = cowboy:start_tls({?MODULE, tls},
+ [{fail_if_no_peer_cert, false}|ct_helper:get_certs_from_ets()],
+ ProtoOpts),
TLSOriginPort = ranch:get_port({?MODULE, tls}),
[{tcp_origin_port, TCPOriginPort}, {tls_origin_port, TLSOriginPort}|Config].
diff --git a/test/gun_SUITE.erl b/test/gun_SUITE.erl
index 656158e..8b90774 100644
--- a/test/gun_SUITE.erl
+++ b/test/gun_SUITE.erl
@@ -462,13 +462,15 @@ server_name_indication_custom(_) ->
do_server_name_indication("localhost", net_adm:localhost(), #{
tls_opts => [
{verify, verify_none}, {versions, ['tlsv1.2']},
+ {fail_if_no_peer_cert, false},
{server_name_indication, net_adm:localhost()}]
}).
server_name_indication_default(_) ->
doc("Ensure a default server_name_indication is accepted."),
do_server_name_indication(net_adm:localhost(), net_adm:localhost(), #{
- tls_opts => [{verify, verify_none}, {versions, ['tlsv1.2']}]
+ tls_opts => [{verify, verify_none}, {versions, ['tlsv1.2']},
+ {fail_if_no_peer_cert, false}]
}).
do_server_name_indication(Host, Expected, GunOpts) ->
@@ -630,7 +632,8 @@ tls_handshake_error_gun_http2_init_retry_0(_) ->
}},
protocols => [http2],
retry => 0,
- transport => tls
+ transport => tls,
+ tls_opts => [{verify, verify_none}]
}),
{error, {down, {shutdown, closed}}} = gun:await_up(ConnPid),
gun:close(ConnPid).
@@ -665,7 +668,8 @@ tls_handshake_error_gun_http2_init_retry_1(_) ->
}},
protocols => [http2],
retry => 1,
- transport => tls
+ transport => tls,
+ tls_opts => [{verify, verify_none}]
}),
{error, {down, {shutdown, closed}}} = gun:await_up(ConnPid),
gun:close(ConnPid).
diff --git a/test/gun_test.erl b/test/gun_test.erl
index 18fcfbf..cffeed5 100644
--- a/test/gun_test.erl
+++ b/test/gun_test.erl
@@ -24,7 +24,9 @@ init_cowboy_tcp(Ref, ProtoOpts, Config) ->
init_cowboy_tls(Ref, ProtoOpts, Config) ->
Opts = ct_helper:get_certs_from_ets(),
- {ok, _} = cowboy:start_tls(Ref, Opts ++ [{port, 0}], ProtoOpts),
+ {ok, _} = cowboy:start_tls(Ref,
+ [{verify, verify_none}, {fail_if_no_peer_cert, false}]
+ ++ Opts ++ [{port, 0}], ProtoOpts),
[{ref, Ref}, {port, ranch:get_port(Ref)}|Config].
%% Origin server helpers.
@@ -64,7 +66,8 @@ init_origin(Parent, tls, Protocol, Fun) ->
end,
%% sni_hosts is necessary for SNI tests to succeed.
Opts = [{sni_hosts, [{net_adm:localhost(), []}]}|Opts1],
- {ok, ListenSocket} = ssl:listen(0, [binary, {active, false}|Opts]),
+ {ok, ListenSocket} = ssl:listen(0, [binary, {active, false},
+ {fail_if_no_peer_cert, false}|Opts]),
{ok, {_, Port}} = ssl:sockname(ListenSocket),
Parent ! {self(), Port},
{ok, ClientSocket0} = ssl:transport_accept(ListenSocket, 5000),
diff --git a/test/rfc7231_SUITE.erl b/test/rfc7231_SUITE.erl
index a5e1fe5..f3a780e 100644
--- a/test/rfc7231_SUITE.erl
+++ b/test/rfc7231_SUITE.erl
@@ -55,7 +55,8 @@ do_proxy_init(Parent, Transport, Status, ConnectRespHeaders, Delay, ConnectRespV
gen_tcp:listen(0, [binary, {active, false}]);
gun_tls ->
Opts = ct_helper:get_certs_from_ets(),
- ssl:listen(0, [binary, {active, false}|Opts])
+ ssl:listen(0, [binary, {active, false}, {verify, verify_none},
+ {fail_if_no_peer_cert, false}|Opts])
end,
{ok, {_, Port}} = Transport:sockname(ListenSocket),
Parent ! {self(), Port},
diff --git a/test/rfc7540_SUITE.erl b/test/rfc7540_SUITE.erl
index ac88469..79ae347 100644
--- a/test/rfc7540_SUITE.erl
+++ b/test/rfc7540_SUITE.erl
@@ -62,7 +62,9 @@ do_proxy_init(Proxy=#proxy{parent=Parent, transport=Transport}) ->
gen_tcp:listen(0, [binary, {active, false}]);
gun_tls ->
Opts = ct_helper:get_certs_from_ets(),
- ssl:listen(0, [binary, {active, false}, {alpn_preferred_protocols, [<<"h2">>]}|Opts])
+ ssl:listen(0, [binary, {active, false}, {verify, verify_none},
+ {fail_if_no_peer_cert, false},
+ {alpn_preferred_protocols, [<<"h2">>]}|Opts])
end,
{ok, {_, Port}} = Transport:sockname(ListenSocket),
Parent ! {self(), Port},
diff --git a/test/socks_SUITE.erl b/test/socks_SUITE.erl
index bd88cbb..19d15ca 100644
--- a/test/socks_SUITE.erl
+++ b/test/socks_SUITE.erl
@@ -50,7 +50,8 @@ do_proxy_init(Parent, Transport, Auth) ->
gen_tcp:listen(0, [binary, {active, false}]);
gun_tls ->
Opts = ct_helper:get_certs_from_ets(),
- ssl:listen(0, [binary, {active, false}|Opts])
+ ssl:listen(0, [binary, {active, false}, {verify, verify_none},
+ {fail_if_no_peer_cert, false}|Opts])
end,
{ok, {_, Port}} = Transport:sockname(ListenSocket),
Parent ! {self(), Port},