Skip to content

Commit 8c03803

Browse files
committed
ssl: Add max value for CRL cache
1 parent d9454db commit 8c03803

5 files changed

Lines changed: 104 additions & 59 deletions

File tree

lib/ssl/doc/ssl_app.md

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,53 @@ The environment parameters can be set on the command line, for example:
6565
might be configurable, by the SSL application. This option can be overridden
6666
by the version option to `ssl:connect/2,3` and `ssl:listen/2`.
6767

68+
- **`max_crl_cache = pos_integer() <optional>`** - Sets the
69+
maximum number of entries allowed in the default crl store. Defaults to 150. Size limit
70+
is enforced by emptying cache when limit is reached.
71+
72+
- **`ssl_pem_cache_clean = pos_integer() <optional>`** - Number of milliseconds
73+
between PEM cache validations. Defaults to 2 minutes.
74+
75+
Note: The cache can be reloaded by calling `ssl:clear_pem_cache/0`.
76+
77+
- **`bypass_pem_cache = boolean() <optional>`** - Introduced in ssl-8.0.2.
78+
Disables the PEM-cache. Can be used as a workaround for the PEM-cache
79+
bottleneck before ssl-8.1.1. Defaults to false.
80+
81+
- **`internal_active_n = integer() <optional>`** - For TLS connections this
82+
value is used to handle the internal socket. As the implementation was changed
83+
from an active once to an active N behavior (N = 100), for performance
84+
reasons, this option exist for possible tweaking or restoring of the old
85+
behavior (internal_active_n = 1) in unforeseen scenarios. The option will not
86+
affect erlang distribution over TLS that will always run in active N mode.
87+
Added in ssl-9.1 (OTP-21.2).
88+
89+
- **`server_session_tickets_amount = integer() <optional>`** - Number of session
90+
tickets sent by the server. It must be greater than 0. Defaults to 3.
91+
92+
- **`server_session_ticket_lifetime = integer() <optional>`** - Lifetime of
93+
session tickets sent by the server. Servers must not use any value greater
94+
than 604800 seconds (7 days). Expired tickets are automatically removed.
95+
Defaults to 7200 seconds (2 hours).
96+
97+
- **`server_session_ticket_store_size = integer() <optional>`** - Sets the
98+
maximum size of the server session ticket store (stateful tickets). Defaults
99+
to 1000. Size limit is enforced by dropping old tickets.
100+
101+
- **`server_session_ticket_max_early_data = integer() <optional>`** - Sets the
102+
maximum size of the early data that the server accepts and also configures its
103+
NewSessionTicket messages to include this same size limit in their
104+
early_data_indication extension. Defaults to 16384. Size limit is enforced by
105+
both client and server.
106+
107+
- **`client_session_ticket_lifetime = integer() <optional>`** - Lifetime of
108+
session tickets in the client ticket store. Expired tickets are automatically
109+
removed. Defaults to 7200 seconds (2 hours).
110+
111+
- **`client_session_ticket_store_size = integer() <optional>`** - Sets the
112+
maximum size of the client session ticket store. Defaults to 1000. Size limit
113+
is enforced by dropping old tickets.
114+
68115
- **`session_lifetime = integer() <optional>`** - Maximum lifetime of the
69116
session data in seconds. Defaults to 24 hours which is the maximum recommended
70117
lifetime by [RFC 5246](http://www.ietf.org/rfc/5246rfc.txt). However sessions
@@ -108,54 +155,11 @@ The environment parameters can be set on the command line, for example:
108155
entries will be invalidated regardless of their remaining lifetime. Defaults
109156
to 1000. Recommended ssl-8.2.1 or later for this option to work as intended.
110157

111-
- **`ssl_pem_cache_clean = integer() <optional>`** - Number of milliseconds
112-
between PEM cache validations. Defaults to 2 minutes.
113-
114-
Note: The cache can be reloaded by calling `ssl:clear_pem_cache/0`.
115-
116-
- **`bypass_pem_cache = boolean() <optional>`** - Introduced in ssl-8.0.2.
117-
Disables the PEM-cache. Can be used as a workaround for the PEM-cache
118-
bottleneck before ssl-8.1.1. Defaults to false.
119-
120-
- **`alert_timeout = integer() <optional>`** - Number of milliseconds between
158+
- **`alert_timeout = pos_integer() <optional>`** - Number of milliseconds between
121159
sending of a fatal alert and closing the connection. Waiting a little while
122160
improves the peers chances to properly receiving the alert so it may shutdown
123161
gracefully. Defaults to 5000 milliseconds.
124162

125-
- **`internal_active_n = integer() <optional>`** - For TLS connections this
126-
value is used to handle the internal socket. As the implementation was changed
127-
from an active once to an active N behavior (N = 100), for performance
128-
reasons, this option exist for possible tweaking or restoring of the old
129-
behavior (internal_active_n = 1) in unforeseen scenarios. The option will not
130-
affect erlang distribution over TLS that will always run in active N mode.
131-
Added in ssl-9.1 (OTP-21.2).
132-
133-
- **`server_session_tickets_amount = integer() <optional>`** - Number of session
134-
tickets sent by the server. It must be greater than 0. Defaults to 3.
135-
136-
- **`server_session_ticket_lifetime = integer() <optional>`** - Lifetime of
137-
session tickets sent by the server. Servers must not use any value greater
138-
than 604800 seconds (7 days). Expired tickets are automatically removed.
139-
Defaults to 7200 seconds (2 hours).
140-
141-
- **`server_session_ticket_store_size = integer() <optional>`** - Sets the
142-
maximum size of the server session ticket store (stateful tickets). Defaults
143-
to 1000. Size limit is enforced by dropping old tickets.
144-
145-
- **`server_session_ticket_max_early_data = integer() <optional>`** - Sets the
146-
maximum size of the early data that the server accepts and also configures its
147-
NewSessionTicket messages to include this same size limit in their
148-
early_data_indication extension. Defaults to 16384. Size limit is enforced by
149-
both client and server.
150-
151-
- **`client_session_ticket_lifetime = integer() <optional>`** - Lifetime of
152-
session tickets in the client ticket store. Expired tickets are automatically
153-
removed. Defaults to 7200 seconds (2 hours).
154-
155-
- **`client_session_ticket_store_size = integer() <optional>`** - Sets the
156-
maximum size of the client session ticket store. Defaults to 1000. Size limit
157-
is enforced by dropping old tickets.
158-
159163
## Error Logger and Event Handlers
160164

161165
The SSL application uses [OTP logger](`m:logger`). TLS/DTLS alerts are logged on

lib/ssl/src/ssl_config.erl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
-define(DEFAULT_MAX_SESSION_CACHE, 1000).
3333
-define(TWO_HOURS, 7200).
3434
-define(SEVEN_DAYS, 604800).
35+
-define(DEFAULT_MAX_CRL_CACHE, 150).
36+
-define(INTERNAL_ACTIVE_N, 100).
3537

3638
%% Connection parameter configuration
3739
-export([init/2,
@@ -44,6 +46,7 @@
4446
%% Application configuration
4547
-export([pre_1_3_session_opts/1,
4648
get_max_early_data_size/0,
49+
get_max_crl_cache/0,
4750
get_ticket_lifetime/0,
4851
get_ticket_store_size/0,
4952
get_internal_active_n/0,
@@ -138,6 +141,14 @@ get_internal_active_n(true) ->
138141
get_internal_active_n(false) ->
139142
application_int(internal_active_n, ?INTERNAL_ACTIVE_N).
140143

144+
get_max_crl_cache() ->
145+
case application:get_env(ssl, max_crl_cache) of
146+
{ok, Size} when is_integer(Size) ->
147+
Size;
148+
_ ->
149+
?DEFAULT_MAX_CRL_CACHE
150+
end.
151+
141152
%%====================================================================
142153
%% Internal functions
143154
%%====================================================================
@@ -278,6 +289,9 @@ prio_dsa(DSA) ->
278289
end,
279290
lists:sort(Order, DSA).
280291

292+
%%====================================================================
293+
%% Internal functions
294+
%%====================================================================
281295
init_manager_name(false) ->
282296
put(ssl_manager, ssl_manager:name(normal)),
283297
put(ssl_pem_cache, ssl_pem_cache:name(normal));

lib/ssl/src/ssl_crl_cache.erl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,12 @@ cache_lookup(URL, {{Cache, _}, _}) ->
234234

235235
handle_http(URI, Rest, {_, [{http, Timeout}]} = CRLDbInfo) ->
236236
CRLs = http_lookup(URI, Rest, CRLDbInfo, Timeout),
237-
%% Uncomment to improve performance, but need to
238-
%% implement cache limit and or cleaning to prevent
239-
%% DoS attack possibilities
240-
%%insert(URI, {der, CRLs}),
237+
case CRLs of
238+
not_available ->
239+
ok;
240+
_ ->
241+
insert(URI, {der, CRLs})
242+
end,
241243
CRLs;
242244
handle_http(_, Rest, CRLDbInfo) ->
243245
get_crls(Rest, CRLDbInfo).

lib/ssl/src/ssl_manager.erl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@
6868
session_cache_client_max :: integer(),
6969
session_client_invalidator :: undefined | pid(),
7070
options :: list(),
71-
client_session_order :: gb_trees:tree()
71+
client_session_order :: gb_trees:tree(),
72+
max_crl_db_entries :: pos_integer()
7273
}).
7374

7475
-define(GEN_UNIQUE_ID_MAX_TRIES, 10).
@@ -268,7 +269,8 @@ init([ManagerName, PemCacheName, Opts]) ->
268269
session_cache_client_max = ClientSessMax,
269270
session_client_invalidator = undefined,
270271
options = Opts,
271-
client_session_order = gb_trees:empty()
272+
client_session_order = gb_trees:empty(),
273+
max_crl_db_entries = ssl_config:get_max_crl_cache()
272274
}}.
273275

274276
%%--------------------------------------------------------------------
@@ -307,8 +309,9 @@ handle_call({{connection_init, Trustedcerts, Role, {CRLCb, UserCRLDb}}, Pid}, _F
307309
end;
308310

309311
handle_call({{insert_crls, Path, CRLs}, _}, _From,
310-
#state{certificate_db = Db} = State) ->
311-
ssl_pkix_db:add_crls(Db, Path, CRLs),
312+
#state{certificate_db = Db,
313+
max_crl_db_entries = Max} = State) ->
314+
ssl_pkix_db:add_crls(Db, Path, CRLs, Max),
312315
{reply, ok, State};
313316

314317
handle_call({{delete_crls, CRLsOrPath}, _}, _From,
@@ -345,8 +348,8 @@ handle_cast({invalidate_session, Host, Port,
345348
session_cache_client_cb = CacheCb} = State) ->
346349
invalidate_session(Cache, CacheCb, {{Host, Port}, ID}, Session, State);
347350
handle_cast({insert_crls, Path, CRLs},
348-
#state{certificate_db = Db} = State) ->
349-
ssl_pkix_db:add_crls(Db, Path, CRLs),
351+
#state{certificate_db = Db, max_crl_db_entries = Max} = State) ->
352+
ssl_pkix_db:add_crls(Db, Path, CRLs, Max),
350353
{noreply, State};
351354

352355
handle_cast({delete_crls, CRLsOrPath},

lib/ssl/src/ssl_pkix_db.erl

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,27 @@
3232
-include_lib("kernel/include/file.hrl").
3333
-include_lib("kernel/include/logger.hrl").
3434

35-
-export([create/1, create_pem_cache/1,
36-
add_crls/3, remove_crls/2, remove/1, add_trusted_certs/3,
35+
-export([create/1,
36+
create_pem_cache/1,
37+
add_crls/4,
38+
remove_crls/2,
39+
remove/1,
40+
add_trusted_certs/3,
3741
refresh_trusted_certs/2,
3842
refresh_trusted_certs/3,
3943
extract_trusted_certs/1,
40-
remove_trusted_certs/2, insert/3, remove/2, clear/1, db_size/1,
41-
ref_count/3, lookup_trusted_cert/4, foldl/3, select_certentries_by_ref/2,
42-
select_certs_by_ref/2, decode_pem_file/1, lookup/2]).
44+
remove_trusted_certs/2,
45+
insert/3,
46+
remove/2,
47+
clear/1,
48+
db_size/1,
49+
ref_count/3,
50+
lookup_trusted_cert/4,
51+
foldl/3,
52+
select_certentries_by_ref/2,
53+
select_certs_by_ref/2,
54+
decode_pem_file/1,
55+
lookup/2]).
4356

4457
%%====================================================================
4558
%% Internal application API
@@ -365,6 +378,15 @@ new_trusted_cert_entry(File, [CertsDb, RefsDb, _ | _]) ->
365378
Error
366379
end.
367380

381+
add_crls([_,_,_, {Cache, _} | _]= DB, Path, CRLs, MaxSize) ->
382+
case ets:info(Cache, size) + length(CRLs) > MaxSize of
383+
true ->
384+
ets:delete_all_objects(Cache),
385+
add_crls(DB, Path, CRLs);
386+
false ->
387+
add_crls(DB, Path, CRLs)
388+
end.
389+
368390
add_crls([_,_,_, {_, Mapping} | _], ?NO_DIST_POINT, CRLs) ->
369391
[add_crls(CRL, Mapping) || CRL <- CRLs];
370392
add_crls([_,_,_, {Cache, Mapping} | _], Path, CRLs) ->

0 commit comments

Comments
 (0)