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