1*e71b7053SJung-uk Kim /* 2*e71b7053SJung-uk Kim * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. 31f13597dSJung-uk Kim * Copyright 2005 Nokia. All rights reserved. 41f13597dSJung-uk Kim * 5*e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 6*e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 7*e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 8*e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 91f13597dSJung-uk Kim */ 1074664626SKris Kennaway 1174664626SKris Kennaway #include <stdio.h> 1274664626SKris Kennaway #include <openssl/rand.h> 13db522d3aSSimon L. B. Nielsen #include <openssl/engine.h> 14*e71b7053SJung-uk Kim #include "internal/refcount.h" 15*e71b7053SJung-uk Kim #include "internal/cryptlib.h" 1674664626SKris Kennaway #include "ssl_locl.h" 17*e71b7053SJung-uk Kim #include "statem/statem_locl.h" 1874664626SKris Kennaway 1974664626SKris Kennaway static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); 2074664626SKris Kennaway static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s); 2174664626SKris Kennaway static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); 2274664626SKris Kennaway 23*e71b7053SJung-uk Kim /* 24*e71b7053SJung-uk Kim * SSL_get_session() and SSL_get1_session() are problematic in TLS1.3 because, 25*e71b7053SJung-uk Kim * unlike in earlier protocol versions, the session ticket may not have been 26*e71b7053SJung-uk Kim * sent yet even though a handshake has finished. The session ticket data could 27*e71b7053SJung-uk Kim * come in sometime later...or even change if multiple session ticket messages 28*e71b7053SJung-uk Kim * are sent from the server. The preferred way for applications to obtain 29*e71b7053SJung-uk Kim * a resumable session is to use SSL_CTX_sess_set_new_cb(). 30*e71b7053SJung-uk Kim */ 31*e71b7053SJung-uk Kim 323b4e3dcbSSimon L. B. Nielsen SSL_SESSION *SSL_get_session(const SSL *ssl) 33f579bf8eSKris Kennaway /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ 3474664626SKris Kennaway { 35*e71b7053SJung-uk Kim return ssl->session; 3674664626SKris Kennaway } 3774664626SKris Kennaway 38f579bf8eSKris Kennaway SSL_SESSION *SSL_get1_session(SSL *ssl) 39f579bf8eSKris Kennaway /* variant of SSL_get_session: caller really gets something */ 40f579bf8eSKris Kennaway { 41f579bf8eSKris Kennaway SSL_SESSION *sess; 426f9291ceSJung-uk Kim /* 436f9291ceSJung-uk Kim * Need to lock this all up rather than just use CRYPTO_add so that 446f9291ceSJung-uk Kim * somebody doesn't free ssl->session between when we check it's non-null 456f9291ceSJung-uk Kim * and when we up the reference count. 466f9291ceSJung-uk Kim */ 47*e71b7053SJung-uk Kim CRYPTO_THREAD_read_lock(ssl->lock); 48f579bf8eSKris Kennaway sess = ssl->session; 49f579bf8eSKris Kennaway if (sess) 50*e71b7053SJung-uk Kim SSL_SESSION_up_ref(sess); 51*e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(ssl->lock); 52*e71b7053SJung-uk Kim return sess; 5374664626SKris Kennaway } 5474664626SKris Kennaway 5574664626SKris Kennaway int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) 5674664626SKris Kennaway { 57*e71b7053SJung-uk Kim return CRYPTO_set_ex_data(&s->ex_data, idx, arg); 5874664626SKris Kennaway } 5974664626SKris Kennaway 603b4e3dcbSSimon L. B. Nielsen void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) 6174664626SKris Kennaway { 62*e71b7053SJung-uk Kim return CRYPTO_get_ex_data(&s->ex_data, idx); 6374664626SKris Kennaway } 6474664626SKris Kennaway 6574664626SKris Kennaway SSL_SESSION *SSL_SESSION_new(void) 6674664626SKris Kennaway { 6774664626SKris Kennaway SSL_SESSION *ss; 6874664626SKris Kennaway 69*e71b7053SJung-uk Kim if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL)) 70*e71b7053SJung-uk Kim return NULL; 71*e71b7053SJung-uk Kim 72*e71b7053SJung-uk Kim ss = OPENSSL_zalloc(sizeof(*ss)); 736f9291ceSJung-uk Kim if (ss == NULL) { 7474664626SKris Kennaway SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); 75*e71b7053SJung-uk Kim return NULL; 7674664626SKris Kennaway } 7774664626SKris Kennaway 78f579bf8eSKris Kennaway ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ 7974664626SKris Kennaway ss->references = 1; 8074664626SKris Kennaway ss->timeout = 60 * 5 + 4; /* 5 minute timeout by default */ 813b4e3dcbSSimon L. B. Nielsen ss->time = (unsigned long)time(NULL); 82*e71b7053SJung-uk Kim ss->lock = CRYPTO_THREAD_lock_new(); 83*e71b7053SJung-uk Kim if (ss->lock == NULL) { 84*e71b7053SJung-uk Kim SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); 85*e71b7053SJung-uk Kim OPENSSL_free(ss); 86*e71b7053SJung-uk Kim return NULL; 87*e71b7053SJung-uk Kim } 88*e71b7053SJung-uk Kim 89*e71b7053SJung-uk Kim if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data)) { 90*e71b7053SJung-uk Kim CRYPTO_THREAD_lock_free(ss->lock); 91*e71b7053SJung-uk Kim OPENSSL_free(ss); 92*e71b7053SJung-uk Kim return NULL; 93*e71b7053SJung-uk Kim } 94*e71b7053SJung-uk Kim return ss; 95*e71b7053SJung-uk Kim } 96*e71b7053SJung-uk Kim 97*e71b7053SJung-uk Kim SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *src) 98*e71b7053SJung-uk Kim { 99*e71b7053SJung-uk Kim return ssl_session_dup(src, 1); 10074664626SKris Kennaway } 10174664626SKris Kennaway 102ed6b93beSJung-uk Kim /* 103ed6b93beSJung-uk Kim * Create a new SSL_SESSION and duplicate the contents of |src| into it. If 104ed6b93beSJung-uk Kim * ticket == 0 then no ticket information is duplicated, otherwise it is. 105ed6b93beSJung-uk Kim */ 106ed6b93beSJung-uk Kim SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) 107ed6b93beSJung-uk Kim { 108ed6b93beSJung-uk Kim SSL_SESSION *dest; 109ed6b93beSJung-uk Kim 110ed6b93beSJung-uk Kim dest = OPENSSL_malloc(sizeof(*src)); 111ed6b93beSJung-uk Kim if (dest == NULL) { 112ed6b93beSJung-uk Kim goto err; 113ed6b93beSJung-uk Kim } 114ed6b93beSJung-uk Kim memcpy(dest, src, sizeof(*dest)); 115ed6b93beSJung-uk Kim 116ed6b93beSJung-uk Kim /* 117ed6b93beSJung-uk Kim * Set the various pointers to NULL so that we can call SSL_SESSION_free in 118ed6b93beSJung-uk Kim * the case of an error whilst halfway through constructing dest 119ed6b93beSJung-uk Kim */ 120ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_PSK 121ed6b93beSJung-uk Kim dest->psk_identity_hint = NULL; 122ed6b93beSJung-uk Kim dest->psk_identity = NULL; 123ed6b93beSJung-uk Kim #endif 124ed6b93beSJung-uk Kim dest->ciphers = NULL; 125*e71b7053SJung-uk Kim dest->ext.hostname = NULL; 126ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_EC 127*e71b7053SJung-uk Kim dest->ext.ecpointformats = NULL; 128*e71b7053SJung-uk Kim dest->ext.supportedgroups = NULL; 129ed6b93beSJung-uk Kim #endif 130*e71b7053SJung-uk Kim dest->ext.tick = NULL; 131*e71b7053SJung-uk Kim dest->ext.alpn_selected = NULL; 132ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_SRP 133ed6b93beSJung-uk Kim dest->srp_username = NULL; 134ed6b93beSJung-uk Kim #endif 135*e71b7053SJung-uk Kim dest->peer_chain = NULL; 136*e71b7053SJung-uk Kim dest->peer = NULL; 137*e71b7053SJung-uk Kim dest->ticket_appdata = NULL; 138*e71b7053SJung-uk Kim memset(&dest->ex_data, 0, sizeof(dest->ex_data)); 139ed6b93beSJung-uk Kim 140ed6b93beSJung-uk Kim /* We deliberately don't copy the prev and next pointers */ 141ed6b93beSJung-uk Kim dest->prev = NULL; 142ed6b93beSJung-uk Kim dest->next = NULL; 143ed6b93beSJung-uk Kim 144ed6b93beSJung-uk Kim dest->references = 1; 145ed6b93beSJung-uk Kim 146*e71b7053SJung-uk Kim dest->lock = CRYPTO_THREAD_lock_new(); 147*e71b7053SJung-uk Kim if (dest->lock == NULL) 148*e71b7053SJung-uk Kim goto err; 149ed6b93beSJung-uk Kim 15047902a71SJung-uk Kim if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data)) 15147902a71SJung-uk Kim goto err; 15247902a71SJung-uk Kim 153*e71b7053SJung-uk Kim if (src->peer != NULL) { 154*e71b7053SJung-uk Kim if (!X509_up_ref(src->peer)) 155*e71b7053SJung-uk Kim goto err; 156*e71b7053SJung-uk Kim dest->peer = src->peer; 157*e71b7053SJung-uk Kim } 158*e71b7053SJung-uk Kim 159*e71b7053SJung-uk Kim if (src->peer_chain != NULL) { 160*e71b7053SJung-uk Kim dest->peer_chain = X509_chain_up_ref(src->peer_chain); 161*e71b7053SJung-uk Kim if (dest->peer_chain == NULL) 162*e71b7053SJung-uk Kim goto err; 163*e71b7053SJung-uk Kim } 164ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_PSK 165ed6b93beSJung-uk Kim if (src->psk_identity_hint) { 166*e71b7053SJung-uk Kim dest->psk_identity_hint = OPENSSL_strdup(src->psk_identity_hint); 167ed6b93beSJung-uk Kim if (dest->psk_identity_hint == NULL) { 168ed6b93beSJung-uk Kim goto err; 169ed6b93beSJung-uk Kim } 170ed6b93beSJung-uk Kim } 171ed6b93beSJung-uk Kim if (src->psk_identity) { 172*e71b7053SJung-uk Kim dest->psk_identity = OPENSSL_strdup(src->psk_identity); 173ed6b93beSJung-uk Kim if (dest->psk_identity == NULL) { 174ed6b93beSJung-uk Kim goto err; 175ed6b93beSJung-uk Kim } 176ed6b93beSJung-uk Kim } 177ed6b93beSJung-uk Kim #endif 178ed6b93beSJung-uk Kim 179ed6b93beSJung-uk Kim if (src->ciphers != NULL) { 180ed6b93beSJung-uk Kim dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers); 181ed6b93beSJung-uk Kim if (dest->ciphers == NULL) 182ed6b93beSJung-uk Kim goto err; 183ed6b93beSJung-uk Kim } 184ed6b93beSJung-uk Kim 185ed6b93beSJung-uk Kim if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, 186ed6b93beSJung-uk Kim &dest->ex_data, &src->ex_data)) { 187ed6b93beSJung-uk Kim goto err; 188ed6b93beSJung-uk Kim } 189ed6b93beSJung-uk Kim 190*e71b7053SJung-uk Kim if (src->ext.hostname) { 191*e71b7053SJung-uk Kim dest->ext.hostname = OPENSSL_strdup(src->ext.hostname); 192*e71b7053SJung-uk Kim if (dest->ext.hostname == NULL) { 193ed6b93beSJung-uk Kim goto err; 194ed6b93beSJung-uk Kim } 195ed6b93beSJung-uk Kim } 196ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_EC 197*e71b7053SJung-uk Kim if (src->ext.ecpointformats) { 198*e71b7053SJung-uk Kim dest->ext.ecpointformats = 199*e71b7053SJung-uk Kim OPENSSL_memdup(src->ext.ecpointformats, 200*e71b7053SJung-uk Kim src->ext.ecpointformats_len); 201*e71b7053SJung-uk Kim if (dest->ext.ecpointformats == NULL) 202ed6b93beSJung-uk Kim goto err; 203ed6b93beSJung-uk Kim } 204*e71b7053SJung-uk Kim if (src->ext.supportedgroups) { 205*e71b7053SJung-uk Kim dest->ext.supportedgroups = 206*e71b7053SJung-uk Kim OPENSSL_memdup(src->ext.supportedgroups, 207*e71b7053SJung-uk Kim src->ext.supportedgroups_len 208*e71b7053SJung-uk Kim * sizeof(*src->ext.supportedgroups)); 209*e71b7053SJung-uk Kim if (dest->ext.supportedgroups == NULL) 210ed6b93beSJung-uk Kim goto err; 211ed6b93beSJung-uk Kim } 212ed6b93beSJung-uk Kim #endif 213ed6b93beSJung-uk Kim 214*e71b7053SJung-uk Kim if (ticket != 0 && src->ext.tick != NULL) { 215*e71b7053SJung-uk Kim dest->ext.tick = 216*e71b7053SJung-uk Kim OPENSSL_memdup(src->ext.tick, src->ext.ticklen); 217*e71b7053SJung-uk Kim if (dest->ext.tick == NULL) 218ed6b93beSJung-uk Kim goto err; 219ed6b93beSJung-uk Kim } else { 220*e71b7053SJung-uk Kim dest->ext.tick_lifetime_hint = 0; 221*e71b7053SJung-uk Kim dest->ext.ticklen = 0; 222ed6b93beSJung-uk Kim } 223*e71b7053SJung-uk Kim 224*e71b7053SJung-uk Kim if (src->ext.alpn_selected != NULL) { 225*e71b7053SJung-uk Kim dest->ext.alpn_selected = OPENSSL_memdup(src->ext.alpn_selected, 226*e71b7053SJung-uk Kim src->ext.alpn_selected_len); 227*e71b7053SJung-uk Kim if (dest->ext.alpn_selected == NULL) 228*e71b7053SJung-uk Kim goto err; 229*e71b7053SJung-uk Kim } 230ed6b93beSJung-uk Kim 231ed6b93beSJung-uk Kim #ifndef OPENSSL_NO_SRP 232ed6b93beSJung-uk Kim if (src->srp_username) { 233*e71b7053SJung-uk Kim dest->srp_username = OPENSSL_strdup(src->srp_username); 234ed6b93beSJung-uk Kim if (dest->srp_username == NULL) { 235ed6b93beSJung-uk Kim goto err; 236ed6b93beSJung-uk Kim } 237ed6b93beSJung-uk Kim } 238ed6b93beSJung-uk Kim #endif 239ed6b93beSJung-uk Kim 240*e71b7053SJung-uk Kim if (src->ticket_appdata != NULL) { 241*e71b7053SJung-uk Kim dest->ticket_appdata = 242*e71b7053SJung-uk Kim OPENSSL_memdup(src->ticket_appdata, src->ticket_appdata_len); 243*e71b7053SJung-uk Kim if (dest->ticket_appdata == NULL) 244*e71b7053SJung-uk Kim goto err; 245*e71b7053SJung-uk Kim } 246*e71b7053SJung-uk Kim 247ed6b93beSJung-uk Kim return dest; 248ed6b93beSJung-uk Kim err: 249ed6b93beSJung-uk Kim SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE); 250ed6b93beSJung-uk Kim SSL_SESSION_free(dest); 251ed6b93beSJung-uk Kim return NULL; 252ed6b93beSJung-uk Kim } 253ed6b93beSJung-uk Kim 254*e71b7053SJung-uk Kim const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) 2553b4e3dcbSSimon L. B. Nielsen { 2563b4e3dcbSSimon L. B. Nielsen if (len) 257*e71b7053SJung-uk Kim *len = (unsigned int)s->session_id_length; 2583b4e3dcbSSimon L. B. Nielsen return s->session_id; 2593b4e3dcbSSimon L. B. Nielsen } 260*e71b7053SJung-uk Kim const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s, 261*e71b7053SJung-uk Kim unsigned int *len) 262*e71b7053SJung-uk Kim { 263*e71b7053SJung-uk Kim if (len != NULL) 264*e71b7053SJung-uk Kim *len = (unsigned int)s->sid_ctx_length; 265*e71b7053SJung-uk Kim return s->sid_ctx; 266*e71b7053SJung-uk Kim } 2673b4e3dcbSSimon L. B. Nielsen 2681f13597dSJung-uk Kim unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s) 2691f13597dSJung-uk Kim { 2701f13597dSJung-uk Kim return s->compress_meth; 2711f13597dSJung-uk Kim } 2721f13597dSJung-uk Kim 2736f9291ceSJung-uk Kim /* 274*e71b7053SJung-uk Kim * SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling 275*e71b7053SJung-uk Kim * the ID with random junk repeatedly until we have no conflict is going to 276*e71b7053SJung-uk Kim * complete in one iteration pretty much "most" of the time (btw: 277*e71b7053SJung-uk Kim * understatement). So, if it takes us 10 iterations and we still can't avoid 278*e71b7053SJung-uk Kim * a conflict - well that's a reasonable point to call it quits. Either the 279*e71b7053SJung-uk Kim * RAND code is broken or someone is trying to open roughly very close to 280*e71b7053SJung-uk Kim * 2^256 SSL sessions to our server. How you might store that many sessions 281*e71b7053SJung-uk Kim * is perhaps a more interesting question ... 2826f9291ceSJung-uk Kim */ 2835c87c606SMark Murray 2845c87c606SMark Murray #define MAX_SESS_ID_ATTEMPTS 10 285*e71b7053SJung-uk Kim static int def_generate_session_id(SSL *ssl, unsigned char *id, 2865c87c606SMark Murray unsigned int *id_len) 2875c87c606SMark Murray { 2885c87c606SMark Murray unsigned int retry = 0; 2895c87c606SMark Murray do 290aeb5019cSJung-uk Kim if (RAND_bytes(id, *id_len) <= 0) 2916be8ae07SJacques Vidrine return 0; 2925c87c606SMark Murray while (SSL_has_matching_session_id(ssl, id, *id_len) && 2935c87c606SMark Murray (++retry < MAX_SESS_ID_ATTEMPTS)) ; 2945c87c606SMark Murray if (retry < MAX_SESS_ID_ATTEMPTS) 2955c87c606SMark Murray return 1; 2965c87c606SMark Murray /* else - woops a session_id match */ 2976f9291ceSJung-uk Kim /* 2986f9291ceSJung-uk Kim * XXX We should also check the external cache -- but the probability of 2996f9291ceSJung-uk Kim * a collision is negligible, and we could not prevent the concurrent 3006f9291ceSJung-uk Kim * creation of sessions with identical IDs since we currently don't have 3016f9291ceSJung-uk Kim * means to atomically check whether a session ID already exists and make 3026f9291ceSJung-uk Kim * a reservation for it if it does not (this problem applies to the 3036f9291ceSJung-uk Kim * internal cache as well). 3045c87c606SMark Murray */ 3055c87c606SMark Murray return 0; 3065c87c606SMark Murray } 3075c87c606SMark Murray 308*e71b7053SJung-uk Kim int ssl_generate_session_id(SSL *s, SSL_SESSION *ss) 309*e71b7053SJung-uk Kim { 310*e71b7053SJung-uk Kim unsigned int tmp; 311*e71b7053SJung-uk Kim GEN_SESSION_CB cb = def_generate_session_id; 312*e71b7053SJung-uk Kim 313*e71b7053SJung-uk Kim switch (s->version) { 314*e71b7053SJung-uk Kim case SSL3_VERSION: 315*e71b7053SJung-uk Kim case TLS1_VERSION: 316*e71b7053SJung-uk Kim case TLS1_1_VERSION: 317*e71b7053SJung-uk Kim case TLS1_2_VERSION: 318*e71b7053SJung-uk Kim case TLS1_3_VERSION: 319*e71b7053SJung-uk Kim case DTLS1_BAD_VER: 320*e71b7053SJung-uk Kim case DTLS1_VERSION: 321*e71b7053SJung-uk Kim case DTLS1_2_VERSION: 322*e71b7053SJung-uk Kim ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; 323*e71b7053SJung-uk Kim break; 324*e71b7053SJung-uk Kim default: 325*e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, 326*e71b7053SJung-uk Kim SSL_R_UNSUPPORTED_SSL_VERSION); 327*e71b7053SJung-uk Kim return 0; 328*e71b7053SJung-uk Kim } 329*e71b7053SJung-uk Kim 330*e71b7053SJung-uk Kim /*- 331*e71b7053SJung-uk Kim * If RFC5077 ticket, use empty session ID (as server). 332*e71b7053SJung-uk Kim * Note that: 333*e71b7053SJung-uk Kim * (a) ssl_get_prev_session() does lookahead into the 334*e71b7053SJung-uk Kim * ClientHello extensions to find the session ticket. 335*e71b7053SJung-uk Kim * When ssl_get_prev_session() fails, statem_srvr.c calls 336*e71b7053SJung-uk Kim * ssl_get_new_session() in tls_process_client_hello(). 337*e71b7053SJung-uk Kim * At that point, it has not yet parsed the extensions, 338*e71b7053SJung-uk Kim * however, because of the lookahead, it already knows 339*e71b7053SJung-uk Kim * whether a ticket is expected or not. 340*e71b7053SJung-uk Kim * 341*e71b7053SJung-uk Kim * (b) statem_clnt.c calls ssl_get_new_session() before parsing 342*e71b7053SJung-uk Kim * ServerHello extensions, and before recording the session 343*e71b7053SJung-uk Kim * ID received from the server, so this block is a noop. 344*e71b7053SJung-uk Kim */ 345*e71b7053SJung-uk Kim if (s->ext.ticket_expected) { 346*e71b7053SJung-uk Kim ss->session_id_length = 0; 347*e71b7053SJung-uk Kim return 1; 348*e71b7053SJung-uk Kim } 349*e71b7053SJung-uk Kim 350*e71b7053SJung-uk Kim /* Choose which callback will set the session ID */ 351*e71b7053SJung-uk Kim CRYPTO_THREAD_read_lock(s->lock); 352*e71b7053SJung-uk Kim CRYPTO_THREAD_read_lock(s->session_ctx->lock); 353*e71b7053SJung-uk Kim if (s->generate_session_id) 354*e71b7053SJung-uk Kim cb = s->generate_session_id; 355*e71b7053SJung-uk Kim else if (s->session_ctx->generate_session_id) 356*e71b7053SJung-uk Kim cb = s->session_ctx->generate_session_id; 357*e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(s->session_ctx->lock); 358*e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(s->lock); 359*e71b7053SJung-uk Kim /* Choose a session ID */ 360*e71b7053SJung-uk Kim memset(ss->session_id, 0, ss->session_id_length); 361*e71b7053SJung-uk Kim tmp = (int)ss->session_id_length; 362*e71b7053SJung-uk Kim if (!cb(s, ss->session_id, &tmp)) { 363*e71b7053SJung-uk Kim /* The callback failed */ 364*e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, 365*e71b7053SJung-uk Kim SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); 366*e71b7053SJung-uk Kim return 0; 367*e71b7053SJung-uk Kim } 368*e71b7053SJung-uk Kim /* 369*e71b7053SJung-uk Kim * Don't allow the callback to set the session length to zero. nor 370*e71b7053SJung-uk Kim * set it higher than it was. 371*e71b7053SJung-uk Kim */ 372*e71b7053SJung-uk Kim if (tmp == 0 || tmp > ss->session_id_length) { 373*e71b7053SJung-uk Kim /* The callback set an illegal length */ 374*e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, 375*e71b7053SJung-uk Kim SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); 376*e71b7053SJung-uk Kim return 0; 377*e71b7053SJung-uk Kim } 378*e71b7053SJung-uk Kim ss->session_id_length = tmp; 379*e71b7053SJung-uk Kim /* Finally, check for a conflict */ 380*e71b7053SJung-uk Kim if (SSL_has_matching_session_id(s, ss->session_id, 381*e71b7053SJung-uk Kim (unsigned int)ss->session_id_length)) { 382*e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID, 383*e71b7053SJung-uk Kim SSL_R_SSL_SESSION_ID_CONFLICT); 384*e71b7053SJung-uk Kim return 0; 385*e71b7053SJung-uk Kim } 386*e71b7053SJung-uk Kim 387*e71b7053SJung-uk Kim return 1; 388*e71b7053SJung-uk Kim } 389*e71b7053SJung-uk Kim 39074664626SKris Kennaway int ssl_get_new_session(SSL *s, int session) 39174664626SKris Kennaway { 39274664626SKris Kennaway /* This gets used by clients and servers. */ 39374664626SKris Kennaway 39474664626SKris Kennaway SSL_SESSION *ss = NULL; 39574664626SKris Kennaway 396*e71b7053SJung-uk Kim if ((ss = SSL_SESSION_new()) == NULL) { 397*e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, 398*e71b7053SJung-uk Kim ERR_R_MALLOC_FAILURE); 399*e71b7053SJung-uk Kim return 0; 400*e71b7053SJung-uk Kim } 40174664626SKris Kennaway 40274664626SKris Kennaway /* If the context has a default timeout, use it */ 4031f13597dSJung-uk Kim if (s->session_ctx->session_timeout == 0) 40474664626SKris Kennaway ss->timeout = SSL_get_default_timeout(s); 40574664626SKris Kennaway else 4061f13597dSJung-uk Kim ss->timeout = s->session_ctx->session_timeout; 40774664626SKris Kennaway 40874664626SKris Kennaway SSL_SESSION_free(s->session); 40974664626SKris Kennaway s->session = NULL; 41074664626SKris Kennaway 4116f9291ceSJung-uk Kim if (session) { 412*e71b7053SJung-uk Kim if (SSL_IS_TLS13(s)) { 4136f9291ceSJung-uk Kim /* 414*e71b7053SJung-uk Kim * We generate the session id while constructing the 415*e71b7053SJung-uk Kim * NewSessionTicket in TLSv1.3. 4166f9291ceSJung-uk Kim */ 417*e71b7053SJung-uk Kim ss->session_id_length = 0; 418*e71b7053SJung-uk Kim } else if (!ssl_generate_session_id(s, ss)) { 419*e71b7053SJung-uk Kim /* SSLfatal() already called */ 420db522d3aSSimon L. B. Nielsen SSL_SESSION_free(ss); 421db522d3aSSimon L. B. Nielsen return 0; 422db522d3aSSimon L. B. Nielsen } 423*e71b7053SJung-uk Kim 4246f9291ceSJung-uk Kim } else { 42574664626SKris Kennaway ss->session_id_length = 0; 42674664626SKris Kennaway } 42774664626SKris Kennaway 428dee36b4fSJung-uk Kim if (s->sid_ctx_length > sizeof(ss->sid_ctx)) { 429*e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, 430*e71b7053SJung-uk Kim ERR_R_INTERNAL_ERROR); 43148454956SJacques Vidrine SSL_SESSION_free(ss); 43248454956SJacques Vidrine return 0; 43348454956SJacques Vidrine } 43474664626SKris Kennaway memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length); 43574664626SKris Kennaway ss->sid_ctx_length = s->sid_ctx_length; 43674664626SKris Kennaway s->session = ss; 43774664626SKris Kennaway ss->ssl_version = s->version; 438f579bf8eSKris Kennaway ss->verify_result = X509_V_OK; 43974664626SKris Kennaway 440*e71b7053SJung-uk Kim /* If client supports extended master secret set it in session */ 441*e71b7053SJung-uk Kim if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) 442*e71b7053SJung-uk Kim ss->flags |= SSL_SESS_FLAG_EXTMS; 443*e71b7053SJung-uk Kim 444*e71b7053SJung-uk Kim return 1; 44574664626SKris Kennaway } 44674664626SKris Kennaway 447*e71b7053SJung-uk Kim SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id, 448*e71b7053SJung-uk Kim size_t sess_id_len) 44974664626SKris Kennaway { 450db522d3aSSimon L. B. Nielsen SSL_SESSION *ret = NULL; 45174664626SKris Kennaway 452*e71b7053SJung-uk Kim if ((s->session_ctx->session_cache_mode 453*e71b7053SJung-uk Kim & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP) == 0) { 454db522d3aSSimon L. B. Nielsen SSL_SESSION data; 455*e71b7053SJung-uk Kim 456db522d3aSSimon L. B. Nielsen data.ssl_version = s->version; 457*e71b7053SJung-uk Kim if (!ossl_assert(sess_id_len <= SSL_MAX_SSL_SESSION_ID_LENGTH)) 458*e71b7053SJung-uk Kim return NULL; 459*e71b7053SJung-uk Kim 460*e71b7053SJung-uk Kim memcpy(data.session_id, sess_id, sess_id_len); 461*e71b7053SJung-uk Kim data.session_id_length = sess_id_len; 462*e71b7053SJung-uk Kim 463*e71b7053SJung-uk Kim CRYPTO_THREAD_read_lock(s->session_ctx->lock); 4641f13597dSJung-uk Kim ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data); 4656f9291ceSJung-uk Kim if (ret != NULL) { 46674664626SKris Kennaway /* don't allow other threads to steal it: */ 467*e71b7053SJung-uk Kim SSL_SESSION_up_ref(ret); 4681f13597dSJung-uk Kim } 469*e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(s->session_ctx->lock); 4701f13597dSJung-uk Kim if (ret == NULL) 471*e71b7053SJung-uk Kim tsan_counter(&s->session_ctx->stats.sess_miss); 47274664626SKris Kennaway } 47374664626SKris Kennaway 474*e71b7053SJung-uk Kim if (ret == NULL && s->session_ctx->get_session_cb != NULL) { 47574664626SKris Kennaway int copy = 1; 47674664626SKris Kennaway 477*e71b7053SJung-uk Kim ret = s->session_ctx->get_session_cb(s, sess_id, sess_id_len, ©); 478*e71b7053SJung-uk Kim 479*e71b7053SJung-uk Kim if (ret != NULL) { 480*e71b7053SJung-uk Kim tsan_counter(&s->session_ctx->stats.sess_cb_hit); 48174664626SKris Kennaway 4826f9291ceSJung-uk Kim /* 4836f9291ceSJung-uk Kim * Increment reference count now if the session callback asks us 4846f9291ceSJung-uk Kim * to do so (note that if the session structures returned by the 4856f9291ceSJung-uk Kim * callback are shared between threads, it must handle the 4866f9291ceSJung-uk Kim * reference count itself [i.e. copy == 0], or things won't be 4876f9291ceSJung-uk Kim * thread-safe). 4886f9291ceSJung-uk Kim */ 48974664626SKris Kennaway if (copy) 490*e71b7053SJung-uk Kim SSL_SESSION_up_ref(ret); 49174664626SKris Kennaway 4926f9291ceSJung-uk Kim /* 4936f9291ceSJung-uk Kim * Add the externally cached session to the internal cache as 4946f9291ceSJung-uk Kim * well if and only if we are supposed to. 4956f9291ceSJung-uk Kim */ 496*e71b7053SJung-uk Kim if ((s->session_ctx->session_cache_mode & 497*e71b7053SJung-uk Kim SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0) { 4986f9291ceSJung-uk Kim /* 499*e71b7053SJung-uk Kim * Either return value of SSL_CTX_add_session should not 500*e71b7053SJung-uk Kim * interrupt the session resumption process. The return 501*e71b7053SJung-uk Kim * value is intentionally ignored. 5026f9291ceSJung-uk Kim */ 503*e71b7053SJung-uk Kim (void)SSL_CTX_add_session(s->session_ctx, ret); 504*e71b7053SJung-uk Kim } 505*e71b7053SJung-uk Kim } 506*e71b7053SJung-uk Kim } 507*e71b7053SJung-uk Kim 508*e71b7053SJung-uk Kim return ret; 509*e71b7053SJung-uk Kim } 510*e71b7053SJung-uk Kim 511*e71b7053SJung-uk Kim /*- 512*e71b7053SJung-uk Kim * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this 513*e71b7053SJung-uk Kim * connection. It is only called by servers. 514*e71b7053SJung-uk Kim * 515*e71b7053SJung-uk Kim * hello: The parsed ClientHello data 516*e71b7053SJung-uk Kim * 517*e71b7053SJung-uk Kim * Returns: 518*e71b7053SJung-uk Kim * -1: fatal error 519*e71b7053SJung-uk Kim * 0: no session found 520*e71b7053SJung-uk Kim * 1: a session may have been found. 521*e71b7053SJung-uk Kim * 522*e71b7053SJung-uk Kim * Side effects: 523*e71b7053SJung-uk Kim * - If a session is found then s->session is pointed at it (after freeing an 524*e71b7053SJung-uk Kim * existing session if need be) and s->verify_result is set from the session. 525*e71b7053SJung-uk Kim * - Both for new and resumed sessions, s->ext.ticket_expected is set to 1 526*e71b7053SJung-uk Kim * if the server should issue a new session ticket (to 0 otherwise). 527*e71b7053SJung-uk Kim */ 528*e71b7053SJung-uk Kim int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) 529*e71b7053SJung-uk Kim { 530*e71b7053SJung-uk Kim /* This is used only by servers. */ 531*e71b7053SJung-uk Kim 532*e71b7053SJung-uk Kim SSL_SESSION *ret = NULL; 533*e71b7053SJung-uk Kim int fatal = 0; 534*e71b7053SJung-uk Kim int try_session_cache = 0; 535*e71b7053SJung-uk Kim SSL_TICKET_STATUS r; 536*e71b7053SJung-uk Kim 537*e71b7053SJung-uk Kim if (SSL_IS_TLS13(s)) { 538*e71b7053SJung-uk Kim /* 539*e71b7053SJung-uk Kim * By default we will send a new ticket. This can be overridden in the 540*e71b7053SJung-uk Kim * ticket processing. 541*e71b7053SJung-uk Kim */ 542*e71b7053SJung-uk Kim s->ext.ticket_expected = 1; 543*e71b7053SJung-uk Kim if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes, 544*e71b7053SJung-uk Kim SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts, 545*e71b7053SJung-uk Kim NULL, 0) 546*e71b7053SJung-uk Kim || !tls_parse_extension(s, TLSEXT_IDX_psk, SSL_EXT_CLIENT_HELLO, 547*e71b7053SJung-uk Kim hello->pre_proc_exts, NULL, 0)) 548*e71b7053SJung-uk Kim return -1; 549*e71b7053SJung-uk Kim 550*e71b7053SJung-uk Kim ret = s->session; 551*e71b7053SJung-uk Kim } else { 552*e71b7053SJung-uk Kim /* sets s->ext.ticket_expected */ 553*e71b7053SJung-uk Kim r = tls_get_ticket_from_client(s, hello, &ret); 554*e71b7053SJung-uk Kim switch (r) { 555*e71b7053SJung-uk Kim case SSL_TICKET_FATAL_ERR_MALLOC: 556*e71b7053SJung-uk Kim case SSL_TICKET_FATAL_ERR_OTHER: 557*e71b7053SJung-uk Kim fatal = 1; 558*e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, 559*e71b7053SJung-uk Kim ERR_R_INTERNAL_ERROR); 560*e71b7053SJung-uk Kim goto err; 561*e71b7053SJung-uk Kim case SSL_TICKET_NONE: 562*e71b7053SJung-uk Kim case SSL_TICKET_EMPTY: 563*e71b7053SJung-uk Kim if (hello->session_id_len > 0) { 564*e71b7053SJung-uk Kim try_session_cache = 1; 565*e71b7053SJung-uk Kim ret = lookup_sess_in_cache(s, hello->session_id, 566*e71b7053SJung-uk Kim hello->session_id_len); 567*e71b7053SJung-uk Kim } 568*e71b7053SJung-uk Kim break; 569*e71b7053SJung-uk Kim case SSL_TICKET_NO_DECRYPT: 570*e71b7053SJung-uk Kim case SSL_TICKET_SUCCESS: 571*e71b7053SJung-uk Kim case SSL_TICKET_SUCCESS_RENEW: 572*e71b7053SJung-uk Kim break; 57374664626SKris Kennaway } 57474664626SKris Kennaway } 57574664626SKris Kennaway 5761f13597dSJung-uk Kim if (ret == NULL) 5771f13597dSJung-uk Kim goto err; 5781f13597dSJung-uk Kim 5791f13597dSJung-uk Kim /* Now ret is non-NULL and we own one of its reference counts. */ 58074664626SKris Kennaway 581*e71b7053SJung-uk Kim /* Check TLS version consistency */ 582*e71b7053SJung-uk Kim if (ret->ssl_version != s->version) 583*e71b7053SJung-uk Kim goto err; 584*e71b7053SJung-uk Kim 585db522d3aSSimon L. B. Nielsen if (ret->sid_ctx_length != s->sid_ctx_length 5866f9291ceSJung-uk Kim || memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) { 5876f9291ceSJung-uk Kim /* 5886f9291ceSJung-uk Kim * We have the session requested by the client, but we don't want to 5896f9291ceSJung-uk Kim * use it in this context. 5906f9291ceSJung-uk Kim */ 59174664626SKris Kennaway goto err; /* treat like cache miss */ 59274664626SKris Kennaway } 593db522d3aSSimon L. B. Nielsen 5946f9291ceSJung-uk Kim if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { 5956f9291ceSJung-uk Kim /* 5966f9291ceSJung-uk Kim * We can't be sure if this session is being used out of context, 5976f9291ceSJung-uk Kim * which is especially important for SSL_VERIFY_PEER. The application 5986f9291ceSJung-uk Kim * should have used SSL[_CTX]_set_session_id_context. For this error 5996f9291ceSJung-uk Kim * case, we generate an error instead of treating the event like a 6006f9291ceSJung-uk Kim * cache miss (otherwise it would be easy for applications to 6016f9291ceSJung-uk Kim * effectively disable the session cache by accident without anyone 6026f9291ceSJung-uk Kim * noticing). 603db522d3aSSimon L. B. Nielsen */ 604db522d3aSSimon L. B. Nielsen 605*e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION, 6066f9291ceSJung-uk Kim SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); 607db522d3aSSimon L. B. Nielsen fatal = 1; 608db522d3aSSimon L. B. Nielsen goto err; 60974664626SKris Kennaway } 61074664626SKris Kennaway 6116f9291ceSJung-uk Kim if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */ 612*e71b7053SJung-uk Kim tsan_counter(&s->session_ctx->stats.sess_timeout); 6136f9291ceSJung-uk Kim if (try_session_cache) { 6141f13597dSJung-uk Kim /* session was from the cache, so remove it */ 6151f13597dSJung-uk Kim SSL_CTX_remove_session(s->session_ctx, ret); 6161f13597dSJung-uk Kim } 61774664626SKris Kennaway goto err; 61874664626SKris Kennaway } 61974664626SKris Kennaway 620*e71b7053SJung-uk Kim /* Check extended master secret extension consistency */ 621*e71b7053SJung-uk Kim if (ret->flags & SSL_SESS_FLAG_EXTMS) { 622*e71b7053SJung-uk Kim /* If old session includes extms, but new does not: abort handshake */ 623*e71b7053SJung-uk Kim if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)) { 624*e71b7053SJung-uk Kim SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_GET_PREV_SESSION, 625*e71b7053SJung-uk Kim SSL_R_INCONSISTENT_EXTMS); 626*e71b7053SJung-uk Kim fatal = 1; 627*e71b7053SJung-uk Kim goto err; 628*e71b7053SJung-uk Kim } 629*e71b7053SJung-uk Kim } else if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) { 630*e71b7053SJung-uk Kim /* If new session includes extms, but old does not: do not resume */ 631*e71b7053SJung-uk Kim goto err; 632*e71b7053SJung-uk Kim } 63374664626SKris Kennaway 634*e71b7053SJung-uk Kim if (!SSL_IS_TLS13(s)) { 635*e71b7053SJung-uk Kim /* We already did this for TLS1.3 */ 63674664626SKris Kennaway SSL_SESSION_free(s->session); 63774664626SKris Kennaway s->session = ret; 638*e71b7053SJung-uk Kim } 639*e71b7053SJung-uk Kim 640*e71b7053SJung-uk Kim tsan_counter(&s->session_ctx->stats.sess_hit); 641f579bf8eSKris Kennaway s->verify_result = s->session->verify_result; 6421f13597dSJung-uk Kim return 1; 64374664626SKris Kennaway 64474664626SKris Kennaway err: 6456f9291ceSJung-uk Kim if (ret != NULL) { 64674664626SKris Kennaway SSL_SESSION_free(ret); 647*e71b7053SJung-uk Kim /* In TLSv1.3 s->session was already set to ret, so we NULL it out */ 648*e71b7053SJung-uk Kim if (SSL_IS_TLS13(s)) 649*e71b7053SJung-uk Kim s->session = NULL; 650*e71b7053SJung-uk Kim 6516f9291ceSJung-uk Kim if (!try_session_cache) { 6526f9291ceSJung-uk Kim /* 6536f9291ceSJung-uk Kim * The session was from a ticket, so we should issue a ticket for 6546f9291ceSJung-uk Kim * the new session 6556f9291ceSJung-uk Kim */ 656*e71b7053SJung-uk Kim s->ext.ticket_expected = 1; 6571f13597dSJung-uk Kim } 6581f13597dSJung-uk Kim } 65974664626SKris Kennaway if (fatal) 66074664626SKris Kennaway return -1; 661*e71b7053SJung-uk Kim 66274664626SKris Kennaway return 0; 66374664626SKris Kennaway } 66474664626SKris Kennaway 66574664626SKris Kennaway int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) 66674664626SKris Kennaway { 66774664626SKris Kennaway int ret = 0; 66874664626SKris Kennaway SSL_SESSION *s; 66974664626SKris Kennaway 6706f9291ceSJung-uk Kim /* 6716f9291ceSJung-uk Kim * add just 1 reference count for the SSL_CTX's session cache even though 6726f9291ceSJung-uk Kim * it has two ways of access: each session is in a doubly linked list and 6736f9291ceSJung-uk Kim * an lhash 6746f9291ceSJung-uk Kim */ 675*e71b7053SJung-uk Kim SSL_SESSION_up_ref(c); 6766f9291ceSJung-uk Kim /* 6776f9291ceSJung-uk Kim * if session c is in already in cache, we take back the increment later 6786f9291ceSJung-uk Kim */ 67974664626SKris Kennaway 680*e71b7053SJung-uk Kim CRYPTO_THREAD_write_lock(ctx->lock); 6811f13597dSJung-uk Kim s = lh_SSL_SESSION_insert(ctx->sessions, c); 68274664626SKris Kennaway 6836f9291ceSJung-uk Kim /* 6846f9291ceSJung-uk Kim * s != NULL iff we already had a session with the given PID. In this 6856f9291ceSJung-uk Kim * case, s == c should hold (then we did not really modify 6866f9291ceSJung-uk Kim * ctx->sessions), or we're in trouble. 6876f9291ceSJung-uk Kim */ 6886f9291ceSJung-uk Kim if (s != NULL && s != c) { 689f579bf8eSKris Kennaway /* We *are* in trouble ... */ 690f579bf8eSKris Kennaway SSL_SESSION_list_remove(ctx, s); 691f579bf8eSKris Kennaway SSL_SESSION_free(s); 6926f9291ceSJung-uk Kim /* 6936f9291ceSJung-uk Kim * ... so pretend the other session did not exist in cache (we cannot 6946f9291ceSJung-uk Kim * handle two SSL_SESSION structures with identical session ID in the 6956f9291ceSJung-uk Kim * same cache, which could happen e.g. when two threads concurrently 6966f9291ceSJung-uk Kim * obtain the same session from an external cache) 6976f9291ceSJung-uk Kim */ 698f579bf8eSKris Kennaway s = NULL; 6996cf8931aSJung-uk Kim } else if (s == NULL && 7006cf8931aSJung-uk Kim lh_SSL_SESSION_retrieve(ctx->sessions, c) == NULL) { 7016cf8931aSJung-uk Kim /* s == NULL can also mean OOM error in lh_SSL_SESSION_insert ... */ 7026cf8931aSJung-uk Kim 7036cf8931aSJung-uk Kim /* 7046cf8931aSJung-uk Kim * ... so take back the extra reference and also don't add 7056cf8931aSJung-uk Kim * the session to the SSL_SESSION_list at this time 7066cf8931aSJung-uk Kim */ 7076cf8931aSJung-uk Kim s = c; 708f579bf8eSKris Kennaway } 709f579bf8eSKris Kennaway 710f579bf8eSKris Kennaway /* Put at the head of the queue unless it is already in the cache */ 71174664626SKris Kennaway if (s == NULL) 71274664626SKris Kennaway SSL_SESSION_list_add(ctx, c); 71374664626SKris Kennaway 7146f9291ceSJung-uk Kim if (s != NULL) { 7156f9291ceSJung-uk Kim /* 7166f9291ceSJung-uk Kim * existing cache entry -- decrement previously incremented reference 7176f9291ceSJung-uk Kim * count because it already takes into account the cache 7186f9291ceSJung-uk Kim */ 719f579bf8eSKris Kennaway 720f579bf8eSKris Kennaway SSL_SESSION_free(s); /* s == c */ 72174664626SKris Kennaway ret = 0; 7226f9291ceSJung-uk Kim } else { 7236f9291ceSJung-uk Kim /* 7246f9291ceSJung-uk Kim * new cache entry -- remove old ones if cache has become too large 7256f9291ceSJung-uk Kim */ 726f579bf8eSKris Kennaway 72774664626SKris Kennaway ret = 1; 72874664626SKris Kennaway 7296f9291ceSJung-uk Kim if (SSL_CTX_sess_get_cache_size(ctx) > 0) { 730*e71b7053SJung-uk Kim while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { 7316f9291ceSJung-uk Kim if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) 73274664626SKris Kennaway break; 73374664626SKris Kennaway else 734*e71b7053SJung-uk Kim tsan_counter(&ctx->stats.sess_cache_full); 73574664626SKris Kennaway } 73674664626SKris Kennaway } 73774664626SKris Kennaway } 738*e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(ctx->lock); 739*e71b7053SJung-uk Kim return ret; 74074664626SKris Kennaway } 74174664626SKris Kennaway 74274664626SKris Kennaway int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) 74374664626SKris Kennaway { 74474664626SKris Kennaway return remove_session_lock(ctx, c, 1); 74574664626SKris Kennaway } 74674664626SKris Kennaway 74774664626SKris Kennaway static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) 74874664626SKris Kennaway { 74974664626SKris Kennaway SSL_SESSION *r; 75074664626SKris Kennaway int ret = 0; 75174664626SKris Kennaway 7526f9291ceSJung-uk Kim if ((c != NULL) && (c->session_id_length != 0)) { 7536f9291ceSJung-uk Kim if (lck) 754*e71b7053SJung-uk Kim CRYPTO_THREAD_write_lock(ctx->lock); 755*e71b7053SJung-uk Kim if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) != NULL) { 75674664626SKris Kennaway ret = 1; 757*e71b7053SJung-uk Kim r = lh_SSL_SESSION_delete(ctx->sessions, r); 758*e71b7053SJung-uk Kim SSL_SESSION_list_remove(ctx, r); 75974664626SKris Kennaway } 760*e71b7053SJung-uk Kim c->not_resumable = 1; 76174664626SKris Kennaway 7626f9291ceSJung-uk Kim if (lck) 763*e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(ctx->lock); 76474664626SKris Kennaway 76574664626SKris Kennaway if (ctx->remove_session_cb != NULL) 766*e71b7053SJung-uk Kim ctx->remove_session_cb(ctx, c); 767*e71b7053SJung-uk Kim 768*e71b7053SJung-uk Kim if (ret) 76974664626SKris Kennaway SSL_SESSION_free(r); 7706f9291ceSJung-uk Kim } else 77174664626SKris Kennaway ret = 0; 772*e71b7053SJung-uk Kim return ret; 77374664626SKris Kennaway } 77474664626SKris Kennaway 77574664626SKris Kennaway void SSL_SESSION_free(SSL_SESSION *ss) 77674664626SKris Kennaway { 77774664626SKris Kennaway int i; 77874664626SKris Kennaway 77974664626SKris Kennaway if (ss == NULL) 78074664626SKris Kennaway return; 781*e71b7053SJung-uk Kim CRYPTO_DOWN_REF(&ss->references, &i, ss->lock); 782*e71b7053SJung-uk Kim REF_PRINT_COUNT("SSL_SESSION", ss); 7836f9291ceSJung-uk Kim if (i > 0) 7846f9291ceSJung-uk Kim return; 785*e71b7053SJung-uk Kim REF_ASSERT_ISNT(i < 0); 78674664626SKris Kennaway 7875c87c606SMark Murray CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); 78874664626SKris Kennaway 789dee36b4fSJung-uk Kim OPENSSL_cleanse(ss->master_key, sizeof(ss->master_key)); 790dee36b4fSJung-uk Kim OPENSSL_cleanse(ss->session_id, sizeof(ss->session_id)); 7916f9291ceSJung-uk Kim X509_free(ss->peer); 792*e71b7053SJung-uk Kim sk_X509_pop_free(ss->peer_chain, X509_free); 7936f9291ceSJung-uk Kim sk_SSL_CIPHER_free(ss->ciphers); 794*e71b7053SJung-uk Kim OPENSSL_free(ss->ext.hostname); 795*e71b7053SJung-uk Kim OPENSSL_free(ss->ext.tick); 7961f13597dSJung-uk Kim #ifndef OPENSSL_NO_EC 797*e71b7053SJung-uk Kim OPENSSL_free(ss->ext.ecpointformats); 798*e71b7053SJung-uk Kim ss->ext.ecpointformats = NULL; 799*e71b7053SJung-uk Kim ss->ext.ecpointformats_len = 0; 800*e71b7053SJung-uk Kim OPENSSL_free(ss->ext.supportedgroups); 801*e71b7053SJung-uk Kim ss->ext.supportedgroups = NULL; 802*e71b7053SJung-uk Kim ss->ext.supportedgroups_len = 0; 8031f13597dSJung-uk Kim #endif /* OPENSSL_NO_EC */ 8041f13597dSJung-uk Kim #ifndef OPENSSL_NO_PSK 8051f13597dSJung-uk Kim OPENSSL_free(ss->psk_identity_hint); 8061f13597dSJung-uk Kim OPENSSL_free(ss->psk_identity); 8071f13597dSJung-uk Kim #endif 8081f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP 8091f13597dSJung-uk Kim OPENSSL_free(ss->srp_username); 810db522d3aSSimon L. B. Nielsen #endif 811*e71b7053SJung-uk Kim OPENSSL_free(ss->ext.alpn_selected); 812*e71b7053SJung-uk Kim OPENSSL_free(ss->ticket_appdata); 813*e71b7053SJung-uk Kim CRYPTO_THREAD_lock_free(ss->lock); 814*e71b7053SJung-uk Kim OPENSSL_clear_free(ss, sizeof(*ss)); 815*e71b7053SJung-uk Kim } 816*e71b7053SJung-uk Kim 817*e71b7053SJung-uk Kim int SSL_SESSION_up_ref(SSL_SESSION *ss) 818*e71b7053SJung-uk Kim { 819*e71b7053SJung-uk Kim int i; 820*e71b7053SJung-uk Kim 821*e71b7053SJung-uk Kim if (CRYPTO_UP_REF(&ss->references, &i, ss->lock) <= 0) 822*e71b7053SJung-uk Kim return 0; 823*e71b7053SJung-uk Kim 824*e71b7053SJung-uk Kim REF_PRINT_COUNT("SSL_SESSION", ss); 825*e71b7053SJung-uk Kim REF_ASSERT_ISNT(i < 2); 826*e71b7053SJung-uk Kim return ((i > 1) ? 1 : 0); 82774664626SKris Kennaway } 82874664626SKris Kennaway 82974664626SKris Kennaway int SSL_set_session(SSL *s, SSL_SESSION *session) 83074664626SKris Kennaway { 831*e71b7053SJung-uk Kim ssl_clear_bad_session(s); 832*e71b7053SJung-uk Kim if (s->ctx->method != s->method) { 833*e71b7053SJung-uk Kim if (!SSL_set_ssl_method(s, s->ctx->method)) 834aeb5019cSJung-uk Kim return 0; 835aeb5019cSJung-uk Kim } 8365c87c606SMark Murray 837*e71b7053SJung-uk Kim if (session != NULL) { 838*e71b7053SJung-uk Kim SSL_SESSION_up_ref(session); 839*e71b7053SJung-uk Kim s->verify_result = session->verify_result; 840*e71b7053SJung-uk Kim } 84174664626SKris Kennaway SSL_SESSION_free(s->session); 84274664626SKris Kennaway s->session = session; 843*e71b7053SJung-uk Kim 844*e71b7053SJung-uk Kim return 1; 84574664626SKris Kennaway } 84674664626SKris Kennaway 847*e71b7053SJung-uk Kim int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, 848*e71b7053SJung-uk Kim unsigned int sid_len) 849*e71b7053SJung-uk Kim { 850*e71b7053SJung-uk Kim if (sid_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { 851*e71b7053SJung-uk Kim SSLerr(SSL_F_SSL_SESSION_SET1_ID, 852*e71b7053SJung-uk Kim SSL_R_SSL_SESSION_ID_TOO_LONG); 853*e71b7053SJung-uk Kim return 0; 85474664626SKris Kennaway } 855*e71b7053SJung-uk Kim s->session_id_length = sid_len; 856*e71b7053SJung-uk Kim if (sid != s->session_id) 857*e71b7053SJung-uk Kim memcpy(s->session_id, sid, sid_len); 858*e71b7053SJung-uk Kim return 1; 85974664626SKris Kennaway } 86074664626SKris Kennaway 86174664626SKris Kennaway long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) 86274664626SKris Kennaway { 8636f9291ceSJung-uk Kim if (s == NULL) 864*e71b7053SJung-uk Kim return 0; 86574664626SKris Kennaway s->timeout = t; 866*e71b7053SJung-uk Kim return 1; 86774664626SKris Kennaway } 86874664626SKris Kennaway 8693b4e3dcbSSimon L. B. Nielsen long SSL_SESSION_get_timeout(const SSL_SESSION *s) 87074664626SKris Kennaway { 8716f9291ceSJung-uk Kim if (s == NULL) 872*e71b7053SJung-uk Kim return 0; 873*e71b7053SJung-uk Kim return s->timeout; 87474664626SKris Kennaway } 87574664626SKris Kennaway 8763b4e3dcbSSimon L. B. Nielsen long SSL_SESSION_get_time(const SSL_SESSION *s) 87774664626SKris Kennaway { 8786f9291ceSJung-uk Kim if (s == NULL) 879*e71b7053SJung-uk Kim return 0; 880*e71b7053SJung-uk Kim return s->time; 88174664626SKris Kennaway } 88274664626SKris Kennaway 88374664626SKris Kennaway long SSL_SESSION_set_time(SSL_SESSION *s, long t) 88474664626SKris Kennaway { 8856f9291ceSJung-uk Kim if (s == NULL) 886*e71b7053SJung-uk Kim return 0; 88774664626SKris Kennaway s->time = t; 888*e71b7053SJung-uk Kim return t; 889*e71b7053SJung-uk Kim } 890*e71b7053SJung-uk Kim 891*e71b7053SJung-uk Kim int SSL_SESSION_get_protocol_version(const SSL_SESSION *s) 892*e71b7053SJung-uk Kim { 893*e71b7053SJung-uk Kim return s->ssl_version; 894*e71b7053SJung-uk Kim } 895*e71b7053SJung-uk Kim 896*e71b7053SJung-uk Kim int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version) 897*e71b7053SJung-uk Kim { 898*e71b7053SJung-uk Kim s->ssl_version = version; 899*e71b7053SJung-uk Kim return 1; 900*e71b7053SJung-uk Kim } 901*e71b7053SJung-uk Kim 902*e71b7053SJung-uk Kim const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s) 903*e71b7053SJung-uk Kim { 904*e71b7053SJung-uk Kim return s->cipher; 905*e71b7053SJung-uk Kim } 906*e71b7053SJung-uk Kim 907*e71b7053SJung-uk Kim int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher) 908*e71b7053SJung-uk Kim { 909*e71b7053SJung-uk Kim s->cipher = cipher; 910*e71b7053SJung-uk Kim return 1; 911*e71b7053SJung-uk Kim } 912*e71b7053SJung-uk Kim 913*e71b7053SJung-uk Kim const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s) 914*e71b7053SJung-uk Kim { 915*e71b7053SJung-uk Kim return s->ext.hostname; 916*e71b7053SJung-uk Kim } 917*e71b7053SJung-uk Kim 918*e71b7053SJung-uk Kim int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname) 919*e71b7053SJung-uk Kim { 920*e71b7053SJung-uk Kim OPENSSL_free(s->ext.hostname); 921*e71b7053SJung-uk Kim if (hostname == NULL) { 922*e71b7053SJung-uk Kim s->ext.hostname = NULL; 923*e71b7053SJung-uk Kim return 1; 924*e71b7053SJung-uk Kim } 925*e71b7053SJung-uk Kim s->ext.hostname = OPENSSL_strdup(hostname); 926*e71b7053SJung-uk Kim 927*e71b7053SJung-uk Kim return s->ext.hostname != NULL; 928*e71b7053SJung-uk Kim } 929*e71b7053SJung-uk Kim 930*e71b7053SJung-uk Kim int SSL_SESSION_has_ticket(const SSL_SESSION *s) 931*e71b7053SJung-uk Kim { 932*e71b7053SJung-uk Kim return (s->ext.ticklen > 0) ? 1 : 0; 933*e71b7053SJung-uk Kim } 934*e71b7053SJung-uk Kim 935*e71b7053SJung-uk Kim unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) 936*e71b7053SJung-uk Kim { 937*e71b7053SJung-uk Kim return s->ext.tick_lifetime_hint; 938*e71b7053SJung-uk Kim } 939*e71b7053SJung-uk Kim 940*e71b7053SJung-uk Kim void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick, 941*e71b7053SJung-uk Kim size_t *len) 942*e71b7053SJung-uk Kim { 943*e71b7053SJung-uk Kim *len = s->ext.ticklen; 944*e71b7053SJung-uk Kim if (tick != NULL) 945*e71b7053SJung-uk Kim *tick = s->ext.tick; 946*e71b7053SJung-uk Kim } 947*e71b7053SJung-uk Kim 948*e71b7053SJung-uk Kim uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s) 949*e71b7053SJung-uk Kim { 950*e71b7053SJung-uk Kim return s->ext.max_early_data; 951*e71b7053SJung-uk Kim } 952*e71b7053SJung-uk Kim 953*e71b7053SJung-uk Kim int SSL_SESSION_set_max_early_data(SSL_SESSION *s, uint32_t max_early_data) 954*e71b7053SJung-uk Kim { 955*e71b7053SJung-uk Kim s->ext.max_early_data = max_early_data; 956*e71b7053SJung-uk Kim 957*e71b7053SJung-uk Kim return 1; 958*e71b7053SJung-uk Kim } 959*e71b7053SJung-uk Kim 960*e71b7053SJung-uk Kim void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s, 961*e71b7053SJung-uk Kim const unsigned char **alpn, 962*e71b7053SJung-uk Kim size_t *len) 963*e71b7053SJung-uk Kim { 964*e71b7053SJung-uk Kim *alpn = s->ext.alpn_selected; 965*e71b7053SJung-uk Kim *len = s->ext.alpn_selected_len; 966*e71b7053SJung-uk Kim } 967*e71b7053SJung-uk Kim 968*e71b7053SJung-uk Kim int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s, const unsigned char *alpn, 969*e71b7053SJung-uk Kim size_t len) 970*e71b7053SJung-uk Kim { 971*e71b7053SJung-uk Kim OPENSSL_free(s->ext.alpn_selected); 972*e71b7053SJung-uk Kim if (alpn == NULL || len == 0) { 973*e71b7053SJung-uk Kim s->ext.alpn_selected = NULL; 974*e71b7053SJung-uk Kim s->ext.alpn_selected_len = 0; 975*e71b7053SJung-uk Kim return 1; 976*e71b7053SJung-uk Kim } 977*e71b7053SJung-uk Kim s->ext.alpn_selected = OPENSSL_memdup(alpn, len); 978*e71b7053SJung-uk Kim if (s->ext.alpn_selected == NULL) { 979*e71b7053SJung-uk Kim s->ext.alpn_selected_len = 0; 980*e71b7053SJung-uk Kim return 0; 981*e71b7053SJung-uk Kim } 982*e71b7053SJung-uk Kim s->ext.alpn_selected_len = len; 983*e71b7053SJung-uk Kim 984*e71b7053SJung-uk Kim return 1; 98574664626SKris Kennaway } 98674664626SKris Kennaway 9871f13597dSJung-uk Kim X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) 9881f13597dSJung-uk Kim { 9891f13597dSJung-uk Kim return s->peer; 9901f13597dSJung-uk Kim } 9911f13597dSJung-uk Kim 9921f13597dSJung-uk Kim int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, 9931f13597dSJung-uk Kim unsigned int sid_ctx_len) 9941f13597dSJung-uk Kim { 9956f9291ceSJung-uk Kim if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { 9966f9291ceSJung-uk Kim SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT, 9976f9291ceSJung-uk Kim SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); 9981f13597dSJung-uk Kim return 0; 9991f13597dSJung-uk Kim } 10001f13597dSJung-uk Kim s->sid_ctx_length = sid_ctx_len; 1001*e71b7053SJung-uk Kim if (sid_ctx != s->sid_ctx) 10021f13597dSJung-uk Kim memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); 10031f13597dSJung-uk Kim 10041f13597dSJung-uk Kim return 1; 10051f13597dSJung-uk Kim } 10061f13597dSJung-uk Kim 1007*e71b7053SJung-uk Kim int SSL_SESSION_is_resumable(const SSL_SESSION *s) 1008*e71b7053SJung-uk Kim { 1009*e71b7053SJung-uk Kim /* 1010*e71b7053SJung-uk Kim * In the case of EAP-FAST, we can have a pre-shared "ticket" without a 1011*e71b7053SJung-uk Kim * session ID. 1012*e71b7053SJung-uk Kim */ 1013*e71b7053SJung-uk Kim return !s->not_resumable 1014*e71b7053SJung-uk Kim && (s->session_id_length > 0 || s->ext.ticklen > 0); 1015*e71b7053SJung-uk Kim } 1016*e71b7053SJung-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) 1021*e71b7053SJung-uk Kim return 0; 102274664626SKris Kennaway l = s->session_timeout; 102374664626SKris Kennaway s->session_timeout = t; 1024*e71b7053SJung-uk Kim 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) 1030*e71b7053SJung-uk Kim return 0; 1031*e71b7053SJung-uk Kim return s->session_timeout; 103274664626SKris Kennaway } 103374664626SKris Kennaway 10346f9291ceSJung-uk Kim int SSL_set_session_secret_cb(SSL *s, 1035*e71b7053SJung-uk Kim tls_session_secret_cb_fn tls_session_secret_cb, 10366f9291ceSJung-uk Kim void *arg) 10371f13597dSJung-uk Kim { 10386f9291ceSJung-uk Kim if (s == NULL) 1039*e71b7053SJung-uk Kim return 0; 1040*e71b7053SJung-uk Kim s->ext.session_secret_cb = tls_session_secret_cb; 1041*e71b7053SJung-uk Kim s->ext.session_secret_cb_arg = arg; 1042*e71b7053SJung-uk Kim return 1; 10431f13597dSJung-uk Kim } 10441f13597dSJung-uk Kim 10451f13597dSJung-uk Kim int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, 10461f13597dSJung-uk Kim void *arg) 10471f13597dSJung-uk Kim { 10486f9291ceSJung-uk Kim if (s == NULL) 1049*e71b7053SJung-uk Kim return 0; 1050*e71b7053SJung-uk Kim s->ext.session_ticket_cb = cb; 1051*e71b7053SJung-uk Kim s->ext.session_ticket_cb_arg = arg; 1052*e71b7053SJung-uk Kim return 1; 10531f13597dSJung-uk Kim } 10541f13597dSJung-uk Kim 10551f13597dSJung-uk Kim int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) 10561f13597dSJung-uk Kim { 10576f9291ceSJung-uk Kim if (s->version >= TLS1_VERSION) { 1058*e71b7053SJung-uk Kim OPENSSL_free(s->ext.session_ticket); 1059*e71b7053SJung-uk Kim s->ext.session_ticket = NULL; 1060*e71b7053SJung-uk Kim s->ext.session_ticket = 10616f9291ceSJung-uk Kim OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); 1062*e71b7053SJung-uk Kim if (s->ext.session_ticket == NULL) { 10631f13597dSJung-uk Kim SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE); 10641f13597dSJung-uk Kim return 0; 10651f13597dSJung-uk Kim } 10661f13597dSJung-uk Kim 1067*e71b7053SJung-uk Kim if (ext_data != NULL) { 1068*e71b7053SJung-uk Kim s->ext.session_ticket->length = ext_len; 1069*e71b7053SJung-uk Kim s->ext.session_ticket->data = s->ext.session_ticket + 1; 1070*e71b7053SJung-uk Kim memcpy(s->ext.session_ticket->data, ext_data, ext_len); 10716f9291ceSJung-uk Kim } else { 1072*e71b7053SJung-uk Kim s->ext.session_ticket->length = 0; 1073*e71b7053SJung-uk Kim s->ext.session_ticket->data = NULL; 10741f13597dSJung-uk Kim } 10751f13597dSJung-uk Kim 10761f13597dSJung-uk Kim return 1; 10771f13597dSJung-uk Kim } 10781f13597dSJung-uk Kim 10791f13597dSJung-uk Kim return 0; 10801f13597dSJung-uk Kim } 10811f13597dSJung-uk Kim 10826f9291ceSJung-uk Kim typedef struct timeout_param_st { 108374664626SKris Kennaway SSL_CTX *ctx; 108474664626SKris Kennaway long time; 10851f13597dSJung-uk Kim LHASH_OF(SSL_SESSION) *cache; 108674664626SKris Kennaway } TIMEOUT_PARAM; 108774664626SKris Kennaway 1088*e71b7053SJung-uk Kim static void timeout_cb(SSL_SESSION *s, TIMEOUT_PARAM *p) 108974664626SKris Kennaway { 10906f9291ceSJung-uk Kim if ((p->time == 0) || (p->time > (s->time + s->timeout))) { /* timeout */ 10916f9291ceSJung-uk Kim /* 10926f9291ceSJung-uk Kim * The reason we don't call SSL_CTX_remove_session() is to save on 10936f9291ceSJung-uk Kim * locking overhead 10946f9291ceSJung-uk Kim */ 10951f13597dSJung-uk Kim (void)lh_SSL_SESSION_delete(p->cache, s); 109674664626SKris Kennaway SSL_SESSION_list_remove(p->ctx, s); 109774664626SKris Kennaway s->not_resumable = 1; 109874664626SKris Kennaway if (p->ctx->remove_session_cb != NULL) 109974664626SKris Kennaway p->ctx->remove_session_cb(p->ctx, s); 110074664626SKris Kennaway SSL_SESSION_free(s); 110174664626SKris Kennaway } 110274664626SKris Kennaway } 110374664626SKris Kennaway 1104*e71b7053SJung-uk Kim IMPLEMENT_LHASH_DOALL_ARG(SSL_SESSION, TIMEOUT_PARAM); 11055c87c606SMark Murray 110674664626SKris Kennaway void SSL_CTX_flush_sessions(SSL_CTX *s, long t) 110774664626SKris Kennaway { 110874664626SKris Kennaway unsigned long i; 110974664626SKris Kennaway TIMEOUT_PARAM tp; 111074664626SKris Kennaway 111174664626SKris Kennaway tp.ctx = s; 111274664626SKris Kennaway tp.cache = s->sessions; 11136f9291ceSJung-uk Kim if (tp.cache == NULL) 11146f9291ceSJung-uk Kim return; 111574664626SKris Kennaway tp.time = t; 1116*e71b7053SJung-uk Kim CRYPTO_THREAD_write_lock(s->lock); 1117*e71b7053SJung-uk Kim i = lh_SSL_SESSION_get_down_load(s->sessions); 1118*e71b7053SJung-uk Kim lh_SSL_SESSION_set_down_load(s->sessions, 0); 1119*e71b7053SJung-uk Kim lh_SSL_SESSION_doall_TIMEOUT_PARAM(tp.cache, timeout_cb, &tp); 1120*e71b7053SJung-uk Kim lh_SSL_SESSION_set_down_load(s->sessions, i); 1121*e71b7053SJung-uk Kim CRYPTO_THREAD_unlock(s->lock); 112274664626SKris Kennaway } 112374664626SKris Kennaway 112474664626SKris Kennaway int ssl_clear_bad_session(SSL *s) 112574664626SKris Kennaway { 112674664626SKris Kennaway if ((s->session != NULL) && 112774664626SKris Kennaway !(s->shutdown & SSL_SENT_SHUTDOWN) && 11286f9291ceSJung-uk Kim !(SSL_in_init(s) || SSL_in_before(s))) { 1129aeb5019cSJung-uk Kim SSL_CTX_remove_session(s->session_ctx, s->session); 1130*e71b7053SJung-uk Kim return 1; 11316f9291ceSJung-uk Kim } else 1132*e71b7053SJung-uk Kim return 0; 113374664626SKris Kennaway } 113474664626SKris Kennaway 113574664626SKris Kennaway /* locked by SSL_CTX in the calling function */ 113674664626SKris Kennaway static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) 113774664626SKris Kennaway { 11386f9291ceSJung-uk Kim if ((s->next == NULL) || (s->prev == NULL)) 11396f9291ceSJung-uk Kim return; 114074664626SKris Kennaway 11416f9291ceSJung-uk Kim if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) { 11426f9291ceSJung-uk Kim /* last element in list */ 11436f9291ceSJung-uk Kim if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { 11446f9291ceSJung-uk Kim /* only one element in list */ 114574664626SKris Kennaway ctx->session_cache_head = NULL; 114674664626SKris Kennaway ctx->session_cache_tail = NULL; 11476f9291ceSJung-uk Kim } else { 114874664626SKris Kennaway ctx->session_cache_tail = s->prev; 114974664626SKris Kennaway s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail); 115074664626SKris Kennaway } 11516f9291ceSJung-uk Kim } else { 11526f9291ceSJung-uk Kim if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { 11536f9291ceSJung-uk Kim /* first element in list */ 115474664626SKris Kennaway ctx->session_cache_head = s->next; 115574664626SKris Kennaway s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head); 11566f9291ceSJung-uk Kim } else { 11576f9291ceSJung-uk Kim /* middle of list */ 115874664626SKris Kennaway s->next->prev = s->prev; 115974664626SKris Kennaway s->prev->next = s->next; 116074664626SKris Kennaway } 116174664626SKris Kennaway } 116274664626SKris Kennaway s->prev = s->next = NULL; 116374664626SKris Kennaway } 116474664626SKris Kennaway 116574664626SKris Kennaway static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) 116674664626SKris Kennaway { 116774664626SKris Kennaway if ((s->next != NULL) && (s->prev != NULL)) 116874664626SKris Kennaway SSL_SESSION_list_remove(ctx, s); 116974664626SKris Kennaway 11706f9291ceSJung-uk Kim if (ctx->session_cache_head == NULL) { 117174664626SKris Kennaway ctx->session_cache_head = s; 117274664626SKris Kennaway ctx->session_cache_tail = s; 117374664626SKris Kennaway s->prev = (SSL_SESSION *)&(ctx->session_cache_head); 117474664626SKris Kennaway s->next = (SSL_SESSION *)&(ctx->session_cache_tail); 11756f9291ceSJung-uk Kim } else { 117674664626SKris Kennaway s->next = ctx->session_cache_head; 117774664626SKris Kennaway s->next->prev = s; 117874664626SKris Kennaway s->prev = (SSL_SESSION *)&(ctx->session_cache_head); 117974664626SKris Kennaway ctx->session_cache_head = s; 118074664626SKris Kennaway } 118174664626SKris Kennaway } 118274664626SKris Kennaway 11835471f83eSSimon L. B. Nielsen void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, 1184*e71b7053SJung-uk Kim int (*cb) (struct ssl_st *ssl, SSL_SESSION *sess)) 11855471f83eSSimon L. B. Nielsen { 11865471f83eSSimon L. B. Nielsen ctx->new_session_cb = cb; 11875471f83eSSimon L. B. Nielsen } 11885471f83eSSimon L. B. Nielsen 11896f9291ceSJung-uk Kim int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (SSL *ssl, SSL_SESSION *sess) { 11905471f83eSSimon L. B. Nielsen return ctx->new_session_cb; 11915471f83eSSimon L. B. Nielsen } 11925471f83eSSimon L. B. Nielsen 11935471f83eSSimon L. B. Nielsen void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, 11945471f83eSSimon L. B. Nielsen void (*cb) (SSL_CTX *ctx, SSL_SESSION *sess)) 11955471f83eSSimon L. B. Nielsen { 11965471f83eSSimon L. B. Nielsen ctx->remove_session_cb = cb; 11975471f83eSSimon L. B. Nielsen } 11985471f83eSSimon L. B. Nielsen 11996f9291ceSJung-uk Kim void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (SSL_CTX *ctx, 12006f9291ceSJung-uk Kim SSL_SESSION *sess) { 12015471f83eSSimon L. B. Nielsen return ctx->remove_session_cb; 12025471f83eSSimon L. B. Nielsen } 12035471f83eSSimon L. B. Nielsen 12045471f83eSSimon L. B. Nielsen void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, 12055471f83eSSimon L. B. Nielsen SSL_SESSION *(*cb) (struct ssl_st *ssl, 1206*e71b7053SJung-uk Kim const unsigned char *data, 1207*e71b7053SJung-uk Kim int len, int *copy)) 12085471f83eSSimon L. B. Nielsen { 12095471f83eSSimon L. B. Nielsen ctx->get_session_cb = cb; 12105471f83eSSimon L. B. Nielsen } 12115471f83eSSimon L. B. Nielsen 12125471f83eSSimon L. B. Nielsen SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (SSL *ssl, 1213*e71b7053SJung-uk Kim const unsigned char 1214*e71b7053SJung-uk Kim *data, int len, 1215*e71b7053SJung-uk Kim int *copy) { 12165471f83eSSimon L. B. Nielsen return ctx->get_session_cb; 12175471f83eSSimon L. B. Nielsen } 12185471f83eSSimon L. B. Nielsen 12195471f83eSSimon L. B. Nielsen void SSL_CTX_set_info_callback(SSL_CTX *ctx, 12205471f83eSSimon L. B. Nielsen void (*cb) (const SSL *ssl, int type, int val)) 12215471f83eSSimon L. B. Nielsen { 12225471f83eSSimon L. B. Nielsen ctx->info_callback = cb; 12235471f83eSSimon L. B. Nielsen } 12245471f83eSSimon L. B. Nielsen 12256f9291ceSJung-uk Kim void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type, 12266f9291ceSJung-uk Kim int val) { 12275471f83eSSimon L. B. Nielsen return ctx->info_callback; 12285471f83eSSimon L. B. Nielsen } 12295471f83eSSimon L. B. Nielsen 12305471f83eSSimon L. B. Nielsen void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, 12316f9291ceSJung-uk Kim int (*cb) (SSL *ssl, X509 **x509, 12326f9291ceSJung-uk Kim EVP_PKEY **pkey)) 12335471f83eSSimon L. B. Nielsen { 12345471f83eSSimon L. B. Nielsen ctx->client_cert_cb = cb; 12355471f83eSSimon L. B. Nielsen } 12365471f83eSSimon L. B. Nielsen 12376f9291ceSJung-uk Kim int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509, 12386f9291ceSJung-uk Kim EVP_PKEY **pkey) { 12395471f83eSSimon L. B. Nielsen return ctx->client_cert_cb; 12405471f83eSSimon L. B. Nielsen } 12415471f83eSSimon L. B. Nielsen 1242db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_ENGINE 1243db522d3aSSimon L. B. Nielsen int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e) 1244db522d3aSSimon L. B. Nielsen { 12456f9291ceSJung-uk Kim if (!ENGINE_init(e)) { 1246db522d3aSSimon L. B. Nielsen SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB); 1247db522d3aSSimon L. B. Nielsen return 0; 1248db522d3aSSimon L. B. Nielsen } 12496f9291ceSJung-uk Kim if (!ENGINE_get_ssl_client_cert_function(e)) { 12506f9291ceSJung-uk Kim SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, 12516f9291ceSJung-uk Kim SSL_R_NO_CLIENT_CERT_METHOD); 1252db522d3aSSimon L. B. Nielsen ENGINE_finish(e); 1253db522d3aSSimon L. B. Nielsen return 0; 1254db522d3aSSimon L. B. Nielsen } 1255db522d3aSSimon L. B. Nielsen ctx->client_cert_engine = e; 1256db522d3aSSimon L. B. Nielsen return 1; 1257db522d3aSSimon L. B. Nielsen } 1258db522d3aSSimon L. B. Nielsen #endif 1259db522d3aSSimon L. B. Nielsen 12605471f83eSSimon L. B. Nielsen void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, 12616f9291ceSJung-uk Kim int (*cb) (SSL *ssl, 12626f9291ceSJung-uk Kim unsigned char *cookie, 12636f9291ceSJung-uk Kim unsigned int *cookie_len)) 12645471f83eSSimon L. B. Nielsen { 12655471f83eSSimon L. B. Nielsen ctx->app_gen_cookie_cb = cb; 12665471f83eSSimon L. B. Nielsen } 12675471f83eSSimon L. B. Nielsen 12685471f83eSSimon L. B. Nielsen void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, 1269*e71b7053SJung-uk Kim int (*cb) (SSL *ssl, 1270*e71b7053SJung-uk Kim const unsigned char *cookie, 12716f9291ceSJung-uk Kim unsigned int cookie_len)) 12725471f83eSSimon L. B. Nielsen { 12735471f83eSSimon L. B. Nielsen ctx->app_verify_cookie_cb = cb; 12745471f83eSSimon L. B. Nielsen } 12755471f83eSSimon L. B. Nielsen 1276*e71b7053SJung-uk Kim int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len) 1277*e71b7053SJung-uk Kim { 1278*e71b7053SJung-uk Kim OPENSSL_free(ss->ticket_appdata); 1279*e71b7053SJung-uk Kim ss->ticket_appdata_len = 0; 1280*e71b7053SJung-uk Kim if (data == NULL || len == 0) { 1281*e71b7053SJung-uk Kim ss->ticket_appdata = NULL; 1282*e71b7053SJung-uk Kim return 1; 1283*e71b7053SJung-uk Kim } 1284*e71b7053SJung-uk Kim ss->ticket_appdata = OPENSSL_memdup(data, len); 1285*e71b7053SJung-uk Kim if (ss->ticket_appdata != NULL) { 1286*e71b7053SJung-uk Kim ss->ticket_appdata_len = len; 1287*e71b7053SJung-uk Kim return 1; 1288*e71b7053SJung-uk Kim } 1289*e71b7053SJung-uk Kim return 0; 1290*e71b7053SJung-uk Kim } 1291*e71b7053SJung-uk Kim 1292*e71b7053SJung-uk Kim int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len) 1293*e71b7053SJung-uk Kim { 1294*e71b7053SJung-uk Kim *data = ss->ticket_appdata; 1295*e71b7053SJung-uk Kim *len = ss->ticket_appdata_len; 1296*e71b7053SJung-uk Kim return 1; 1297*e71b7053SJung-uk Kim } 1298*e71b7053SJung-uk Kim 1299*e71b7053SJung-uk Kim void SSL_CTX_set_stateless_cookie_generate_cb( 1300*e71b7053SJung-uk Kim SSL_CTX *ctx, 1301*e71b7053SJung-uk Kim int (*cb) (SSL *ssl, 1302*e71b7053SJung-uk Kim unsigned char *cookie, 1303*e71b7053SJung-uk Kim size_t *cookie_len)) 1304*e71b7053SJung-uk Kim { 1305*e71b7053SJung-uk Kim ctx->gen_stateless_cookie_cb = cb; 1306*e71b7053SJung-uk Kim } 1307*e71b7053SJung-uk Kim 1308*e71b7053SJung-uk Kim void SSL_CTX_set_stateless_cookie_verify_cb( 1309*e71b7053SJung-uk Kim SSL_CTX *ctx, 1310*e71b7053SJung-uk Kim int (*cb) (SSL *ssl, 1311*e71b7053SJung-uk Kim const unsigned char *cookie, 1312*e71b7053SJung-uk Kim size_t cookie_len)) 1313*e71b7053SJung-uk Kim { 1314*e71b7053SJung-uk Kim ctx->verify_stateless_cookie_cb = cb; 1315*e71b7053SJung-uk Kim } 1316*e71b7053SJung-uk Kim 1317*e71b7053SJung-uk Kim IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION) 1318