1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2015-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 23-module(ssl_pem_cache_SUITE). 24 25%% Note: This directive should only be used in test suites. 26-compile(export_all). 27 28-include_lib("common_test/include/ct.hrl"). 29-include_lib("kernel/include/file.hrl"). 30 31-define(CLEANUP_INTERVAL, 5000). 32 33%%-------------------------------------------------------------------- 34%% Common Test interface functions ----------------------------------- 35%%-------------------------------------------------------------------- 36all() -> 37 [ 38 pem_cleanup, 39 clear_pem_cache, 40 invalid_insert]. 41 42groups() -> 43 []. 44 45init_per_suite(Config0) -> 46 catch crypto:stop(), 47 try crypto:start() of 48 ok -> 49 ssl_test_lib:clean_start(), 50 %% make rsa certs 51 ssl_test_lib:make_rsa_cert(Config0) 52 catch _:_ -> 53 {skip, "Crypto did not start"} 54 end. 55 56end_per_suite(_Config) -> 57 application:stop(crypto). 58 59init_per_group(_GroupName, Config) -> 60 Config. 61 62end_per_group(_GroupName, Config) -> 63 Config. 64 65init_per_testcase(pem_cleanup = Case, Config) -> 66 application:load(ssl), 67 end_per_testcase(Case, Config) , 68 application:set_env(ssl, ssl_pem_cache_clean, ?CLEANUP_INTERVAL), 69 ssl:start(), 70 ct:timetrap({minutes, 1}), 71 Config; 72init_per_testcase(_, Config) -> 73 ssl:start(), 74 ct:timetrap({seconds, 5}), 75 Config. 76 77end_per_testcase(_TestCase, Config) -> 78 ssl_test_lib:clean_env(), 79 ssl:stop(), 80 Config. 81 82%%-------------------------------------------------------------------- 83%% Test Cases -------------------------------------------------------- 84%%-------------------------------------------------------------------- 85pem_cleanup() -> 86 [{doc, "Test pem cache invalidate mechanism"}]. 87pem_cleanup(Config)when is_list(Config) -> 88 process_flag(trap_exit, true), 89 ClientOpts = proplists:get_value(client_rsa_verify_opts, Config), 90 ServerOpts = proplists:get_value(server_rsa_verify_opts, Config), 91 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 92 93 Server = 94 ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 95 {from, self()}, 96 {mfa, {ssl_test_lib, no_result, []}}, 97 {options, ServerOpts}]), 98 Port = ssl_test_lib:inet_port(Server), 99 Client = 100 ssl_test_lib:start_client([{node, ClientNode}, 101 {port, Port}, {host, Hostname}, 102 {mfa, {ssl_test_lib, no_result, []}}, 103 {from, self()}, {options, ClientOpts}]), 104 105 Size = ssl_pkix_db:db_size(get_pem_cache()), 106 Certfile = proplists:get_value(certfile, ServerOpts), 107 {ok, FileInfo} = file:read_file_info(Certfile), 108 Time = later(), 109 ok = file:write_file_info(Certfile, FileInfo#file_info{mtime = Time}), 110 ct:sleep(2 * ?CLEANUP_INTERVAL), 111 Size1 = ssl_pkix_db:db_size(get_pem_cache()), 112 ssl_test_lib:close(Server), 113 ssl_test_lib:close(Client), 114 false = Size == Size1. 115 116clear_pem_cache() -> 117 [{doc,"Test that internal reference tabel is cleaned properly even when " 118 " the PEM cache is cleared" }]. 119clear_pem_cache(Config) when is_list(Config) -> 120 {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), 121 [_, _,_, _, Prop] = StatusInfo, 122 State = ssl_test_lib:state(Prop), 123 [_,{FilRefDb, _} |_] = element(6, State), 124 {Server, Client} = basic_verify_test_no_close(Config), 125 CountReferencedFiles = fun({_, -1}, Acc) -> 126 Acc; 127 ({_, N}, Acc) -> 128 N + Acc 129 end, 130 131 2 = ets:foldl(CountReferencedFiles, 0, FilRefDb), 132 ssl:clear_pem_cache(), 133 _ = sys:get_status(whereis(ssl_manager)), 134 {Server1, Client1} = basic_verify_test_no_close(Config), 135 4 = ets:foldl(CountReferencedFiles, 0, FilRefDb), 136 ssl_test_lib:close(Server), 137 ssl_test_lib:close(Client), 138 ct:sleep(2000), 139 _ = sys:get_status(whereis(ssl_manager)), 140 2 = ets:foldl(CountReferencedFiles, 0, FilRefDb), 141 ssl_test_lib:close(Server1), 142 ssl_test_lib:close(Client1), 143 ct:sleep(2000), 144 _ = sys:get_status(whereis(ssl_manager)), 145 0 = ets:foldl(CountReferencedFiles, 0, FilRefDb). 146 147invalid_insert() -> 148 [{doc, "Test that insert of invalid pem does not cause empty cache entry"}]. 149invalid_insert(Config)when is_list(Config) -> 150 process_flag(trap_exit, true), 151 152 ClientOpts = proplists:get_value(client_rsa_verify_opts, Config), 153 ServerOpts = proplists:get_value(server_rsa_verify_opts, Config), 154 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 155 BadClientOpts = [{cacertfile, "tmp/does_not_exist.pem"} | proplists:delete(cacertfile, ClientOpts)], 156 Server = 157 ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 158 {from, self()}, 159 {mfa, {ssl_test_lib, no_result, []}}, 160 {options, ServerOpts}]), 161 Port = ssl_test_lib:inet_port(Server), 162 ssl_test_lib:start_client_error([{node, ClientNode}, 163 {port, Port}, {host, Hostname}, 164 {from, self()}, {options, BadClientOpts}]), 165 ssl_test_lib:close(Server), 166 1 = ssl_pkix_db:db_size(get_fileref_db()). 167 168 169 170%%-------------------------------------------------------------------- 171%% Internal funcations 172%%-------------------------------------------------------------------- 173 174get_pem_cache() -> 175 {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), 176 [_, _,_, _, Prop] = StatusInfo, 177 State = ssl_test_lib:state(Prop), 178 case element(6, State) of 179 [_CertDb, _FileRefDb, PemCache| _] -> 180 PemCache; 181 _ -> 182 undefined 183 end. 184 185get_fileref_db() -> 186 {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), 187 [_, _,_, _, Prop] = StatusInfo, 188 State = ssl_test_lib:state(Prop), 189 case element(6, State) of 190 [_CertDb, {FileRefDb,_} | _] -> 191 FileRefDb; 192 _ -> 193 undefined 194 end. 195later()-> 196 DateTime = calendar:now_to_local_time(os:timestamp()), 197 Gregorian = calendar:datetime_to_gregorian_seconds(DateTime), 198 calendar:gregorian_seconds_to_datetime(Gregorian + (2 * ?CLEANUP_INTERVAL)). 199 200basic_verify_test_no_close(Config) -> 201 ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), 202 ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), 203 204 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 205 206 Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 207 {from, self()}, 208 {mfa, {ssl_test_lib, send_recv_result_active, []}}, 209 {options, ServerOpts}]), 210 Port = ssl_test_lib:inet_port(Server), 211 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 212 {host, Hostname}, 213 {from, self()}, 214 {mfa, {ssl_test_lib, send_recv_result_active, []}}, 215 {options, ClientOpts}]), 216 217 ssl_test_lib:check_result(Server, ok, Client, ok), 218 {Server, Client}. 219