1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2019-2020. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20%% 21 22-module(openssl_sni_SUITE). 23 24-include_lib("common_test/include/ct.hrl"). 25%% Callback functions 26-export([all/0, 27 groups/0, 28 init_per_suite/1, 29 end_per_suite/1, 30 init_per_group/2, 31 end_per_group/2, 32 init_per_testcase/2, 33 end_per_testcase/2]). 34 35%% Testcases 36-export([erlang_server_openssl_client_sni_match/1, 37 erlang_server_openssl_client_sni_match_fun/1, 38 erlang_server_openssl_client_sni_no_match/1, 39 erlang_server_openssl_client_sni_no_match_fun/1, 40 erlang_server_openssl_client_sni_no_header/1, 41 erlang_server_openssl_client_sni_no_header_fun/1 42 ]). 43 44%% Apply exports 45-export([send_and_hostname/1 46 ]). 47 48-define(OPENSSL_QUIT, "Q\n"). 49-define(OPENSSL_RENEGOTIATE, "R\n"). 50-define(SLEEP, 1000). 51 52%%-------------------------------------------------------------------- 53%% Common Test interface functions ----------------------------------- 54%%-------------------------------------------------------------------- 55 56all() -> 57 %% Note: SNI not supported in sslv3 58 case ssl_test_lib:openssl_sane_dtls() of 59 true -> 60 [{group, 'tlsv1.3'}, 61 {group, 'tlsv1.2'}, 62 {group, 'tlsv1.1'}, 63 {group, 'tlsv1'} 64 %% Seems broken in openssl 65 %%{group, 'dtlsv1.2'}, 66 %%{group, 'dtlsv1'} 67 ]; 68 false -> 69 [{group, 'tlsv1.3'}, 70 {group, 'tlsv1.2'}, 71 {group, 'tlsv1.1'}, 72 {group, 'tlsv1'}] 73 end. 74 75groups() -> 76 case ssl_test_lib:openssl_sane_dtls() of 77 true -> 78 [{'tlsv1.3', [], sni_tests()}, 79 {'tlsv1.2', [], sni_tests()}, 80 {'tlsv1.1', [], sni_tests()}, 81 {'tlsv1', [], sni_tests()} 82 %% Seems broken in openssl 83 %%{'dtlsv1.2', [], sni_tests()}, 84 %%{'dtlsv1', [], sni_tests()} 85 ]; 86 false -> 87 [{'tlsv1.3', [], sni_tests()}, 88 {'tlsv1.2', [], sni_tests()}, 89 {'tlsv1.1', [], sni_tests()}, 90 {'tlsv1', [], sni_tests()} 91 ] 92 end. 93 94sni_tests() -> 95 [erlang_server_openssl_client_sni_match, 96 erlang_server_openssl_client_sni_match_fun, 97 erlang_server_openssl_client_sni_no_match, 98 erlang_server_openssl_client_sni_no_match_fun, 99 erlang_server_openssl_client_sni_no_header, 100 erlang_server_openssl_client_sni_no_header_fun]. 101 102init_per_suite(Config0) -> 103 case os:find_executable("openssl") of 104 false -> 105 {skip, "Openssl not found"}; 106 _ -> 107 case check_openssl_sni_support(Config0) of 108 {skip, _} = Skip -> 109 Skip; 110 _ -> 111 ct:pal("Version: ~p", [os:cmd("openssl version")]), 112 catch crypto:stop(), 113 try crypto:start() of 114 ok -> 115 ssl_test_lib:clean_start(), 116 Config = ssl_test_lib:make_rsa_cert(Config0), 117 RsaOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), 118 [{sni_server_opts, [{sni_hosts, 119 [{"a.server", [ 120 {certfile, proplists:get_value(certfile, RsaOpts)}, 121 {keyfile, proplists:get_value(keyfile, RsaOpts)} 122 ]}, 123 {"b.server", [ 124 {certfile, proplists:get_value(certfile, RsaOpts)}, 125 {keyfile, proplists:get_value(keyfile, RsaOpts)} 126 ]} 127 ]}]} | Config] 128 catch _:_ -> 129 {skip, "Crypto did not start"} 130 end 131 end 132 end. 133 134end_per_suite(_Config) -> 135 ssl:stop(), 136 application:stop(crypto), 137 ssl_test_lib:kill_openssl(). 138 139init_per_group(GroupName, Config) -> 140 ssl_test_lib:init_per_group_openssl(GroupName, Config). 141 142end_per_group(GroupName, Config) -> 143 ssl_test_lib:end_per_group(GroupName, Config). 144 145init_per_testcase(_TestCase, Config) -> 146 ct:timetrap({seconds, 10}), 147 Config. 148 149 150end_per_testcase(_, Config) -> 151 Config. 152 153%%-------------------------------------------------------------------- 154%% Test Cases -------------------------------------------------------- 155%%-------------------------------------------------------------------- 156erlang_server_openssl_client_sni_no_header(Config) when is_list(Config) -> 157 erlang_server_openssl_client_sni_test(Config, undefined, undefined, "server Peer cert"). 158 159erlang_server_openssl_client_sni_no_header_fun(Config) when is_list(Config) -> 160 erlang_server_openssl_client_sni_test_sni_fun(Config, undefined, undefined, "server Peer cert"). 161 162erlang_server_openssl_client_sni_match(Config) when is_list(Config) -> 163 erlang_server_openssl_client_sni_test(Config, "a.server", "a.server", "server Peer cert"). 164 165erlang_server_openssl_client_sni_match_fun(Config) when is_list(Config) -> 166 erlang_server_openssl_client_sni_test_sni_fun(Config, "a.server", "a.server", "server Peer cert"). 167 168erlang_server_openssl_client_sni_no_match(Config) when is_list(Config) -> 169 erlang_server_openssl_client_sni_test(Config, "c.server", undefined, "server Peer cert"). 170 171erlang_server_openssl_client_sni_no_match_fun(Config) when is_list(Config) -> 172 erlang_server_openssl_client_sni_test_sni_fun(Config, "c.server", undefined, "server Peer cert"). 173 174 175erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) -> 176 Version = ssl_test_lib:protocol_version(Config), 177 ct:log("Start running handshake, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", 178 [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]), 179 ServerOptions = proplists:get_value(sni_server_opts, Config) ++ proplists:get_value(server_rsa_opts, Config), 180 {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 181 Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 182 {from, self()}, {mfa, {?MODULE, send_and_hostname, []}}, 183 {options, ServerOptions}]), 184 Port = ssl_test_lib:inet_port(Server), 185 Exe = "openssl", 186 ClientArgs = case SNIHostname of 187 undefined -> 188 openssl_client_args(Version, Hostname,Port); 189 _ -> 190 openssl_client_args(Version, Hostname, Port, SNIHostname) 191 end, 192 ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs), 193 194 ssl_test_lib:check_result(Server, ExpectedSNIHostname), 195 ssl_test_lib:close_port(ClientPort), 196 ssl_test_lib:close(Server), 197 ok. 198 199 200erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) -> 201 Version = ssl_test_lib:protocol_version(Config), 202 ct:log("Start running handshake for sni_fun, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", 203 [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]), 204 [{sni_hosts, ServerSNIConf}] = proplists:get_value(sni_server_opts, Config), 205 SNIFun = fun(Domain) -> proplists:get_value(Domain, ServerSNIConf, undefined) end, 206 ServerOptions = proplists:get_value(server_rsa_opts, Config) ++ [{sni_fun, SNIFun}], 207 {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 208 Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 209 {from, self()}, {mfa, {?MODULE, send_and_hostname, []}}, 210 {options, ServerOptions}]), 211 Port = ssl_test_lib:inet_port(Server), 212 Exe = "openssl", 213 ClientArgs = case SNIHostname of 214 undefined -> 215 openssl_client_args(Version, Hostname,Port); 216 _ -> 217 openssl_client_args(Version, Hostname, Port, SNIHostname) 218 end, 219 220 ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs), 221 222 ssl_test_lib:check_result(Server, ExpectedSNIHostname), 223 ssl_test_lib:close_port(ClientPort), 224 ssl_test_lib:close(Server). 225%%-------------------------------------------------------------------- 226%% Callback functions ------------------------------------------------ 227%%-------------------------------------------------------------------- 228send_and_hostname(SSLSocket) -> 229 ssl:send(SSLSocket, "OK"), 230 case ssl:connection_information(SSLSocket, [sni_hostname]) of 231 {ok, []} -> 232 undefined; 233 {ok, [{sni_hostname, Hostname}]} -> 234 Hostname 235 end. 236%%-------------------------------------------------------------------- 237%% Internal functions ----------------------------------------------- 238%%-------------------------------------------------------------------- 239openssl_client_args(Version, Hostname, Port) -> 240 ssl_test_lib:maybe_force_ipv4(["s_client", "-connect", Hostname ++ ":" ++ integer_to_list(Port), 241 ssl_test_lib:version_flag(Version)]). 242 243openssl_client_args(Version, Hostname, Port, ServerName) -> 244 ssl_test_lib:maybe_force_ipv4(["s_client", "-connect", Hostname ++ ":" ++ 245 integer_to_list(Port), 246 ssl_test_lib:version_flag(Version), "-servername", ServerName]). 247 248check_openssl_sni_support(Config) -> 249 HelpText = os:cmd("openssl s_client --help"), 250 case ssl_test_lib:is_sane_oppenssl_client() of 251 true -> 252 case string:str(HelpText, "-servername") of 253 0 -> 254 {skip, "Current openssl doesn't support SNI"}; 255 _ -> 256 Config 257 end; 258 false -> 259 {skip, "Current openssl doesn't support SNI or extension handling is flawed"} 260 end. 261