GH365: Missing #ifdef rename.
[openssl.git] / ssl / ssl_sess.c
index ed17429b07ff3089f69770aa7a725a4a9436aa96..26a3c43f246145406e987c80995c212eaf613f03 100644 (file)
@@ -193,12 +193,12 @@ SSL_SESSION *SSL_SESSION_new(void)
 {
     SSL_SESSION *ss;
 
-    ss = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
+    ss = OPENSSL_malloc(sizeof(*ss));
     if (ss == NULL) {
         SSLerr(SSL_F_SSL_SESSION_NEW, ERR_R_MALLOC_FAILURE);
         return (0);
     }
-    memset(ss, 0, sizeof(SSL_SESSION));
+    memset(ss, 0, sizeof(*ss));
 
     ss->verify_result = 1;      /* avoid 0 (= X509_V_OK) just in case */
     ss->references = 1;
@@ -207,14 +207,12 @@ SSL_SESSION *SSL_SESSION_new(void)
     ss->prev = NULL;
     ss->next = NULL;
     ss->compress_meth = 0;
-#ifndef OPENSSL_NO_TLSEXT
     ss->tlsext_hostname = NULL;
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
     ss->tlsext_ecpointformatlist_length = 0;
     ss->tlsext_ecpointformatlist = NULL;
     ss->tlsext_ellipticcurvelist_length = 0;
     ss->tlsext_ellipticcurvelist = NULL;
-# endif
 #endif
     CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 #ifndef OPENSSL_NO_PSK
@@ -227,6 +225,129 @@ SSL_SESSION *SSL_SESSION_new(void)
     return (ss);
 }
 
