Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
4641-public_key-ssl-add-password-fun-for-decodi...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 4641-public_key-ssl-add-password-fun-for-decoding-keyfile.patch of Package erlang
From c6e437b5e914deb06983cc7bd224d1b1e2d8f9ea Mon Sep 17 00:00:00 2001 From: Jakub Witczak <kuba@erlang.org> Date: Fri, 14 Jan 2022 17:20:35 +0100 Subject: [PATCH] public_key,ssl: add password fun for decoding keyfiles Implementing password fun option for ssl connect API This change allows password option to accept as a value either a string or a fun. Added specific tests and documentation. The motivation for this change is to better protect a private key. If the private key is protected by password the password may be retreived using user supplied function therefore enabling storing password in a secure vault or something similar. --- lib/public_key/doc/src/public_key.xml | 1 + lib/public_key/src/public_key.erl | 10 +- lib/public_key/test/public_key_SUITE.erl | 57 ++-- lib/ssl/doc/src/ssl.xml | 4 +- lib/ssl/src/ssl.erl | 11 +- lib/ssl/src/ssl_config.erl | 2 +- lib/ssl/test/ssl_api_SUITE.erl | 3 +- lib/ssl/test/ssl_test_lib.erl | 36 ++- lib/ssl/test/tls_api_SUITE.erl | 372 +++++++++++++++-------- 9 files changed, 331 insertions(+), 165 deletions(-) diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 4c674333b2..884425cf15 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -418,6 +418,7 @@ entries. Notice that if the PEM entry is of type 'SubjectPublickeyInfo', it is further decoded to an <c>rsa_public_key()</c> or <c>dsa_public_key()</c>.</p> + <p>Password can be either an octet string or function which returns same type.</p> </desc> </func> diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 0b5061f695..b3b830b3c8 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -241,8 +241,11 @@ pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type), is_binary(Der) -> der_decode(Asn1Type, Der). --spec pem_entry_decode(PemEntry, Password) -> term() when PemEntry :: pem_entry(), - Password :: string() . +-spec pem_entry_decode(PemEntry, Password) -> term() when + PemEntry :: pem_entry(), + Password :: string() | fun(() -> string()). +pem_entry_decode(PemEntry, PasswordFun) when is_function(PasswordFun) -> + pem_entry_decode(PemEntry, PasswordFun()); pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type), is_binary(Der) -> der_decode(Asn1Type, Der); @@ -264,8 +267,7 @@ pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry, is_binary(Salt) andalso ((erlang:byte_size(Salt) == 8) or (erlang:byte_size(Salt) == 16)) andalso is_list(Password) -> - do_pem_entry_decode(PemEntry, Password). - + do_pem_entry_decode(PemEntry, Password). %%-------------------------------------------------------------------- %% diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl index b176cbef6a..3984110f5d 100644 --- a/lib/public_key/test/public_key_SUITE.erl +++ b/lib/public_key/test/public_key_SUITE.erl @@ -62,8 +62,10 @@ init_ec_pem_encode_generated/1, ec_pem_encode_generated/0, ec_pem_encode_generated/1, - encrypted_pem/0, - encrypted_pem/1, + encrypted_pem_pwdstring/0, + encrypted_pem_pwdstring/1, + encrypted_pem_pwdfun/0, + encrypted_pem_pwdfun/1, dh_pem/0, dh_pem/1, pkcs10_pem/0, @@ -121,7 +123,8 @@ ]). -define(TIMEOUT, 120000). % 2 min - +-define(PASSWORD1, "1234abcd"). +-define(PASSWORD2, "4567efgh"). %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- @@ -158,13 +161,13 @@ all() -> ]. groups() -> - [{pem_decode_encode, [], [dsa_pem, rsa_pem, rsa_pss_pss_pem, ec_pem, encrypted_pem, + [{pem_decode_encode, [], [dsa_pem, rsa_pem, rsa_pss_pss_pem, ec_pem, + encrypted_pem_pwdstring, encrypted_pem_pwdfun, dh_pem, cert_pem, pkcs7_pem, pkcs10_pem, ec_pem2, rsa_priv_pkcs8, dsa_priv_pkcs8, ec_priv_pkcs8, - eddsa_priv_pkcs8, eddsa_priv_rfc5958, - ec_pem_encode_generated, - gen_ec_param_prime_field, gen_ec_param_char_2_field - ]}, + eddsa_priv_pkcs8, eddsa_priv_rfc5958, + ec_pem_encode_generated, gen_ec_param_prime_field, + gen_ec_param_char_2_field]}, {sign_verify, [], [rsa_sign_verify, rsa_pss_sign_verify, dsa_sign_verify]} ]. %%------------------------------------------------------------------- @@ -451,37 +454,45 @@ ec_pem_encode_generated(_Config) -> %%-------------------------------------------------------------------- -encrypted_pem() -> - [{doc, "Encrypted PEM-file decode/encode"}]. -encrypted_pem(Config) when is_list(Config) -> +encrypted_pem_pwdstring() -> + [{doc, "Encrypted PEM-file decode/encode with password string used"}]. +encrypted_pem_pwdstring(Config) when is_list(Config) -> + encrypted_pem(Config, ?PASSWORD1, ?PASSWORD2). + +encrypted_pem_pwdfun() -> + [{doc, "Encrypted PEM-file decode/encode with password fun used"}]. +encrypted_pem_pwdfun(Config) when is_list(Config) -> + encrypted_pem(Config, fun() -> ?PASSWORD1 end, fun() -> ?PASSWORD2 end). + +encrypted_pem(Config, Password1, Password2) -> Datadir = proplists:get_value(data_dir, Config), [{'RSAPrivateKey', DerRSAKey, not_encrypted}] = - erl_make_certs:pem_to_der(filename:join(Datadir, "client_key.pem")), + erl_make_certs:pem_to_der(filename:join(Datadir, "client_key.pem")), RSAKey = public_key:der_decode('RSAPrivateKey', DerRSAKey), Salt0 = crypto:strong_rand_bytes(8), Entry0 = public_key:pem_entry_encode('RSAPrivateKey', RSAKey, - {{"DES-EDE3-CBC", Salt0}, "1234abcd"}), - RSAKey = public_key:pem_entry_decode(Entry0,"1234abcd"), + {{"DES-EDE3-CBC", Salt0}, ?PASSWORD1}), + RSAKey = public_key:pem_entry_decode(Entry0, Password1), Des3KeyFile = filename:join(Datadir, "des3_client_key.pem"), erl_make_certs:der_to_pem(Des3KeyFile, [Entry0]), [{'RSAPrivateKey', _, {"DES-EDE3-CBC", Salt0}}] = - erl_make_certs:pem_to_der(Des3KeyFile), + erl_make_certs:pem_to_der(Des3KeyFile), Salt1 = crypto:strong_rand_bytes(8), Entry1 = public_key:pem_entry_encode('RSAPrivateKey', RSAKey, - {{"DES-CBC", Salt1}, "4567efgh"}), + {{"DES-CBC", Salt1}, ?PASSWORD2}), DesKeyFile = filename:join(Datadir, "des_client_key.pem"), erl_make_certs:der_to_pem(DesKeyFile, [Entry1]), - [{'RSAPrivateKey', _, {"DES-CBC", Salt1}} =Entry2] = - erl_make_certs:pem_to_der(DesKeyFile), + [{'RSAPrivateKey', _, {"DES-CBC", Salt1}} = Entry2] = + erl_make_certs:pem_to_der(DesKeyFile), {ok, Pem} = file:read_file(DesKeyFile), check_encapsulated_header(Pem), - true = check_entry_type(public_key:pem_entry_decode(Entry2, "4567efgh"), - 'RSAPrivateKey'). - + true = check_entry_type(public_key:pem_entry_decode(Entry2, Password2), + 'RSAPrivateKey'). + %%-------------------------------------------------------------------- dh_pem() -> @@ -783,7 +794,7 @@ pkix_path_validation(Config) when is_list(Config) -> % RsaPssKey = {public_key:generate_key({rsa, 1024, 65537}), pss_params(sha256)}, RsaPssKey = {hardcode_rsa_key(1), pss_params(sha256)}, - CaKPSS = {TrustedPSSCert,_} = erl_make_certs:make_cert([{key, RsaPssKey}, + _CaKPSS = {TrustedPSSCert,_} = erl_make_certs:make_cert([{key, RsaPssKey}, {subject, [ {name, "RSASSA-PSS Public Key"}, {?'id-at-name', {printableString, "public_key"}}, @@ -794,7 +805,7 @@ pkix_path_validation(Config) when is_list(Config) -> {org_unit, "testing dep"} ]} ]), - ChainPSSCert = {CertPSS, _} = erl_make_certs:make_cert([{issuer, {TrustedPSSCert,RsaPssKey}}]), + _ChainPSSCert = {CertPSS, _} = erl_make_certs:make_cert([{issuer, {TrustedPSSCert,RsaPssKey}}]), {ok, _} = public_key:pkix_path_validation(TrustedPSSCert, [CertPSS], []). pkix_path_validation_root_expired() -> diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index f75005e1ac..486e21d51e 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -358,11 +358,11 @@ <datatype> <name name="key_password"/> <desc> - <p>String containing the user's password. Only used if the + <p>String containing the user's password or a function returning same type. Only used if the private keyfile is password-protected.</p> </desc> </datatype> - + <datatype> <name name="cipher_suites"/> <desc> diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index d1ca621e22..d70df3c473 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -347,7 +347,7 @@ key_id := crypto:key_id(), password => crypto:password()}. % exported -type key_pem() :: file:filename(). --type key_password() :: string(). +-type key_password() :: string() | fun(() -> string()). -type cipher_suites() :: ciphers(). -type ciphers() :: [erl_cipher_suite()] | string(). % (according to old API) exported @@ -1736,6 +1736,12 @@ handle_option(padding_check = Option, Value0, #{versions := Versions} = Options assert_option_dependency(Option, versions, Versions, ['tlsv1']), Value = validate_option(Option, Value0), OptionsMap#{Option => Value}; +handle_option(password = Option, unbound, OptionsMap, #{rules := Rules}) -> + Value = validate_option(Option, default_value(Option, Rules)), + OptionsMap#{password => Value}; +handle_option(password = Option, Value0, OptionsMap, _Env) -> + Value = validate_option(Option, Value0), + OptionsMap#{password => Value}; handle_option(psk_identity = Option, unbound, OptionsMap, #{rules := Rules}) -> Value = validate_option(Option, default_value(Option, Rules)), OptionsMap#{Option => Value}; @@ -2283,6 +2289,9 @@ validate_option(partial_chain, Value, _) validate_option(password, Value, _) when is_list(Value) -> Value; +validate_option(password, Value, _) + when is_function(Value, 0) -> + Value; validate_option(protocol, Value = tls, _) -> Value; validate_option(protocol, Value = dtls, _) -> diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl index 89198eaa2b..80a5b4f44c 100644 --- a/lib/ssl/src/ssl_config.erl +++ b/lib/ssl/src/ssl_config.erl @@ -43,7 +43,7 @@ init(#{erl_dist := ErlDist, key := Key, keyfile := KeyFile, - password := Password, + password := Password, %% Can be fun() or string() dh := DH, dhfile := DHFile} = SslOpts, Role) -> diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index beabdcb8de..628e7119ba 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -157,6 +157,7 @@ ]). -export([make_rsa_cert/1, + make_rsa_cert_with_protected_keyfile/2, make_dsa_cert/1, make_ecdsa_cert/1, make_ecdh_rsa_cert/1, @@ -1764,7 +1765,7 @@ make_rsa_cert(Config) -> [{server_rsa_opts, [{reuseaddr, true} | ServerConf]}, {server_rsa_verify_opts, [{reuseaddr, true}, {verify, verify_peer} | ServerConf]}, {client_rsa_opts, ClientConf}, - {client_rsa_verify_opts, [{verify, verify_peer} |ClientConf]}, + {client_rsa_verify_opts, [{verify, verify_peer} |ClientConf]}, {server_rsa_der_opts, [{reuseaddr, true} | ServerDerConf]}, {server_rsa_der_verify_opts, [{reuseaddr, true}, {verify, verify_peer} | ServerDerConf]}, {client_rsa_der_opts, ClientDerConf}, @@ -1774,6 +1775,34 @@ make_rsa_cert(Config) -> Config end. +make_rsa_cert_with_protected_keyfile(Config0, Password) -> + Config1 = make_rsa_cert(Config0), + + ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config1), + [PemEntry] = pem_to_der(proplists:get_value(keyfile, ClientOpts)), + ASN1OctetStrTag = 4, + IV = <<4,8,154,8,95,192,188,232,4,8,154,8,95,192,188,232>>, + Length = <<16:8/unsigned-big-integer>>, + Params = {"AES-256-CBC", + {'PBES2-params', + {'PBES2-params_keyDerivationFunc', + ?'id-PBKDF2', + {'PBKDF2-params', + {specified, <<125,96,67,95,2,233,224,174>>}, + 2048,asn1_NOVALUE, + {'PBKDF2-params_prf', ?'id-hmacWithSHA1','NULL'}}}, + {'PBES2-params_encryptionScheme', + ?'id-aes256-CBC', + {asn1_OPENTYPE, <<ASN1OctetStrTag, Length/binary, IV/binary>>}}}}, + ProtectedPemEntry = public_key:pem_entry_encode( + 'PrivateKeyInfo',public_key:pem_entry_decode(PemEntry), + {Params, Password}), + ProtectedClientKeyFile = filename:join(proplists:get_value(priv_dir,Config1), + "tls_password_client.pem"), + der_to_pem(ProtectedClientKeyFile, [ProtectedPemEntry]), + ProtectedClientOpts = [{keyfile,ProtectedClientKeyFile} | proplists:delete(keyfile, ClientOpts)], + [{client_protected_rsa_opts, ProtectedClientOpts} | Config1]. + make_rsa_1024_cert(Config) -> CryptoSupport = crypto:supports(), case proplists:get_bool(rsa, proplists:get_value(public_keys, CryptoSupport)) of @@ -1994,6 +2023,7 @@ run_server_error(Opts) -> Pid = proplists:get_value(from, Opts), Transport = proplists:get_value(transport, Opts, ssl), ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, Options]), + Timeout = proplists:get_value(timeout, Opts, infinity), case Transport:listen(Port, Options) of {ok, #sslsocket{} = ListenSocket} -> %% To make sure error_client will @@ -2001,7 +2031,7 @@ run_server_error(Opts) -> Pid ! {listen, up}, send_selected_port(Pid, Port, ListenSocket), ct:log("~p:~p~nssl:transport_accept(~p)~n", [?MODULE,?LINE, ListenSocket]), - case Transport:transport_accept(ListenSocket) of + case Transport:transport_accept(ListenSocket, Timeout) of {error, _} = Error -> Pid ! {self(), Error}; {ok, AcceptSocket} -> diff --git a/lib/ssl/test/tls_api_SUITE.erl b/lib/ssl/test/tls_api_SUITE.erl index e2e1629336..7acf0e19f7 100644 --- a/lib/ssl/test/tls_api_SUITE.erl +++ b/lib/ssl/test/tls_api_SUITE.erl @@ -22,6 +22,7 @@ -module(tls_api_SUITE). -include_lib("common_test/include/ct.hrl"). +-include_lib("public_key/include/public_key.hrl"). -include_lib("ssl/src/ssl_record.hrl"). -include_lib("ssl/src/ssl_internal.hrl"). -include_lib("ssl/src/ssl_api.hrl"). @@ -42,7 +43,7 @@ -export([tls_upgrade/0, tls_upgrade/1, tls_upgrade_new_opts/0, - tls_upgrade_new_opts/1, + tls_upgrade_new_opts/1, tls_upgrade_with_timeout/0, tls_upgrade_with_timeout/1, tls_upgrade_with_client_timeout/0, @@ -59,6 +60,12 @@ tls_client_closes_socket/1, tls_closed_in_active_once/0, tls_closed_in_active_once/1, + tls_password_incorrect/0, + tls_password_incorrect/1, + tls_password_correct/0, + tls_password_correct/1, + tls_password_badarg/0, + tls_password_badarg/1, tls_reset_in_active_once/0, tls_reset_in_active_once/1, tls_tcp_msg/0, @@ -101,6 +108,9 @@ ]). -define(SLEEP, 500). +-define(CORRECT_PASSWORD, "hello test"). +-define(INCORRECT_PASSWORD, "hello"). +-define(BADARG_PASSWORD, hello). %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- @@ -132,6 +142,9 @@ api_tests() -> tls_shutdown_write, tls_shutdown_both, tls_shutdown_error, + tls_password_correct, + tls_password_incorrect, + tls_password_badarg, tls_client_closes_socket, tls_closed_in_active_once, tls_reset_in_active_once, @@ -155,7 +168,8 @@ init_per_suite(Config0) -> try crypto:start() of ok -> ssl_test_lib:clean_start(), - ssl_test_lib:make_rsa_cert(Config0) + ssl_test_lib:make_rsa_cert_with_protected_keyfile(Config0, + ?CORRECT_PASSWORD) catch _:_ -> {skip, "Crypto did not start"} end. @@ -166,7 +180,7 @@ end_per_suite(_Config) -> application:stop(crypto). init_per_group(GroupName, Config) -> - ssl_test_lib:init_per_group(GroupName, Config). + ssl_test_lib:init_per_group(GroupName, Config). end_per_group(GroupName, Config) -> ssl_test_lib:end_per_group(GroupName, Config). @@ -178,7 +192,7 @@ init_per_testcase(Testcase, Config) when Testcase == tls_server_handshake_timeou init_per_testcase(_, Config) -> ct:timetrap({seconds, 5}), Config. -end_per_testcase(_TestCase, Config) -> +end_per_testcase(_TestCase, Config) -> Config. %%-------------------------------------------------------------------- @@ -193,28 +207,28 @@ tls_upgrade(Config) when is_list(Config) -> {ClientNode, 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()}, - {mfa, {?MODULE, + Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, upgrade_result, []}}, - {tcp_options, + {tcp_options, [{active, false} | TcpOpts]}, {ssl_options, [{verify, verify_peer} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_upgrade_client([{node, ClientNode}, - {port, Port}, + Client = ssl_test_lib:start_upgrade_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {?MODULE, upgrade_result, []}}, {tcp_options, [binary]}, {ssl_options, [{verify, verify_peer}, {server_name_indication, Hostname} | ClientOpts]}]), - + ct:log("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). @@ -228,30 +242,30 @@ tls_upgrade_new_opts(Config) when is_list(Config) -> {ClientNode, 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()}, - {mfa, {?MODULE, + Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, upgrade_result_new_opts, []}}, - {tcp_options, + {tcp_options, [{active, false} | TcpOpts]}, {ssl_options, [{verify, verify_peer}, {mode, list} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_upgrade_client([{node, ClientNode}, - {port, Port}, + Client = ssl_test_lib:start_upgrade_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {?MODULE, upgrade_result_new_opts, []}}, {tcp_options, [binary]}, {ssl_options, [{verify, verify_peer}, {mode, list}, {server_name_indication, Hostname} | ClientOpts]}]), - + ct:log("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). @@ -265,29 +279,29 @@ tls_upgrade_with_timeout(Config) when is_list(Config) -> {ClientNode, 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()}, + Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0}, + {from, self()}, {timeout, 5000}, - {mfa, {?MODULE, + {mfa, {?MODULE, upgrade_result, []}}, - {tcp_options, + {tcp_options, [{active, false} | TcpOpts]}, {ssl_options, [{verify, verify_peer} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_upgrade_client([{node, ClientNode}, - {port, Port}, + Client = ssl_test_lib:start_upgrade_client([{node, ClientNode}, + {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {?MODULE, upgrade_result, []}}, {tcp_options, TcpOpts}, {ssl_options, [{verify, verify_peer}, {server_name_indication, Hostname} | ClientOpts]}]), - + ct:log("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). @@ -297,7 +311,7 @@ tls_downgrade() -> tls_downgrade(Config) when is_list(Config) -> ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), - + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, @@ -310,7 +324,7 @@ tls_downgrade(Config) when is_list(Config) -> {from, self()}, {mfa, {?MODULE, tls_downgrade_result, [self()]}}, {options, [{active, false}, {verify, verify_peer} | ClientOpts]}]), - + ssl_test_lib:check_result(Server, ready, Client, ready), Server ! go, @@ -328,23 +342,23 @@ tls_shutdown(Config) when is_list(Config) -> ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, {mfa, {?MODULE, tls_shutdown_result, [server]}}, {options, [{exit_on_close, false}, {active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, - {mfa, + {from, self()}, + {mfa, {?MODULE, tls_shutdown_result, [client]}}, - {options, + {options, [{exit_on_close, false}, {active, false} | ClientOpts]}]), - + ssl_test_lib:check_result(Server, ok, Client, ok), - + ssl_test_lib:close(Server), ssl_test_lib:close(Client). @@ -355,17 +369,17 @@ tls_shutdown_write(Config) when is_list(Config) -> ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, {mfa, {?MODULE, tls_shutdown_write_result, [server]}}, {options, [{active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {?MODULE, tls_shutdown_write_result, [client]}}, {options, [{active, false} | ClientOpts]}]), - + ssl_test_lib:check_result(Server, ok, Client, {error, closed}). %%-------------------------------------------------------------------- @@ -375,17 +389,17 @@ tls_shutdown_both(Config) when is_list(Config) -> ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, {mfa, {?MODULE, tls_shutdown_both_result, [server]}}, {options, [{active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {?MODULE, tls_shutdown_both_result, [client]}}, {options, [{active, false} | ClientOpts]}]), - + ssl_test_lib:check_result(Server, ok, Client, {error, closed}). %%-------------------------------------------------------------------- @@ -403,25 +417,25 @@ tls_shutdown_error(Config) when is_list(Config) -> tls_client_closes_socket() -> [{doc,"Test what happens when client closes socket before handshake is completed"}]. -tls_client_closes_socket(Config) when is_list(Config) -> +tls_client_closes_socket(Config) when is_list(Config) -> ServerOpts = ssl_test_lib:ssl_options(server_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), TcpOpts = [binary, {reuseaddr, true}], - - Server = ssl_test_lib:start_upgrade_server_error([{node, ServerNode}, {port, 0}, - {from, self()}, + + Server = ssl_test_lib:start_upgrade_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, {tcp_options, TcpOpts}, {ssl_options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), Connect = fun() -> - {ok, _Socket} = rpc:call(ClientNode, gen_tcp, connect, - [Hostname, Port, [binary]]), - %% Make sure that ssl_accept is called before + {ok, _Socket} = rpc:call(ClientNode, gen_tcp, connect, + [Hostname, Port, [binary]]), + %% Make sure that ssl_accept is called before %% client process ends and closes socket. ct:sleep(?SLEEP) end, - + _Client = spawn_link(Connect), ssl_test_lib:check_result(Server, {error,closed}). @@ -460,7 +474,7 @@ tls_reset_in_active_once(Config) when is_list(Config) -> %%-------------------------------------------------------------------- tls_closed_in_active_once() -> [{doc, "Test that active once can be used to deliver not only all data" - " but even the close message, see ERL-1409, in normal operation." + " but even the close message, see ERL-1409, in normal operation." " This is also test, with slightly different circumstances in" " the old tls_closed_in_active_once test" " renamed tls_reset_in_active_once"}]. @@ -560,9 +574,9 @@ tls_tcp_msg(Config) when is_list(Config) -> ct:log("Testcase ~p connected to Server ~p ~n", [self(), Server]), gen_tcp:send(Socket, "<SOME GARBLED NON SSL MESSAGE>"), - receive + receive {tcp_closed, Socket} -> - receive + receive {Server, {error, Error}} -> ct:log("Error ~p", [Error]) end @@ -600,7 +614,7 @@ tls_tcp_msg_big(Config) when is_list(Config) -> {Server, {error, Error}} -> ct:log("Error ~p", [Error]); {'EXIT', Server, _} -> - ok + ok end end. @@ -619,7 +633,7 @@ tls_dont_crash_on_handshake_garbage(Config) -> {mfa, ssl_test_lib, no_result}, {options, [{versions, [Version]} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - + {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {active, false}]), %% Send hello and garbage record @@ -639,7 +653,7 @@ tls_dont_crash_on_handshake_garbage(Config) -> _ -> ssl_test_lib:check_server_alert(Server, handshake_failure) end. - + %%-------------------------------------------------------------------- tls_tcp_error_propagation_in_active_mode() -> [{doc,"Test that process receives {ssl_error, Socket, closed} when tcp error ocurres"}]. @@ -660,7 +674,7 @@ tls_tcp_error_propagation_in_active_mode(Config) when is_list(Config) -> {from, self()}, {mfa, {?MODULE, receive_msg, []}}, {options, ClientOpts}]), - + {status, _, _, StatusInfo} = sys:get_status(Pid), [_, _,_, _, Prop] = StatusInfo, State = ssl_test_lib:state(Prop), @@ -675,21 +689,21 @@ tls_tcp_error_propagation_in_active_mode(Config) when is_list(Config) -> peername() -> [{doc,"Test API function peername/1"}]. -peername(Config) when is_list(Config) -> +peername(Config) when is_list(Config) -> ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, {mfa, {ssl, peername, []}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {ssl, peername, []}}, {options, [{port, 0} | ClientOpts]}]), - + ClientPort = ssl_test_lib:inet_port(Client), ServerIp = ssl_test_lib:node_to_hostip(ServerNode, server), ClientIp = ssl_test_lib:node_to_hostip(ClientNode, client), @@ -700,39 +714,39 @@ peername(Config) when is_list(Config) -> [self(), Client, Server]), ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg), - + ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- sockname() -> [{doc,"Test API function sockname/1"}]. -sockname(Config) when is_list(Config) -> +sockname(Config) when is_list(Config) -> ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, {mfa, {ssl, sockname, []}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {ssl, sockname, []}}, {options, [{port, 0} | ClientOpts]}]), - + ClientPort = ssl_test_lib:inet_port(Client), ServerIp = ssl_test_lib:node_to_hostip(ServerNode, server), ClientIp = ssl_test_lib:node_to_hostip(ClientNode, client), ServerMsg = {ok, {ServerIp, Port}}, ClientMsg = {ok, {ClientIp, ClientPort}}, - + ct:log("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), - + ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg), - + ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- @@ -759,7 +773,7 @@ tls_server_handshake_timeout(Config) -> {'EXIT', Server, _} -> %% Make sure supervisor had time to react on process exit %% Could we come up with a better solution to this? - ct:sleep(500), + ct:sleep(500), [] = supervisor:which_children(tls_connection_sup) end end. @@ -767,26 +781,26 @@ tls_server_handshake_timeout(Config) -> %%-------------------------------------------------------------------- transport_close() -> [{doc, "Test what happens if socket is closed on TCP level after a while of normal operation"}]. -transport_close(Config) when is_list(Config) -> +transport_close(Config) when is_list(Config) -> ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = - ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), - {ok, TcpS} = rpc:call(ClientNode, gen_tcp, connect, + {ok, TcpS} = rpc:call(ClientNode, gen_tcp, connect, [Hostname,Port,[binary, {active, false}]]), - {ok, SslS} = rpc:call(ClientNode, ssl, connect, + {ok, SslS} = rpc:call(ClientNode, ssl, connect, [TcpS,[{active, false}|ClientOpts]]), - + ct:log("Testcase ~p, Client ~p Server ~p ~n", [self(), self(), Server]), - ok = ssl:send(SslS, "Hello world"), - {ok,<<"Hello world">>} = ssl:recv(SslS, 11), - gen_tcp:close(TcpS), + ok = ssl:send(SslS, "Hello world"), + {ok,<<"Hello world">>} = ssl:recv(SslS, 11), + gen_tcp:close(TcpS), {error, _} = ssl:send(SslS, "Hello world"). %%-------------------------------------------------------------------- @@ -856,36 +870,36 @@ check_connection_processes(Sup, N, M) -> emulated_options() -> [{doc,"Test API function getopts/2 and setopts/2"}]. -emulated_options(Config) when is_list(Config) -> +emulated_options(Config) when is_list(Config) -> ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), Values = [{mode, list}, {packet, 0}, {header, 0}, - {active, true}], - %% Shall be the reverse order of Values! + {active, true}], + %% Shall be the reverse order of Values! Options = [active, header, packet, mode], - + NewValues = [{mode, binary}, {active, once}], - %% Shall be the reverse order of NewValues! + %% Shall be the reverse order of NewValues! NewOptions = [active, mode], - - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, tls_socket_options_result, + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, tls_socket_options_result, [Options, Values, NewOptions, NewValues]}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, tls_socket_options_result, + {from, self()}, + {mfa, {?MODULE, tls_socket_options_result, [Options, Values, NewOptions, NewValues]}}, {options, ClientOpts}]), - + ssl_test_lib:check_result(Server, ok, Client, ok), ssl_test_lib:close(Server), - + {ok, Listen} = ssl:listen(0, ServerOpts), {ok,[{mode,list}]} = ssl:getopts(Listen, [mode]), ok = ssl:setopts(Listen, [{mode, binary}]), @@ -896,40 +910,40 @@ accept_pool() -> [{doc,"Test having an accept pool."}]. accept_pool(Config) when is_list(Config) -> ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config), - ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server0 = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, + Server0 = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, {accepters, 3}, {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server0), [Server1, Server2] = ssl_test_lib:accepters(2), - Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, ClientOpts} ]), - - Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + + Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, ClientOpts} ]), - - Client2 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + + Client2 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, ClientOpts} ]), ssl_test_lib:check_ok([Server0, Server1, Server2, Client0, Client1, Client2]), - + ssl_test_lib:close(Server0), ssl_test_lib:close(Server1), ssl_test_lib:close(Server2), @@ -959,7 +973,7 @@ reuseaddr(Config) when is_list(Config) -> {options, [{active, false} | ClientOpts]}]), ssl_test_lib:close(Server), ssl_test_lib:close(Client), - + Server1 = ssl_test_lib:start_server([{node, ServerNode}, {port, Port}, {from, self()}, @@ -976,6 +990,104 @@ reuseaddr(Config) when is_list(Config) -> ssl_test_lib:close(Server1), ssl_test_lib:close(Client1). +%%-------------------------------------------------------------------- +tls_password_correct() -> + [{doc, "Test that connection is possible with a correct password"}]. +tls_password_correct(Config) when is_list(Config) -> + F = fun (P) -> + ProtectedClientOpts = ?config(client_protected_rsa_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_rsa_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, tls_shutdown_result, [server]}}, + {options, [{exit_on_close, false}, + {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, tls_shutdown_result, [client]}}, + {options, + [{exit_on_close, false}, + {verify, verify_none}, + {active, false}, + {password, P} | ProtectedClientOpts]}]), + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client) + end, + F(?CORRECT_PASSWORD), + F(fun() -> ?CORRECT_PASSWORD end). + +%%-------------------------------------------------------------------- +tls_password_incorrect() -> + [{doc, "Test that connection is not possible with wrong password"}]. +tls_password_incorrect(Config) when is_list(Config) -> + F = fun (P) -> + ProtectedClientOpts = ?config(client_protected_rsa_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_rsa_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, ssl_test_lib, 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, ssl_test_lib, no_result}, + {options, + [{active, false}, + {verify, verify_none}, + {password, P} | ProtectedClientOpts]}]), + Results = ssl_test_lib:get_result([Server, Client]), + Pred = fun({Pid, {error, closed}}) -> + Server == Pid; + ({Pid, {error, {options, {keyfile, _, {error, _}}}}}) -> + Client == Pid; + (_) -> false + end, + true = lists:all(Pred, Results) + end, + F(?INCORRECT_PASSWORD), + F(fun() -> ?INCORRECT_PASSWORD end). + +%%-------------------------------------------------------------------- +tls_password_badarg() -> + [{doc, "Test that connection is not possible with badarg password"}]. +tls_password_badarg(Config) when is_list(Config) -> + F = fun (P, ServerError, ClientError) -> + ProtectedClientOpts = ?config(client_protected_rsa_opts, Config), + ServerOpts = ssl_test_lib:ssl_options(server_rsa_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, ssl_test_lib, no_result}, + {timeout, 100}, + {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, ssl_test_lib, no_result}, + {options, + [{active, false}, + {verify, verify_none}, + {password, P} | ProtectedClientOpts]}]), + ssl_test_lib:check_result(Server, ServerError, Client, ClientError) + end, + %% {options error comes from ssl app + F(?BADARG_PASSWORD, {error, timeout}, + {error, {options, {password, ?BADARG_PASSWORD}}}), + %% {keyfile, badarg} error comes from crypto:macN, also handhsake is initiated + %% so different server error is observed + F(fun() -> ?BADARG_PASSWORD end, {error, closed}, + {error, {keyfile,badarg}}). + %%-------------------------------------------------------------------- %% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- @@ -991,7 +1103,7 @@ upgrade_result(Socket) -> upgrade_result_new_opts(Socket) -> ssl:setopts(Socket, [{active, true}]), ok = ssl:send(Socket, "Hello world"), - %% Make sure list option set in ssl:connect/handskae overrides + %% Make sure list option set in ssl:connect/handshake overrides %% previous gen_tcp socket option that was set to binary. "Hello world" = ssl_test_lib:active_recv(Socket, length("Hello world")), ok. @@ -999,7 +1111,7 @@ upgrade_result_new_opts(Socket) -> tls_downgrade_result(Socket, Pid) -> ok = ssl_test_lib:send_recv_result(Socket), Pid ! {self(), ready}, - receive + receive go -> ok end, @@ -1062,20 +1174,20 @@ receive_msg(_) -> Msg -> Msg end. - + tls_socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) -> %% Test get/set emulated opts - {ok, DefaultValues} = ssl:getopts(Socket, Options), + {ok, DefaultValues} = ssl:getopts(Socket, Options), ssl:setopts(Socket, NewValues), {ok, NewValues} = ssl:getopts(Socket, NewOptions), %% Test get/set inet opts - {ok,[{nodelay,false}]} = ssl:getopts(Socket, [nodelay]), + {ok,[{nodelay,false}]} = ssl:getopts(Socket, [nodelay]), ssl:setopts(Socket, [{nodelay, true}]), {ok,[{nodelay, true}]} = ssl:getopts(Socket, [nodelay]), {ok, All} = ssl:getopts(Socket, []), ct:log("All opts ~p~n", [All]), ok. - + active_tcp_recv(Socket, N) -> active_tcp_recv(Socket, N, []). -- 2.31.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor