diff options
Diffstat (limited to 'lib/ssl')
-rw-r--r-- | lib/ssl/doc/src/new_ssl.xml | 22 | ||||
-rw-r--r-- | lib/ssl/src/ssl.erl | 3 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 3 | ||||
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 141 | ||||
-rw-r--r-- | lib/ssl/test/ssl_test_lib.erl | 14 | ||||
-rw-r--r-- | lib/ssl/test/ssl_to_openssl_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/ssl/vsn.mk | 7 |
7 files changed, 168 insertions, 24 deletions
diff --git a/lib/ssl/doc/src/new_ssl.xml b/lib/ssl/doc/src/new_ssl.xml index b642280096..a83c2d1383 100644 --- a/lib/ssl/doc/src/new_ssl.xml +++ b/lib/ssl/doc/src/new_ssl.xml @@ -84,8 +84,6 @@ <item>New API functions are ssl:shutdown/2, ssl:cipher_suites/[0,1] and ssl:versions/0</item> - <item>Diffie-Hellman keyexchange is - not supported yet.</item> <item>CRL and policy certificate extensions are not supported yet. </item> <item>Supported SSL/TLS-versions are SSL-3.0 and TLS-1.0 </item> @@ -118,8 +116,8 @@ {fail_if_no_peer_cert, boolean()} {depth, integer()} | {certfile, path()} | {keyfile, path()} | {password, string()} | - {cacertfile, path()} | {ciphers, ciphers()} | {ssl_imp, ssl_imp()} - | {reuse_sessions, boolean()} | {reuse_session, fun()} + {cacertfile, path()} | {dhfile, path()} | {ciphers, ciphers()} | + {ssl_imp, ssl_imp()} | {reuse_sessions, boolean()} | {reuse_session, fun()} </c></p> <p><c>transportoption() = {CallbackModule, DataTag, ClosedTag} @@ -262,6 +260,12 @@ end CA certificates (trusted certificates used for verifying a peer certificate). May be omitted if you do not want to verify the peer.</item> + + <tag>{dhfile, path()}</tag> + <item>Path to file containing PEM encoded Diffie Hellman parameters, + for the server to use if a cipher suite using Diffie Hellman key exchange + is negotiated. If not specified hardcode parameters will be used. + </item> <tag>{ciphers, ciphers()}</tag> <item>The function <c>ciphers_suites/0</c> can @@ -491,6 +495,16 @@ end </func> <func> + <name>renegotiate(Socket) -> ok</name> + <fsummary> Initiates a new handshake.</fsummary> + <type> + <v>Socket = sslsocket()</v> + </type> + <desc><p>Initiates a new handshake.</p> + </desc> + </func> + + <func> <name>send(Socket, Data) -> ok | {error, Reason}</name> <fsummary>Write data to a socket.</fsummary> <type> diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 87a0939897..965e40a109 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -560,10 +560,11 @@ handle_options(Opts0, Role) -> CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed}), SslOptions = [versions, verify, verify_fun, + fail_if_no_peer_cert, verify_client_once, depth, certfile, keyfile, key, password, cacertfile, dhfile, ciphers, debug, reuse_session, reuse_sessions, ssl_imp, - cd_info, renegotiate_at], + cb_info, renegotiate_at], SockOpts = lists:foldl(fun(Key, PropList) -> proplists:delete(Key, PropList) diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 4ec90600e9..dcf3331e6b 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -441,7 +441,8 @@ certify(#certificate{} = Cert, Opts#ssl_options.verify, Opts#ssl_options.verify_fun) of {PeerCert, PublicKeyInfo} -> - handle_peer_cert(PeerCert, PublicKeyInfo, State); + handle_peer_cert(PeerCert, PublicKeyInfo, + State#state{client_certificate_requested = false}); #alert{} = Alert -> handle_own_alert(Alert, Version, certify_certificate, State), {stop, normal, State} diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 8dc987e3ff..d1ee2ed77f 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -151,7 +151,7 @@ all(doc) -> all(suite) -> [app, connection_info, controlling_process, controller_dies, peercert, connect_dist, - peername, sockname, socket_options, versions, cipher_suites, + peername, sockname, socket_options, valid_ssl_options, versions, cipher_suites, upgrade, upgrade_with_timeout, tcp_connect, ipv6, ekeyfile, ecertfile, ecacertfile, eoptions, shutdown, shutdown_write, shutdown_both, shutdown_error, ciphers, @@ -159,8 +159,9 @@ all(suite) -> server_verify_peer_passive, server_verify_peer_active, server_verify_peer_active_once, server_verify_none_passive, server_verify_none_active, - server_verify_none_active_once, - server_verify_no_cacerts, client_verify_none_passive, + server_verify_none_active_once, server_verify_no_cacerts, + server_require_peer_cert_ok, server_require_peer_cert_fail, + client_verify_none_passive, client_verify_none_active, client_verify_none_active_once %%, session_cache_process_list, session_cache_process_mnesia ,reuse_session, reuse_session_expired, server_does_not_want_to_reuse_session, @@ -605,6 +606,59 @@ socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) -> ok. %%-------------------------------------------------------------------- +valid_ssl_options(doc) -> + ["Test what happens when we give valid options"]; + +valid_ssl_options(suite) -> + []; + +valid_ssl_options(Config) when is_list(Config) -> + ClientOpts = [{reuseaddr, true} | ?config(client_opts, Config)], + ServerOpts = [{reuseaddr, true} | ?config(server_opts, Config)], + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Port = ssl_test_lib:inet_port(ServerNode), + + StartOk = + fun(Peer, Pid, TestOpt) -> + receive + {Pid, ok} when Peer =:= server -> + ok; + {Pid, {ok, _}} when Peer =:= client -> + ok; + {Pid, Error} -> + test_server:fail({Peer, + {option_being_tested, TestOpt}, + {got, Error}}) + end + end, + + %% The following contains both documented and undocumented options as + %% listed in ssl:handle_options/2. It excludes file options which are + %% tested elsewhere (cacertfile, certfile, keyfile). + TestOpts = [{versions, []}, {verify, verify_none}, {verify_fun, fun(_) -> false end}, + {fail_if_no_peer_cert, false}, {verify_client_once, false}, + {depth, 1}, {key, undefined}, {password, "secret"}, {ciphers, []}, + {reuse_sessions, true}, {reuse_session, fun(_,_,_,_) -> true end}, + {renegotiate_at, 1000000000}, {debug, []}, + {cb_info, {gen_tcp, tcp, tcp_closed}}], + [begin + Server = + ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, + {from, self()}, + {options, [TestOpt | ServerOpts]}]), + Client = + ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, {from, self()}, + {options, [TestOpt | ClientOpts]}]), + StartOk(server, Server, TestOpt), + StartOk(client, Client, TestOpt), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + ok + end || TestOpt <- TestOpts], + ok. + +%%-------------------------------------------------------------------- versions(doc) -> ["Test API function versions/0"]; @@ -806,7 +860,7 @@ tcp_connect(Config) when is_list(Config) -> Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0}, {from, self()}, {timeout, 5000}, - {mfa, {?MODULE, should_close, []}}, + {mfa, {?MODULE, dummy, []}}, {tcp_options, TcpOpts}, {ssl_options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), @@ -815,18 +869,20 @@ tcp_connect(Config) when is_list(Config) -> test_server:format("Testcase ~p connected to Server ~p ~n", [self(), Server]), gen_tcp:send(Socket, "<SOME GARBLED NON SSL MESSAGE>"), - ssl_test_lib:check_result(Server, {error,esslerrssl}, tcp_closed, Socket), - + receive + {tcp_closed, Socket} -> + receive + {Server, {error, Error}} -> + test_server:format("Error ~p", [Error]) + end + end, ssl_test_lib:close(Server). -should_close(Socket) -> - receive - {ssl, Socket, closed} -> - server_closed; - Other -> - exit({?LINE, Other}) - end. +dummy(Socket) -> + %% Should not happen as the ssl connection will not be established + %% due to fatal handshake failiure + exit(kill). %%-------------------------------------------------------------------- ipv6(doc) -> @@ -1779,7 +1835,66 @@ server_verify_no_cacerts(Config) when is_list(Config) -> | ServerOpts]}]), ssl_test_lib:check_result(Server, {error, {eoptions, {cacertfile, ""}}}). + +%%-------------------------------------------------------------------- + +server_require_peer_cert_ok(doc) -> + ["Test server option fail_if_no_peer_cert when peer sends cert"]; + +server_require_peer_cert_ok(suite) -> + []; + +server_require_peer_cert_ok(Config) when is_list(Config) -> + ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} + | ?config(server_verification_opts, Config)], + ClientOpts = ?config(client_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{active, false} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{active, false} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- + +server_require_peer_cert_fail(doc) -> + ["Test server option fail_if_no_peer_cert when peer doesn't send cert"]; + +server_require_peer_cert_fail(suite) -> + []; + +server_require_peer_cert_fail(Config) when is_list(Config) -> + ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} + | ?config(server_verification_opts, Config)], + BadClientOpts = ?config(client_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Port = ssl_test_lib:inet_port(ServerNode), + + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{active, false} | ServerOpts]}]), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, send_recv_result, []}}, + {options, [{active, false} | BadClientOpts]}]), + ssl_test_lib:check_result(Server, {error, esslaccept}, + Client, {error, esslconnect}), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + %%-------------------------------------------------------------------- client_verify_none_passive(doc) -> diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index f985058cd7..ee799c50c8 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -448,9 +448,19 @@ trigger_renegotiate(Socket, _, 0, Id) -> test_server:sleep(1000), case ssl:session_info(Socket) of [{session_id, Id} | _ ] -> + %% If a warning alert is received + %% from openssl this may not be + %% an error! fail_session_not_renegotiated; - _ -> - ok + %% Tests that uses this function will no reuse + %% sessions so if we get a new session id the + %% renegotiation has seceded. + [{session_id, _} | _ ] -> + ok; + {error, closed} -> + fail_session_fatal_alert_during_renegotiation; + {error, timeout} -> + fail_timeout end; trigger_renegotiate(Socket, ErlData, N, Id) -> diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index adb5b9cd13..624404b556 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -327,7 +327,7 @@ erlang_client_openssl_server_no_wrap_sequence_number(Config) when is_list(Config {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), - ErlData = "From erlang to openssl", + ErlData = "From erlang to openssl\n", N = 10, Port = ssl_test_lib:inet_port(node()), diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index bf67fcd257..0f3f8e95ec 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -17,8 +17,11 @@ # %CopyrightEnd% # -SSL_VSN = 3.10.9 -TICKETS = OTP-8510 +SSL_VSN = 3.11 + +TICKETS = OTP-8517 OTP-7046 OTP-8557 + +#TICKETS_3.10.9 = OTP-8510 #TICKETS_3.10.8 = OTP-8372 OTP-8441 OTP-8459 #TICKETS_3.10.7 = OTP-8260 OTP-8218 OTP-8250 |