diff options
Diffstat (limited to 'lib/ssl')
-rw-r--r-- | lib/ssl/doc/src/notes.xml | 23 | ||||
-rw-r--r-- | lib/ssl/src/ssl_cipher.erl | 4 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 2 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 2 | ||||
-rw-r--r-- | lib/ssl/src/ssl_manager.erl | 8 | ||||
-rw-r--r-- | lib/ssl/src/ssl_pem_cache.erl | 12 | ||||
-rw-r--r-- | lib/ssl/src/ssl_pkix_db.erl | 17 | ||||
-rw-r--r-- | lib/ssl/src/tls_handshake.erl | 3 | ||||
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 30 | ||||
-rw-r--r-- | lib/ssl/test/ssl_handshake_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/ssl/test/ssl_pem_cache_SUITE.erl | 45 | ||||
-rw-r--r-- | lib/ssl/test/ssl_test_lib.erl | 5 |
12 files changed, 129 insertions, 24 deletions
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 62ec9d0190..10c2bd933f 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -170,6 +170,29 @@ </section> +<section><title>SSL 8.2.6.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Correct handling of empty server SNI extension</p> + <p> + Own Id: OTP-15168</p> + </item> + <item> + <p> + Correct cipher suite handling for ECDHE_*, the incorrect + handling could cause an incorrrect suite to be selected + and most likly fail the handshake.</p> + <p> + Own Id: OTP-15203</p> + </item> + </list> + </section> + +</section> + <section><title>SSL 8.2.6.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl index 50dadd0903..1aeb415bd9 100644 --- a/lib/ssl/src/ssl_cipher.erl +++ b/lib/ssl/src/ssl_cipher.erl @@ -2777,6 +2777,8 @@ ecdsa_signed_suites(Ciphers, Version) -> rsa_keyed(dhe_rsa) -> true; +rsa_keyed(ecdhe_rsa) -> + true; rsa_keyed(rsa) -> true; rsa_keyed(rsa_psk) -> @@ -2840,6 +2842,8 @@ ec_keyed(ecdh_ecdsa) -> true; ec_keyed(ecdh_rsa) -> true; +ec_keyed(ecdhe_ecdsa) -> + true; ec_keyed(_) -> false. diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 064350e6de..4b3a6cde01 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -634,6 +634,8 @@ init(_Type, _Event, _State, _Connection) -> tls_connection | dtls_connection) -> gen_statem:state_function_result(). %%-------------------------------------------------------------------- +error({call, From}, {close, _}, State, _Connection) -> + stop_and_reply(normal, {reply, From, ok}, State); error({call, From}, _Msg, State, _Connection) -> {next_state, ?FUNCTION_NAME, State, [{reply, From, {error, closed}}]}. diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 4d0bdd6386..5e4e50f0e1 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -1931,7 +1931,7 @@ dec_hello_extensions(<<?UINT16(?EC_POINT_FORMATS_EXT), ?UINT16(Len), ECPointFormats}}); dec_hello_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len), Rest/binary>>, Acc) when Len == 0 -> - dec_hello_extensions(Rest, Acc#hello_extensions{sni = ""}); %% Server may send an empy SNI + dec_hello_extensions(Rest, Acc#hello_extensions{sni = #sni{hostname = ""}}); %% Server may send an empy SNI dec_hello_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len), ExtData:Len/binary, Rest/binary>>, Acc) -> diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index f44fe6a2bf..52aa164420 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -127,7 +127,13 @@ cache_pem_file(File, DbHandle) -> [Content] -> {ok, Content}; undefined -> - ssl_pem_cache:insert(File) + case ssl_pkix_db:decode_pem_file(File) of + {ok, Content} -> + ssl_pem_cache:insert(File, Content), + {ok, Content}; + Error -> + Error + end end. %%-------------------------------------------------------------------- diff --git a/lib/ssl/src/ssl_pem_cache.erl b/lib/ssl/src/ssl_pem_cache.erl index 115ab4451d..a952e20133 100644 --- a/lib/ssl/src/ssl_pem_cache.erl +++ b/lib/ssl/src/ssl_pem_cache.erl @@ -29,7 +29,7 @@ -export([start_link/1, start_link_dist/1, name/1, - insert/1, + insert/2, clear/0]). % Spawn export @@ -90,19 +90,17 @@ start_link_dist(_) -> %%-------------------------------------------------------------------- --spec insert(binary()) -> {ok, term()} | {error, reason()}. +-spec insert(binary(), term()) -> ok | {error, reason()}. %% %% Description: Cache a pem file and return its content. %%-------------------------------------------------------------------- -insert(File) -> - {ok, PemBin} = file:read_file(File), - Content = public_key:pem_decode(PemBin), +insert(File, Content) -> case bypass_cache() of true -> - {ok, Content}; + ok; false -> cast({cache_pem, File, Content}), - {ok, Content} + ok end. %%-------------------------------------------------------------------- diff --git a/lib/ssl/src/ssl_pkix_db.erl b/lib/ssl/src/ssl_pkix_db.erl index 8828c3a0d8..b6fae36ff9 100644 --- a/lib/ssl/src/ssl_pkix_db.erl +++ b/lib/ssl/src/ssl_pkix_db.erl @@ -157,7 +157,7 @@ extract_trusted_certs(File) -> {error, {badmatch, Error}} end. --spec decode_pem_file(binary()) -> {ok, term()}. +-spec decode_pem_file(binary()) -> {ok, term()} | {error, term()}. decode_pem_file(File) -> case file:read_file(File) of {ok, PemBin} -> @@ -316,11 +316,16 @@ decode_certs(Ref, Cert) -> end. new_trusted_cert_entry(File, [CertsDb, RefsDb, _ | _]) -> - Ref = make_ref(), - init_ref_db(Ref, File, RefsDb), - {ok, Content} = ssl_pem_cache:insert(File), - add_certs_from_pem(Content, Ref, CertsDb), - {ok, Ref}. + case decode_pem_file(File) of + {ok, Content} -> + Ref = make_ref(), + init_ref_db(Ref, File, RefsDb), + ok = ssl_pem_cache:insert(File, Content), + add_certs_from_pem(Content, Ref, CertsDb), + {ok, Ref}; + Error -> + Error + end. add_crls([_,_,_, {_, Mapping} | _], ?NO_DIST_POINT, CRLs) -> [add_crls(CRL, Mapping) || CRL <- CRLs]; diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl index f1eecb2875..7f5c2e07f6 100644 --- a/lib/ssl/src/tls_handshake.erl +++ b/lib/ssl/src/tls_handshake.erl @@ -126,6 +126,9 @@ hello(#client_hello{client_version = ClientVersion, handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation) end catch + error:{case_clause,{asn1, Asn1Reason}} -> + %% ASN-1 decode of certificate somehow failed + ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {failed_to_decode_own_certificate, Asn1Reason}); _:_ -> ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data) end. diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 0381d0d87d..013786d863 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -243,7 +243,8 @@ error_handling_tests()-> recv_active, recv_active_once, recv_error_handling, - call_in_error_state + call_in_error_state, + close_in_error_state ]. error_handling_tests_tls()-> @@ -4036,6 +4037,33 @@ run_error_server([ Pid | Opts]) -> %%-------------------------------------------------------------------- +close_in_error_state() -> + [{doc,"Special case of closing socket in error state"}]. +close_in_error_state(Config) when is_list(Config) -> + ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config), + ServerOpts = [{cacertfile, "foo.pem"} | proplists:delete(cacertfile, ServerOpts0)], + ClientOpts = ssl_test_lib:ssl_options(client_opts, Config), + _ = spawn_link(?MODULE, run_error_server_close, [[self() | ServerOpts]]), + receive + {_Pid, Port} -> + spawn_link(?MODULE, run_client_error, [[Port, ClientOpts]]) + end, + receive + ok -> + ok; + Other -> + ct:fail(Other) + end. + +run_error_server_close([Pid | Opts]) -> + {ok, Listen} = ssl:listen(0, Opts), + {ok,{_, Port}} = ssl:sockname(Listen), + Pid ! {self(), Port}, + {ok, Socket} = ssl:transport_accept(Listen), + Pid ! ssl:close(Socket). + +%%-------------------------------------------------------------------- + rizzo() -> [{doc, "Test that there is a 1/n-1-split for non RC4 in 'TLS < 1.1' as it is vunrable to Rizzo/Dungon attack"}]. diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl index 2c7c62407e..9ae04184e2 100644 --- a/lib/ssl/test/ssl_handshake_SUITE.erl +++ b/lib/ssl/test/ssl_handshake_SUITE.erl @@ -149,7 +149,7 @@ decode_single_hello_sni_extension_correctly(_Config) -> Exts = Decoded. decode_empty_server_sni_correctly(_Config) -> - Exts = #hello_extensions{sni = ""}, + Exts = #hello_extensions{sni = #sni{hostname = ""}}, SNI = <<?UINT16(?SNI_EXT),?UINT16(0)>>, Decoded = ssl_handshake:decode_hello_extensions(SNI), Exts = Decoded. diff --git a/lib/ssl/test/ssl_pem_cache_SUITE.erl b/lib/ssl/test/ssl_pem_cache_SUITE.erl index 96b15d9b51..3b79780974 100644 --- a/lib/ssl/test/ssl_pem_cache_SUITE.erl +++ b/lib/ssl/test/ssl_pem_cache_SUITE.erl @@ -34,7 +34,7 @@ %% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- all() -> - [pem_cleanup]. + [pem_cleanup, invalid_insert]. groups() -> []. @@ -68,6 +68,10 @@ init_per_testcase(pem_cleanup = Case, Config) -> application:set_env(ssl, ssl_pem_cache_clean, ?CLEANUP_INTERVAL), ssl:start(), ct:timetrap({minutes, 1}), + Config; +init_per_testcase(_, Config) -> + ssl:start(), + ct:timetrap({seconds, 5}), Config. end_per_testcase(_TestCase, Config) -> @@ -108,7 +112,34 @@ pem_cleanup(Config)when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client), false = Size == Size1. - + +invalid_insert() -> + [{doc, "Test that insert of invalid pem does not cause empty cache entry"}]. +invalid_insert(Config)when is_list(Config) -> + process_flag(trap_exit, true), + + ClientOpts = proplists:get_value(client_verification_opts, Config), + ServerOpts = proplists:get_value(server_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + BadClientOpts = [{cacertfile, "tmp/does_not_exist.pem"} | proplists:delete(cacertfile, ClientOpts)], + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, no_result, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + ssl_test_lib:start_client_error([{node, ClientNode}, + {port, Port}, {host, Hostname}, + {from, self()}, {options, BadClientOpts}]), + ssl_test_lib:close(Server), + 1 = ssl_pkix_db:db_size(get_fileref_db()). + + + +%%-------------------------------------------------------------------- +%% Internal funcations +%%-------------------------------------------------------------------- + get_pem_cache() -> {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), [_, _,_, _, Prop] = StatusInfo, @@ -120,6 +151,16 @@ get_pem_cache() -> undefined end. +get_fileref_db() -> + {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), + [_, _,_, _, Prop] = StatusInfo, + State = ssl_test_lib:state(Prop), + case element(6, State) of + [_CertDb, {FileRefDb,_} | _] -> + FileRefDb; + _ -> + undefined + end. later()-> DateTime = calendar:now_to_local_time(os:timestamp()), Gregorian = calendar:datetime_to_gregorian_seconds(DateTime), diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 91a9c774a6..7202e3662c 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -1524,11 +1524,6 @@ v_1_2_check(ecdh_ecdsa, ecdh_rsa) -> true; v_1_2_check(ecdh_rsa, ecdh_ecdsa) -> true; -v_1_2_check(ecdhe_ecdsa, ecdhe_rsa) -> - true; -v_1_2_check(ecdhe_rsa, ecdhe_ecdsa) -> - true; - v_1_2_check(_, _) -> false. |