X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssl_sess.c;h=b17fcdcb548342159688267751e3737031e87bb0;hp=77c917f38a0d6d9f5dc69c52ddb60a0d97fb84ec;hb=db0f35dda18403accabe98e7780f3dfc516f49de;hpb=534a43ffeaec03e50768ccf84d431f96f11256e3 diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 77c917f38a..b17fcdcb54 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -46,12 +46,12 @@ static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s); static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); /* - * TODO(TLS1.3): SSL_get_session() and SSL_get1_session() are problematic in - * TLS1.3 because, unlike in earlier protocol versions, the session ticket - * may not have been sent yet even though a handshake has finished. The session - * ticket data could come in sometime later...or even change if multiple session - * ticket messages are sent from the server. We need to work out how to deal - * with this. + * SSL_get_session() and SSL_get1_session() are problematic in TLS1.3 because, + * unlike in earlier protocol versions, the session ticket may not have been + * sent yet even though a handshake has finished. The session ticket data could + * come in sometime later...or even change if multiple session ticket messages + * are sent from the server. The preferred way for applications to obtain + * a resumable session is to use SSL_CTX_sess_set_new_cb(). */ SSL_SESSION *SSL_get_session(const SSL *ssl) @@ -151,6 +151,8 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) #ifndef OPENSSL_NO_SRP dest->srp_username = NULL; #endif + dest->peer_chain = NULL; + dest->peer = NULL; memset(&dest->ex_data, 0, sizeof(dest->ex_data)); /* We deliberately don't copy the prev and next pointers */ @@ -163,8 +165,14 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) if (dest->lock == NULL) goto err; - if (src->peer != NULL) - X509_up_ref(src->peer); + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data)) + goto err; + + if (src->peer != NULL) { + if (!X509_up_ref(src->peer)) + goto err; + dest->peer = src->peer; + } if (src->peer_chain != NULL) { dest->peer_chain = X509_chain_up_ref(src->peer_chain); @@ -220,7 +228,7 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) } #endif - if (ticket != 0) { + if (ticket != 0 && src->ext.tick != NULL) { dest->ext.tick = OPENSSL_memdup(src->ext.tick, src->ext.ticklen); if (dest->ext.tick == NULL) @@ -458,20 +466,21 @@ int ssl_get_new_session(SSL *s, int session) * - Both for new and resumed sessions, s->ext.ticket_expected is set to 1 * if the server should issue a new session ticket (to 0 otherwise). */ -int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) +int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello, int *al) { /* This is used only by servers. */ SSL_SESSION *ret = NULL; int fatal = 0; int try_session_cache = 0; - int r; + TICKET_RETURN r; if (SSL_IS_TLS13(s)) { - int al; - - if (!tls_parse_extension(s, TLSEXT_IDX_psk, EXT_CLIENT_HELLO, - hello->pre_proc_exts, NULL, 0, &al)) + if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes, + SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts, + NULL, 0, al) + || !tls_parse_extension(s, TLSEXT_IDX_psk, SSL_EXT_CLIENT_HELLO, + hello->pre_proc_exts, NULL, 0, al)) return -1; ret = s->session; @@ -479,18 +488,18 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) /* sets s->ext.ticket_expected */ r = tls_get_ticket_from_client(s, hello, &ret); switch (r) { - case -1: /* Error during processing */ + case TICKET_FATAL_ERR_MALLOC: + case TICKET_FATAL_ERR_OTHER: fatal = 1; goto err; - case 0: /* No ticket found */ - case 1: /* Zero length ticket found */ + case TICKET_NONE: + case TICKET_EMPTY: try_session_cache = 1; - break; /* Ok to carry on processing session id. */ - case 2: /* Ticket found but not decrypted. */ - case 3: /* Ticket decrypted, *ret has been set. */ break; - default: - abort(); + case TICKET_NO_DECRYPT: + case TICKET_SUCCESS: + case TICKET_SUCCESS_RENEW: + break; } } @@ -501,7 +510,6 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) SSL_SESSION data; data.ssl_version = s->version; - memset(data.session_id, 0, sizeof(data.session_id)); memcpy(data.session_id, hello->session_id, hello->session_id_len); data.session_id_length = hello->session_id_len; @@ -603,7 +611,7 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) /* If old session includes extms, but new does not: abort handshake */ if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)) { SSLerr(SSL_F_SSL_GET_PREV_SESSION, SSL_R_INCONSISTENT_EXTMS); - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); fatal = 1; goto err; } @@ -620,13 +628,12 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) s->session_ctx->stats.sess_hit++; s->verify_result = s->session->verify_result; - return 1; err: if (ret != NULL) { SSL_SESSION_free(ret); - /* In TLSv1.3 we already set s->session, so better NULL it out */ + /* In TLSv1.3 s->session was already set to ret, so we NULL it out */ if (SSL_IS_TLS13(s)) s->session = NULL; @@ -638,10 +645,12 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello) s->ext.ticket_expected = 1; } } - if (fatal) + if (fatal) { + *al = SSL_AD_INTERNAL_ERROR; return -1; - else - return 0; + } + + return 0; } int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) @@ -791,6 +800,7 @@ void SSL_SESSION_free(SSL_SESSION *ss) #ifndef OPENSSL_NO_SRP OPENSSL_free(ss->srp_username); #endif + OPENSSL_free(ss->ext.alpn_selected); CRYPTO_THREAD_lock_free(ss->lock); OPENSSL_clear_free(ss, sizeof(*ss)); } @@ -834,7 +844,8 @@ int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, return 0; } s->session_id_length = sid_len; - memcpy(s->session_id, sid, sid_len); + if (sid != s->session_id) + memcpy(s->session_id, sid, sid_len); return 1; } @@ -901,6 +912,11 @@ void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick, *tick = s->ext.tick; } +uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s) +{ + return s->ext.max_early_data; +} + X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) { return s->peer; @@ -915,11 +931,22 @@ int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, return 0; } s->sid_ctx_length = sid_ctx_len; - memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); + if (sid_ctx != s->sid_ctx) + memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); return 1; } +int SSL_SESSION_is_resumable(const SSL_SESSION *s) +{ + /* + * In the case of EAP-FAST, we can have a pre-shared "ticket" without a + * session ID. + */ + return !s->not_resumable + && (s->session_id_length > 0 || s->ext.ticklen > 0); +} + long SSL_CTX_set_timeout(SSL_CTX *s, long t) { long l;