xref: /openbsd-src/lib/libssl/ssl_sess.c (revision f4fe6251b363bc47c99c75caa60c829516bf905e)
1*f4fe6251Sjsing /* $OpenBSD: ssl_sess.c,v 1.128 2024/07/22 14:47:15 jsing Exp $ */
25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
35b37fcf3Sryker  * All rights reserved.
45b37fcf3Sryker  *
55b37fcf3Sryker  * This package is an SSL implementation written
65b37fcf3Sryker  * by Eric Young (eay@cryptsoft.com).
75b37fcf3Sryker  * The implementation was written so as to conform with Netscapes SSL.
85b37fcf3Sryker  *
95b37fcf3Sryker  * This library is free for commercial and non-commercial use as long as
105b37fcf3Sryker  * the following conditions are aheared to.  The following conditions
115b37fcf3Sryker  * apply to all code found in this distribution, be it the RC4, RSA,
125b37fcf3Sryker  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
135b37fcf3Sryker  * included with this distribution is covered by the same copyright terms
145b37fcf3Sryker  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
155b37fcf3Sryker  *
165b37fcf3Sryker  * Copyright remains Eric Young's, and as such any Copyright notices in
175b37fcf3Sryker  * the code are not to be removed.
185b37fcf3Sryker  * If this package is used in a product, Eric Young should be given attribution
195b37fcf3Sryker  * as the author of the parts of the library used.
205b37fcf3Sryker  * This can be in the form of a textual message at program startup or
215b37fcf3Sryker  * in documentation (online or textual) provided with the package.
225b37fcf3Sryker  *
235b37fcf3Sryker  * Redistribution and use in source and binary forms, with or without
245b37fcf3Sryker  * modification, are permitted provided that the following conditions
255b37fcf3Sryker  * are met:
265b37fcf3Sryker  * 1. Redistributions of source code must retain the copyright
275b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer.
285b37fcf3Sryker  * 2. Redistributions in binary form must reproduce the above copyright
295b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer in the
305b37fcf3Sryker  *    documentation and/or other materials provided with the distribution.
315b37fcf3Sryker  * 3. All advertising materials mentioning features or use of this software
325b37fcf3Sryker  *    must display the following acknowledgement:
335b37fcf3Sryker  *    "This product includes cryptographic software written by
345b37fcf3Sryker  *     Eric Young (eay@cryptsoft.com)"
355b37fcf3Sryker  *    The word 'cryptographic' can be left out if the rouines from the library
365b37fcf3Sryker  *    being used are not cryptographic related :-).
375b37fcf3Sryker  * 4. If you include any Windows specific code (or a derivative thereof) from
385b37fcf3Sryker  *    the apps directory (application code) you must include an acknowledgement:
395b37fcf3Sryker  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
405b37fcf3Sryker  *
415b37fcf3Sryker  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
425b37fcf3Sryker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
435b37fcf3Sryker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
445b37fcf3Sryker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
455b37fcf3Sryker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
465b37fcf3Sryker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
475b37fcf3Sryker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485b37fcf3Sryker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
495b37fcf3Sryker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
505b37fcf3Sryker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
515b37fcf3Sryker  * SUCH DAMAGE.
525b37fcf3Sryker  *
535b37fcf3Sryker  * The licence and distribution terms for any publically available version or
545b37fcf3Sryker  * derivative of this code cannot be changed.  i.e. this code cannot simply be
555b37fcf3Sryker  * copied and put under another distribution licence
565b37fcf3Sryker  * [including the GNU Public Licence.]
575b37fcf3Sryker  */
580a5d6edeSdjm /* ====================================================================
590a5d6edeSdjm  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
600a5d6edeSdjm  *
610a5d6edeSdjm  * Redistribution and use in source and binary forms, with or without
620a5d6edeSdjm  * modification, are permitted provided that the following conditions
630a5d6edeSdjm  * are met:
640a5d6edeSdjm  *
650a5d6edeSdjm  * 1. Redistributions of source code must retain the above copyright
660a5d6edeSdjm  *    notice, this list of conditions and the following disclaimer.
670a5d6edeSdjm  *
680a5d6edeSdjm  * 2. Redistributions in binary form must reproduce the above copyright
690a5d6edeSdjm  *    notice, this list of conditions and the following disclaimer in
700a5d6edeSdjm  *    the documentation and/or other materials provided with the
710a5d6edeSdjm  *    distribution.
720a5d6edeSdjm  *
730a5d6edeSdjm  * 3. All advertising materials mentioning features or use of this
740a5d6edeSdjm  *    software must display the following acknowledgment:
750a5d6edeSdjm  *    "This product includes software developed by the OpenSSL Project
760a5d6edeSdjm  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
770a5d6edeSdjm  *
780a5d6edeSdjm  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
790a5d6edeSdjm  *    endorse or promote products derived from this software without
800a5d6edeSdjm  *    prior written permission. For written permission, please contact
810a5d6edeSdjm  *    openssl-core@openssl.org.
820a5d6edeSdjm  *
830a5d6edeSdjm  * 5. Products derived from this software may not be called "OpenSSL"
840a5d6edeSdjm  *    nor may "OpenSSL" appear in their names without prior written
850a5d6edeSdjm  *    permission of the OpenSSL Project.
860a5d6edeSdjm  *
870a5d6edeSdjm  * 6. Redistributions of any form whatsoever must retain the following
880a5d6edeSdjm  *    acknowledgment:
890a5d6edeSdjm  *    "This product includes software developed by the OpenSSL Project
900a5d6edeSdjm  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
910a5d6edeSdjm  *
920a5d6edeSdjm  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
930a5d6edeSdjm  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
940a5d6edeSdjm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
950a5d6edeSdjm  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
960a5d6edeSdjm  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
970a5d6edeSdjm  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
980a5d6edeSdjm  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
990a5d6edeSdjm  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1000a5d6edeSdjm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1010a5d6edeSdjm  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1020a5d6edeSdjm  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
1030a5d6edeSdjm  * OF THE POSSIBILITY OF SUCH DAMAGE.
1040a5d6edeSdjm  * ====================================================================
1050a5d6edeSdjm  *
1060a5d6edeSdjm  * This product includes cryptographic software written by Eric Young
1070a5d6edeSdjm  * (eay@cryptsoft.com).  This product includes software written by Tim
1080a5d6edeSdjm  * Hudson (tjh@cryptsoft.com).
1090a5d6edeSdjm  *
1100a5d6edeSdjm  */
1110a5d6edeSdjm /* ====================================================================
1120a5d6edeSdjm  * Copyright 2005 Nokia. All rights reserved.
1130a5d6edeSdjm  *
1140a5d6edeSdjm  * The portions of the attached software ("Contribution") is developed by
1150a5d6edeSdjm  * Nokia Corporation and is licensed pursuant to the OpenSSL open source
1160a5d6edeSdjm  * license.
1170a5d6edeSdjm  *
1180a5d6edeSdjm  * The Contribution, originally written by Mika Kousa and Pasi Eronen of
1190a5d6edeSdjm  * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
1200a5d6edeSdjm  * support (see RFC 4279) to OpenSSL.
1210a5d6edeSdjm  *
1220a5d6edeSdjm  * No patent licenses or other rights except those expressly stated in
1230a5d6edeSdjm  * the OpenSSL open source license shall be deemed granted or received
1240a5d6edeSdjm  * expressly, by implication, estoppel, or otherwise.
1250a5d6edeSdjm  *
1260a5d6edeSdjm  * No assurances are provided by Nokia that the Contribution does not
1270a5d6edeSdjm  * infringe the patent or other intellectual property rights of any third
1280a5d6edeSdjm  * party or that the license provides you with all the necessary rights
1290a5d6edeSdjm  * to make use of the Contribution.
1300a5d6edeSdjm  *
1310a5d6edeSdjm  * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
1320a5d6edeSdjm  * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
1330a5d6edeSdjm  * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
1340a5d6edeSdjm  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
1350a5d6edeSdjm  * OTHERWISE.
1360a5d6edeSdjm  */
1375b37fcf3Sryker 
138913ec974Sbeck #include <openssl/lhash.h>
139f4dd87b5Sjsing #include <openssl/opensslconf.h>
1409c1df9efSjsing 
141c9675a23Stb #include "ssl_local.h"
1425b37fcf3Sryker 
1435b37fcf3Sryker static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
1445b37fcf3Sryker static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);
145913ec974Sbeck static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
1465b37fcf3Sryker 
147ba5406e9Sbeck /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
148dbea66cdSguenther SSL_SESSION *
149dbea66cdSguenther SSL_get_session(const SSL *ssl)
1505b37fcf3Sryker {
1515b37fcf3Sryker 	return (ssl->session);
1525b37fcf3Sryker }
15371e04849Sbeck LSSL_ALIAS(SSL_get_session);
1545b37fcf3Sryker 
155ba5406e9Sbeck /* variant of SSL_get_session: caller really gets something */
156dbea66cdSguenther SSL_SESSION *
157dbea66cdSguenther SSL_get1_session(SSL *ssl)
158ba5406e9Sbeck {
159ba5406e9Sbeck 	SSL_SESSION *sess;
1609c1df9efSjsing 
1619c1df9efSjsing 	/*
1629c1df9efSjsing 	 * Need to lock this all up rather than just use CRYPTO_add so that
163ba5406e9Sbeck 	 * somebody doesn't free ssl->session between when we check it's
1649c1df9efSjsing 	 * non-null and when we up the reference count.
1659c1df9efSjsing 	 */
166cdc51833Smarkus 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION);
167ba5406e9Sbeck 	sess = ssl->session;
168ba5406e9Sbeck 	if (sess)
169ba5406e9Sbeck 		sess->references++;
170cdc51833Smarkus 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION);
1719c1df9efSjsing 
172ba5406e9Sbeck 	return (sess);
173ba5406e9Sbeck }
17471e04849Sbeck LSSL_ALIAS(SSL_get1_session);
175ba5406e9Sbeck 
17635fb0677Sjsing int
17735fb0677Sjsing SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
178ba5406e9Sbeck     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
1795b37fcf3Sryker {
1809c1df9efSjsing 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION,
1819c1df9efSjsing 	    argl, argp, new_func, dup_func, free_func);
1825b37fcf3Sryker }
18371e04849Sbeck LSSL_ALIAS(SSL_SESSION_get_ex_new_index);
1845b37fcf3Sryker 
18535fb0677Sjsing int
18635fb0677Sjsing SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
1875b37fcf3Sryker {
1887e086035Sjsing 	return (CRYPTO_set_ex_data(&s->ex_data, idx, arg));
1895b37fcf3Sryker }
19071e04849Sbeck LSSL_ALIAS(SSL_SESSION_set_ex_data);
1915b37fcf3Sryker 
192dbea66cdSguenther void *
193dbea66cdSguenther SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx)
1945b37fcf3Sryker {
1957e086035Sjsing 	return (CRYPTO_get_ex_data(&s->ex_data, idx));
1965b37fcf3Sryker }
19771e04849Sbeck LSSL_ALIAS(SSL_SESSION_get_ex_data);
1985b37fcf3Sryker 
199d309fe46Stb uint32_t
200d309fe46Stb SSL_SESSION_get_max_early_data(const SSL_SESSION *s)
201d309fe46Stb {
202d309fe46Stb 	return 0;
203d309fe46Stb }
20471e04849Sbeck LSSL_ALIAS(SSL_SESSION_get_max_early_data);
205d309fe46Stb 
206d309fe46Stb int
207d309fe46Stb SSL_SESSION_set_max_early_data(SSL_SESSION *s, uint32_t max_early_data)
208d309fe46Stb {
209d309fe46Stb 	return 1;
210d309fe46Stb }
21171e04849Sbeck LSSL_ALIAS(SSL_SESSION_set_max_early_data);
212d309fe46Stb 
213dbea66cdSguenther SSL_SESSION *
214dbea66cdSguenther SSL_SESSION_new(void)
2155b37fcf3Sryker {
2165b37fcf3Sryker 	SSL_SESSION *ss;
2175b37fcf3Sryker 
218e68eaf89Sbeck 	if (!OPENSSL_init_ssl(0, NULL)) {
219e68eaf89Sbeck 		SSLerrorx(SSL_R_LIBRARY_BUG);
220e68eaf89Sbeck 		return(NULL);
221e68eaf89Sbeck 	}
222e68eaf89Sbeck 
2238462f404Sjsing 	if ((ss = calloc(1, sizeof(*ss))) == NULL) {
224c9d7abb7Sbeck 		SSLerrorx(ERR_R_MALLOC_FAILURE);
2258462f404Sjsing 		return (NULL);
2268462f404Sjsing 	}
2275b37fcf3Sryker 
228ba5406e9Sbeck 	ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
2295b37fcf3Sryker 	ss->references = 1;
230b5ddb6d5Stb 	ss->timeout = 60 * 5 + 4; /* 5 minutes 4 seconds timeout by default */
231aa8444d1Sguenther 	ss->time = time(NULL);
2327e086035Sjsing 	ss->prev = NULL;
2337e086035Sjsing 	ss->next = NULL;
2344fcf65c5Sdjm 	ss->tlsext_hostname = NULL;
23535fb0677Sjsing 
236ad618767Sjsing 	ss->peer_cert_type = -1;
237ad618767Sjsing 
2387e086035Sjsing 	ss->tlsext_ecpointformatlist_length = 0;
2397e086035Sjsing 	ss->tlsext_ecpointformatlist = NULL;
2407e086035Sjsing 	ss->tlsext_supportedgroups_length = 0;
2417e086035Sjsing 	ss->tlsext_supportedgroups = NULL;
2429c1df9efSjsing 
2437e086035Sjsing 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
2449c1df9efSjsing 
2455b37fcf3Sryker 	return (ss);
2465b37fcf3Sryker }
24771e04849Sbeck LSSL_ALIAS(SSL_SESSION_new);
2485b37fcf3Sryker 
249ed031ec4Stb SSL_SESSION *
250ed031ec4Stb ssl_session_dup(SSL_SESSION *sess, int include_ticket)
251ed031ec4Stb {
252ed031ec4Stb 	SSL_SESSION *copy;
253ed031ec4Stb 	CBS cbs;
254ed031ec4Stb 
255ed031ec4Stb 	if ((copy = calloc(1, sizeof(*copy))) == NULL) {
256ed031ec4Stb 		SSLerrorx(ERR_R_MALLOC_FAILURE);
257ed031ec4Stb 		goto err;
258ed031ec4Stb 	}
259ed031ec4Stb 
260ed031ec4Stb 	copy->ssl_version = sess->ssl_version;
261ed031ec4Stb 
262ed031ec4Stb 	CBS_init(&cbs, sess->master_key, sess->master_key_length);
263ed031ec4Stb 	if (!CBS_write_bytes(&cbs, copy->master_key, sizeof(copy->master_key),
264ed031ec4Stb 	    &copy->master_key_length))
265ed031ec4Stb 		goto err;
266ed031ec4Stb 
267ed031ec4Stb 	CBS_init(&cbs, sess->session_id, sess->session_id_length);
268ed031ec4Stb 	if (!CBS_write_bytes(&cbs, copy->session_id, sizeof(copy->session_id),
269ed031ec4Stb 	    &copy->session_id_length))
270ed031ec4Stb 		goto err;
271ed031ec4Stb 
272ed031ec4Stb 	CBS_init(&cbs, sess->sid_ctx, sess->sid_ctx_length);
273ed031ec4Stb 	if (!CBS_write_bytes(&cbs, copy->sid_ctx, sizeof(copy->sid_ctx),
274ed031ec4Stb 	    &copy->sid_ctx_length))
275ed031ec4Stb 		goto err;
276ed031ec4Stb 
277ed031ec4Stb 	if (sess->peer_cert != NULL) {
278ed031ec4Stb 		if (!X509_up_ref(sess->peer_cert))
279ed031ec4Stb 			goto err;
280ed031ec4Stb 		copy->peer_cert = sess->peer_cert;
281ed031ec4Stb 	}
282ed031ec4Stb 	copy->peer_cert_type = sess->peer_cert_type;
283ed031ec4Stb 
284ed031ec4Stb 	copy->verify_result = sess->verify_result;
285ed031ec4Stb 
286ed031ec4Stb 	copy->timeout = sess->timeout;
287ed031ec4Stb 	copy->time = sess->time;
288ed031ec4Stb 	copy->references = 1;
289ed031ec4Stb 
290*f4fe6251Sjsing 	copy->cipher_value = sess->cipher_value;
291ed031ec4Stb 
292ed031ec4Stb 	if (sess->tlsext_hostname != NULL) {
293ed031ec4Stb 		copy->tlsext_hostname = strdup(sess->tlsext_hostname);
294ed031ec4Stb 		if (copy->tlsext_hostname == NULL)
295ed031ec4Stb 			goto err;
296ed031ec4Stb 	}
297ed031ec4Stb 
298ed031ec4Stb 	if (include_ticket) {
299ed031ec4Stb 		CBS_init(&cbs, sess->tlsext_tick, sess->tlsext_ticklen);
300ed031ec4Stb 		if (!CBS_stow(&cbs, &copy->tlsext_tick, &copy->tlsext_ticklen))
301ed031ec4Stb 			goto err;
302ed031ec4Stb 		copy->tlsext_tick_lifetime_hint =
303ed031ec4Stb 		    sess->tlsext_tick_lifetime_hint;
304ed031ec4Stb 
305ed031ec4Stb 		/*
306ed031ec4Stb 		 * XXX - copy sess->resumption_master_secret and all other
307ed031ec4Stb 		 * TLSv1.3 info here.
308ed031ec4Stb 		 */
309ed031ec4Stb 	}
310ed031ec4Stb 
311ed031ec4Stb 	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, copy,
312ed031ec4Stb 	    &copy->ex_data))
313ed031ec4Stb 		goto err;
314ed031ec4Stb 
315ed031ec4Stb 	if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, &copy->ex_data,
316ed031ec4Stb 	    &sess->ex_data))
317ed031ec4Stb 		goto err;
318ed031ec4Stb 
319ed031ec4Stb 	/* Omit prev/next: the new session gets its own slot in the cache. */
320ed031ec4Stb 
321ed031ec4Stb 	copy->not_resumable = sess->not_resumable;
322ed031ec4Stb 
323ed031ec4Stb 	CBS_init(&cbs, sess->tlsext_ecpointformatlist,
324ed031ec4Stb 	    sess->tlsext_ecpointformatlist_length);
325ed031ec4Stb 	if (!CBS_stow(&cbs, &copy->tlsext_ecpointformatlist,
326ed031ec4Stb 	    &copy->tlsext_ecpointformatlist_length))
327ed031ec4Stb 		goto err;
328ed031ec4Stb 
329ed031ec4Stb 	if (sess->tlsext_supportedgroups != NULL) {
330ed031ec4Stb 		if ((copy->tlsext_supportedgroups = calloc(sizeof(uint16_t),
331ed031ec4Stb 		    sess->tlsext_supportedgroups_length)) == NULL)
332ed031ec4Stb 			goto err;
333ed031ec4Stb 		memcpy(copy->tlsext_supportedgroups,
334ed031ec4Stb 		    sess->tlsext_supportedgroups,
335ed031ec4Stb 		    sizeof(uint16_t) * sess->tlsext_supportedgroups_length);
336ed031ec4Stb 		copy->tlsext_supportedgroups_length =
337ed031ec4Stb 		    sess->tlsext_supportedgroups_length;
338ed031ec4Stb 	}
339ed031ec4Stb 
340ed031ec4Stb 	return copy;
341ed031ec4Stb 
342ed031ec4Stb  err:
343ed031ec4Stb 	SSL_SESSION_free(copy);
344ed031ec4Stb 
345ed031ec4Stb 	return NULL;
346ed031ec4Stb }
347ed031ec4Stb 
348dbea66cdSguenther const unsigned char *
34905ce10daSjsing SSL_SESSION_get_id(const SSL_SESSION *ss, unsigned int *len)
3504fcf65c5Sdjm {
35105ce10daSjsing 	if (len != NULL)
3527c24ca9eStb 		*len = (unsigned int)ss->session_id_length;
35305ce10daSjsing 	return ss->session_id;
35405ce10daSjsing }
35571e04849Sbeck LSSL_ALIAS(SSL_SESSION_get_id);
35605ce10daSjsing 
35705ce10daSjsing const unsigned char *
35805ce10daSjsing SSL_SESSION_get0_id_context(const SSL_SESSION *ss, unsigned int *len)
35905ce10daSjsing {
36005ce10daSjsing 	if (len != NULL)
36105ce10daSjsing 		*len = (unsigned int)ss->sid_ctx_length;
36205ce10daSjsing 	return ss->sid_ctx;
3634fcf65c5Sdjm }
36471e04849Sbeck LSSL_ALIAS(SSL_SESSION_get0_id_context);
3654fcf65c5Sdjm 
36635fb0677Sjsing unsigned int
36705ce10daSjsing SSL_SESSION_get_compress_id(const SSL_SESSION *ss)
3685cdd308eSdjm {
369e5b4af74Stedu 	return 0;
3705cdd308eSdjm }
37171e04849Sbeck LSSL_ALIAS(SSL_SESSION_get_compress_id);
3725cdd308eSdjm 
3731a87ffccStb unsigned long
3741a87ffccStb SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s)
3751a87ffccStb {
3761a87ffccStb 	return s->tlsext_tick_lifetime_hint;
3771a87ffccStb }
37871e04849Sbeck LSSL_ALIAS(SSL_SESSION_get_ticket_lifetime_hint);
3791a87ffccStb 
3801a87ffccStb int
3811a87ffccStb SSL_SESSION_has_ticket(const SSL_SESSION *s)
3821a87ffccStb {
3831a87ffccStb 	return (s->tlsext_ticklen > 0) ? 1 : 0;
3841a87ffccStb }
38571e04849Sbeck LSSL_ALIAS(SSL_SESSION_has_ticket);
3861a87ffccStb 
3879c1df9efSjsing /*
38846f2cc82Sjsing  * SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling
38946f2cc82Sjsing  * the ID with random gunk repeatedly until we have no conflict is going to
39046f2cc82Sjsing  * complete in one iteration pretty much "most" of the time (btw:
39146f2cc82Sjsing  * understatement). So, if it takes us 10 iterations and we still can't avoid
39246f2cc82Sjsing  * a conflict - well that's a reasonable point to call it quits. Either the
39346f2cc82Sjsing  * arc4random code is broken or someone is trying to open roughly very close to
39446f2cc82Sjsing  * 2^128 (or 2^256) SSL sessions to our server. How you might store that many
39546f2cc82Sjsing  * sessions is perhaps a more interesting question...
3969c1df9efSjsing  */
397da347917Sbeck 
398da347917Sbeck #define MAX_SESS_ID_ATTEMPTS 10
3999c1df9efSjsing 
40035fb0677Sjsing static int
4019c1df9efSjsing def_generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len)
402da347917Sbeck {
403da347917Sbeck 	unsigned int retry = 0;
4049c1df9efSjsing 
4059c1df9efSjsing 	do {
4062a423e6aSjsing 		arc4random_buf(id, *id_len);
4079c1df9efSjsing 	} while (SSL_has_matching_session_id(ssl, id, *id_len) &&
408da347917Sbeck 	    (++retry < MAX_SESS_ID_ATTEMPTS));
4099c1df9efSjsing 
410da347917Sbeck 	if (retry < MAX_SESS_ID_ATTEMPTS)
411da347917Sbeck 		return 1;
4129c1df9efSjsing 
413da347917Sbeck 	/* else - woops a session_id match */
414da347917Sbeck 	/* XXX We should also check the external cache --
415da347917Sbeck 	 * but the probability of a collision is negligible, and
416da347917Sbeck 	 * we could not prevent the concurrent creation of sessions
417da347917Sbeck 	 * with identical IDs since we currently don't have means
418da347917Sbeck 	 * to atomically check whether a session ID already exists
419da347917Sbeck 	 * and make a reservation for it if it does not
420da347917Sbeck 	 * (this problem applies to the internal cache as well).
421da347917Sbeck 	 */
422da347917Sbeck 	return 0;
423da347917Sbeck }
424da347917Sbeck 
42535fb0677Sjsing int
42635fb0677Sjsing ssl_get_new_session(SSL *s, int session)
4275b37fcf3Sryker {
428da347917Sbeck 	unsigned int tmp;
4295b37fcf3Sryker 	SSL_SESSION *ss = NULL;
430da347917Sbeck 	GEN_SESSION_CB cb = def_generate_session_id;
4315b37fcf3Sryker 
4329c1df9efSjsing 	/* This gets used by clients and servers. */
4339c1df9efSjsing 
4349c1df9efSjsing 	if ((ss = SSL_SESSION_new()) == NULL)
4359c1df9efSjsing 		return (0);
4365b37fcf3Sryker 
4375b37fcf3Sryker 	/* If the context has a default timeout, use it */
4380a5d6edeSdjm 	if (s->session_ctx->session_timeout == 0)
4395b37fcf3Sryker 		ss->timeout = SSL_get_default_timeout(s);
440913ec974Sbeck 	else
4410a5d6edeSdjm 		ss->timeout = s->session_ctx->session_timeout;
4425b37fcf3Sryker 
44335fb0677Sjsing 	if (s->session != NULL) {
4445b37fcf3Sryker 		SSL_SESSION_free(s->session);
4455b37fcf3Sryker 		s->session = NULL;
4465b37fcf3Sryker 	}
4475b37fcf3Sryker 
44835fb0677Sjsing 	if (session) {
449bbf55693Sguenther 		switch (s->version) {
450bbf55693Sguenther 		case TLS1_VERSION:
451bbf55693Sguenther 		case TLS1_1_VERSION:
452bbf55693Sguenther 		case TLS1_2_VERSION:
453bbf55693Sguenther 		case DTLS1_VERSION:
454e9d01b14Sjsing 		case DTLS1_2_VERSION:
455bbf55693Sguenther 			ss->ssl_version = s->version;
4565b37fcf3Sryker 			ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
457bbf55693Sguenther 			break;
458bbf55693Sguenther 		default:
459c9d7abb7Sbeck 			SSLerror(s, SSL_R_UNSUPPORTED_SSL_VERSION);
4605b37fcf3Sryker 			SSL_SESSION_free(ss);
4615b37fcf3Sryker 			return (0);
4625b37fcf3Sryker 		}
4639c1df9efSjsing 
4649c1df9efSjsing 		/* If RFC4507 ticket use empty session ID. */
4656f7f653bSjsing 		if (s->tlsext_ticket_expected) {
4664fcf65c5Sdjm 			ss->session_id_length = 0;
4674fcf65c5Sdjm 			goto sess_id_done;
4684fcf65c5Sdjm 		}
4699c1df9efSjsing 
4709c1df9efSjsing 		/* Choose which callback will set the session ID. */
4715b37fcf3Sryker 		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
4726f7f653bSjsing 		if (s->generate_session_id)
4736f7f653bSjsing 			cb = s->generate_session_id;
4746f7f653bSjsing 		else if (s->session_ctx->generate_session_id)
4756f7f653bSjsing 			cb = s->session_ctx->generate_session_id;
4765b37fcf3Sryker 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
4779c1df9efSjsing 
4789c1df9efSjsing 		/* Choose a session ID. */
479da347917Sbeck 		tmp = ss->session_id_length;
48035fb0677Sjsing 		if (!cb(s, ss->session_id, &tmp)) {
481da347917Sbeck 			/* The callback failed */
482c9d7abb7Sbeck 			SSLerror(s, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
483da347917Sbeck 			SSL_SESSION_free(ss);
484da347917Sbeck 			return (0);
485da347917Sbeck 		}
4869c1df9efSjsing 
4879c1df9efSjsing 		/*
4889c1df9efSjsing 		 * Don't allow the callback to set the session length to zero.
4899c1df9efSjsing 		 * nor set it higher than it was.
4909c1df9efSjsing 		 */
491aca06622Stb 		if (tmp == 0 || tmp > ss->session_id_length) {
492da347917Sbeck 			/* The callback set an illegal length */
493c9d7abb7Sbeck 			SSLerror(s, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
494da347917Sbeck 			SSL_SESSION_free(ss);
495da347917Sbeck 			return (0);
496da347917Sbeck 		}
497da347917Sbeck 		ss->session_id_length = tmp;
4989c1df9efSjsing 
4999c1df9efSjsing 		/* Finally, check for a conflict. */
500da347917Sbeck 		if (SSL_has_matching_session_id(s, ss->session_id,
50135fb0677Sjsing 		    ss->session_id_length)) {
502c9d7abb7Sbeck 			SSLerror(s, SSL_R_SSL_SESSION_ID_CONFLICT);
503da347917Sbeck 			SSL_SESSION_free(ss);
504da347917Sbeck 			return (0);
5055b37fcf3Sryker 		}
5069c1df9efSjsing 
5074fcf65c5Sdjm  sess_id_done:
5084fcf65c5Sdjm 		if (s->tlsext_hostname) {
50974a2cbdcSbeck 			ss->tlsext_hostname = strdup(s->tlsext_hostname);
5104fcf65c5Sdjm 			if (ss->tlsext_hostname == NULL) {
511c9d7abb7Sbeck 				SSLerror(s, ERR_R_INTERNAL_ERROR);
5124fcf65c5Sdjm 				SSL_SESSION_free(ss);
5134fcf65c5Sdjm 				return 0;
5144fcf65c5Sdjm 			}
5154fcf65c5Sdjm 		}
51635fb0677Sjsing 	} else {
5175b37fcf3Sryker 		ss->session_id_length = 0;
5185b37fcf3Sryker 	}
5195b37fcf3Sryker 
52035fb0677Sjsing 	if (s->sid_ctx_length > sizeof ss->sid_ctx) {
521c9d7abb7Sbeck 		SSLerror(s, ERR_R_INTERNAL_ERROR);
522cf5de1f6Smarkus 		SSL_SESSION_free(ss);
523cf5de1f6Smarkus 		return 0;
524cf5de1f6Smarkus 	}
5259c1df9efSjsing 
526913ec974Sbeck 	memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length);
527913ec974Sbeck 	ss->sid_ctx_length = s->sid_ctx_length;
5285b37fcf3Sryker 	s->session = ss;
5295b37fcf3Sryker 	ss->ssl_version = s->version;
530ba5406e9Sbeck 	ss->verify_result = X509_V_OK;
5315b37fcf3Sryker 
5325b37fcf3Sryker 	return (1);
5335b37fcf3Sryker }
5345b37fcf3Sryker 
53573ea8b0bStb static SSL_SESSION *
53673ea8b0bStb ssl_session_from_cache(SSL *s, CBS *session_id)
53773ea8b0bStb {
53873ea8b0bStb 	SSL_SESSION *sess;
53973ea8b0bStb 	SSL_SESSION data;
54073ea8b0bStb 
5416f7f653bSjsing 	if ((s->session_ctx->session_cache_mode &
54273ea8b0bStb 	     SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
54373ea8b0bStb 		return NULL;
54473ea8b0bStb 
545a71df539Stb 	memset(&data, 0, sizeof(data));
546a71df539Stb 
54773ea8b0bStb 	data.ssl_version = s->version;
548dcb88a9cStb 
549dcb88a9cStb 	if (!CBS_write_bytes(session_id, data.session_id,
550dcb88a9cStb 	    sizeof(data.session_id), &data.session_id_length))
551dcb88a9cStb 		return NULL;
55273ea8b0bStb 
55373ea8b0bStb 	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
5546f7f653bSjsing 	sess = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data);
55573ea8b0bStb 	if (sess != NULL)
55673ea8b0bStb 		CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
55773ea8b0bStb 	CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
55873ea8b0bStb 
55973ea8b0bStb 	if (sess == NULL)
5606f7f653bSjsing 		s->session_ctx->stats.sess_miss++;
56173ea8b0bStb 
56273ea8b0bStb 	return sess;
56373ea8b0bStb }
56473ea8b0bStb 
56573ea8b0bStb static SSL_SESSION *
56673ea8b0bStb ssl_session_from_callback(SSL *s, CBS *session_id)
56773ea8b0bStb {
56873ea8b0bStb 	SSL_SESSION *sess;
56973ea8b0bStb 	int copy;
57073ea8b0bStb 
5716f7f653bSjsing 	if (s->session_ctx->get_session_cb == NULL)
57273ea8b0bStb 		return NULL;
57373ea8b0bStb 
57473ea8b0bStb 	copy = 1;
5756f7f653bSjsing 	if ((sess = s->session_ctx->get_session_cb(s,
57673ea8b0bStb 	    CBS_data(session_id), CBS_len(session_id), &copy)) == NULL)
57773ea8b0bStb 		return NULL;
57873ea8b0bStb 	/*
57973ea8b0bStb 	 * The copy handler may have set copy == 0 to indicate that the session
58073ea8b0bStb 	 * structures are shared between threads and that it handles the
58173ea8b0bStb 	 * reference count itself. If it didn't set copy to zero, we must
58273ea8b0bStb 	 * increment the reference count.
58373ea8b0bStb 	 */
58473ea8b0bStb 	if (copy)
58573ea8b0bStb 		CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
58673ea8b0bStb 
5876f7f653bSjsing 	s->session_ctx->stats.sess_cb_hit++;
588de6dfec6Stb 
58973ea8b0bStb 	/* Add the externally cached session to the internal cache as well. */
5906f7f653bSjsing 	if (!(s->session_ctx->session_cache_mode &
59173ea8b0bStb 	    SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
59273ea8b0bStb 		/*
59373ea8b0bStb 		 * The following should not return 1,
59473ea8b0bStb 		 * otherwise, things are very strange.
59573ea8b0bStb 		 */
59673ea8b0bStb 		SSL_CTX_add_session(s->session_ctx, sess);
59773ea8b0bStb 	}
59873ea8b0bStb 
59973ea8b0bStb 	return sess;
60073ea8b0bStb }
60173ea8b0bStb 
60273ea8b0bStb static SSL_SESSION *
60373ea8b0bStb ssl_session_by_id(SSL *s, CBS *session_id)
60473ea8b0bStb {
60573ea8b0bStb 	SSL_SESSION *sess;
60673ea8b0bStb 
60773ea8b0bStb 	if (CBS_len(session_id) == 0)
60873ea8b0bStb 		return NULL;
60973ea8b0bStb 
61073ea8b0bStb 	if ((sess = ssl_session_from_cache(s, session_id)) == NULL)
61173ea8b0bStb 		sess = ssl_session_from_callback(s, session_id);
61273ea8b0bStb 
61373ea8b0bStb 	return sess;
61473ea8b0bStb }
61573ea8b0bStb 
6169c1df9efSjsing /*
6176e180e32Stb  * ssl_get_prev_session attempts to find an SSL_SESSION to be used to resume
6186e180e32Stb  * this connection. It is only called by servers.
6195cdd308eSdjm  *
6205cdd308eSdjm  *   session_id: points at the session ID in the ClientHello. This code will
6215cdd308eSdjm  *       read past the end of this in order to parse out the session ticket
6225cdd308eSdjm  *       extension, if any.
623307759eeSjsing  *   ext_block: a CBS for the ClientHello extensions block.
6246e180e32Stb  *   alert: alert that the caller should send in case of failure.
6255cdd308eSdjm  *
6265cdd308eSdjm  * Returns:
6275cdd308eSdjm  *   -1: error
6285cdd308eSdjm  *    0: a session may have been found.
6295cdd308eSdjm  *
6305cdd308eSdjm  * Side effects:
6319c1df9efSjsing  *   - If a session is found then s->session is pointed at it (after freeing
6329c1df9efSjsing  *     an existing session if need be) and s->verify_result is set from the
6339c1df9efSjsing  *     session.
6346f7f653bSjsing  *   - For both new and resumed sessions, s->tlsext_ticket_expected
6356e180e32Stb  *     indicates whether the server should issue a new session ticket or not.
6365cdd308eSdjm  */
63735fb0677Sjsing int
6389a3f7535Stb ssl_get_prev_session(SSL *s, CBS *session_id, CBS *ext_block, int *alert)
6395b37fcf3Sryker {
64009480eb4Stb 	SSL_SESSION *sess = NULL;
6419a3f7535Stb 	int alert_desc = SSL_AD_INTERNAL_ERROR, fatal = 0;
64273ea8b0bStb 	int ticket_decrypted = 0;
6435b37fcf3Sryker 
6449c1df9efSjsing 	/* This is used only by servers. */
6459c1df9efSjsing 
6468890443aSjsing 	if (CBS_len(session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH)
647913ec974Sbeck 		goto err;
6485cdd308eSdjm 
6496f7f653bSjsing 	/* Sets s->tlsext_ticket_expected. */
650a4c79661Stb 	switch (tls1_process_ticket(s, ext_block, &alert_desc, &sess)) {
65112abb213Stb 	case TLS1_TICKET_FATAL_ERROR:
6524fcf65c5Sdjm 		fatal = 1;
6534fcf65c5Sdjm 		goto err;
65412abb213Stb 	case TLS1_TICKET_NONE:
65512abb213Stb 	case TLS1_TICKET_EMPTY:
65673ea8b0bStb 		if ((sess = ssl_session_by_id(s, session_id)) == NULL)
65773ea8b0bStb 			goto err;
65873ea8b0bStb 		break;
65912abb213Stb 	case TLS1_TICKET_NOT_DECRYPTED:
660a4c79661Stb 		goto err;
66112abb213Stb 	case TLS1_TICKET_DECRYPTED:
66273ea8b0bStb 		ticket_decrypted = 1;
663a4c79661Stb 
664a4c79661Stb 		/*
665a4c79661Stb 		 * The session ID is used by some clients to detect that the
666a4c79661Stb 		 * ticket has been accepted so we copy it into sess.
667a4c79661Stb 		 */
668a4c79661Stb 		if (!CBS_write_bytes(session_id, sess->session_id,
669ef6795cfStb 		    sizeof(sess->session_id), &sess->session_id_length)) {
670a4c79661Stb 			fatal = 1;
671a4c79661Stb 			goto err;
672a4c79661Stb 		}
6735cdd308eSdjm 		break;
6745cdd308eSdjm 	default:
6750b321686Sderaadt 		SSLerror(s, ERR_R_INTERNAL_ERROR);
676034e32e4Sjsing 		fatal = 1;
6770b321686Sderaadt 		goto err;
6784fcf65c5Sdjm 	}
6795cdd308eSdjm 
68009480eb4Stb 	/* Now sess is non-NULL and we own one of its reference counts. */
681913ec974Sbeck 
68209480eb4Stb 	if (sess->sid_ctx_length != s->sid_ctx_length ||
6832d126708Stb 	    timingsafe_memcmp(sess->sid_ctx, s->sid_ctx,
6842d126708Stb 	    sess->sid_ctx_length) != 0) {
6852d126708Stb 		/*
6862d126708Stb 		 * We have the session requested by the client, but we don't
6872d126708Stb 		 * want to use it in this context. Treat it like a cache miss.
6882d126708Stb 		 */
6892d126708Stb 		goto err;
690913ec974Sbeck 	}
6914fcf65c5Sdjm 
69235fb0677Sjsing 	if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) {
6939c1df9efSjsing 		/*
6949c1df9efSjsing 		 * We can't be sure if this session is being used out of
6954fcf65c5Sdjm 		 * context, which is especially important for SSL_VERIFY_PEER.
6969c1df9efSjsing 		 * The application should have used
6979c1df9efSjsing 		 * SSL[_CTX]_set_session_id_context.
6984fcf65c5Sdjm 		 *
6994fcf65c5Sdjm 		 * For this error case, we generate an error instead of treating
7004fcf65c5Sdjm 		 * the event like a cache miss (otherwise it would be easy for
7014fcf65c5Sdjm 		 * applications to effectively disable the session cache by
7024fcf65c5Sdjm 		 * accident without anyone noticing).
7034fcf65c5Sdjm 		 */
704c9d7abb7Sbeck 		SSLerror(s, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
7054fcf65c5Sdjm 		fatal = 1;
7064fcf65c5Sdjm 		goto err;
7075b37fcf3Sryker 	}
7085b37fcf3Sryker 
70909480eb4Stb 	if (sess->timeout < (time(NULL) - sess->time)) {
7106f7f653bSjsing 		s->session_ctx->stats.sess_timeout++;
71173ea8b0bStb 		if (!ticket_decrypted) {
7122d126708Stb 			/* The session was from the cache, so remove it. */
71309480eb4Stb 			SSL_CTX_remove_session(s->session_ctx, sess);
7145cdd308eSdjm 		}
715913ec974Sbeck 		goto err;
7165b37fcf3Sryker 	}
7175b37fcf3Sryker 
7186f7f653bSjsing 	s->session_ctx->stats.sess_hit++;
7195b37fcf3Sryker 
7205b37fcf3Sryker 	SSL_SESSION_free(s->session);
72109480eb4Stb 	s->session = sess;
722ba5406e9Sbeck 	s->verify_result = s->session->verify_result;
7232d126708Stb 
7245cdd308eSdjm 	return 1;
725913ec974Sbeck 
726913ec974Sbeck  err:
72709480eb4Stb 	SSL_SESSION_free(sess);
72873ea8b0bStb 	if (ticket_decrypted) {
7299c1df9efSjsing 		/*
73073ea8b0bStb 		 * The session was from a ticket. Issue a ticket for the new
73173ea8b0bStb 		 * session.
7329c1df9efSjsing 		 */
7336f7f653bSjsing 		s->tlsext_ticket_expected = 1;
7345cdd308eSdjm 	}
7359a3f7535Stb 	if (fatal) {
7369a3f7535Stb 		*alert = alert_desc;
737913ec974Sbeck 		return -1;
738e8f311bdStb 	}
739913ec974Sbeck 	return 0;
7405b37fcf3Sryker }
7415b37fcf3Sryker 
74235fb0677Sjsing int
74335fb0677Sjsing SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
7445b37fcf3Sryker {
7455b37fcf3Sryker 	int ret = 0;
7465b37fcf3Sryker 	SSL_SESSION *s;
7475b37fcf3Sryker 
7489c1df9efSjsing 	/*
7499c1df9efSjsing 	 * Add just 1 reference count for the SSL_CTX's session cache
750ba5406e9Sbeck 	 * even though it has two ways of access: each session is in a
7519c1df9efSjsing 	 * doubly linked list and an lhash.
7529c1df9efSjsing 	 */
7535b37fcf3Sryker 	CRYPTO_add(&c->references, 1, CRYPTO_LOCK_SSL_SESSION);
7545b37fcf3Sryker 
7559c1df9efSjsing 	/*
7569c1df9efSjsing 	 * If session c is in already in cache, we take back the increment
7579c1df9efSjsing 	 * later.
7589c1df9efSjsing 	 */
7595b37fcf3Sryker 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
7606f7f653bSjsing 	s = lh_SSL_SESSION_insert(ctx->sessions, c);
7615b37fcf3Sryker 
7629c1df9efSjsing 	/*
7639c1df9efSjsing 	 * s != NULL iff we already had a session with the given PID.
764ba5406e9Sbeck 	 * In this case, s == c should hold (then we did not really modify
7656f7f653bSjsing 	 * ctx->sessions), or we're in trouble.
7669c1df9efSjsing 	 */
76735fb0677Sjsing 	if (s != NULL && s != c) {
768ba5406e9Sbeck 		/* We *are* in trouble ... */
769ba5406e9Sbeck 		SSL_SESSION_list_remove(ctx, s);
770ba5406e9Sbeck 		SSL_SESSION_free(s);
7719c1df9efSjsing 		/*
7729c1df9efSjsing 		 * ... so pretend the other session did not exist in cache
773ba5406e9Sbeck 		 * (we cannot handle two SSL_SESSION structures with identical
774ba5406e9Sbeck 		 * session ID in the same cache, which could happen e.g. when
7759c1df9efSjsing 		 * two threads concurrently obtain the same session from an
7769c1df9efSjsing 		 * external cache).
7779c1df9efSjsing 		 */
778ba5406e9Sbeck 		s = NULL;
779ba5406e9Sbeck 	}
780ba5406e9Sbeck 
781ba5406e9Sbeck 	/* Put at the head of the queue unless it is already in the cache */
7825b37fcf3Sryker 	if (s == NULL)
7835b37fcf3Sryker 		SSL_SESSION_list_add(ctx, c);
7845b37fcf3Sryker 
78535fb0677Sjsing 	if (s != NULL) {
7869c1df9efSjsing 		/*
7879c1df9efSjsing 		 * existing cache entry -- decrement previously incremented
7889c1df9efSjsing 		 * reference count because it already takes into account the
7899c1df9efSjsing 		 * cache.
7909c1df9efSjsing 		 */
791ba5406e9Sbeck 		SSL_SESSION_free(s); /* s == c */
7925b37fcf3Sryker 		ret = 0;
79335fb0677Sjsing 	} else {
7949c1df9efSjsing 		/*
7959c1df9efSjsing 		 * New cache entry -- remove old ones if cache has become
7969c1df9efSjsing 		 * too large.
7979c1df9efSjsing 		 */
798ba5406e9Sbeck 
7995b37fcf3Sryker 		ret = 1;
8005b37fcf3Sryker 
80135fb0677Sjsing 		if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
8025b37fcf3Sryker 			while (SSL_CTX_sess_number(ctx) >
80335fb0677Sjsing 			    SSL_CTX_sess_get_cache_size(ctx)) {
804913ec974Sbeck 				if (!remove_session_lock(ctx,
8056f7f653bSjsing 				    ctx->session_cache_tail, 0))
8065b37fcf3Sryker 					break;
8075b37fcf3Sryker 				else
8086f7f653bSjsing 					ctx->stats.sess_cache_full++;
8095b37fcf3Sryker 			}
8105b37fcf3Sryker 		}
8115b37fcf3Sryker 	}
8125b37fcf3Sryker 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
8135b37fcf3Sryker 	return (ret);
8145b37fcf3Sryker }
81571e04849Sbeck LSSL_ALIAS(SSL_CTX_add_session);
8165b37fcf3Sryker 
81735fb0677Sjsing int
81835fb0677Sjsing SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
819913ec974Sbeck {
820913ec974Sbeck 	return remove_session_lock(ctx, c, 1);
821913ec974Sbeck }
82271e04849Sbeck LSSL_ALIAS(SSL_CTX_remove_session);
823913ec974Sbeck 
82435fb0677Sjsing static int
82535fb0677Sjsing remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
8265b37fcf3Sryker {
8275b37fcf3Sryker 	SSL_SESSION *r;
8285b37fcf3Sryker 	int ret = 0;
8295b37fcf3Sryker 
8308744b8fcStb 	if (c == NULL || c->session_id_length == 0)
8318744b8fcStb 		return 0;
8328744b8fcStb 
83335fb0677Sjsing 	if (lck)
83435fb0677Sjsing 		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
8356f7f653bSjsing 	if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) == c) {
8365b37fcf3Sryker 		ret = 1;
8376f7f653bSjsing 		r = lh_SSL_SESSION_delete(ctx->sessions, c);
8385b37fcf3Sryker 		SSL_SESSION_list_remove(ctx, c);
8395b37fcf3Sryker 	}
84035fb0677Sjsing 	if (lck)
84135fb0677Sjsing 		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
8425b37fcf3Sryker 
84335fb0677Sjsing 	if (ret) {
8447e086035Sjsing 		r->not_resumable = 1;
8456f7f653bSjsing 		if (ctx->remove_session_cb != NULL)
8466f7f653bSjsing 			ctx->remove_session_cb(ctx, r);
8475b37fcf3Sryker 		SSL_SESSION_free(r);
8485b37fcf3Sryker 	}
8498744b8fcStb 
8508744b8fcStb 	return ret;
8515b37fcf3Sryker }
8525b37fcf3Sryker 
85335fb0677Sjsing void
85435fb0677Sjsing SSL_SESSION_free(SSL_SESSION *ss)
8555b37fcf3Sryker {
8565b37fcf3Sryker 	int i;
8575b37fcf3Sryker 
858913ec974Sbeck 	if (ss == NULL)
859913ec974Sbeck 		return;
860913ec974Sbeck 
8615b37fcf3Sryker 	i = CRYPTO_add(&ss->references, -1, CRYPTO_LOCK_SSL_SESSION);
86235fb0677Sjsing 	if (i > 0)
86335fb0677Sjsing 		return;
8645b37fcf3Sryker 
8657e086035Sjsing 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
8665b37fcf3Sryker 
8670f777b12Sjsing 	explicit_bzero(ss->master_key, sizeof ss->master_key);
8680f777b12Sjsing 	explicit_bzero(ss->session_id, sizeof ss->session_id);
86947dd5b40Sjsing 
870666c9986Sjsing 	X509_free(ss->peer_cert);
87147dd5b40Sjsing 
8726f3a6cb1Sbeck 	free(ss->tlsext_hostname);
8736f3a6cb1Sbeck 	free(ss->tlsext_tick);
8747e086035Sjsing 	free(ss->tlsext_ecpointformatlist);
8757e086035Sjsing 	free(ss->tlsext_supportedgroups);
8768462f404Sjsing 
8774bcd03dbStb 	tls13_secret_cleanup(&ss->resumption_master_secret);
8784bcd03dbStb 
8798f2be08bSjsing 	freezero(ss, sizeof(*ss));
8805b37fcf3Sryker }
88171e04849Sbeck LSSL_ALIAS(SSL_SESSION_free);
8825b37fcf3Sryker 
88335fb0677Sjsing int
884c6d61022Sjsing SSL_SESSION_up_ref(SSL_SESSION *ss)
885c6d61022Sjsing {
886c8993338Stb 	return CRYPTO_add(&ss->references, 1, CRYPTO_LOCK_SSL_SESSION) > 1;
887c6d61022Sjsing }
88871e04849Sbeck LSSL_ALIAS(SSL_SESSION_up_ref);
889c6d61022Sjsing 
890c6d61022Sjsing int
89135fb0677Sjsing SSL_set_session(SSL *s, SSL_SESSION *session)
8925b37fcf3Sryker {
89391532218Sjsing 	const SSL_METHOD *method;
8945b37fcf3Sryker 
89591532218Sjsing 	if (session == NULL) {
89691532218Sjsing 		SSL_SESSION_free(s->session);
89791532218Sjsing 		s->session = NULL;
89891532218Sjsing 
89991532218Sjsing 		return SSL_set_ssl_method(s, s->ctx->method);
90091532218Sjsing 	}
90191532218Sjsing 
9029fef1c44Sjsing 	if ((method = ssl_get_method(session->ssl_version)) == NULL) {
903c9d7abb7Sbeck 		SSLerror(s, SSL_R_UNABLE_TO_FIND_SSL_METHOD);
9045b37fcf3Sryker 		return (0);
9055b37fcf3Sryker 	}
9065b37fcf3Sryker 
90791532218Sjsing 	if (!SSL_set_ssl_method(s, method))
9085b37fcf3Sryker 		return (0);
9095b37fcf3Sryker 
9105b37fcf3Sryker 	CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
9115b37fcf3Sryker 	SSL_SESSION_free(s->session);
9125b37fcf3Sryker 	s->session = session;
913ce6fc090Sbeck 	s->verify_result = s->session->verify_result;
914913ec974Sbeck 
91591532218Sjsing 	return (1);
9165b37fcf3Sryker }
91771e04849Sbeck LSSL_ALIAS(SSL_set_session);
9185b37fcf3Sryker 
91929e4fea2Sjsing size_t
92029e4fea2Sjsing SSL_SESSION_get_master_key(const SSL_SESSION *ss, unsigned char *out,
92129e4fea2Sjsing     size_t max_out)
92229e4fea2Sjsing {
92329e4fea2Sjsing 	size_t len = ss->master_key_length;
92429e4fea2Sjsing 
92529e4fea2Sjsing 	if (out == NULL)
92629e4fea2Sjsing 		return len;
92729e4fea2Sjsing 
92829e4fea2Sjsing 	if (len > max_out)
92929e4fea2Sjsing 		len = max_out;
93029e4fea2Sjsing 
93129e4fea2Sjsing 	memcpy(out, ss->master_key, len);
93229e4fea2Sjsing 
93329e4fea2Sjsing 	return len;
93429e4fea2Sjsing }
93571e04849Sbeck LSSL_ALIAS(SSL_SESSION_get_master_key);
93629e4fea2Sjsing 
93735fb0677Sjsing long
93835fb0677Sjsing SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
9395b37fcf3Sryker {
94035fb0677Sjsing 	if (s == NULL)
94135fb0677Sjsing 		return (0);
9425b37fcf3Sryker 	s->timeout = t;
9435b37fcf3Sryker 	return (1);
9445b37fcf3Sryker }
94571e04849Sbeck LSSL_ALIAS(SSL_SESSION_set_timeout);
9465b37fcf3Sryker 
94735fb0677Sjsing long
94835fb0677Sjsing SSL_SESSION_get_timeout(const SSL_SESSION *s)
9495b37fcf3Sryker {
95035fb0677Sjsing 	if (s == NULL)
95135fb0677Sjsing 		return (0);
9525b37fcf3Sryker 	return (s->timeout);
9535b37fcf3Sryker }
95471e04849Sbeck LSSL_ALIAS(SSL_SESSION_get_timeout);
9555b37fcf3Sryker 
956aa8444d1Sguenther /* XXX 2038 */
95735fb0677Sjsing long
95835fb0677Sjsing SSL_SESSION_get_time(const SSL_SESSION *s)
9595b37fcf3Sryker {
96035fb0677Sjsing 	if (s == NULL)
96135fb0677Sjsing 		return (0);
9625b37fcf3Sryker 	return (s->time);
9635b37fcf3Sryker }
96471e04849Sbeck LSSL_ALIAS(SSL_SESSION_get_time);
9655b37fcf3Sryker 
966aa8444d1Sguenther /* XXX 2038 */
96735fb0677Sjsing long
96835fb0677Sjsing SSL_SESSION_set_time(SSL_SESSION *s, long t)
9695b37fcf3Sryker {
97035fb0677Sjsing 	if (s == NULL)
97135fb0677Sjsing 		return (0);
9725b37fcf3Sryker 	s->time = t;
9735b37fcf3Sryker 	return (t);
9745b37fcf3Sryker }
97571e04849Sbeck LSSL_ALIAS(SSL_SESSION_set_time);
9765b37fcf3Sryker 
977274bd5fbStb int
9785d90759aStb SSL_SESSION_get_protocol_version(const SSL_SESSION *s)
979274bd5fbStb {
980274bd5fbStb 	return s->ssl_version;
981274bd5fbStb }
98271e04849Sbeck LSSL_ALIAS(SSL_SESSION_get_protocol_version);
983274bd5fbStb 
9842d36c056Stb const SSL_CIPHER *
9852d36c056Stb SSL_SESSION_get0_cipher(const SSL_SESSION *s)
9862d36c056Stb {
987*f4fe6251Sjsing 	return ssl3_get_cipher_by_value(s->cipher_value);
9882d36c056Stb }
98971e04849Sbeck LSSL_ALIAS(SSL_SESSION_get0_cipher);
9902d36c056Stb 
991dbea66cdSguenther X509 *
992dbea66cdSguenther SSL_SESSION_get0_peer(SSL_SESSION *s)
9935cdd308eSdjm {
994666c9986Sjsing 	return s->peer_cert;
9955cdd308eSdjm }
99671e04849Sbeck LSSL_ALIAS(SSL_SESSION_get0_peer);
9975cdd308eSdjm 
99835fb0677Sjsing int
99925ba64d1Stb SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
100025ba64d1Stb     unsigned int sid_len)
100125ba64d1Stb {
100225ba64d1Stb 	if (sid_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
100325ba64d1Stb 		SSLerrorx(SSL_R_SSL_SESSION_ID_TOO_LONG);
100425ba64d1Stb 		return 0;
100525ba64d1Stb 	}
100625ba64d1Stb 	s->session_id_length = sid_len;
100725ba64d1Stb 	memmove(s->session_id, sid, sid_len);
100825ba64d1Stb 	return 1;
100925ba64d1Stb }
101071e04849Sbeck LSSL_ALIAS(SSL_SESSION_set1_id);
101125ba64d1Stb 
101225ba64d1Stb int
101335fb0677Sjsing SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
10145cdd308eSdjm     unsigned int sid_ctx_len)
10155cdd308eSdjm {
101635fb0677Sjsing 	if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
1017c9d7abb7Sbeck 		SSLerrorx(SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
10185cdd308eSdjm 		return 0;
10195cdd308eSdjm 	}
10205cdd308eSdjm 	s->sid_ctx_length = sid_ctx_len;
10215cdd308eSdjm 	memcpy(s->sid_ctx, sid_ctx, sid_ctx_len);
10225cdd308eSdjm 
10235cdd308eSdjm 	return 1;
10245cdd308eSdjm }
102571e04849Sbeck LSSL_ALIAS(SSL_SESSION_set1_id_context);
10265cdd308eSdjm 
10275b7f4dd6Stb int
10285b7f4dd6Stb SSL_SESSION_is_resumable(const SSL_SESSION *s)
10295b7f4dd6Stb {
10305b7f4dd6Stb 	return 0;
10315b7f4dd6Stb }
103271e04849Sbeck LSSL_ALIAS(SSL_SESSION_is_resumable);
10335b7f4dd6Stb 
103435fb0677Sjsing long
103535fb0677Sjsing SSL_CTX_set_timeout(SSL_CTX *s, long t)
1036913ec974Sbeck {
1037913ec974Sbeck 	long l;
10389c1df9efSjsing 
103935fb0677Sjsing 	if (s == NULL)
104035fb0677Sjsing 		return (0);
1041913ec974Sbeck 	l = s->session_timeout;
1042913ec974Sbeck 	s->session_timeout = t;
10439c1df9efSjsing 
1044913ec974Sbeck 	return (l);
1045913ec974Sbeck }
104671e04849Sbeck LSSL_ALIAS(SSL_CTX_set_timeout);
1047913ec974Sbeck 
104835fb0677Sjsing long
104935fb0677Sjsing SSL_CTX_get_timeout(const SSL_CTX *s)
1050913ec974Sbeck {
105135fb0677Sjsing 	if (s == NULL)
105235fb0677Sjsing 		return (0);
1053913ec974Sbeck 	return (s->session_timeout);
1054913ec974Sbeck }
105571e04849Sbeck LSSL_ALIAS(SSL_CTX_get_timeout);
1056913ec974Sbeck 
105735fb0677Sjsing int
10589c1df9efSjsing SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s,
10599c1df9efSjsing     void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers,
10609c1df9efSjsing     SSL_CIPHER **cipher, void *arg), void *arg)
10610a5d6edeSdjm {
106235fb0677Sjsing 	if (s == NULL)
106335fb0677Sjsing 		return (0);
10646f7f653bSjsing 	s->tls_session_secret_cb = tls_session_secret_cb;
10656f7f653bSjsing 	s->tls_session_secret_cb_arg = arg;
10660a5d6edeSdjm 	return (1);
10670a5d6edeSdjm }
106871e04849Sbeck LSSL_ALIAS(SSL_set_session_secret_cb);
10690a5d6edeSdjm 
107035fb0677Sjsing int
107135fb0677Sjsing SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
10720a5d6edeSdjm     void *arg)
10730a5d6edeSdjm {
107435fb0677Sjsing 	if (s == NULL)
107535fb0677Sjsing 		return (0);
10766f7f653bSjsing 	s->tls_session_ticket_ext_cb = cb;
10776f7f653bSjsing 	s->tls_session_ticket_ext_cb_arg = arg;
10780a5d6edeSdjm 	return (1);
10790a5d6edeSdjm }
108071e04849Sbeck LSSL_ALIAS(SSL_set_session_ticket_ext_cb);
10810a5d6edeSdjm 
108235fb0677Sjsing int
108335fb0677Sjsing SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
10840a5d6edeSdjm {
108535fb0677Sjsing 	if (s->version >= TLS1_VERSION) {
10866f7f653bSjsing 		free(s->tlsext_session_ticket);
10876f7f653bSjsing 		s->tlsext_session_ticket =
10889c1df9efSjsing 		    malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
10896f7f653bSjsing 		if (!s->tlsext_session_ticket) {
1090c9d7abb7Sbeck 			SSLerror(s, ERR_R_MALLOC_FAILURE);
10910a5d6edeSdjm 			return 0;
10920a5d6edeSdjm 		}
10930a5d6edeSdjm 
109435fb0677Sjsing 		if (ext_data) {
10956f7f653bSjsing 			s->tlsext_session_ticket->length = ext_len;
10966f7f653bSjsing 			s->tlsext_session_ticket->data =
10976f7f653bSjsing 			    s->tlsext_session_ticket + 1;
10986f7f653bSjsing 			memcpy(s->tlsext_session_ticket->data,
10999c1df9efSjsing 			    ext_data, ext_len);
110035fb0677Sjsing 		} else {
11016f7f653bSjsing 			s->tlsext_session_ticket->length = 0;
11026f7f653bSjsing 			s->tlsext_session_ticket->data = NULL;
11030a5d6edeSdjm 		}
11040a5d6edeSdjm 
11050a5d6edeSdjm 		return 1;
11060a5d6edeSdjm 	}
11070a5d6edeSdjm 
11080a5d6edeSdjm 	return 0;
11090a5d6edeSdjm }
111071e04849Sbeck LSSL_ALIAS(SSL_set_session_ticket_ext);
11110a5d6edeSdjm 
111235fb0677Sjsing typedef struct timeout_param_st {
11135b37fcf3Sryker 	SSL_CTX *ctx;
11145b37fcf3Sryker 	long time;
11151bbccf41Sjsing 	struct lhash_st_SSL_SESSION *cache;
11165b37fcf3Sryker } TIMEOUT_PARAM;
11175b37fcf3Sryker 
111835fb0677Sjsing static void
111935fb0677Sjsing timeout_doall_arg(SSL_SESSION *s, TIMEOUT_PARAM *p)
11205b37fcf3Sryker {
11219c1df9efSjsing 	if ((p->time == 0) || (p->time > (s->time + s->timeout))) {
11229c1df9efSjsing 		/* timeout */
11235b37fcf3Sryker 		/* The reason we don't call SSL_CTX_remove_session() is to
11245b37fcf3Sryker 		 * save on locking overhead */
11250a5d6edeSdjm 		(void)lh_SSL_SESSION_delete(p->cache, s);
11265b37fcf3Sryker 		SSL_SESSION_list_remove(p->ctx, s);
11277e086035Sjsing 		s->not_resumable = 1;
11286f7f653bSjsing 		if (p->ctx->remove_session_cb != NULL)
11296f7f653bSjsing 			p->ctx->remove_session_cb(p->ctx, s);
11305b37fcf3Sryker 		SSL_SESSION_free(s);
11315b37fcf3Sryker 	}
11325b37fcf3Sryker }
11335b37fcf3Sryker 
11341bbccf41Sjsing static void
11351bbccf41Sjsing timeout_LHASH_DOALL_ARG(void *arg1, void *arg2)
11361bbccf41Sjsing {
11371bbccf41Sjsing 	SSL_SESSION *a = arg1;
11381bbccf41Sjsing 	TIMEOUT_PARAM *b = arg2;
11391bbccf41Sjsing 
11401bbccf41Sjsing 	timeout_doall_arg(a, b);
11411bbccf41Sjsing }
1142da347917Sbeck 
1143aa8444d1Sguenther /* XXX 2038 */
114435fb0677Sjsing void
114535fb0677Sjsing SSL_CTX_flush_sessions(SSL_CTX *s, long t)
11465b37fcf3Sryker {
11475b37fcf3Sryker 	TIMEOUT_PARAM tp;
11485b37fcf3Sryker 
11495b37fcf3Sryker 	tp.ctx = s;
11506f7f653bSjsing 	tp.cache = s->sessions;
115135fb0677Sjsing 	if (tp.cache == NULL)
115235fb0677Sjsing 		return;
11535b37fcf3Sryker 	tp.time = t;
115420273a99Sjsing 
11555b37fcf3Sryker 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
11561bbccf41Sjsing 	lh_SSL_SESSION_doall_arg(tp.cache, timeout_LHASH_DOALL_ARG,
11570a5d6edeSdjm 	    TIMEOUT_PARAM, &tp);
11585b37fcf3Sryker 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
11595b37fcf3Sryker }
116071e04849Sbeck LSSL_ALIAS(SSL_CTX_flush_sessions);
11615b37fcf3Sryker 
116235fb0677Sjsing int
116335fb0677Sjsing ssl_clear_bad_session(SSL *s)
11645b37fcf3Sryker {
11656f7f653bSjsing 	if ((s->session != NULL) && !(s->shutdown & SSL_SENT_SHUTDOWN) &&
116635fb0677Sjsing 	    !(SSL_in_init(s) || SSL_in_before(s))) {
11675b37fcf3Sryker 		SSL_CTX_remove_session(s->ctx, s->session);
11685b37fcf3Sryker 		return (1);
116935fb0677Sjsing 	} else
11705b37fcf3Sryker 		return (0);
11715b37fcf3Sryker }
11725b37fcf3Sryker 
11735b37fcf3Sryker /* locked by SSL_CTX in the calling function */
117435fb0677Sjsing static void
117535fb0677Sjsing SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
11765b37fcf3Sryker {
11777e086035Sjsing 	if (s->next == NULL || s->prev == NULL)
11789c1df9efSjsing 		return;
11795b37fcf3Sryker 
11806f7f653bSjsing 	if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) {
11819c1df9efSjsing 		/* last element in list */
11826f7f653bSjsing 		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) {
11839c1df9efSjsing 			/* only one element in list */
11846f7f653bSjsing 			ctx->session_cache_head = NULL;
11856f7f653bSjsing 			ctx->session_cache_tail = NULL;
118635fb0677Sjsing 		} else {
11876f7f653bSjsing 			ctx->session_cache_tail = s->prev;
11887e086035Sjsing 			s->prev->next =
11896f7f653bSjsing 			    (SSL_SESSION *)&(ctx->session_cache_tail);
11905b37fcf3Sryker 		}
119135fb0677Sjsing 	} else {
11926f7f653bSjsing 		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) {
11939c1df9efSjsing 			/* first element in list */
11946f7f653bSjsing 			ctx->session_cache_head = s->next;
11957e086035Sjsing 			s->next->prev =
11966f7f653bSjsing 			    (SSL_SESSION *)&(ctx->session_cache_head);
11979c1df9efSjsing 		} else {
11989c1df9efSjsing 			/* middle of list */
11997e086035Sjsing 			s->next->prev = s->prev;
12007e086035Sjsing 			s->prev->next = s->next;
12015b37fcf3Sryker 		}
12025b37fcf3Sryker 	}
12037e086035Sjsing 	s->prev = s->next = NULL;
12045b37fcf3Sryker }
12055b37fcf3Sryker 
120635fb0677Sjsing static void
120735fb0677Sjsing SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
12085b37fcf3Sryker {
12097e086035Sjsing 	if (s->next != NULL && s->prev != NULL)
12105b37fcf3Sryker 		SSL_SESSION_list_remove(ctx, s);
12115b37fcf3Sryker 
12126f7f653bSjsing 	if (ctx->session_cache_head == NULL) {
12136f7f653bSjsing 		ctx->session_cache_head = s;
12146f7f653bSjsing 		ctx->session_cache_tail = s;
12156f7f653bSjsing 		s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
12166f7f653bSjsing 		s->next = (SSL_SESSION *)&(ctx->session_cache_tail);
121735fb0677Sjsing 	} else {
12186f7f653bSjsing 		s->next = ctx->session_cache_head;
12197e086035Sjsing 		s->next->prev = s;
12206f7f653bSjsing 		s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
12216f7f653bSjsing 		ctx->session_cache_head = s;
12225b37fcf3Sryker 	}
12235b37fcf3Sryker }
12245b37fcf3Sryker 
122535fb0677Sjsing void
122635fb0677Sjsing SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
122735fb0677Sjsing     int (*cb)(struct ssl_st *ssl, SSL_SESSION *sess)) {
12286f7f653bSjsing 	ctx->new_session_cb = cb;
12294fcf65c5Sdjm }
123071e04849Sbeck LSSL_ALIAS(SSL_CTX_sess_set_new_cb);
12314fcf65c5Sdjm 
12329c1df9efSjsing int
12339c1df9efSjsing (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess)
12344fcf65c5Sdjm {
12356f7f653bSjsing 	return ctx->new_session_cb;
12364fcf65c5Sdjm }
123771e04849Sbeck LSSL_ALIAS(SSL_CTX_sess_get_new_cb);
12384fcf65c5Sdjm 
123935fb0677Sjsing void
124035fb0677Sjsing SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
12414fcf65c5Sdjm     void (*cb)(SSL_CTX *ctx, SSL_SESSION *sess))
12424fcf65c5Sdjm {
12436f7f653bSjsing 	ctx->remove_session_cb = cb;
12444fcf65c5Sdjm }
124571e04849Sbeck LSSL_ALIAS(SSL_CTX_sess_set_remove_cb);
12464fcf65c5Sdjm 
12479c1df9efSjsing void
12489c1df9efSjsing (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx, SSL_SESSION *sess)
12494fcf65c5Sdjm {
12506f7f653bSjsing 	return ctx->remove_session_cb;
12514fcf65c5Sdjm }
125271e04849Sbeck LSSL_ALIAS(SSL_CTX_sess_get_remove_cb);
12534fcf65c5Sdjm 
125435fb0677Sjsing void
12559c1df9efSjsing SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*cb)(struct ssl_st *ssl,
12560a4fabb9Stb     const unsigned char *data, int len, int *copy))
12574fcf65c5Sdjm {
12586f7f653bSjsing 	ctx->get_session_cb = cb;
12594fcf65c5Sdjm }
126071e04849Sbeck LSSL_ALIAS(SSL_CTX_sess_set_get_cb);
12614fcf65c5Sdjm 
12629c1df9efSjsing SSL_SESSION *
12630a4fabb9Stb (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl, const unsigned char *data,
12649c1df9efSjsing     int len, int *copy)
12654fcf65c5Sdjm {
12666f7f653bSjsing 	return ctx->get_session_cb;
12674fcf65c5Sdjm }
126871e04849Sbeck LSSL_ALIAS(SSL_CTX_sess_get_get_cb);
12694fcf65c5Sdjm 
127035fb0677Sjsing void
127135fb0677Sjsing SSL_CTX_set_info_callback(SSL_CTX *ctx,
12724fcf65c5Sdjm     void (*cb)(const SSL *ssl, int type, int val))
12734fcf65c5Sdjm {
12746f7f653bSjsing 	ctx->info_callback = cb;
12754fcf65c5Sdjm }
127671e04849Sbeck LSSL_ALIAS(SSL_CTX_set_info_callback);
12774fcf65c5Sdjm 
12789c1df9efSjsing void
12799c1df9efSjsing (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type, int val)
12804fcf65c5Sdjm {
12816f7f653bSjsing 	return ctx->info_callback;
12824fcf65c5Sdjm }
128371e04849Sbeck LSSL_ALIAS(SSL_CTX_get_info_callback);
12844fcf65c5Sdjm 
128535fb0677Sjsing void
128635fb0677Sjsing SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
12874fcf65c5Sdjm     int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey))
12884fcf65c5Sdjm {
12896f7f653bSjsing 	ctx->client_cert_cb = cb;
12904fcf65c5Sdjm }
129171e04849Sbeck LSSL_ALIAS(SSL_CTX_set_client_cert_cb);
12924fcf65c5Sdjm 
12939c1df9efSjsing int
12949c1df9efSjsing (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509,
12959c1df9efSjsing     EVP_PKEY **pkey)
12964fcf65c5Sdjm {
12976f7f653bSjsing 	return ctx->client_cert_cb;
12984fcf65c5Sdjm }
129971e04849Sbeck LSSL_ALIAS(SSL_CTX_get_client_cert_cb);
13004fcf65c5Sdjm 
130135fb0677Sjsing void
130235fb0677Sjsing SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
13034fcf65c5Sdjm     int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len))
13044fcf65c5Sdjm {
13056f7f653bSjsing 	ctx->app_gen_cookie_cb = cb;
13064fcf65c5Sdjm }
130771e04849Sbeck LSSL_ALIAS(SSL_CTX_set_cookie_generate_cb);
13084fcf65c5Sdjm 
130935fb0677Sjsing void
131035fb0677Sjsing SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
13110a4fabb9Stb     int (*cb)(SSL *ssl, const unsigned char *cookie, unsigned int cookie_len))
13124fcf65c5Sdjm {
13136f7f653bSjsing 	ctx->app_verify_cookie_cb = cb;
13144fcf65c5Sdjm }
131571e04849Sbeck LSSL_ALIAS(SSL_CTX_set_cookie_verify_cb);
13164fcf65c5Sdjm 
1317d820b776Sjsing int
1318d820b776Sjsing PEM_write_SSL_SESSION(FILE *fp, SSL_SESSION *x)
131907781822Sjsing {
13207c5b2634Sjsing 	return PEM_ASN1_write((i2d_of_void *)i2d_SSL_SESSION,
13217c5b2634Sjsing 	    PEM_STRING_SSL_SESSION, fp, x, NULL, NULL, 0, NULL, NULL);
132207781822Sjsing }
132371e04849Sbeck LSSL_ALIAS(PEM_write_SSL_SESSION);
132407781822Sjsing 
132507781822Sjsing SSL_SESSION *
132607781822Sjsing PEM_read_SSL_SESSION(FILE *fp, SSL_SESSION **x, pem_password_cb *cb, void *u)
132707781822Sjsing {
13287c5b2634Sjsing 	return PEM_ASN1_read((d2i_of_void *)d2i_SSL_SESSION,
13297c5b2634Sjsing 	    PEM_STRING_SSL_SESSION, fp, (void **)x, cb, u);
133007781822Sjsing }
133171e04849Sbeck LSSL_ALIAS(PEM_read_SSL_SESSION);
133207781822Sjsing 
1333d820b776Sjsing SSL_SESSION *
1334d820b776Sjsing PEM_read_bio_SSL_SESSION(BIO *bp, SSL_SESSION **x, pem_password_cb *cb, void *u)
1335d820b776Sjsing {
13367c5b2634Sjsing 	return PEM_ASN1_read_bio((d2i_of_void *)d2i_SSL_SESSION,
13377c5b2634Sjsing 	    PEM_STRING_SSL_SESSION, bp, (void **)x, cb, u);
1338d820b776Sjsing }
133971e04849Sbeck LSSL_ALIAS(PEM_read_bio_SSL_SESSION);
1340d820b776Sjsing 
134107781822Sjsing int
134207781822Sjsing PEM_write_bio_SSL_SESSION(BIO *bp, SSL_SESSION *x)
134307781822Sjsing {
13447c5b2634Sjsing 	return PEM_ASN1_write_bio((i2d_of_void *)i2d_SSL_SESSION,
13457c5b2634Sjsing 	    PEM_STRING_SSL_SESSION, bp, x, NULL, NULL, 0, NULL, NULL);
134607781822Sjsing }
134771e04849Sbeck LSSL_ALIAS(PEM_write_bio_SSL_SESSION);
1348