1/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay@cryptsoft.com). 6 * The implementation was written so as to conform with Netscapes SSL. 7 * 8 * This library is free for commercial and non-commercial use as long as 9 * the following conditions are aheared to. The following conditions 10 * apply to all code found in this distribution, be it the RC4, RSA, 11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 12 * included with this distribution is covered by the same copyright terms 13 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 14 * 15 * Copyright remains Eric Young's, and as such any Copyright notices in 16 * the code are not to be removed. 17 * If this package is used in a product, Eric Young should be given attribution 18 * as the author of the parts of the library used. 19 * This can be in the form of a textual message at program startup or 20 * in documentation (online or textual) provided with the package. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * "This product includes cryptographic software written by 33 * Eric Young (eay@cryptsoft.com)" 34 * The word 'cryptographic' can be left out if the rouines from the library 35 * being used are not cryptographic related :-). 36 * 4. If you include any Windows specific code (or a derivative thereof) from 37 * the apps directory (application code) you must include an acknowledgement: 38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * SUCH DAMAGE. 51 * 52 * The licence and distribution terms for any publically available version or 53 * derivative of this code cannot be changed. i.e. this code cannot simply be 54 * copied and put under another distribution licence 55 * [including the GNU Public Licence.] 56 */ 57/* ==================================================================== 58 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. 59 * 60 * Redistribution and use in source and binary forms, with or without 61 * modification, are permitted provided that the following conditions 62 * are met: 63 * 64 * 1. Redistributions of source code must retain the above copyright 65 * notice, this list of conditions and the following disclaimer. 66 * 67 * 2. Redistributions in binary form must reproduce the above copyright 68 * notice, this list of conditions and the following disclaimer in 69 * the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3. All advertising materials mentioning features or use of this 73 * software must display the following acknowledgment: 74 * "This product includes software developed by the OpenSSL Project 75 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 76 * 77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 78 * endorse or promote products derived from this software without 79 * prior written permission. For written permission, please contact 80 * openssl-core@openssl.org. 81 * 82 * 5. Products derived from this software may not be called "OpenSSL" 83 * nor may "OpenSSL" appear in their names without prior written 84 * permission of the OpenSSL Project. 85 * 86 * 6. Redistributions of any form whatsoever must retain the following 87 * acknowledgment: 88 * "This product includes software developed by the OpenSSL Project 89 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 90 * 91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 94 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 102 * OF THE POSSIBILITY OF SUCH DAMAGE. 103 * ==================================================================== 104 * 105 * This product includes cryptographic software written by Eric Young 106 * (eay@cryptsoft.com). This product includes software written by Tim 107 * Hudson (tjh@cryptsoft.com). 108 * 109 */ 110/* ==================================================================== 111 * Copyright 2005 Nokia. All rights reserved. 112 * 113 * The portions of the attached software ("Contribution") is developed by 114 * Nokia Corporation and is licensed pursuant to the OpenSSL open source 115 * license. 116 * 117 * The Contribution, originally written by Mika Kousa and Pasi Eronen of 118 * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites 119 * support (see RFC 4279) to OpenSSL. 120 * 121 * No patent licenses or other rights except those expressly stated in 122 * the OpenSSL open source license shall be deemed granted or received 123 * expressly, by implication, estoppel, or otherwise. 124 * 125 * No assurances are provided by Nokia that the Contribution does not 126 * infringe the patent or other intellectual property rights of any third 127 * party or that the license provides you with all the necessary rights 128 * to make use of the Contribution. 129 * 130 * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN 131 * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA 132 * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY 133 * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR 134 * OTHERWISE. */ 135 136#include <openssl/ssl.h> 137 138#include <assert.h> 139#include <stdio.h> 140#include <string.h> 141 142#include <openssl/err.h> 143#include <openssl/lhash.h> 144#include <openssl/mem.h> 145#include <openssl/rand.h> 146 147#include "internal.h" 148#include "../crypto/internal.h" 149 150 151/* The address of this is a magic value, a pointer to which is returned by 152 * SSL_magic_pending_session_ptr(). It allows a session callback to indicate 153 * that it needs to asynchronously fetch session information. */ 154static const char g_pending_session_magic = 0; 155 156static CRYPTO_EX_DATA_CLASS g_ex_data_class = 157 CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA; 158 159static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session); 160static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session); 161static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock); 162 163SSL_SESSION *SSL_SESSION_new(void) { 164 SSL_SESSION *session = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)); 165 if (session == NULL) { 166 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); 167 return 0; 168 } 169 memset(session, 0, sizeof(SSL_SESSION)); 170 171 session->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ 172 session->references = 1; 173 session->timeout = SSL_DEFAULT_SESSION_TIMEOUT; 174 session->time = (unsigned long)time(NULL); 175 CRYPTO_new_ex_data(&session->ex_data); 176 return session; 177} 178 179SSL_SESSION *SSL_SESSION_up_ref(SSL_SESSION *session) { 180 if (session != NULL) { 181 CRYPTO_refcount_inc(&session->references); 182 } 183 return session; 184} 185 186void SSL_SESSION_free(SSL_SESSION *session) { 187 if (session == NULL || 188 !CRYPTO_refcount_dec_and_test_zero(&session->references)) { 189 return; 190 } 191 192 CRYPTO_free_ex_data(&g_ex_data_class, session, &session->ex_data); 193 194 OPENSSL_cleanse(session->master_key, sizeof(session->master_key)); 195 OPENSSL_cleanse(session->session_id, sizeof(session->session_id)); 196 X509_free(session->peer); 197 sk_X509_pop_free(session->cert_chain, X509_free); 198 OPENSSL_free(session->tlsext_hostname); 199 OPENSSL_free(session->tlsext_tick); 200 OPENSSL_free(session->tlsext_signed_cert_timestamp_list); 201 OPENSSL_free(session->ocsp_response); 202 OPENSSL_free(session->psk_identity); 203 OPENSSL_cleanse(session, sizeof(*session)); 204 OPENSSL_free(session); 205} 206 207const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session, 208 unsigned *out_len) { 209 if (out_len != NULL) { 210 *out_len = session->session_id_length; 211 } 212 return session->session_id; 213} 214 215long SSL_SESSION_get_timeout(const SSL_SESSION *session) { 216 return session->timeout; 217} 218 219long SSL_SESSION_get_time(const SSL_SESSION *session) { 220 if (session == NULL) { 221 /* NULL should crash, but silently accept it here for compatibility. */ 222 return 0; 223 } 224 return session->time; 225} 226 227uint32_t SSL_SESSION_get_key_exchange_info(const SSL_SESSION *session) { 228 return session->key_exchange_info; 229} 230 231X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) { 232 return session->peer; 233} 234 235long SSL_SESSION_set_time(SSL_SESSION *session, long time) { 236 if (session == NULL) { 237 return 0; 238 } 239 240 session->time = time; 241 return time; 242} 243 244long SSL_SESSION_set_timeout(SSL_SESSION *session, long timeout) { 245 if (session == NULL) { 246 return 0; 247 } 248 249 session->timeout = timeout; 250 return 1; 251} 252 253int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx, 254 unsigned sid_ctx_len) { 255 if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { 256 OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); 257 return 0; 258 } 259 260 session->sid_ctx_length = sid_ctx_len; 261 memcpy(session->sid_ctx, sid_ctx, sid_ctx_len); 262 263 return 1; 264} 265 266SSL_SESSION *SSL_magic_pending_session_ptr(void) { 267 return (SSL_SESSION *)&g_pending_session_magic; 268} 269 270SSL_SESSION *SSL_get_session(const SSL *ssl) 271{ 272 /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ 273 return ssl->session; 274} 275 276SSL_SESSION *SSL_get1_session(SSL *ssl) { 277 /* variant of SSL_get_session: caller really gets something */ 278 return SSL_SESSION_up_ref(ssl->session); 279} 280 281int SSL_SESSION_get_ex_new_index(long argl, void *argp, 282 CRYPTO_EX_unused *unused, 283 CRYPTO_EX_dup *dup_func, 284 CRYPTO_EX_free *free_func) { 285 int index; 286 if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, 287 free_func)) { 288 return -1; 289 } 290 return index; 291} 292 293int SSL_SESSION_set_ex_data(SSL_SESSION *session, int idx, void *arg) { 294 return CRYPTO_set_ex_data(&session->ex_data, idx, arg); 295} 296 297void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) { 298 return CRYPTO_get_ex_data(&session->ex_data, idx); 299} 300 301int ssl_get_new_session(SSL *ssl, int is_server) { 302 if (ssl->mode & SSL_MODE_NO_SESSION_CREATION) { 303 OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_MAY_NOT_BE_CREATED); 304 return 0; 305 } 306 307 SSL_SESSION *session = SSL_SESSION_new(); 308 if (session == NULL) { 309 return 0; 310 } 311 312 /* If the context has a default timeout, use it over the default. */ 313 if (ssl->initial_ctx->session_timeout != 0) { 314 session->timeout = ssl->initial_ctx->session_timeout; 315 } 316 317 session->ssl_version = ssl->version; 318 319 if (is_server) { 320 if (ssl->tlsext_ticket_expected) { 321 /* Don't set session IDs for sessions resumed with tickets. This will keep 322 * them out of the session cache. */ 323 session->session_id_length = 0; 324 } else { 325 session->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; 326 if (!RAND_bytes(session->session_id, session->session_id_length)) { 327 goto err; 328 } 329 } 330 331 if (ssl->tlsext_hostname != NULL) { 332 session->tlsext_hostname = BUF_strdup(ssl->tlsext_hostname); 333 if (session->tlsext_hostname == NULL) { 334 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); 335 goto err; 336 } 337 } 338 } else { 339 session->session_id_length = 0; 340 } 341 342 if (ssl->sid_ctx_length > sizeof(session->sid_ctx)) { 343 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); 344 goto err; 345 } 346 memcpy(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length); 347 session->sid_ctx_length = ssl->sid_ctx_length; 348 349 session->verify_result = X509_V_OK; 350 351 SSL_SESSION_free(ssl->session); 352 ssl->session = session; 353 return 1; 354 355err: 356 SSL_SESSION_free(session); 357 return 0; 358} 359 360/* ssl_lookup_session looks up |session_id| in the session cache and sets 361 * |*out_session| to an |SSL_SESSION| object if found. The caller takes 362 * ownership of the result. */ 363static enum ssl_session_result_t ssl_lookup_session( 364 SSL *ssl, SSL_SESSION **out_session, const uint8_t *session_id, 365 size_t session_id_len) { 366 *out_session = NULL; 367 368 if (session_id_len == 0 || session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { 369 return ssl_session_success; 370 } 371 372 SSL_SESSION *session; 373 /* Try the internal cache, if it exists. */ 374 if (!(ssl->initial_ctx->session_cache_mode & 375 SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) { 376 SSL_SESSION data; 377 data.ssl_version = ssl->version; 378 data.session_id_length = session_id_len; 379 memcpy(data.session_id, session_id, session_id_len); 380 381 CRYPTO_MUTEX_lock_read(&ssl->initial_ctx->lock); 382 session = lh_SSL_SESSION_retrieve(ssl->initial_ctx->sessions, &data); 383 if (session != NULL) { 384 SSL_SESSION_up_ref(session); 385 } 386 /* TODO(davidben): This should probably move it to the front of the list. */ 387 CRYPTO_MUTEX_unlock(&ssl->initial_ctx->lock); 388 389 if (session != NULL) { 390 *out_session = session; 391 return ssl_session_success; 392 } 393 } 394 395 /* Fall back to the external cache, if it exists. */ 396 if (ssl->initial_ctx->get_session_cb == NULL) { 397 return ssl_session_success; 398 } 399 int copy = 1; 400 session = ssl->initial_ctx->get_session_cb(ssl, (uint8_t *)session_id, 401 session_id_len, ©); 402 if (session == NULL) { 403 return ssl_session_success; 404 } 405 if (session == SSL_magic_pending_session_ptr()) { 406 return ssl_session_retry; 407 } 408 409 /* Increment reference count now if the session callback asks us to do so 410 * (note that if the session structures returned by the callback are shared 411 * between threads, it must handle the reference count itself [i.e. copy == 412 * 0], or things won't be thread-safe). */ 413 if (copy) { 414 SSL_SESSION_up_ref(session); 415 } 416 417 /* Add the externally cached session to the internal cache if necessary. */ 418 if (!(ssl->initial_ctx->session_cache_mode & 419 SSL_SESS_CACHE_NO_INTERNAL_STORE)) { 420 SSL_CTX_add_session(ssl->initial_ctx, session); 421 } 422 423 *out_session = session; 424 return ssl_session_success; 425} 426 427enum ssl_session_result_t ssl_get_prev_session( 428 SSL *ssl, SSL_SESSION **out_session, int *out_send_ticket, 429 const struct ssl_early_callback_ctx *ctx) { 430 /* This is used only by servers. */ 431 assert(ssl->server); 432 SSL_SESSION *session = NULL; 433 int send_ticket = 0; 434 435 /* If tickets are disabled, always behave as if no tickets are present. */ 436 const uint8_t *ticket = NULL; 437 size_t ticket_len = 0; 438 const int tickets_supported = 439 !(SSL_get_options(ssl) & SSL_OP_NO_TICKET) && 440 ssl->version > SSL3_VERSION && 441 SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_session_ticket, 442 &ticket, &ticket_len); 443 if (tickets_supported) { 444 if (!tls_process_ticket(ssl, &session, &send_ticket, ticket, ticket_len, 445 ctx->session_id, ctx->session_id_len)) { 446 return ssl_session_error; 447 } 448 } else { 449 /* The client does not support session tickets, so the session ID should be 450 * used instead. */ 451 enum ssl_session_result_t lookup_ret = ssl_lookup_session( 452 ssl, &session, ctx->session_id, ctx->session_id_len); 453 if (lookup_ret != ssl_session_success) { 454 return lookup_ret; 455 } 456 } 457 458 if (session == NULL || 459 session->sid_ctx_length != ssl->sid_ctx_length || 460 memcmp(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length) != 0) { 461 goto no_session; 462 } 463 464 if ((ssl->verify_mode & SSL_VERIFY_PEER) && ssl->sid_ctx_length == 0) { 465 /* We can't be sure if this session is being used out of context, which is 466 * especially important for SSL_VERIFY_PEER. The application should have 467 * used SSL[_CTX]_set_session_id_context. 468 * 469 * For this error case, we generate an error instead of treating the event 470 * like a cache miss (otherwise it would be easy for applications to 471 * effectively disable the session cache by accident without anyone 472 * noticing). */ 473 OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); 474 goto fatal_error; 475 } 476 477 if (session->timeout < (long)(time(NULL) - session->time)) { 478 if (!tickets_supported) { 479 /* The session was from the cache, so remove it. */ 480 SSL_CTX_remove_session(ssl->initial_ctx, session); 481 } 482 goto no_session; 483 } 484 485 *out_session = session; 486 *out_send_ticket = send_ticket; 487 return ssl_session_success; 488 489fatal_error: 490 SSL_SESSION_free(session); 491 return ssl_session_error; 492 493no_session: 494 *out_session = NULL; 495 *out_send_ticket = tickets_supported; 496 SSL_SESSION_free(session); 497 return ssl_session_success; 498} 499 500int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) { 501 /* Although |session| is inserted into two structures (a doubly-linked list 502 * and the hash table), |ctx| only takes one reference. */ 503 SSL_SESSION_up_ref(session); 504 505 SSL_SESSION *old_session; 506 CRYPTO_MUTEX_lock_write(&ctx->lock); 507 if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) { 508 CRYPTO_MUTEX_unlock(&ctx->lock); 509 SSL_SESSION_free(session); 510 return 0; 511 } 512 513 if (old_session != NULL) { 514 if (old_session == session) { 515 /* |session| was already in the cache. */ 516 CRYPTO_MUTEX_unlock(&ctx->lock); 517 SSL_SESSION_free(old_session); 518 return 0; 519 } 520 521 /* There was a session ID collision. |old_session| must be removed from 522 * the linked list and released. */ 523 SSL_SESSION_list_remove(ctx, old_session); 524 SSL_SESSION_free(old_session); 525 } 526 527 SSL_SESSION_list_add(ctx, session); 528 529 /* Enforce any cache size limits. */ 530 if (SSL_CTX_sess_get_cache_size(ctx) > 0) { 531 while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { 532 if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) { 533 break; 534 } 535 } 536 } 537 538 CRYPTO_MUTEX_unlock(&ctx->lock); 539 return 1; 540} 541 542int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session) { 543 return remove_session_lock(ctx, session, 1); 544} 545 546static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) { 547 int ret = 0; 548 549 if (session != NULL && session->session_id_length != 0) { 550 if (lock) { 551 CRYPTO_MUTEX_lock_write(&ctx->lock); 552 } 553 SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions, 554 session); 555 if (found_session == session) { 556 ret = 1; 557 found_session = lh_SSL_SESSION_delete(ctx->sessions, session); 558 SSL_SESSION_list_remove(ctx, session); 559 } 560 561 if (lock) { 562 CRYPTO_MUTEX_unlock(&ctx->lock); 563 } 564 565 if (ret) { 566 found_session->not_resumable = 1; 567 if (ctx->remove_session_cb != NULL) { 568 ctx->remove_session_cb(ctx, found_session); 569 } 570 SSL_SESSION_free(found_session); 571 } 572 } 573 574 return ret; 575} 576 577int SSL_set_session(SSL *ssl, SSL_SESSION *session) { 578 if (ssl->session == session) { 579 return 1; 580 } 581 582 SSL_SESSION_free(ssl->session); 583 ssl->session = session; 584 if (session != NULL) { 585 SSL_SESSION_up_ref(session); 586 ssl->verify_result = session->verify_result; 587 } 588 589 return 1; 590} 591 592long SSL_CTX_set_timeout(SSL_CTX *ctx, long timeout) { 593 if (ctx == NULL) { 594 return 0; 595 } 596 597 long old_timeout = ctx->session_timeout; 598 ctx->session_timeout = timeout; 599 return old_timeout; 600} 601 602long SSL_CTX_get_timeout(const SSL_CTX *ctx) { 603 if (ctx == NULL) { 604 return 0; 605 } 606 607 return ctx->session_timeout; 608} 609 610typedef struct timeout_param_st { 611 SSL_CTX *ctx; 612 long time; 613 LHASH_OF(SSL_SESSION) *cache; 614} TIMEOUT_PARAM; 615 616static void timeout_doall_arg(SSL_SESSION *session, void *void_param) { 617 TIMEOUT_PARAM *param = void_param; 618 619 if (param->time == 0 || 620 param->time > (session->time + session->timeout)) { 621 /* timeout */ 622 /* The reason we don't call SSL_CTX_remove_session() is to 623 * save on locking overhead */ 624 (void) lh_SSL_SESSION_delete(param->cache, session); 625 SSL_SESSION_list_remove(param->ctx, session); 626 session->not_resumable = 1; 627 if (param->ctx->remove_session_cb != NULL) { 628 param->ctx->remove_session_cb(param->ctx, session); 629 } 630 SSL_SESSION_free(session); 631 } 632} 633 634void SSL_CTX_flush_sessions(SSL_CTX *ctx, long time) { 635 TIMEOUT_PARAM tp; 636 637 tp.ctx = ctx; 638 tp.cache = ctx->sessions; 639 if (tp.cache == NULL) { 640 return; 641 } 642 tp.time = time; 643 CRYPTO_MUTEX_lock_write(&ctx->lock); 644 lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp); 645 CRYPTO_MUTEX_unlock(&ctx->lock); 646} 647 648int ssl_clear_bad_session(SSL *ssl) { 649 if (ssl->session != NULL && !(ssl->shutdown & SSL_SENT_SHUTDOWN) && 650 !SSL_in_init(ssl)) { 651 SSL_CTX_remove_session(ssl->ctx, ssl->session); 652 return 1; 653 } 654 655 return 0; 656} 657 658/* locked by SSL_CTX in the calling function */ 659static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session) { 660 if (session->next == NULL || session->prev == NULL) { 661 return; 662 } 663 664 if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) { 665 /* last element in list */ 666 if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) { 667 /* only one element in list */ 668 ctx->session_cache_head = NULL; 669 ctx->session_cache_tail = NULL; 670 } else { 671 ctx->session_cache_tail = session->prev; 672 session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail); 673 } 674 } else { 675 if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) { 676 /* first element in list */ 677 ctx->session_cache_head = session->next; 678 session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head); 679 } else { /* middle of list */ 680 session->next->prev = session->prev; 681 session->prev->next = session->next; 682 } 683 } 684 session->prev = session->next = NULL; 685} 686 687static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session) { 688 if (session->next != NULL && session->prev != NULL) { 689 SSL_SESSION_list_remove(ctx, session); 690 } 691 692 if (ctx->session_cache_head == NULL) { 693 ctx->session_cache_head = session; 694 ctx->session_cache_tail = session; 695 session->prev = (SSL_SESSION *)&(ctx->session_cache_head); 696 session->next = (SSL_SESSION *)&(ctx->session_cache_tail); 697 } else { 698 session->next = ctx->session_cache_head; 699 session->next->prev = session; 700 session->prev = (SSL_SESSION *)&(ctx->session_cache_head); 701 ctx->session_cache_head = session; 702 } 703} 704 705void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, 706 int (*cb)(SSL *ssl, SSL_SESSION *session)) { 707 ctx->new_session_cb = cb; 708} 709 710int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *session) { 711 return ctx->new_session_cb; 712} 713 714void SSL_CTX_sess_set_remove_cb( 715 SSL_CTX *ctx, void (*cb)(SSL_CTX *ctx, SSL_SESSION *session)) { 716 ctx->remove_session_cb = cb; 717} 718 719void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX *ctx, 720 SSL_SESSION *session) { 721 return ctx->remove_session_cb; 722} 723 724void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, 725 SSL_SESSION *(*cb)(SSL *ssl, 726 uint8_t *id, int id_len, 727 int *out_copy)) { 728 ctx->get_session_cb = cb; 729} 730 731SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))( 732 SSL *ssl, uint8_t *id, int id_len, int *out_copy) { 733 return ctx->get_session_cb; 734} 735 736void SSL_CTX_set_info_callback( 737 SSL_CTX *ctx, void (*cb)(const SSL *ssl, int type, int value)) { 738 ctx->info_callback = cb; 739} 740 741void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type, 742 int value) { 743 return ctx->info_callback; 744} 745 746void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, 747 X509 **out_x509, 748 EVP_PKEY **out_pkey)) { 749 ctx->client_cert_cb = cb; 750} 751 752int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **out_x509, 753 EVP_PKEY **out_pkey) { 754 return ctx->client_cert_cb; 755} 756 757void SSL_CTX_set_channel_id_cb(SSL_CTX *ctx, 758 void (*cb)(SSL *ssl, EVP_PKEY **pkey)) { 759 ctx->channel_id_cb = cb; 760} 761 762void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL *ssl, EVP_PKEY **pkey) { 763 return ctx->channel_id_cb; 764} 765