aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/src/ssl_app.erl7
-rw-r--r--lib/ssl/src/ssl_connection.erl25
-rw-r--r--lib/ssl/src/ssl_dist_sup.erl1
-rw-r--r--lib/ssl/src/ssl_record.erl16
-rw-r--r--lib/ssl/src/ssl_session_cache.erl16
-rw-r--r--lib/ssl/src/ssl_session_cache_api.erl25
-rw-r--r--lib/ssl/src/ssl_sup.erl1
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl95
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl2
9 files changed, 112 insertions, 76 deletions
diff --git a/lib/ssl/src/ssl_app.erl b/lib/ssl/src/ssl_app.erl
index c9f81726b9..0c475a6d01 100644
--- a/lib/ssl/src/ssl_app.erl
+++ b/lib/ssl/src/ssl_app.erl
@@ -27,16 +27,9 @@
-export([start/2, stop/1]).
-%%--------------------------------------------------------------------
--spec start(normal | {takeover, node()} | {failover, node()}, list()) ->
- ignore | {ok, pid()} | {error, term()}.
-%%--------------------------------------------------------------------
start(_Type, _StartArgs) ->
ssl_sup:start_link().
-%--------------------------------------------------------------------
--spec stop(term())-> ok.
-%%--------------------------------------------------------------------
stop(_State) ->
ok.
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index d4807704b2..28dd0c85d0 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -293,10 +293,6 @@ start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
%% gen_fsm callbacks
%%====================================================================
%%--------------------------------------------------------------------
--spec init(list()) -> {ok, state_name(), #state{}, timeout()} | {stop, term()}.
-%% Possible return values not used now.
-%% | {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
%% initialize.
@@ -324,8 +320,6 @@ init([Role, Host, Port, Socket, {SSLOpts0, _} = Options,
end.
%%--------------------------------------------------------------------
-%% -spec state_name(event(), #state{}) -> gen_fsm_state_return()
-%%
%% Description:There should be one instance of this function for each
%% possible state name. Whenever a gen_fsm receives an event sent
%% using gen_fsm:send_event/2, the instance of this function with the
@@ -728,10 +722,6 @@ connection(timeout, State) ->
connection(Msg, State) ->
handle_unexpected_message(Msg, connection, State).
%%--------------------------------------------------------------------
--spec handle_event(term(), state_name(), #state{}) -> term().
-%% As it is not currently used gen_fsm_state_return() makes
-%% dialyzer unhappy!
-%%
%% Description: Whenever a gen_fsm receives an event sent using
%% gen_fsm:send_all_state_event/2, this function is called to handle
%% the event. Not currently used!
@@ -740,12 +730,6 @@ handle_event(_Event, StateName, State) ->
{next_state, StateName, State, get_timeout(State)}.
%%--------------------------------------------------------------------
--spec handle_sync_event(term(), from(), state_name(), #state{}) ->
- gen_fsm_state_return() |
- {reply, reply(), state_name(), #state{}} |
- {reply, reply(), state_name(), #state{}, timeout()} |
- {stop, reason(), reply(), #state{}}.
-%%
%% Description: Whenever a gen_fsm receives an event sent using
%% gen_fsm:sync_send_all_state_event/2,3, this function is called to handle
%% the event.
@@ -905,11 +889,6 @@ handle_sync_event(peer_certificate, _, StateName,
{reply, {ok, Cert}, StateName, State, get_timeout(State)}.
%%--------------------------------------------------------------------
--spec handle_info(msg(),state_name(), #state{}) ->
- {next_state, state_name(), #state{}}|
- {next_state, state_name(), #state{}, timeout()} |
- {stop, reason(), #state{}}.
-%%
%% Description: This function is called by a gen_fsm when it receives any
%% other message than a synchronous or asynchronous event
%% (or a system message).
@@ -972,8 +951,6 @@ handle_info(Msg, StateName, State) ->
{next_state, StateName, State, get_timeout(State)}.
%%--------------------------------------------------------------------
--spec terminate(reason(), state_name(), #state{}) -> term().
-%%
%% Description:This function is called by a gen_fsm when it is about
%% to terminate. It should be the opposite of Module:init/1 and do any
%% necessary cleaning up. When it returns, the gen_fsm terminates with
@@ -1004,8 +981,6 @@ terminate(Reason, _StateName, #state{transport_cb = Transport,
Transport:close(Socket).
%%--------------------------------------------------------------------
--spec code_change(term(), state_name(), #state{}, list()) -> {ok, state_name(), #state{}}.
-%%
%% code_change(OldVsn, StateName, State, Extra) -> {ok, StateName, NewState}
%% Description: Convert process state when code is changed
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl
index c1912401d7..9d9afb7707 100644
--- a/lib/ssl/src/ssl_dist_sup.erl
+++ b/lib/ssl/src/ssl_dist_sup.erl
@@ -41,7 +41,6 @@ start_link() ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
--spec init([]) -> {ok, {SupFlags :: tuple(), [ChildSpec :: tuple()]}}.
init([]) ->
SessionCertManager = session_and_cert_manager_child_spec(),
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index f52d2f961c..830026c825 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -508,8 +508,12 @@ decode_cipher_text(CipherText, ConnnectionStates0) ->
%%
%% Description: Encodes data to send on the ssl-socket.
%%--------------------------------------------------------------------
-encode_data(Frag, Version, ConnectionStates) ->
- Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH, Version),
+encode_data(Frag, Version,
+ #connection_states{current_write = #connection_state{
+ security_parameters =
+ #security_parameters{bulk_cipher_algorithm = BCA}}} =
+ ConnectionStates) ->
+ Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH, Version, BCA),
encode_iolist(?APPLICATION_DATA, Data, Version, ConnectionStates).
%%--------------------------------------------------------------------
@@ -588,11 +592,11 @@ record_protocol_role(client) ->
record_protocol_role(server) ->
?SERVER.
-%% 1/n-1 splitting countermeasure Rizzo/Duong-Beast
-split_bin(<<FirstByte:8, Rest/binary>>, ChunkSize, Version) when {3, 1} == Version orelse
- {3, 0} == Version ->
+%% 1/n-1 splitting countermeasure Rizzo/Duong-Beast, RC4 chiphers are not vulnerable to this attack.
+split_bin(<<FirstByte:8, Rest/binary>>, ChunkSize, Version, BCA) when BCA =/= ?RC4 andalso ({3, 1} == Version orelse
+ {3, 0} == Version) ->
do_split_bin(Rest, ChunkSize, [[FirstByte]]);
-split_bin(Bin, ChunkSize, _) ->
+split_bin(Bin, ChunkSize, _, _) ->
do_split_bin(Bin, ChunkSize, []).
do_split_bin(<<>>, _, Acc) ->
diff --git a/lib/ssl/src/ssl_session_cache.erl b/lib/ssl/src/ssl_session_cache.erl
index 93969f628f..f9bbf905e1 100644
--- a/lib/ssl/src/ssl_session_cache.erl
+++ b/lib/ssl/src/ssl_session_cache.erl
@@ -28,27 +28,19 @@
-export([init/1, terminate/1, lookup/2, update/3, delete/2, foldl/3,
select_session/2]).
--type key() :: {{host(), inet:port_number()}, session_id()} | {inet:port_number(), session_id()}.
-
%%--------------------------------------------------------------------
--spec init(list()) -> db_handle(). %% Returns reference to the cache (opaque)
-%%
%% Description: Return table reference. Called by ssl_manager process.
%%--------------------------------------------------------------------
init(_) ->
ets:new(cache_name(), [set, protected]).
%%--------------------------------------------------------------------
--spec terminate(db_handle()) -> any().
-%%
%% Description: Handles cache table at termination of ssl manager.
%%--------------------------------------------------------------------
terminate(Cache) ->
ets:delete(Cache).
%%--------------------------------------------------------------------
--spec lookup(db_handle(), key()) -> #session{} | undefined.
-%%
%% Description: Looks up a cach entry. Should be callable from any
%% process.
%%--------------------------------------------------------------------
@@ -61,8 +53,6 @@ lookup(Cache, Key) ->
end.
%%--------------------------------------------------------------------
--spec update(db_handle(), key(), #session{}) -> any().
-%%
%% Description: Caches a new session or updates a already cached one.
%% Will only be called from the ssl_manager process.
%%--------------------------------------------------------------------
@@ -70,8 +60,6 @@ update(Cache, Key, Session) ->
ets:insert(Cache, {Key, Session}).
%%--------------------------------------------------------------------
--spec delete(db_handle(), key()) -> any().
-%%
%% Description: Delets a cache entry.
%% Will only be called from the ssl_manager process.
%%--------------------------------------------------------------------
@@ -79,8 +67,6 @@ delete(Cache, Key) ->
ets:delete(Cache, Key).
%%--------------------------------------------------------------------
--spec foldl(fun(), term(), db_handle()) -> term().
-%%
%% Description: Calls Fun(Elem, AccIn) on successive elements of the
%% cache, starting with AccIn == Acc0. Fun/2 must return a new
%% accumulator which is passed to the next call. The function returns
@@ -91,8 +77,6 @@ foldl(Fun, Acc0, Cache) ->
ets:foldl(Fun, Acc0, Cache).
%%--------------------------------------------------------------------
--spec select_session(db_handle(), {host(), inet:port_number()} | inet:port_number()) -> [#session{}].
-%%
%% Description: Selects a session that could be reused. Should be callable
%% from any process.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_session_cache_api.erl b/lib/ssl/src/ssl_session_cache_api.erl
index f8416bf327..f2b22b0f1b 100644
--- a/lib/ssl/src/ssl_session_cache_api.erl
+++ b/lib/ssl/src/ssl_session_cache_api.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
@@ -20,18 +20,15 @@
%%
-module(ssl_session_cache_api).
+-include("ssl_handshake.hrl").
+-include("ssl_internal.hrl").
--export([behaviour_info/1]).
+-type key() :: {{host(), inet:port_number()}, session_id()} | {inet:port_number(), session_id()}.
-behaviour_info(callbacks) ->
- [
- {init, 1},
- {terminate, 1},
- {lookup, 2},
- {update, 3},
- {delete, 2},
- {foldl, 3},
- {select_session, 2}
- ];
-behaviour_info(_) ->
- undefined.
+-callback init(list()) -> db_handle().
+-callback terminate(db_handle()) -> any().
+-callback lookup(db_handle(), key()) -> #session{} | undefined.
+-callback update(db_handle(), key(), #session{}) -> any().
+-callback delete(db_handle(), key()) -> any().
+-callback foldl(fun(), term(), db_handle()) -> term().
+-callback select_session(db_handle(), {host(), inet:port_number()} | inet:port_number()) -> [#session{}].
diff --git a/lib/ssl/src/ssl_sup.erl b/lib/ssl/src/ssl_sup.erl
index cb10b1362a..59039a6e0a 100644
--- a/lib/ssl/src/ssl_sup.erl
+++ b/lib/ssl/src/ssl_sup.erl
@@ -41,7 +41,6 @@ start_link() ->
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
--spec init([]) -> {ok, {SupFlags :: tuple(), [ChildSpec :: tuple()]}}.
init([]) ->
%% OLD ssl - moved start to ssl.erl only if old
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 228ec9e294..45da9ac25b 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -259,7 +259,7 @@ all() ->
no_reuses_session_server_restart_new_cert_file, reuseaddr,
hibernate, connect_twice, renegotiate_dos_mitigate_active,
renegotiate_dos_mitigate_passive,
- tcp_error_propagation_in_active_mode
+ tcp_error_propagation_in_active_mode, rizzo, no_rizzo_rc4
].
groups() ->
@@ -2347,8 +2347,8 @@ server_verify_client_once_passive(Config) when is_list(Config) ->
{options, [{active, false} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client0, ok),
- ssl_test_lib:close(Client0),
Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
+ ssl_test_lib:close(Client0),
Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2385,8 +2385,8 @@ server_verify_client_once_active(Config) when is_list(Config) ->
{options, [{active, true} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client0, ok),
- ssl_test_lib:close(Client0),
Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
+ ssl_test_lib:close(Client0),
Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2423,8 +2423,8 @@ server_verify_client_once_active_once(Config) when is_list(Config) ->
{options, [{active, once} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client0, ok),
- ssl_test_lib:close(Client0),
Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
+ ssl_test_lib:close(Client0),
Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -3033,8 +3033,8 @@ invalid_signature_server(Config) when is_list(Config) ->
{from, self()},
{options, [{verify, verify_peer} | ClientOpts]}]),
- ssl_test_lib:check_result(Server, {error, "bad certificate"},
- Client, {error,"bad certificate"}).
+ tcp_delivery_workaround(Server, {error, "bad certificate"},
+ Client, {error,"bad certificate"}).
%%--------------------------------------------------------------------
@@ -3786,7 +3786,73 @@ tcp_error_propagation_in_active_mode(Config) when is_list(Config) ->
Pid ! {tcp_error, Socket, etimedout},
ssl_test_lib:check_result(Client, {ssl_closed, SslSocket}).
+%%--------------------------------------------------------------------
+
+rizzo(doc) -> ["Test that there is a 1/n-1-split for non RC4 in 'TLS < 1.1' as it is
+ vunrable to Rizzo/Dungon attack"];
+
+rizzo(Config) when is_list(Config) ->
+ Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128],
+ run_send_recv_rizzo(Ciphers, Config, sslv3,
+ {?MODULE, send_recv_result_active_rizzo, []}),
+ run_send_recv_rizzo(Ciphers, Config, tlsv1,
+ {?MODULE, send_recv_result_active_rizzo, []}).
+
+no_rizzo_rc4(doc) ->
+ ["Test that there is no 1/n-1-split for RC4 as it is not vunrable to Rizzo/Dungon attack"];
+
+no_rizzo_rc4(Config) when is_list(Config) ->
+ Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(),Y == rc4_128],
+ run_send_recv_rizzo(Ciphers, Config, sslv3,
+ {?MODULE, send_recv_result_active_no_rizzo, []}),
+ run_send_recv_rizzo(Ciphers, Config, tlsv1,
+ {?MODULE, send_recv_result_active_no_rizzo, []}).
+
+run_send_recv_rizzo(Ciphers, Config, Version, Mfa) ->
+ Result = lists:map(fun(Cipher) ->
+ rizzo_test(Cipher, Config, Version, Mfa) end,
+ Ciphers),
+ case lists:flatten(Result) of
+ [] ->
+ ok;
+ Error ->
+ test_server:format("Cipher suite errors: ~p~n", [Error]),
+ test_server:fail(cipher_suite_failed_see_test_case_log)
+ end.
+
+rizzo_test(Cipher, Config, Version, Mfa) ->
+ {ClientOpts, ServerOpts} = client_server_opts(Cipher, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, Mfa},
+ {options, [{active, true}, {ciphers, [Cipher]},
+ {versions, [Version]}
+ | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, Mfa},
+ {options, [{active, true} | ClientOpts]}]),
+ Result = ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
+ case Result of
+ ok ->
+ [];
+ Error ->
+ [{Cipher, Error}]
+ end.
+
+client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == rsa orelse KeyAlgo == dhe_rsa ->
+ {?config(client_opts, Config),
+ ?config(server_opts, Config)};
+client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == dss orelse KeyAlgo == dhe_dss ->
+ {?config(client_dsa_opts, Config),
+ ?config(server_dsa_opts, Config)}.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -3807,6 +3873,23 @@ send_recv_result_active(Socket) ->
ok
end.
+send_recv_result_active_rizzo(Socket) ->
+ ssl:send(Socket, "Hello world"),
+ receive
+ {ssl, Socket, "H"} ->
+ receive
+ {ssl, Socket, "ello world"} ->
+ ok
+ end
+ end.
+
+send_recv_result_active_no_rizzo(Socket) ->
+ ssl:send(Socket, "Hello world"),
+ receive
+ {ssl, Socket, "Hello world"} ->
+ ok
+ end.
+
send_recv_result_active_once(Socket) ->
ssl:send(Socket, "Hello world"),
receive
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 9c4a5ce640..7f782233ef 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -242,6 +242,8 @@ check_timer(Timer) ->
case erlang:read_timer(Timer) of
false ->
{status, _, _, _} = sys:get_status(whereis(ssl_manager)),
+ timer:sleep(?SLEEP),
+ {status, _, _, _} = sys:get_status(whereis(ssl_manager)),
ok;
Int ->
test_server:sleep(Int),