xref: /freebsd/crypto/openssl/ssl/ssl_sess.c (revision dee36b4f92f269b95977ae9c4a37046fb7cc351c)
174664626SKris Kennaway /* ssl/ssl_sess.c */
274664626SKris Kennaway /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
374664626SKris Kennaway  * All rights reserved.
474664626SKris Kennaway  *
574664626SKris Kennaway  * This package is an SSL implementation written
674664626SKris Kennaway  * by Eric Young (eay@cryptsoft.com).
774664626SKris Kennaway  * The implementation was written so as to conform with Netscapes SSL.
874664626SKris Kennaway  *
974664626SKris Kennaway  * This library is free for commercial and non-commercial use as long as
1074664626SKris Kennaway  * the following conditions are aheared to.  The following conditions
1174664626SKris Kennaway  * apply to all code found in this distribution, be it the RC4, RSA,
1274664626SKris Kennaway  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1374664626SKris Kennaway  * included with this distribution is covered by the same copyright terms
1474664626SKris Kennaway  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1574664626SKris Kennaway  *
1674664626SKris Kennaway  * Copyright remains Eric Young's, and as such any Copyright notices in
1774664626SKris Kennaway  * the code are not to be removed.
1874664626SKris Kennaway  * If this package is used in a product, Eric Young should be given attribution
1974664626SKris Kennaway  * as the author of the parts of the library used.
2074664626SKris Kennaway  * This can be in the form of a textual message at program startup or
2174664626SKris Kennaway  * in documentation (online or textual) provided with the package.
2274664626SKris Kennaway  *
2374664626SKris Kennaway  * Redistribution and use in source and binary forms, with or without
2474664626SKris Kennaway  * modification, are permitted provided that the following conditions
2574664626SKris Kennaway  * are met:
2674664626SKris Kennaway  * 1. Redistributions of source code must retain the copyright
2774664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer.
2874664626SKris Kennaway  * 2. Redistributions in binary form must reproduce the above copyright
2974664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer in the
3074664626SKris Kennaway  *    documentation and/or other materials provided with the distribution.
3174664626SKris Kennaway  * 3. All advertising materials mentioning features or use of this software
3274664626SKris Kennaway  *    must display the following acknowledgement:
3374664626SKris Kennaway  *    "This product includes cryptographic software written by
3474664626SKris Kennaway  *     Eric Young (eay@cryptsoft.com)"
3574664626SKris Kennaway  *    The word 'cryptographic' can be left out if the rouines from the library
3674664626SKris Kennaway  *    being used are not cryptographic related :-).
3774664626SKris Kennaway  * 4. If you include any Windows specific code (or a derivative thereof) from
3874664626SKris Kennaway  *    the apps directory (application code) you must include an acknowledgement:
3974664626SKris Kennaway  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4074664626SKris Kennaway  *
4174664626SKris Kennaway  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4274664626SKris Kennaway  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4374664626SKris Kennaway  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4474664626SKris Kennaway  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4574664626SKris Kennaway  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4674664626SKris Kennaway  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4774664626SKris Kennaway  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4874664626SKris Kennaway  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4974664626SKris Kennaway  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5074664626SKris Kennaway  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5174664626SKris Kennaway  * SUCH DAMAGE.
5274664626SKris Kennaway  *
5374664626SKris Kennaway  * The licence and distribution terms for any publically available version or
5474664626SKris Kennaway  * derivative of this code cannot be changed.  i.e. this code cannot simply be
5574664626SKris Kennaway  * copied and put under another distribution licence
5674664626SKris Kennaway  * [including the GNU Public Licence.]
5774664626SKris Kennaway  */
581f13597dSJung-uk Kim /* ====================================================================
591f13597dSJung-uk Kim  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
601f13597dSJung-uk Kim  *
611f13597dSJung-uk Kim  * Redistribution and use in source and binary forms, with or without
621f13597dSJung-uk Kim  * modification, are permitted provided that the following conditions
631f13597dSJung-uk Kim  * are met:
641f13597dSJung-uk Kim  *
651f13597dSJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
661f13597dSJung-uk Kim  *    notice, this list of conditions and the following disclaimer.
671f13597dSJung-uk Kim  *
681f13597dSJung-uk Kim  * 2. Redistributions in binary form must reproduce the above copyright
691f13597dSJung-uk Kim  *    notice, this list of conditions and the following disclaimer in
701f13597dSJung-uk Kim  *    the documentation and/or other materials provided with the
711f13597dSJung-uk Kim  *    distribution.
721f13597dSJung-uk Kim  *
731f13597dSJung-uk Kim  * 3. All advertising materials mentioning features or use of this
741f13597dSJung-uk Kim  *    software must display the following acknowledgment:
751f13597dSJung-uk Kim  *    "This product includes software developed by the OpenSSL Project
761f13597dSJung-uk Kim  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
771f13597dSJung-uk Kim  *
781f13597dSJung-uk Kim  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
791f13597dSJung-uk Kim  *    endorse or promote products derived from this software without
801f13597dSJung-uk Kim  *    prior written permission. For written permission, please contact
811f13597dSJung-uk Kim  *    openssl-core@openssl.org.
821f13597dSJung-uk Kim  *
831f13597dSJung-uk Kim  * 5. Products derived from this software may not be called "OpenSSL"
841f13597dSJung-uk Kim  *    nor may "OpenSSL" appear in their names without prior written
851f13597dSJung-uk Kim  *    permission of the OpenSSL Project.
861f13597dSJung-uk Kim  *
871f13597dSJung-uk Kim  * 6. Redistributions of any form whatsoever must retain the following
881f13597dSJung-uk Kim  *    acknowledgment:
891f13597dSJung-uk Kim  *    "This product includes software developed by the OpenSSL Project
901f13597dSJung-uk Kim  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
911f13597dSJung-uk Kim  *
921f13597dSJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
931f13597dSJung-uk Kim  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
941f13597dSJung-uk Kim  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
951f13597dSJung-uk Kim  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
961f13597dSJung-uk Kim  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
971f13597dSJung-uk Kim  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
981f13597dSJung-uk Kim  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
991f13597dSJung-uk Kim  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1001f13597dSJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1011f13597dSJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1021f13597dSJung-uk Kim  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
1031f13597dSJung-uk Kim  * OF THE POSSIBILITY OF SUCH DAMAGE.
1041f13597dSJung-uk Kim  * ====================================================================
1051f13597dSJung-uk Kim  *
1061f13597dSJung-uk Kim  * This product includes cryptographic software written by Eric Young
1071f13597dSJung-uk Kim  * (eay@cryptsoft.com).  This product includes software written by Tim
1081f13597dSJung-uk Kim  * Hudson (tjh@cryptsoft.com).
1091f13597dSJung-uk Kim  *
1101f13597dSJung-uk Kim  */
1111f13597dSJung-uk Kim /* ====================================================================
1121f13597dSJung-uk Kim  * Copyright 2005 Nokia. All rights reserved.
1131f13597dSJung-uk Kim  *
1141f13597dSJung-uk Kim  * The portions of the attached software ("Contribution") is developed by
1151f13597dSJung-uk Kim  * Nokia Corporation and is licensed pursuant to the OpenSSL open source
1161f13597dSJung-uk Kim  * license.
1171f13597dSJung-uk Kim  *
1181f13597dSJung-uk Kim  * The Contribution, originally written by Mika Kousa and Pasi Eronen of
1191f13597dSJung-uk Kim  * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
1201f13597dSJung-uk Kim  * support (see RFC 4279) to OpenSSL.
1211f13597dSJung-uk Kim  *
1221f13597dSJung-uk Kim  * No patent licenses or other rights except those expressly stated in
1231f13597dSJung-uk Kim  * the OpenSSL open source license shall be deemed granted or received
1241f13597dSJung-uk Kim  * expressly, by implication, estoppel, or otherwise.
1251f13597dSJung-uk Kim  *
1261f13597dSJung-uk Kim  * No assurances are provided by Nokia that the Contribution does not
1271f13597dSJung-uk Kim  * infringe the patent or other intellectual property rights of any third
1281f13597dSJung-uk Kim  * party or that the license provides you with all the necessary rights
1291f13597dSJung-uk Kim  * to make use of the Contribution.
1301f13597dSJung-uk Kim  *
1311f13597dSJung-uk Kim  * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
1321f13597dSJung-uk Kim  * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
1331f13597dSJung-uk Kim  * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
1341f13597dSJung-uk Kim  * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
1351f13597dSJung-uk Kim  * OTHERWISE.
1361f13597dSJung-uk Kim  */
13774664626SKris Kennaway 
13874664626SKris Kennaway #include <stdio.h>
13974664626SKris Kennaway #include <openssl/lhash.h>
14074664626SKris Kennaway #include <openssl/rand.h>
141db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_ENGINE
142db522d3aSSimon L. B. Nielsen # include <openssl/engine.h>
143db522d3aSSimon L. B. Nielsen #endif
14474664626SKris Kennaway #include "ssl_locl.h"
14574664626SKris Kennaway 
14674664626SKris Kennaway static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
14774664626SKris Kennaway static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);
14874664626SKris Kennaway static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
14974664626SKris Kennaway 
1503b4e3dcbSSimon L. B. Nielsen SSL_SESSION *SSL_get_session(const SSL *ssl)
151f579bf8eSKris Kennaway /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
15274664626SKris Kennaway {
15374664626SKris Kennaway     return (ssl->session);
15474664626SKris Kennaway }
15574664626SKris Kennaway 
156f579bf8eSKris Kennaway SSL_SESSION *SSL_get1_session(SSL *ssl)
157f579bf8eSKris Kennaway /* variant of SSL_get_session: caller really gets something */
158f579bf8eSKris Kennaway {
159f579bf8eSKris Kennaway     SSL_SESSION *sess;
1606f9291ceSJung-uk Kim     /*
1616f9291ceSJung-uk Kim      * Need to lock this all up rather than just use CRYPTO_add so that
1626f9291ceSJung-uk Kim      * somebody doesn't free ssl->session between when we check it's non-null
1636f9291ceSJung-uk Kim      * and when we up the reference count.
1646f9291ceSJung-uk Kim      */
16550ef0093SJacques Vidrine     CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION);
166f579bf8eSKris Kennaway     sess = ssl->session;
167f579bf8eSKris Kennaway     if (sess)
168f579bf8eSKris Kennaway         sess->references++;
16950ef0093SJacques Vidrine     CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION);
170f579bf8eSKris Kennaway     return (sess);
171f579bf8eSKris Kennaway }
172f579bf8eSKris Kennaway 
1736f9291ceSJung-uk Kim int SSL_SESSION_get_ex_new_index(long argl, void *argp,
1746f9291ceSJung-uk Kim                                  CRYPTO_EX_new *new_func,
1756f9291ceSJung-uk Kim                                  CRYPTO_EX_dup *dup_func,
1766f9291ceSJung-uk Kim                                  CRYPTO_EX_free *free_func)
17774664626SKris Kennaway {
1785c87c606SMark Murray     return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp,
1795c87c606SMark Murray                                    new_func, dup_func, free_func);
18074664626SKris Kennaway }
18174664626SKris Kennaway 
18274664626SKris Kennaway int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
18374664626SKris Kennaway {
18474664626SKris Kennaway     return (CRYPTO_set_ex_data(&s->ex_data, idx, arg));
18574664626SKris Kennaway }
18674664626SKris Kennaway 
1873b4e3dcbSSimon L. B. Nielsen void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx)
18874664626SKris Kennaway {
18974664626SKris Kennaway     return (CRYPTO_get_ex_data(&s->ex_data, idx));
19074664626SKris Kennaway }
19174664626SKris Kennaway 
19274664626SKris Kennaway SSL_SESSION *SSL_SESSION_new(void)
19374664626SKris Kennaway {
19474664626SKris Kennaway     SSL_SESSION *ss;
19574664626SKris Kennaway 
196ddd58736SKris Kennaway     ss = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
1976f9291ceSJung-uk Kim     if (ss == NULL) {
19874664626SKris Kennaway         SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE);
19974664626SKris Kennaway         return (0);
20074664626SKris Kennaway     }
20174664626SKris Kennaway     memset(ss, 0, sizeof(SSL_SESSION));
20274664626SKris Kennaway 
203f579bf8eSKris Kennaway     ss->verify_result = 1;      /* avoid 0 (= X509_V_OK) just in case */
20474664626SKris Kennaway     ss->references = 1;
20574664626SKris Kennaway     ss->timeout = 60 * 5 + 4;   /* 5 minute timeout by default */
2063b4e3dcbSSimon L. B. Nielsen     ss->time = (unsigned long)time(NULL);
20774664626SKris Kennaway     ss->prev = NULL;
20874664626SKris Kennaway     ss->next = NULL;
20974664626SKris Kennaway     ss->compress_meth = 0;
210db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_TLSEXT
211db522d3aSSimon L. B. Nielsen     ss->tlsext_hostname = NULL;
2121f13597dSJung-uk Kim # ifndef OPENSSL_NO_EC
2131f13597dSJung-uk Kim     ss->tlsext_ecpointformatlist_length = 0;
2141f13597dSJung-uk Kim     ss->tlsext_ecpointformatlist = NULL;
2151f13597dSJung-uk Kim     ss->tlsext_ellipticcurvelist_length = 0;
2161f13597dSJung-uk Kim     ss->tlsext_ellipticcurvelist = NULL;
2171f13597dSJung-uk Kim # endif
218db522d3aSSimon L. B. Nielsen #endif
2195c87c606SMark Murray     CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
2201f13597dSJung-uk Kim #ifndef OPENSSL_NO_PSK
2211f13597dSJung-uk Kim     ss->psk_identity_hint = NULL;
2221f13597dSJung-uk Kim     ss->psk_identity = NULL;
2231f13597dSJung-uk Kim #endif
2241f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP
2251f13597dSJung-uk Kim     ss->srp_username = NULL;
2261f13597dSJung-uk Kim #endif
22774664626SKris Kennaway     return (ss);
22874664626SKris Kennaway }
22974664626SKris Kennaway 
230ed6b93beSJung-uk Kim /*
231ed6b93beSJung-uk Kim  * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
232ed6b93beSJung-uk Kim  * ticket == 0 then no ticket information is duplicated, otherwise it is.
233ed6b93beSJung-uk Kim  */
234ed6b93beSJung-uk Kim SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
235ed6b93beSJung-uk Kim {
236ed6b93beSJung-uk Kim     SSL_SESSION *dest;
237ed6b93beSJung-uk Kim 
238ed6b93beSJung-uk Kim     dest = OPENSSL_malloc(sizeof(*src));
239ed6b93beSJung-uk Kim     if (dest == NULL) {
240ed6b93beSJung-uk Kim         goto err;
241ed6b93beSJung-uk Kim     }
242ed6b93beSJung-uk Kim     memcpy(dest, src, sizeof(*dest));
243ed6b93beSJung-uk Kim 
244ed6b93beSJung-uk Kim     /*
245ed6b93beSJung-uk Kim      * Set the various pointers to NULL so that we can call SSL_SESSION_free in
246ed6b93beSJung-uk Kim      * the case of an error whilst halfway through constructing dest
247ed6b93beSJung-uk Kim      */
248ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_PSK
249ed6b93beSJung-uk Kim     dest->psk_identity_hint = NULL;
250ed6b93beSJung-uk Kim     dest->psk_identity = NULL;
251ed6b93beSJung-uk Kim #endif
252ed6b93beSJung-uk Kim     dest->ciphers = NULL;
253ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_TLSEXT
254ed6b93beSJung-uk Kim     dest->tlsext_hostname = NULL;
255ed6b93beSJung-uk Kim # ifndef OPENSSL_NO_EC
256ed6b93beSJung-uk Kim     dest->tlsext_ecpointformatlist = NULL;
257ed6b93beSJung-uk Kim     dest->tlsext_ellipticcurvelist = NULL;
258ed6b93beSJung-uk Kim # endif
259ed6b93beSJung-uk Kim     dest->tlsext_tick = NULL;
26080815a77SJung-uk Kim #endif
261ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_SRP
262ed6b93beSJung-uk Kim     dest->srp_username = NULL;
263ed6b93beSJung-uk Kim #endif
264ed6b93beSJung-uk Kim 
265ed6b93beSJung-uk Kim     /* We deliberately don't copy the prev and next pointers */
266ed6b93beSJung-uk Kim     dest->prev = NULL;
267ed6b93beSJung-uk Kim     dest->next = NULL;
268ed6b93beSJung-uk Kim 
269ed6b93beSJung-uk Kim     dest->references = 1;
270ed6b93beSJung-uk Kim 
271ed6b93beSJung-uk Kim     if (src->sess_cert != NULL)
272ed6b93beSJung-uk Kim         CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
273ed6b93beSJung-uk Kim 
274ed6b93beSJung-uk Kim     if (src->peer != NULL)
275ed6b93beSJung-uk Kim         CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
276ed6b93beSJung-uk Kim 
27747902a71SJung-uk Kim     if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data))
27847902a71SJung-uk Kim         goto err;
27947902a71SJung-uk Kim 
280ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_PSK
281ed6b93beSJung-uk Kim     if (src->psk_identity_hint) {
282ed6b93beSJung-uk Kim         dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint);
283ed6b93beSJung-uk Kim         if (dest->psk_identity_hint == NULL) {
284ed6b93beSJung-uk Kim             goto err;
285ed6b93beSJung-uk Kim         }
286ed6b93beSJung-uk Kim     }
287ed6b93beSJung-uk Kim     if (src->psk_identity) {
288ed6b93beSJung-uk Kim         dest->psk_identity = BUF_strdup(src->psk_identity);
289ed6b93beSJung-uk Kim         if (dest->psk_identity == NULL) {
290ed6b93beSJung-uk Kim             goto err;
291ed6b93beSJung-uk Kim         }
292ed6b93beSJung-uk Kim     }
293ed6b93beSJung-uk Kim #endif
294ed6b93beSJung-uk Kim 
295ed6b93beSJung-uk Kim     if(src->ciphers != NULL) {
296ed6b93beSJung-uk Kim         dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
297ed6b93beSJung-uk Kim         if (dest->ciphers == NULL)
298ed6b93beSJung-uk Kim             goto err;
299ed6b93beSJung-uk Kim     }
300ed6b93beSJung-uk Kim 
301ed6b93beSJung-uk Kim     if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
302ed6b93beSJung-uk Kim                                             &dest->ex_data, &src->ex_data)) {
303ed6b93beSJung-uk Kim         goto err;
304ed6b93beSJung-uk Kim     }
305ed6b93beSJung-uk Kim 
306ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_TLSEXT
307ed6b93beSJung-uk Kim     if (src->tlsext_hostname) {
308ed6b93beSJung-uk Kim         dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
309ed6b93beSJung-uk Kim         if (dest->tlsext_hostname == NULL) {
310ed6b93beSJung-uk Kim             goto err;
311ed6b93beSJung-uk Kim         }
312ed6b93beSJung-uk Kim     }
313ed6b93beSJung-uk Kim # ifndef OPENSSL_NO_EC
314ed6b93beSJung-uk Kim     if (src->tlsext_ecpointformatlist) {
315ed6b93beSJung-uk Kim         dest->tlsext_ecpointformatlist =
316ed6b93beSJung-uk Kim             BUF_memdup(src->tlsext_ecpointformatlist,
317ed6b93beSJung-uk Kim                        src->tlsext_ecpointformatlist_length);
318ed6b93beSJung-uk Kim         if (dest->tlsext_ecpointformatlist == NULL)
319ed6b93beSJung-uk Kim             goto err;
320ed6b93beSJung-uk Kim     }
321ed6b93beSJung-uk Kim     if (src->tlsext_ellipticcurvelist) {
322ed6b93beSJung-uk Kim         dest->tlsext_ellipticcurvelist =
323ed6b93beSJung-uk Kim             BUF_memdup(src->tlsext_ellipticcurvelist,
324ed6b93beSJung-uk Kim                        src->tlsext_ellipticcurvelist_length);
325ed6b93beSJung-uk Kim         if (dest->tlsext_ellipticcurvelist == NULL)
326ed6b93beSJung-uk Kim             goto err;
327ed6b93beSJung-uk Kim     }
328ed6b93beSJung-uk Kim # endif
329ed6b93beSJung-uk Kim 
33047902a71SJung-uk Kim     if (ticket != 0 && src->tlsext_tick != NULL) {
331ed6b93beSJung-uk Kim         dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
332ed6b93beSJung-uk Kim         if(dest->tlsext_tick == NULL)
333ed6b93beSJung-uk Kim             goto err;
334ed6b93beSJung-uk Kim     } else {
335ed6b93beSJung-uk Kim         dest->tlsext_tick_lifetime_hint = 0;
336ed6b93beSJung-uk Kim         dest->tlsext_ticklen = 0;
337ed6b93beSJung-uk Kim     }
33880815a77SJung-uk Kim #endif
339ed6b93beSJung-uk Kim 
340ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_SRP
341ed6b93beSJung-uk Kim     if (src->srp_username) {
342ed6b93beSJung-uk Kim         dest->srp_username = BUF_strdup(src->srp_username);
343ed6b93beSJung-uk Kim         if (dest->srp_username == NULL) {
344ed6b93beSJung-uk Kim             goto err;
345ed6b93beSJung-uk Kim         }
346ed6b93beSJung-uk Kim     }
347ed6b93beSJung-uk Kim #endif
348ed6b93beSJung-uk Kim 
349ed6b93beSJung-uk Kim     return dest;
350ed6b93beSJung-uk Kim err:
351ed6b93beSJung-uk Kim     SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
352ed6b93beSJung-uk Kim     SSL_SESSION_free(dest);
353ed6b93beSJung-uk Kim     return NULL;
354ed6b93beSJung-uk Kim }
355ed6b93beSJung-uk Kim 
3566f9291ceSJung-uk Kim const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
3576f9291ceSJung-uk Kim                                         unsigned int *len)
3583b4e3dcbSSimon L. B. Nielsen {
3593b4e3dcbSSimon L. B. Nielsen     if (len)
3603b4e3dcbSSimon L. B. Nielsen         *len = s->session_id_length;
3613b4e3dcbSSimon L. B. Nielsen     return s->session_id;
3623b4e3dcbSSimon L. B. Nielsen }
3633b4e3dcbSSimon L. B. Nielsen 
3641f13597dSJung-uk Kim unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s)
3651f13597dSJung-uk Kim {
3661f13597dSJung-uk Kim     return s->compress_meth;
3671f13597dSJung-uk Kim }
3681f13597dSJung-uk Kim 
3696f9291ceSJung-uk Kim /*
3706f9291ceSJung-uk Kim  * Even with SSLv2, we have 16 bytes (128 bits) of session ID space.
3716f9291ceSJung-uk Kim  * SSLv3/TLSv1 has 32 bytes (256 bits). As such, filling the ID with random
3726f9291ceSJung-uk Kim  * gunk repeatedly until we have no conflict is going to complete in one
3736f9291ceSJung-uk Kim  * iteration pretty much "most" of the time (btw: understatement). So, if it
3746f9291ceSJung-uk Kim  * takes us 10 iterations and we still can't avoid a conflict - well that's a
3756f9291ceSJung-uk Kim  * reasonable point to call it quits. Either the RAND code is broken or
3766f9291ceSJung-uk Kim  * someone is trying to open roughly very close to 2^128 (or 2^256) SSL
3776f9291ceSJung-uk Kim  * sessions to our server. How you might store that many sessions is perhaps
3786f9291ceSJung-uk Kim  * a more interesting question ...
3796f9291ceSJung-uk Kim  */
3805c87c606SMark Murray 
3815c87c606SMark Murray #define MAX_SESS_ID_ATTEMPTS 10
3825c87c606SMark Murray static int def_generate_session_id(const SSL *ssl, unsigned char *id,
3835c87c606SMark Murray                                    unsigned int *id_len)
3845c87c606SMark Murray {
3855c87c606SMark Murray     unsigned int retry = 0;
3865c87c606SMark Murray     do
387aeb5019cSJung-uk Kim         if (RAND_bytes(id, *id_len) <= 0)
3886be8ae07SJacques Vidrine             return 0;
3895c87c606SMark Murray     while (SSL_has_matching_session_id(ssl, id, *id_len) &&
3905c87c606SMark Murray            (++retry < MAX_SESS_ID_ATTEMPTS)) ;
3915c87c606SMark Murray     if (retry < MAX_SESS_ID_ATTEMPTS)
3925c87c606SMark Murray         return 1;
3935c87c606SMark Murray     /* else - woops a session_id match */
3946f9291ceSJung-uk Kim     /*
3956f9291ceSJung-uk Kim      * XXX We should also check the external cache -- but the probability of
3966f9291ceSJung-uk Kim      * a collision is negligible, and we could not prevent the concurrent
3976f9291ceSJung-uk Kim      * creation of sessions with identical IDs since we currently don't have
3986f9291ceSJung-uk Kim      * means to atomically check whether a session ID already exists and make
3996f9291ceSJung-uk Kim      * a reservation for it if it does not (this problem applies to the
4006f9291ceSJung-uk Kim      * internal cache as well).
4015c87c606SMark Murray      */
4025c87c606SMark Murray     return 0;
4035c87c606SMark Murray }
4045c87c606SMark Murray 
40574664626SKris Kennaway int ssl_get_new_session(SSL *s, int session)
40674664626SKris Kennaway {
40774664626SKris Kennaway     /* This gets used by clients and servers. */
40874664626SKris Kennaway 
4095c87c606SMark Murray     unsigned int tmp;
41074664626SKris Kennaway     SSL_SESSION *ss = NULL;
4115c87c606SMark Murray     GEN_SESSION_CB cb = def_generate_session_id;
41274664626SKris Kennaway 
4136f9291ceSJung-uk Kim     if ((ss = SSL_SESSION_new()) == NULL)
4146f9291ceSJung-uk Kim         return (0);
41574664626SKris Kennaway 
41674664626SKris Kennaway     /* If the context has a default timeout, use it */
4171f13597dSJung-uk Kim     if (s->session_ctx->session_timeout == 0)
41874664626SKris Kennaway         ss->timeout = SSL_get_default_timeout(s);
41974664626SKris Kennaway     else
4201f13597dSJung-uk Kim         ss->timeout = s->session_ctx->session_timeout;
42174664626SKris Kennaway 
4226f9291ceSJung-uk Kim     if (s->session != NULL) {
42374664626SKris Kennaway         SSL_SESSION_free(s->session);
42474664626SKris Kennaway         s->session = NULL;
42574664626SKris Kennaway     }
42674664626SKris Kennaway 
4276f9291ceSJung-uk Kim     if (session) {
4286f9291ceSJung-uk Kim         if (s->version == SSL2_VERSION) {
42974664626SKris Kennaway             ss->ssl_version = SSL2_VERSION;
43074664626SKris Kennaway             ss->session_id_length = SSL2_SSL_SESSION_ID_LENGTH;
4316f9291ceSJung-uk Kim         } else if (s->version == SSL3_VERSION) {
43274664626SKris Kennaway             ss->ssl_version = SSL3_VERSION;
43374664626SKris Kennaway             ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
4346f9291ceSJung-uk Kim         } else if (s->version == TLS1_VERSION) {
43574664626SKris Kennaway             ss->ssl_version = TLS1_VERSION;
43674664626SKris Kennaway             ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
4376f9291ceSJung-uk Kim         } else if (s->version == TLS1_1_VERSION) {
4381f13597dSJung-uk Kim             ss->ssl_version = TLS1_1_VERSION;
4391f13597dSJung-uk Kim             ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
4406f9291ceSJung-uk Kim         } else if (s->version == TLS1_2_VERSION) {
4411f13597dSJung-uk Kim             ss->ssl_version = TLS1_2_VERSION;
4421f13597dSJung-uk Kim             ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
4436f9291ceSJung-uk Kim         } else if (s->version == DTLS1_BAD_VER) {
4446a599222SSimon L. B. Nielsen             ss->ssl_version = DTLS1_BAD_VER;
4456a599222SSimon L. B. Nielsen             ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
4466f9291ceSJung-uk Kim         } else if (s->version == DTLS1_VERSION) {
4473b4e3dcbSSimon L. B. Nielsen             ss->ssl_version = DTLS1_VERSION;
4483b4e3dcbSSimon L. B. Nielsen             ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
4497bded2dbSJung-uk Kim         } else if (s->version == DTLS1_2_VERSION) {
4507bded2dbSJung-uk Kim             ss->ssl_version = DTLS1_2_VERSION;
4517bded2dbSJung-uk Kim             ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
4526f9291ceSJung-uk Kim         } else {
45374664626SKris Kennaway             SSLerr(SSL_F_SSL_GET_NEW_SESSION, SSL_R_UNSUPPORTED_SSL_VERSION);
45474664626SKris Kennaway             SSL_SESSION_free(ss);
45574664626SKris Kennaway             return (0);
45674664626SKris Kennaway         }
457db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_TLSEXT
4586f9291ceSJung-uk Kim         /*-
459751d2991SJung-uk Kim          * If RFC5077 ticket, use empty session ID (as server).
460751d2991SJung-uk Kim          * Note that:
461751d2991SJung-uk Kim          * (a) ssl_get_prev_session() does lookahead into the
462751d2991SJung-uk Kim          *     ClientHello extensions to find the session ticket.
463751d2991SJung-uk Kim          *     When ssl_get_prev_session() fails, s3_srvr.c calls
464751d2991SJung-uk Kim          *     ssl_get_new_session() in ssl3_get_client_hello().
465751d2991SJung-uk Kim          *     At that point, it has not yet parsed the extensions,
466751d2991SJung-uk Kim          *     however, because of the lookahead, it already knows
467751d2991SJung-uk Kim          *     whether a ticket is expected or not.
468751d2991SJung-uk Kim          *
469751d2991SJung-uk Kim          * (b) s3_clnt.c calls ssl_get_new_session() before parsing
470751d2991SJung-uk Kim          *     ServerHello extensions, and before recording the session
471751d2991SJung-uk Kim          *     ID received from the server, so this block is a noop.
472751d2991SJung-uk Kim          */
4736f9291ceSJung-uk Kim         if (s->tlsext_ticket_expected) {
474db522d3aSSimon L. B. Nielsen             ss->session_id_length = 0;
475db522d3aSSimon L. B. Nielsen             goto sess_id_done;
476db522d3aSSimon L. B. Nielsen         }
477db522d3aSSimon L. B. Nielsen #endif
4785c87c606SMark Murray         /* Choose which callback will set the session ID */
47974664626SKris Kennaway         CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
4805c87c606SMark Murray         if (s->generate_session_id)
4815c87c606SMark Murray             cb = s->generate_session_id;
4821f13597dSJung-uk Kim         else if (s->session_ctx->generate_session_id)
4831f13597dSJung-uk Kim             cb = s->session_ctx->generate_session_id;
48474664626SKris Kennaway         CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
4855c87c606SMark Murray         /* Choose a session ID */
4865c87c606SMark Murray         tmp = ss->session_id_length;
4876f9291ceSJung-uk Kim         if (!cb(s, ss->session_id, &tmp)) {
4885c87c606SMark Murray             /* The callback failed */
4895c87c606SMark Murray             SSLerr(SSL_F_SSL_GET_NEW_SESSION,
4905c87c606SMark Murray                    SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
4915c87c606SMark Murray             SSL_SESSION_free(ss);
4925c87c606SMark Murray             return (0);
4935c87c606SMark Murray         }
4946f9291ceSJung-uk Kim         /*
4956f9291ceSJung-uk Kim          * Don't allow the callback to set the session length to zero. nor
4966f9291ceSJung-uk Kim          * set it higher than it was.
4976f9291ceSJung-uk Kim          */
4986f9291ceSJung-uk Kim         if (!tmp || (tmp > ss->session_id_length)) {
4995c87c606SMark Murray             /* The callback set an illegal length */
5005c87c606SMark Murray             SSLerr(SSL_F_SSL_GET_NEW_SESSION,
5015c87c606SMark Murray                    SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
5025c87c606SMark Murray             SSL_SESSION_free(ss);
5035c87c606SMark Murray             return (0);
5045c87c606SMark Murray         }
5055c87c606SMark Murray         /* If the session length was shrunk and we're SSLv2, pad it */
5065c87c606SMark Murray         if ((tmp < ss->session_id_length) && (s->version == SSL2_VERSION))
5075c87c606SMark Murray             memset(ss->session_id + tmp, 0, ss->session_id_length - tmp);
5085c87c606SMark Murray         else
5095c87c606SMark Murray             ss->session_id_length = tmp;
5105c87c606SMark Murray         /* Finally, check for a conflict */
5115c87c606SMark Murray         if (SSL_has_matching_session_id(s, ss->session_id,
5126f9291ceSJung-uk Kim                                         ss->session_id_length)) {
5136f9291ceSJung-uk Kim             SSLerr(SSL_F_SSL_GET_NEW_SESSION, SSL_R_SSL_SESSION_ID_CONFLICT);
5145c87c606SMark Murray             SSL_SESSION_free(ss);
5155c87c606SMark Murray             return (0);
51674664626SKris Kennaway         }
517db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_TLSEXT
518db522d3aSSimon L. B. Nielsen  sess_id_done:
519db522d3aSSimon L. B. Nielsen         if (s->tlsext_hostname) {
520db522d3aSSimon L. B. Nielsen             ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
521db522d3aSSimon L. B. Nielsen             if (ss->tlsext_hostname == NULL) {
522db522d3aSSimon L. B. Nielsen                 SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
523db522d3aSSimon L. B. Nielsen                 SSL_SESSION_free(ss);
524db522d3aSSimon L. B. Nielsen                 return 0;
525db522d3aSSimon L. B. Nielsen             }
526db522d3aSSimon L. B. Nielsen         }
527db522d3aSSimon L. B. Nielsen #endif
5286f9291ceSJung-uk Kim     } else {
52974664626SKris Kennaway         ss->session_id_length = 0;
53074664626SKris Kennaway     }
53174664626SKris Kennaway 
532*dee36b4fSJung-uk Kim     if (s->sid_ctx_length > sizeof(ss->sid_ctx)) {
5335c87c606SMark Murray         SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
53448454956SJacques Vidrine         SSL_SESSION_free(ss);
53548454956SJacques Vidrine         return 0;
53648454956SJacques Vidrine     }
53774664626SKris Kennaway     memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length);
53874664626SKris Kennaway     ss->sid_ctx_length = s->sid_ctx_length;
53974664626SKris Kennaway     s->session = ss;
54074664626SKris Kennaway     ss->ssl_version = s->version;
541f579bf8eSKris Kennaway     ss->verify_result = X509_V_OK;
54274664626SKris Kennaway 
54374664626SKris Kennaway     return (1);
54474664626SKris Kennaway }
54574664626SKris Kennaway 
5466f9291ceSJung-uk Kim /*-
5476f9291ceSJung-uk Kim  * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this
5481f13597dSJung-uk Kim  * connection. It is only called by servers.
5491f13597dSJung-uk Kim  *
5501f13597dSJung-uk Kim  *   session_id: points at the session ID in the ClientHello. This code will
5511f13597dSJung-uk Kim  *       read past the end of this in order to parse out the session ticket
5521f13597dSJung-uk Kim  *       extension, if any.
5531f13597dSJung-uk Kim  *   len: the length of the session ID.
5541f13597dSJung-uk Kim  *   limit: a pointer to the first byte after the ClientHello.
5551f13597dSJung-uk Kim  *
5561f13597dSJung-uk Kim  * Returns:
5571f13597dSJung-uk Kim  *   -1: error
5581f13597dSJung-uk Kim  *    0: a session may have been found.
5591f13597dSJung-uk Kim  *
5601f13597dSJung-uk Kim  * Side effects:
5611f13597dSJung-uk Kim  *   - If a session is found then s->session is pointed at it (after freeing an
5621f13597dSJung-uk Kim  *     existing session if need be) and s->verify_result is set from the session.
5631f13597dSJung-uk Kim  *   - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1
5641f13597dSJung-uk Kim  *     if the server should issue a new session ticket (to 0 otherwise).
5651f13597dSJung-uk Kim  */
566db522d3aSSimon L. B. Nielsen int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
567db522d3aSSimon L. B. Nielsen                          const unsigned char *limit)
56874664626SKris Kennaway {
56974664626SKris Kennaway     /* This is used only by servers. */
57074664626SKris Kennaway 
571db522d3aSSimon L. B. Nielsen     SSL_SESSION *ret = NULL;
57274664626SKris Kennaway     int fatal = 0;
5731f13597dSJung-uk Kim     int try_session_cache = 1;
574db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_TLSEXT
575db522d3aSSimon L. B. Nielsen     int r;
576db522d3aSSimon L. B. Nielsen #endif
57774664626SKris Kennaway 
578aeb5019cSJung-uk Kim     if (limit - session_id < len) {
579ed6b93beSJung-uk Kim         fatal = 1;
580ed6b93beSJung-uk Kim         goto err;
581ed6b93beSJung-uk Kim     }
582ed6b93beSJung-uk Kim 
5831f13597dSJung-uk Kim     if (len == 0)
5841f13597dSJung-uk Kim         try_session_cache = 0;
5851f13597dSJung-uk Kim 
586db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_TLSEXT
5876f9291ceSJung-uk Kim     /* sets s->tlsext_ticket_expected */
5886f9291ceSJung-uk Kim     r = tls1_process_ticket(s, session_id, len, limit, &ret);
5896f9291ceSJung-uk Kim     switch (r) {
5901f13597dSJung-uk Kim     case -1:                   /* Error during processing */
591db522d3aSSimon L. B. Nielsen         fatal = 1;
592db522d3aSSimon L. B. Nielsen         goto err;
5931f13597dSJung-uk Kim     case 0:                    /* No ticket found */
5941f13597dSJung-uk Kim     case 1:                    /* Zero length ticket found */
5951f13597dSJung-uk Kim         break;                  /* Ok to carry on processing session id. */
5961f13597dSJung-uk Kim     case 2:                    /* Ticket found but not decrypted. */
5971f13597dSJung-uk Kim     case 3:                    /* Ticket decrypted, *ret has been set. */
5981f13597dSJung-uk Kim         try_session_cache = 0;
5991f13597dSJung-uk Kim         break;
6001f13597dSJung-uk Kim     default:
6011f13597dSJung-uk Kim         abort();
602db522d3aSSimon L. B. Nielsen     }
603db522d3aSSimon L. B. Nielsen #endif
6041f13597dSJung-uk Kim 
6051f13597dSJung-uk Kim     if (try_session_cache &&
6061f13597dSJung-uk Kim         ret == NULL &&
6076f9291ceSJung-uk Kim         !(s->session_ctx->session_cache_mode &
6086f9291ceSJung-uk Kim           SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
609db522d3aSSimon L. B. Nielsen         SSL_SESSION data;
610db522d3aSSimon L. B. Nielsen         data.ssl_version = s->version;
611db522d3aSSimon L. B. Nielsen         data.session_id_length = len;
612db522d3aSSimon L. B. Nielsen         if (len == 0)
613db522d3aSSimon L. B. Nielsen             return 0;
614db522d3aSSimon L. B. Nielsen         memcpy(data.session_id, session_id, len);
61574664626SKris Kennaway         CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
6161f13597dSJung-uk Kim         ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data);
6176f9291ceSJung-uk Kim         if (ret != NULL) {
61874664626SKris Kennaway             /* don't allow other threads to steal it: */
61974664626SKris Kennaway             CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_SSL_SESSION);
6201f13597dSJung-uk Kim         }
62174664626SKris Kennaway         CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
6221f13597dSJung-uk Kim         if (ret == NULL)
6231f13597dSJung-uk Kim             s->session_ctx->stats.sess_miss++;
62474664626SKris Kennaway     }
62574664626SKris Kennaway 
6261f13597dSJung-uk Kim     if (try_session_cache &&
6276f9291ceSJung-uk Kim         ret == NULL && s->session_ctx->get_session_cb != NULL) {
62874664626SKris Kennaway         int copy = 1;
62974664626SKris Kennaway 
6306f9291ceSJung-uk Kim         if ((ret = s->session_ctx->get_session_cb(s, session_id, len, &copy))) {
6311f13597dSJung-uk Kim             s->session_ctx->stats.sess_cb_hit++;
63274664626SKris Kennaway 
6336f9291ceSJung-uk Kim             /*
6346f9291ceSJung-uk Kim              * Increment reference count now if the session callback asks us
6356f9291ceSJung-uk Kim              * to do so (note that if the session structures returned by the
6366f9291ceSJung-uk Kim              * callback are shared between threads, it must handle the
6376f9291ceSJung-uk Kim              * reference count itself [i.e. copy == 0], or things won't be
6386f9291ceSJung-uk Kim              * thread-safe).
6396f9291ceSJung-uk Kim              */
64074664626SKris Kennaway             if (copy)
64174664626SKris Kennaway                 CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_SSL_SESSION);
64274664626SKris Kennaway 
6436f9291ceSJung-uk Kim             /*
6446f9291ceSJung-uk Kim              * Add the externally cached session to the internal cache as
6456f9291ceSJung-uk Kim              * well if and only if we are supposed to.
6466f9291ceSJung-uk Kim              */
6476f9291ceSJung-uk Kim             if (!
6486f9291ceSJung-uk Kim                 (s->session_ctx->session_cache_mode &
6496f9291ceSJung-uk Kim                  SSL_SESS_CACHE_NO_INTERNAL_STORE))
6506f9291ceSJung-uk Kim                 /*
6516f9291ceSJung-uk Kim                  * The following should not return 1, otherwise, things are
6526f9291ceSJung-uk Kim                  * very strange
6536f9291ceSJung-uk Kim                  */
6541f13597dSJung-uk Kim                 SSL_CTX_add_session(s->session_ctx, ret);
65574664626SKris Kennaway         }
65674664626SKris Kennaway     }
65774664626SKris Kennaway 
6581f13597dSJung-uk Kim     if (ret == NULL)
6591f13597dSJung-uk Kim         goto err;
6601f13597dSJung-uk Kim 
6611f13597dSJung-uk Kim     /* Now ret is non-NULL and we own one of its reference counts. */
66274664626SKris Kennaway 
663db522d3aSSimon L. B. Nielsen     if (ret->sid_ctx_length != s->sid_ctx_length
6646f9291ceSJung-uk Kim         || memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) {
6656f9291ceSJung-uk Kim         /*
6666f9291ceSJung-uk Kim          * We have the session requested by the client, but we don't want to
6676f9291ceSJung-uk Kim          * use it in this context.
6686f9291ceSJung-uk Kim          */
66974664626SKris Kennaway         goto err;               /* treat like cache miss */
67074664626SKris Kennaway     }
671db522d3aSSimon L. B. Nielsen 
6726f9291ceSJung-uk Kim     if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) {
6736f9291ceSJung-uk Kim         /*
6746f9291ceSJung-uk Kim          * We can't be sure if this session is being used out of context,
6756f9291ceSJung-uk Kim          * which is especially important for SSL_VERIFY_PEER. The application
6766f9291ceSJung-uk Kim          * should have used SSL[_CTX]_set_session_id_context. For this error
6776f9291ceSJung-uk Kim          * case, we generate an error instead of treating the event like a
6786f9291ceSJung-uk Kim          * cache miss (otherwise it would be easy for applications to
6796f9291ceSJung-uk Kim          * effectively disable the session cache by accident without anyone
6806f9291ceSJung-uk Kim          * noticing).
681db522d3aSSimon L. B. Nielsen          */
682db522d3aSSimon L. B. Nielsen 
6836f9291ceSJung-uk Kim         SSLerr(SSL_F_SSL_GET_PREV_SESSION,
6846f9291ceSJung-uk Kim                SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
685db522d3aSSimon L. B. Nielsen         fatal = 1;
686db522d3aSSimon L. B. Nielsen         goto err;
68774664626SKris Kennaway     }
68874664626SKris Kennaway 
6896f9291ceSJung-uk Kim     if (ret->cipher == NULL) {
69074664626SKris Kennaway         unsigned char buf[5], *p;
69174664626SKris Kennaway         unsigned long l;
69274664626SKris Kennaway 
69374664626SKris Kennaway         p = buf;
69474664626SKris Kennaway         l = ret->cipher_id;
69574664626SKris Kennaway         l2n(l, p);
6966a599222SSimon L. B. Nielsen         if ((ret->ssl_version >> 8) >= SSL3_VERSION_MAJOR)
69774664626SKris Kennaway             ret->cipher = ssl_get_cipher_by_char(s, &(buf[2]));
69874664626SKris Kennaway         else
69974664626SKris Kennaway             ret->cipher = ssl_get_cipher_by_char(s, &(buf[1]));
70074664626SKris Kennaway         if (ret->cipher == NULL)
70174664626SKris Kennaway             goto err;
70274664626SKris Kennaway     }
70374664626SKris Kennaway 
7046f9291ceSJung-uk Kim     if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */
7051f13597dSJung-uk Kim         s->session_ctx->stats.sess_timeout++;
7066f9291ceSJung-uk Kim         if (try_session_cache) {
7071f13597dSJung-uk Kim             /* session was from the cache, so remove it */
7081f13597dSJung-uk Kim             SSL_CTX_remove_session(s->session_ctx, ret);
7091f13597dSJung-uk Kim         }
71074664626SKris Kennaway         goto err;
71174664626SKris Kennaway     }
71274664626SKris Kennaway 
7131f13597dSJung-uk Kim     s->session_ctx->stats.sess_hit++;
71474664626SKris Kennaway 
71574664626SKris Kennaway     if (s->session != NULL)
71674664626SKris Kennaway         SSL_SESSION_free(s->session);
71774664626SKris Kennaway     s->session = ret;
718f579bf8eSKris Kennaway     s->verify_result = s->session->verify_result;
7191f13597dSJung-uk Kim     return 1;
72074664626SKris Kennaway 
72174664626SKris Kennaway  err:
7226f9291ceSJung-uk Kim     if (ret != NULL) {
72374664626SKris Kennaway         SSL_SESSION_free(ret);
7241f13597dSJung-uk Kim #ifndef OPENSSL_NO_TLSEXT
7256f9291ceSJung-uk Kim         if (!try_session_cache) {
7266f9291ceSJung-uk Kim             /*
7276f9291ceSJung-uk Kim              * The session was from a ticket, so we should issue a ticket for
7286f9291ceSJung-uk Kim              * the new session
7296f9291ceSJung-uk Kim              */
7301f13597dSJung-uk Kim             s->tlsext_ticket_expected = 1;
7311f13597dSJung-uk Kim         }
7321f13597dSJung-uk Kim #endif
7331f13597dSJung-uk Kim     }
73474664626SKris Kennaway     if (fatal)
73574664626SKris Kennaway         return -1;
73674664626SKris Kennaway     else
73774664626SKris Kennaway         return 0;
73874664626SKris Kennaway }
73974664626SKris Kennaway 
74074664626SKris Kennaway int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
74174664626SKris Kennaway {
74274664626SKris Kennaway     int ret = 0;
74374664626SKris Kennaway     SSL_SESSION *s;
74474664626SKris Kennaway 
7456f9291ceSJung-uk Kim     /*
7466f9291ceSJung-uk Kim      * add just 1 reference count for the SSL_CTX's session cache even though
7476f9291ceSJung-uk Kim      * it has two ways of access: each session is in a doubly linked list and
7486f9291ceSJung-uk Kim      * an lhash
7496f9291ceSJung-uk Kim      */
75074664626SKris Kennaway     CRYPTO_add(&c->references, 1, CRYPTO_LOCK_SSL_SESSION);
7516f9291ceSJung-uk Kim     /*
7526f9291ceSJung-uk Kim      * if session c is in already in cache, we take back the increment later
7536f9291ceSJung-uk Kim      */
75474664626SKris Kennaway 
75574664626SKris Kennaway     CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
7561f13597dSJung-uk Kim     s = lh_SSL_SESSION_insert(ctx->sessions, c);
75774664626SKris Kennaway 
7586f9291ceSJung-uk Kim     /*
7596f9291ceSJung-uk Kim      * s != NULL iff we already had a session with the given PID. In this
7606f9291ceSJung-uk Kim      * case, s == c should hold (then we did not really modify
7616f9291ceSJung-uk Kim      * ctx->sessions), or we're in trouble.
7626f9291ceSJung-uk Kim      */
7636f9291ceSJung-uk Kim     if (s != NULL && s != c) {
764f579bf8eSKris Kennaway         /* We *are* in trouble ... */
765f579bf8eSKris Kennaway         SSL_SESSION_list_remove(ctx, s);
766f579bf8eSKris Kennaway         SSL_SESSION_free(s);
7676f9291ceSJung-uk Kim         /*
7686f9291ceSJung-uk Kim          * ... so pretend the other session did not exist in cache (we cannot
7696f9291ceSJung-uk Kim          * handle two SSL_SESSION structures with identical session ID in the
7706f9291ceSJung-uk Kim          * same cache, which could happen e.g. when two threads concurrently
7716f9291ceSJung-uk Kim          * obtain the same session from an external cache)
7726f9291ceSJung-uk Kim          */
773f579bf8eSKris Kennaway         s = NULL;
7746cf8931aSJung-uk Kim     } else if (s == NULL &&
7756cf8931aSJung-uk Kim                lh_SSL_SESSION_retrieve(ctx->sessions, c) == NULL) {
7766cf8931aSJung-uk Kim         /* s == NULL can also mean OOM error in lh_SSL_SESSION_insert ... */
7776cf8931aSJung-uk Kim 
7786cf8931aSJung-uk Kim         /*
7796cf8931aSJung-uk Kim          * ... so take back the extra reference and also don't add
7806cf8931aSJung-uk Kim          * the session to the SSL_SESSION_list at this time
7816cf8931aSJung-uk Kim          */
7826cf8931aSJung-uk Kim         s = c;
783f579bf8eSKris Kennaway     }
784f579bf8eSKris Kennaway 
785f579bf8eSKris Kennaway     /* Put at the head of the queue unless it is already in the cache */
78674664626SKris Kennaway     if (s == NULL)
78774664626SKris Kennaway         SSL_SESSION_list_add(ctx, c);
78874664626SKris Kennaway 
7896f9291ceSJung-uk Kim     if (s != NULL) {
7906f9291ceSJung-uk Kim         /*
7916f9291ceSJung-uk Kim          * existing cache entry -- decrement previously incremented reference
7926f9291ceSJung-uk Kim          * count because it already takes into account the cache
7936f9291ceSJung-uk Kim          */
794f579bf8eSKris Kennaway 
795f579bf8eSKris Kennaway         SSL_SESSION_free(s);    /* s == c */
79674664626SKris Kennaway         ret = 0;
7976f9291ceSJung-uk Kim     } else {
7986f9291ceSJung-uk Kim         /*
7996f9291ceSJung-uk Kim          * new cache entry -- remove old ones if cache has become too large
8006f9291ceSJung-uk Kim          */
801f579bf8eSKris Kennaway 
80274664626SKris Kennaway         ret = 1;
80374664626SKris Kennaway 
8046f9291ceSJung-uk Kim         if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
80574664626SKris Kennaway             while (SSL_CTX_sess_number(ctx) >
8066f9291ceSJung-uk Kim                    SSL_CTX_sess_get_cache_size(ctx)) {
8076f9291ceSJung-uk Kim                 if (!remove_session_lock(ctx, ctx->session_cache_tail, 0))
80874664626SKris Kennaway                     break;
80974664626SKris Kennaway                 else
81074664626SKris Kennaway                     ctx->stats.sess_cache_full++;
81174664626SKris Kennaway             }
81274664626SKris Kennaway         }
81374664626SKris Kennaway     }
81474664626SKris Kennaway     CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
81574664626SKris Kennaway     return (ret);
81674664626SKris Kennaway }
81774664626SKris Kennaway 
81874664626SKris Kennaway int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
81974664626SKris Kennaway {
82074664626SKris Kennaway     return remove_session_lock(ctx, c, 1);
82174664626SKris Kennaway }
82274664626SKris Kennaway 
82374664626SKris Kennaway static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
82474664626SKris Kennaway {
82574664626SKris Kennaway     SSL_SESSION *r;
82674664626SKris Kennaway     int ret = 0;
82774664626SKris Kennaway 
8286f9291ceSJung-uk Kim     if ((c != NULL) && (c->session_id_length != 0)) {
8296f9291ceSJung-uk Kim         if (lck)
8306f9291ceSJung-uk Kim             CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
8316f9291ceSJung-uk Kim         if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) == c) {
83274664626SKris Kennaway             ret = 1;
8331f13597dSJung-uk Kim             r = lh_SSL_SESSION_delete(ctx->sessions, c);
83474664626SKris Kennaway             SSL_SESSION_list_remove(ctx, c);
83574664626SKris Kennaway         }
83674664626SKris Kennaway 
8376f9291ceSJung-uk Kim         if (lck)
8386f9291ceSJung-uk Kim             CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
83974664626SKris Kennaway 
8406f9291ceSJung-uk Kim         if (ret) {
84174664626SKris Kennaway             r->not_resumable = 1;
84274664626SKris Kennaway             if (ctx->remove_session_cb != NULL)
84374664626SKris Kennaway                 ctx->remove_session_cb(ctx, r);
84474664626SKris Kennaway             SSL_SESSION_free(r);
84574664626SKris Kennaway         }
8466f9291ceSJung-uk Kim     } else
84774664626SKris Kennaway         ret = 0;
84874664626SKris Kennaway     return (ret);
84974664626SKris Kennaway }
85074664626SKris Kennaway 
85174664626SKris Kennaway void SSL_SESSION_free(SSL_SESSION *ss)
85274664626SKris Kennaway {
85374664626SKris Kennaway     int i;
85474664626SKris Kennaway 
85574664626SKris Kennaway     if (ss == NULL)
85674664626SKris Kennaway         return;
85774664626SKris Kennaway 
85874664626SKris Kennaway     i = CRYPTO_add(&ss->references, -1, CRYPTO_LOCK_SSL_SESSION);
85974664626SKris Kennaway #ifdef REF_PRINT
86074664626SKris Kennaway     REF_PRINT("SSL_SESSION", ss);
86174664626SKris Kennaway #endif
8626f9291ceSJung-uk Kim     if (i > 0)
8636f9291ceSJung-uk Kim         return;
86474664626SKris Kennaway #ifdef REF_CHECK
8656f9291ceSJung-uk Kim     if (i < 0) {
86674664626SKris Kennaway         fprintf(stderr, "SSL_SESSION_free, bad reference count\n");
86774664626SKris Kennaway         abort();                /* ok */
86874664626SKris Kennaway     }
86974664626SKris Kennaway #endif
87074664626SKris Kennaway 
8715c87c606SMark Murray     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
87274664626SKris Kennaway 
873*dee36b4fSJung-uk Kim     OPENSSL_cleanse(ss->key_arg, sizeof(ss->key_arg));
874*dee36b4fSJung-uk Kim     OPENSSL_cleanse(ss->master_key, sizeof(ss->master_key));
875*dee36b4fSJung-uk Kim     OPENSSL_cleanse(ss->session_id, sizeof(ss->session_id));
8766f9291ceSJung-uk Kim     if (ss->sess_cert != NULL)
8776f9291ceSJung-uk Kim         ssl_sess_cert_free(ss->sess_cert);
8786f9291ceSJung-uk Kim     if (ss->peer != NULL)
8796f9291ceSJung-uk Kim         X509_free(ss->peer);
8806f9291ceSJung-uk Kim     if (ss->ciphers != NULL)
8816f9291ceSJung-uk Kim         sk_SSL_CIPHER_free(ss->ciphers);
882db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_TLSEXT
8836f9291ceSJung-uk Kim     if (ss->tlsext_hostname != NULL)
8846f9291ceSJung-uk Kim         OPENSSL_free(ss->tlsext_hostname);
8856f9291ceSJung-uk Kim     if (ss->tlsext_tick != NULL)
8866f9291ceSJung-uk Kim         OPENSSL_free(ss->tlsext_tick);
8871f13597dSJung-uk Kim # ifndef OPENSSL_NO_EC
8881f13597dSJung-uk Kim     ss->tlsext_ecpointformatlist_length = 0;
8896f9291ceSJung-uk Kim     if (ss->tlsext_ecpointformatlist != NULL)
8906f9291ceSJung-uk Kim         OPENSSL_free(ss->tlsext_ecpointformatlist);
8911f13597dSJung-uk Kim     ss->tlsext_ellipticcurvelist_length = 0;
8926f9291ceSJung-uk Kim     if (ss->tlsext_ellipticcurvelist != NULL)
8936f9291ceSJung-uk Kim         OPENSSL_free(ss->tlsext_ellipticcurvelist);
8941f13597dSJung-uk Kim # endif                         /* OPENSSL_NO_EC */
8951f13597dSJung-uk Kim #endif
8961f13597dSJung-uk Kim #ifndef OPENSSL_NO_PSK
8971f13597dSJung-uk Kim     if (ss->psk_identity_hint != NULL)
8981f13597dSJung-uk Kim         OPENSSL_free(ss->psk_identity_hint);
8991f13597dSJung-uk Kim     if (ss->psk_identity != NULL)
9001f13597dSJung-uk Kim         OPENSSL_free(ss->psk_identity);
9011f13597dSJung-uk Kim #endif
9021f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP
9031f13597dSJung-uk Kim     if (ss->srp_username != NULL)
9041f13597dSJung-uk Kim         OPENSSL_free(ss->srp_username);
905db522d3aSSimon L. B. Nielsen #endif
9065c87c606SMark Murray     OPENSSL_cleanse(ss, sizeof(*ss));
907ddd58736SKris Kennaway     OPENSSL_free(ss);
90874664626SKris Kennaway }
90974664626SKris Kennaway 
91074664626SKris Kennaway int SSL_set_session(SSL *s, SSL_SESSION *session)
91174664626SKris Kennaway {
91274664626SKris Kennaway     int ret = 0;
9131f13597dSJung-uk Kim     const SSL_METHOD *meth;
91474664626SKris Kennaway 
9156f9291ceSJung-uk Kim     if (session != NULL) {
91674664626SKris Kennaway         meth = s->ctx->method->get_ssl_method(session->ssl_version);
91774664626SKris Kennaway         if (meth == NULL)
91874664626SKris Kennaway             meth = s->method->get_ssl_method(session->ssl_version);
9196f9291ceSJung-uk Kim         if (meth == NULL) {
92074664626SKris Kennaway             SSLerr(SSL_F_SSL_SET_SESSION, SSL_R_UNABLE_TO_FIND_SSL_METHOD);
92174664626SKris Kennaway             return (0);
92274664626SKris Kennaway         }
92374664626SKris Kennaway 
9246f9291ceSJung-uk Kim         if (meth != s->method) {
92574664626SKris Kennaway             if (!SSL_set_ssl_method(s, meth))
92674664626SKris Kennaway                 return (0);
92774664626SKris Kennaway         }
9285c87c606SMark Murray #ifndef OPENSSL_NO_KRB5
9295c87c606SMark Murray         if (s->kssl_ctx && !s->kssl_ctx->client_princ &&
9306f9291ceSJung-uk Kim             session->krb5_client_princ_len > 0) {
9316f9291ceSJung-uk Kim             s->kssl_ctx->client_princ =
9326f9291ceSJung-uk Kim                 (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1);
933aeb5019cSJung-uk Kim             if (s->kssl_ctx->client_princ == NULL) {
934aeb5019cSJung-uk Kim                 SSLerr(SSL_F_SSL_SET_SESSION, ERR_R_MALLOC_FAILURE);
935aeb5019cSJung-uk Kim                 return 0;
936aeb5019cSJung-uk Kim             }
9375c87c606SMark Murray             memcpy(s->kssl_ctx->client_princ, session->krb5_client_princ,
9385c87c606SMark Murray                    session->krb5_client_princ_len);
9395c87c606SMark Murray             s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0';
9405c87c606SMark Murray         }
9415c87c606SMark Murray #endif                          /* OPENSSL_NO_KRB5 */
9425c87c606SMark Murray 
94374664626SKris Kennaway         /* CRYPTO_w_lock(CRYPTO_LOCK_SSL); */
94474664626SKris Kennaway         CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
94574664626SKris Kennaway         if (s->session != NULL)
94674664626SKris Kennaway             SSL_SESSION_free(s->session);
94774664626SKris Kennaway         s->session = session;
948de7cdddaSKris Kennaway         s->verify_result = s->session->verify_result;
94974664626SKris Kennaway         /* CRYPTO_w_unlock(CRYPTO_LOCK_SSL); */
95074664626SKris Kennaway         ret = 1;
9516f9291ceSJung-uk Kim     } else {
9526f9291ceSJung-uk Kim         if (s->session != NULL) {
95374664626SKris Kennaway             SSL_SESSION_free(s->session);
95474664626SKris Kennaway             s->session = NULL;
95574664626SKris Kennaway         }
95674664626SKris Kennaway 
95774664626SKris Kennaway         meth = s->ctx->method;
9586f9291ceSJung-uk Kim         if (meth != s->method) {
95974664626SKris Kennaway             if (!SSL_set_ssl_method(s, meth))
96074664626SKris Kennaway                 return (0);
96174664626SKris Kennaway         }
96274664626SKris Kennaway         ret = 1;
96374664626SKris Kennaway     }
96474664626SKris Kennaway     return (ret);
96574664626SKris Kennaway }
96674664626SKris Kennaway 
96774664626SKris Kennaway long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
96874664626SKris Kennaway {
9696f9291ceSJung-uk Kim     if (s == NULL)
9706f9291ceSJung-uk Kim         return (0);
97174664626SKris Kennaway     s->timeout = t;
97274664626SKris Kennaway     return (1);
97374664626SKris Kennaway }
97474664626SKris Kennaway 
9753b4e3dcbSSimon L. B. Nielsen long SSL_SESSION_get_timeout(const SSL_SESSION *s)
97674664626SKris Kennaway {
9776f9291ceSJung-uk Kim     if (s == NULL)
9786f9291ceSJung-uk Kim         return (0);
97974664626SKris Kennaway     return (s->timeout);
98074664626SKris Kennaway }
98174664626SKris Kennaway 
9823b4e3dcbSSimon L. B. Nielsen long SSL_SESSION_get_time(const SSL_SESSION *s)
98374664626SKris Kennaway {
9846f9291ceSJung-uk Kim     if (s == NULL)
9856f9291ceSJung-uk Kim         return (0);
98674664626SKris Kennaway     return (s->time);
98774664626SKris Kennaway }
98874664626SKris Kennaway 
98974664626SKris Kennaway long SSL_SESSION_set_time(SSL_SESSION *s, long t)
99074664626SKris Kennaway {
9916f9291ceSJung-uk Kim     if (s == NULL)
9926f9291ceSJung-uk Kim         return (0);
99374664626SKris Kennaway     s->time = t;
99474664626SKris Kennaway     return (t);
99574664626SKris Kennaway }
99674664626SKris Kennaway 
9971f13597dSJung-uk Kim X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
9981f13597dSJung-uk Kim {
9991f13597dSJung-uk Kim     return s->peer;
10001f13597dSJung-uk Kim }
10011f13597dSJung-uk Kim 
10021f13597dSJung-uk Kim int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx,
10031f13597dSJung-uk Kim                                 unsigned int sid_ctx_len)
10041f13597dSJung-uk Kim {
10056f9291ceSJung-uk Kim     if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
10066f9291ceSJung-uk Kim         SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT,
10076f9291ceSJung-uk Kim                SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
10081f13597dSJung-uk Kim         return 0;
10091f13597dSJung-uk Kim     }
10101f13597dSJung-uk Kim     s->sid_ctx_length = sid_ctx_len;
1011ed7112f0SJung-uk Kim     if (s->sid_ctx != sid_ctx)
10121f13597dSJung-uk Kim         memcpy(s->sid_ctx, sid_ctx, sid_ctx_len);
10131f13597dSJung-uk Kim 
10141f13597dSJung-uk Kim     return 1;
10151f13597dSJung-uk Kim }
10161f13597dSJung-uk Kim 
101774664626SKris Kennaway long SSL_CTX_set_timeout(SSL_CTX *s, long t)
101874664626SKris Kennaway {
101974664626SKris Kennaway     long l;
10206f9291ceSJung-uk Kim     if (s == NULL)
10216f9291ceSJung-uk Kim         return (0);
102274664626SKris Kennaway     l = s->session_timeout;
102374664626SKris Kennaway     s->session_timeout = t;
102474664626SKris Kennaway     return (l);
102574664626SKris Kennaway }
102674664626SKris Kennaway 
10273b4e3dcbSSimon L. B. Nielsen long SSL_CTX_get_timeout(const SSL_CTX *s)
102874664626SKris Kennaway {
10296f9291ceSJung-uk Kim     if (s == NULL)
10306f9291ceSJung-uk Kim         return (0);
103174664626SKris Kennaway     return (s->session_timeout);
103274664626SKris Kennaway }
103374664626SKris Kennaway 
10341f13597dSJung-uk Kim #ifndef OPENSSL_NO_TLSEXT
10356f9291ceSJung-uk Kim int SSL_set_session_secret_cb(SSL *s,
10366f9291ceSJung-uk Kim                               int (*tls_session_secret_cb) (SSL *s,
10376f9291ceSJung-uk Kim                                                             void *secret,
10386f9291ceSJung-uk Kim                                                             int *secret_len,
10396f9291ceSJung-uk Kim                                                             STACK_OF(SSL_CIPHER)
10406f9291ceSJung-uk Kim                                                             *peer_ciphers,
10416f9291ceSJung-uk Kim                                                             SSL_CIPHER
10426f9291ceSJung-uk Kim                                                             **cipher,
10436f9291ceSJung-uk Kim                                                             void *arg),
10446f9291ceSJung-uk Kim                               void *arg)
10451f13597dSJung-uk Kim {
10466f9291ceSJung-uk Kim     if (s == NULL)
10476f9291ceSJung-uk Kim         return (0);
10481f13597dSJung-uk Kim     s->tls_session_secret_cb = tls_session_secret_cb;
10491f13597dSJung-uk Kim     s->tls_session_secret_cb_arg = arg;
10501f13597dSJung-uk Kim     return (1);
10511f13597dSJung-uk Kim }
10521f13597dSJung-uk Kim 
10531f13597dSJung-uk Kim int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
10541f13597dSJung-uk Kim                                   void *arg)
10551f13597dSJung-uk Kim {
10566f9291ceSJung-uk Kim     if (s == NULL)
10576f9291ceSJung-uk Kim         return (0);
10581f13597dSJung-uk Kim     s->tls_session_ticket_ext_cb = cb;
10591f13597dSJung-uk Kim     s->tls_session_ticket_ext_cb_arg = arg;
10601f13597dSJung-uk Kim     return (1);
10611f13597dSJung-uk Kim }
10621f13597dSJung-uk Kim 
10631f13597dSJung-uk Kim int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
10641f13597dSJung-uk Kim {
10656f9291ceSJung-uk Kim     if (s->version >= TLS1_VERSION) {
10666f9291ceSJung-uk Kim         if (s->tlsext_session_ticket) {
10671f13597dSJung-uk Kim             OPENSSL_free(s->tlsext_session_ticket);
10681f13597dSJung-uk Kim             s->tlsext_session_ticket = NULL;
10691f13597dSJung-uk Kim         }
10701f13597dSJung-uk Kim 
10716f9291ceSJung-uk Kim         s->tlsext_session_ticket =
10726f9291ceSJung-uk Kim             OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
10736f9291ceSJung-uk Kim         if (!s->tlsext_session_ticket) {
10741f13597dSJung-uk Kim             SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
10751f13597dSJung-uk Kim             return 0;
10761f13597dSJung-uk Kim         }
10771f13597dSJung-uk Kim 
10786f9291ceSJung-uk Kim         if (ext_data) {
10791f13597dSJung-uk Kim             s->tlsext_session_ticket->length = ext_len;
10801f13597dSJung-uk Kim             s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
10811f13597dSJung-uk Kim             memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
10826f9291ceSJung-uk Kim         } else {
10831f13597dSJung-uk Kim             s->tlsext_session_ticket->length = 0;
10841f13597dSJung-uk Kim             s->tlsext_session_ticket->data = NULL;
10851f13597dSJung-uk Kim         }
10861f13597dSJung-uk Kim 
10871f13597dSJung-uk Kim         return 1;
10881f13597dSJung-uk Kim     }
10891f13597dSJung-uk Kim 
10901f13597dSJung-uk Kim     return 0;
10911f13597dSJung-uk Kim }
10921f13597dSJung-uk Kim #endif                          /* OPENSSL_NO_TLSEXT */
10931f13597dSJung-uk Kim 
10946f9291ceSJung-uk Kim typedef struct timeout_param_st {
109574664626SKris Kennaway     SSL_CTX *ctx;
109674664626SKris Kennaway     long time;
10971f13597dSJung-uk Kim     LHASH_OF(SSL_SESSION) *cache;
109874664626SKris Kennaway } TIMEOUT_PARAM;
109974664626SKris Kennaway 
11001f13597dSJung-uk Kim static void timeout_doall_arg(SSL_SESSION *s, TIMEOUT_PARAM *p)
110174664626SKris Kennaway {
11026f9291ceSJung-uk Kim     if ((p->time == 0) || (p->time > (s->time + s->timeout))) { /* timeout */
11036f9291ceSJung-uk Kim         /*
11046f9291ceSJung-uk Kim          * The reason we don't call SSL_CTX_remove_session() is to save on
11056f9291ceSJung-uk Kim          * locking overhead
11066f9291ceSJung-uk Kim          */
11071f13597dSJung-uk Kim         (void)lh_SSL_SESSION_delete(p->cache, s);
110874664626SKris Kennaway         SSL_SESSION_list_remove(p->ctx, s);
110974664626SKris Kennaway         s->not_resumable = 1;
111074664626SKris Kennaway         if (p->ctx->remove_session_cb != NULL)
111174664626SKris Kennaway             p->ctx->remove_session_cb(p->ctx, s);
111274664626SKris Kennaway         SSL_SESSION_free(s);
111374664626SKris Kennaway     }
111474664626SKris Kennaway }
111574664626SKris Kennaway 
11161f13597dSJung-uk Kim static IMPLEMENT_LHASH_DOALL_ARG_FN(timeout, SSL_SESSION, TIMEOUT_PARAM)
11175c87c606SMark Murray 
111874664626SKris Kennaway void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
111974664626SKris Kennaway {
112074664626SKris Kennaway     unsigned long i;
112174664626SKris Kennaway     TIMEOUT_PARAM tp;
112274664626SKris Kennaway 
112374664626SKris Kennaway     tp.ctx = s;
112474664626SKris Kennaway     tp.cache = s->sessions;
11256f9291ceSJung-uk Kim     if (tp.cache == NULL)
11266f9291ceSJung-uk Kim         return;
112774664626SKris Kennaway     tp.time = t;
112874664626SKris Kennaway     CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
11291f13597dSJung-uk Kim     i = CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load;
11301f13597dSJung-uk Kim     CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load = 0;
11311f13597dSJung-uk Kim     lh_SSL_SESSION_doall_arg(tp.cache, LHASH_DOALL_ARG_FN(timeout),
11321f13597dSJung-uk Kim                              TIMEOUT_PARAM, &tp);
11331f13597dSJung-uk Kim     CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load = i;
113474664626SKris Kennaway     CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
113574664626SKris Kennaway }
113674664626SKris Kennaway 
113774664626SKris Kennaway int ssl_clear_bad_session(SSL *s)
113874664626SKris Kennaway {
113974664626SKris Kennaway     if ((s->session != NULL) &&
114074664626SKris Kennaway         !(s->shutdown & SSL_SENT_SHUTDOWN) &&
11416f9291ceSJung-uk Kim         !(SSL_in_init(s) || SSL_in_before(s))) {
1142aeb5019cSJung-uk Kim         SSL_CTX_remove_session(s->session_ctx, s->session);
114374664626SKris Kennaway         return (1);
11446f9291ceSJung-uk Kim     } else
114574664626SKris Kennaway         return (0);
114674664626SKris Kennaway }
114774664626SKris Kennaway 
114874664626SKris Kennaway /* locked by SSL_CTX in the calling function */
114974664626SKris Kennaway static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
115074664626SKris Kennaway {
11516f9291ceSJung-uk Kim     if ((s->next == NULL) || (s->prev == NULL))
11526f9291ceSJung-uk Kim         return;
115374664626SKris Kennaway 
11546f9291ceSJung-uk Kim     if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) {
11556f9291ceSJung-uk Kim         /* last element in list */
11566f9291ceSJung-uk Kim         if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) {
11576f9291ceSJung-uk Kim             /* only one element in list */
115874664626SKris Kennaway             ctx->session_cache_head = NULL;
115974664626SKris Kennaway             ctx->session_cache_tail = NULL;
11606f9291ceSJung-uk Kim         } else {
116174664626SKris Kennaway             ctx->session_cache_tail = s->prev;
116274664626SKris Kennaway             s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
116374664626SKris Kennaway         }
11646f9291ceSJung-uk Kim     } else {
11656f9291ceSJung-uk Kim         if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) {
11666f9291ceSJung-uk Kim             /* first element in list */
116774664626SKris Kennaway             ctx->session_cache_head = s->next;
116874664626SKris Kennaway             s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
11696f9291ceSJung-uk Kim         } else {
11706f9291ceSJung-uk Kim             /* middle of list */
117174664626SKris Kennaway             s->next->prev = s->prev;
117274664626SKris Kennaway             s->prev->next = s->next;
117374664626SKris Kennaway         }
117474664626SKris Kennaway     }
117574664626SKris Kennaway     s->prev = s->next = NULL;
117674664626SKris Kennaway }
117774664626SKris Kennaway 
117874664626SKris Kennaway static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
117974664626SKris Kennaway {
118074664626SKris Kennaway     if ((s->next != NULL) && (s->prev != NULL))
118174664626SKris Kennaway         SSL_SESSION_list_remove(ctx, s);
118274664626SKris Kennaway 
11836f9291ceSJung-uk Kim     if (ctx->session_cache_head == NULL) {
118474664626SKris Kennaway         ctx->session_cache_head = s;
118574664626SKris Kennaway         ctx->session_cache_tail = s;
118674664626SKris Kennaway         s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
118774664626SKris Kennaway         s->next = (SSL_SESSION *)&(ctx->session_cache_tail);
11886f9291ceSJung-uk Kim     } else {
118974664626SKris Kennaway         s->next = ctx->session_cache_head;
119074664626SKris Kennaway         s->next->prev = s;
119174664626SKris Kennaway         s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
119274664626SKris Kennaway         ctx->session_cache_head = s;
119374664626SKris Kennaway     }
119474664626SKris Kennaway }
119574664626SKris Kennaway 
11965471f83eSSimon L. B. Nielsen void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
11976f9291ceSJung-uk Kim                              int (*cb) (struct ssl_st *ssl,
11986f9291ceSJung-uk Kim                                         SSL_SESSION *sess))
11995471f83eSSimon L. B. Nielsen {
12005471f83eSSimon L. B. Nielsen     ctx->new_session_cb = cb;
12015471f83eSSimon L. B. Nielsen }
12025471f83eSSimon L. B. Nielsen 
12036f9291ceSJung-uk Kim int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (SSL *ssl, SSL_SESSION *sess) {
12045471f83eSSimon L. B. Nielsen     return ctx->new_session_cb;
12055471f83eSSimon L. B. Nielsen }
12065471f83eSSimon L. B. Nielsen 
12075471f83eSSimon L. B. Nielsen void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
12085471f83eSSimon L. B. Nielsen                                 void (*cb) (SSL_CTX *ctx, SSL_SESSION *sess))
12095471f83eSSimon L. B. Nielsen {
12105471f83eSSimon L. B. Nielsen     ctx->remove_session_cb = cb;
12115471f83eSSimon L. B. Nielsen }
12125471f83eSSimon L. B. Nielsen 
12136f9291ceSJung-uk Kim void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (SSL_CTX *ctx,
12146f9291ceSJung-uk Kim                                                   SSL_SESSION *sess) {
12155471f83eSSimon L. B. Nielsen     return ctx->remove_session_cb;
12165471f83eSSimon L. B. Nielsen }
12175471f83eSSimon L. B. Nielsen 
12185471f83eSSimon L. B. Nielsen void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
12195471f83eSSimon L. B. Nielsen                              SSL_SESSION *(*cb) (struct ssl_st *ssl,
12206f9291ceSJung-uk Kim                                                  unsigned char *data, int len,
12216f9291ceSJung-uk Kim                                                  int *copy))
12225471f83eSSimon L. B. Nielsen {
12235471f83eSSimon L. B. Nielsen     ctx->get_session_cb = cb;
12245471f83eSSimon L. B. Nielsen }
12255471f83eSSimon L. B. Nielsen 
12265471f83eSSimon L. B. Nielsen SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (SSL *ssl,
12276f9291ceSJung-uk Kim                                                        unsigned char *data,
12286f9291ceSJung-uk Kim                                                        int len, int *copy) {
12295471f83eSSimon L. B. Nielsen     return ctx->get_session_cb;
12305471f83eSSimon L. B. Nielsen }
12315471f83eSSimon L. B. Nielsen 
12325471f83eSSimon L. B. Nielsen void SSL_CTX_set_info_callback(SSL_CTX *ctx,
12335471f83eSSimon L. B. Nielsen                                void (*cb) (const SSL *ssl, int type, int val))
12345471f83eSSimon L. B. Nielsen {
12355471f83eSSimon L. B. Nielsen     ctx->info_callback = cb;
12365471f83eSSimon L. B. Nielsen }
12375471f83eSSimon L. B. Nielsen 
12386f9291ceSJung-uk Kim void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type,
12396f9291ceSJung-uk Kim                                                  int val) {
12405471f83eSSimon L. B. Nielsen     return ctx->info_callback;
12415471f83eSSimon L. B. Nielsen }
12425471f83eSSimon L. B. Nielsen 
12435471f83eSSimon L. B. Nielsen void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
12446f9291ceSJung-uk Kim                                 int (*cb) (SSL *ssl, X509 **x509,
12456f9291ceSJung-uk Kim                                            EVP_PKEY **pkey))
12465471f83eSSimon L. B. Nielsen {
12475471f83eSSimon L. B. Nielsen     ctx->client_cert_cb = cb;
12485471f83eSSimon L. B. Nielsen }
12495471f83eSSimon L. B. Nielsen 
12506f9291ceSJung-uk Kim int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509,
12516f9291ceSJung-uk Kim                                                  EVP_PKEY **pkey) {
12525471f83eSSimon L. B. Nielsen     return ctx->client_cert_cb;
12535471f83eSSimon L. B. Nielsen }
12545471f83eSSimon L. B. Nielsen 
1255db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_ENGINE
1256db522d3aSSimon L. B. Nielsen int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
1257db522d3aSSimon L. B. Nielsen {
12586f9291ceSJung-uk Kim     if (!ENGINE_init(e)) {
1259db522d3aSSimon L. B. Nielsen         SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB);
1260db522d3aSSimon L. B. Nielsen         return 0;
1261db522d3aSSimon L. B. Nielsen     }
12626f9291ceSJung-uk Kim     if (!ENGINE_get_ssl_client_cert_function(e)) {
12636f9291ceSJung-uk Kim         SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE,
12646f9291ceSJung-uk Kim                SSL_R_NO_CLIENT_CERT_METHOD);
1265db522d3aSSimon L. B. Nielsen         ENGINE_finish(e);
1266db522d3aSSimon L. B. Nielsen         return 0;
1267db522d3aSSimon L. B. Nielsen     }
1268db522d3aSSimon L. B. Nielsen     ctx->client_cert_engine = e;
1269db522d3aSSimon L. B. Nielsen     return 1;
1270db522d3aSSimon L. B. Nielsen }
1271db522d3aSSimon L. B. Nielsen #endif
1272db522d3aSSimon L. B. Nielsen 
12735471f83eSSimon L. B. Nielsen void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
12746f9291ceSJung-uk Kim                                     int (*cb) (SSL *ssl,
12756f9291ceSJung-uk Kim                                                unsigned char *cookie,
12766f9291ceSJung-uk Kim                                                unsigned int *cookie_len))
12775471f83eSSimon L. B. Nielsen {
12785471f83eSSimon L. B. Nielsen     ctx->app_gen_cookie_cb = cb;
12795471f83eSSimon L. B. Nielsen }
12805471f83eSSimon L. B. Nielsen 
12815471f83eSSimon L. B. Nielsen void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
12826f9291ceSJung-uk Kim                                   int (*cb) (SSL *ssl, unsigned char *cookie,
12836f9291ceSJung-uk Kim                                              unsigned int cookie_len))
12845471f83eSSimon L. B. Nielsen {
12855471f83eSSimon L. B. Nielsen     ctx->app_verify_cookie_cb = cb;
12865471f83eSSimon L. B. Nielsen }
12875471f83eSSimon L. B. Nielsen 
12886f9291ceSJung-uk Kim IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION,
12896f9291ceSJung-uk Kim                  SSL_SESSION)
1290