+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+    SSL_SESSION *dest;
+
+    dest = OPENSSL_malloc(sizeof(*src));
+    if (dest == NULL) {
+        goto err;
+    }
+    memcpy(dest, src, sizeof(*dest));
+
+    /*
+     * 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
+     */
+#ifndef OPENSSL_NO_PSK
+    dest->psk_identity_hint = NULL;
+    dest->psk_identity = NULL;
+#endif
+    dest->ciphers = NULL;
+    dest->tlsext_hostname = NULL;
+#ifndef OPENSSL_NO_EC
+    dest->tlsext_ecpointformatlist = NULL;
+    dest->tlsext_ellipticcurvelist = NULL;
+#endif
+    dest->tlsext_tick = NULL;
+#ifndef OPENSSL_NO_SRP
+    dest->srp_username = NULL;
+#endif
+    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->peer != NULL)
+        CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
+
+    if (src->peer_chain != NULL) {
+        dest->peer_chain = X509_chain_up_ref(src->peer_chain);
+        if (dest->peer_chain == NULL)
+            goto err;
+    }
+
+#ifndef OPENSSL_NO_PSK
+    if (src->psk_identity_hint) {
+        dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint);
+        if (dest->psk_identity_hint == NULL) {
+            goto err;
+        }
+    }
+    if (src->psk_identity) {
+        dest->psk_identity = BUF_strdup(src->psk_identity);
+        if (dest->psk_identity == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    if(src->ciphers != NULL) {
+        dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+        if (dest->ciphers == NULL)
+            goto err;
+    }
+
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+                                            &dest->ex_data, &src->ex_data)) {
+        goto err;
+    }
+
+    if (src->tlsext_hostname) {
+        dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
+        if (dest->tlsext_hostname == NULL) {
+            goto err;
+        }
+    }
+#ifndef OPENSSL_NO_EC
+    if (src->tlsext_ecpointformatlist) {
+        dest->tlsext_ecpointformatlist =
+            BUF_memdup(src->tlsext_ecpointformatlist,
+                       src->tlsext_ecpointformatlist_length);
+        if (dest->tlsext_ecpointformatlist == NULL)
+            goto err;
+    }
+    if (src->tlsext_ellipticcurvelist) {
+        dest->tlsext_ellipticcurvelist =
+            BUF_memdup(src->tlsext_ellipticcurvelist,
+                       src->tlsext_ellipticcurvelist_length);
+        if (dest->tlsext_ellipticcurvelist == NULL)
+            goto err;
+    }
+#endif
+
+    if (ticket != 0) {
+        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;
+    }
+
+#ifndef OPENSSL_NO_SRP
+    if (src->srp_username) {
+        dest->srp_username = BUF_strdup(src->srp_username);
+        if (dest->srp_username == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    return dest;
+err:
+    SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
+    SSL_SESSION_free(dest);
+    return NULL;
+}
+
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
                                         unsigned int *len)
 {
@@ -257,7 +378,7 @@ static int def_generate_session_id(const SSL *ssl, unsigned char *id,
 {
     unsigned int retry = 0;
     do
-        if (RAND_pseudo_bytes(id, *id_len) <= 0)
+        if (RAND_bytes(id, *id_len) <= 0)
             return 0;
     while (SSL_has_matching_session_id(ssl, id, *id_len) &&
            (++retry < MAX_SESS_ID_ATTEMPTS)) ;
@@ -292,10 +413,8 @@ int ssl_get_new_session(SSL *s, int session)
     else
         ss->timeout = s->session_ctx->session_timeout;
 
-    if (s->session != NULL) {
-        SSL_SESSION_free(s->session);
-        s->session = NULL;
-    }
+    SSL_SESSION_free(s->session);
+    s->session = NULL;
 
     if (session) {
         if (s->version == SSL3_VERSION) {
@@ -324,27 +443,27 @@ int ssl_get_new_session(SSL *s, int session)
             SSL_SESSION_free(ss);
             return (0);
         }
-#ifndef OPENSSL_NO_TLSEXT
-                /*-
-                 * If RFC5077 ticket, use empty session ID (as server).
-                 * Note that:
-                 * (a) ssl_get_prev_session() does lookahead into the
-                 *     ClientHello extensions to find the session ticket.
-                 *     When ssl_get_prev_session() fails, s3_srvr.c calls
-                 *     ssl_get_new_session() in ssl3_get_client_hello().
-                 *     At that point, it has not yet parsed the extensions,
-                 *     however, because of the lookahead, it already knows
-                 *     whether a ticket is expected or not.
-                 *
-                 * (b) s3_clnt.c calls ssl_get_new_session() before parsing
-                 *     ServerHello extensions, and before recording the session
-                 *     ID received from the server, so this block is a noop.
-                 */
+
+        /*-
+         * If RFC5077 ticket, use empty session ID (as server).
+         * Note that:
+         * (a) ssl_get_prev_session() does lookahead into the
+         *     ClientHello extensions to find the session ticket.
+         *     When ssl_get_prev_session() fails, s3_srvr.c calls
+         *     ssl_get_new_session() in ssl3_get_client_hello().
+         *     At that point, it has not yet parsed the extensions,
+         *     however, because of the lookahead, it already knows
+         *     whether a ticket is expected or not.
+         *
+         * (b) s3_clnt.c calls ssl_get_new_session() before parsing
+         *     ServerHello extensions, and before recording the session
+         *     ID received from the server, so this block is a noop.
+         */
         if (s->tlsext_ticket_expected) {
             ss->session_id_length = 0;
             goto sess_id_done;
         }
-#endif
+
         /* Choose which callback will set the session ID */
         CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
         if (s->generate_session_id)
@@ -380,7 +499,7 @@ int ssl_get_new_session(SSL *s, int session)
             SSL_SESSION_free(ss);
             return (0);
         }
-#ifndef OPENSSL_NO_TLSEXT
+
  sess_id_done:
         if (s->tlsext_hostname) {
             ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
@@ -390,7 +509,6 @@ int ssl_get_new_session(SSL *s, int session)
                 return 0;
             }
         }
-#endif
     } else {
         ss->session_id_length = 0;
     }
@@ -429,27 +547,24 @@ int ssl_get_new_session(SSL *s, int session)
  *   - Both for new and resumed sessions, s->tlsext_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, unsigned char *session_id, int len,
-                         const unsigned char *limit)
+int ssl_get_prev_session(SSL *s, PACKET *pkt, unsigned char *session_id,
+                         int len)
 {
     /* This is used only by servers. */
 
     SSL_SESSION *ret = NULL;
     int fatal = 0;
     int try_session_cache = 1;
-#ifndef OPENSSL_NO_TLSEXT
     int r;
-#endif
 
-    if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
+    if (len < 0 || len > SSL_MAX_SSL_SESSION_ID_LENGTH)
         goto err;
 
     if (len == 0)
         try_session_cache = 0;
 
-#ifndef OPENSSL_NO_TLSEXT
     /* sets s->tlsext_ticket_expected */
-    r = tls1_process_ticket(s, session_id, len, limit, &ret);
+    r = tls1_process_ticket(s, pkt, session_id, len, &ret);
     switch (r) {
     case -1:                   /* Error during processing */
         fatal = 1;
@@ -464,7 +579,6 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
     default:
         abort();
     }
-#endif
 
     if (try_session_cache &&
         ret == NULL &&
@@ -510,12 +624,14 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
              */
             if (!
                 (s->session_ctx->session_cache_mode &
-                 SSL_SESS_CACHE_NO_INTERNAL_STORE))
+                 SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
                 /*
                  * The following should not return 1, otherwise, things are
                  * very strange
                  */
-                SSL_CTX_add_session(s->session_ctx, ret);
+                if (SSL_CTX_add_session(s->session_ctx, ret))
+                    goto err;
+            }
         }
     }
 
