From db509dd5debcd72d7f1d024d289315274f9b788b Mon Sep 17 00:00:00 2001 From: Qijiang Fan Date: Thu, 16 Apr 2015 22:25:57 +0800 Subject: ssl: add option sni_fun The newly added function sni_fun allows dynamic update of SSL options like keys and certificates depending on different SNI hostname, rather than a predefined rules of SSL options. --- lib/ssl/test/ssl_sni_SUITE.erl | 34 +++++++++++++++++++++++++- lib/ssl/test/ssl_to_openssl_SUITE.erl | 46 ++++++++++++++++++++++++++++++++--- 2 files changed, 76 insertions(+), 4 deletions(-) (limited to 'lib/ssl/test') diff --git a/lib/ssl/test/ssl_sni_SUITE.erl b/lib/ssl/test/ssl_sni_SUITE.erl index 134e508b10..46cd644e4d 100644 --- a/lib/ssl/test/ssl_sni_SUITE.erl +++ b/lib/ssl/test/ssl_sni_SUITE.erl @@ -31,7 +31,7 @@ %%-------------------------------------------------------------------- suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> [no_sni_header, sni_match, sni_no_match]. +all() -> [no_sni_header, sni_match, sni_no_match] ++ [no_sni_header_fun, sni_match_fun, sni_no_match_fun]. init_per_suite(Config0) -> catch crypto:stop(), @@ -57,12 +57,20 @@ end_per_suite(_) -> no_sni_header(Config) -> run_handshake(Config, undefined, undefined, "server"). +no_sni_header_fun(Config) -> + run_sni_fun_handshake(Config, undefined, undefined, "server"). + sni_match(Config) -> run_handshake(Config, "a.server", "a.server", "a.server"). +sni_match_fun(Config) -> + run_sni_fun_handshake(Config, "a.server", "a.server", "a.server"). + sni_no_match(Config) -> run_handshake(Config, "c.server", undefined, "server"). +sni_no_match_fun(Config) -> + run_sni_fun_handshake(Config, "c.server", undefined, "server"). %%-------------------------------------------------------------------- @@ -112,6 +120,30 @@ recv_and_certificate(SSLSocket) -> ct:log("Subject of certificate received from server: ~p", [Subject]), rdn_to_string(rdnPart(Subject, ?'id-at-commonName')). +run_sni_fun_handshake(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) -> + ct:log("Start running handshake for sni_fun, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]), + [{sni_hosts, ServerSNIConf}] = ?config(sni_server_opts, Config), + SNIFun = fun(Domain) -> proplists:get_value(Domain, ServerSNIConf, undefined) end, + ServerOptions = ?config(server_opts, Config) ++ [{sni_fun, SNIFun}], + ClientOptions = + case SNIHostname of + undefined -> + ?config(client_opts, Config); + _ -> + [{server_name_indication, SNIHostname}] ++ ?config(client_opts, Config) + end, + ct:log("Options: ~p", [[ServerOptions, ClientOptions]]), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, {mfa, {?MODULE, send_and_hostname, []}}, + {options, ServerOptions}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, {from, self()}, + {mfa, {?MODULE, recv_and_certificate, []}}, + {options, ClientOptions}]), + ssl_test_lib:check_result(Server, ExpectedSNIHostname, Client, ExpectedCN). + run_handshake(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) -> ct:log("Start running handshake, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]), diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index 3807a9983c..0413415e49 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -102,9 +102,12 @@ npn_tests() -> erlang_client_openssl_server_npn_only_server]. sni_server_tests() -> - [erlang_server_oepnssl_client_sni_match, + [erlang_server_openssl_client_sni_match, + erlang_server_openssl_client_sni_match_fun, erlang_server_openssl_client_sni_no_match, - erlang_server_openssl_client_sni_no_header]. + erlang_server_openssl_client_sni_no_match_fun, + erlang_server_openssl_client_sni_no_header, + erlang_server_openssl_client_sni_no_header_fun]. init_per_suite(Config0) -> @@ -230,7 +233,10 @@ special_init(TestCase, Config) special_init(TestCase, Config) when TestCase == erlang_server_openssl_client_sni_match; TestCase == erlang_server_openssl_client_sni_no_match; - TestCase == erlang_server_openssl_client_sni_no_header -> + TestCase == erlang_server_openssl_client_sni_no_header; + TestCase == erlang_server_openssl_client_sni_match_fun; + TestCase == erlang_server_openssl_client_sni_no_match_fun; + TestCase == erlang_server_openssl_client_sni_no_header_fun -> check_openssl_sni_support(Config); special_init(_, Config) -> @@ -1196,12 +1202,21 @@ erlang_server_openssl_client_npn_only_client(Config) when is_list(Config) -> erlang_server_openssl_client_sni_no_header(Config) when is_list(Config) -> erlang_server_openssl_client_sni_test(Config, undefined, undefined, "server"). +erlang_server_openssl_client_sni_no_header_fun(Config) when is_list(Config) -> + erlang_server_openssl_client_sni_test_sni_fun(Config, undefined, undefined, "server"). + erlang_server_openssl_client_sni_match(Config) when is_list(Config) -> erlang_server_openssl_client_sni_test(Config, "a.server", "a.server", "a.server"). +erlang_server_openssl_client_sni_match_fun(Config) when is_list(Config) -> + erlang_server_openssl_client_sni_test_sni_fun(Config, "a.server", "a.server", "a.server"). + erlang_server_openssl_client_sni_no_match(Config) when is_list(Config) -> erlang_server_openssl_client_sni_test(Config, "c.server", undefined, "server"). +erlang_server_openssl_client_sni_no_match_fun(Config) when is_list(Config) -> + erlang_server_openssl_client_sni_test_sni_fun(Config, "c.server", undefined, "server"). + %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ @@ -1285,6 +1300,31 @@ erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname, ok. +erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) -> + ct:log("Start running handshake for sni_fun, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]), + [{sni_hosts, ServerSNIConf}] = ?config(sni_server_opts, Config), + SNIFun = fun(Domain) -> proplists:get_value(Domain, ServerSNIConf, undefined) end, + ServerOptions = ?config(server_opts, Config) ++ [{sni_fun, SNIFun}], + {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, {mfa, {?MODULE, send_and_hostname, []}}, + {options, ServerOptions}]), + Port = ssl_test_lib:inet_port(Server), + ClientCommand = case SNIHostname of + undefined -> + "openssl s_client -connect " ++ Hostname ++ ":" ++ integer_to_list(Port); + _ -> + "openssl s_client -connect " ++ Hostname ++ ":" ++ integer_to_list(Port) ++ " -servername " ++ SNIHostname + end, + ct:log("Options: ~p", [[ServerOptions, ClientCommand]]), + ClientPort = open_port({spawn, ClientCommand}, [stderr_to_stdout]), + ssl_test_lib:check_result(Server, ExpectedSNIHostname), + ExpectedClientOutput = ["OK", "/CN=" ++ ExpectedCN ++ "/"], + ok = client_read_bulk(ClientPort, ExpectedClientOutput), + ssl_test_lib:close_port(ClientPort), + ssl_test_lib:close(Server), + ok. + cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) -> process_flag(trap_exit, true), -- cgit v1.2.3