summaryrefslogtreecommitdiffstats
path: root/ssl/s3_clnt.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2015-05-18 16:27:48 +0100
committerMatt Caswell <matt@openssl.org>2015-06-02 12:44:40 +0100
commit939b4960276b040fc0ed52232238fcc9e2e9ec21 (patch)
treecefe73e09d05363aa05e229b9ee40090fda12f93 /ssl/s3_clnt.c
parentcce3e4adb78a8d3eeb6e0e4efe332fcc5d75f615 (diff)
Fix race condition in NewSessionTicket
If a NewSessionTicket is received by a multi-threaded client when attempting to reuse a previous ticket then a race condition can occur potentially leading to a double free of the ticket data. CVE-2015-1791 This also fixes RT#3808 where a session ID is changed for a session already in the client session cache. Since the session ID is the key to the cache this breaks the cache access. Parts of this patch were inspired by this Akamai change: https://github.com/akamai/openssl/commit/c0bf69a791239ceec64509f9f19fcafb2461b0d3 Reviewed-by: Rich Salz <rsalz@openssl.org> (cherry picked from commit 27c76b9b8010b536687318739c6f631ce4194688) Conflicts: ssl/ssl.h ssl/ssl_err.c
Diffstat (limited to 'ssl/s3_clnt.c')
-rw-r--r--ssl/s3_clnt.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 012905b046..eb7b94eac9 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -2139,6 +2139,38 @@ int ssl3_get_new_session_ticket(SSL *s)
}
p = d = (unsigned char *)s->init_msg;
+
+ if (s->session->session_id_length > 0) {
+ int i = s->session_ctx->session_cache_mode;
+ SSL_SESSION *new_sess;
+ /*
+ * We reused an existing session, so we need to replace it with a new
+ * one
+ */
+ if (i & SSL_SESS_CACHE_CLIENT) {
+ /*
+ * Remove the old session from the cache
+ */
+ if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
+ if (s->session_ctx->remove_session_cb != NULL)
+ s->session_ctx->remove_session_cb(s->session_ctx,
+ s->session);
+ } else {
+ /* We carry on if this fails */
+ SSL_CTX_remove_session(s->session_ctx, s->session);
+ }
+ }
+
+ if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+
+ SSL_SESSION_free(s->session);
+ s->session = new_sess;
+ }
+
n2l(p, s->session->tlsext_tick_lifetime_hint);
n2s(p, ticklen);
/* ticket_lifetime_hint + ticket_length + ticket */