@@ -576,8 +692,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
 
     s->session_ctx->stats.sess_hit++;
 
-    if (s->session != NULL)
-        SSL_SESSION_free(s->session);
+    SSL_SESSION_free(s->session);
     s->session = ret;
     s->verify_result = s->session->verify_result;
     return 1;
@@ -585,7 +700,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
  err:
     if (ret != NULL) {
         SSL_SESSION_free(ret);
-#ifndef OPENSSL_NO_TLSEXT
+
         if (!try_session_cache) {
             /*
              * The session was from a ticket, so we should issue a ticket for
@@ -593,7 +708,6 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
              */
             s->tlsext_ticket_expected = 1;
         }
-#endif
     }
     if (fatal)
         return -1;
@@ -727,38 +841,25 @@ void SSL_SESSION_free(SSL_SESSION *ss)
 
     OPENSSL_cleanse(ss->master_key, sizeof ss->master_key);
     OPENSSL_cleanse(ss->session_id, sizeof ss->session_id);
-    if (ss->sess_cert != NULL)
-        ssl_sess_cert_free(ss->sess_cert);
-    if (ss->peer != NULL)
-        X509_free(ss->peer);
-    if (ss->ciphers != NULL)
-        sk_SSL_CIPHER_free(ss->ciphers);
-#ifndef OPENSSL_NO_TLSEXT
-    if (ss->tlsext_hostname != NULL)
-        OPENSSL_free(ss->tlsext_hostname);
-    if (ss->tlsext_tick != NULL)
-        OPENSSL_free(ss->tlsext_tick);
-# ifndef OPENSSL_NO_EC
+    X509_free(ss->peer);
+    sk_X509_pop_free(ss->peer_chain, X509_free);
+    sk_SSL_CIPHER_free(ss->ciphers);
+    OPENSSL_free(ss->tlsext_hostname);
+    OPENSSL_free(ss->tlsext_tick);
+#ifndef OPENSSL_NO_EC
     ss->tlsext_ecpointformatlist_length = 0;
-    if (ss->tlsext_ecpointformatlist != NULL)
-        OPENSSL_free(ss->tlsext_ecpointformatlist);
+    OPENSSL_free(ss->tlsext_ecpointformatlist);
     ss->tlsext_ellipticcurvelist_length = 0;
-    if (ss->tlsext_ellipticcurvelist != NULL)
-        OPENSSL_free(ss->tlsext_ellipticcurvelist);
-# endif                         /* OPENSSL_NO_EC */
-#endif
+    OPENSSL_free(ss->tlsext_ellipticcurvelist);
+#endif                         /* OPENSSL_NO_EC */
 #ifndef OPENSSL_NO_PSK
