aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/src/inet_tls_dist.erl2
-rw-r--r--lib/ssl/src/ssl_connection.erl2
-rw-r--r--lib/ssl/src/ssl_dist_sup.erl2
-rw-r--r--lib/ssl/src/ssl_internal.hrl3
-rw-r--r--lib/ssl/src/ssl_manager.erl2
-rw-r--r--lib/ssl/src/ssl_session.erl2
-rw-r--r--lib/ssl/src/ssl_tls_dist_proxy.erl43
-rw-r--r--lib/ssl/src/tls_connection.erl3
-rw-r--r--lib/ssl/src/tls_record.erl62
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl1
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl13
-rw-r--r--lib/ssl/test/ssl_test_lib.erl11
12 files changed, 113 insertions, 33 deletions
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index b6e62a18c9..404ae93d20 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -30,7 +30,7 @@
childspecs() ->
{ok, [{ssl_dist_sup,{ssl_dist_sup, start_link, []},
- permanent, 2000, worker, [ssl_dist_sup]}]}.
+ permanent, infinity, supervisor, [ssl_dist_sup]}]}.
select(Node) ->
case split_node(atom_to_list(Node), $@, []) of
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index f8afbdb41d..12a56df69f 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1781,7 +1781,7 @@ handle_trusted_certs_db(#state{ssl_options = #ssl_options{cacertfile = <<>>, cac
ok;
handle_trusted_certs_db(#state{cert_db_ref = Ref,
cert_db = CertDb,
- ssl_options = #ssl_options{cacertfile = <<>>}}) ->
+ ssl_options = #ssl_options{cacertfile = <<>>}}) when CertDb =/= undefined ->
%% Certs provided as DER directly can not be shared
%% with other connections and it is safe to delete them when the connection ends.
ssl_pkix_db:remove_trusted_certs(Ref, CertDb);
diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl
index aa1fa57db8..435ad27a44 100644
--- a/lib/ssl/src/ssl_dist_sup.erl
+++ b/lib/ssl/src/ssl_dist_sup.erl
@@ -70,7 +70,7 @@ connection_manager_child_spec() ->
Name = ssl_connection_dist,
StartFunc = {tls_connection_sup, start_link_dist, []},
Restart = permanent,
- Shutdown = 4000,
+ Shutdown = infinity,
Modules = [tls_connection_sup],
Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 3851b2bc6e..8c7ed9c0d1 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -78,6 +78,9 @@
-define(ALL_DATAGRAM_SUPPORTED_VERSIONS, ['dtlsv1.2', dtlsv1]).
-define(MIN_DATAGRAM_SUPPORTED_VERSIONS, ['dtlsv1.2', dtlsv1]).
+-define('24H_in_msec', 86400000).
+-define('24H_in_sec', 86400).
+
-record(ssl_options, {
protocol :: tls | dtls,
versions :: [ssl_record:ssl_version()], %% ssl_record:atom_version() in API
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index 2e05ba5aa5..cc15678f23 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -57,8 +57,6 @@
clear_pem_cache
}).
--define('24H_in_msec', 86400000).
--define('24H_in_sec', 86400).
-define(GEN_UNIQUE_ID_MAX_TRIES, 10).
-define(SESSION_VALIDATION_INTERVAL, 60000).
-define(CLEAR_PEM_CACHE, 120000).
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index 0d6cc93a20..1849a05314 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -31,8 +31,6 @@
%% Internal application API
-export([is_new/2, client_id/4, server_id/6, valid_session/2]).
--define('24H_in_sec', 8640).
-
-type seconds() :: integer().
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl
index 273d3b5521..fda08cb87f 100644
--- a/lib/ssl/src/ssl_tls_dist_proxy.erl
+++ b/lib/ssl/src/ssl_tls_dist_proxy.erl
@@ -66,9 +66,13 @@ handle_call({listen, Name}, _From, State) ->
{ok, TcpAddress} = get_tcp_address(Socket),
{ok, WorldTcpAddress} = get_tcp_address(World),
{_,Port} = WorldTcpAddress#net_address.address,
- {ok, Creation} = erl_epmd:register_node(Name, Port),
- {reply, {ok, {Socket, TcpAddress, Creation}},
- State#state{listen={Socket, World}}};
+ case erl_epmd:register_node(Name, Port) of
+ {ok, Creation} ->
+ {reply, {ok, {Socket, TcpAddress, Creation}},
+ State#state{listen={Socket, World}}};
+ {error, _} = Error ->
+ {reply, Error, State}
+ end;
Error ->
{reply, Error, State}
end;
@@ -134,6 +138,7 @@ accept_loop(Proxy, erts = Type, Listen, Extra) ->
Extra ! {accept,self(),Socket,inet,proxy},
receive
{_Kernel, controller, Pid} ->
+ inet:setopts(Socket, [nodelay()]),
ok = gen_tcp:controlling_process(Socket, Pid),
flush_old_controller(Pid, Socket),
Pid ! {self(), controller};
@@ -167,7 +172,7 @@ accept_loop(Proxy, world = Type, Listen, Extra) ->
accept_loop(Proxy, Type, Listen, Extra).
try_connect(Port) ->
- case gen_tcp:connect({127,0,0,1}, Port, [{active, false}, {packet,?PPRE}]) of
+ case gen_tcp:connect({127,0,0,1}, Port, [{active, false}, {packet,?PPRE}, nodelay()]) of
R = {ok, _S} ->
R;
{error, _R} ->
@@ -177,7 +182,7 @@ try_connect(Port) ->
setup_proxy(Ip, Port, Parent) ->
process_flag(trap_exit, true),
Opts = get_ssl_options(client),
- case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}] ++ Opts) of
+ case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}, nodelay()] ++ Opts) of
{ok, World} ->
{ok, ErtsL} = gen_tcp:listen(0, [{active, true}, {ip, {127,0,0,1}}, binary, {packet,?PPRE}]),
{ok, #net_address{address={_,LPort}}} = get_tcp_address(ErtsL),
@@ -193,25 +198,41 @@ setup_proxy(Ip, Port, Parent) ->
Parent ! {self(), Err}
end.
+
+%% we may not always want the nodelay behaviour
+%% %% for performance reasons
+
+nodelay() ->
+ case application:get_env(kernel, dist_nodelay) of
+ undefined ->
+ {nodelay, true};
+ {ok, true} ->
+ {nodelay, true};
+ {ok, false} ->
+ {nodelay, false};
+ _ ->
+ {nodelay, true}
+ end.
+
setup_connection(World, ErtsListen) ->
process_flag(trap_exit, true),
{ok, TcpAddress} = get_tcp_address(ErtsListen),
{_Addr,Port} = TcpAddress#net_address.address,
- {ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}]),
- ssl:setopts(World, [{active,true}, {packet,?PPRE}]),
+ {ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}, nodelay()]),
+ ssl:setopts(World, [{active,true}, {packet,?PPRE}, nodelay()]),
loop_conn_setup(World, Erts).
loop_conn_setup(World, Erts) ->
receive
{ssl, World, Data = <<$a, _/binary>>} ->
gen_tcp:send(Erts, Data),
- ssl:setopts(World, [{packet,?PPOST}]),
- inet:setopts(Erts, [{packet,?PPOST}]),
+ ssl:setopts(World, [{packet,?PPOST}, nodelay()]),
+ inet:setopts(Erts, [{packet,?PPOST}, nodelay()]),
loop_conn(World, Erts);
{tcp, Erts, Data = <<$a, _/binary>>} ->
ssl:send(World, Data),
- ssl:setopts(World, [{packet,?PPOST}]),
- inet:setopts(Erts, [{packet,?PPOST}]),
+ ssl:setopts(World, [{packet,?PPOST}, nodelay()]),
+ inet:setopts(Erts, [{packet,?PPOST}, nodelay()]),
loop_conn(World, Erts);
{ssl, World, Data = <<_, _/binary>>} ->
gen_tcp:send(Erts, Data),
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 3093508f61..a468c131ce 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -168,9 +168,10 @@ hello(start, #state{host = Host, port = Port, role = client,
Cache, CacheCb, Renegotiation, Cert),
Version = Hello#client_hello.client_version,
+ HelloVersion = tls_record:lowest_protocol_version(SslOpts#ssl_options.versions),
Handshake0 = ssl_handshake:init_handshake_history(),
{BinMsg, ConnectionStates, Handshake} =
- encode_handshake(Hello, Version, ConnectionStates0, Handshake0),
+ encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0),
Transport:send(Socket, BinMsg),
State1 = State0#state{connection_states = ConnectionStates,
negotiated_version = Version, %% Requested version
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index aa524f0225..1e266ed424 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -41,8 +41,9 @@
-export([encode_plain_text/4]).
%% Protocol version handling
--export([protocol_version/1, lowest_protocol_version/2,
- highest_protocol_version/1, is_higher/2, supported_protocol_versions/0,
+-export([protocol_version/1, lowest_protocol_version/1, lowest_protocol_version/2,
+ highest_protocol_version/1, highest_protocol_version/2,
+ is_higher/2, supported_protocol_versions/0,
is_acceptable_version/1, is_acceptable_version/2]).
-export_type([tls_version/0, tls_atom_version/0]).
@@ -257,6 +258,18 @@ lowest_protocol_version(Version = {M,_},
Version;
lowest_protocol_version(_,Version) ->
Version.
+
+%%--------------------------------------------------------------------
+-spec lowest_protocol_version([tls_version()]) -> tls_version().
+%%
+%% Description: Lowest protocol version present in a list
+%%--------------------------------------------------------------------
+lowest_protocol_version([]) ->
+ lowest_protocol_version();
+lowest_protocol_version(Versions) ->
+ [Ver | Vers] = Versions,
+ lowest_list_protocol_version(Ver, Vers).
+
%%--------------------------------------------------------------------
-spec highest_protocol_version([tls_version()]) -> tls_version().
%%
@@ -266,19 +279,29 @@ highest_protocol_version([]) ->
highest_protocol_version();
highest_protocol_version(Versions) ->
[Ver | Vers] = Versions,
- highest_protocol_version(Ver, Vers).
+ highest_list_protocol_version(Ver, Vers).
-highest_protocol_version(Version, []) ->
+%%--------------------------------------------------------------------
+-spec highest_protocol_version(tls_version(), tls_version()) -> tls_version().
+%%
+%% Description: Highest protocol version of two given versions
+%%--------------------------------------------------------------------
+highest_protocol_version(Version = {M, N}, {M, O}) when N > O ->
+ Version;
+highest_protocol_version({M, _},
+ Version = {M, _}) ->
Version;
-highest_protocol_version(Version = {N, M}, [{N, O} | Rest]) when M > O ->
- highest_protocol_version(Version, Rest);
-highest_protocol_version({M, _}, [Version = {M, _} | Rest]) ->
- highest_protocol_version(Version, Rest);
-highest_protocol_version(Version = {M,_}, [{N,_} | Rest]) when M > N ->
- highest_protocol_version(Version, Rest);
-highest_protocol_version(_, [Version | Rest]) ->
- highest_protocol_version(Version, Rest).
+highest_protocol_version(Version = {M,_},
+ {N, _}) when M > N ->
+ Version;
+highest_protocol_version(_,Version) ->
+ Version.
+%%--------------------------------------------------------------------
+-spec is_higher(V1 :: tls_version(), V2::tls_version()) -> tls_version().
+%%
+%% Description: Is V1 > V2
+%%--------------------------------------------------------------------
is_higher({M, N}, {M, O}) when N > O ->
true;
is_higher({M, _}, {N, _}) when M > N ->
@@ -352,6 +375,17 @@ is_acceptable_version(_,_) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+
+lowest_list_protocol_version(Ver, []) ->
+ Ver;
+lowest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
+ lowest_list_protocol_version(lowest_protocol_version(Ver1, Ver2), Rest).
+
+highest_list_protocol_version(Ver, []) ->
+ Ver;
+highest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
+ highest_list_protocol_version(highest_protocol_version(Ver1, Ver2), Rest).
+
encode_tls_cipher_text(Type, {MajVer, MinVer}, Fragment) ->
Length = erlang:iolist_size(Fragment),
[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>, Fragment].
@@ -370,6 +404,10 @@ mac_hash({3, N} = Version, MacAlg, MacSecret, SeqNo, Type, Length, Fragment)
highest_protocol_version() ->
highest_protocol_version(supported_protocol_versions()).
+lowest_protocol_version() ->
+ lowest_protocol_version(supported_protocol_versions()).
+
+
sufficient_tlsv1_2_crypto_support() ->
CryptoSupport = crypto:supports(),
proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)).
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 6f6107de2c..f032c769e2 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -35,7 +35,6 @@
-include("tls_record.hrl").
-include("tls_handshake.hrl").
--define('24H_in_sec', 86400).
-define(TIMEOUT, 20000).
-define(EXPIRE, 10).
-define(SLEEP, 500).
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 72d62b29a7..19ed4e1299 100644
--- a/lib/ssl/test/ssl_dist_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_SUITE.erl
@@ -40,7 +40,7 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- [basic, payload, plain_options, plain_verify_options].
+ [basic, payload, plain_options, plain_verify_options, nodelay_option].
groups() ->
[].
@@ -250,6 +250,17 @@ plain_verify_options(Config) when is_list(Config) ->
stop_ssl_node(NH1),
stop_ssl_node(NH2),
success(Config).
+%%--------------------------------------------------------------------
+nodelay_option() ->
+ [{doc,"Test specifying dist_nodelay option"}].
+nodelay_option(Config) ->
+ try
+ %% The default is 'true', so try setting it to 'false'.
+ application:set_env(kernel, dist_nodelay, false),
+ basic(Config)
+ after
+ application:unset_env(kernel, dist_nodelay)
+ end.
%%--------------------------------------------------------------------
%%% Internal functions -----------------------------------------------
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index ba8588f2f9..f25f6f9425 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -226,6 +226,17 @@ run_client(Opts) ->
ct:log("~p:~p~nClient faild several times: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
Pid ! {self(), {error, Reason}}
end;
+ {error, econnreset = Reason} ->
+ case get(retries) of
+ N when N < 5 ->
+ ct:log("~p:~p~neconnreset retries=~p sleep ~p",[?MODULE,?LINE, N,?SLEEP]),
+ put(retries, N+1),
+ ct:sleep(?SLEEP),
+ run_client(Opts);
+ _ ->
+ ct:log("~p:~p~nClient faild several times: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
+ Pid ! {self(), {error, Reason}}
+ end;
{error, Reason} ->
ct:log("~p:~p~nClient: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
Pid ! {connect_failed, Reason};