]>
Commit | Line | Data |
---|---|---|
846e33c7 | 1 | /* |
33388b44 | 2 | * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. |
c80149d9 | 3 | * Copyright 2005 Nokia. All rights reserved. |
f1fd4544 | 4 | * |
2c18d164 | 5 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
846e33c7 RS |
6 | * this file except in compliance with the License. You can obtain a copy |
7 | * in the file LICENSE in the source distribution or at | |
8 | * https://www.openssl.org/source/license.html | |
f1fd4544 | 9 | */ |
846e33c7 | 10 | |
d02b48c6 | 11 | #include <stdio.h> |
ec577822 | 12 | #include <openssl/rand.h> |
3c27208f | 13 | #include <openssl/engine.h> |
cd420b0b | 14 | #include "internal/refcount.h" |
6cc0b3c2 | 15 | #include "internal/cryptlib.h" |
706457b7 DMSP |
16 | #include "ssl_local.h" |
17 | #include "statem/statem_local.h" | |
d02b48c6 | 18 | |
852c2ed2 RS |
19 | DEFINE_STACK_OF(X509) |
20 | ||
58964a49 | 21 | static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); |
0f113f3e | 22 | static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s); |
801294f8 | 23 | static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); |
58964a49 | 24 | |
e7a28df7 | 25 | /* |
e586eac8 MC |
26 | * SSL_get_session() and SSL_get1_session() are problematic in TLS1.3 because, |
27 | * unlike in earlier protocol versions, the session ticket may not have been | |
28 | * sent yet even though a handshake has finished. The session ticket data could | |
29 | * come in sometime later...or even change if multiple session ticket messages | |
30 | * are sent from the server. The preferred way for applications to obtain | |
31 | * a resumable session is to use SSL_CTX_sess_set_new_cb(). | |
e7a28df7 MC |
32 | */ |
33 | ||
0821bcd4 | 34 | SSL_SESSION *SSL_get_session(const SSL *ssl) |
52732b38 | 35 | /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ |
0f113f3e | 36 | { |
26a7d938 | 37 | return ssl->session; |
0f113f3e | 38 | } |
52732b38 BM |
39 | |
40 | SSL_SESSION *SSL_get1_session(SSL *ssl) | |
41 | /* variant of SSL_get_session: caller really gets something */ | |
0f113f3e MC |
42 | { |
43 | SSL_SESSION *sess; | |
44 | /* | |
45 | * Need to lock this all up rather than just use CRYPTO_add so that | |
46 | * somebody doesn't free ssl->session between when we check it's non-null | |
47 | * and when we up the reference count. | |
48 | */ | |
16203f7b | 49 | CRYPTO_THREAD_read_lock(ssl->lock); |
0f113f3e MC |
50 | sess = ssl->session; |
51 | if (sess) | |
16203f7b AG |
52 | SSL_SESSION_up_ref(sess); |
53 | CRYPTO_THREAD_unlock(ssl->lock); | |
54 | return sess; | |
0f113f3e MC |
55 | } |
56 | ||
6b691a5c | 57 | int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) |
0f113f3e | 58 | { |
26a7d938 | 59 | return CRYPTO_set_ex_data(&s->ex_data, idx, arg); |
0f113f3e | 60 | } |
58964a49 | 61 | |
0821bcd4 | 62 | void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) |
0f113f3e | 63 | { |
26a7d938 | 64 | return CRYPTO_get_ex_data(&s->ex_data, idx); |
0f113f3e | 65 | } |
58964a49 | 66 | |
6b691a5c | 67 | SSL_SESSION *SSL_SESSION_new(void) |
0f113f3e MC |
68 | { |
69 | SSL_SESSION *ss; | |
70 | ||
534a43ff MC |
71 | if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL)) |
72 | return NULL; | |
73 | ||
b51bce94 | 74 | ss = OPENSSL_zalloc(sizeof(*ss)); |
0f113f3e MC |
75 | if (ss == NULL) { |
76 | SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); | |
16203f7b | 77 | return NULL; |
0f113f3e | 78 | } |
0f113f3e MC |
79 | |
80 | ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ | |
81 | ss->references = 1; | |
82 | ss->timeout = 60 * 5 + 4; /* 5 minute timeout by default */ | |
83 | ss->time = (unsigned long)time(NULL); | |
16203f7b AG |
84 | ss->lock = CRYPTO_THREAD_lock_new(); |
85 | if (ss->lock == NULL) { | |
86 | SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); | |
87 | OPENSSL_free(ss); | |
88 | return NULL; | |
89 | } | |
90 | ||
25a807bc F |
91 | if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data)) { |
92 | CRYPTO_THREAD_lock_free(ss->lock); | |
93 | OPENSSL_free(ss); | |
94 | return NULL; | |
95 | } | |
16203f7b | 96 | return ss; |
0f113f3e | 97 | } |
d02b48c6 | 98 | |
9fdcc21f | 99 | SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src) |
07927bed MC |
100 | { |
101 | return ssl_session_dup(src, 1); | |
102 | } | |
103 | ||
98ece4ee MC |
104 | /* |
105 | * Create a new SSL_SESSION and duplicate the contents of |src| into it. If | |
106 | * ticket == 0 then no ticket information is duplicated, otherwise it is. | |
107 | */ | |
9fdcc21f | 108 | SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket) |
98ece4ee MC |
109 | { |
110 | SSL_SESSION *dest; | |
111 | ||
112 | dest = OPENSSL_malloc(sizeof(*src)); | |
113 | if (dest == NULL) { | |
114 | goto err; | |
115 | } | |
116 | memcpy(dest, src, sizeof(*dest)); | |
117 | ||
708cf593 MC |
118 | /* |
119 | * Set the various pointers to NULL so that we can call SSL_SESSION_free in | |
120 | * the case of an error whilst halfway through constructing dest | |
121 | */ | |
122 | #ifndef OPENSSL_NO_PSK | |
123 | dest->psk_identity_hint = NULL; | |
124 | dest->psk_identity = NULL; | |
125 | #endif | |
aff8c126 | 126 | dest->ext.hostname = NULL; |
aff8c126 | 127 | dest->ext.tick = NULL; |
eed3ec90 | 128 | dest->ext.alpn_selected = NULL; |
708cf593 MC |
129 | #ifndef OPENSSL_NO_SRP |
130 | dest->srp_username = NULL; | |
131 | #endif | |
1ee21259 TS |
132 | dest->peer_chain = NULL; |
133 | dest->peer = NULL; | |
df0fed9a | 134 | dest->ticket_appdata = NULL; |
51598215 | 135 | memset(&dest->ex_data, 0, sizeof(dest->ex_data)); |
9b6a8254 | 136 | |
708cf593 MC |
137 | /* We deliberately don't copy the prev and next pointers */ |
138 | dest->prev = NULL; | |
139 | dest->next = NULL; | |
140 | ||
141 | dest->references = 1; | |
142 | ||
16203f7b AG |
143 | dest->lock = CRYPTO_THREAD_lock_new(); |
144 | if (dest->lock == NULL) | |
145 | goto err; | |
146 | ||
1ee21259 TS |
147 | if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data)) |
148 | goto err; | |
149 | ||
150 | if (src->peer != NULL) { | |
151 | if (!X509_up_ref(src->peer)) | |
152 | goto err; | |
153 | dest->peer = src->peer; | |
154 | } | |
708cf593 | 155 | |
36f038f1 DSH |
156 | if (src->peer_chain != NULL) { |
157 | dest->peer_chain = X509_chain_up_ref(src->peer_chain); | |
158 | if (dest->peer_chain == NULL) | |
159 | goto err; | |
160 | } | |
98ece4ee MC |
161 | #ifndef OPENSSL_NO_PSK |
162 | if (src->psk_identity_hint) { | |
7644a9ae | 163 | dest->psk_identity_hint = OPENSSL_strdup(src->psk_identity_hint); |
98ece4ee MC |
164 | if (dest->psk_identity_hint == NULL) { |
165 | goto err; | |
166 | } | |
98ece4ee MC |
167 | } |
168 | if (src->psk_identity) { | |
7644a9ae | 169 | dest->psk_identity = OPENSSL_strdup(src->psk_identity); |
98ece4ee MC |
170 | if (dest->psk_identity == NULL) { |
171 | goto err; | |
172 | } | |
98ece4ee MC |
173 | } |
174 | #endif | |
175 | ||
98ece4ee | 176 | if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, |
a230b26e | 177 | &dest->ex_data, &src->ex_data)) { |
98ece4ee MC |
178 | goto err; |
179 | } | |
180 | ||
aff8c126 RS |
181 | if (src->ext.hostname) { |
182 | dest->ext.hostname = OPENSSL_strdup(src->ext.hostname); | |
183 | if (dest->ext.hostname == NULL) { | |
98ece4ee MC |
184 | goto err; |
185 | } | |
98ece4ee | 186 | } |
98ece4ee | 187 | |
1ee21259 | 188 | if (ticket != 0 && src->ext.tick != NULL) { |
aff8c126 RS |
189 | dest->ext.tick = |
190 | OPENSSL_memdup(src->ext.tick, src->ext.ticklen); | |
191 | if (dest->ext.tick == NULL) | |
98ece4ee | 192 | goto err; |
708cf593 | 193 | } else { |
aff8c126 RS |
194 | dest->ext.tick_lifetime_hint = 0; |
195 | dest->ext.ticklen = 0; | |
98ece4ee MC |
196 | } |
197 | ||
27232cc3 MC |
198 | if (src->ext.alpn_selected != NULL) { |
199 | dest->ext.alpn_selected = OPENSSL_memdup(src->ext.alpn_selected, | |
200 | src->ext.alpn_selected_len); | |
201 | if (dest->ext.alpn_selected == NULL) | |
eed3ec90 | 202 | goto err; |
eed3ec90 TS |
203 | } |
204 | ||
98ece4ee | 205 | #ifndef OPENSSL_NO_SRP |
98ece4ee | 206 | if (src->srp_username) { |
7644a9ae | 207 | dest->srp_username = OPENSSL_strdup(src->srp_username); |
98ece4ee MC |
208 | if (dest->srp_username == NULL) { |
209 | goto err; | |
210 | } | |
98ece4ee MC |
211 | } |
212 | #endif | |
213 | ||
df0fed9a TS |
214 | if (src->ticket_appdata != NULL) { |
215 | dest->ticket_appdata = | |
216 | OPENSSL_memdup(src->ticket_appdata, src->ticket_appdata_len); | |
217 | if (dest->ticket_appdata == NULL) | |
218 | goto err; | |
219 | } | |
220 | ||
98ece4ee | 221 | return dest; |
a230b26e | 222 | err: |
98ece4ee MC |
223 | SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE); |
224 | SSL_SESSION_free(dest); | |
225 | return NULL; | |
226 | } | |
227 | ||
a230b26e | 228 | const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) |
0f113f3e MC |
229 | { |
230 | if (len) | |
348240c6 | 231 | *len = (unsigned int)s->session_id_length; |
0f113f3e MC |
232 | return s->session_id; |
233 | } | |
fddfc0af RG |
234 | const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s, |
235 | unsigned int *len) | |
236 | { | |
237 | if (len != NULL) | |
348240c6 | 238 | *len = (unsigned int)s->sid_ctx_length; |
fddfc0af RG |
239 | return s->sid_ctx; |
240 | } | |
4879ec7b | 241 | |
f9b0b452 | 242 | unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s) |
0f113f3e MC |
243 | { |
244 | return s->compress_meth; | |
245 | } | |
246 | ||
247 | /* | |
248 | * SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling | |
249 | * the ID with random junk repeatedly until we have no conflict is going to | |
250 | * complete in one iteration pretty much "most" of the time (btw: | |
251 | * understatement). So, if it takes us 10 iterations and we still can't avoid | |
252 | * a conflict - well that's a reasonable point to call it quits. Either the | |
253 | * RAND code is broken or someone is trying to open roughly very close to | |
254 | * 2^256 SSL sessions to our server. How you might store that many sessions | |
255 | * is perhaps a more interesting question ... | |
256 | */ | |
dc644fe2 GT |
257 | |
258 | #define MAX_SESS_ID_ATTEMPTS 10 | |
ae3947de | 259 | static int def_generate_session_id(SSL *ssl, unsigned char *id, |
0f113f3e | 260 | unsigned int *id_len) |
dc644fe2 | 261 | { |
0f113f3e MC |
262 | unsigned int retry = 0; |
263 | do | |
8f21260b | 264 | if (RAND_bytes_ex(ssl->ctx->libctx, id, *id_len) <= 0) |
0f113f3e MC |
265 | return 0; |
266 | while (SSL_has_matching_session_id(ssl, id, *id_len) && | |
267 | (++retry < MAX_SESS_ID_ATTEMPTS)) ; | |
268 | if (retry < MAX_SESS_ID_ATTEMPTS) | |
269 | return 1; | |
270 | /* else - woops a session_id match */ | |
271 | /* | |
272 | * XXX We should also check the external cache -- but the probability of | |
273 | * a collision is negligible, and we could not prevent the concurrent | |
274 | * creation of sessions with identical IDs since we currently don't have | |
275 | * means to atomically check whether a session ID already exists and make | |
276 | * a reservation for it if it does not (this problem applies to the | |
277 | * internal cache as well). | |
278 | */ | |
279 | return 0; | |
dc644fe2 GT |
280 | } |
281 | ||
a84e5c9a TS |
282 | int ssl_generate_session_id(SSL *s, SSL_SESSION *ss) |
283 | { | |
284 | unsigned int tmp; | |
285 | GEN_SESSION_CB cb = def_generate_session_id; | |
286 | ||
287 | switch (s->version) { | |
288 | case SSL3_VERSION: | |
289 | case TLS1_VERSION: | |
290 | case TLS1_1_VERSION: | |
291 | case TLS1_2_VERSION: | |
292 | case TLS1_3_VERSION: | |
293 | case DTLS1_BAD_VER: | |
294 | case DTLS1_VERSION: | |
295 | case DTLS1_2_VERSION: | |
296 | ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; | |
297 | break; | |
298 | default: | |
f63a17d6 MC |
299 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, |
300 | SSL_R_UNSUPPORTED_SSL_VERSION); | |
a84e5c9a TS |
301 | return 0; |
302 | } | |
303 | ||
304 | /*- | |
305 | * If RFC5077 ticket, use empty session ID (as server). | |
306 | * Note that: | |
307 | * (a) ssl_get_prev_session() does lookahead into the | |
308 | * ClientHello extensions to find the session ticket. | |
309 | * When ssl_get_prev_session() fails, statem_srvr.c calls | |
310 | * ssl_get_new_session() in tls_process_client_hello(). | |
311 | * At that point, it has not yet parsed the extensions, | |
312 | * however, because of the lookahead, it already knows | |
313 | * whether a ticket is expected or not. | |
314 | * | |
315 | * (b) statem_clnt.c calls ssl_get_new_session() before parsing | |
316 | * ServerHello extensions, and before recording the session | |
317 | * ID received from the server, so this block is a noop. | |
318 | */ | |
319 | if (s->ext.ticket_expected) { | |
320 | ss->session_id_length = 0; | |
321 | return 1; | |
322 | } | |
323 | ||
324 | /* Choose which callback will set the session ID */ | |
325 | CRYPTO_THREAD_read_lock(s->lock); | |
326 | CRYPTO_THREAD_read_lock(s->session_ctx->lock); | |
327 | if (s->generate_session_id) | |
328 | cb = s->generate_session_id; | |
329 | else if (s->session_ctx->generate_session_id) | |
330 | cb = s->session_ctx->generate_session_id; | |
331 | CRYPTO_THREAD_unlock(s->session_ctx->lock); | |
332 | CRYPTO_THREAD_unlock(s->lock); | |
333 | /* Choose a session ID */ | |
334 | memset(ss->session_id, 0, ss->session_id_length); | |
335 | tmp = (int)ss->session_id_length; | |
336 | if (!cb(s, ss->session_id, &tmp)) { | |
337 | /* The callback failed */ | |
f63a17d6 MC |
338 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, |
339 | SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); | |
a84e5c9a TS |
340 | return 0; |
341 | } | |
342 | /* | |
343 | * Don't allow the callback to set the session length to zero. nor | |
344 | * set it higher than it was. | |
345 | */ | |
346 | if (tmp == 0 || tmp > ss->session_id_length) { | |
347 | /* The callback set an illegal length */ | |
f63a17d6 MC |
348 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, |
349 | SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); | |
a84e5c9a TS |
350 | return 0; |
351 | } | |
352 | ss->session_id_length = tmp; | |
353 | /* Finally, check for a conflict */ | |
354 | if (SSL_has_matching_session_id(s, ss->session_id, | |
355 | (unsigned int)ss->session_id_length)) { | |
f63a17d6 MC |
356 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, |
357 | SSL_R_SSL_SESSION_ID_CONFLICT); | |
a84e5c9a TS |
358 | return 0; |
359 | } | |
360 | ||
361 | return 1; | |
362 | } | |
363 | ||
6b691a5c | 364 | int ssl_get_new_session(SSL *s, int session) |
0f113f3e MC |
365 | { |
366 | /* This gets used by clients and servers. */ | |
367 | ||
0f113f3e | 368 | SSL_SESSION *ss = NULL; |
0f113f3e | 369 | |
f63a17d6 MC |
370 | if ((ss = SSL_SESSION_new()) == NULL) { |
371 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, | |
372 | ERR_R_MALLOC_FAILURE); | |
a84e5c9a | 373 | return 0; |
f63a17d6 | 374 | } |
0f113f3e MC |
375 | |
376 | /* If the context has a default timeout, use it */ | |
377 | if (s->session_ctx->session_timeout == 0) | |
378 | ss->timeout = SSL_get_default_timeout(s); | |
379 | else | |
380 | ss->timeout = s->session_ctx->session_timeout; | |
381 | ||
62adbcee RS |
382 | SSL_SESSION_free(s->session); |
383 | s->session = NULL; | |
0f113f3e MC |
384 | |
385 | if (session) { | |
32305f88 MC |
386 | if (SSL_IS_TLS13(s)) { |
387 | /* | |
388 | * We generate the session id while constructing the | |
389 | * NewSessionTicket in TLSv1.3. | |
390 | */ | |
391 | ss->session_id_length = 0; | |
392 | } else if (!ssl_generate_session_id(s, ss)) { | |
f63a17d6 | 393 | /* SSLfatal() already called */ |
0f113f3e | 394 | SSL_SESSION_free(ss); |
a84e5c9a | 395 | return 0; |
0f113f3e | 396 | } |
e481f9b9 | 397 | |
0f113f3e MC |
398 | } else { |
399 | ss->session_id_length = 0; | |
400 | } | |
401 | ||
cbe29648 | 402 | if (s->sid_ctx_length > sizeof(ss->sid_ctx)) { |
f63a17d6 MC |
403 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, |
404 | ERR_R_INTERNAL_ERROR); | |
0f113f3e MC |
405 | SSL_SESSION_free(ss); |
406 | return 0; | |
407 | } | |
408 | memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length); | |
409 | ss->sid_ctx_length = s->sid_ctx_length; | |
410 | s->session = ss; | |
411 | ss->ssl_version = s->version; | |
412 | ss->verify_result = X509_V_OK; | |
413 | ||
e7f0d921 | 414 | /* If client supports extended master secret set it in session */ |
555cbb32 | 415 | if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) |
e7f0d921 DSH |
416 | ss->flags |= SSL_SESS_FLAG_EXTMS; |
417 | ||
a84e5c9a | 418 | return 1; |
0f113f3e | 419 | } |
d02b48c6 | 420 | |
6cc0b3c2 MC |
421 | SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id, |
422 | size_t sess_id_len) | |
423 | { | |
424 | SSL_SESSION *ret = NULL; | |
6cc0b3c2 MC |
425 | |
426 | if ((s->session_ctx->session_cache_mode | |
427 | & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP) == 0) { | |
428 | SSL_SESSION data; | |
429 | ||
430 | data.ssl_version = s->version; | |
431 | if (!ossl_assert(sess_id_len <= SSL_MAX_SSL_SESSION_ID_LENGTH)) | |
432 | return NULL; | |
433 | ||
434 | memcpy(data.session_id, sess_id, sess_id_len); | |
435 | data.session_id_length = sess_id_len; | |
436 | ||
437 | CRYPTO_THREAD_read_lock(s->session_ctx->lock); | |
438 | ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data); | |
439 | if (ret != NULL) { | |
440 | /* don't allow other threads to steal it: */ | |
441 | SSL_SESSION_up_ref(ret); | |
442 | } | |
443 | CRYPTO_THREAD_unlock(s->session_ctx->lock); | |
444 | if (ret == NULL) | |
9ef9088c | 445 | tsan_counter(&s->session_ctx->stats.sess_miss); |
6cc0b3c2 MC |
446 | } |
447 | ||
448 | if (ret == NULL && s->session_ctx->get_session_cb != NULL) { | |
449 | int copy = 1; | |
450 | ||
451 | ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, ©); | |
452 | ||
453 | if (ret != NULL) { | |
9ef9088c | 454 | tsan_counter(&s->session_ctx->stats.sess_cb_hit); |
6cc0b3c2 MC |
455 | |
456 | /* | |
457 | * Increment reference count now if the session callback asks us | |
458 | * to do so (note that if the session structures returned by the | |
459 | * callback are shared between threads, it must handle the | |
460 | * reference count itself [i.e. copy == 0], or things won't be | |
461 | * thread-safe). | |
462 | */ | |
463 | if (copy) | |
464 | SSL_SESSION_up_ref(ret); | |
465 | ||
466 | /* | |
467 | * Add the externally cached session to the internal cache as | |
468 | * well if and only if we are supposed to. | |
469 | */ | |
470 | if ((s->session_ctx->session_cache_mode & | |
471 | SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0) { | |
472 | /* | |
473 | * Either return value of SSL_CTX_add_session should not | |
474 | * interrupt the session resumption process. The return | |
475 | * value is intentionally ignored. | |
476 | */ | |
477 | (void)SSL_CTX_add_session(s->session_ctx, ret); | |
478 | } | |
479 | } | |
480 | } | |
481 | ||
482 | return ret; | |
483 | } | |
484 | ||
3a83462d MC |
485 | /*- |
486 | * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this | |
c519e89f BM |
487 | * connection. It is only called by servers. |
488 | * | |
de7d61d5 | 489 | * hello: The parsed ClientHello data |
c519e89f BM |
490 | * |
491 | * Returns: | |
1053a6e2 MC |
492 | * -1: fatal error |
493 | * 0: no session found | |
494 | * 1: a session may have been found. | |
c519e89f BM |
495 | * |
496 | * Side effects: | |
497 | * - If a session is found then s->session is pointed at it (after freeing an | |
498 | * existing session if need be) and s->verify_result is set from the session. | |
aff8c126 | 499 | * - Both for new and resumed sessions, s->ext.ticket_expected is set to 1 |
c519e89f BM |
500 | * if the server should issue a new session ticket (to 0 otherwise). |
501 | */ | |
f63a17d6 | 502 | int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) |
0f113f3e MC |
503 | { |
504 | /* This is used only by servers. */ | |
b56bce4f | 505 | |
0f113f3e | 506 | SSL_SESSION *ret = NULL; |
9ef9088c | 507 | int fatal = 0; |
1053a6e2 | 508 | int try_session_cache = 0; |
61fb5923 | 509 | SSL_TICKET_STATUS r; |
d02b48c6 | 510 | |
1053a6e2 | 511 | if (SSL_IS_TLS13(s)) { |
61fb5923 MC |
512 | /* |
513 | * By default we will send a new ticket. This can be overridden in the | |
514 | * ticket processing. | |
515 | */ | |
516 | s->ext.ticket_expected = 1; | |
fe874d27 MC |
517 | if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes, |
518 | SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts, | |
f63a17d6 | 519 | NULL, 0) |
fe874d27 | 520 | || !tls_parse_extension(s, TLSEXT_IDX_psk, SSL_EXT_CLIENT_HELLO, |
f63a17d6 | 521 | hello->pre_proc_exts, NULL, 0)) |
1053a6e2 MC |
522 | return -1; |
523 | ||
524 | ret = s->session; | |
525 | } else { | |
526 | /* sets s->ext.ticket_expected */ | |
527 | r = tls_get_ticket_from_client(s, hello, &ret); | |
528 | switch (r) { | |
df0fed9a TS |
529 | case SSL_TICKET_FATAL_ERR_MALLOC: |
530 | case SSL_TICKET_FATAL_ERR_OTHER: | |
1053a6e2 | 531 | fatal = 1; |
f63a17d6 MC |
532 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, |
533 | ERR_R_INTERNAL_ERROR); | |
1053a6e2 | 534 | goto err; |
df0fed9a TS |
535 | case SSL_TICKET_NONE: |
536 | case SSL_TICKET_EMPTY: | |
6cc0b3c2 | 537 | if (hello->session_id_len > 0) { |
0afca811 | 538 | try_session_cache = 1; |
6cc0b3c2 MC |
539 | ret = lookup_sess_in_cache(s, hello->session_id, |
540 | hello->session_id_len); | |
541 | } | |
61c32649 | 542 | break; |
df0fed9a TS |
543 | case SSL_TICKET_NO_DECRYPT: |
544 | case SSL_TICKET_SUCCESS: | |
545 | case SSL_TICKET_SUCCESS_RENEW: | |
1053a6e2 | 546 | break; |
1053a6e2 | 547 | } |
0f113f3e | 548 | } |
c519e89f | 549 | |
0f113f3e MC |
550 | if (ret == NULL) |
551 | goto err; | |
552 | ||
553 | /* Now ret is non-NULL and we own one of its reference counts. */ | |
554 | ||
128ae276 MC |
555 | /* Check TLS version consistency */ |
556 | if (ret->ssl_version != s->version) | |
557 | goto err; | |
558 | ||
0f113f3e MC |
559 | if (ret->sid_ctx_length != s->sid_ctx_length |
560 | || memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) { | |
561 | /* | |
562 | * We have the session requested by the client, but we don't want to | |
563 | * use it in this context. | |
564 | */ | |
565 | goto err; /* treat like cache miss */ | |
566 | } | |
567 | ||
568 | if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { | |
569 | /* | |
570 | * We can't be sure if this session is being used out of context, | |
571 | * which is especially important for SSL_VERIFY_PEER. The application | |
572 | * should have used SSL[_CTX]_set_session_id_context. For this error | |
573 | * case, we generate an error instead of treating the event like a | |
574 | * cache miss (otherwise it would be easy for applications to | |
575 | * effectively disable the session cache by accident without anyone | |
576 | * noticing). | |
577 | */ | |
578 | ||
f63a17d6 MC |
579 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, |
580 | SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); | |
0f113f3e MC |
581 | fatal = 1; |
582 | goto err; | |
583 | } | |
584 | ||
0f113f3e | 585 | if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */ |
9ef9088c | 586 | tsan_counter(&s->session_ctx->stats.sess_timeout); |
0f113f3e MC |
587 | if (try_session_cache) { |
588 | /* session was from the cache, so remove it */ | |
589 | SSL_CTX_remove_session(s->session_ctx, ret); | |
590 | } | |
591 | goto err; | |
592 | } | |
593 | ||
e7f0d921 DSH |
594 | /* Check extended master secret extension consistency */ |
595 | if (ret->flags & SSL_SESS_FLAG_EXTMS) { | |
596 | /* If old session includes extms, but new does not: abort handshake */ | |
555cbb32 | 597 | if (!(s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS)) { |
f63a17d6 MC |
598 | SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_GET_PREV_SESSION, |
599 | SSL_R_INCONSISTENT_EXTMS); | |
e7f0d921 DSH |
600 | fatal = 1; |
601 | goto err; | |
602 | } | |
555cbb32 | 603 | } else if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) { |
e7f0d921 DSH |
604 | /* If new session includes extms, but old does not: do not resume */ |
605 | goto err; | |
606 | } | |
607 | ||
1053a6e2 MC |
608 | if (!SSL_IS_TLS13(s)) { |
609 | /* We already did this for TLS1.3 */ | |
610 | SSL_SESSION_free(s->session); | |
611 | s->session = ret; | |
612 | } | |
0f113f3e | 613 | |
9ef9088c | 614 | tsan_counter(&s->session_ctx->stats.sess_hit); |
0f113f3e MC |
615 | s->verify_result = s->session->verify_result; |
616 | return 1; | |
8876bc05 BM |
617 | |
618 | err: | |
0f113f3e MC |
619 | if (ret != NULL) { |
620 | SSL_SESSION_free(ret); | |
1f5b44e9 | 621 | /* In TLSv1.3 s->session was already set to ret, so we NULL it out */ |
128ae276 MC |
622 | if (SSL_IS_TLS13(s)) |
623 | s->session = NULL; | |
e481f9b9 | 624 | |
0f113f3e MC |
625 | if (!try_session_cache) { |
626 | /* | |
627 | * The session was from a ticket, so we should issue a ticket for | |
628 | * the new session | |
629 | */ | |
aff8c126 | 630 | s->ext.ticket_expected = 1; |
0f113f3e | 631 | } |
0f113f3e | 632 | } |
f63a17d6 | 633 | if (fatal) |
0f113f3e | 634 | return -1; |
40f805ad MC |
635 | |
636 | return 0; | |
0f113f3e | 637 | } |
d02b48c6 | 638 | |
6b691a5c | 639 | int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) |
0f113f3e | 640 | { |
9ef9088c | 641 | int ret = 0; |
0f113f3e MC |
642 | SSL_SESSION *s; |
643 | ||
644 | /* | |
645 | * add just 1 reference count for the SSL_CTX's session cache even though | |
646 | * it has two ways of access: each session is in a doubly linked list and | |
647 | * an lhash | |
648 | */ | |
16203f7b | 649 | SSL_SESSION_up_ref(c); |
0f113f3e MC |
650 | /* |
651 | * if session c is in already in cache, we take back the increment later | |
652 | */ | |
653 | ||
16203f7b | 654 | CRYPTO_THREAD_write_lock(ctx->lock); |
0f113f3e MC |
655 | s = lh_SSL_SESSION_insert(ctx->sessions, c); |
656 | ||
657 | /* | |
658 | * s != NULL iff we already had a session with the given PID. In this | |
659 | * case, s == c should hold (then we did not really modify | |
660 | * ctx->sessions), or we're in trouble. | |
661 | */ | |
662 | if (s != NULL && s != c) { | |
663 | /* We *are* in trouble ... */ | |
664 | SSL_SESSION_list_remove(ctx, s); | |
665 | SSL_SESSION_free(s); | |
666 | /* | |
667 | * ... so pretend the other session did not exist in cache (we cannot | |
668 | * handle two SSL_SESSION structures with identical session ID in the | |
669 | * same cache, which could happen e.g. when two threads concurrently | |
670 | * obtain the same session from an external cache) | |
671 | */ | |
672 | s = NULL; | |
38088ce9 BE |
673 | } else if (s == NULL && |
674 | lh_SSL_SESSION_retrieve(ctx->sessions, c) == NULL) { | |
675 | /* s == NULL can also mean OOM error in lh_SSL_SESSION_insert ... */ | |
676 | ||
677 | /* | |
678 | * ... so take back the extra reference and also don't add | |
679 | * the session to the SSL_SESSION_list at this time | |
680 | */ | |
681 | s = c; | |
0f113f3e MC |
682 | } |
683 | ||
684 | /* Put at the head of the queue unless it is already in the cache */ | |
685 | if (s == NULL) | |
686 | SSL_SESSION_list_add(ctx, c); | |
687 | ||
688 | if (s != NULL) { | |
689 | /* | |
690 | * existing cache entry -- decrement previously incremented reference | |
691 | * count because it already takes into account the cache | |
692 | */ | |
693 | ||
694 | SSL_SESSION_free(s); /* s == c */ | |
695 | ret = 0; | |
696 | } else { | |
697 | /* | |
698 | * new cache entry -- remove old ones if cache has become too large | |
699 | */ | |
700 | ||
701 | ret = 1; | |
702 | ||
703 | if (SSL_CTX_sess_get_cache_size(ctx) > 0) { | |
a230b26e | 704 | while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { |
0f113f3e MC |
705 | if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) |
706 | break; | |
707 | else | |
9ef9088c | 708 | tsan_counter(&ctx->stats.sess_cache_full); |
0f113f3e MC |
709 | } |
710 | } | |
711 | } | |
16203f7b AG |
712 | CRYPTO_THREAD_unlock(ctx->lock); |
713 | return ret; | |
0f113f3e | 714 | } |
d02b48c6 | 715 | |
6b691a5c | 716 | int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) |
801294f8 | 717 | { |
0f113f3e | 718 | return remove_session_lock(ctx, c, 1); |
801294f8 DSH |
719 | } |
720 | ||
0fda2e37 | 721 | static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) |
0f113f3e MC |
722 | { |
723 | SSL_SESSION *r; | |
724 | int ret = 0; | |
725 | ||
726 | if ((c != NULL) && (c->session_id_length != 0)) { | |
727 | if (lck) | |
16203f7b | 728 | CRYPTO_THREAD_write_lock(ctx->lock); |
66d7de16 | 729 | if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) != NULL) { |
0f113f3e | 730 | ret = 1; |
66d7de16 MC |
731 | r = lh_SSL_SESSION_delete(ctx->sessions, r); |
732 | SSL_SESSION_list_remove(ctx, r); | |
0f113f3e | 733 | } |
e4612d02 | 734 | c->not_resumable = 1; |
0f113f3e MC |
735 | |
736 | if (lck) | |
16203f7b | 737 | CRYPTO_THREAD_unlock(ctx->lock); |
0f113f3e | 738 | |
e4612d02 MC |
739 | if (ctx->remove_session_cb != NULL) |
740 | ctx->remove_session_cb(ctx, c); | |
c0a58e03 MH |
741 | |
742 | if (ret) | |
743 | SSL_SESSION_free(r); | |
0f113f3e MC |
744 | } else |
745 | ret = 0; | |
26a7d938 | 746 | return ret; |
0f113f3e | 747 | } |
d02b48c6 | 748 | |
6b691a5c | 749 | void SSL_SESSION_free(SSL_SESSION *ss) |
0f113f3e MC |
750 | { |
751 | int i; | |
d02b48c6 | 752 | |
e6e9170d RS |
753 | if (ss == NULL) |
754 | return; | |
2f545ae4 | 755 | CRYPTO_DOWN_REF(&ss->references, &i, ss->lock); |
f3f1cf84 | 756 | REF_PRINT_COUNT("SSL_SESSION", ss); |
0f113f3e MC |
757 | if (i > 0) |
758 | return; | |
f3f1cf84 | 759 | REF_ASSERT_ISNT(i < 0); |
d02b48c6 | 760 | |
0f113f3e | 761 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); |
58964a49 | 762 | |
cbe29648 RS |
763 | OPENSSL_cleanse(ss->master_key, sizeof(ss->master_key)); |
764 | OPENSSL_cleanse(ss->session_id, sizeof(ss->session_id)); | |
222561fe | 765 | X509_free(ss->peer); |
c34b0f99 | 766 | sk_X509_pop_free(ss->peer_chain, X509_free); |
aff8c126 RS |
767 | OPENSSL_free(ss->ext.hostname); |
768 | OPENSSL_free(ss->ext.tick); | |
ddac1974 | 769 | #ifndef OPENSSL_NO_PSK |
25aaa98a RS |
770 | OPENSSL_free(ss->psk_identity_hint); |
771 | OPENSSL_free(ss->psk_identity); | |
edc032b5 BL |
772 | #endif |
773 | #ifndef OPENSSL_NO_SRP | |
25aaa98a | 774 | OPENSSL_free(ss->srp_username); |
ed3883d2 | 775 | #endif |
f6370040 | 776 | OPENSSL_free(ss->ext.alpn_selected); |
df0fed9a | 777 | OPENSSL_free(ss->ticket_appdata); |
16203f7b | 778 | CRYPTO_THREAD_lock_free(ss->lock); |
4b45c6e5 | 779 | OPENSSL_clear_free(ss, sizeof(*ss)); |
0f113f3e | 780 | } |
d02b48c6 | 781 | |
16203f7b AG |
782 | int SSL_SESSION_up_ref(SSL_SESSION *ss) |
783 | { | |
784 | int i; | |
785 | ||
2f545ae4 | 786 | if (CRYPTO_UP_REF(&ss->references, &i, ss->lock) <= 0) |
16203f7b AG |
787 | return 0; |
788 | ||
789 | REF_PRINT_COUNT("SSL_SESSION", ss); | |
790 | REF_ASSERT_ISNT(i < 2); | |
791 | return ((i > 1) ? 1 : 0); | |
792 | } | |
793 | ||
6b691a5c | 794 | int SSL_set_session(SSL *s, SSL_SESSION *session) |
0f113f3e | 795 | { |
e70656cf MC |
796 | ssl_clear_bad_session(s); |
797 | if (s->ctx->method != s->method) { | |
798 | if (!SSL_set_ssl_method(s, s->ctx->method)) | |
799 | return 0; | |
800 | } | |
0f113f3e | 801 | |
e70656cf | 802 | if (session != NULL) { |
16203f7b | 803 | SSL_SESSION_up_ref(session); |
e70656cf | 804 | s->verify_result = session->verify_result; |
0f113f3e | 805 | } |
e70656cf MC |
806 | SSL_SESSION_free(s->session); |
807 | s->session = session; | |
808 | ||
809 | return 1; | |
0f113f3e | 810 | } |
d02b48c6 | 811 | |
fddfc0af RG |
812 | int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, |
813 | unsigned int sid_len) | |
814 | { | |
815 | if (sid_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { | |
816 | SSLerr(SSL_F_SSL_SESSION_SET1_ID, | |
817 | SSL_R_SSL_SESSION_ID_TOO_LONG); | |
818 | return 0; | |
819 | } | |
820 | s->session_id_length = sid_len; | |
6aad9393 RG |
821 | if (sid != s->session_id) |
822 | memcpy(s->session_id, sid, sid_len); | |
fddfc0af RG |
823 | return 1; |
824 | } | |
825 | ||
6b691a5c | 826 | long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) |
0f113f3e MC |
827 | { |
828 | if (s == NULL) | |
26a7d938 | 829 | return 0; |
0f113f3e | 830 | s->timeout = t; |
208fb891 | 831 | return 1; |
0f113f3e | 832 | } |
d02b48c6 | 833 | |
0821bcd4 | 834 | long SSL_SESSION_get_timeout(const SSL_SESSION *s) |
0f113f3e MC |
835 | { |
836 | if (s == NULL) | |
26a7d938 K |
837 | return 0; |
838 | return s->timeout; | |
0f113f3e | 839 | } |
d02b48c6 | 840 | |
0821bcd4 | 841 | long SSL_SESSION_get_time(const SSL_SESSION *s) |
0f113f3e MC |
842 | { |
843 | if (s == NULL) | |
26a7d938 K |
844 | return 0; |
845 | return s->time; | |
0f113f3e | 846 | } |
d02b48c6 | 847 | |
6b691a5c | 848 | long SSL_SESSION_set_time(SSL_SESSION *s, long t) |
0f113f3e MC |
849 | { |
850 | if (s == NULL) | |
26a7d938 | 851 | return 0; |
0f113f3e | 852 | s->time = t; |
26a7d938 | 853 | return t; |
0f113f3e | 854 | } |
d02b48c6 | 855 | |
bd01f649 TS |
856 | int SSL_SESSION_get_protocol_version(const SSL_SESSION *s) |
857 | { | |
bd01f649 TS |
858 | return s->ssl_version; |
859 | } | |
860 | ||
5a43d511 MC |
861 | int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version) |
862 | { | |
863 | s->ssl_version = version; | |
864 | return 1; | |
865 | } | |
866 | ||
e9281323 RS |
867 | const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s) |
868 | { | |
869 | return s->cipher; | |
870 | } | |
1a993d1d MC |
871 | |
872 | int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher) | |
873 | { | |
874 | s->cipher = cipher; | |
875 | return 1; | |
876 | } | |
e9281323 | 877 | |
4b6b8487 LC |
878 | const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s) |
879 | { | |
aff8c126 | 880 | return s->ext.hostname; |
4b6b8487 LC |
881 | } |
882 | ||
67738645 MC |
883 | int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname) |
884 | { | |
885 | OPENSSL_free(s->ext.hostname); | |
886 | if (hostname == NULL) { | |
887 | s->ext.hostname = NULL; | |
888 | return 1; | |
889 | } | |
890 | s->ext.hostname = OPENSSL_strdup(hostname); | |
891 | ||
892 | return s->ext.hostname != NULL; | |
893 | } | |
894 | ||
f2baac27 MC |
895 | int SSL_SESSION_has_ticket(const SSL_SESSION *s) |
896 | { | |
aff8c126 | 897 | return (s->ext.ticklen > 0) ? 1 : 0; |
f2baac27 MC |
898 | } |
899 | ||
900 | unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) | |
901 | { | |
aff8c126 | 902 | return s->ext.tick_lifetime_hint; |
f2baac27 MC |
903 | } |
904 | ||
48593cb1 | 905 | void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick, |
a230b26e | 906 | size_t *len) |
b7c9187b | 907 | { |
aff8c126 | 908 | *len = s->ext.ticklen; |
61986d32 | 909 | if (tick != NULL) |
aff8c126 | 910 | *tick = s->ext.tick; |
b7c9187b MC |
911 | } |
912 | ||
fcc47578 MC |
913 | uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s) |
914 | { | |
915 | return s->ext.max_early_data; | |
916 | } | |
917 | ||
98e1d934 MC |
918 | int SSL_SESSION_set_max_early_data(SSL_SESSION *s, uint32_t max_early_data) |
919 | { | |
920 | s->ext.max_early_data = max_early_data; | |
921 | ||
922 | return 1; | |
923 | } | |
924 | ||
67738645 MC |
925 | void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s, |
926 | const unsigned char **alpn, | |
927 | size_t *len) | |
928 | { | |
929 | *alpn = s->ext.alpn_selected; | |
930 | *len = s->ext.alpn_selected_len; | |
931 | } | |
932 | ||
933 | int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s, const unsigned char *alpn, | |
934 | size_t len) | |
935 | { | |
936 | OPENSSL_free(s->ext.alpn_selected); | |
937 | if (alpn == NULL || len == 0) { | |
938 | s->ext.alpn_selected = NULL; | |
939 | s->ext.alpn_selected_len = 0; | |
940 | return 1; | |
941 | } | |
942 | s->ext.alpn_selected = OPENSSL_memdup(alpn, len); | |
943 | if (s->ext.alpn_selected == NULL) { | |
944 | s->ext.alpn_selected_len = 0; | |
945 | return 0; | |
946 | } | |
947 | s->ext.alpn_selected_len = len; | |
948 | ||
949 | return 1; | |
950 | } | |
951 | ||
08557cf2 | 952 | X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) |
0f113f3e MC |
953 | { |
954 | return s->peer; | |
955 | } | |
956 | ||
957 | int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, | |
958 | unsigned int sid_ctx_len) | |
959 | { | |
960 | if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { | |
961 | SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT, | |
962 | SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); | |
963 | return 0; | |
964 | } | |
965 | s->sid_ctx_length = sid_ctx_len; | |
6aad9393 RG |
966 | if (sid_ctx != s->sid_ctx) |
967 | memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); | |
0f113f3e MC |
968 | |
969 | return 1; | |
970 | } | |
08557cf2 | 971 | |
e586eac8 MC |
972 | int SSL_SESSION_is_resumable(const SSL_SESSION *s) |
973 | { | |
974 | /* | |
975 | * In the case of EAP-FAST, we can have a pre-shared "ticket" without a | |
976 | * session ID. | |
977 | */ | |
978 | return !s->not_resumable | |
979 | && (s->session_id_length > 0 || s->ext.ticklen > 0); | |
980 | } | |
981 | ||
6b691a5c | 982 | long SSL_CTX_set_timeout(SSL_CTX *s, long t) |
0f113f3e MC |
983 | { |
984 | long l; | |
985 | if (s == NULL) | |
26a7d938 | 986 | return 0; |
0f113f3e MC |
987 | l = s->session_timeout; |
988 | s->session_timeout = t; | |
26a7d938 | 989 | return l; |
0f113f3e | 990 | } |
413c4f45 | 991 | |
0821bcd4 | 992 | long SSL_CTX_get_timeout(const SSL_CTX *s) |
0f113f3e MC |
993 | { |
994 | if (s == NULL) | |
26a7d938 K |
995 | return 0; |
996 | return s->session_timeout; | |
0f113f3e | 997 | } |
413c4f45 | 998 | |
0f113f3e | 999 | int SSL_set_session_secret_cb(SSL *s, |
aff8c126 | 1000 | tls_session_secret_cb_fn tls_session_secret_cb, |
0f113f3e MC |
1001 | void *arg) |
1002 | { | |
1003 | if (s == NULL) | |
26a7d938 | 1004 | return 0; |
aff8c126 RS |
1005 | s->ext.session_secret_cb = tls_session_secret_cb; |
1006 | s->ext.session_secret_cb_arg = arg; | |
208fb891 | 1007 | return 1; |
0f113f3e | 1008 | } |
12bf56c0 DSH |
1009 | |
1010 | int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, | |
0f113f3e MC |
1011 | void *arg) |
1012 | { | |
1013 | if (s == NULL) | |
26a7d938 | 1014 | return 0; |
aff8c126 RS |
1015 | s->ext.session_ticket_cb = cb; |
1016 | s->ext.session_ticket_cb_arg = arg; | |
208fb891 | 1017 | return 1; |
0f113f3e | 1018 | } |
12bf56c0 DSH |
1019 | |
1020 | int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) | |
0f113f3e MC |
1021 | { |
1022 | if (s->version >= TLS1_VERSION) { | |
aff8c126 RS |
1023 | OPENSSL_free(s->ext.session_ticket); |
1024 | s->ext.session_ticket = NULL; | |
1025 | s->ext.session_ticket = | |
0f113f3e | 1026 | OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); |
aff8c126 | 1027 | if (s->ext.session_ticket == NULL) { |
0f113f3e MC |
1028 | SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE); |
1029 | return 0; | |
1030 | } | |
1031 | ||
1ed327f7 | 1032 | if (ext_data != NULL) { |
aff8c126 RS |
1033 | s->ext.session_ticket->length = ext_len; |
1034 | s->ext.session_ticket->data = s->ext.session_ticket + 1; | |
1035 | memcpy(s->ext.session_ticket->data, ext_data, ext_len); | |
0f113f3e | 1036 | } else { |
aff8c126 RS |
1037 | s->ext.session_ticket->length = 0; |
1038 | s->ext.session_ticket->data = NULL; | |
0f113f3e MC |
1039 | } |
1040 | ||
1041 | return 1; | |
1042 | } | |
1043 | ||
1044 | return 0; | |
1045 | } | |
0f113f3e MC |
1046 | |
1047 | typedef struct timeout_param_st { | |
1048 | SSL_CTX *ctx; | |
1049 | long time; | |
1050 | LHASH_OF(SSL_SESSION) *cache; | |
1051 | } TIMEOUT_PARAM; | |
d02b48c6 | 1052 | |
2a056de8 | 1053 | static void timeout_cb(SSL_SESSION *s, TIMEOUT_PARAM *p) |
0f113f3e MC |
1054 | { |
1055 | if ((p->time == 0) || (p->time > (s->time + s->timeout))) { /* timeout */ | |
1056 | /* | |
1057 | * The reason we don't call SSL_CTX_remove_session() is to save on | |
1058 | * locking overhead | |
1059 | */ | |
1060 | (void)lh_SSL_SESSION_delete(p->cache, s); | |
1061 | SSL_SESSION_list_remove(p->ctx, s); | |
1062 | s->not_resumable = 1; | |
1063 | if (p->ctx->remove_session_cb != NULL) | |
1064 | p->ctx->remove_session_cb(p->ctx, s); | |
1065 | SSL_SESSION_free(s); | |
1066 | } | |
1067 | } | |
d02b48c6 | 1068 | |
2a056de8 | 1069 | IMPLEMENT_LHASH_DOALL_ARG(SSL_SESSION, TIMEOUT_PARAM); |
3c914840 | 1070 | |
6b691a5c | 1071 | void SSL_CTX_flush_sessions(SSL_CTX *s, long t) |
0f113f3e MC |
1072 | { |
1073 | unsigned long i; | |
1074 | TIMEOUT_PARAM tp; | |
1075 | ||
1076 | tp.ctx = s; | |
1077 | tp.cache = s->sessions; | |
1078 | if (tp.cache == NULL) | |
1079 | return; | |
1080 | tp.time = t; | |
16203f7b | 1081 | CRYPTO_THREAD_write_lock(s->lock); |
739a1eb1 RS |
1082 | i = lh_SSL_SESSION_get_down_load(s->sessions); |
1083 | lh_SSL_SESSION_set_down_load(s->sessions, 0); | |
2a056de8 | 1084 | lh_SSL_SESSION_doall_TIMEOUT_PARAM(tp.cache, timeout_cb, &tp); |
739a1eb1 | 1085 | lh_SSL_SESSION_set_down_load(s->sessions, i); |
16203f7b | 1086 | CRYPTO_THREAD_unlock(s->lock); |
0f113f3e | 1087 | } |
d02b48c6 | 1088 | |
6b691a5c | 1089 | int ssl_clear_bad_session(SSL *s) |
0f113f3e MC |
1090 | { |
1091 | if ((s->session != NULL) && | |
1092 | !(s->shutdown & SSL_SENT_SHUTDOWN) && | |
1093 | !(SSL_in_init(s) || SSL_in_before(s))) { | |
e2bb9b9b | 1094 | SSL_CTX_remove_session(s->session_ctx, s->session); |
208fb891 | 1095 | return 1; |
0f113f3e | 1096 | } else |
26a7d938 | 1097 | return 0; |
0f113f3e | 1098 | } |
58964a49 RE |
1099 | |
1100 | /* locked by SSL_CTX in the calling function */ | |
6b691a5c | 1101 | static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) |
0f113f3e MC |
1102 | { |
1103 | if ((s->next == NULL) || (s->prev == NULL)) | |
1104 | return; | |
1105 | ||
1106 | if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) { | |
1107 | /* last element in list */ | |
1108 | if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { | |
1109 | /* only one element in list */ | |
1110 | ctx->session_cache_head = NULL; | |
1111 | ctx->session_cache_tail = NULL; | |
1112 | } else { | |
1113 | ctx->session_cache_tail = s->prev; | |
1114 | s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail); | |
1115 | } | |
1116 | } else { | |
1117 | if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { | |
1118 | /* first element in list */ | |
1119 | ctx->session_cache_head = s->next; | |
1120 | s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head); | |
1121 | } else { | |
1122 | /* middle of list */ | |
1123 | s->next->prev = s->prev; | |
1124 | s->prev->next = s->next; | |
1125 | } | |
1126 | } | |
1127 | s->prev = s->next = NULL; | |
1128 | } | |
58964a49 | 1129 | |
6b691a5c | 1130 | static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) |
0f113f3e MC |
1131 | { |
1132 | if ((s->next != NULL) && (s->prev != NULL)) | |
1133 | SSL_SESSION_list_remove(ctx, s); | |
1134 | ||
1135 | if (ctx->session_cache_head == NULL) { | |
1136 | ctx->session_cache_head = s; | |
1137 | ctx->session_cache_tail = s; | |
1138 | s->prev = (SSL_SESSION *)&(ctx->session_cache_head); | |
1139 | s->next = (SSL_SESSION *)&(ctx->session_cache_tail); | |
1140 | } else { | |
1141 | s->next = ctx->session_cache_head; | |
1142 | s->next->prev = s; | |
1143 | s->prev = (SSL_SESSION *)&(ctx->session_cache_head); | |
1144 | ctx->session_cache_head = s; | |
1145 | } | |
1146 | } | |
58964a49 | 1147 | |
7806f3dd | 1148 | void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, |
a230b26e | 1149 | int (*cb) (struct ssl_st *ssl, SSL_SESSION *sess)) |
0f113f3e MC |
1150 | { |
1151 | ctx->new_session_cb = cb; | |
1152 | } | |
7806f3dd | 1153 | |
0f113f3e MC |
1154 | int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (SSL *ssl, SSL_SESSION *sess) { |
1155 | return ctx->new_session_cb; | |
1156 | } | |
7806f3dd NL |
1157 | |
1158 | void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, | |
0f113f3e MC |
1159 | void (*cb) (SSL_CTX *ctx, SSL_SESSION *sess)) |
1160 | { | |
1161 | ctx->remove_session_cb = cb; | |
1162 | } | |
7806f3dd | 1163 | |
0f113f3e MC |
1164 | void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (SSL_CTX *ctx, |
1165 | SSL_SESSION *sess) { | |
1166 | return ctx->remove_session_cb; | |
1167 | } | |
7806f3dd NL |
1168 | |
1169 | void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, | |
0f113f3e | 1170 | SSL_SESSION *(*cb) (struct ssl_st *ssl, |
b6981744 EK |
1171 | const unsigned char *data, |
1172 | int len, int *copy)) | |
0f113f3e MC |
1173 | { |
1174 | ctx->get_session_cb = cb; | |
1175 | } | |
1176 | ||
1177 | SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (SSL *ssl, | |
a230b26e EK |
1178 | const unsigned char |
1179 | *data, int len, | |
1180 | int *copy) { | |
0f113f3e MC |
1181 | return ctx->get_session_cb; |
1182 | } | |
1183 | ||
1184 | void SSL_CTX_set_info_callback(SSL_CTX *ctx, | |
1185 | void (*cb) (const SSL *ssl, int type, int val)) | |
1186 | { | |
1187 | ctx->info_callback = cb; | |
1188 | } | |
1189 | ||
1190 | void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type, | |
1191 | int val) { | |
1192 | return ctx->info_callback; | |
1193 | } | |
7806f3dd NL |
1194 | |
1195 | void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, | |
0f113f3e MC |
1196 | int (*cb) (SSL *ssl, X509 **x509, |
1197 | EVP_PKEY **pkey)) | |
1198 | { | |
1199 | ctx->client_cert_cb = cb; | |
1200 | } | |
7806f3dd | 1201 | |
0f113f3e MC |
1202 | int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509, |
1203 | EVP_PKEY **pkey) { | |
1204 | return ctx->client_cert_cb; | |
1205 | } | |
7806f3dd | 1206 | |
368888bc DSH |
1207 | #ifndef OPENSSL_NO_ENGINE |
1208 | int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e) | |
0f113f3e MC |
1209 | { |
1210 | if (!ENGINE_init(e)) { | |
1211 | SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB); | |
1212 | return 0; | |
1213 | } | |
1214 | if (!ENGINE_get_ssl_client_cert_function(e)) { | |
1215 | SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, | |
1216 | SSL_R_NO_CLIENT_CERT_METHOD); | |
1217 | ENGINE_finish(e); | |
1218 | return 0; | |
1219 | } | |
1220 | ctx->client_cert_engine = e; | |
1221 | return 1; | |
1222 | } | |
368888bc DSH |
1223 | #endif |
1224 | ||
7806f3dd | 1225 | void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, |
0f113f3e MC |
1226 | int (*cb) (SSL *ssl, |
1227 | unsigned char *cookie, | |
1228 | unsigned int *cookie_len)) | |
1229 | { | |
1230 | ctx->app_gen_cookie_cb = cb; | |
1231 | } | |
7806f3dd NL |
1232 | |
1233 | void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, | |
a230b26e EK |
1234 | int (*cb) (SSL *ssl, |
1235 | const unsigned char *cookie, | |
0f113f3e MC |
1236 | unsigned int cookie_len)) |
1237 | { | |
1238 | ctx->app_verify_cookie_cb = cb; | |
1239 | } | |
7806f3dd | 1240 | |
df0fed9a TS |
1241 | int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len) |
1242 | { | |
1243 | OPENSSL_free(ss->ticket_appdata); | |
1244 | ss->ticket_appdata_len = 0; | |
1245 | if (data == NULL || len == 0) { | |
1246 | ss->ticket_appdata = NULL; | |
1247 | return 1; | |
1248 | } | |
1249 | ss->ticket_appdata = OPENSSL_memdup(data, len); | |
1250 | if (ss->ticket_appdata != NULL) { | |
1251 | ss->ticket_appdata_len = len; | |
1252 | return 1; | |
1253 | } | |
1254 | return 0; | |
1255 | } | |
1256 | ||
1257 | int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len) | |
1258 | { | |
1259 | *data = ss->ticket_appdata; | |
1260 | *len = ss->ticket_appdata_len; | |
1261 | return 1; | |
1262 | } | |
1263 | ||
3fa2812f BS |
1264 | void SSL_CTX_set_stateless_cookie_generate_cb( |
1265 | SSL_CTX *ctx, | |
1266 | int (*cb) (SSL *ssl, | |
1267 | unsigned char *cookie, | |
1268 | size_t *cookie_len)) | |
1269 | { | |
1270 | ctx->gen_stateless_cookie_cb = cb; | |
1271 | } | |
1272 | ||
1273 | void SSL_CTX_set_stateless_cookie_verify_cb( | |
1274 | SSL_CTX *ctx, | |
1275 | int (*cb) (SSL *ssl, | |
1276 | const unsigned char *cookie, | |
1277 | size_t cookie_len)) | |
1278 | { | |
1279 | ctx->verify_stateless_cookie_cb = cb; | |
1280 | } | |
1281 | ||
a230b26e | 1282 | IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION) |