X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_sess.c;h=3b9a9f75359e59b77a1179b26dccc3500673a404;hp=09d0193f06bb7f07fa9d3363a7b3e07db323e88e;hb=6d8b3dce7c8feee8aa9107e2ffcc588c782a6113;hpb=2a056de832a62f9c6da67779f3764f004df6fdb0 diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 09d0193f06..3b9a9f7535 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -1,4 +1,3 @@ -/* ssl/ssl_sess.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -138,9 +137,7 @@ #include #include #include -#ifndef OPENSSL_NO_ENGINE -# include -#endif +#include #include "ssl_locl.h" static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); @@ -162,12 +159,12 @@ SSL_SESSION *SSL_get1_session(SSL *ssl) * somebody doesn't free ssl->session between when we check it's non-null * and when we up the reference count. */ - CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION); + CRYPTO_THREAD_read_lock(ssl->lock); sess = ssl->session; if (sess) - sess->references++; - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION); - return (sess); + SSL_SESSION_up_ref(sess); + CRYPTO_THREAD_unlock(ssl->lock); + return sess; } int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) @@ -187,15 +184,26 @@ SSL_SESSION *SSL_SESSION_new(void) ss = OPENSSL_zalloc(sizeof(*ss)); if (ss == NULL) { SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); - return (NULL); + return NULL; } ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ ss->references = 1; ss->timeout = 60 * 5 + 4; /* 5 minute timeout by default */ ss->time = (unsigned long)time(NULL); - CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); - return (ss); + ss->lock = CRYPTO_THREAD_lock_new(); + if (ss->lock == NULL) { + SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ss); + return NULL; + } + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data)) { + CRYPTO_THREAD_lock_free(ss->lock); + OPENSSL_free(ss); + return NULL; + } + return ss; } /* @@ -238,6 +246,10 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) dest->references = 1; + dest->lock = CRYPTO_THREAD_lock_new(); + if (dest->lock == NULL) + goto err; + if (src->peer != NULL) X509_up_ref(src->peer); @@ -438,12 +450,14 @@ int ssl_get_new_session(SSL *s, int session) } /* Choose which callback will set the session ID */ - CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_THREAD_read_lock(s->lock); + CRYPTO_THREAD_read_lock(s->session_ctx->lock); if (s->generate_session_id) cb = s->generate_session_id; else if (s->session_ctx->generate_session_id) cb = s->session_ctx->generate_session_id; - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_THREAD_unlock(s->session_ctx->lock); + CRYPTO_THREAD_unlock(s->lock); /* Choose a session ID */ tmp = ss->session_id_length; if (!cb(s, ss->session_id, &tmp)) { @@ -529,12 +543,8 @@ int ssl_get_prev_session(SSL *s, const PACKET *ext, const PACKET *session_id) int fatal = 0; int try_session_cache = 1; int r; - size_t len = PACKET_remaining(session_id); - if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) - goto err; - - if (len == 0) + if (PACKET_remaining(session_id) == 0) try_session_cache = 0; /* sets s->tlsext_ticket_expected and extended master secret flag */ @@ -567,13 +577,13 @@ int ssl_get_prev_session(SSL *s, const PACKET *ext, const PACKET *session_id) goto err; } data.session_id_length = local_len; - CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_THREAD_read_lock(s->session_ctx->lock); ret = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data); if (ret != NULL) { /* don't allow other threads to steal it: */ - CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_SSL_SESSION); + SSL_SESSION_up_ref(ret); } - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_THREAD_unlock(s->session_ctx->lock); if (ret == NULL) s->session_ctx->stats.sess_miss++; } @@ -581,13 +591,9 @@ int ssl_get_prev_session(SSL *s, const PACKET *ext, const PACKET *session_id) if (try_session_cache && ret == NULL && s->session_ctx->get_session_cb != NULL) { int copy = 1; - /* The user callback takes a non-const pointer, so grab a local copy. */ - unsigned char *sid = NULL; - size_t sid_len; - if (!PACKET_memdup(session_id, &sid, &sid_len)) - goto err; - ret = s->session_ctx->get_session_cb(s, sid, sid_len, ©); - OPENSSL_free(sid); + ret = s->session_ctx->get_session_cb(s, PACKET_data(session_id), + PACKET_remaining(session_id), + ©); if (ret != NULL) { s->session_ctx->stats.sess_cb_hit++; @@ -600,7 +606,7 @@ int ssl_get_prev_session(SSL *s, const PACKET *ext, const PACKET *session_id) * thread-safe). */ if (copy) - CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_SSL_SESSION); + SSL_SESSION_up_ref(ret); /* * Add the externally cached session to the internal cache as @@ -723,12 +729,12 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) * it has two ways of access: each session is in a doubly linked list and * an lhash */ - CRYPTO_add(&c->references, 1, CRYPTO_LOCK_SSL_SESSION); + SSL_SESSION_up_ref(c); /* * if session c is in already in cache, we take back the increment later */ - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_THREAD_write_lock(ctx->lock); s = lh_SSL_SESSION_insert(ctx->sessions, c); /* @@ -778,8 +784,8 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) } } } - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); - return (ret); + CRYPTO_THREAD_unlock(ctx->lock); + return ret; } int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) @@ -794,7 +800,7 @@ static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) if ((c != NULL) && (c->session_id_length != 0)) { if (lck) - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_THREAD_write_lock(ctx->lock); if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) == c) { ret = 1; r = lh_SSL_SESSION_delete(ctx->sessions, c); @@ -802,7 +808,7 @@ static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) } if (lck) - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_THREAD_unlock(ctx->lock); if (ret) { r->not_resumable = 1; @@ -822,18 +828,11 @@ void SSL_SESSION_free(SSL_SESSION *ss) if (ss == NULL) return; - i = CRYPTO_add(&ss->references, -1, CRYPTO_LOCK_SSL_SESSION); -#ifdef REF_PRINT - REF_PRINT("SSL_SESSION", ss); -#endif + CRYPTO_atomic_add(&ss->references, -1, &i, ss->lock); + REF_PRINT_COUNT("SSL_SESSION", ss); if (i > 0) return; -#ifdef REF_CHECK - if (i < 0) { - fprintf(stderr, "SSL_SESSION_free, bad reference count\n"); - abort(); /* ok */ - } -#endif + REF_ASSERT_ISNT(i < 0); CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); @@ -857,41 +856,41 @@ void SSL_SESSION_free(SSL_SESSION *ss) #ifndef OPENSSL_NO_SRP OPENSSL_free(ss->srp_username); #endif + CRYPTO_THREAD_lock_free(ss->lock); OPENSSL_clear_free(ss, sizeof(*ss)); } +int SSL_SESSION_up_ref(SSL_SESSION *ss) +{ + int i; + + if (CRYPTO_atomic_add(&ss->references, 1, &i, ss->lock) <= 0) + return 0; + + REF_PRINT_COUNT("SSL_SESSION", ss); + REF_ASSERT_ISNT(i < 2); + return ((i > 1) ? 1 : 0); +} + int SSL_set_session(SSL *s, SSL_SESSION *session) { int ret = 0; - const SSL_METHOD *meth; - if (session != NULL) { - meth = s->ctx->method->get_ssl_method(session->ssl_version); - if (meth == NULL) - meth = s->method->get_ssl_method(session->ssl_version); - if (meth == NULL) { - SSLerr(SSL_F_SSL_SET_SESSION, SSL_R_UNABLE_TO_FIND_SSL_METHOD); - return (0); - } - - if (meth != s->method) { - if (!SSL_set_ssl_method(s, meth)) + if (s->ctx->method != s->method) { + if (!SSL_set_ssl_method(s, s->ctx->method)) return (0); } - /* CRYPTO_w_lock(CRYPTO_LOCK_SSL); */ - CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION); + SSL_SESSION_up_ref(session); SSL_SESSION_free(s->session); s->session = session; s->verify_result = s->session->verify_result; - /* CRYPTO_w_unlock(CRYPTO_LOCK_SSL); */ ret = 1; } else { SSL_SESSION_free(s->session); s->session = NULL; - meth = s->ctx->method; - if (meth != s->method) { - if (!SSL_set_ssl_method(s, meth)) + if (s->ctx->method != s->method) { + if (!SSL_set_ssl_method(s, s->ctx->method)) return (0); } ret = 1; @@ -929,6 +928,11 @@ long SSL_SESSION_set_time(SSL_SESSION *s, long t) return (t); } +const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s) +{ + return s->tlsext_hostname; +} + int SSL_SESSION_has_ticket(const SSL_SESSION *s) { return (s->tlsext_ticklen > 0) ? 1 : 0; @@ -1072,12 +1076,12 @@ void SSL_CTX_flush_sessions(SSL_CTX *s, long t) if (tp.cache == NULL) return; tp.time = t; - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_THREAD_write_lock(s->lock); i = CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load; CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load = 0; lh_SSL_SESSION_doall_TIMEOUT_PARAM(tp.cache, timeout_cb, &tp); CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load = i; - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_THREAD_unlock(s->lock); } int ssl_clear_bad_session(SSL *s) @@ -1163,14 +1167,14 @@ void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (SSL_CTX *ctx, void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*cb) (struct ssl_st *ssl, - unsigned char *data, int len, - int *copy)) + const unsigned char *data, + int len, int *copy)) { ctx->get_session_cb = cb; } SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (SSL *ssl, - unsigned char *data, + const unsigned char *data, int len, int *copy) { return ctx->get_session_cb; }