diff options
| author | Ingela Anderton Andin <[email protected]> | 2016-12-06 18:20:14 +0100 | 
|---|---|---|
| committer | Ingela Anderton Andin <[email protected]> | 2017-01-19 10:24:58 +0100 | 
| commit | c6472824546dc8e6914139c2443b926d3f0945cc (patch) | |
| tree | 1bb73fadd7fb0245dca92f11d87edfe2fb2b68bc /lib/ssl/src | |
| parent | a44947369f44cb334ca45dbecca2e3f878af8229 (diff) | |
| download | otp-c6472824546dc8e6914139c2443b926d3f0945cc.tar.gz otp-c6472824546dc8e6914139c2443b926d3f0945cc.tar.bz2 otp-c6472824546dc8e6914139c2443b926d3f0945cc.zip | |
ssl: Move PEM cache to a dedicated process
The PEM cache handling has proven to be too disruptive of the manager process.
Diffstat (limited to 'lib/ssl/src')
| -rw-r--r-- | lib/ssl/src/Makefile | 15 | ||||
| -rw-r--r-- | lib/ssl/src/ssl.app.src | 13 | ||||
| -rw-r--r-- | lib/ssl/src/ssl.erl | 2 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_admin_sup.erl | 95 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_config.erl | 8 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_connection_sup.erl | 101 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_dist_admin_sup.erl | 74 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_dist_connection_sup.erl | 79 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_dist_sup.erl | 42 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_manager.erl | 183 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_pem_cache.erl | 266 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_pkix_db.erl | 67 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_sup.erl | 86 | 
13 files changed, 723 insertions, 308 deletions
| diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile index 3dda1a3316..2e7df9792e 100644 --- a/lib/ssl/src/Makefile +++ b/lib/ssl/src/Makefile @@ -48,9 +48,17 @@ MODULES= \  	dtls \  	ssl_alert \  	ssl_app \ -	ssl_dist_sup\  	ssl_sup \ +	ssl_admin_sup\ +	tls_connection_sup \ +        ssl_connection_sup \ +        ssl_listen_tracker_sup\ +	dtls_connection_sup \ +	dtls_udp_listener\  	dtls_udp_sup \ +	ssl_dist_sup\ +        ssl_dist_admin_sup\ +        ssl_dist_connection_sup\  	inet_tls_dist \  	inet6_tls_dist \  	ssl_certificate\ @@ -61,21 +69,18 @@ MODULES= \  	dtls_connection \  	ssl_config \  	ssl_connection \ -	tls_connection_sup \ -	dtls_connection_sup \  	tls_handshake \  	dtls_handshake\  	ssl_handshake\  	ssl_manager \  	ssl_session \  	ssl_session_cache \ +	ssl_pem_cache \  	ssl_crl\  	ssl_crl_cache \  	ssl_crl_hash_dir \  	tls_socket \  	dtls_socket \ -	dtls_udp_listener\ -	ssl_listen_tracker_sup \  	tls_record \  	dtls_record \  	ssl_record \ diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src index 9c5d795848..148989174d 100644 --- a/lib/ssl/src/ssl.app.src +++ b/lib/ssl/src/ssl.app.src @@ -10,12 +10,14 @@  	       tls_v1,  	       ssl_v3,  	       ssl_v2, +	       tls_connection_sup,  	       %% DTLS  	       dtls_connection,  	       dtls_handshake,  	       dtls_record,  	       dtls_socket,  	       dtls_v1, +	       dtls_connection_sup,  	       dtls_udp_listener,  	       dtls_udp_sup,  	       %% API @@ -31,16 +33,19 @@  	       ssl_cipher,  	       ssl_srp_primes,  	       ssl_alert, -	       ssl_listen_tracker_sup,	 +	       ssl_listen_tracker_sup, %% may be used by DTLS over SCTP	  	       %% Erlang Distribution over SSL/TLS  	       inet_tls_dist,  	       inet6_tls_dist,  	       ssl_tls_dist_proxy,  	       ssl_dist_sup, -	       %% SSL/TLS session handling +               ssl_dist_connection_sup, +               ssl_dist_admin_sup, +	       %% SSL/TLS session and cert handling  	       ssl_session,  	       ssl_session_cache,  	       ssl_manager, +	       ssl_pem_cache,  	       ssl_pkix_db,  	       ssl_certificate,  	       %% CRL handling @@ -51,8 +56,8 @@  	       %% App structure  	       ssl_app,  	       ssl_sup, -	       tls_connection_sup, -	       dtls_connection_sup	 +	       ssl_admin_sup, +	       ssl_connection_sup  	       ]},      {registered, [ssl_sup, ssl_manager]},      {applications, [crypto, public_key, kernel, stdlib]}, diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 0b7229b67e..4a5a7e25ea 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -577,7 +577,7 @@ prf(#sslsocket{pid = {Listen,_}}, _,_,_,_) when is_port(Listen) ->  %% Description: Clear the PEM cache  %%--------------------------------------------------------------------  clear_pem_cache() -> -    ssl_manager:clear_pem_cache(). +    ssl_pem_cache:clear().  %%---------------------------------------------------------------  -spec format_error({error, term()}) -> list(). diff --git a/lib/ssl/src/ssl_admin_sup.erl b/lib/ssl/src/ssl_admin_sup.erl new file mode 100644 index 0000000000..9c96435753 --- /dev/null +++ b/lib/ssl/src/ssl_admin_sup.erl @@ -0,0 +1,95 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%%     http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% + +-module(ssl_admin_sup). + +-behaviour(supervisor). + +%% API +-export([start_link/0, manager_opts/0]). + +%% Supervisor callback +-export([init/1]). + +%%%========================================================================= +%%%  API +%%%========================================================================= + +-spec start_link() -> {ok, pid()} | ignore | {error, term()}. +			 +start_link() -> +    supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +%%%========================================================================= +%%%  Supervisor callback +%%%========================================================================= + +init([]) ->     +    PEMCache = pem_cache_child_spec(), +    SessionCertManager = session_and_cert_manager_child_spec(), +    {ok, {{rest_for_one, 10, 3600}, [PEMCache, SessionCertManager]}}. + +manager_opts() -> +    CbOpts = case application:get_env(ssl, session_cb) of +		 {ok, Cb} when is_atom(Cb) -> +		     InitArgs = session_cb_init_args(), +		     [{session_cb, Cb}, {session_cb_init_args, InitArgs}]; +		 _  -> +		     [] +	     end, +    case application:get_env(ssl, session_lifetime) of +	{ok, Time} when is_integer(Time) -> +	    [{session_lifetime, Time}| CbOpts]; +	_  -> +	    CbOpts +    end. +     +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- + +pem_cache_child_spec() -> +    Name = ssl_pem_cache,   +    StartFunc = {ssl_pem_cache, start_link, [[]]}, +    Restart = permanent,  +    Shutdown = 4000, +    Modules = [ssl_pem_cache], +    Type = worker, +    {Name, StartFunc, Restart, Shutdown, Type, Modules}. + +session_and_cert_manager_child_spec() -> +    Opts = manager_opts(), +    Name = ssl_manager,   +    StartFunc = {ssl_manager, start_link, [Opts]}, +    Restart = permanent,  +    Shutdown = 4000, +    Modules = [ssl_manager], +    Type = worker, +    {Name, StartFunc, Restart, Shutdown, Type, Modules}. + +session_cb_init_args() -> +    case application:get_env(ssl, session_cb_init_args) of +	{ok, Args} when is_list(Args) -> +	    Args; +	_  -> +	    [] +    end. diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl index 0652d029c3..54f83928ee 100644 --- a/lib/ssl/src/ssl_config.erl +++ b/lib/ssl/src/ssl_config.erl @@ -41,9 +41,11 @@ init(SslOpts, Role) ->      {ok, CertDbRef, CertDbHandle, FileRefHandle, CacheHandle, CRLDbHandle, OwnCert, PrivateKey, DHParams}.  init_manager_name(false) -> -    put(ssl_manager, ssl_manager:manager_name(normal)); +    put(ssl_manager, ssl_manager:name(normal)), +    put(ssl_cache, ssl_pem_cache:name(normal));  init_manager_name(true) -> -    put(ssl_manager, ssl_manager:manager_name(dist)). +    put(ssl_manager, ssl_manager:name(dist)), +    put(ssl_cache, ssl_pem_cache:name(dist)).  init_certificates(#ssl_options{cacerts = CaCerts,  			       cacertfile = CACertFile, @@ -135,6 +137,8 @@ file_error(File, Throw) ->      case Throw of  	{Opt,{badmatch, {error, {badmatch, Error}}}} ->  	    throw({options, {Opt, binary_to_list(File), Error}}); +	{Opt, {badmatch, Error}} -> +	    throw({options, {Opt, binary_to_list(File), Error}});  	_ ->  	    throw(Throw)      end. diff --git a/lib/ssl/src/ssl_connection_sup.erl b/lib/ssl/src/ssl_connection_sup.erl new file mode 100644 index 0000000000..1a1f43e683 --- /dev/null +++ b/lib/ssl/src/ssl_connection_sup.erl @@ -0,0 +1,101 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%%     http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% + +-module(ssl_connection_sup). + +-behaviour(supervisor). + +%% API +-export([start_link/0]). + +%% Supervisor callback +-export([init/1]). + +%%%========================================================================= +%%%  API +%%%========================================================================= + +-spec start_link() -> {ok, pid()} | ignore | {error, term()}. +			 +start_link() -> +    supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +%%%========================================================================= +%%%  Supervisor callback +%%%========================================================================= + +init([]) ->     +   +    TLSConnetionManager = tls_connection_manager_child_spec(), +    %% Handles emulated options so that they inherited by the accept +    %% socket, even when setopts is performed on the listen socket +    ListenOptionsTracker = listen_options_tracker_child_spec(),  +     +    DTLSConnetionManager = dtls_connection_manager_child_spec(), +    DTLSUdpListeners = dtls_udp_listeners_spec(), + +    {ok, {{one_for_one, 10, 3600}, [TLSConnetionManager,  +				    ListenOptionsTracker, +				    DTLSConnetionManager,  +				    DTLSUdpListeners +				   ]}}. + +     +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- + +tls_connection_manager_child_spec() -> +    Name = tls_connection,   +    StartFunc = {tls_connection_sup, start_link, []}, +    Restart = permanent,  +    Shutdown = 4000, +    Modules = [tls_connection_sup], +    Type = supervisor, +    {Name, StartFunc, Restart, Shutdown, Type, Modules}. + +dtls_connection_manager_child_spec() -> +    Name = dtls_connection, +    StartFunc = {dtls_connection_sup, start_link, []}, +    Restart = permanent, +    Shutdown = 4000, +    Modules = [dtls_connection_sup], +    Type = supervisor, +    {Name, StartFunc, Restart, Shutdown, Type, Modules}. + +listen_options_tracker_child_spec() -> +    Name = tls_socket,   +    StartFunc = {ssl_listen_tracker_sup, start_link, []}, +    Restart = permanent,  +    Shutdown = 4000, +    Modules = [tls_socket], +    Type = supervisor, +    {Name, StartFunc, Restart, Shutdown, Type, Modules}. + +dtls_udp_listeners_spec() -> +    Name = dtls_udp_listener,   +    StartFunc = {dtls_udp_sup, start_link, []}, +    Restart = permanent,  +    Shutdown = 4000, +    Modules = [], +    Type = supervisor, +    {Name, StartFunc, Restart, Shutdown, Type, Modules}. diff --git a/lib/ssl/src/ssl_dist_admin_sup.erl b/lib/ssl/src/ssl_dist_admin_sup.erl new file mode 100644 index 0000000000..f60806c4cb --- /dev/null +++ b/lib/ssl/src/ssl_dist_admin_sup.erl @@ -0,0 +1,74 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2016-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%%     http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% + +-module(ssl_dist_admin_sup). + +-behaviour(supervisor). + +%% API +-export([start_link/0]). + +%% Supervisor callback +-export([init/1]). + +%%%========================================================================= +%%%  API +%%%========================================================================= + +-spec start_link() -> {ok, pid()} | ignore | {error, term()}. +			 +start_link() -> +    supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +%%%========================================================================= +%%%  Supervisor callback +%%%========================================================================= + +init([]) ->     +    PEMCache = pem_cache_child_spec(), +    SessionCertManager = session_and_cert_manager_child_spec(), +    {ok, {{rest_for_one, 10, 3600}, [PEMCache, SessionCertManager]}}. + + +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- + +pem_cache_child_spec() -> +    Name = ssl_pem_cache_dist,   +    StartFunc = {ssl_pem_cache, start_link_dist, [[]]}, +    Restart = permanent,  +    Shutdown = 4000, +    Modules = [ssl_pem_cache], +    Type = worker, +    {Name, StartFunc, Restart, Shutdown, Type, Modules}. + +session_and_cert_manager_child_spec() -> +    Opts = ssl_admin_sup:manager_opts(), +    Name = ssl_dist_manager,   +    StartFunc = {ssl_manager, start_link_dist, [Opts]}, +    Restart = permanent,  +    Shutdown = 4000, +    Modules = [ssl_manager], +    Type = worker, +    {Name, StartFunc, Restart, Shutdown, Type, Modules}. + diff --git a/lib/ssl/src/ssl_dist_connection_sup.erl b/lib/ssl/src/ssl_dist_connection_sup.erl new file mode 100644 index 0000000000..e5842c866e --- /dev/null +++ b/lib/ssl/src/ssl_dist_connection_sup.erl @@ -0,0 +1,79 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%%     http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% + +-module(ssl_dist_connection_sup). + +-behaviour(supervisor). + +%% API +-export([start_link/0]). + +%% Supervisor callback +-export([init/1]). + +%%%========================================================================= +%%%  API +%%%========================================================================= + +-spec start_link() -> {ok, pid()} | ignore | {error, term()}. +			 +start_link() -> +    supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +%%%========================================================================= +%%%  Supervisor callback +%%%========================================================================= + +init([]) ->     +   +    TLSConnetionManager = tls_connection_manager_child_spec(), +    %% Handles emulated options so that they inherited by the accept +    %% socket, even when setopts is performed on the listen socket +    ListenOptionsTracker = listen_options_tracker_child_spec(),  +     +    {ok, {{one_for_one, 10, 3600}, [TLSConnetionManager,  +				    ListenOptionsTracker +				   ]}}. + +     +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- + +tls_connection_manager_child_spec() -> +    Name = dist_tls_connection,   +    StartFunc = {tls_connection_sup, start_link_dist, []}, +    Restart = permanent,  +    Shutdown = 4000, +    Modules = [tls_connection_sup], +    Type = supervisor, +    {Name, StartFunc, Restart, Shutdown, Type, Modules}. + +listen_options_tracker_child_spec() -> +    Name = dist_tls_socket,   +    StartFunc = {ssl_listen_tracker_sup, start_link_dist, []}, +    Restart = permanent,  +    Shutdown = 4000, +    Modules = [tls_socket], +    Type = supervisor, +    {Name, StartFunc, Restart, Shutdown, Type, Modules}. + diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl index d47cd76bf5..690b896919 100644 --- a/lib/ssl/src/ssl_dist_sup.erl +++ b/lib/ssl/src/ssl_dist_sup.erl @@ -44,34 +44,29 @@ start_link() ->  %%%=========================================================================  init([]) ->     -    SessionCertManager = session_and_cert_manager_child_spec(), -    ConnetionManager = connection_manager_child_spec(), -    ListenOptionsTracker = listen_options_tracker_child_spec(),  +    AdminSup = ssl_admin_child_spec(), +    ConnectionSup = ssl_connection_sup(),      ProxyServer = proxy_server_child_spec(), - -    {ok, {{one_for_all, 10, 3600}, [SessionCertManager, ConnetionManager,  -				    ListenOptionsTracker, -				    ProxyServer]}}. +    {ok, {{one_for_all, 10, 3600}, [AdminSup, ProxyServer, ConnectionSup]}}.  %%--------------------------------------------------------------------  %%% Internal functions  %%-------------------------------------------------------------------- -session_and_cert_manager_child_spec() -> -    Opts = ssl_sup:manager_opts(), -    Name = ssl_manager_dist,   -    StartFunc = {ssl_manager, start_link_dist, [Opts]}, +ssl_admin_child_spec() -> +    Name = ssl_dist_admin_sup,   +    StartFunc = {ssl_dist_admin_sup, start_link , []},      Restart = permanent,       Shutdown = 4000, -    Modules = [ssl_manager], -    Type = worker, +    Modules = [ssl_admin_sup], +    Type = supervisor,      {Name, StartFunc, Restart, Shutdown, Type, Modules}. -connection_manager_child_spec() -> -    Name = ssl_connection_dist,   -    StartFunc = {tls_connection_sup, start_link_dist, []}, -    Restart = permanent,  -    Shutdown = infinity, -    Modules = [tls_connection_sup], +ssl_connection_sup() -> +    Name = ssl_dist_connection_sup, +    StartFunc = {ssl_dist_connection_sup, start_link, []}, +    Restart = permanent, +    Shutdown = 4000, +    Modules = [ssl_connection_sup],      Type = supervisor,      {Name, StartFunc, Restart, Shutdown, Type, Modules}. @@ -83,12 +78,3 @@ proxy_server_child_spec() ->      Modules = [ssl_tls_dist_proxy],      Type = worker,      {Name, StartFunc, Restart, Shutdown, Type, Modules}. - -listen_options_tracker_child_spec() -> -    Name = tls_socket_dist,   -    StartFunc = {ssl_listen_tracker_sup, start_link_dist, []}, -    Restart = permanent,  -    Shutdown = 4000, -    Modules = [tls_socket], -    Type = supervisor, -    {Name, StartFunc, Restart, Shutdown, Type, Modules}. diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index 5bd9521de7..29b15f843f 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -32,10 +32,9 @@  	 new_session_id/1, clean_cert_db/2,  	 register_session/2, register_session/3, invalidate_session/2,  	 insert_crls/2, insert_crls/3, delete_crls/1, delete_crls/2,  -	 invalidate_session/3, invalidate_pem/1, clear_pem_cache/0, manager_name/1]). +	 invalidate_session/3, name/1]). -% Spawn export --export([init_session_validator/1, init_pem_cache_validator/1]). +-export([init_session_validator/1]).  %% gen_server callbacks  -export([init/1, handle_call/3, handle_cast/2, handle_info/2, @@ -52,9 +51,7 @@  	  session_lifetime        :: integer(),  	  certificate_db          :: db_handle(),  	  session_validation_timer :: reference(), -	  last_delay_timer  = {undefined, undefined},%% Keep for testing purposes -	  last_pem_check             :: erlang:timestamp(), -	  clear_pem_cache            :: integer(), +	  last_delay_timer  = {undefined, undefined},%% Keep for testing purposes	   	  session_cache_client_max   :: integer(),  	  session_cache_server_max   :: integer(),  	  session_server_invalidator :: undefined | pid(), @@ -63,7 +60,6 @@  -define(GEN_UNIQUE_ID_MAX_TRIES, 10).  -define(SESSION_VALIDATION_INTERVAL, 60000). --define(CLEAR_PEM_CACHE, 120000).  -define(CLEAN_SESSION_DB, 60000).  -define(CLEAN_CERT_DB, 500).  -define(DEFAULT_MAX_SESSION_CACHE, 1000). @@ -74,14 +70,14 @@  %%====================================================================  %%-------------------------------------------------------------------- --spec manager_name(normal | dist) -> atom(). +-spec name(normal | dist) -> atom().  %%  %% Description: Returns the registered name of the ssl manager process  %% in the operation modes 'normal' and 'dist'.  %%-------------------------------------------------------------------- -manager_name(normal) -> +name(normal) ->      ?MODULE; -manager_name(dist) -> +name(dist) ->      list_to_atom(atom_to_list(?MODULE) ++ "dist").  %%-------------------------------------------------------------------- @@ -91,9 +87,10 @@ manager_name(dist) ->  %% and certificate caching.  %%--------------------------------------------------------------------  start_link(Opts) -> -    DistMangerName = manager_name(normal), -    gen_server:start_link({local, DistMangerName},  -			  ?MODULE, [DistMangerName, Opts], []). +    MangerName = name(normal), +    CacheName = ssl_pem_cache:name(normal), +    gen_server:start_link({local, MangerName},  +			  ?MODULE, [MangerName, CacheName, Opts], []).  %%--------------------------------------------------------------------  -spec start_link_dist(list()) -> {ok, pid()} | ignore | {error, term()}. @@ -102,9 +99,10 @@ start_link(Opts) ->  %% be used by the erlang distribution. Note disables soft upgrade!  %%--------------------------------------------------------------------  start_link_dist(Opts) -> -    DistMangerName = manager_name(dist), +    DistMangerName = name(dist), +    DistCacheName = ssl_pem_cache:name(dist),      gen_server:start_link({local, DistMangerName},  -			  ?MODULE, [DistMangerName, Opts], []). +			  ?MODULE, [DistMangerName, DistCacheName, Opts], []).  %%--------------------------------------------------------------------  -spec connection_init(binary()| {der, list()}, client | server,  @@ -115,25 +113,10 @@ start_link_dist(Opts) ->  %% Description: Do necessary initializations for a new connection.  %%--------------------------------------------------------------------  connection_init({der, _} = Trustedcerts, Role, CRLCache) -> -    case bypass_pem_cache() of -	true -> -	    {ok, Extracted} = ssl_pkix_db:extract_trusted_certs(Trustedcerts), -	    call({connection_init, Extracted, Role, CRLCache}); -	false -> -	    call({connection_init, Trustedcerts, Role, CRLCache}) -    end; - -connection_init(<<>> = Trustedcerts, Role, CRLCache) -> -    call({connection_init, Trustedcerts, Role, CRLCache}); - +    {ok, Extracted} = ssl_pkix_db:extract_trusted_certs(Trustedcerts), +    call({connection_init, Extracted, Role, CRLCache});  connection_init(Trustedcerts, Role, CRLCache) -> -    case bypass_pem_cache() of -	true -> -	    {ok, Extracted} = ssl_pkix_db:extract_trusted_certs(Trustedcerts), -	    call({connection_init, Extracted, Role, CRLCache}); -	false -> -	    call({connection_init, Trustedcerts, Role, CRLCache}) -    end. +    call({connection_init, Trustedcerts, Role, CRLCache}).  %%--------------------------------------------------------------------  -spec cache_pem_file(binary(), term()) -> {ok, term()} | {error, reason()}. @@ -141,31 +124,14 @@ connection_init(Trustedcerts, Role, CRLCache) ->  %% Description: Cache a pem file and return its content.  %%--------------------------------------------------------------------  cache_pem_file(File, DbHandle) -> -    case bypass_pem_cache() of -	true -> -	    ssl_pkix_db:decode_pem_file(File); -	false -> -	    case ssl_pkix_db:lookup_cached_pem(DbHandle, File) of -		[{Content,_}] -> -		    {ok, Content}; -		[Content] -> -		    {ok, Content}; -		undefined -> -		    call({cache_pem, File}) -	    end +    case ssl_pkix_db:lookup(File, DbHandle) of +	[Content]  -> +	    {ok, Content}; +	undefined -> +	  ssl_pem_cache:insert(File)      end.  %%-------------------------------------------------------------------- --spec clear_pem_cache() -> ok. -%% -%% Description: Clear the PEM cache -%%-------------------------------------------------------------------- -clear_pem_cache() -> -    %% Not supported for distribution at the moement, should it be? -    put(ssl_manager, manager_name(normal)), -    call(unconditionally_clear_pem_cache). - -%%--------------------------------------------------------------------  -spec lookup_trusted_cert(term(), reference(), serialnumber(), issuer()) ->  				 undefined |   				 {ok, {der_cert(), #'OTPCertificate'{}}}. @@ -222,26 +188,22 @@ invalidate_session(Port, Session) ->      load_mitigation(),      cast({invalidate_session, Port, Session}). --spec invalidate_pem(File::binary()) -> ok. -invalidate_pem(File) -> -    cast({invalidate_pem, File}). -  insert_crls(Path, CRLs)->      insert_crls(Path, CRLs, normal).  insert_crls(?NO_DIST_POINT_PATH = Path, CRLs, ManagerType)-> -    put(ssl_manager, manager_name(ManagerType)), +    put(ssl_manager, name(ManagerType)),      cast({insert_crls, Path, CRLs});  insert_crls(Path, CRLs, ManagerType)-> -    put(ssl_manager, manager_name(ManagerType)), +    put(ssl_manager, name(ManagerType)),      call({insert_crls, Path, CRLs}).  delete_crls(Path)->      delete_crls(Path, normal).  delete_crls(?NO_DIST_POINT_PATH = Path, ManagerType)-> -    put(ssl_manager, manager_name(ManagerType)), +    put(ssl_manager, name(ManagerType)),      cast({delete_crls, Path});  delete_crls(Path, ManagerType)-> -    put(ssl_manager, manager_name(ManagerType)), +    put(ssl_manager, name(ManagerType)),      call({delete_crls, Path}).  %%==================================================================== @@ -255,8 +217,9 @@ delete_crls(Path, ManagerType)->  %%  %% Description: Initiates the server  %%-------------------------------------------------------------------- -init([Name, Opts]) -> -    put(ssl_manager, Name), +init([ManagerName, PemCacheName, Opts]) -> +    put(ssl_manager, ManagerName), +    put(ssl_pem_cache, PemCacheName),      process_flag(trap_exit, true),      CacheCb = proplists:get_value(session_cb, Opts, ssl_session_cache),      SessionLifeTime =   @@ -270,16 +233,12 @@ init([Name, Opts]) ->  		      proplists:get_value(session_cb_init_args, Opts, [])]),      Timer = erlang:send_after(SessionLifeTime * 1000 + 5000,   			      self(), validate_sessions), -    Interval = pem_check_interval(), -    erlang:send_after(Interval, self(), clear_pem_cache),      {ok, #state{certificate_db = CertDb,  		session_cache_client = ClientSessionCache,  		session_cache_server = ServerSessionCache,  		session_cache_cb = CacheCb,  		session_lifetime = SessionLifeTime,  		session_validation_timer = Timer, -		last_pem_check =  os:timestamp(), -		clear_pem_cache = Interval, 	  		session_cache_client_max =   		    max_session_cache_size(session_cache_client_max),  		session_cache_server_max =  @@ -330,21 +289,7 @@ handle_call({{new_session_id, Port}, _},  	    _, #state{session_cache_cb = CacheCb,  		      session_cache_server = Cache} = State) ->      Id = new_id(Port, ?GEN_UNIQUE_ID_MAX_TRIES, Cache, CacheCb), -    {reply, Id, State}; - -handle_call({{cache_pem,File}, _Pid}, _, -	    #state{certificate_db = Db} = State) -> -    try ssl_pkix_db:cache_pem_file(File, Db) of -	Result -> -	    {reply, Result, State} -    catch  -	_:Reason -> -	    {reply, {error, Reason}, State} -    end; -handle_call({unconditionally_clear_pem_cache, _},_,  -	    #state{certificate_db = [_,_,PemChace | _]} = State) -> -    ssl_pkix_db:clear(PemChace), -    {reply, ok,  State}. +    {reply, Id, State}.  %%--------------------------------------------------------------------  -spec  handle_cast(msg(), #state{}) -> {noreply, #state{}}. @@ -382,11 +327,6 @@ handle_cast({insert_crls, Path, CRLs},  handle_cast({delete_crls, CRLsOrPath},     	    #state{certificate_db = Db} = State) ->      ssl_pkix_db:remove_crls(Db, CRLsOrPath), -    {noreply, State}; - -handle_cast({invalidate_pem, File}, -	    #state{certificate_db = [_, _, PemCache | _]} = State) -> -    ssl_pkix_db:remove(File, PemCache),      {noreply, State}.  %%-------------------------------------------------------------------- @@ -418,22 +358,14 @@ handle_info({delayed_clean_session, Key, Cache}, #state{session_cache_cb = Cache      CacheCb:delete(Cache, Key),      {noreply, State}; -handle_info(clear_pem_cache, #state{certificate_db = [_,_,PemChace | _], -				    clear_pem_cache = Interval, -				    last_pem_check = CheckPoint} = State) -> -    NewCheckPoint = os:timestamp(), -    start_pem_cache_validator(PemChace, CheckPoint), -    erlang:send_after(Interval, self(), clear_pem_cache), -    {noreply, State#state{last_pem_check = NewCheckPoint}}; -  handle_info({clean_cert_db, Ref, File}, -	    #state{certificate_db = [CertDb,RefDb, PemCache | _]} = State) -> +	    #state{certificate_db = [CertDb, {RefDb, FileMapDb} | _]} = State) ->      case ssl_pkix_db:lookup(Ref, RefDb) of  	undefined -> %% Alredy cleaned  	    ok;  	_ -> -	    clean_cert_db(Ref, CertDb, RefDb, PemCache, File) +	    clean_cert_db(Ref, CertDb, RefDb, FileMapDb, File)      end,      {noreply, State}; @@ -523,14 +455,6 @@ delay_time() ->  	   ?CLEAN_SESSION_DB      end. -bypass_pem_cache() -> -    case application:get_env(ssl, bypass_pem_cache) of -	{ok, Bool} when is_boolean(Bool) -> -	    Bool; -	_ -> -	    false -    end. -  max_session_cache_size(CacheType) ->      case application:get_env(ssl, CacheType) of  	{ok, Size} when is_integer(Size) -> @@ -594,16 +518,11 @@ new_id(Port, Tries, Cache, CacheCb) ->  	    new_id(Port, Tries - 1, Cache, CacheCb)      end. -clean_cert_db(Ref, CertDb, RefDb, PemCache, File) -> +clean_cert_db(Ref, CertDb, RefDb, FileMapDb, File) ->      case ssl_pkix_db:ref_count(Ref, RefDb, 0) of  	0 ->	   -	    case ssl_pkix_db:lookup_cached_pem(PemCache, File) of -		[{Content, Ref}] -> -		    ssl_pkix_db:insert(File, Content, PemCache);		 -		_ -> -		    ok -	    end,  	    ssl_pkix_db:remove(Ref, RefDb), +	    ssl_pkix_db:remove(File, FileMapDb),  	    ssl_pkix_db:remove_trusted_certs(Ref, CertDb);  	_ ->  	    ok @@ -687,42 +606,6 @@ exists_equivalent(#session{  exists_equivalent(Session, [ _ | Rest]) ->      exists_equivalent(Session, Rest). -start_pem_cache_validator(PemCache, CheckPoint) -> -    spawn_link(?MODULE, init_pem_cache_validator,  -	       [[get(ssl_manager), PemCache, CheckPoint]]). - -init_pem_cache_validator([SslManagerName, PemCache, CheckPoint]) -> -    put(ssl_manager, SslManagerName), -    ssl_pkix_db:foldl(fun pem_cache_validate/2, -		      CheckPoint, PemCache). - -pem_cache_validate({File, _}, CheckPoint) -> -    case file:read_file_info(File, []) of -	{ok, #file_info{mtime = Time}} -> -	    case is_before_checkpoint(Time, CheckPoint) of -		true -> -		    ok; -		false -> -		    invalidate_pem(File) -	    end; -	_  -> -	    invalidate_pem(File) -    end, -    CheckPoint. - -pem_check_interval() -> -    case application:get_env(ssl, ssl_pem_cache_clean) of -	{ok, Interval} when is_integer(Interval) -> -	    Interval; -	_  -> -	    ?CLEAR_PEM_CACHE -    end. -	 -is_before_checkpoint(Time, CheckPoint) -> -    calendar:datetime_to_gregorian_seconds( -      calendar:now_to_datetime(CheckPoint)) - -    calendar:datetime_to_gregorian_seconds(Time) > 0. -  add_trusted_certs(Pid, Trustedcerts, Db) ->      try  	ssl_pkix_db:add_trusted_certs(Pid, Trustedcerts, Db) 	     diff --git a/lib/ssl/src/ssl_pem_cache.erl b/lib/ssl/src/ssl_pem_cache.erl new file mode 100644 index 0000000000..2b31374bcc --- /dev/null +++ b/lib/ssl/src/ssl_pem_cache.erl @@ -0,0 +1,266 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 20016-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%%     http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Manages ssl sessions and trusted certifacates +%%---------------------------------------------------------------------- + +-module(ssl_pem_cache). +-behaviour(gen_server). + +%% Internal application API +-export([start_link/1,  +	 start_link_dist/1, +	 name/1, +	 insert/1, +	 clear/0]). + +% Spawn export +-export([init_pem_cache_validator/1]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, +	 terminate/2, code_change/3]). + +-include("ssl_handshake.hrl"). +-include("ssl_internal.hrl"). +-include_lib("kernel/include/file.hrl"). + +-record(state, { +	  pem_cache,                   +	  last_pem_check             :: erlang:timestamp(), +	  clear            :: integer() +	 }). + +-define(CLEAR_PEM_CACHE, 120000). +-define(DEFAULT_MAX_SESSION_CACHE, 1000). + +%%==================================================================== +%% API +%%==================================================================== + +%%-------------------------------------------------------------------- +-spec name(normal | dist) -> atom(). +%% +%% Description: Returns the registered name of the ssl cache process +%% in the operation modes 'normal' and 'dist'. +%%-------------------------------------------------------------------- +name(normal) -> +    ?MODULE; +name(dist) -> +    list_to_atom(atom_to_list(?MODULE) ++ "dist"). + +%%-------------------------------------------------------------------- +-spec start_link(list()) -> {ok, pid()} | ignore | {error, term()}. +%% +%% Description: Starts the ssl pem cache handler  +%%-------------------------------------------------------------------- +start_link(_) -> +    CacheName = name(normal), +    gen_server:start_link({local, CacheName},  +			  ?MODULE, [CacheName], []). + +%%-------------------------------------------------------------------- +-spec start_link_dist(list()) -> {ok, pid()} | ignore | {error, term()}. +%% +%% Description: Starts a special instance of the ssl manager to +%% be used by the erlang distribution. Note disables soft upgrade! +%%-------------------------------------------------------------------- +start_link_dist(_) -> +    DistCacheName = name(dist), +    gen_server:start_link({local, DistCacheName},  +			  ?MODULE, [DistCacheName], []). + + +%%-------------------------------------------------------------------- +-spec insert(binary()) -> {ok, term()} | {error, reason()}. +%%		     +%% Description: Cache a pem file and return its content. +%%-------------------------------------------------------------------- +insert(File) ->     +    {ok, PemBin} = file:read_file(File), +    Content = public_key:pem_decode(PemBin), +    case bypass_cache() of +	true -> +	    {ok, Content}; +	false -> +	    cast({cache_pem, File, Content}), +	    {ok, Content} +    end. + +%%-------------------------------------------------------------------- +-spec clear() -> ok. +%% +%% Description: Clear the PEM cache +%%-------------------------------------------------------------------- +clear() -> +    %% Not supported for distribution at the moement, should it be? +    put(ssl_pem_cache, name(normal)), +    call(unconditionally_clear_pem_cache). + +-spec invalidate_pem(File::binary()) -> ok. +invalidate_pem(File) -> +    cast({invalidate_pem, File}). + +%%==================================================================== +%% gen_server callbacks +%%==================================================================== + +%%-------------------------------------------------------------------- +-spec init(list()) -> {ok, #state{}}. +%% Possible return values not used now.  +%% |  {ok, #state{}, timeout()} | ignore | {stop, term()}.		   +%% +%% Description: Initiates the server +%%-------------------------------------------------------------------- +init([Name]) -> +    put(ssl_pem_cache, Name), +    process_flag(trap_exit, true), +    PemCache = ssl_pkix_db:create_pem_cache(), +    Interval = pem_check_interval(), +    erlang:send_after(Interval, self(), clear_pem_cache), +    {ok, #state{pem_cache = PemCache, +		last_pem_check =  os:timestamp(), +		clear = Interval 	 +	       }}. + +%%-------------------------------------------------------------------- +-spec handle_call(msg(), from(), #state{}) -> {reply, reply(), #state{}}.  +%% Possible return values not used now.   +%%					      {reply, reply(), #state{}, timeout()} | +%%					      {noreply, #state{}} | +%%					      {noreply, #state{}, timeout()} | +%%					      {stop, reason(), reply(), #state{}} | +%%					      {stop, reason(), #state{}}. +%% +%% Description: Handling call messages +%%-------------------------------------------------------------------- +handle_call({unconditionally_clear_pem_cache, _},_,  +	    #state{pem_cache = PemCache} = State) -> +    ssl_pkix_db:clear(PemCache), +    {reply, ok,  State}. + +%%-------------------------------------------------------------------- +-spec  handle_cast(msg(), #state{}) -> {noreply, #state{}}. +%% Possible return values not used now.   +%%				      | {noreply, #state{}, timeout()} | +%%				       {stop, reason(), #state{}}. +%% +%% Description: Handling cast messages +%%-------------------------------------------------------------------- +handle_cast({cache_pem, File, Content}, #state{pem_cache = Db} = State) -> +    ssl_pkix_db:insert(File, Content, Db),  +    {noreply, State}; + +handle_cast({invalidate_pem, File}, #state{pem_cache = Db} = State) -> +    ssl_pkix_db:remove(File, Db), +    {noreply, State}. + + +%%-------------------------------------------------------------------- +-spec handle_info(msg(), #state{}) -> {noreply, #state{}}. +%% Possible return values not used now. +%%				      |{noreply, #state{}, timeout()} | +%%				      {stop, reason(), #state{}}. +%% +%% Description: Handling all non call/cast messages +%%------------------------------------------------------------------- +handle_info(clear_pem_cache, #state{pem_cache = PemCache, +				    clear = Interval, +				    last_pem_check = CheckPoint} = State) -> +    NewCheckPoint = os:timestamp(), +    start_pem_cache_validator(PemCache, CheckPoint), +    erlang:send_after(Interval, self(), clear_pem_cache), +    {noreply, State#state{last_pem_check = NewCheckPoint}}; + +handle_info(_Info, State) -> +    {noreply, State}. + +%%-------------------------------------------------------------------- +-spec terminate(reason(), #state{}) -> ok. +%%		        +%% Description: This function is called by a gen_server 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_server terminates with Reason. +%% The return value is ignored. +%%-------------------------------------------------------------------- +terminate(_Reason, #state{}) -> +    ok. + +%%-------------------------------------------------------------------- +-spec code_change(term(), #state{}, list()) -> {ok, #state{}}.			  +%% +%% Description: Convert process state when code is changed +%%-------------------------------------------------------------------- +code_change(_OldVsn, State, _Extra) -> +    {ok, State}. + +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- +call(Msg) -> +    gen_server:call(get(ssl_pem_cache), {Msg, self()}, infinity). + +cast(Msg) -> +    gen_server:cast(get(ssl_pem_cache), Msg). + +start_pem_cache_validator(PemCache, CheckPoint) -> +    spawn_link(?MODULE, init_pem_cache_validator,  +	       [[get(ssl_pem_cache), PemCache, CheckPoint]]). + +init_pem_cache_validator([CacheName, PemCache, CheckPoint]) -> +    put(ssl_pem_cache, CacheName), +    ssl_pkix_db:foldl(fun pem_cache_validate/2, +		      CheckPoint, PemCache). + +pem_cache_validate({File, _}, CheckPoint) -> +    case file:read_file_info(File, []) of +	{ok, #file_info{mtime = Time}} -> +	    case is_before_checkpoint(Time, CheckPoint) of +		true -> +		    ok; +		false -> +		    invalidate_pem(File) +	    end; +	_  -> +	    invalidate_pem(File) +    end, +    CheckPoint. + +is_before_checkpoint(Time, CheckPoint) -> +    calendar:datetime_to_gregorian_seconds( +      calendar:now_to_datetime(CheckPoint)) - +	calendar:datetime_to_gregorian_seconds(Time) > 0. + +pem_check_interval() -> +    case application:get_env(ssl, ssl_pem_cache_clean) of +	{ok, Interval} when is_integer(Interval) -> +	    Interval; +	_  -> +	    ?CLEAR_PEM_CACHE +    end. + +bypass_cache() -> +    case application:get_env(ssl, bypass_pem_cache) of +	{ok, Bool} when is_boolean(Bool) -> +	    Bool; +	_ -> +	    false +    end. diff --git a/lib/ssl/src/ssl_pkix_db.erl b/lib/ssl/src/ssl_pkix_db.erl index b4299969e4..961a555873 100644 --- a/lib/ssl/src/ssl_pkix_db.erl +++ b/lib/ssl/src/ssl_pkix_db.erl @@ -28,11 +28,11 @@  -include_lib("public_key/include/public_key.hrl").  -include_lib("kernel/include/file.hrl"). --export([create/0, add_crls/3, remove_crls/2, remove/1, add_trusted_certs/3,  +-export([create/0, create_pem_cache/0,  +	 add_crls/3, remove_crls/2, remove/1, add_trusted_certs/3,   	 extract_trusted_certs/1,  	 remove_trusted_certs/2, insert/3, remove/2, clear/1, db_size/1,  	 ref_count/3, lookup_trusted_cert/4, foldl/3, select_cert_by_issuer/2, -	 lookup_cached_pem/2, cache_pem_file/2, cache_pem_file/3,  	 decode_pem_file/1, lookup/2]).  %%==================================================================== @@ -52,13 +52,19 @@ create() ->       %% on DER format to ssl:connect/listen.)       ets:new(ssl_otp_cacertificate_db, [set, public]),       %% Let connection processes call ref_count/3 directly -     ets:new(ssl_otp_ca_file_ref, [set, public]), -     ets:new(ssl_otp_pem_cache, [set, protected]), +     {ets:new(ssl_otp_ca_file_ref, [set, public]), +      ets:new(ssl_otp_ca_ref_file_mapping, [set, protected]) +     }, +     %% Lookups in named table owned by ssl_pem_cache process +     ssl_otp_pem_cache,       %% Default cache       {ets:new(ssl_otp_crl_cache, [set, protected]),        ets:new(ssl_otp_crl_issuer_mapping, [bag, protected])}      ]. +create_pem_cache() -> +    ets:new(ssl_otp_pem_cache, [named_table, set, protected]). +  %%--------------------------------------------------------------------  -spec remove([db_handle()]) -> ok.   %% @@ -70,6 +76,8 @@ remove(Dbs) ->  			  true = ets:delete(Db1);  		     (undefined) ->   			  ok; +		     (ssl_otp_pem_cache) ->  +			  ok;  		     (Db) ->  			  true = ets:delete(Db)  		  end, Dbs). @@ -101,11 +109,6 @@ lookup_trusted_cert(_DbHandle, {extracted,Certs}, SerialNumber, Issuer) ->  	    {ok, Cert}      end. -lookup_cached_pem([_, _, PemChache | _], File) -> -    lookup_cached_pem(PemChache, File); -lookup_cached_pem(PemChache, File) -> -    lookup(File, PemChache). -  %%--------------------------------------------------------------------  -spec add_trusted_certs(pid(), {erlang:timestamp(), string()} |  			{der, list()}, [db_handle()]) -> {ok, [db_handle()]}. @@ -122,17 +125,11 @@ add_trusted_certs(_Pid, {der, DerList}, [CertDb, _,_ | _]) ->      add_certs_from_der(DerList, NewRef, CertDb),      {ok, NewRef}; -add_trusted_certs(_Pid, File, [CertsDb, RefDb, PemChache | _] = Db) -> -    case lookup_cached_pem(Db, File) of -	[{_Content, Ref}] -> +add_trusted_certs(_Pid, File, [ _, {RefDb, FileMapDb} | _] = Db) -> +    case lookup(File, FileMapDb) of +	[Ref] ->  	    ref_count(Ref, RefDb, 1),  	    {ok, Ref}; -	[Content] -> -	    Ref = make_ref(), -	    update_counter(Ref, 1, RefDb), -	    insert(File, {Content, Ref}, PemChache), -	    add_certs_from_pem(Content, Ref, CertsDb), -	    {ok, Ref};  	undefined ->  	    new_trusted_cert_entry(File, Db)      end. @@ -151,25 +148,6 @@ extract_trusted_certs(File) ->              {error, {badmatch, Error}}      end. -%%-------------------------------------------------------------------- -%% -%% Description: Cache file as binary in DB -%%-------------------------------------------------------------------- --spec cache_pem_file(binary(), [db_handle()]) -> {ok, term()}. -cache_pem_file(File, [_CertsDb, _RefDb, PemChache | _]) -> -    {ok, PemBin} = file:read_file(File), -    Content = public_key:pem_decode(PemBin), -    insert(File, Content, PemChache), -    {ok, Content}. - - --spec cache_pem_file(reference(), binary(), [db_handle()]) -> {ok, term()}. -cache_pem_file(Ref, File, [_CertsDb, _RefDb, PemChache| _]) -> -    {ok, PemBin} = file:read_file(File), -    Content = public_key:pem_decode(PemBin), -    insert(File, {Content, Ref}, PemChache), -    {ok, Content}. -  -spec decode_pem_file(binary()) -> {ok, term()}.  decode_pem_file(File) ->      case file:read_file(File) of @@ -246,6 +224,8 @@ select_cert_by_issuer(Cache, Issuer) ->  %%--------------------------------------------------------------------  ref_count({extracted, _}, _Db, _N) ->      not_cached; +ref_count(Key, {Db, _}, N) -> +    ref_count(Key, Db, N);  ref_count(Key, Db, N) ->      ets:update_counter(Db,Key,N). @@ -278,9 +258,9 @@ insert(Key, Data, Db) ->  %%--------------------------------------------------------------------  %%% Internal functions  %%-------------------------------------------------------------------- -update_counter(Key, Count, Db) -> -    true = ets:insert(Db, {Key, Count}), -    ok. +init_ref_db(Ref, File, {RefDb, FileMapDb}) -> +    true = ets:insert(RefDb, {Ref, 1}), +    true = ets:insert(FileMapDb, {File, Ref}).  remove_certs(Ref, CertsDb) ->      true = ets:match_delete(CertsDb, {{Ref, '_', '_'}, '_'}), @@ -326,10 +306,10 @@ decode_certs(Ref, Cert) ->  	    undefined      end. -new_trusted_cert_entry(File, [CertsDb, RefDb, _ | _] = Db) -> +new_trusted_cert_entry(File, [CertsDb, RefsDb, _ | _]) ->      Ref = make_ref(), -    update_counter(Ref, 1, RefDb), -    {ok, Content} = cache_pem_file(Ref, File, Db), +    init_ref_db(Ref, File, RefsDb), +    {ok, Content} = ssl_pem_cache:insert(File),      add_certs_from_pem(Content, Ref, CertsDb),      {ok, Ref}. @@ -361,4 +341,3 @@ crl_issuer(DerCRL) ->      CRL = public_key:der_decode('CertificateList', DerCRL),      TBSCRL = CRL#'CertificateList'.tbsCertList,      TBSCRL#'TBSCertList'.issuer. - diff --git a/lib/ssl/src/ssl_sup.erl b/lib/ssl/src/ssl_sup.erl index 8245801139..05a7aaaa82 100644 --- a/lib/ssl/src/ssl_sup.erl +++ b/lib/ssl/src/ssl_sup.erl @@ -25,7 +25,7 @@  -behaviour(supervisor).  %% API --export([start_link/0, manager_opts/0]). +-export([start_link/0]).  %% Supervisor callback  -export([init/1]). @@ -44,90 +44,28 @@ start_link() ->  %%%=========================================================================  init([]) ->     -    SessionCertManager = session_and_cert_manager_child_spec(), -    TLSConnetionManager = tls_connection_manager_child_spec(), -    %% Handles emulated options so that they inherited by the accept -    %% socket, even when setopts is performed on the listen socket -    ListenOptionsTracker = listen_options_tracker_child_spec(),  -     -    DTLSConnetionManager = dtls_connection_manager_child_spec(), -    DTLSUdpListeners = dtls_udp_listeners_spec(), +    {ok, {{rest_for_one, 10, 3600}, [ssl_admin_child_spec(), +				     ssl_connection_sup() +				    ]}}. -    {ok, {{one_for_all, 10, 3600}, [SessionCertManager, TLSConnetionManager,  -				    ListenOptionsTracker, -				    DTLSConnetionManager, DTLSUdpListeners -				   ]}}. - - -manager_opts() -> -    CbOpts = case application:get_env(ssl, session_cb) of -		 {ok, Cb} when is_atom(Cb) -> -		     InitArgs = session_cb_init_args(), -		     [{session_cb, Cb}, {session_cb_init_args, InitArgs}]; -		 _  -> -		     [] -	     end, -    case application:get_env(ssl, session_lifetime) of -	{ok, Time} when is_integer(Time) -> -	    [{session_lifetime, Time}| CbOpts]; -	_  -> -	    CbOpts -    end. -      %%--------------------------------------------------------------------  %%% Internal functions  %%-------------------------------------------------------------------- - -session_and_cert_manager_child_spec() -> -    Opts = manager_opts(), -    Name = ssl_manager,   -    StartFunc = {ssl_manager, start_link, [Opts]}, +ssl_admin_child_spec() -> +    Name = ssl_admin_sup,   +    StartFunc = {ssl_admin_sup, start_link, []},      Restart = permanent,       Shutdown = 4000, -    Modules = [ssl_manager], -    Type = worker, -    {Name, StartFunc, Restart, Shutdown, Type, Modules}. - -tls_connection_manager_child_spec() -> -    Name = tls_connection,   -    StartFunc = {tls_connection_sup, start_link, []}, -    Restart = permanent,  -    Shutdown = 4000, -    Modules = [tls_connection_sup], +    Modules = [ssl_admin_sup],      Type = supervisor,      {Name, StartFunc, Restart, Shutdown, Type, Modules}. -dtls_connection_manager_child_spec() -> -    Name = dtls_connection, -    StartFunc = {dtls_connection_sup, start_link, []}, +ssl_connection_sup() -> +    Name = ssl_connection_sup, +    StartFunc = {ssl_connection_sup, start_link, []},      Restart = permanent,      Shutdown = 4000, -    Modules = [dtls_connection_sup], -    Type = supervisor, -    {Name, StartFunc, Restart, Shutdown, Type, Modules}. - -listen_options_tracker_child_spec() -> -    Name = tls_socket,   -    StartFunc = {ssl_listen_tracker_sup, start_link, []}, -    Restart = permanent,  -    Shutdown = 4000, -    Modules = [tls_socket], -    Type = supervisor, -    {Name, StartFunc, Restart, Shutdown, Type, Modules}. - -dtls_udp_listeners_spec() -> -    Name = dtls_udp_listener,   -    StartFunc = {dtls_udp_sup, start_link, []}, -    Restart = permanent,  -    Shutdown = 4000, -    Modules = [], +    Modules = [ssl_connection_sup],      Type = supervisor,      {Name, StartFunc, Restart, Shutdown, Type, Modules}. -session_cb_init_args() -> -    case application:get_env(ssl, session_cb_init_args) of -	{ok, Args} when is_list(Args) -> -	    Args; -	_  -> -	    [] -    end. | 