-    if (ss->psk_identity_hint != NULL)
-        OPENSSL_free(ss->psk_identity_hint);
-    if (ss->psk_identity != NULL)
-        OPENSSL_free(ss->psk_identity);
+    OPENSSL_free(ss->psk_identity_hint);
+    OPENSSL_free(ss->psk_identity);
 #endif
 #ifndef OPENSSL_NO_SRP
-    if (ss->srp_username != NULL)
-        OPENSSL_free(ss->srp_username);
+    OPENSSL_free(ss->srp_username);
 #endif
-    OPENSSL_cleanse(ss, sizeof(*ss));
-    OPENSSL_free(ss);
+    OPENSSL_clear_free(ss, sizeof(*ss));
 }
 
 int SSL_set_session(SSL *s, SSL_SESSION *session)
@@ -779,35 +880,17 @@ int SSL_set_session(SSL *s, SSL_SESSION *session)
             if (!SSL_set_ssl_method(s, meth))
                 return (0);
         }
-#ifndef OPENSSL_NO_KRB5
-        if (s->kssl_ctx && !s->kssl_ctx->client_princ &&
-            session->krb5_client_princ_len > 0) {
-            s->kssl_ctx->client_princ =
-                (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1);
-            if (s->kssl_ctx->client_princ == NULL) {
-                SSLerr(SSL_F_SSL_SET_SESSION, ERR_R_MALLOC_FAILURE);
-                return (0);
-            }
-            memcpy(s->kssl_ctx->client_princ, session->krb5_client_princ,
-                   session->krb5_client_princ_len);
-            s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0';
-        }
-#endif                          /* OPENSSL_NO_KRB5 */
 
         /* CRYPTO_w_lock(CRYPTO_LOCK_SSL); */
         CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION);
-        if (s->session != NULL)
-            SSL_SESSION_free(s->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 {
-        if (s->session != NULL) {
-            SSL_SESSION_free(s->session);
-            s->session = NULL;
-        }
-
+        SSL_SESSION_free(s->session);
+        s->session = NULL;
         meth = s->ctx->method;
         if (meth != s->method) {
             if (!SSL_set_ssl_method(s, meth))
@@ -848,6 +931,24 @@ long SSL_SESSION_set_time(SSL_SESSION *s, long t)
     return (t);
 }
 
+int SSL_SESSION_has_ticket(const SSL_SESSION *s)
+{
+    return (s->tlsext_ticklen > 0) ? 1 : 0;
+}
+
+unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s)
+{
+    return s->tlsext_tick_lifetime_hint;
+}
+
+void SSL_SESSION_get0_ticket(const SSL_SESSION *s, unsigned char **tick,
+                            size_t *len)
+{
+    *len = s->tlsext_ticklen;
+    if (tick != NULL)
+        *tick = s->tlsext_tick;
+}
+
 X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
 {
     return s->peer;
@@ -884,7 +985,6 @@ long SSL_CTX_get_timeout(const SSL_CTX *s)
     return (s->session_timeout);
 }
 
-#ifndef OPENSSL_NO_TLSEXT
 int SSL_set_session_secret_cb(SSL *s,
                               int (*tls_session_secret_cb) (SSL *s,
                                                             void *secret,
@@ -916,11 +1016,8 @@ int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
 int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
 {
     if (s->version >= TLS1_VERSION) {
-        if (s->tlsext_session_ticket) {
-            OPENSSL_free(s->tlsext_session_ticket);
-            s->tlsext_session_ticket = NULL;
-        }
-
+        OPENSSL_free(s->tlsext_session_ticket);
+        s->tlsext_session_ticket = NULL;
         s->tlsext_session_ticket =
             OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
         if (!s->tlsext_session_ticket) {
@@ -942,7 +1039,6 @@ int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
 
     return 0;
 }
-#endif                          /* OPENSSL_NO_TLSEXT */
 
 typedef struct timeout_param_st {
     SSL_CTX *ctx;