1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2019-2019. 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_reject_SUITE).
23
24-include_lib("common_test/include/ct.hrl").
25%% Common test
26-export([all/0,
27         groups/0,
28         init_per_suite/1,
29         init_per_group/2,
30         init_per_testcase/2,
31         end_per_suite/1,
32         end_per_group/2,
33         end_per_testcase/2
34        ]).
35
36%% Test cases
37-export([erlang_client_bad_openssl_server/0,
38         erlang_client_bad_openssl_server/1,
39         ssl2_erlang_server_openssl_client/0,
40         ssl2_erlang_server_openssl_client/1,
41         ssl3_erlang_server_openssl_client/0,
42         ssl3_erlang_server_openssl_client/1
43        ]).
44
45%% Apply export
46-export([server_sent_garbage/1
47        ]).
48
49
50-define(SLEEP, 1000).
51-define(OPENSSL_GARBAGE, "P\n").
52
53%%--------------------------------------------------------------------
54%% Common Test interface functions -----------------------------------
55%%--------------------------------------------------------------------
56
57all() ->
58    [{group, 'tlsv1.2'},
59     {group, 'tlsv1.1'},
60     {group, 'tlsv1'}
61     ].
62
63groups() ->
64    [{'tlsv1.2', [], all_versions_tests()},
65     {'tlsv1.1', [], all_versions_tests()},
66     {'tlsv1', [], all_versions_tests()}
67    ].
68
69all_versions_tests() ->
70    [
71     erlang_client_bad_openssl_server,
72     ssl2_erlang_server_openssl_client,
73     ssl3_erlang_server_openssl_client
74    ].
75
76init_per_suite(Config0) ->
77    case os:find_executable("openssl") of
78        false ->
79            {skip, "Openssl not found"};
80        _ ->
81            ct:pal("Version: ~p", [os:cmd("openssl version")]),
82            catch crypto:stop(),
83            try crypto:start() of
84                ok ->
85                    ssl_test_lib:clean_start(),
86                    ssl_test_lib:make_rsa_cert(Config0)
87            catch _:_  ->
88                    {skip, "Crypto did not start"}
89            end
90    end.
91
92end_per_suite(_Config) ->
93    ssl:stop(),
94    application:stop(crypto),
95    ssl_test_lib:kill_openssl().
96
97init_per_group(GroupName, Config) ->
98    ssl_test_lib:init_per_group_openssl(GroupName, Config).
99
100end_per_group(GroupName, Config) ->
101    ssl_test_lib:end_per_group(GroupName, Config).
102
103init_per_testcase(TestCase, Config) ->
104    ct:timetrap({seconds, 10}),
105    special_init(TestCase, Config).
106
107special_init(ssl2_erlang_server_openssl_client, Config) ->
108    case ssl_test_lib:supports_ssl_tls_version(sslv2) of
109        true ->
110            Config;
111        false ->
112            {skip, "sslv2 not supported by openssl"}
113     end;
114special_init(ssl3_erlang_server_openssl_client, Config) ->
115    case ssl_test_lib:supports_ssl_tls_version(sslv3) of
116        true ->
117            Config;
118        false ->
119            {skip, "sslv3 not supported by openssl"}
120     end;
121
122special_init(_, Config) ->
123     Config.
124
125end_per_testcase(_, Config) ->
126    Config.
127
128%%--------------------------------------------------------------------
129%% Test Cases --------------------------------------------------------
130%%--------------------------------------------------------------------
131erlang_client_bad_openssl_server() ->
132    [{doc,"Test what happens if openssl server sends garbage to erlang ssl client"}].
133erlang_client_bad_openssl_server(Config) when is_list(Config) ->
134    process_flag(trap_exit, true),
135    ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
136    ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
137
138    {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
139
140    Port = ssl_test_lib:inet_port(node()),
141    CertFile = proplists:get_value(certfile, ServerOpts),
142    KeyFile = proplists:get_value(keyfile, ServerOpts),
143    Version = ssl_test_lib:protocol_version(Config),
144    Exe = "openssl",
145    Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
146            "-cert", CertFile, "-key", KeyFile],
147    OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
148
149    ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
150
151    Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
152                                         {host, Hostname},
153                                         {from, self()},
154                                         {mfa, {?MODULE, server_sent_garbage, []}},
155                                         {options,
156                                          [{versions, [Version]} | ClientOpts]}]),
157
158    %% Send garbage
159    true = port_command(OpensslPort, ?OPENSSL_GARBAGE),
160
161    ct:sleep(?SLEEP),
162
163    Client0 ! server_sent_garbage,
164
165    ssl_test_lib:check_result(Client0, true),
166
167    ssl_test_lib:close(Client0),
168
169    %% Make sure openssl does not hang and leave zombie process
170    Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
171                                         {host, Hostname},
172                                         {from, self()},
173                                         {mfa, {ssl_test_lib, no_result, []}},
174                                         {options,
175                                          [{versions, [Version]} | ClientOpts]}]),
176
177    %% Clean close down!   Server needs to be closed first !!
178    ssl_test_lib:close_port(OpensslPort),
179    ssl_test_lib:close(Client1),
180    process_flag(trap_exit, false).
181
182%%--------------------------------------------------------------------
183ssl2_erlang_server_openssl_client() ->
184    [{doc,"Test that ssl v2 clients are rejected"}].
185
186ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
187    process_flag(trap_exit, true),
188    ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
189
190    {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
191
192    Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
193                                              {from, self()},
194                                              {options, ServerOpts}]),
195    Port = ssl_test_lib:inet_port(Server),
196
197    Exe = "openssl",
198    Args = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
199            "-ssl2", "-msg"],
200
201    OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
202
203    ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
204    ssl_test_lib:consume_port_exit(OpenSslPort),
205    ssl_test_lib:check_server_alert(Server, bad_record_mac),
206    process_flag(trap_exit, false).
207
208%%--------------------------------------------------------------------
209ssl3_erlang_server_openssl_client() ->
210    [{doc,"Test that ssl v3 clients are rejected"}].
211
212ssl3_erlang_server_openssl_client(Config) when is_list(Config) ->
213    process_flag(trap_exit, true),
214    ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
215
216    {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
217
218    Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
219                                              {from, self()},
220                                              {options, ServerOpts}]),
221    Port = ssl_test_lib:inet_port(Server),
222
223    Exe = "openssl",
224    Args = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
225            "-ssl3", "-msg"],
226
227    OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
228
229    ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
230    ssl_test_lib:consume_port_exit(OpenSslPort),
231    ssl_test_lib:check_server_alert(Server, bad_record_mac),
232    process_flag(trap_exit, false).
233
234%%--------------------------------------------------------------------
235%% Callback functions ------------------------------------------------
236%%--------------------------------------------------------------------
237
238server_sent_garbage(Socket) ->
239    receive
240	server_sent_garbage ->
241	    {error, closed} == ssl:send(Socket, "data")
242
243    end.
244