aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/doc/src/notes.xml20
-rw-r--r--lib/ssl/src/ssl.appup.src5
-rw-r--r--lib/ssl/src/ssl_connection.erl2
-rw-r--r--lib/ssl/src/ssl_handshake.erl38
-rw-r--r--lib/ssl/src/ssl_tls_dist_proxy.erl2
-rw-r--r--lib/ssl/src/tls_connection.erl59
-rw-r--r--lib/ssl/src/tls_handshake.erl39
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl7
-rw-r--r--lib/ssl/test/ssl_crl_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_npn_hello_SUITE.erl9
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl4
-rw-r--r--lib/ssl/test/ssl_payload_SUITE.erl9
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl3
13 files changed, 157 insertions, 42 deletions
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 3b6f988a2d..9d68ee0eee 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -28,6 +28,26 @@
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 8.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The TLS/SSL protocol version selection for the SSL server
+ has been corrected to follow RFC 5246 Appendix E.1
+ especially in case where the list of supported versions
+ has gaps. Now the server selects the highest protocol
+ version it supports that is not higher than what the
+ client supports.</p>
+ <p>
+ Own Id: OTP-13753 Aux Id: seq13150 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 8.0</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index feee6648d7..22e24af0a8 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -2,11 +2,10 @@
{"%VSN%",
[
{<<"^8[.]0([.][0-9]+)?$">>, [{restart_application, ssl}]},
- {<<"^[3-7][.].*">>, [{restart_application, ssl}]}
+ {<<"^[3-7][.][^.].*">>, [{restart_application, ssl}]}
],
[
{<<"^8[.]0([.][0-9]+)?$">>, [{restart_application, ssl}]},
- {<<"^[3-7][.].*">>, [{restart_application, ssl}]}
+ {<<"^[3-7][.][^.].*">>, [{restart_application, ssl}]}
]
}.
-
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index adee59393e..8a990870e8 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -824,8 +824,6 @@ handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName,
#state{negotiated_version = Version} = State, Connection) ->
Connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), Version,
StateName, State);
-handle_common_event(internal, _, _, _, _) ->
- {keep_state_and_data, [postpone]};
handle_common_event(_Type, Msg, StateName, #state{negotiated_version = Version} = State,
Connection) ->
Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE),
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index bca341c8bc..081efda768 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -658,7 +658,7 @@ select_hashsign(#certificate_request{hashsign_algorithms = #hash_sign_algos{hash
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm)
end;
select_hashsign(#certificate_request{}, Cert, _, Version) ->
- select_hashsign(undefined, Cert, undefined, undefined, Version).
+ select_hashsign(undefined, Cert, undefined, [], Version).
%%--------------------------------------------------------------------
-spec select_hashsign_algs({atom(), atom()}| undefined, oid(), ssl_record:ssl_version()) ->
@@ -1305,8 +1305,40 @@ handle_server_hello_extensions(RecordCB, Random, CipherSuite, Compression,
end.
select_version(RecordCB, ClientVersion, Versions) ->
- ServerVersion = RecordCB:highest_protocol_version(Versions),
- RecordCB:lowest_protocol_version(ClientVersion, ServerVersion).
+ do_select_version(RecordCB, ClientVersion, Versions).
+
+do_select_version(_, ClientVersion, []) ->
+ ClientVersion;
+do_select_version(RecordCB, ClientVersion, [Version | Versions]) ->
+ case RecordCB:is_higher(Version, ClientVersion) of
+ true ->
+ %% Version too high for client - keep looking
+ do_select_version(RecordCB, ClientVersion, Versions);
+ false ->
+ %% Version ok for client - look for a higher
+ do_select_version(RecordCB, ClientVersion, Versions, Version)
+ end.
+%%
+do_select_version(_, _, [], GoodVersion) ->
+ GoodVersion;
+do_select_version(
+ RecordCB, ClientVersion, [Version | Versions], GoodVersion) ->
+ BetterVersion =
+ case RecordCB:is_higher(Version, ClientVersion) of
+ true ->
+ %% Version too high for client
+ GoodVersion;
+ false ->
+ %% Version ok for client
+ case RecordCB:is_higher(Version, GoodVersion) of
+ true ->
+ %% Use higher version
+ Version;
+ false ->
+ GoodVersion
+ end
+ end,
+ do_select_version(RecordCB, ClientVersion, Versions, BetterVersion).
renegotiation_info(_, client, _, false) ->
#renegotiation_info{renegotiated_connection = undefined};
diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl
index a920f54ed2..08947f24dd 100644
--- a/lib/ssl/src/ssl_tls_dist_proxy.erl
+++ b/lib/ssl/src/ssl_tls_dist_proxy.erl
@@ -117,7 +117,7 @@ handle_call({listen, Driver, Name}, _From, State) ->
{ok, WorldTcpAddress} = get_tcp_address(World),
{_,Port} = WorldTcpAddress#net_address.address,
ErlEpmd = net_kernel:epmd_module(),
- case ErlEpmd:register_node(Name, Port) of
+ case ErlEpmd:register_node(Name, Port, Driver) of
{ok, Creation} ->
{reply, {ok, {Socket, TcpAddress, Creation}},
State#state{listen={Socket, World}}};
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index eaf866c339..8b828f3421 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -214,7 +214,7 @@ init({call, From}, {start, Timeout},
{Record, State} = next_record(State1),
next_event(hello, Record, State);
init(Type, Event, State) ->
- ssl_connection:init(Type, Event, State, ?MODULE).
+ gen_handshake(ssl_connection, init, Type, Event, State).
%%--------------------------------------------------------------------
-spec error(gen_statem:event_type(),
@@ -258,13 +258,13 @@ hello(internal, #client_hello{client_version = ClientVersion,
_ -> Protocol0
end,
- ssl_connection:hello(internal, {common_client_hello, Type, ServerHelloExt},
+ gen_handshake(ssl_connection, hello, internal, {common_client_hello, Type, ServerHelloExt},
State#state{connection_states = ConnectionStates,
negotiated_version = Version,
hashsign_algorithm = HashSign,
session = Session,
client_ecc = {EllipticCurves, EcPointFormats},
- negotiated_protocol = Protocol}, ?MODULE)
+ negotiated_protocol = Protocol})
end;
hello(internal, #server_hello{} = Hello,
#state{connection_states = ConnectionStates0,
@@ -280,36 +280,36 @@ hello(internal, #server_hello{} = Hello,
Version, NewId, ConnectionStates, ProtoExt, Protocol, State)
end;
hello(info, Event, State) ->
- handle_info(Event, hello, State);
+ gen_info(Event, hello, State);
hello(Type, Event, State) ->
- ssl_connection:hello(Type, Event, State, ?MODULE).
+ gen_handshake(ssl_connection, hello, Type, Event, State).
%%--------------------------------------------------------------------
-spec abbreviated(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
abbreviated(info, Event, State) ->
- handle_info(Event, abbreviated, State);
+ gen_info(Event, abbreviated, State);
abbreviated(Type, Event, State) ->
- ssl_connection:abbreviated(Type, Event, State, ?MODULE).
+ gen_handshake(ssl_connection, abbreviated, Type, Event, State).
%%--------------------------------------------------------------------
-spec certify(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
certify(info, Event, State) ->
- handle_info(Event, certify, State);
+ gen_info(Event, certify, State);
certify(Type, Event, State) ->
- ssl_connection:certify(Type, Event, State, ?MODULE).
+ gen_handshake(ssl_connection, certify, Type, Event, State).
%%--------------------------------------------------------------------
-spec cipher(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
cipher(info, Event, State) ->
- handle_info(Event, cipher, State);
+ gen_info(Event, cipher, State);
cipher(Type, Event, State) ->
- ssl_connection:cipher(Type, Event, State, ?MODULE).
+ gen_handshake(ssl_connection, cipher, Type, Event, State).
%%--------------------------------------------------------------------
-spec connection(gen_statem:event_type(),
@@ -317,7 +317,7 @@ cipher(Type, Event, State) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
connection(info, Event, State) ->
- handle_info(Event, connection, State);
+ gen_info(Event, connection, State);
connection(internal, #hello_request{},
#state{role = client, host = Host, port = Port,
session = #session{own_certificate = Cert} = Session0,
@@ -433,11 +433,16 @@ handle_common_event(internal, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = Da
%%% TLS record protocol level Alert messages
handle_common_event(internal, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
#state{negotiated_version = Version} = State) ->
- case decode_alerts(EncAlerts) of
+ try decode_alerts(EncAlerts) of
Alerts = [_|_] ->
handle_alerts(Alerts, {next_state, StateName, State});
+ [] ->
+ handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, empty_alert), Version, StateName, State);
#alert{} = Alert ->
handle_own_alert(Alert, Version, StateName, State)
+ catch
+ _:_ ->
+ handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, alert_decode_error), Version, StateName, State)
end;
%% Ignore unknown TLS record level protocol messages
handle_common_event(internal, #ssl_tls{type = _Unknown}, StateName, State) ->
@@ -1040,3 +1045,31 @@ handle_sni_extension(#client_hello{extensions = HelloExtensions}, State0) ->
end;
handle_sni_extension(_, State) ->
State.
+
+gen_handshake(GenConnection, StateName, Type, Event, #state{negotiated_version = Version} = State) ->
+ try GenConnection:StateName(Type, Event, State, ?MODULE) of
+ Result ->
+ Result
+ catch
+ _:_ ->
+ handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data), Version, StateName, State)
+ end.
+
+gen_info(Event, connection = StateName, #state{negotiated_version = Version} = State) ->
+ try handle_info(Event, StateName, State) of
+ Result ->
+ Result
+ catch
+ _:_ ->
+ handle_own_alert(?ALERT_REC(?FATAL, ?INTERNAL_ERROR, malformed_data), Version, StateName, State)
+ end;
+
+gen_info(Event, StateName, #state{negotiated_version = Version} = State) ->
+ try handle_info(Event, StateName, State) of
+ Result ->
+ Result
+ catch
+ _:_ ->
+ handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data), Version, StateName, State)
+ end.
+
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index 566b7db332..6e593950d9 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -109,19 +109,25 @@ hello(#client_hello{client_version = ClientVersion,
cipher_suites = CipherSuites} = Hello,
#ssl_options{versions = Versions} = SslOpts,
Info, Renegotiation) ->
- Version = ssl_handshake:select_version(tls_record, ClientVersion, Versions),
- case ssl_cipher:is_fallback(CipherSuites) of
+ try
+ Version = ssl_handshake:select_version(tls_record, ClientVersion, Versions),
+ case ssl_cipher:is_fallback(CipherSuites) of
true ->
- Highest = tls_record:highest_protocol_version(Versions),
- case tls_record:is_higher(Highest, Version) of
- true ->
- ?ALERT_REC(?FATAL, ?INAPPROPRIATE_FALLBACK);
- false ->
- handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
- end;
- false ->
- handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
- end.
+ Highest = tls_record:highest_protocol_version(Versions),
+ case tls_record:is_higher(Highest, Version) of
+ true ->
+ ?ALERT_REC(?FATAL, ?INAPPROPRIATE_FALLBACK);
+ false ->
+ handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
+ end;
+ false ->
+ handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
+ end
+ catch
+ _:_ ->
+ ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data)
+ end.
+
%%--------------------------------------------------------------------
-spec encode_handshake(tls_handshake(), tls_record:tls_version()) -> iolist().
%%
@@ -187,8 +193,13 @@ handle_client_hello(Version, #client_hello{session_id = SugesstedId,
get_tls_handshake_aux(Version, <<?BYTE(Type), ?UINT24(Length),
Body:Length/binary,Rest/binary>>, #ssl_options{v2_hello_compatible = V2Hello} = Opts, Acc) ->
Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>,
- Handshake = decode_handshake(Version, Type, Body, V2Hello),
- get_tls_handshake_aux(Version, Rest, Opts, [{Handshake,Raw} | Acc]);
+ try decode_handshake(Version, Type, Body, V2Hello) of
+ Handshake ->
+ get_tls_handshake_aux(Version, Rest, Opts, [{Handshake,Raw} | Acc])
+ catch
+ _:_ ->
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, handshake_decode_error))
+ end;
get_tls_handshake_aux(_Version, Data, _, Acc) ->
{lists:reverse(Acc), Data}.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 665dbb1df3..38341f77aa 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -340,7 +340,7 @@ init_per_testcase(TestCase, Config) when TestCase == client_renegotiate;
TestCase == renegotiate_dos_mitigate_passive;
TestCase == renegotiate_dos_mitigate_absolute ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 30}),
+ ct:timetrap({seconds, 90}),
Config;
init_per_testcase(TestCase, Config) when TestCase == psk_cipher_suites;
@@ -350,6 +350,11 @@ init_per_testcase(TestCase, Config) when TestCase == psk_cipher_suites;
TestCase == ciphers_dsa_signed_certs;
TestCase == ciphers_dsa_signed_certs_openssl_names;
TestCase == anonymous_cipher_suites;
+ TestCase == ciphers_ecdsa_signed_certs;
+ TestCase == ciphers_ecdsa_signed_certs_openssl_names;
+ TestCase == anonymous_cipher_suites;
+ TestCase == psk_anon_cipher_suites;
+ TestCase == psk_anon_with_hint_cipher_suites;
TestCase == versions_option,
TestCase == tls_tcp_connect_big ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
diff --git a/lib/ssl/test/ssl_crl_SUITE.erl b/lib/ssl/test/ssl_crl_SUITE.erl
index 00636e5660..e37e127440 100644
--- a/lib/ssl/test/ssl_crl_SUITE.erl
+++ b/lib/ssl/test/ssl_crl_SUITE.erl
@@ -72,7 +72,7 @@ init_per_suite(Config) ->
false ->
{skip, io_lib:format("Bad openssl version: ~p",[OpenSSL_version])};
_ ->
- catch crypto:stop(),
+ end_per_suite(Config),
try crypto:start() of
ok ->
{ok, Hostname0} = inet:gethostname(),
diff --git a/lib/ssl/test/ssl_npn_hello_SUITE.erl b/lib/ssl/test/ssl_npn_hello_SUITE.erl
index 00eb9fee4f..6ae9efe5e9 100644
--- a/lib/ssl/test/ssl_npn_hello_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_hello_SUITE.erl
@@ -41,6 +41,15 @@ all() ->
create_server_hello_with_advertised_protocols_test,
create_server_hello_with_no_advertised_protocols_test].
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 5}),
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index e49d432c21..17237118a0 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -41,7 +41,7 @@
-define(MANY, 1000).
-define(SOME, 50).
--define(BASE_TIMEOUT_SECONDS, 15).
+-define(BASE_TIMEOUT_SECONDS, 30).
-define(SOME_SCALE, 20).
-define(MANY_SCALE, 20).
@@ -140,6 +140,7 @@ init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
+ ssl:stop(),
ssl:start(),
{ok, _} = make_certs:all(proplists:get_value(data_dir, Config),
proplists:get_value(priv_dir, Config)),
@@ -162,6 +163,7 @@ init_per_group(GroupName, Config) ->
{skip, "Missing crypto support"}
end;
_ ->
+ ssl:stop(),
ssl:start(),
Config
end.
diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl
index cb0571d0a7..c0b762760d 100644
--- a/lib/ssl/test/ssl_payload_SUITE.erl
+++ b/lib/ssl/test/ssl_payload_SUITE.erl
@@ -104,8 +104,13 @@ init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_huge;
TestCase == client_echos_passive_huge;
TestCase == client_echos_active_once_huge;
TestCase == client_echos_active_huge ->
- ct:timetrap({seconds, 90}),
- Config;
+ case erlang:system_info(system_architecture) of
+ "sparc-sun-solaris2.10" ->
+ {skip,"Will take to long time on an old Sparc"};
+ _ ->
+ ct:timetrap({seconds, 90}),
+ Config
+ end;
init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_big;
TestCase == server_echos_active_once_big;
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index b3109b5de9..83a4dae0a1 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -116,6 +116,7 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
+ ssl:stop(),
ssl:start(),
{ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
proplists:get_value(priv_dir, Config0)),
@@ -1264,7 +1265,7 @@ client_check_result(Port, DataExpected, DataReceived) ->
_ ->
client_check_result(Port, DataExpected, NewData)
end
- after 3000 ->
+ after 20000 ->
ct:fail({"Time out on openSSL Client", {expected, DataExpected},
{got, DataReceived}})
end.