More ssl_session_dup fixes
authorMatt Caswell <matt@openssl.org>
Thu, 11 Jun 2015 00:30:06 +0000 (01:30 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 11 Jun 2015 09:18:32 +0000 (10:18 +0100)
Fix error handling in ssl_session_dup, as well as incorrect setting up of
the session ticket. Follow on from CVE-2015-1791.

Thanks to LibreSSL project for reporting these issues.

Conflicts:
ssl/ssl_sess.c

Reviewed-by: Tim Hudson <tjh@openssl.org>
ssl/ssl_sess.c

index d3bac0bb9f4444ebf77d767fc061e84f5b11827e..e1695ab40601ab570dabe70feb6fe65bbc2c7702 100644 (file)
@@ -149,12 +149,22 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
     }
     memcpy(dest, src, sizeof(*dest));
 
-#ifndef OPENSSL_NO_KRB5
-    dest->krb5_client_princ_len = src->krb5_client_princ_len;
-    if (src->krb5_client_princ_len > 0)
-        memcpy(dest->krb5_client_princ, src->krb5_client_princ,
-               src->krb5_client_princ_len);
+    /*
+     * Set the various pointers to NULL so that we can call SSL_SESSION_free in
+     * the case of an error whilst halfway through constructing dest
+     */
+    dest->ciphers = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+    dest->tlsext_hostname = NULL;
 #endif
+    dest->tlsext_tick = NULL;
+    memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+    /* We deliberately don't copy the prev and next pointers */
+    dest->prev = NULL;
+    dest->next = NULL;
+
+    dest->references = 1;
 
     if (src->sess_cert != NULL)
         CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
@@ -162,14 +172,10 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
     if (src->peer != NULL)
         CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
 
-    dest->references = 1;
-
     if(src->ciphers != NULL) {
         dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
         if (dest->ciphers == NULL)
             goto err;
-    } else {
-        dest->ciphers = NULL;
     }
 
     if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
@@ -177,27 +183,22 @@ SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
         goto err;
     }
 
-    /* We deliberately don't copy the prev and next pointers */
-    dest->prev = NULL;
-    dest->next = NULL;
-
 #ifndef OPENSSL_NO_TLSEXT
     if (src->tlsext_hostname) {
         dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
         if (dest->tlsext_hostname == NULL) {
             goto err;
         }
-    } else {
-        dest->tlsext_hostname = NULL;
     }
 #endif
 
     if (ticket != 0) {
-        dest->tlsext_tick_lifetime_hint = src->tlsext_tick_lifetime_hint;
-        dest->tlsext_ticklen = src->tlsext_ticklen;
-        if((dest->tlsext_tick = OPENSSL_malloc(src->tlsext_ticklen)) == NULL) {
+        dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
+        if(dest->tlsext_tick == NULL)
             goto err;
-        }
+    } else {
+        dest->tlsext_tick_lifetime_hint = 0;
+        dest->tlsext_ticklen = 0;
     }
 
     return dest;