diff options
Diffstat (limited to 'lib/ssl/test')
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 936 | ||||
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE_data/dHParam.pem | 5 | ||||
-rw-r--r-- | lib/ssl/test/ssl_packet_SUITE.erl | 174 | ||||
-rw-r--r-- | lib/ssl/test/ssl_test_lib.erl | 172 | ||||
-rw-r--r-- | lib/ssl/test/ssl_to_openssl_SUITE.erl | 362 |
5 files changed, 1316 insertions, 333 deletions
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 3d9cec43dd..7f33efd7e1 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -26,10 +26,13 @@ -include("test_server.hrl"). -include("test_server_line.hrl"). +-include_lib("public_key/include/public_key.hrl"). -define('24H_in_sec', 86400). -define(TIMEOUT, 60000). -define(EXPIRE, 10). +-define(SLEEP, 500). + -behaviour(ssl_session_cache_api). @@ -150,19 +153,26 @@ 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, misc_ssl_options, versions, cipher_suites, upgrade, upgrade_with_timeout, tcp_connect, ipv6, ekeyfile, ecertfile, ecacertfile, eoptions, shutdown, shutdown_write, shutdown_both, shutdown_error, ciphers, - send_close, + send_close, close_transport_accept, dh_params, 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, + server_verify_client_once_passive, + server_verify_client_once_active, + server_verify_client_once_active_once, + 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 + ,reuse_session, reuse_session_expired, server_does_not_want_to_reuse_session, + client_renegotiate, server_renegotiate, + client_no_wrap_sequence_number, server_no_wrap_sequence_number, + extended_key_usage, validate_extensions_fun ]. %% Test cases starts here. @@ -236,7 +246,7 @@ controlling_process(Config) when is_list(Config) -> Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {?MODULE, controlling_process_result, [self(), ClientMsg]}}, @@ -267,7 +277,7 @@ controlling_process_result(Socket, Pid, Msg) -> ok = ssl:controlling_process(Socket, Pid), %% Make sure other side has evaluated controlling_process %% before message is sent - test_server:sleep(100), + test_server:sleep(?SLEEP), ssl:send(Socket, Msg), no_result_msg. @@ -298,7 +308,7 @@ controller_dies(Config) when is_list(Config) -> {options, ClientOpts}]), test_server:format("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), - timer:sleep(200), %% so that they are connected + test_server:sleep(?SLEEP), %% so that they are connected process_flag(trap_exit, true), @@ -307,7 +317,7 @@ controller_dies(Config) when is_list(Config) -> get_close(Client, ?LINE), %% Test that clients die when process disappear - Server ! listen, timer:sleep(200), + Server ! listen, Tester = self(), Connect = fun(Pid) -> {ok, Socket} = ssl:connect(Hostname, Port, @@ -321,7 +331,7 @@ controller_dies(Config) when is_list(Config) -> get_close(Client2, ?LINE), %% Test that clients die when the controlling process have changed - Server ! listen, timer:sleep(200), + Server ! listen, Client3 = spawn_link(fun() -> Connect(Tester) end), Controller = spawn_link(fun() -> receive die_nice -> normal end end), @@ -345,7 +355,7 @@ controller_dies(Config) when is_list(Config) -> get_close(Controller, ?LINE), %% Test that servers die - Server ! listen, timer:sleep(200), + Server ! listen, LastClient = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, @@ -353,7 +363,7 @@ controller_dies(Config) when is_list(Config) -> controller_dies_result, [self(), ClientMsg]}}, {options, [{reuseaddr,true}|ClientOpts]}]), - timer:sleep(200), %% so that they are connected + test_server:sleep(?SLEEP), %% so that they are connected exit(Server, killed), get_close(Server, ?LINE), @@ -484,9 +494,9 @@ peername(Config) when is_list(Config) -> Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, peername_result, []}}, - {options, [{port, 0} | ClientOpts]}]), + {from, self()}, + {mfa, {?MODULE, peername_result, []}}, + {options, [{port, 0} | ClientOpts]}]), ClientPort = ssl_test_lib:inet_port(Client), ServerIp = ssl_test_lib:node_to_hostip(ServerNode), @@ -526,6 +536,7 @@ sockname(Config) when is_list(Config) -> {from, self()}, {mfa, {?MODULE, sockname_result, []}}, {options, [{port, 0} | ClientOpts]}]), + ClientPort = ssl_test_lib:inet_port(Client), ServerIp = ssl_test_lib:node_to_hostip(ServerNode), ClientIp = ssl_test_lib:node_to_hostip(ClientNode), @@ -602,6 +613,46 @@ socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) -> ok. %%-------------------------------------------------------------------- +misc_ssl_options(doc) -> + ["Test what happens when we give valid options"]; + +misc_ssl_options(suite) -> + []; + +misc_ssl_options(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + %% Chek that ssl options not tested elsewhere are filtered away e.i. not passed to inet. + TestOpts = [{depth, 1}, + {key, undefined}, + {password, []}, + {reuse_session, fun(_,_,_,_) -> true end}, + {debug, []}, + {cb_info, {gen_tcp, tcp, tcp_closed}}], + + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, send_recv_result_active, []}}, + {options, TestOpts ++ 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_active, []}}, + {options, TestOpts ++ ClientOpts}]), + + test_server:format("Testcase ~p, Client ~p Server ~p ~n", + [self(), Client, Server]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- versions(doc) -> ["Test API function versions/0"]; @@ -667,13 +718,71 @@ send_close(Config) when is_list(Config) -> test_server:format("Testcase ~p, Client ~p Server ~p ~n", [self(), self(), Server]), - ok = ssl:send(SslS, "HejHopp"), - {ok,<<"Hejhopp">>} = ssl:recv(SslS, 7), + ok = ssl:send(SslS, "Hello world"), + {ok,<<"Hello world">>} = ssl:recv(SslS, 11), gen_tcp:close(TcpS), - {error, _} = ssl:send(SslS, "HejHopp"), + {error, _} = ssl:send(SslS, "Hello world"), ssl_test_lib:close(Server). %%-------------------------------------------------------------------- +close_transport_accept(doc) -> + ["Tests closing ssl socket when waiting on ssl:transport_accept/1"]; + +close_transport_accept(suite) -> + []; + +close_transport_accept(Config) when is_list(Config) -> + ServerOpts = ?config(server_opts, Config), + {_ClientNode, ServerNode, _Hostname} = ssl_test_lib:run_where(Config), + + Port = 0, + Opts = [{active, false} | ServerOpts], + {ok, ListenSocket} = rpc:call(ServerNode, ssl, listen, [Port, Opts]), + spawn_link(fun() -> + test_server:sleep(?SLEEP), + rpc:call(ServerNode, ssl, close, [ListenSocket]) + end), + case rpc:call(ServerNode, ssl, transport_accept, [ListenSocket]) of + {error, closed} -> + ok; + Other -> + exit({?LINE, Other}) + end. + +%%-------------------------------------------------------------------- +dh_params(doc) -> + ["Test to specify DH-params file in server."]; + +dh_params(suite) -> + []; + +dh_params(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + DataDir = ?config(data_dir, Config), + DHParamFile = filename:join(DataDir, "dHParam.pem"), + + {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_active, []}}, + {options, [{dhfile, DHParamFile} | 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_active, []}}, + {options, + [{ciphers,[{dhe_rsa,aes_256_cbc,sha,ignore}]} | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- upgrade(doc) -> ["Test that you can upgrade an tcp connection to an ssl connection"]; @@ -710,11 +819,11 @@ upgrade(Config) when is_list(Config) -> ssl_test_lib:close(Client). upgrade_result(Socket) -> - ok = ssl:send(Socket, "Hejhopp"), + ok = ssl:send(Socket, "Hello world"), %% Make sure binary is inherited from tcp socket and that we do %% not get the list default! receive - {ssl, _, <<"Hejhopp">>} -> + {ssl, _, <<"Hello world">>} -> ok end. @@ -763,15 +872,14 @@ tcp_connect(suite) -> []; tcp_connect(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), TcpOpts = [binary, {reuseaddr, true}], 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), @@ -780,18 +888,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) -> @@ -843,12 +953,14 @@ ekeyfile(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), BadOpts = ?config(server_bad_key, 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}, + ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, {from, self()}, {options, BadOpts}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, {host, Hostname}, @@ -869,19 +981,21 @@ ecertfile(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerBadOpts = ?config(server_bad_cert, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Port = ssl_test_lib:inet_port(ServerNode), - Server0 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, + Server = + ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, {from, self()}, {options, ServerBadOpts}]), - Client0 = + + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, {options, ClientOpts}]), - ssl_test_lib:check_result(Server0, {error, ecertfile}, Client0, + ssl_test_lib:check_result(Server, {error, ecertfile}, Client, {error, closed}). @@ -896,15 +1010,18 @@ ecacertfile(Config) when is_list(Config) -> ClientOpts = [{reuseaddr, true}|?config(client_opts, Config)], ServerBadOpts = [{reuseaddr, true}|?config(server_bad_ca, Config)], {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Port = ssl_test_lib:inet_port(ServerNode), Server0 = ssl_test_lib:start_server_error([{node, ServerNode}, - {port, Port}, {from, self()}, + {port, 0}, {from, self()}, {options, ServerBadOpts}]), + + Port0 = ssl_test_lib:inet_port(Server0), + + Client0 = ssl_test_lib:start_client_error([{node, ClientNode}, - {port, Port}, {host, Hostname}, + {port, Port0}, {host, Hostname}, {from, self()}, {options, ClientOpts}]), @@ -917,11 +1034,14 @@ ecacertfile(Config) when is_list(Config) -> Server1 = ssl_test_lib:start_server_error([{node, ServerNode}, - {port, Port}, {from, self()}, + {port, 0}, {from, self()}, {options, ServerBadOpts1}]), + + Port1 = ssl_test_lib:inet_port(Server1), + Client1 = ssl_test_lib:start_client_error([{node, ClientNode}, - {port, Port}, {host, Hostname}, + {port, Port1}, {host, Hostname}, {from, self()}, {options, ClientOpts}]), @@ -942,198 +1062,58 @@ eoptions(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Port = ssl_test_lib:inet_port(ServerNode), - - %% Emulated opts - Server0 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{active, trice} | ServerOpts]}]), - Client0 = - ssl_test_lib:start_client_error([{node, ClientNode}, - {port, Port}, {host, Hostname}, - {from, self()}, - {options, [{active, trice} | ClientOpts]}]), - ssl_test_lib:check_result(Server0, {error, {eoptions, {active,trice}}}, - Client0, {error, {eoptions, {active,trice}}}), - - test_server:sleep(500), - - Server1 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{header, a} | ServerOpts]}]), - Client1 = - ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{header, a} | ClientOpts]}]), - ssl_test_lib:check_result(Server1, {error, {eoptions, {header, a}}}, - Client1, {error, {eoptions, {header, a}}}), - - test_server:sleep(500), - - - Server2 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{mode, a} | ServerOpts]}]), - - Client2 = - ssl_test_lib:start_client_error([{node, ClientNode}, - {port, Port}, {host, Hostname}, - {from, self()}, - {options, [{mode, a} | ClientOpts]}]), - ssl_test_lib:check_result(Server2, {error, {eoptions, {mode, a}}}, - Client2, {error, {eoptions, {mode, a}}}), - - - test_server:sleep(500), - - Server3 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{packet, 8.0} | ServerOpts]}]), - Client3 = - ssl_test_lib:start_client_error([{node, ClientNode}, - {port, Port}, {host, Hostname}, - {from, self()}, - {options, [{packet, 8.0} | ClientOpts]}]), - ssl_test_lib:check_result(Server3, {error, {eoptions, {packet, 8.0}}}, - Client3, {error, {eoptions, {packet, 8.0}}}), - - test_server:sleep(500), - - %% ssl - Server4 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{verify, 4} | ServerOpts]}]), - Client4 = - ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{verify, 4} | ClientOpts]}]), - ssl_test_lib:check_result(Server4, {error, {eoptions, {verify, 4}}}, - Client4, {error, {eoptions, {verify, 4}}}), - - test_server:sleep(500), - - Server5 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{depth, four} | ServerOpts]}]), - Client5 = - ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{depth, four} | ClientOpts]}]), - ssl_test_lib:check_result(Server5, {error, {eoptions, {depth, four}}}, - Client5, {error, {eoptions, {depth, four}}}), - - test_server:sleep(500), - - Server6 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{cacertfile, ""} | ServerOpts]}]), - Client6 = - ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{cacertfile, ""} | ClientOpts]}]), - ssl_test_lib:check_result(Server6, {error, {eoptions, {cacertfile, ""}}}, - Client6, {error, {eoptions, {cacertfile, ""}}}), - - - test_server:sleep(500), - - Server7 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{certfile, 'cert.pem'} | ServerOpts]}]), - Client7 = - ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{certfile, 'cert.pem'} | ClientOpts]}]), - ssl_test_lib:check_result(Server7, - {error, {eoptions, {certfile, 'cert.pem'}}}, - Client7, {error, {eoptions, {certfile, 'cert.pem'}}}), - - test_server:sleep(500), - - Server8 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{keyfile,'key.pem' } | ServerOpts]}]), - Client8 = - ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, {options, [{keyfile, 'key.pem'} - | ClientOpts]}]), - ssl_test_lib:check_result(Server8, - {error, {eoptions, {keyfile, 'key.pem'}}}, - Client8, {error, {eoptions, {keyfile, 'key.pem'}}}), - - test_server:sleep(500), - - Server9 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{key, 'key.pem' } | ServerOpts]}]), - Client9 = - ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, {options, [{key, 'key.pem'} - | ClientOpts]}]), - ssl_test_lib:check_result(Server9, {error, {eoptions, {key, 'key.pem'}}}, - Client9, {error, {eoptions, {key, 'key.pem'}}}), + Check = fun(Client, Server, {versions, [sslv2, sslv3]} = Option) -> + ssl_test_lib:check_result(Server, + {error, {eoptions, {sslv2, Option}}}, + Client, + {error, {eoptions, {sslv2, Option}}}); + (Client, Server, Option) -> + ssl_test_lib:check_result(Server, + {error, {eoptions, Option}}, + Client, + {error, {eoptions, Option}}) + end, - test_server:sleep(500), - - Server10 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{password, foo} | ServerOpts]}]), - Client10 = - ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{password, foo} | ClientOpts]}]), - ssl_test_lib:check_result(Server10, {error, {eoptions, {password, foo}}}, - Client10, {error, {eoptions, {password, foo}}}), - - test_server:sleep(500), - - %% Misc - Server11 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{ssl_imp, cool} | ServerOpts]}]), - Client11 = - ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{ssl_imp, cool} | ClientOpts]}]), - ssl_test_lib:check_result(Server11, {error, {eoptions, {ssl_imp, cool}}}, - Client11, {error, {eoptions, {ssl_imp, cool}}}), - - - test_server:sleep(500), - - Server12 = - ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port}, - {from, self()}, - {options, [{debug, cool} | ServerOpts]}]), - Client12 = - ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{debug, cool} | ClientOpts]}]), - ssl_test_lib:check_result(Server12, {error, {eoptions, {debug, cool}}}, - Client12, {error, {eoptions, {debug, cool}}}). + TestOpts = [{versions, [sslv2, sslv3]}, + {ssl_imp, cool}, + {verify, 4}, + {verify_fun, function}, + {fail_if_no_peer_cert, 0}, + {verify_client_once, 1}, + {validate_extensions_fun, function}, + {depth, four}, + {certfile, 'cert.pem'}, + {keyfile,'key.pem' }, + {password, foo}, + {cacertfile, ""}, + {dhfile,'dh.pem' }, + {ciphers, [{foo, bar, sha, ignore}]}, + {reuse_session, foo}, + {reuse_sessions, 0}, + {renegotiate_at, "10"}, + {debug, 1}, + {mode, depech}, + {packet, 8.0}, + {packet_size, "2"}, + {header, a}, + {active, trice}, + {key, 'key.pem' }], + + [begin + Server = + ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {options, [TestOpt | ServerOpts]}]), + %% Will never reach a point where port is used. + Client = + ssl_test_lib:start_client_error([{node, ClientNode}, {port, 0}, + {host, Hostname}, {from, self()}, + {options, [TestOpt | ClientOpts]}]), + Check(Client, Server, TestOpt), + ok + end || TestOpt <- TestOpts], + ok. %%-------------------------------------------------------------------- shutdown(doc) -> @@ -1203,7 +1183,7 @@ shutdown_write(Config) when is_list(Config) -> ssl_test_lib:check_result(Server, ok, Client, {error, closed}). shutdown_write_result(Socket, server) -> - test_server:sleep(500), + test_server:sleep(?SLEEP), ssl:shutdown(Socket, write); shutdown_write_result(Socket, client) -> ssl:recv(Socket, 0). @@ -1233,7 +1213,7 @@ shutdown_both(Config) when is_list(Config) -> ssl_test_lib:check_result(Server, ok, Client, {error, closed}). shutdown_both_result(Socket, server) -> - test_server:sleep(500), + test_server:sleep(?SLEEP), ssl:shutdown(Socket, read_write); shutdown_both_result(Socket, client) -> ssl:recv(Socket, 0). @@ -1339,7 +1319,7 @@ reuse_session(Config) when is_list(Config) -> Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {mfa, {?MODULE, no_result, []}}, + {mfa, {ssl_test_lib, no_result, []}}, {from, self()}, {options, ClientOpts}]), SessionInfo = receive @@ -1350,7 +1330,7 @@ reuse_session(Config) when is_list(Config) -> Server ! listen, %% Make sure session is registered - test_server:sleep(500), + test_server:sleep(?SLEEP), Client1 = ssl_test_lib:start_client([{node, ClientNode}, @@ -1410,7 +1390,7 @@ reuse_session(Config) when is_list(Config) -> Server1 ! listen, %% Make sure session is registered - test_server:sleep(500), + test_server:sleep(?SLEEP), Client4 = ssl_test_lib:start_client([{node, ClientNode}, @@ -1457,7 +1437,7 @@ reuse_session_expired(Config) when is_list(Config) -> Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {mfa, {?MODULE, no_result, []}}, + {mfa, {ssl_test_lib, no_result, []}}, {from, self()}, {options, ClientOpts}]), SessionInfo = receive @@ -1468,7 +1448,7 @@ reuse_session_expired(Config) when is_list(Config) -> Server ! listen, %% Make sure session is registered - test_server:sleep(500), + test_server:sleep(?SLEEP), Client1 = ssl_test_lib:start_client([{node, ClientNode}, @@ -1530,7 +1510,7 @@ server_does_not_want_to_reuse_session(Config) when is_list(Config) -> Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {mfa, {?MODULE, no_result, []}}, + {mfa, {ssl_test_lib, no_result, []}}, {from, self()}, {options, ClientOpts}]), SessionInfo = receive @@ -1541,7 +1521,7 @@ server_does_not_want_to_reuse_session(Config) when is_list(Config) -> Server ! listen, %% Make sure session is registered - test_server:sleep(500), + test_server:sleep(?SLEEP), Client1 = ssl_test_lib:start_client([{node, ClientNode}, @@ -1725,8 +1705,122 @@ server_verify_none_active_once(Config) when is_list(Config) -> ssl_test_lib:check_result(Server, ok, Client, ok), ssl_test_lib:close(Server), ssl_test_lib:close(Client). +%%-------------------------------------------------------------------- + +server_verify_client_once_passive(doc) -> + ["Test server option verify_client_once"]; + +server_verify_client_once_passive(suite) -> + []; + +server_verify_client_once_passive(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_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}, {verify, verify_peer}, + {verify_client_once, true} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client0 = 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, Client0, ok), + ssl_test_lib:close(Client0), + Server ! listen, + Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, result_ok, []}}, + {options, [{active, false} | ClientOpts]}]), + + ssl_test_lib:check_result(Client1, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client1). + +%%-------------------------------------------------------------------- + +server_verify_client_once_active(doc) -> + ["Test server option verify_client_once"]; + +server_verify_client_once_active(suite) -> + []; + +server_verify_client_once_active(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_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_active, []}}, + {options, [{active, once}, {verify, verify_peer}, + {verify_client_once, true} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, send_recv_result_active, []}}, + {options, [{active, true} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client0, ok), + ssl_test_lib:close(Client0), + Server ! listen, + Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, result_ok, []}}, + {options, [{active, true} | ClientOpts]}]), + + ssl_test_lib:check_result(Client1, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client1). + +%%-------------------------------------------------------------------- + +server_verify_client_once_active_once(doc) -> + ["Test server option verify_client_once"]; + +server_verify_client_once_active_once(suite) -> + []; +server_verify_client_once_active_once(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_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_active_once, []}}, + {options, [{active, once}, {verify, verify_peer}, + {verify_client_once, true} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, send_recv_result_active_once, []}}, + {options, [{active, once} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client0, ok), + ssl_test_lib:close(Client0), + Server ! listen, + + Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, result_ok, []}}, + {options, [{active, once} | ClientOpts]}]), + + ssl_test_lib:check_result(Client1, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client1). + %%-------------------------------------------------------------------- server_verify_no_cacerts(doc) -> @@ -1744,7 +1838,68 @@ 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), + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, no_result, []}}, + {options, [{active, false} | ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, no_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) -> @@ -1849,31 +2004,289 @@ client_verify_none_active_once(Config) when is_list(Config) -> ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +client_renegotiate(doc) -> + ["Test ssl:renegotiate/1 on client."]; + +client_renegotiate(suite) -> + []; + +client_renegotiate(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Data = "From erlang to erlang", + + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, + renegotiate, [Data]}}, + {options, [{reuse_sessions, false} | ClientOpts]}]), + + ssl_test_lib:check_result(Client, ok, Server, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + process_flag(trap_exit, false), + ok. +%%-------------------------------------------------------------------- +server_renegotiate(doc) -> + ["Test ssl:renegotiate/1 on server."]; + +server_renegotiate(suite) -> + []; + +server_renegotiate(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Data = "From erlang to erlang", + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, + renegotiate, [Data]}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, + {options, [{reuse_sessions, false} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + ok. + +%%-------------------------------------------------------------------- +client_no_wrap_sequence_number(doc) -> + ["Test that erlang client will renegotiate session when", + "max sequence number celing is about to be reached. Although" + "in the testcase we use the test option renegotiate_at" + " to lower treashold substantially."]; + +client_no_wrap_sequence_number(suite) -> + []; + +client_no_wrap_sequence_number(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + ErlData = "From erlang to erlang", + N = 10, + + 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), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + trigger_renegotiate, [[ErlData, N+2]]}}, + {options, [{reuse_sessions, false}, + {renegotiate_at, N} | ClientOpts]}]), + + ssl_test_lib:check_result(Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + process_flag(trap_exit, false), + ok. +%%-------------------------------------------------------------------- +server_no_wrap_sequence_number(doc) -> + ["Test that erlang server will renegotiate session when", + "max sequence number celing is about to be reached. Although" + "in the testcase we use the test option renegotiate_at" + " to lower treashold substantially."]; + +server_no_wrap_sequence_number(suite) -> + []; + +server_no_wrap_sequence_number(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Data = "From erlang to erlang", + N = 10, + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + trigger_renegotiate, [[Data, N+2]]}}, + {options, [{renegotiate_at, N} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, no_result, []}}, + {options, [{reuse_sessions, false} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + ok. + +%%-------------------------------------------------------------------- +extended_key_usage(doc) -> + ["Test cert that has a critical extended_key_usage extension"]; + +extended_key_usage(suite) -> + []; + +extended_key_usage(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + PrivDir = ?config(priv_dir, Config), + + CertFile = proplists:get_value(certfile, ServerOpts), + KeyFile = proplists:get_value(keyfile, ServerOpts), + NewCertFile = filename:join(PrivDir, "cert.pem"), + + {ok, [{cert, DerCert, _}]} = public_key:pem_to_der(CertFile), + + {ok, [KeyInfo]} = public_key:pem_to_der(KeyFile), + + {ok, Key} = public_key:decode_private_key(KeyInfo), + + {ok, OTPCert} = public_key:pkix_decode_cert(DerCert, otp), + + ExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-serverAuth']}, + + OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate, + + Extensions = OTPTbsCert#'OTPTBSCertificate'.extensions, + + NewOTPTbsCert = OTPTbsCert#'OTPTBSCertificate'{extensions = [ExtKeyUsageExt |Extensions]}, + + NewDerCert = public_key:sign(NewOTPTbsCert, Key), + + public_key:der_to_pem(NewCertFile, [{cert, NewDerCert}]), + + NewServerOpts = [{certfile, NewCertFile} | proplists:delete(certfile, ServerOpts)], + + {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_active, []}}, + {options, NewServerOpts}]), + 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_active, []}}, + {options, ClientOpts}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +validate_extensions_fun(doc) -> + ["Test that it is possible to specify a validate_extensions_fun"]; + +validate_extensions_fun(suite) -> + []; + +validate_extensions_fun(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + + Fun = fun(Extensions, State, _, AccError) -> + {Extensions, State, AccError} + end, + + {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_active, []}}, + {options, [{validate_extensions_fun, Fun}, + {verify, verify_peer} | 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_active, []}}, + {options,[{validate_extensions_fun, Fun} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- send_recv_result(Socket) -> - ssl:send(Socket, "Hejhopp"), - test_server:sleep(100), - {ok,"Hejhopp"} = ssl:recv(Socket, 7), + ssl:send(Socket, "Hello world"), + {ok,"Hello world"} = ssl:recv(Socket, 11), ok. send_recv_result_active(Socket) -> - ssl:send(Socket, "Hejhopp"), - test_server:sleep(100), + ssl:send(Socket, "Hello world"), receive - {ssl, Socket, "Hejhopp"} -> + {ssl, Socket, "Hello world"} -> ok end. send_recv_result_active_once(Socket) -> - ssl:send(Socket, "Hejhopp"), - test_server:sleep(100), + ssl:send(Socket, "Hello world"), receive - {ssl, Socket, "Hejhopp"} -> + {ssl, Socket, "Hello world"} -> ok end. +result_ok(_Socket) -> + ok. + +renegotiate(Socket, Data) -> + test_server:format("Renegotiating ~n", []), + Result = ssl:renegotiate(Socket), + test_server:format("Result ~p~n", [Result]), + ssl:send(Socket, Data), + case Result of + ok -> + ok; + %% It is not an error in erlang ssl + %% if peer rejects renegotiation. + %% Connection will stay up + {error, renegotiation_rejected} -> + ok; + Other -> + Other + end. + session_cache_process_list(doc) -> ["Test reuse of sessions (short handshake)"]; @@ -1909,7 +2322,7 @@ session_cache_process(Type,Config) when is_list(Config) -> Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {mfa, {?MODULE, no_result, []}}, + {mfa, {ssl_test_lib, no_result, []}}, {from, self()}, {options, ClientOpts}]), SessionInfo = receive @@ -1920,7 +2333,7 @@ session_cache_process(Type,Config) when is_list(Config) -> Server ! listen, %% Make sure session is registered - test_server:sleep(500), + test_server:sleep(?SLEEP), Client1 = ssl_test_lib:start_client([{node, ClientNode}, @@ -1963,7 +2376,7 @@ session_cache_process(Type,Config) when is_list(Config) -> Server1 ! listen, %% Make sure session is registered - test_server:sleep(500), + test_server:sleep(?SLEEP), Client4 = ssl_test_lib:start_client([{node, ClientNode}, @@ -2112,3 +2525,14 @@ session_loop(Sess) -> session_loop(Sess) end. +erlang_ssl_receive(Socket, Data) -> + receive + {ssl, Socket, Data} -> + io:format("Received ~p~n",[Data]), + ok; + Other -> + test_server:fail({unexpected_message, Other}) + after ?SLEEP * 3 -> + test_server:fail({did_not_get, Data}) + end. + diff --git a/lib/ssl/test/ssl_basic_SUITE_data/dHParam.pem b/lib/ssl/test/ssl_basic_SUITE_data/dHParam.pem new file mode 100644 index 0000000000..feb581da30 --- /dev/null +++ b/lib/ssl/test/ssl_basic_SUITE_data/dHParam.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAMY5VmCZ22ZEy/KO8kjt94PH7ZtSG0Z0zitlMlvd4VsNkDzXsVeu+wkH +FGDC3h3vgv6iwXGCbmrSOVk/FPZbzLhwZ8aLnkUFOBbOvVvb1JptQwOt8mf+eScG +M2gGBktheQV5Nf1IrzOctG7VGt+neiqb/Y86uYCcDdL+M8++0qnLAgEC +-----END DH PARAMETERS----- diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl index f031552457..1bcb9a657b 100644 --- a/lib/ssl/test/ssl_packet_SUITE.erl +++ b/lib/ssl/test/ssl_packet_SUITE.erl @@ -144,7 +144,9 @@ all(suite) -> packet_wait_passive, packet_wait_active, packet_baddata_passive, packet_baddata_active, packet_size_passive, packet_size_active, - packet_erl_decode + packet_erl_decode, + packet_http_decode, + packet_http_bin_decode_multi ]. %% Test cases starts here. @@ -1466,6 +1468,173 @@ client_packet_decode(Socket, CDR) -> end, ok. +%%-------------------------------------------------------------------- +packet_http_decode(doc) -> + ["Test setting the packet option {packet, http}"]; +packet_http_decode(suite) -> + []; + +packet_http_decode(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Request = "GET / HTTP/1.1\r\n" + "host: www.example.com\r\n" + "user-agent: HttpTester\r\n" + "\r\n", + Response = "HTTP/1.1 200 OK\r\n" + "\r\n" + "Hello!", + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_http_decode, [Response]}}, + {options, [{active, true}, binary, {packet, http} | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_decode, [Request]}}, + {options, [{active, true}, binary, {packet, http} | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + +server_http_decode(Socket, HttpResponse) -> + assert_packet_opt(Socket, http), + receive + {ssl, Socket, {http_request, 'GET', _, {1,1}}} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + assert_packet_opt(Socket, http), + receive + {ssl, Socket, {http_header, _, 'Host', _, "www.example.com"}} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + assert_packet_opt(Socket, http), + receive + {ssl, Socket, {http_header, _, 'User-Agent', _, "HttpTester"}} -> ok; + Other3 -> exit({?LINE, Other3}) + end, + assert_packet_opt(Socket, http), + receive + {ssl, Socket, http_eoh} -> ok; + Other4 -> exit({?LINE, Other4}) + end, + assert_packet_opt(Socket, http), + ok = ssl:send(Socket, HttpResponse), + ok. + +client_http_decode(Socket, HttpRequest) -> + ok = ssl:send(Socket, HttpRequest), + receive + {ssl, Socket, {http_response, {1,1}, 200, "OK"}} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + receive + {ssl, Socket, http_eoh} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + ok = ssl:setopts(Socket, [{packet, 0}]), + receive + {ssl, Socket, <<"Hello!">>} -> ok; + Other3 -> exit({?LINE, Other3}) + end, + ok. + +%%-------------------------------------------------------------------- +packet_http_bin_decode_multi(doc) -> + ["Test setting the packet option {packet, http_bin} with multiple requests"]; +packet_http_bin_decode_multi(suite) -> + []; + +packet_http_bin_decode_multi(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Request = <<"GET / HTTP/1.1\r\n" + "host: www.example.com\r\n" + "user-agent: HttpTester\r\n" + "\r\n">>, + Response = <<"HTTP/1.1 200 OK\r\n" + "\r\n" + "Hello!">>, + NumMsgs = 3, + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, server_http_bin_decode, [Response, NumMsgs]}}, + {options, [{active, true}, binary, {packet, http_bin} | + ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, client_http_bin_decode, [Request, NumMsgs]}}, + {options, [{active, true}, binary, {packet, http_bin} | + ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + +server_http_bin_decode(Socket, HttpResponse, Count) when Count > 0 -> + assert_packet_opt(Socket, http_bin), + receive + {ssl, Socket, {http_request, 'GET', _, {1,1}}} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + assert_packet_opt(Socket, http_bin), + receive + {ssl, Socket, {http_header, _, 'Host', _, <<"www.example.com">>}} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + assert_packet_opt(Socket, http_bin), + receive + {ssl, Socket, {http_header, _, 'User-Agent', _, <<"HttpTester">>}} -> ok; + Other3 -> exit({?LINE, Other3}) + end, + assert_packet_opt(Socket, http_bin), + receive + {ssl, Socket, http_eoh} -> ok; + Other4 -> exit({?LINE, Other4}) + end, + assert_packet_opt(Socket, http_bin), + ok = ssl:send(Socket, HttpResponse), + server_http_bin_decode(Socket, HttpResponse, Count - 1); +server_http_bin_decode(_, _, _) -> + ok. + +client_http_bin_decode(Socket, HttpRequest, Count) when Count > 0 -> + ok = ssl:send(Socket, HttpRequest), + receive + {ssl, Socket, {http_response, {1,1}, 200, <<"OK">>}} -> ok; + Other1 -> exit({?LINE, Other1}) + end, + receive + {ssl, Socket, http_eoh} -> ok; + Other2 -> exit({?LINE, Other2}) + end, + ok = ssl:setopts(Socket, [{packet, 0}]), + receive + {ssl, Socket, <<"Hello!">>} -> ok; + Other3 -> exit({?LINE, Other3}) + end, + ok = ssl:setopts(Socket, [{packet, http_bin}]), + client_http_bin_decode(Socket, HttpRequest, Count - 1); +client_http_bin_decode(_, _, _) -> + ok. %%-------------------------------------------------------------------- %% Internal functions @@ -1572,3 +1741,6 @@ active_packet(Socket, Data, N) -> Other -> {other, Other, ssl:session_info(Socket),N} end. + +assert_packet_opt(Socket, Type) -> + {ok, [{packet, Type}]} = ssl:getopts(Socket, [packet]). diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 2df2e70679..00c5350ad0 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -26,6 +26,7 @@ %% Note: This directive should only be used in test suites. -compile(export_all). +-record(sslsocket, { fd = nil, pid = nil}). timetrap(Time) -> Mul = try @@ -52,7 +53,11 @@ node_to_hostip(Node) -> Address. start_server(Args) -> - spawn_link(?MODULE, run_server, [Args]). + Result = spawn_link(?MODULE, run_server, [Args]), + receive + {listen, up} -> + Result + end. run_server(Opts) -> Node = proplists:get_value(node, Opts), @@ -61,23 +66,14 @@ run_server(Opts) -> Pid = proplists:get_value(from, Opts), test_server:format("ssl:listen(~p, ~p)~n", [Port, Options]), {ok, ListenSocket} = rpc:call(Node, ssl, listen, [Port, Options]), - case Port of - 0 -> - {ok, {_, NewPort}} = ssl:sockname(ListenSocket), - Pid ! {self(), {port, NewPort}}; - _ -> - ok - end, + Pid ! {listen, up}, + send_selected_port(Pid, Port, ListenSocket), run_server(ListenSocket, Opts). run_server(ListenSocket, Opts) -> + AcceptSocket = connect(ListenSocket, Opts), Node = proplists:get_value(node, Opts), Pid = proplists:get_value(from, Opts), - test_server:format("ssl:transport_accept(~p)~n", [ListenSocket]), - {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept, - [ListenSocket]), - test_server:format("ssl:ssl_accept(~p)~n", [AcceptSocket]), - ok = rpc:call(Node, ssl, ssl_accept, [AcceptSocket]), {Module, Function, Args} = proplists:get_value(mfa, Opts), test_server:format("Server: apply(~p,~p,~p)~n", [Module, Function, [AcceptSocket | Args]]), @@ -85,6 +81,7 @@ run_server(ListenSocket, Opts) -> no_result_msg -> ok; Msg -> + test_server:format("Msg: ~p ~n", [Msg]), Pid ! {self(), Msg} end, receive @@ -94,8 +91,44 @@ run_server(ListenSocket, Opts) -> ok = rpc:call(Node, ssl, close, [AcceptSocket]) end. +%%% To enable to test with s_client -reconnect +connect(ListenSocket, Opts) -> + Node = proplists:get_value(node, Opts), + ReconnectTimes = proplists:get_value(reconnect_times, Opts, 0), + AcceptSocket = connect(ListenSocket, Node, 1 + ReconnectTimes, dummy), + case ReconnectTimes of + 0 -> + AcceptSocket; + _ -> + remove_close_msg(ReconnectTimes), + AcceptSocket + end. + +connect(_, _, 0, AcceptSocket) -> + AcceptSocket; +connect(ListenSocket, Node, N, _) -> + test_server:format("ssl:transport_accept(~p)~n", [ListenSocket]), + {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept, + [ListenSocket]), + test_server:format("ssl:ssl_accept(~p)~n", [AcceptSocket]), + ok = rpc:call(Node, ssl, ssl_accept, [AcceptSocket]), + connect(ListenSocket, Node, N-1, AcceptSocket). + +remove_close_msg(0) -> + ok; +remove_close_msg(ReconnectTimes) -> + receive + {ssl_closed, _} -> + remove_close_msg(ReconnectTimes -1) + end. + + start_client(Args) -> - spawn_link(?MODULE, run_client, [Args]). + Result = spawn_link(?MODULE, run_client, [Args]), + receive + connected -> + Result + end. run_client(Opts) -> Node = proplists:get_value(node, Opts), @@ -106,14 +139,11 @@ run_client(Opts) -> test_server:format("ssl:connect(~p, ~p, ~p)~n", [Host, Port, Options]), case rpc:call(Node, ssl, connect, [Host, Port, Options]) of {ok, Socket} -> + Pid ! connected, test_server:format("Client: connected~n", []), - case proplists:get_value(port, Options) of - 0 -> - {ok, {_, NewPort}} = ssl:sockname(Socket), - Pid ! {self(), {port, NewPort}}; - _ -> - ok - end, + %% In specail cases we want to know the client port, it will + %% be indicated by sending {port, 0} in options list! + send_selected_port(Pid, proplists:get_value(port, Options), Socket), {Module, Function, Args} = proplists:get_value(mfa, Opts), test_server:format("Client: apply(~p,~p,~p)~n", [Module, Function, [Socket | Args]]), @@ -178,6 +208,26 @@ check_result(Pid, Msg) -> test_server:fail(Reason) end. +check_result_ignore_renegotiation_reject(Pid, Msg) -> + receive + {Pid, fail_session_fatal_alert_during_renegotiation} -> + test_server:comment("Server rejected old renegotiation"), + ok; + {ssl_error, _, esslconnect} -> + test_server:comment("Server rejected old renegotiation"), + ok; + {Pid, Msg} -> + ok; + {Port, {data,Debug}} when is_port(Port) -> + io:format("openssl ~s~n",[Debug]), + check_result(Pid,Msg); + Unexpected -> + Reason = {{expected, {Pid, Msg}}, + {got, Unexpected}}, + test_server:fail(Reason) + end. + + wait_for_result(Server, ServerMsg, Client, ClientMsg) -> receive {Server, ServerMsg} -> @@ -237,7 +287,7 @@ cert_options(Config) -> "badcert.pem"]), BadKeyFile = filename:join([?config(priv_dir, Config), "badkey.pem"]), - [{client_opts, [{ssl_imp, new}]}, + [{client_opts, [{ssl_imp, new},{reuseaddr, true}]}, {client_verification_opts, [{cacertfile, ClientCaCertFile}, {certfile, ClientCertFile}, {keyfile, ClientKeyFile}, @@ -269,7 +319,11 @@ cert_options(Config) -> start_upgrade_server(Args) -> - spawn_link(?MODULE, run_upgrade_server, [Args]). + Result = spawn_link(?MODULE, run_upgrade_server, [Args]), + receive + {listen, up} -> + Result + end. run_upgrade_server(Opts) -> Node = proplists:get_value(node, Opts), @@ -281,15 +335,8 @@ run_upgrade_server(Opts) -> test_server:format("gen_tcp:listen(~p, ~p)~n", [Port, TcpOptions]), {ok, ListenSocket} = rpc:call(Node, gen_tcp, listen, [Port, TcpOptions]), - - case Port of - 0 -> - {ok, {_, NewPort}} = inet:sockname(ListenSocket), - Pid ! {self(), {port, NewPort}}; - _ -> - ok - end, - + Pid ! {listen, up}, + send_selected_port(Pid, Port, ListenSocket), test_server:format("gen_tcp:accept(~p)~n", [ListenSocket]), {ok, AcceptSocket} = rpc:call(Node, gen_tcp, accept, [ListenSocket]), @@ -331,14 +378,8 @@ run_upgrade_client(Opts) -> test_server:format("gen_tcp:connect(~p, ~p, ~p)~n", [Host, Port, TcpOptions]), {ok, Socket} = rpc:call(Node, gen_tcp, connect, [Host, Port, TcpOptions]), - - case proplists:get_value(port, Opts) of - 0 -> - {ok, {_, NewPort}} = inet:sockname(Socket), - Pid ! {self(), {port, NewPort}}; - _ -> - ok - end, + + send_selected_port(Pid, Port, Socket), test_server:format("ssl:connect(~p, ~p)~n", [Socket, SslOptions]), {ok, SslSocket} = rpc:call(Node, ssl, connect, [Socket, SslOptions]), @@ -354,7 +395,11 @@ run_upgrade_client(Opts) -> end. start_server_error(Args) -> - spawn_link(?MODULE, run_server_error, [Args]). + Result = spawn_link(?MODULE, run_server_error, [Args]), + receive + {listen, up} -> + Result + end. run_server_error(Opts) -> Node = proplists:get_value(node, Opts), @@ -364,8 +409,10 @@ run_server_error(Opts) -> test_server:format("ssl:listen(~p, ~p)~n", [Port, Options]), case rpc:call(Node, ssl, listen, [Port, Options]) of {ok, ListenSocket} -> - test_server:sleep(2000), %% To make sure error_client will + %% To make sure error_client will %% get {error, closed} and not {error, connection_refused} + Pid ! {listen, up}, + send_selected_port(Pid, Port, ListenSocket), test_server:format("ssl:transport_accept(~p)~n", [ListenSocket]), case rpc:call(Node, ssl, transport_accept, [ListenSocket]) of {error, _} = Error -> @@ -376,6 +423,9 @@ run_server_error(Opts) -> Pid ! {self(), Error} end; Error -> + %% Not really true but as this is an error test + %% this is what we want. + Pid ! {listen, up}, Pid ! {self(), Error} end. @@ -400,8 +450,8 @@ inet_port(Pid) when is_pid(Pid)-> inet_port(Node) -> {Port, Socket} = do_inet_port(Node), - rpc:call(Node, gen_tcp, close, [Socket]), - Port. + rpc:call(Node, gen_tcp, close, [Socket]), + Port. do_inet_port(Node) -> {ok, Socket} = rpc:call(Node, gen_tcp, listen, [0, [{reuseaddr, true}]]), @@ -410,3 +460,37 @@ do_inet_port(Node) -> no_result(_) -> no_result_msg. + +trigger_renegotiate(Socket, [ErlData, N]) -> + [{session_id, Id} | _ ] = ssl:session_info(Socket), + trigger_renegotiate(Socket, ErlData, N, Id). + +trigger_renegotiate(Socket, _, 0, Id) -> + test_server:sleep(1000), + case ssl:session_info(Socket) of + [{session_id, Id} | _ ] -> + fail_session_not_renegotiated; + %% Tests that uses this function will not reuse + %% sessions so if we get a new session id the + %% renegotiation has succeeded. + [{session_id, _} | _ ] -> + ok; + {error, closed} -> + fail_session_fatal_alert_during_renegotiation; + {error, timeout} -> + fail_timeout + end; + +trigger_renegotiate(Socket, ErlData, N, Id) -> + ssl:send(Socket, ErlData), + trigger_renegotiate(Socket, ErlData, N-1, Id). + + +send_selected_port(Pid, 0, #sslsocket{} = Socket) -> + {ok, {_, NewPort}} = ssl:sockname(Socket), + Pid ! {self(), {port, NewPort}}; +send_selected_port(Pid, 0, Socket) -> + {ok, {_, NewPort}} = inet:sockname(Socket), + Pid ! {self(), {port, NewPort}}; +send_selected_port(_,_,_) -> + ok. diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index c079e12b83..cbf0447bf0 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -30,6 +30,9 @@ -define(TIMEOUT, 120000). -define(SLEEP, 1000). +-define(OPENSSL_RENEGOTIATE, "r\n"). +-define(OPENSSL_QUIT, "Q\n"). +-define(OPENSSL_GARBAGE, "P\n"). %% Test server callback functions %%-------------------------------------------------------------------- @@ -114,6 +117,11 @@ all(doc) -> all(suite) -> [erlang_client_openssl_server, erlang_server_openssl_client, + erlang_server_openssl_client_reuse_session, + erlang_client_openssl_server_renegotiate, + erlang_client_openssl_server_no_wrap_sequence_number, + erlang_server_openssl_client_no_wrap_sequence_number, + erlang_client_openssl_server_no_server_ca_cert, ssl3_erlang_client_openssl_server, ssl3_erlang_server_openssl_client, ssl3_erlang_client_openssl_server_client_cert, @@ -124,7 +132,8 @@ all(suite) -> tls1_erlang_client_openssl_server_client_cert, tls1_erlang_server_openssl_client_client_cert, tls1_erlang_server_erlang_client_client_cert, - ciphers + ciphers, + erlang_client_bad_openssl_server ]. %% Test cases starts here. @@ -148,13 +157,13 @@ erlang_client_openssl_server(Config) when is_list(Config) -> KeyFile = proplists:get_value(keyfile, ServerOpts), Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile, + " -cert " ++ CertFile ++ " -key " ++ KeyFile, test_server:format("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), - test_server:sleep(?SLEEP), + wait_for_openssl_server(), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, @@ -193,14 +202,199 @@ erlang_server_openssl_client(Config) when is_list(Config) -> {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), + Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ + " -host localhost", + + test_server:format("openssl cmd: ~p~n", [Cmd]), + + OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + port_command(OpenSslPort, Data), + + ssl_test_lib:check_result(Server, ok), + + ssl_test_lib:close(Server), + + close_port(OpenSslPort), + process_flag(trap_exit, false), + ok. + +%%-------------------------------------------------------------------- + +erlang_server_openssl_client_reuse_session(doc) -> + ["Test erlang server with openssl client that reconnects with the" + "same session id, to test reusing of sessions."]; +erlang_server_openssl_client_reuse_session(suite) -> + []; +erlang_server_openssl_client_reuse_session(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ServerOpts = ?config(server_opts, Config), + + {_, ServerNode, _} = ssl_test_lib:run_where(Config), + + Data = "From openssl to erlang", + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, + {reconnect_times, 5}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ + " -host localhost -reconnect", + + test_server:format("openssl cmd: ~p~n", [Cmd]), + + OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + + port_command(OpenSslPort, Data), + + ssl_test_lib:check_result(Server, ok), + + ssl_test_lib:close(Server), + + close_port(OpenSslPort), + process_flag(trap_exit, false), + ok. + +%%-------------------------------------------------------------------- + +erlang_client_openssl_server_renegotiate(doc) -> + ["Test erlang client when openssl server issuses a renegotiate"]; +erlang_client_openssl_server_renegotiate(suite) -> + []; +erlang_client_openssl_server_renegotiate(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), + + {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), + + ErlData = "From erlang to openssl", + OpenSslData = "From openssl to erlang", + + Port = ssl_test_lib:inet_port(node()), + CertFile = proplists:get_value(certfile, ServerOpts), + KeyFile = proplists:get_value(keyfile, ServerOpts), + + Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ + " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg", + + test_server:format("openssl cmd: ~p~n", [Cmd]), + + OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + + wait_for_openssl_server(), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, + delayed_send, [[ErlData, OpenSslData]]}}, + {options, ClientOpts}]), + + port_command(OpensslPort, ?OPENSSL_RENEGOTIATE), test_server:sleep(?SLEEP), + port_command(OpensslPort, OpenSslData), + + %%ssl_test_lib:check_result(Client, ok), + %% Currently allow test case to not fail + %% if server requires secure renegotiation from RFC-5746 + %% This should be removed as soon as we have implemented it. + ssl_test_lib:check_result_ignore_renegotiation_reject(Client, ok), + + %% Clean close down! Server needs to be closed first !! + close_port(OpensslPort), + + ssl_test_lib:close(Client), + process_flag(trap_exit, false), + ok. + +%%-------------------------------------------------------------------- + +erlang_client_openssl_server_no_wrap_sequence_number(doc) -> + ["Test that erlang client will renegotiate session when", + "max sequence number celing is about to be reached. Although" + "in the testcase we use the test option renegotiate_at" + " to lower treashold substantially."]; +erlang_client_openssl_server_no_wrap_sequence_number(suite) -> + []; +erlang_client_openssl_server_no_wrap_sequence_number(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), + + {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), + + ErlData = "From erlang to openssl\n", + N = 10, + + Port = ssl_test_lib:inet_port(node()), + CertFile = proplists:get_value(certfile, ServerOpts), + KeyFile = proplists:get_value(keyfile, ServerOpts), + Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ + " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg", + + test_server:format("openssl cmd: ~p~n", [Cmd]), + + OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + + wait_for_openssl_server(), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + trigger_renegotiate, [[ErlData, N+2]]}}, + {options, [{reuse_sessions, false}, + {renegotiate_at, N} | ClientOpts]}]), + + %%ssl_test_lib:check_result(Client, ok), + %% Currently allow test case to not fail + %% if server requires secure renegotiation from RFC-5746 + %% This should be removed as soon as we have implemented it. + ssl_test_lib:check_result_ignore_renegotiation_reject(Client, ok), + + %% Clean close down! Server needs to be closed first !! + close_port(OpensslPort), + + ssl_test_lib:close(Client), + process_flag(trap_exit, false), + ok. +%%-------------------------------------------------------------------- +erlang_server_openssl_client_no_wrap_sequence_number(doc) -> + ["Test that erlang client will renegotiate session when", + "max sequence number celing is about to be reached. Although" + "in the testcase we use the test option renegotiate_at" + " to lower treashold substantially."]; + +erlang_server_openssl_client_no_wrap_sequence_number(suite) -> + []; +erlang_server_openssl_client_no_wrap_sequence_number(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ServerOpts = ?config(server_opts, Config), + + {_, ServerNode, _} = ssl_test_lib:run_where(Config), + + Data = "From openssl to erlang", + + N = 10, + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + trigger_renegotiate, [[Data, N+2]]}}, + {options, [{renegotiate_at, N} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ - " -host localhost", + " -host localhost -msg", test_server:format("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + port_command(OpenSslPort, Data), ssl_test_lib:check_result(Server, ok), @@ -210,6 +404,53 @@ erlang_server_openssl_client(Config) when is_list(Config) -> close_port(OpenSslPort), process_flag(trap_exit, false), ok. +%%-------------------------------------------------------------------- + +erlang_client_openssl_server_no_server_ca_cert(doc) -> + ["Test erlang client when openssl server sends a cert chain not" + "including the ca cert. Explicitly test this even if it is" + "implicitly tested eleswhere."]; +erlang_client_openssl_server_no_server_ca_cert(suite) -> + []; +erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), + + {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), + + Data = "From openssl to erlang", + + Port = ssl_test_lib:inet_port(node()), + CertFile = proplists:get_value(certfile, ServerOpts), + KeyFile = proplists:get_value(keyfile, ServerOpts), + + Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ + " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg", + + test_server:format("openssl cmd: ~p~n", [Cmd]), + + OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + + wait_for_openssl_server(), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, + erlang_ssl_receive, [Data]}}, + {options, ClientOpts}]), + + port_command(OpensslPort, Data), + + ssl_test_lib:check_result(Client, ok), + + %% Clean close down! Server needs to be closed first !! + close_port(OpensslPort), + + ssl_test_lib:close(Client), + process_flag(trap_exit, false), + ok. %%-------------------------------------------------------------------- ssl3_erlang_client_openssl_server(doc) -> @@ -233,7 +474,7 @@ ssl3_erlang_client_openssl_server(Config) when is_list(Config) -> OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), - test_server:sleep(?SLEEP), + wait_for_openssl_server(), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, @@ -268,8 +509,6 @@ ssl3_erlang_server_openssl_client(Config) when is_list(Config) -> {options, [{versions, [sslv3]} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - - test_server:sleep(?SLEEP), Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ " -host localhost -ssl3", @@ -300,8 +539,8 @@ ssl3_erlang_client_openssl_server_client_cert(Config) when is_list(Config) -> Data = "From openssl to erlang", Port = ssl_test_lib:inet_port(node()), - CaCertFile = proplists:get_value(cacertfile, ServerOpts), CertFile = proplists:get_value(certfile, ServerOpts), + CaCertFile = proplists:get_value(cacertfile, ServerOpts), KeyFile = proplists:get_value(keyfile, ServerOpts), Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ @@ -312,7 +551,7 @@ ssl3_erlang_client_openssl_server_client_cert(Config) when is_list(Config) -> OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), - test_server:sleep(?SLEEP), + wait_for_openssl_server(), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, @@ -354,8 +593,6 @@ ssl3_erlang_server_openssl_client_client_cert(Config) when is_list(Config) -> | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - test_server:sleep(?SLEEP), - CaCertFile = proplists:get_value(cacertfile, ClientOpts), CertFile = proplists:get_value(certfile, ClientOpts), KeyFile = proplists:get_value(keyfile, ClientOpts), @@ -402,8 +639,6 @@ ssl3_erlang_server_erlang_client_client_cert(Config) when is_list(Config) -> | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - test_server:sleep(?SLEEP), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, @@ -439,14 +674,13 @@ tls1_erlang_client_openssl_server(Config) when is_list(Config) -> KeyFile = proplists:get_value(keyfile, ServerOpts), Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ - " -cert " ++ CertFile - ++ " -key " ++ KeyFile ++ " -tls1", + " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -tls1", test_server:format("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), - test_server:sleep(?SLEEP), + wait_for_openssl_server(), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, @@ -484,8 +718,6 @@ tls1_erlang_server_openssl_client(Config) when is_list(Config) -> [{versions, [tlsv1]} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - test_server:sleep(?SLEEP), - Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ " -host localhost -tls1", @@ -529,7 +761,7 @@ tls1_erlang_client_openssl_server_client_cert(Config) when is_list(Config) -> OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), - test_server:sleep(?SLEEP), + wait_for_openssl_server(), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, @@ -571,8 +803,6 @@ tls1_erlang_server_openssl_client_client_cert(Config) when is_list(Config) -> | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - test_server:sleep(?SLEEP), - CaCertFile = proplists:get_value(cacertfile, ClientOpts), CertFile = proplists:get_value(certfile, ClientOpts), KeyFile = proplists:get_value(keyfile, ClientOpts), @@ -617,8 +847,6 @@ tls1_erlang_server_erlang_client_client_cert(Config) when is_list(Config) -> | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - test_server:sleep(?SLEEP), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, @@ -668,14 +896,13 @@ cipher(CipherSuite, Version, Config) -> KeyFile = proplists:get_value(keyfile, ServerOpts), Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ - " -cert " ++ CertFile - ++ " -key " ++ KeyFile ++ "", + " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "", test_server:format("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), - test_server:sleep(?SLEEP), + wait_for_openssl_server(), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, @@ -707,6 +934,52 @@ cipher(CipherSuite, Version, Config) -> Return. %%-------------------------------------------------------------------- +erlang_client_bad_openssl_server(doc) -> + [""]; +erlang_client_bad_openssl_server(suite) -> + []; +erlang_client_bad_openssl_server(Config) when is_list(Config) -> + process_flag(trap_exit, true), + ServerOpts = ?config(server_verification_opts, Config), + ClientOpts = ?config(client_verification_opts, Config), + + {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), + + Port = ssl_test_lib:inet_port(node()), + CertFile = proplists:get_value(certfile, ServerOpts), + KeyFile = proplists:get_value(keyfile, ServerOpts), + + Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ + " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "", + + test_server:format("openssl cmd: ~p~n", [Cmd]), + + OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + + wait_for_openssl_server(), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, server_sent_garbage, []}}, + {options, + [{versions, [tlsv1]} | ClientOpts]}]), + + %% Send garbage + port_command(OpensslPort, ?OPENSSL_GARBAGE), + + test_server:sleep(?SLEEP), + + Client ! server_sent_garbage, + + ssl_test_lib:check_result(Client, true), + + ssl_test_lib:close(Client), + %% Clean close down! + close_port(OpensslPort), + process_flag(trap_exit, false), + ok. +%%-------------------------------------------------------------------- erlang_ssl_receive(Socket, Data) -> test_server:format("Connection info: ~p~n", @@ -738,8 +1011,14 @@ connection_info(Socket, Version) -> connection_info_result(Socket) -> ssl:connection_info(Socket). + +delayed_send(Socket, [ErlData, OpenSslData]) -> + test_server:sleep(?SLEEP), + ssl:send(Socket, ErlData), + erlang_ssl_receive(Socket, OpenSslData). + close_port(Port) -> - port_command(Port, "Q\n"), + port_command(Port, ?OPENSSL_QUIT), %%catch port_command(Port, "quit\n"), close_loop(Port, 500, false). @@ -770,3 +1049,22 @@ close_loop(Port, Time, SentClose) -> io:format("Timeout~n",[]) end end. + + +server_sent_garbage(Socket) -> + receive + server_sent_garbage -> + {error, closed} == ssl:send(Socket, "data") + end. + +wait_for_openssl_server() -> + receive + {Port, {data, Debug}} when is_port(Port) -> + io:format("openssl ~s~n",[Debug]), + %% openssl has started make sure + %% it will be in accept. Parsing + %% output is too error prone. (Even + %% more so than sleep!) + test_server:sleep(?SLEEP) + end. + |