aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/doc/src/book.xml2
-rw-r--r--lib/ssl/doc/src/notes.xml31
-rw-r--r--lib/ssl/doc/src/ssl.xml7
-rw-r--r--lib/ssl/doc/src/using_ssl.xml2
-rw-r--r--lib/ssl/src/inet_ssl_dist.erl29
-rw-r--r--lib/ssl/src/ssl.appup.src2
-rw-r--r--lib/ssl/src/ssl.erl37
-rw-r--r--lib/ssl/src/ssl_app.erl2
-rw-r--r--lib/ssl/src/ssl_connection.erl94
-rw-r--r--lib/ssl/src/ssl_handshake.hrl5
-rw-r--r--lib/ssl/src/ssl_internal.hrl6
-rw-r--r--lib/ssl/test/Makefile5
-rw-r--r--lib/ssl/test/make_certs.erl2
-rw-r--r--lib/ssl/test/old_ssl_active_SUITE.erl84
-rw-r--r--lib/ssl/test/old_ssl_active_once_SUITE.erl86
-rw-r--r--lib/ssl/test/old_ssl_dist_SUITE.erl34
-rw-r--r--lib/ssl/test/old_ssl_misc_SUITE.erl70
-rw-r--r--lib/ssl/test/old_ssl_passive_SUITE.erl84
-rw-r--r--lib/ssl/test/old_ssl_peer_cert_SUITE.erl73
-rw-r--r--lib/ssl/test/old_ssl_protocol_SUITE.erl70
-rw-r--r--lib/ssl/test/old_ssl_verify_SUITE.erl70
-rw-r--r--lib/ssl/test/old_transport_accept_SUITE.erl39
-rw-r--r--lib/ssl/test/ssl.cover36
-rw-r--r--lib/ssl/test/ssl.spec2
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl325
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl96
-rw-r--r--lib/ssl/test/ssl_payload_SUITE.erl50
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl27
-rw-r--r--lib/ssl/test/ssl_test_lib.erl14
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl38
-rw-r--r--lib/ssl/vsn.mk3
31 files changed, 930 insertions, 495 deletions
diff --git a/lib/ssl/doc/src/book.xml b/lib/ssl/doc/src/book.xml
index 85d6b56b26..ecfb915b44 100644
--- a/lib/ssl/doc/src/book.xml
+++ b/lib/ssl/doc/src/book.xml
@@ -4,7 +4,7 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>1999</year><year>2009</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 8f81ccb567..52ee9c086a 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1999</year><year>2010</year>
+ <year>1999</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,7 +31,34 @@
<p>This document describes the changes made to the SSL application.
</p>
- <section><title>SSL 4.1.3</title>
+ <section><title>SSL 4.1.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Reduced memory footprint of an ssl connection.</p>
+ <p>
+ Handshake hashes, premaster secret and "public_key_info"
+ does not need to be saved when the connection has been
+ established. The own certificate is no longer duplicated
+ in the state.</p>
+ <p>
+ Own Id: OTP-9021</p>
+ </item>
+ <item>
+ <p>
+ Add the option {hibernate_after, int()} to ssl:connect
+ and ssl:listen</p>
+ <p>
+ Own Id: OTP-9106</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 4.1.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index daf7b77527..cd5c9281cd 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -269,6 +269,13 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<p> {bad_cert, cert_expired}, {bad_cert, invalid_issuer}, {bad_cert, invalid_signature}, {bad_cert, unknown_ca}, {bad_cert, name_not_permitted}, {bad_cert, missing_basic_constraint}, {bad_cert, invalid_key_usage}</p>
</item>
+ <tag>{hibernate_after, integer()|undefined}</tag>
+ <item>When an integer-value is specified, the <code>ssl_connection</code>
+ will go into hibernation after the specified number of milliseconds
+ of inactivity, thus reducing its memory footprint. When
+ <code>undefined</code> is specified (this is the default), the process
+ will never go into hibernation.
+ </item>
</taglist>
</section>
diff --git a/lib/ssl/doc/src/using_ssl.xml b/lib/ssl/doc/src/using_ssl.xml
index 4bdd8f97b4..605290b6f9 100644
--- a/lib/ssl/doc/src/using_ssl.xml
+++ b/lib/ssl/doc/src/using_ssl.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2011</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/ssl/src/inet_ssl_dist.erl b/lib/ssl/src/inet_ssl_dist.erl
index f62aefd35a..6c0fbc0618 100644
--- a/lib/ssl/src/inet_ssl_dist.erl
+++ b/lib/ssl/src/inet_ssl_dist.erl
@@ -1,8 +1,8 @@
-%%<copyright>
-%% <year>2000-2008</year>
-%% <holder>Ericsson AB, All Rights Reserved</holder>
-%%</copyright>
-%%<legalnotice>
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
@@ -14,8 +14,9 @@
%% the License for the specific language governing rights and limitations
%% under the License.
%%
-%% The Initial Developer of the Original Code is Ericsson AB.
-%%</legalnotice>
+%% %CopyrightEnd%
+%%
+
%%
-module(inet_ssl_dist).
@@ -135,6 +136,9 @@ accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
[self(), AcceptPid, Socket, MyNode,
Allowed, SetupTime]).
+%% Suppress dialyzer warning, we do not really care about old ssl code
+%% as we intend to remove it.
+-spec(do_accept(_,_,_,_,_,_) -> no_return()).
do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
process_flag(priority, max),
receive
@@ -167,8 +171,8 @@ do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
ssl_prim:getll(S)
end,
f_address = fun get_remote_id/2,
- mf_tick = {?MODULE, tick},
- mf_getstat = {?MODULE,getstat}
+ mf_tick = fun ?MODULE:tick/1,
+ mf_getstat = fun ?MODULE:getstat/1
},
dist_util:handshake_other_started(HSData);
{false,IP} ->
@@ -204,6 +208,9 @@ setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
LongOrShortNames,
SetupTime]).
+%% Suppress dialyzer warning, we do not really care about old ssl code
+%% as we intend to remove it.
+-spec(do_setup(_,_,_,_,_,_) -> no_return()).
do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
process_flag(priority, max),
?trace("~p~n",[{inet_ssl_dist,self(),setup,Node}]),
@@ -258,8 +265,8 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
protocol = ssl,
family = inet}
end,
- mf_tick = {?MODULE, tick},
- mf_getstat = {?MODULE,getstat},
+ mf_tick = fun ?MODULE:tick/1,
+ mf_getstat = fun ?MODULE:getstat/1,
request_type = Type
},
dist_util:handshake_we_started(HSData);
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index e6a8c557fc..d3e426f254 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,12 +1,14 @@
%% -*- erlang -*-
{"%VSN%",
[
+ {"4.1.3", [{restart_application, ssl}]},
{"4.1.2", [{restart_application, ssl}]},
{"4.1.1", [{restart_application, ssl}]},
{"4.1", [{restart_application, ssl}]},
{"4.0.1", [{restart_application, ssl}]}
],
[
+ {"4.1.3", [{restart_application, ssl}]},
{"4.1.2", [{restart_application, ssl}]},
{"4.1.1", [{restart_application, ssl}]},
{"4.1", [{restart_application, ssl}]},
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 0e108c430f..7b1fda4cf9 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -52,15 +52,14 @@
-type option() :: socketoption() | ssloption() | transportoption().
-type socketoption() :: [{property(), term()}]. %% See gen_tcp and inet
-type property() :: atom().
-
-type ssloption() :: {verify, verify_type()} |
{verify_fun, {fun(), InitialUserState::term()}} |
{fail_if_no_peer_cert, boolean()} | {depth, integer()} |
- {cert, der_encoded()} | {certfile, path()} | {key, der_encoded()} |
- {keyfile, path()} | {password, string()} | {cacerts, [der_encoded()]} |
- {cacertfile, path()} | {dh, der_encoded()} | {dhfile, path()} |
+ {cert, Der::binary()} | {certfile, path()} | {key, Der::binary()} |
+ {keyfile, path()} | {password, string()} | {cacerts, [Der::binary()]} |
+ {cacertfile, path()} | {dh, Der::binary()} | {dhfile, path()} |
{ciphers, ciphers()} | {ssl_imp, ssl_imp()} | {reuse_sessions, boolean()} |
- {reuse_session, fun()}.
+ {reuse_session, fun()} | {hibernate_after, integer()|undefined}.
-type verify_type() :: verify_none | verify_peer.
-type path() :: string().
@@ -72,8 +71,8 @@
%%--------------------------------------------------------------------
--spec start() -> ok.
--spec start(permanent | transient | temporary) -> ok.
+-spec start() -> ok | {error, reason()}.
+-spec start(permanent | transient | temporary) -> ok | {error, reason()}.
%%
%% Description: Utility function that starts the ssl,
%% crypto and public_key applications. Default type
@@ -98,9 +97,12 @@ stop() ->
application:stop(ssl).
%%--------------------------------------------------------------------
--spec connect(host() | port(), [option()]) -> {ok, #sslsocket{}}.
--spec connect(host() | port(), [option()] | port_num(), timeout() | list()) -> {ok, #sslsocket{}}.
--spec connect(host() | port(), port_num(), list(), timeout()) -> {ok, #sslsocket{}}.
+-spec connect(host() | port(), [option()]) -> {ok, #sslsocket{}} |
+ {error, reason()}.
+-spec connect(host() | port(), [option()] | port_num(), timeout() | list()) ->
+ {ok, #sslsocket{}} | {error, reason()}.
+-spec connect(host() | port(), port_num(), list(), timeout()) ->
+ {ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Connect to a ssl server.
@@ -171,8 +173,10 @@ listen(Port, Options0) ->
end.
%%--------------------------------------------------------------------
--spec transport_accept(#sslsocket{}) -> {ok, #sslsocket{}}.
--spec transport_accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}}.
+-spec transport_accept(#sslsocket{}) -> {ok, #sslsocket{}} |
+ {error, reason()}.
+-spec transport_accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
+ {error, reason()}.
%%
%% Description: Performs transport accept on a ssl listen socket
%%--------------------------------------------------------------------
@@ -706,7 +710,8 @@ handle_options(Opts0, _Role) ->
reuse_sessions = handle_option(reuse_sessions, Opts, true),
secure_renegotiate = handle_option(secure_renegotiate, Opts, false),
renegotiate_at = handle_option(renegotiate_at, Opts, ?DEFAULT_RENEGOTIATE_AT),
- debug = handle_option(debug, Opts, [])
+ debug = handle_option(debug, Opts, []),
+ hibernate_after = handle_option(hibernate_after, Opts, undefined)
},
CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed, tcp_error}),
@@ -715,7 +720,7 @@ handle_options(Opts0, _Role) ->
depth, cert, certfile, key, keyfile,
password, cacerts, cacertfile, dh, dhfile, ciphers,
debug, reuse_session, reuse_sessions, ssl_imp,
- cb_info, renegotiate_at, secure_renegotiate],
+ cb_info, renegotiate_at, secure_renegotiate, hibernate_after],
SockOpts = lists:foldl(fun(Key, PropList) ->
proplists:delete(Key, PropList)
@@ -822,6 +827,10 @@ validate_option(renegotiate_at, Value) when is_integer(Value) ->
validate_option(debug, Value) when is_list(Value); Value == true ->
Value;
+validate_option(hibernate_after, undefined) ->
+ undefined;
+validate_option(hibernate_after, Value) when is_integer(Value), Value >= 0 ->
+ Value;
validate_option(Opt, Value) ->
throw({error, {eoptions, {Opt, Value}}}).
diff --git a/lib/ssl/src/ssl_app.erl b/lib/ssl/src/ssl_app.erl
index 8d50fd7bdb..c9f81726b9 100644
--- a/lib/ssl/src/ssl_app.erl
+++ b/lib/ssl/src/ssl_app.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 489895cf29..574e1e9468 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -289,9 +289,9 @@ start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
%% gen_fsm callbacks
%%====================================================================
%%--------------------------------------------------------------------
--spec init(list()) -> {ok, state_name(), #state{}} | {stop, term()}.
+-spec init(list()) -> {ok, state_name(), #state{}, timeout()} | {stop, term()}.
%% Possible return values not used now.
-%% | {ok, state_name(), #state{}, timeout()} |
+%% | {ok, state_name(), #state{}} |
%% ignore
%% Description:Whenever a gen_fsm is started using gen_fsm:start/[3,4] or
%% gen_fsm:start_link/3,4, this function is called by the new process to
@@ -311,7 +311,7 @@ init([Role, Host, Port, Socket, {SSLOpts0, _} = Options,
session_cache = CacheRef,
private_key = Key,
diffie_hellman_params = DHParams},
- {ok, hello, State}
+ {ok, hello, State, get_timeout(State)}
catch
throw:Error ->
{stop, Error}
@@ -412,6 +412,9 @@ hello(Hello = #client_hello{client_version = ClientVersion},
{stop, normal, State}
end;
+hello(timeout, State) ->
+ { next_state, hello, State, hibernate };
+
hello(Msg, State) ->
handle_unexpected_message(Msg, hello, State).
%%--------------------------------------------------------------------
@@ -460,6 +463,9 @@ abbreviated(#finished{verify_data = Data} = Finished,
{stop, normal, State}
end;
+abbreviated(timeout, State) ->
+ { next_state, abbreviated, State, hibernate };
+
abbreviated(Msg, State) ->
handle_unexpected_message(Msg, abbreviated, State).
@@ -582,6 +588,9 @@ certify(#client_key_exchange{exchange_keys = Keys},
{stop, normal, State}
end;
+certify(timeout, State) ->
+ { next_state, certify, State, hibernate };
+
certify(Msg, State) ->
handle_unexpected_message(Msg, certify, State).
@@ -664,6 +673,9 @@ cipher(#finished{verify_data = Data} = Finished,
{stop, normal, State}
end;
+cipher(timeout, State) ->
+ { next_state, cipher, State, hibernate };
+
cipher(Msg, State) ->
handle_unexpected_message(Msg, cipher, State).
@@ -693,6 +705,9 @@ connection(#hello_request{}, #state{host = Host, port = Port,
connection(#client_hello{} = Hello, #state{role = server} = State) ->
hello(Hello, State);
+connection(timeout, State) ->
+ {next_state, connection, State, hibernate};
+
connection(Msg, State) ->
handle_unexpected_message(Msg, connection, State).
%%--------------------------------------------------------------------
@@ -705,7 +720,7 @@ connection(Msg, State) ->
%% the event. Not currently used!
%%--------------------------------------------------------------------
handle_event(_Event, StateName, State) ->
- {next_state, StateName, State}.
+ {next_state, StateName, State, get_timeout(State)}.
%%--------------------------------------------------------------------
-spec handle_sync_event(term(), from(), state_name(), #state{}) ->
@@ -736,7 +751,8 @@ handle_sync_event({application_data, Data0}, From, connection,
{Msgs, [], ConnectionStates} ->
Result = Transport:send(Socket, Msgs),
{reply, Result,
- connection, State#state{connection_states = ConnectionStates}};
+ connection, State#state{connection_states = ConnectionStates},
+ get_timeout(State)};
{Msgs, RestData, ConnectionStates} ->
if
Msgs =/= [] ->
@@ -749,12 +765,14 @@ handle_sync_event({application_data, Data0}, From, connection,
renegotiation = {true, internal}})
end
catch throw:Error ->
- {reply, Error, connection, State}
+ {reply, Error, connection, State, get_timeout(State)}
end;
handle_sync_event({application_data, Data}, From, StateName,
#state{send_queue = Queue} = State) ->
%% In renegotiation priorities handshake, send data when handshake is finished
- {next_state, StateName, State#state{send_queue = queue:in({From, Data}, Queue)}};
+ {next_state, StateName,
+ State#state{send_queue = queue:in({From, Data}, Queue)},
+ get_timeout(State)};
handle_sync_event(start, From, hello, State) ->
hello(start, State#state{from = From});
@@ -768,9 +786,9 @@ handle_sync_event(start, From, hello, State) ->
%% here to make sure it is the users problem and not owers if
%% they upgrade a active socket.
handle_sync_event(start, _, connection, State) ->
- {reply, connected, connection, State};
+ {reply, connected, connection, State, get_timeout(State)};
handle_sync_event(start, From, StateName, State) ->
- {next_state, StateName, State#state{from = From}};
+ {next_state, StateName, State#state{from = From}, get_timeout(State)};
handle_sync_event(close, _, StateName, State) ->
%% Run terminate before returning
@@ -796,7 +814,7 @@ handle_sync_event({shutdown, How0}, _, StateName,
case Transport:shutdown(Socket, How0) of
ok ->
- {reply, ok, StateName, State};
+ {reply, ok, StateName, State, get_timeout(State)};
Error ->
{stop, normal, Error, State}
end;
@@ -807,30 +825,33 @@ handle_sync_event({recv, N}, From, connection = StateName, State0) ->
%% Doing renegotiate wait with handling request until renegotiate is
%% finished. Will be handled by next_state_connection/2.
handle_sync_event({recv, N}, From, StateName, State) ->
- {next_state, StateName, State#state{bytes_to_read = N, from = From,
- recv_during_renegotiation = true}};
+ {next_state, StateName,
+ State#state{bytes_to_read = N, from = From,
+ recv_during_renegotiation = true},
+ get_timeout(State)};
handle_sync_event({new_user, User}, _From, StateName,
State =#state{user_application = {OldMon, _}}) ->
NewMon = erlang:monitor(process, User),
erlang:demonitor(OldMon, [flush]),
- {reply, ok, StateName, State#state{user_application = {NewMon,User}}};
+ {reply, ok, StateName, State#state{user_application = {NewMon,User}},
+ get_timeout(State)};
handle_sync_event({get_opts, OptTags}, _From, StateName,
#state{socket = Socket,
socket_options = SockOpts} = State) ->
OptsReply = get_socket_opts(Socket, OptTags, SockOpts, []),
- {reply, OptsReply, StateName, State};
+ {reply, OptsReply, StateName, State, get_timeout(State)};
handle_sync_event(sockname, _From, StateName,
#state{socket = Socket} = State) ->
SockNameReply = inet:sockname(Socket),
- {reply, SockNameReply, StateName, State};
+ {reply, SockNameReply, StateName, State, get_timeout(State)};
handle_sync_event(peername, _From, StateName,
#state{socket = Socket} = State) ->
PeerNameReply = inet:peername(Socket),
- {reply, PeerNameReply, StateName, State};
+ {reply, PeerNameReply, StateName, State, get_timeout(State)};
handle_sync_event({set_opts, Opts0}, _From, StateName,
#state{socket_options = Opts1,
@@ -840,27 +861,27 @@ handle_sync_event({set_opts, Opts0}, _From, StateName,
State1 = State0#state{socket_options = Opts},
if
Opts#socket_options.active =:= false ->
- {reply, ok, StateName, State1};
+ {reply, ok, StateName, State1, get_timeout(State1)};
Buffer =:= <<>>, Opts1#socket_options.active =:= false ->
%% Need data, set active once
{Record, State2} = next_record_if_active(State1),
case next_state(StateName, Record, State2) of
- {next_state, StateName, State} ->
- {reply, ok, StateName, State};
+ {next_state, StateName, State, Timeout} ->
+ {reply, ok, StateName, State, Timeout};
{stop, Reason, State} ->
{stop, Reason, State}
end;
Buffer =:= <<>> ->
%% Active once already set
- {reply, ok, StateName, State1};
+ {reply, ok, StateName, State1, get_timeout(State1)};
true ->
case application_data(<<>>, State1) of
Stop = {stop,_,_} ->
Stop;
{Record, State2} ->
case next_state(StateName, Record, State2) of
- {next_state, StateName, State} ->
- {reply, ok, StateName, State};
+ {next_state, StateName, State, Timeout} ->
+ {reply, ok, StateName, State, Timeout};
{stop, Reason, State} ->
{stop, Reason, State}
end
@@ -871,7 +892,7 @@ handle_sync_event(renegotiate, From, connection, State) ->
renegotiate(State#state{renegotiation = {true, From}});
handle_sync_event(renegotiate, _, StateName, State) ->
- {reply, {error, already_renegotiating}, StateName, State};
+ {reply, {error, already_renegotiating}, StateName, State, get_timeout(State)};
handle_sync_event(info, _, StateName,
#state{negotiated_version = Version,
@@ -879,19 +900,19 @@ handle_sync_event(info, _, StateName,
AtomVersion = ssl_record:protocol_version(Version),
{reply, {ok, {AtomVersion, ssl_cipher:suite_definition(Suite)}},
- StateName, State};
+ StateName, State, get_timeout(State)};
handle_sync_event(session_info, _, StateName,
#state{session = #session{session_id = Id,
cipher_suite = Suite}} = State) ->
{reply, [{session_id, Id},
{cipher_suite, ssl_cipher:suite_definition(Suite)}],
- StateName, State};
+ StateName, State, get_timeout(State)};
handle_sync_event(peer_certificate, _, StateName,
#state{session = #session{peer_certificate = Cert}}
= State) ->
- {reply, {ok, Cert}, StateName, State}.
+ {reply, {ok, Cert}, StateName, State, get_timeout(State)}.
%%--------------------------------------------------------------------
-spec handle_info(msg(),state_name(), #state{}) ->
@@ -955,7 +976,7 @@ handle_info({'DOWN', MonitorRef, _, _, _}, _,
handle_info(Msg, StateName, State) ->
Report = io_lib:format("SSL: Got unexpected info: ~p ~n", [Msg]),
error_logger:info_report(Report),
- {next_state, StateName, State}.
+ {next_state, StateName, State, get_timeout(State)}.
%%--------------------------------------------------------------------
-spec terminate(reason(), state_name(), #state{}) -> term().
@@ -1086,13 +1107,13 @@ init_private_key({rsa, PrivateKey}, _, _,_) ->
init_private_key({dsa, PrivateKey},_,_,_) ->
public_key:der_decode('DSAPrivateKey', PrivateKey).
--spec(handle_file_error/6 :: (_,_,_,_,_,_) -> no_return()).
+-spec(handle_file_error(_,_,_,_,_,_) -> no_return()).
handle_file_error(Line, Error, {badmatch, Reason}, File, Throw, Stack) ->
file_error(Line, Error, Reason, File, Throw, Stack);
handle_file_error(Line, Error, Reason, File, Throw, Stack) ->
file_error(Line, Error, Reason, File, Throw, Stack).
--spec(file_error/6 :: (_,_,_,_,_,_) -> no_return()).
+-spec(file_error(_,_,_,_,_,_) -> no_return()).
file_error(Line, Error, Reason, File, Throw, Stack) ->
Report = io_lib:format("SSL: ~p: ~p:~p ~s~n ~p~n",
[Line, Error, Reason, File, Stack]),
@@ -1412,8 +1433,6 @@ key_exchange(#state{role = client,
State#state{connection_states = ConnectionStates1,
tls_handshake_hashes = Hashes1}.
--spec(rsa_key_exchange/2 :: (_,_) -> no_return()).
-
rsa_key_exchange(PremasterSecret, PublicKeyInfo = {Algorithm, _, _})
when Algorithm == ?rsaEncryption;
Algorithm == ?md2WithRSAEncryption;
@@ -1780,7 +1799,7 @@ handle_tls_handshake(Handle, StateName, #state{tls_packets = [Packet]} = State)
handle_tls_handshake(Handle, StateName, #state{tls_packets = [Packet | Packets]} = State0) ->
FsmReturn = {next_state, StateName, State0#state{tls_packets = Packets}},
case Handle(Packet, FsmReturn) of
- {next_state, NextStateName, State} ->
+ {next_state, NextStateName, State, _Timeout} ->
handle_tls_handshake(Handle, NextStateName, State);
{stop, _,_} = Stop ->
Stop
@@ -1791,11 +1810,11 @@ next_state(_, #alert{} = Alert, #state{negotiated_version = Version} = State) ->
{stop, normal, State};
next_state(Next, no_record, State) ->
- {next_state, Next, State};
+ {next_state, Next, State, get_timeout(State)};
next_state(Next, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, State) ->
Alerts = decode_alerts(EncAlerts),
- handle_alerts(Alerts, {next_state, Next, State});
+ handle_alerts(Alerts, {next_state, Next, State, get_timeout(State)});
next_state(StateName, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
State0 = #state{tls_handshake_buffer = Buf0, negotiated_version = Version}) ->
@@ -2046,7 +2065,7 @@ handle_alerts([], Result) ->
handle_alerts(_, {stop, _, _} = Stop) ->
%% If it is a fatal alert immediately close
Stop;
-handle_alerts([Alert | Alerts], {next_state, StateName, State}) ->
+handle_alerts([Alert | Alerts], {next_state, StateName, State, _Timeout}) ->
handle_alerts(Alerts, handle_alert(Alert, StateName, State)).
handle_alert(#alert{level = ?FATAL} = Alert, StateName,
@@ -2227,3 +2246,8 @@ linux_workaround_transport_delivery_problems(#alert{level = ?FATAL}, Socket) ->
end;
linux_workaround_transport_delivery_problems(_, _) ->
ok.
+
+get_timeout(#state{ssl_options=#ssl_options{hibernate_after=undefined}}) ->
+ infinity;
+get_timeout(#state{ssl_options=#ssl_options{hibernate_after=HibernateAfter}}) ->
+ HibernateAfter.
diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl
index 8ae4d2332e..fb0ebac7d1 100644
--- a/lib/ssl/src/ssl_handshake.hrl
+++ b/lib/ssl/src/ssl_handshake.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -29,9 +29,8 @@
-include_lib("public_key/include/public_key.hrl").
-type algo_oid() :: ?'rsaEncryption' | ?'id-dsa'.
--type public_key() :: #'RSAPublicKey'{} | integer().
-type public_key_params() :: #'Dss-Parms'{} | term().
--type public_key_info() :: {algo_oid(), public_key(), public_key_params()}.
+-type public_key_info() :: {algo_oid(), #'RSAPublicKey'{} | integer() , public_key_params()}.
-record(session, {
session_id,
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 715941e3ad..c28daa271e 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -98,7 +98,11 @@
reuse_sessions, % boolean()
renegotiate_at,
secure_renegotiate,
- debug %
+ debug,
+ hibernate_after % undefined if not hibernating,
+ % or number of ms of inactivity
+ % after which ssl_connection will
+ % go into hibernation
}).
-record(socket_options,
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index c0a7f8d257..fd3b6d06ad 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2010. All Rights Reserved.
+# Copyright Ericsson AB 1999-2011. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -60,6 +60,7 @@ ERL_FILES = $(MODULES:%=%.erl)
HRL_FILES = ssl_test_MACHINE.hrl
HRL_FILES_SRC = \
+ ssl_int.hrl \
ssl_alert.hrl \
ssl_handshake.hrl
@@ -126,7 +127,7 @@ release_spec: opt
release_tests_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(HRL_FILES_NEEDED_IN_TEST) $(COVER_FILE) $(RELSYSDIR)
- $(INSTALL_DATA) ssl.spec $(RELSYSDIR)
+ $(INSTALL_DATA) ssl.spec ssl.cover $(RELSYSDIR)
chmod -f -R u+w $(RELSYSDIR)
@tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
diff --git a/lib/ssl/test/make_certs.erl b/lib/ssl/test/make_certs.erl
index 3c18a905b4..693289990c 100644
--- a/lib/ssl/test/make_certs.erl
+++ b/lib/ssl/test/make_certs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/ssl/test/old_ssl_active_SUITE.erl b/lib/ssl/test/old_ssl_active_SUITE.erl
index d1cec26827..52ff0bcc5d 100644
--- a/lib/ssl/test/old_ssl_active_SUITE.erl
+++ b/lib/ssl/test/old_ssl_active_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,11 +20,10 @@
%%
-module(old_ssl_active_SUITE).
--export([all/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
init_per_testcase/2,
- fin_per_testcase/2,
- config/1,
- finish/1,
+ end_per_testcase/2,
cinit_return_chkclose/1,
sinit_return_chkclose/1,
cinit_big_return_chkclose/1,
@@ -40,7 +39,7 @@
-import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
test_server_only/6]).
--include("test_server.hrl").
+-include_lib("test_server/include/test_server.hrl").
-include("ssl_test_MACHINE.hrl").
-define(MANYCONNS, ssl_test_MACHINE:many_conns()).
@@ -49,33 +48,35 @@ init_per_testcase(_Case, Config) ->
WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
[{watchdog, WatchDog}| Config].
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
WatchDog = ?config(watchdog, Config),
test_server:timetrap_cancel(WatchDog).
-all(doc) ->
- "Test of ssl.erl interface in active mode.";
-all(suite) ->
- {conf,
- config,
- [cinit_return_chkclose,
- sinit_return_chkclose,
- cinit_big_return_chkclose,
- sinit_big_return_chkclose,
- cinit_big_echo_chkclose,
- cinit_huge_echo_chkclose,
- sinit_big_echo_chkclose,
- cinit_few_echo_chkclose,
- cinit_many_echo_chkclose,
- cinit_cnocert],
- finish}.
-
-config(doc) ->
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [cinit_return_chkclose, sinit_return_chkclose,
+ cinit_big_return_chkclose, sinit_big_return_chkclose,
+ cinit_big_echo_chkclose, cinit_huge_echo_chkclose,
+ sinit_big_echo_chkclose, cinit_few_echo_chkclose,
+ cinit_many_echo_chkclose, cinit_cnocert].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_suite(doc) ->
"Want to se what Config contains, and record the number of available "
"file descriptors";
-config(suite) ->
+init_per_suite(suite) ->
[];
-config(Config) ->
+init_per_suite(Config) ->
io:format("Config: ~p~n", [Config]),
case os:type() of
{unix, _} ->
@@ -87,20 +88,25 @@ config(Config) ->
%% operating system, version of OTP, Erts, kernel and stdlib.
%% Check if SSL exists. If this case fails, all other cases are skipped
- crypto:start(),
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config.
-
-finish(doc) ->
+ case catch crypto:start() of
+ ok ->
+ application:start(public_key),
+ case ssl:start() of
+ ok -> ssl:stop();
+ {error, {already_started, _}} -> ssl:stop();
+ Error -> ?t:fail({failed_starting_ssl,Error})
+ end,
+ Config;
+ _Else ->
+ {skip,"Could not start crypto!"}
+ end.
+
+end_per_suite(doc) ->
"This test case has no mission other than closing the conf case";
-finish(suite) ->
+end_per_suite(suite) ->
[];
-finish(Config) ->
+end_per_suite(Config) ->
+ crypto:stop(),
Config.
cinit_return_chkclose(doc) ->
diff --git a/lib/ssl/test/old_ssl_active_once_SUITE.erl b/lib/ssl/test/old_ssl_active_once_SUITE.erl
index 63eaa730e9..c7beadb301 100644
--- a/lib/ssl/test/old_ssl_active_once_SUITE.erl
+++ b/lib/ssl/test/old_ssl_active_once_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,11 +20,10 @@
%%
-module(old_ssl_active_once_SUITE).
--export([all/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
init_per_testcase/2,
- fin_per_testcase/2,
- config/1,
- finish/1,
+ end_per_testcase/2,
server_accept_timeout/1,
cinit_return_chkclose/1,
sinit_return_chkclose/1,
@@ -40,7 +39,7 @@
-import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
test_server_only/6]).
--include("test_server.hrl").
+-include_lib("test_server/include/test_server.hrl").
-include("ssl_test_MACHINE.hrl").
-define(MANYCONNS, ssl_test_MACHINE:many_conns()).
@@ -49,50 +48,57 @@ init_per_testcase(_Case, Config) ->
WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
[{watchdog, WatchDog}| Config].
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
WatchDog = ?config(watchdog, Config),
test_server:timetrap_cancel(WatchDog).
-all(doc) ->
- "Test of ssl.erl interface in passive mode.";
-all(suite) ->
- {conf,
- config,
- [server_accept_timeout,
- cinit_return_chkclose,
- sinit_return_chkclose,
- cinit_big_return_chkclose,
- sinit_big_return_chkclose,
- cinit_big_echo_chkclose,
- cinit_huge_echo_chkclose,
- sinit_big_echo_chkclose,
- cinit_few_echo_chkclose,
- cinit_many_echo_chkclose,
- cinit_cnocert],
- finish}.
-
-config(doc) ->
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [server_accept_timeout, cinit_return_chkclose,
+ sinit_return_chkclose, cinit_big_return_chkclose,
+ sinit_big_return_chkclose, cinit_big_echo_chkclose,
+ cinit_huge_echo_chkclose, sinit_big_echo_chkclose,
+ cinit_few_echo_chkclose, cinit_many_echo_chkclose,
+ cinit_cnocert].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_suite(doc) ->
"Want to se what Config contains.";
-config(suite) ->
+init_per_suite(suite) ->
[];
-config(Config) ->
+init_per_suite(Config) ->
io:format("Config: ~p~n", [Config]),
%% Check if SSL exists. If this case fails, all other cases are skipped
- crypto:start(),
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config.
-
-finish(doc) ->
+ case catch crypto:start() of
+ ok ->
+ application:start(public_key),
+ case ssl:start() of
+ ok -> ssl:stop();
+ {error, {already_started, _}} -> ssl:stop();
+ Error -> ?t:fail({failed_starting_ssl,Error})
+ end,
+ Config;
+ _Else ->
+ {skip,"Could not start crypto"}
+ end.
+
+end_per_suite(doc) ->
"This test case has no mission other than closing the conf case";
-finish(suite) ->
+end_per_suite(suite) ->
[];
-finish(Config) ->
+end_per_suite(Config) ->
+ crypto:stop(),
Config.
server_accept_timeout(doc) ->
diff --git a/lib/ssl/test/old_ssl_dist_SUITE.erl b/lib/ssl/test/old_ssl_dist_SUITE.erl
index 97090c1409..4544fb616a 100644
--- a/lib/ssl/test/old_ssl_dist_SUITE.erl
+++ b/lib/ssl/test/old_ssl_dist_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -29,39 +29,55 @@
%%%-------------------------------------------------------------------
-module(old_ssl_dist_SUITE).
--include("test_server.hrl").
+-include_lib("test_server/include/test_server.hrl").
-define(DEFAULT_TIMETRAP_SECS, 240).
-define(AWAIT_SLL_NODE_UP_TIMEOUT, 30000).
--export([all/1]).
+-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
-export([init_per_suite/1,
end_per_suite/1,
init_per_testcase/2,
- fin_per_testcase/2]).
+ end_per_testcase/2]).
-export([cnct2tstsrvr/1]).
-export([basic/1]).
-record(node_handle, {connection_handler, socket, name, nodename}).
-all(doc) ->
- [];
-all(suite) ->
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
[basic].
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
init_per_suite(Config) ->
- add_ssl_opts_config(Config).
+ try crypto:start() of
+ ok ->
+ add_ssl_opts_config(Config)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
end_per_suite(Config) ->
+ application:stop(crypto),
Config.
init_per_testcase(Case, Config) when list(Config) ->
Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMETRAP_SECS)),
[{watchdog, Dog},{testcase, Case}|Config].
-fin_per_testcase(_Case, Config) when list(Config) ->
+end_per_testcase(_Case, Config) when list(Config) ->
Dog = ?config(watchdog, Config),
?t:timetrap_cancel(Dog),
ok.
diff --git a/lib/ssl/test/old_ssl_misc_SUITE.erl b/lib/ssl/test/old_ssl_misc_SUITE.erl
index 2767123a12..ea03e83867 100644
--- a/lib/ssl/test/old_ssl_misc_SUITE.erl
+++ b/lib/ssl/test/old_ssl_misc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,18 +20,17 @@
%%
-module(old_ssl_misc_SUITE).
--export([all/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
init_per_testcase/2,
- fin_per_testcase/2,
- config/1,
- finish/1,
+ end_per_testcase/2,
seed/1,
app/1
]).
-import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
test_server_only/6]).
--include("test_server.hrl").
+-include_lib("test_server/include/test_server.hrl").
-include("ssl_test_MACHINE.hrl").
-define(MANYCONNS, 5).
@@ -40,41 +39,52 @@ init_per_testcase(_Case, Config) ->
WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
[{watchdog, WatchDog}| Config].
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
WatchDog = ?config(watchdog, Config),
test_server:timetrap_cancel(WatchDog).
-all(doc) ->
- "Test of misc in ssl.erl interface.";
-all(suite) ->
- {conf,
- config,
- [seed, app],
- finish
- }.
+suite() -> [{ct_hooks,[ts_install_cth]}].
-config(doc) ->
+all() ->
+ [seed, app].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_suite(doc) ->
"Want to se what Config contains.";
-config(suite) ->
+init_per_suite(suite) ->
[];
-config(Config) ->
+init_per_suite(Config) ->
io:format("Config: ~p~n", [Config]),
%% Check if SSL exists. If this case fails, all other cases are skipped
- crypto:start(),
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config.
-
-finish(doc) ->
+ case catch crypto:start() of
+ ok ->
+ application:start(public_key),
+ case ssl:start() of
+ ok -> ssl:stop();
+ {error, {already_started, _}} -> ssl:stop();
+ Error -> ?t:fail({failed_starting_ssl,Error})
+ end,
+ Config;
+ _Else ->
+ {skip,"Could not start crypto!"}
+ end.
+
+end_per_suite(doc) ->
"This test case has no mission other than closing the conf case";
-finish(suite) ->
+end_per_suite(suite) ->
[];
-finish(Config) ->
+end_per_suite(Config) ->
+ crypto:stop(),
Config.
seed(doc) ->
diff --git a/lib/ssl/test/old_ssl_passive_SUITE.erl b/lib/ssl/test/old_ssl_passive_SUITE.erl
index 96a7938583..7b54fe876a 100644
--- a/lib/ssl/test/old_ssl_passive_SUITE.erl
+++ b/lib/ssl/test/old_ssl_passive_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,11 +20,10 @@
%%
-module(old_ssl_passive_SUITE).
--export([all/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1,
+ end_per_suite/1, init_per_group/2,end_per_group/2,
init_per_testcase/2,
- fin_per_testcase/2,
- config/1,
- finish/1,
+ end_per_testcase/2,
server_accept_timeout/1,
cinit_return_chkclose/1,
sinit_return_chkclose/1,
@@ -40,7 +39,7 @@
-import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
test_server_only/6]).
--include("test_server.hrl").
+-include_lib("test_server/include/test_server.hrl").
-include("ssl_test_MACHINE.hrl").
-define(MANYCONNS, ssl_test_MACHINE:many_conns()).
@@ -49,49 +48,56 @@ init_per_testcase(_Case, Config) ->
WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
[{watchdog, WatchDog}| Config].
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
WatchDog = ?config(watchdog, Config),
test_server:timetrap_cancel(WatchDog).
-all(doc) ->
- "Test of ssl.erl interface in passive mode.";
-all(suite) ->
- {conf,
- config,
- [server_accept_timeout,
- cinit_return_chkclose,
- sinit_return_chkclose,
- cinit_big_return_chkclose,
- sinit_big_return_chkclose,
- cinit_big_echo_chkclose,
- sinit_big_echo_chkclose,
- cinit_few_echo_chkclose,
- cinit_many_echo_chkclose,
- cinit_cnocert],
- finish}.
-
-config(doc) ->
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [server_accept_timeout, cinit_return_chkclose,
+ sinit_return_chkclose, cinit_big_return_chkclose,
+ sinit_big_return_chkclose, cinit_big_echo_chkclose,
+ sinit_big_echo_chkclose, cinit_few_echo_chkclose,
+ cinit_many_echo_chkclose, cinit_cnocert].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_suite(doc) ->
"Want to se what Config contains.";
-config(suite) ->
+init_per_suite(suite) ->
[];
-config(Config) ->
+init_per_suite(Config) ->
io:format("Config: ~p~n", [Config]),
%% Check if SSL exists. If this case fails, all other cases are skipped
- crypto:start(),
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config.
-
-finish(doc) ->
+ case catch crypto:start() of
+ ok ->
+ application:start(public_key),
+ case ssl:start() of
+ ok -> ssl:stop();
+ {error, {already_started, _}} -> ssl:stop();
+ Error -> ?t:fail({failed_starting_ssl,Error})
+ end,
+ Config;
+ _Else ->
+ {skip,"Could not start crypto"}
+ end.
+
+end_per_suite(doc) ->
"This test case has no mission other than closing the conf case";
-finish(suite) ->
+end_per_suite(suite) ->
[];
-finish(Config) ->
+end_per_suite(Config) ->
+ crypto:stop(),
Config.
server_accept_timeout(doc) ->
diff --git a/lib/ssl/test/old_ssl_peer_cert_SUITE.erl b/lib/ssl/test/old_ssl_peer_cert_SUITE.erl
index e5b3975d41..ee19bad175 100644
--- a/lib/ssl/test/old_ssl_peer_cert_SUITE.erl
+++ b/lib/ssl/test/old_ssl_peer_cert_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,11 +20,10 @@
%%
-module(old_ssl_peer_cert_SUITE).
--export([all/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
init_per_testcase/2,
- fin_per_testcase/2,
- config/1,
- finish/1,
+ end_per_testcase/2,
cinit_plain/1,
cinit_both_verify/1,
cinit_cnocert/1
@@ -32,7 +31,7 @@
-import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
test_server_only/6]).
--include("test_server.hrl").
+-include_lib("test_server/include/test_server.hrl").
-include("ssl_test_MACHINE.hrl").
@@ -40,42 +39,52 @@ init_per_testcase(_Case, Config) ->
WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
[{watchdog, WatchDog}| Config].
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
WatchDog = ?config(watchdog, Config),
test_server:timetrap_cancel(WatchDog).
-all(doc) ->
- "Test of ssl verification and peer certificate retrieval.";
-all(suite) ->
- {conf,
- config,
- [cinit_plain,
- cinit_both_verify,
- cinit_cnocert],
- finish}.
-
-config(doc) ->
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [cinit_plain, cinit_both_verify, cinit_cnocert].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_suite(doc) ->
"Want to se what Config contains.";
-config(suite) ->
+init_per_suite(suite) ->
[];
-config(Config) ->
+init_per_suite(Config) ->
io:format("Config: ~p~n", [Config]),
%% Check if SSL exists. If this case fails, all other cases are skipped
- crypto:start(),
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config.
-
-finish(doc) ->
+ case catch crypto:start() of
+ ok ->
+ application:start(public_key),
+ case ssl:start() of
+ ok -> ssl:stop();
+ {error, {already_started, _}} -> ssl:stop();
+ Error -> ?t:fail({failed_starting_ssl,Error})
+ end,
+ Config;
+ _Else ->
+ {skip,"Could not start crypto"}
+ end.
+
+end_per_suite(doc) ->
"This test case has no mission other than closing the conf case";
-finish(suite) ->
+end_per_suite(suite) ->
[];
-finish(Config) ->
+end_per_suite(Config) ->
+ crypto:stop(),
Config.
cinit_plain(doc) ->
diff --git a/lib/ssl/test/old_ssl_protocol_SUITE.erl b/lib/ssl/test/old_ssl_protocol_SUITE.erl
index efdbf45a3d..9b9937c210 100644
--- a/lib/ssl/test/old_ssl_protocol_SUITE.erl
+++ b/lib/ssl/test/old_ssl_protocol_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,13 +20,15 @@
%%
-module(old_ssl_protocol_SUITE).
--export([all/1, init_per_testcase/2, fin_per_testcase/2, config/1,
- finish/1, sslv2/1, sslv3/1, tlsv1/1, sslv2_sslv3/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ init_per_testcase/2, end_per_testcase/2,
+ sslv2/1, sslv3/1, tlsv1/1, sslv2_sslv3/1,
sslv2_tlsv1/1, sslv3_tlsv1/1, sslv2_sslv3_tlsv1/1]).
-import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
test_server_only/6]).
--include("test_server.hrl").
+-include_lib("test_server/include/test_server.hrl").
-include("ssl_test_MACHINE.hrl").
@@ -34,41 +36,53 @@ init_per_testcase(_Case, Config) ->
WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
[{watchdog, WatchDog}| Config].
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
WatchDog = ?config(watchdog, Config),
test_server:timetrap_cancel(WatchDog).
-all(doc) ->
- "Test of configuration protocol_version.";
-all(suite) ->
- {conf,
- config,
- [sslv2, sslv3, tlsv1, sslv2_sslv3, sslv2_tlsv1, sslv3_tlsv1,
- sslv2_sslv3_tlsv1],
- finish}.
+suite() -> [{ct_hooks,[ts_install_cth]}].
-config(doc) ->
+all() ->
+ [sslv2, sslv3, tlsv1, sslv2_sslv3, sslv2_tlsv1,
+ sslv3_tlsv1, sslv2_sslv3_tlsv1].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_suite(doc) ->
"Want to se what Config contains.";
-config(suite) ->
+init_per_suite(suite) ->
[];
-config(Config) ->
+init_per_suite(Config) ->
io:format("Config: ~p~n", [Config]),
%% Check if SSL exists. If this case fails, all other cases are skipped
- crypto:start(),
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config.
-
-finish(doc) ->
+ case catch crypto:start() of
+ ok ->
+ application:start(public_key),
+ case ssl:start() of
+ ok -> ssl:stop();
+ {error, {already_started, _}} -> ssl:stop();
+ Error -> ?t:fail({failed_starting_ssl,Error})
+ end,
+ Config;
+ _Else ->
+ {skip,"Could not start crypto"}
+ end.
+
+end_per_suite(doc) ->
"This test case has no other purpose than closing the conf case.";
-finish(suite) ->
+end_per_suite(suite) ->
[];
-finish(Config) ->
+end_per_suite(Config) ->
+ crypto:stop(),
Config.
%%%%%
diff --git a/lib/ssl/test/old_ssl_verify_SUITE.erl b/lib/ssl/test/old_ssl_verify_SUITE.erl
index 7a8cd1578a..4c11ea6850 100644
--- a/lib/ssl/test/old_ssl_verify_SUITE.erl
+++ b/lib/ssl/test/old_ssl_verify_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,18 +20,17 @@
%%
-module(old_ssl_verify_SUITE).
--export([all/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
init_per_testcase/2,
- fin_per_testcase/2,
- config/1,
- finish/1,
+ end_per_testcase/2,
cinit_both_verify/1,
cinit_cnocert/1
]).
-import(ssl_test_MACHINE, [mk_ssl_cert_opts/1, test_one_listener/7,
test_server_only/6]).
--include("test_server.hrl").
+-include_lib("test_server/include/test_server.hrl").
-include("ssl_test_MACHINE.hrl").
@@ -39,41 +38,52 @@ init_per_testcase(_Case, Config) ->
WatchDog = ssl_test_lib:timetrap(?DEFAULT_TIMEOUT),
[{watchdog, WatchDog}| Config].
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
WatchDog = ?config(watchdog, Config),
test_server:timetrap_cancel(WatchDog).
-all(doc) ->
- "Test of ssl.erl interface in active mode.";
-all(suite) ->
- {conf,
- config,
- [cinit_both_verify,
- cinit_cnocert],
- finish}.
+suite() -> [{ct_hooks,[ts_install_cth]}].
-config(doc) ->
+all() ->
+ [cinit_both_verify, cinit_cnocert].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_suite(doc) ->
"Want to se what Config contains.";
-config(suite) ->
+init_per_suite(suite) ->
[];
-config(Config) ->
+init_per_suite(Config) ->
io:format("Config: ~p~n", [Config]),
%% Check if SSL exists. If this case fails, all other cases are skipped
- crypto:start(),
- application:start(public_key),
- case ssl:start() of
- ok -> ssl:stop();
- {error, {already_started, _}} -> ssl:stop();
- Error -> ?t:fail({failed_starting_ssl,Error})
- end,
- Config.
-
-finish(doc) ->
+ case catch crypto:start() of
+ ok ->
+ application:start(public_key),
+ case ssl:start() of
+ ok -> ssl:stop();
+ {error, {already_started, _}} -> ssl:stop();
+ Error -> ?t:fail({failed_starting_ssl,Error})
+ end,
+ Config;
+ _Else ->
+ {skip,"Could not start crypto"}
+ end.
+
+end_per_suite(doc) ->
"This test case has no mission other than closing the conf case";
-finish(suite) ->
+end_per_suite(suite) ->
[];
-finish(Config) ->
+end_per_suite(Config) ->
+ crypto:stop(),
Config.
cinit_both_verify(doc) ->
diff --git a/lib/ssl/test/old_transport_accept_SUITE.erl b/lib/ssl/test/old_transport_accept_SUITE.erl
index 71c1d9e181..6f0c8e456b 100644
--- a/lib/ssl/test/old_transport_accept_SUITE.erl
+++ b/lib/ssl/test/old_transport_accept_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,16 +19,17 @@
%%
-module(old_transport_accept_SUITE).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("test_server_line.hrl").
%% Default timetrap timeout (set in init_per_testcase).
-define(default_timeout, ?t:minutes(1)).
-define(application, ssh).
--export([all/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
init_per_testcase/2,
- fin_per_testcase/2,
+ end_per_testcase/2,
config/1,
echo_once/1,
echo_twice/1,
@@ -43,15 +44,37 @@ init_per_testcase(_Case, Config) ->
[{watchdog, WatchDog}, {protomod, gen_tcp}, {serialize_accept, true}|
Config].
-fin_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
WatchDog = ?config(watchdog, Config),
test_server:timetrap_cancel(WatchDog).
-all(doc) ->
- "Test transport_accept and ssl_accept";
-all(suite) ->
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
[config, echo_once, echo_twice, close_before_ssl_accept].
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ try crypto:start() of
+ ok ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ application:stop(crypto),
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
config(doc) ->
"Want to se what Config contains.";
config(suite) ->
diff --git a/lib/ssl/test/ssl.cover b/lib/ssl/test/ssl.cover
index e8daa363c5..60774cc0f1 100644
--- a/lib/ssl/test/ssl.cover
+++ b/lib/ssl/test/ssl.cover
@@ -1,19 +1,21 @@
-{exclude, [ssl_pkix_oid,
- 'PKIX1Algorithms88',
- 'PKIX1Explicit88',
- 'PKIX1Implicit88',
- 'PKIXAttributeCertificate',
- 'SSL-PKIX',
- ssl_pem,
- ssl_pkix,
- ssl_base64,
- ssl_broker,
- ssl_broker_int,
- ssl_broker_sup,
- ssl_debug,
- ssl_server,
- ssl_prim,
- inet_ssl_dist,
- 'OTP-PKIX'
+{incl_app,ssl,details}.
+
+{excl_mods, ssl, [ssl_pkix_oid,
+ 'PKIX1Algorithms88',
+ 'PKIX1Explicit88',
+ 'PKIX1Implicit88',
+ 'PKIXAttributeCertificate',
+ 'SSL-PKIX',
+ ssl_pem,
+ ssl_pkix,
+ ssl_base64,
+ ssl_broker,
+ ssl_broker_int,
+ ssl_broker_sup,
+ ssl_debug,
+ ssl_server,
+ ssl_prim,
+ inet_ssl_dist,
+ 'OTP-PKIX'
]}.
diff --git a/lib/ssl/test/ssl.spec b/lib/ssl/test/ssl.spec
index 6ef4fb73db..fc7c1bbb82 100644
--- a/lib/ssl/test/ssl.spec
+++ b/lib/ssl/test/ssl.spec
@@ -1 +1 @@
-{topcase, {dir, "../ssl_test"}}.
+{suites,"../ssl_test",all}.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 6a1b83d344..4f0907027f 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -24,11 +24,12 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("test_server_line.hrl").
-include_lib("public_key/include/public_key.hrl").
-include("ssl_alert.hrl").
+-include("ssl_int.hrl").
-define('24H_in_sec', 86400).
-define(TIMEOUT, 60000).
@@ -48,7 +49,7 @@
%%--------------------------------------------------------------------
init_per_suite(Config0) ->
Dog = ssl_test_lib:timetrap(?LONG_TIMEOUT *2),
- case application:start(crypto) of
+ try crypto:start() of
ok ->
application:start(public_key),
ssl:start(),
@@ -61,8 +62,8 @@ init_per_suite(Config0) ->
Config1 = ssl_test_lib:make_dsa_cert(Config0),
Config = ssl_test_lib:cert_options(Config1),
- [{watchdog, Dog} | Config];
- _ ->
+ [{watchdog, Dog} | Config]
+ catch _:_ ->
{skip, "Crypto did not start"}
end.
%%--------------------------------------------------------------------
@@ -88,6 +89,13 @@ end_per_suite(_Config) ->
%% variable, but should NOT alter/remove any existing entries.
%% Description: Initialization before each test case
%%--------------------------------------------------------------------
+init_per_testcase(session_cache_process_list, Config) ->
+ init_customized_session_cache(list, Config);
+
+init_per_testcase(session_cache_process_mnesia, Config) ->
+ mnesia:start(),
+ init_customized_session_cache(mnesia, Config);
+
init_per_testcase(reuse_session_expired, Config0) ->
Config = lists:keydelete(watchdog, 1, Config0),
Dog = ssl_test_lib:timetrap(?EXPIRE * 1000 * 5),
@@ -137,6 +145,16 @@ init_per_testcase(_TestCase, Config0) ->
Dog = test_server:timetrap(?TIMEOUT),
[{watchdog, Dog} | Config].
+init_customized_session_cache(Type, Config0) ->
+ Config = lists:keydelete(watchdog, 1, Config0),
+ Dog = test_server:timetrap(?TIMEOUT),
+ ssl:stop(),
+ application:load(ssl),
+ application:set_env(ssl, session_cb, ?MODULE),
+ application:set_env(ssl, session_cb_init_args, [Type]),
+ ssl:start(),
+ [{watchdog, Dog} | Config].
+
%%--------------------------------------------------------------------
%% Function: end_per_testcase(TestCase, Config) -> _
%% Case - atom()
@@ -145,6 +163,16 @@ init_per_testcase(_TestCase, Config0) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
+end_per_testcase(session_cache_process_list, Config) ->
+ application:unset_env(ssl, session_cb),
+ end_per_testcase(default_action, Config);
+end_per_testcase(session_cache_process_mnesia, Config) ->
+ application:unset_env(ssl, session_cb),
+ application:unset_env(ssl, session_cb_init_args),
+ mnesia:stop(),
+ ssl:stop(),
+ ssl:start(),
+ end_per_testcase(default_action, Config);
end_per_testcase(reuse_session_expired, Config) ->
application:unset_env(ssl, session_lifetime),
end_per_testcase(default_action, Config);
@@ -173,52 +201,69 @@ end_per_testcase(_TestCase, Config) ->
%% Name of a test case.
%% Description: Returns a list of all test cases in this test suite
%%--------------------------------------------------------------------
-all(doc) ->
- ["Test the basic ssl functionality"];
+suite() -> [{ct_hooks,[ts_install_cth]}].
-all(suite) ->
+all() ->
[app, alerts, connection_info, protocol_versions,
- empty_protocol_versions, controlling_process, controller_dies,
- client_closes_socket, peercert, connect_dist, peername, sockname,
- socket_options, misc_ssl_options, versions, cipher_suites,
- upgrade, upgrade_with_timeout, tcp_connect, ipv6, ekeyfile,
- ecertfile, ecacertfile, eoptions, shutdown, shutdown_write,
- shutdown_both, shutdown_error,
+ empty_protocol_versions, controlling_process,
+ controller_dies, client_closes_socket, peercert,
+ connect_dist, peername, sockname, socket_options,
+ misc_ssl_options, versions, cipher_suites, upgrade,
+ upgrade_with_timeout, tcp_connect, ipv6, ekeyfile,
+ ecertfile, ecacertfile, eoptions, shutdown,
+ shutdown_write, shutdown_both, shutdown_error,
ciphers_rsa_signed_certs, ciphers_rsa_signed_certs_ssl3,
ciphers_rsa_signed_certs_openssl_names,
ciphers_rsa_signed_certs_openssl_names_ssl3,
- ciphers_dsa_signed_certs,
- ciphers_dsa_signed_certs_ssl3,
+ ciphers_dsa_signed_certs, ciphers_dsa_signed_certs_ssl3,
ciphers_dsa_signed_certs_openssl_names,
ciphers_dsa_signed_certs_openssl_names_ssl3,
anonymous_cipher_suites,
default_reject_anonymous,
send_close,
- close_transport_accept, dh_params, server_verify_peer_passive,
- server_verify_peer_active, server_verify_peer_active_once,
+ close_transport_accept, dh_params,
+ server_verify_peer_passive, server_verify_peer_active,
+ server_verify_peer_active_once,
server_verify_none_passive, server_verify_none_active,
- server_verify_none_active_once, server_verify_no_cacerts,
- server_require_peer_cert_ok, server_require_peer_cert_fail,
+ server_verify_none_active_once,
+ server_verify_no_cacerts, server_require_peer_cert_ok,
+ server_require_peer_cert_fail,
server_verify_client_once_passive,
server_verify_client_once_active,
- server_verify_client_once_active_once, client_verify_none_passive,
- client_verify_none_active, client_verify_none_active_once,
- reuse_session, reuse_session_expired,
- server_does_not_want_to_reuse_session, client_renegotiate,
- server_renegotiate, client_renegotiate_reused_session,
- server_renegotiate_reused_session, client_no_wrap_sequence_number,
- server_no_wrap_sequence_number,
- extended_key_usage_verify_peer, extended_key_usage_verify_none,
- no_authority_key_identifier,
- invalid_signature_client, invalid_signature_server, cert_expired,
- client_with_cert_cipher_suites_handshake, unknown_server_ca_fail,
- der_input, unknown_server_ca_accept_verify_none, unknown_server_ca_accept_verify_peer,
+ server_verify_client_once_active_once,
+ client_verify_none_passive, client_verify_none_active,
+ client_verify_none_active_once,
+ reuse_session,
+ reuse_session_expired,
+ server_does_not_want_to_reuse_session,
+ client_renegotiate, server_renegotiate,
+ client_renegotiate_reused_session,
+ server_renegotiate_reused_session,
+ client_no_wrap_sequence_number,
+ server_no_wrap_sequence_number, extended_key_usage_verify_peer,
+ extended_key_usage_verify_none,
+ no_authority_key_identifier, invalid_signature_client,
+ invalid_signature_server, cert_expired,
+ client_with_cert_cipher_suites_handshake,
+ unknown_server_ca_fail, der_input,
+ unknown_server_ca_accept_verify_none,
+ unknown_server_ca_accept_verify_peer,
unknown_server_ca_accept_backwardscompatibilty,
- %different_ca_peer_sign,
+ %%different_ca_peer_sign,
no_reuses_session_server_restart_new_cert,
- no_reuses_session_server_restart_new_cert_file, reuseaddr
+ no_reuses_session_server_restart_new_cert_file, reuseaddr,
+ hibernate
].
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
%% Test cases starts here.
%%--------------------------------------------------------------------
app(doc) ->
@@ -1059,6 +1104,8 @@ dummy(_Socket) ->
exit(kill).
%%--------------------------------------------------------------------
+ipv6() ->
+ [{require, ipv6_hosts}].
ipv6(doc) ->
["Test ipv6."];
ipv6(suite) ->
@@ -1066,7 +1113,7 @@ ipv6(suite) ->
ipv6(Config) when is_list(Config) ->
{ok, Hostname0} = inet:gethostname(),
- case lists:member(list_to_atom(Hostname0), ?config(ipv6_hosts, Config)) of
+ case lists:member(list_to_atom(Hostname0), ct:get_config(ipv6_hosts)) of
true ->
ClientOpts = ?config(client_opts, Config),
ServerOpts = ?config(server_opts, Config),
@@ -3275,19 +3322,47 @@ reuseaddr(Config) when is_list(Config) ->
ssl_test_lib:close(Client1).
%%--------------------------------------------------------------------
+
+hibernate(doc) ->
+ ["Check that an SSL connection that is started with option "
+ "{hibernate_after, 1000} indeed hibernates after 1000ms of "
+ "inactivity"];
+
+hibernate(suite) ->
+ [];
+
+hibernate(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_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, send_recv_result_active, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ {Client, #sslsocket{pid=Pid}} = ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, send_recv_result_active, []}},
+ {options, [{hibernate_after, 1000}|ClientOpts]}]),
+
+ { current_function, { _M, _F, _A } } =
+ process_info(Pid, current_function),
+
+ timer:sleep(1100),
+
+ { current_function, { erlang, hibernate, 3} } =
+ process_info(Pid, current_function),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-erlang_ssl_receive(Socket, Data) ->
- receive
- {ssl, Socket, Data} ->
- test_server:format("Received ~p~n",[Data]),
- ok;
- Other ->
- test_server:fail({unexpected_message, Other})
- after ?SLEEP * 3 ->
- test_server:fail({did_not_get, Data})
- end.
-
send_recv_result(Socket) ->
ssl:send(Socket, "Hello world"),
{ok,"Hello world"} = ssl:recv(Socket, 11),
@@ -3327,7 +3402,6 @@ renegotiate_reuse_session(Socket, Data) ->
test_server:sleep(?SLEEP),
renegotiate(Socket, Data).
-
new_config(PrivDir, ServerOpts0) ->
CaCertFile = proplists:get_value(cacertfile, ServerOpts0),
CertFile = proplists:get_value(certfile, ServerOpts0),
@@ -3347,3 +3421,162 @@ new_config(PrivDir, ServerOpts0) ->
[{cacertfile, NewCaCertFile}, {certfile, NewCertFile},
{keyfile, NewKeyFile} | ServerOpts].
+
+session_cache_process_list(doc) ->
+ ["Test reuse of sessions (short handshake)"];
+
+session_cache_process_list(suite) ->
+ [];
+session_cache_process_list(Config) when is_list(Config) ->
+ session_cache_process(list,Config).
+
+session_cache_process_mnesia(doc) ->
+ ["Test reuse of sessions (short handshake)"];
+
+session_cache_process_mnesia(suite) ->
+ [];
+session_cache_process_mnesia(Config) when is_list(Config) ->
+ session_cache_process(mnesia,Config).
+
+session_cache_process(Type,Config) when is_list(Config) ->
+ reuse_session(Config).
+
+init([Type]) ->
+ ets:new(ssl_test, [named_table, public, set]),
+ ets:insert(ssl_test, {type, Type}),
+ case Type of
+ list ->
+ spawn(fun() -> session_loop([]) end);
+ mnesia ->
+ mnesia:start(),
+ {atomic,ok} = mnesia:create_table(sess_cache, []),
+ sess_cache
+ end.
+
+session_cb() ->
+ [{type, Type}] = ets:lookup(ssl_test, type),
+ Type.
+
+terminate(Cache) ->
+ case session_cb() of
+ list ->
+ Cache ! terminate;
+ mnesia ->
+ catch {atomic,ok} =
+ mnesia:delete_table(sess_cache)
+ end.
+
+lookup(Cache, Key) ->
+ case session_cb() of
+ list ->
+ Cache ! {self(), lookup, Key},
+ receive {Cache, Res} -> Res end;
+ mnesia ->
+ case mnesia:transaction(fun() ->
+ mnesia:read(sess_cache,
+ Key, read)
+ end) of
+ {atomic, [{sess_cache, Key, Value}]} ->
+ Value;
+ _ ->
+ undefined
+ end
+ end.
+
+update(Cache, Key, Value) ->
+ case session_cb() of
+ list ->
+ Cache ! {update, Key, Value};
+ mnesia ->
+ {atomic, ok} =
+ mnesia:transaction(fun() ->
+ mnesia:write(sess_cache,
+ {sess_cache, Key, Value}, write)
+ end)
+ end.
+
+delete(Cache, Key) ->
+ case session_cb() of
+ list ->
+ Cache ! {delete, Key};
+ mnesia ->
+ {atomic, ok} =
+ mnesia:transaction(fun() ->
+ mnesia:delete(sess_cache, Key)
+ end)
+ end.
+
+foldl(Fun, Acc, Cache) ->
+ case session_cb() of
+ list ->
+ Cache ! {self(),foldl,Fun,Acc},
+ receive {Cache, Res} -> Res end;
+ mnesia ->
+ Foldl = fun() ->
+ mnesia:foldl(Fun, Acc, sess_cache)
+ end,
+ {atomic, Res} = mnesia:transaction(Foldl),
+ Res
+ end.
+
+select_session(Cache, PartialKey) ->
+ case session_cb() of
+ list ->
+ Cache ! {self(),select_session, PartialKey},
+ receive
+ {Cache, Res} ->
+ Res
+ end;
+ mnesia ->
+ Sel = fun() ->
+ mnesia:select(Cache,
+ [{{sess_cache,{PartialKey,'$1'}, '$2'},
+ [],['$$']}])
+ end,
+ {atomic, Res} = mnesia:transaction(Sel),
+ Res
+ end.
+
+session_loop(Sess) ->
+ receive
+ terminate ->
+ ok;
+ {Pid, lookup, Key} ->
+ case lists:keysearch(Key,1,Sess) of
+ {value, {Key,Value}} ->
+ Pid ! {self(), Value};
+ _ ->
+ Pid ! {self(), undefined}
+ end,
+ session_loop(Sess);
+ {update, Key, Value} ->
+ NewSess = [{Key,Value}| lists:keydelete(Key,1,Sess)],
+ session_loop(NewSess);
+ {delete, Key} ->
+ session_loop(lists:keydelete(Key,1,Sess));
+ {Pid,foldl,Fun,Acc} ->
+ Res = lists:foldl(Fun, Acc,Sess),
+ Pid ! {self(), Res},
+ session_loop(Sess);
+ {Pid,select_session,PKey} ->
+ Sel = fun({{PKey0, Id},Session}, Acc) when PKey == PKey0 ->
+ [[Id, Session]|Acc];
+ (_,Acc) ->
+ Acc
+ end,
+ Sessions = lists:foldl(Sel, [], Sess),
+ Pid ! {self(), Sessions},
+ session_loop(Sess)
+ end.
+
+
+erlang_ssl_receive(Socket, Data) ->
+ receive
+ {ssl, Socket, Data} ->
+ io:format("Received ~p~n",[Data]),
+ ok;
+ Other ->
+ test_server:fail({unexpected_message, Other})
+ after ?SLEEP * 3 ->
+ test_server:fail({did_not_get, Data})
+ end.
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index b1e585e39e..d22d5d2954 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -23,7 +23,7 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(BYTE(X), X:8/unsigned-big-integer).
-define(UINT16(X), X:16/unsigned-big-integer).
@@ -53,7 +53,7 @@
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- case application:start(crypto) of
+ try crypto:start() of
ok ->
application:start(public_key),
ssl:start(),
@@ -61,8 +61,8 @@ init_per_suite(Config) ->
(catch make_certs:all(?config(data_dir, Config),
?config(priv_dir, Config))),
test_server:format("Make certs ~p~n", [Result]),
- ssl_test_lib:cert_options(Config);
- _ ->
+ ssl_test_lib:cert_options(Config)
+ catch _:_ ->
{skip, "Crypto did not start"}
end.
%%--------------------------------------------------------------------
@@ -118,56 +118,56 @@ end_per_testcase(_TestCase, Config) ->
%% Name of a test case.
%% Description: Returns a list of all test cases in this test suite
%%--------------------------------------------------------------------
-all(doc) ->
- ["Test that erlang:decode_packet/3 seems to be handled correctly."
- "We only use the most basic packet types in our tests as testing of"
- "the packet types are for inet to verify"
- ];
-
-all(suite) ->
- [packet_raw_passive_many_small,
- packet_0_passive_many_small, packet_1_passive_many_small,
- packet_2_passive_many_small, packet_4_passive_many_small,
- packet_raw_passive_some_big, packet_0_passive_some_big,
- packet_1_passive_some_big,
- packet_2_passive_some_big, packet_4_passive_some_big,
- packet_raw_active_once_many_small,
- packet_0_active_once_many_small, packet_1_active_once_many_small,
- packet_2_active_once_many_small, packet_4_active_once_many_small,
- packet_raw_active_once_some_big,
- packet_0_active_once_some_big, packet_1_active_once_some_big,
- packet_2_active_once_some_big, packet_4_active_once_some_big,
- packet_raw_active_many_small, packet_0_active_many_small,
- packet_1_active_many_small,
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [packet_raw_passive_many_small,
+ packet_0_passive_many_small,
+ packet_1_passive_many_small,
+ packet_2_passive_many_small,
+ packet_4_passive_many_small,
+ packet_raw_passive_some_big, packet_0_passive_some_big,
+ packet_1_passive_some_big, packet_2_passive_some_big,
+ packet_4_passive_some_big,
+ packet_raw_active_once_many_small,
+ packet_0_active_once_many_small,
+ packet_1_active_once_many_small,
+ packet_2_active_once_many_small,
+ packet_4_active_once_many_small,
+ packet_raw_active_once_some_big,
+ packet_0_active_once_some_big,
+ packet_1_active_once_some_big,
+ packet_2_active_once_some_big,
+ packet_4_active_once_some_big,
+ packet_raw_active_many_small,
+ packet_0_active_many_small, packet_1_active_many_small,
packet_2_active_many_small, packet_4_active_many_small,
- packet_raw_active_some_big, packet_0_active_some_big,
- packet_1_active_some_big, packet_2_active_some_big,
- packet_4_active_some_big,
- packet_send_to_large,
+ packet_raw_active_some_big, packet_0_active_some_big,
+ packet_1_active_some_big, packet_2_active_some_big,
+ packet_4_active_some_big, packet_send_to_large,
packet_wait_passive, packet_wait_active,
packet_baddata_passive, packet_baddata_active,
packet_size_passive, packet_size_active,
- packet_cdr_decode,
- packet_cdr_decode_list,
- packet_http_decode,
- packet_http_decode_list,
- packet_http_bin_decode_multi,
- packet_http_error_passive,
- packet_line_decode,
- packet_line_decode_list,
- packet_asn1_decode,
- packet_asn1_decode_list,
- packet_tpkt_decode,
- packet_tpkt_decode_list,
- %packet_fcgi_decode,
- packet_sunrm_decode,
- packet_sunrm_decode_list,
- header_decode_one_byte,
- header_decode_two_bytes,
+ packet_cdr_decode, packet_cdr_decode_list,
+ packet_http_decode, packet_http_decode_list,
+ packet_http_bin_decode_multi, packet_http_error_passive,
+ packet_line_decode, packet_line_decode_list,
+ packet_asn1_decode, packet_asn1_decode_list,
+ packet_tpkt_decode, packet_tpkt_decode_list,
+ packet_sunrm_decode, packet_sunrm_decode_list,
+ header_decode_one_byte, header_decode_two_bytes,
header_decode_two_bytes_one_sent,
- header_decode_two_bytes_two_sent
+ header_decode_two_bytes_two_sent].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
- ].
%% Test cases starts here.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl
index b19d1f286f..24e86b3913 100644
--- a/lib/ssl/test/ssl_payload_SUITE.erl
+++ b/lib/ssl/test/ssl_payload_SUITE.erl
@@ -22,7 +22,7 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(TIMEOUT, 600000).
@@ -37,13 +37,13 @@
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- case application:start(crypto) of
+ try crypto:start() of
ok ->
application:start(public_key),
ssl:start(),
make_certs:all(?config(data_dir, Config), ?config(priv_dir, Config)),
- ssl_test_lib:cert_options(Config);
- _ ->
+ ssl_test_lib:cert_options(Config)
+ catch _:_ ->
{skip, "Crypto did not start"}
end.
%%--------------------------------------------------------------------
@@ -99,24 +99,30 @@ end_per_testcase(_TestCase, Config) ->
%% Name of a test case.
%% Description: Returns a list of all test cases in this test suite
%%--------------------------------------------------------------------
-all(doc) ->
- ["Test payload over ssl in all socket modes, active, active_once,"
- "and passive mode."];
-
-all(suite) ->
- [server_echos_passive_small, server_echos_active_once_small,
- server_echos_active_small,
- client_echos_passive_small, client_echos_active_once_small,
- client_echos_active_small,
- server_echos_passive_big, server_echos_active_once_big,
- server_echos_active_big,
- client_echos_passive_big, client_echos_active_once_big,
- client_echos_active_big,
- server_echos_passive_huge, server_echos_active_once_huge,
- server_echos_active_huge,
- client_echos_passive_huge, client_echos_active_once_huge,
- client_echos_active_huge
- ].
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [server_echos_passive_small,
+ server_echos_active_once_small,
+ server_echos_active_small, client_echos_passive_small,
+ client_echos_active_once_small,
+ client_echos_active_small, server_echos_passive_big,
+ server_echos_active_once_big, server_echos_active_big,
+ client_echos_passive_big, client_echos_active_once_big,
+ client_echos_active_big, server_echos_passive_huge,
+ server_echos_active_once_huge, server_echos_active_huge,
+ client_echos_passive_huge,
+ client_echos_active_once_huge, client_echos_active_huge].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
%% Test cases starts here.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 5aac9bb4e3..a43b9ab586 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -24,7 +24,7 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(SLEEP, 500).
-define(TIMEOUT, 60000).
@@ -47,7 +47,7 @@
%%--------------------------------------------------------------------
init_per_suite(Config0) ->
Dog = ssl_test_lib:timetrap(?LONG_TIMEOUT *2),
- case application:start(crypto) of
+ try crypto:start() of
ok ->
application:start(public_key),
ssl:start(),
@@ -60,8 +60,8 @@ init_per_suite(Config0) ->
Config1 = ssl_test_lib:make_dsa_cert(Config0),
Config = ssl_test_lib:cert_options(Config1),
- [{watchdog, Dog} | Config];
- _ ->
+ [{watchdog, Dog} | Config]
+ catch _:_ ->
{skip, "Crypto did not start"}
end.
@@ -145,13 +145,20 @@ end_per_testcase(_TestCase, Config) ->
%% Name of a test case.
%% Description: Returns a list of all test cases in this test suite
%%--------------------------------------------------------------------
-all(doc) ->
- ["Test session cach API"];
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [session_cache_process_list,
+ session_cache_process_mnesia].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
-all(suite) ->
- [
- session_cache_process_list, session_cache_process_mnesia
- ].
+end_per_group(_GroupName, Config) ->
+ Config.
session_cache_process_list(doc) ->
["Test reuse of sessions (short handshake)"];
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index f6ccbe85e3..40bbdf1dbd 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -128,12 +128,14 @@ remove_close_msg(ReconnectTimes) ->
remove_close_msg(ReconnectTimes -1)
end.
-
start_client(Args) ->
- Result = spawn_link(?MODULE, run_client, [Args]),
+ Result = spawn_link(?MODULE, run_client, [lists:delete(return_socket, Args)]),
receive
- connected ->
- Result
+ { connected, Socket } ->
+ case lists:member(return_socket, Args) of
+ true -> { Result, Socket };
+ false -> Result
+ end
end.
run_client(Opts) ->
@@ -145,7 +147,7 @@ run_client(Opts) ->
test_server:format("ssl:connect(~p, ~p, ~p)~n", [Host, Port, Options]),
case rpc:call(Node, ssl, connect, [Host, Port, Options]) of
{ok, Socket} ->
- Pid ! connected,
+ Pid ! { connected, Socket },
test_server:format("Client: connected~n", []),
%% In specail cases we want to know the client port, it will
%% be indicated by sending {port, 0} in options list!
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 0cbaafd99c..64a6a9eaf8 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -24,7 +24,7 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--include("test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(TIMEOUT, 120000).
-define(LONG_TIMEOUT, 600000).
@@ -50,7 +50,7 @@ init_per_suite(Config0) ->
false ->
{skip, "Openssl not found"};
_ ->
- case application:start(crypto) of
+ try crypto:start() of
ok ->
application:start(public_key),
ssl:start(),
@@ -60,8 +60,8 @@ init_per_suite(Config0) ->
test_server:format("Make certs ~p~n", [Result]),
Config1 = ssl_test_lib:make_dsa_cert(Config0),
Config = ssl_test_lib:cert_options(Config1),
- [{watchdog, Dog} | Config];
- _ ->
+ [{watchdog, Dog} | Config]
+ catch _:_ ->
{skip, "Crypto did not start"}
end
end.
@@ -143,11 +143,10 @@ end_per_testcase(_, Config) ->
%% Name of a test case.
%% Description: Returns a list of all test cases in this test suite
%%--------------------------------------------------------------------
-all(doc) ->
- ["Test erlangs ssl against openssl"];
+suite() -> [{ct_hooks,[ts_install_cth]}].
-all(suite) ->
- [erlang_client_openssl_server,
+all() ->
+ [erlang_client_openssl_server,
erlang_server_openssl_client,
tls1_erlang_client_openssl_server_dsa_cert,
tls1_erlang_server_openssl_client_dsa_cert,
@@ -158,22 +157,29 @@ all(suite) ->
erlang_client_openssl_server_no_wrap_sequence_number,
erlang_server_openssl_client_no_wrap_sequence_number,
erlang_client_openssl_server_no_server_ca_cert,
- ssl3_erlang_client_openssl_server,
+ ssl3_erlang_client_openssl_server,
ssl3_erlang_server_openssl_client,
ssl3_erlang_client_openssl_server_client_cert,
ssl3_erlang_server_openssl_client_client_cert,
ssl3_erlang_server_erlang_client_client_cert,
- tls1_erlang_client_openssl_server,
+ tls1_erlang_client_openssl_server,
tls1_erlang_server_openssl_client,
tls1_erlang_client_openssl_server_client_cert,
tls1_erlang_server_openssl_client_client_cert,
tls1_erlang_server_erlang_client_client_cert,
- ciphers_rsa_signed_certs,
- ciphers_dsa_signed_certs,
- erlang_client_bad_openssl_server,
- expired_session,
- ssl2_erlang_server_openssl_client
- ].
+ ciphers_rsa_signed_certs, ciphers_dsa_signed_certs,
+ erlang_client_bad_openssl_server, expired_session,
+ ssl2_erlang_server_openssl_client].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
%% Test cases starts here.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index a4be7bb889..2f1edfa186 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1,2 +1 @@
-
-SSL_VSN = 4.1.3
+SSL_VSN = 4.1.4