Fix source where indent will not be able to cope
[openssl.git] / ssl / ssl_sess.c
index 3f0b19558d7a3429e6c1b1f317c60c97cf0576f7..c21aeed8b18fba3557924165081c480a03870e66 100644 (file)
@@ -231,13 +231,18 @@ const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
        return s->session_id;
        }
 
        return s->session_id;
        }
 
-/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1
- * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly
+unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s)
+       {
+       return s->compress_meth;
+       }
+
+/* SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling
+ * the ID with random junk repeatedly
  * until we have no conflict is going to complete in one iteration pretty much
  * "most" of the time (btw: understatement). So, if it takes us 10 iterations
  * and we still can't avoid a conflict - well that's a reasonable point to call
  * it quits. Either the RAND code is broken or someone is trying to open roughly
  * until we have no conflict is going to complete in one iteration pretty much
  * "most" of the time (btw: understatement). So, if it takes us 10 iterations
  * and we still can't avoid a conflict - well that's a reasonable point to call
  * it quits. Either the RAND code is broken or someone is trying to open roughly
- * very close to 2^128 (or 2^256) SSL sessions to our server. How you might
+ * very close to 2^256 SSL sessions to our server. How you might
  * store that many sessions is perhaps a more interesting question ... */
 
 #define MAX_SESS_ID_ATTEMPTS 10
  * store that many sessions is perhaps a more interesting question ... */
 
 #define MAX_SESS_ID_ATTEMPTS 10
@@ -288,12 +293,7 @@ int ssl_get_new_session(SSL *s, int session)
 
        if (session)
                {
 
        if (session)
                {
-               if (s->version == SSL2_VERSION)
-                       {
-                       ss->ssl_version=SSL2_VERSION;
-                       ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
-                       }
-               else if (s->version == SSL3_VERSION)
+               if (s->version == SSL3_VERSION)
                        {
                        ss->ssl_version=SSL3_VERSION;
                        ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
                        {
                        ss->ssl_version=SSL3_VERSION;
                        ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
@@ -308,6 +308,11 @@ int ssl_get_new_session(SSL *s, int session)
                        ss->ssl_version=TLS1_1_VERSION;
                        ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
                        }
                        ss->ssl_version=TLS1_1_VERSION;
                        ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
                        }
+               else if (s->version == TLS1_2_VERSION)
+                       {
+                       ss->ssl_version=TLS1_2_VERSION;
+                       ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+                       }
                else if (s->version == DTLS1_BAD_VER)
                        {
                        ss->ssl_version=DTLS1_BAD_VER;
                else if (s->version == DTLS1_BAD_VER)
                        {
                        ss->ssl_version=DTLS1_BAD_VER;
@@ -318,6 +323,11 @@ int ssl_get_new_session(SSL *s, int session)
                        ss->ssl_version=DTLS1_VERSION;
                        ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
                        }
                        ss->ssl_version=DTLS1_VERSION;
                        ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
                        }
+               else if (s->version == DTLS1_2_VERSION)
+                       {
+                       ss->ssl_version=DTLS1_2_VERSION;
+                       ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+                       }
                else
                        {
                        SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
                else
                        {
                        SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
@@ -325,7 +335,21 @@ int ssl_get_new_session(SSL *s, int session)
                        return(0);
                        }
 #ifndef OPENSSL_NO_TLSEXT
                        return(0);
                        }
 #ifndef OPENSSL_NO_TLSEXT
-               /* If RFC4507 ticket use empty session ID */
+               /*-
+                * 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;
                if (s->tlsext_ticket_expected)
                        {
                        ss->session_id_length = 0;
@@ -359,11 +383,7 @@ int ssl_get_new_session(SSL *s, int session)
                        SSL_SESSION_free(ss);
                        return(0);
                        }
                        SSL_SESSION_free(ss);
                        return(0);
                        }
-               /* If the session length was shrunk and we're SSLv2, pad it */
-               if((tmp < ss->session_id_length) && (s->version == SSL2_VERSION))
-                       memset(ss->session_id + tmp, 0, ss->session_id_length - tmp);
-               else
-                       ss->session_id_length = tmp;
+               ss->session_id_length = tmp;
                /* Finally, check for a conflict */
                if(SSL_has_matching_session_id(s, ss->session_id,
                                                ss->session_id_length))
                /* Finally, check for a conflict */
                if(SSL_has_matching_session_id(s, ss->session_id,
                                                ss->session_id_length))
@@ -383,32 +403,6 @@ int ssl_get_new_session(SSL *s, int session)
                                return 0;
                                }
                        }
                                return 0;
                                }
                        }
-#ifndef OPENSSL_NO_EC
-               if (s->tlsext_ecpointformatlist)
-                       {
-                       if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist);
-                       if ((ss->tlsext_ecpointformatlist = OPENSSL_malloc(s->tlsext_ecpointformatlist_length)) == NULL)
-                               {
-                               SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE);
-                               SSL_SESSION_free(ss);
-                               return 0;
-                               }
-                       ss->tlsext_ecpointformatlist_length = s->tlsext_ecpointformatlist_length;
-                       memcpy(ss->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
-                       }
-               if (s->tlsext_ellipticcurvelist)
-                       {
-                       if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
-                       if ((ss->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
-                               {
-                               SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE);
-                               SSL_SESSION_free(ss);
-                               return 0;
-                               }
-                       ss->tlsext_ellipticcurvelist_length = s->tlsext_ellipticcurvelist_length;
-                       memcpy(ss->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length);
-                       }
-#endif
 #endif
                }
        else
 #endif
                }
        else
@@ -431,6 +425,26 @@ int ssl_get_new_session(SSL *s, int session)
        return(1);
        }
 
        return(1);
        }
 
+/*-
+ * ssl_get_prev attempts to find an SSL_SESSION to be used to resume this
+ * connection. It is only called by servers.
+ *
+ *   session_id: points at the session ID in the ClientHello. This code will
+ *       read past the end of this in order to parse out the session ticket
+ *       extension, if any.
+ *   len: the length of the session ID.
+ *   limit: a pointer to the first byte after the ClientHello.
+ *
+ * Returns:
+ *   -1: error
+ *    0: a session may have been found.
+ *
+ * Side effects:
+ *   - If a session is found then s->session is pointed at it (after freeing an
+ *     existing session if need be) and s->verify_result is set from the 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, unsigned char *session_id, int len,
                        const unsigned char *limit)
        {
@@ -438,27 +452,40 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
 
        SSL_SESSION *ret=NULL;
        int fatal = 0;
 
        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)
                goto err;
 #ifndef OPENSSL_NO_TLSEXT
        int r;
 #endif
 
        if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
                goto err;
+
+       if (len == 0)
+               try_session_cache = 0;
+
 #ifndef OPENSSL_NO_TLSEXT
 #ifndef OPENSSL_NO_TLSEXT
+       /* sets s->tlsext_ticket_expected */
        r = tls1_process_ticket(s, session_id, len, limit, &ret);
        r = tls1_process_ticket(s, session_id, len, limit, &ret);
-       if (r == -1)
+       switch (r)
                {
                {
+       case -1: /* Error during processing */
                fatal = 1;
                goto err;
                fatal = 1;
                goto err;
+       case 0: /* No ticket found */
+       case 1: /* Zero length ticket found */
+               break; /* Ok to carry on processing session id. */
+       case 2: /* Ticket found but not decrypted. */
+       case 3: /* Ticket decrypted, *ret has been set. */
+               try_session_cache = 0;
+               break;
+       default:
+               abort();
                }
                }
-       else if (r == 0 || (!ret && !len))
-               goto err;
-       else if (!ret && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
-#else
-       if (len == 0)
-               goto err;
-       if (!(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
 #endif
 #endif
+
+       if (try_session_cache &&
+           ret == NULL &&
+           !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
                {
                SSL_SESSION data;
                data.ssl_version=s->version;
                {
                SSL_SESSION data;
                data.ssl_version=s->version;
@@ -469,20 +496,22 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
                CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
                ret=lh_SSL_SESSION_retrieve(s->session_ctx->sessions,&data);
                if (ret != NULL)
                CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
                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);
+                       {
+                       /* don't allow other threads to steal it: */
+                       CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
+                       }
                CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
                CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+               if (ret == NULL)
+                       s->session_ctx->stats.sess_miss++;
                }
 
                }
 
-       if (ret == NULL)
+       if (try_session_cache &&
+           ret == NULL &&
+           s->session_ctx->get_session_cb != NULL)
                {
                int copy=1;
        
                {
                int copy=1;
        
-               s->session_ctx->stats.sess_miss++;
-               ret=NULL;
-               if (s->session_ctx->get_session_cb != NULL
-                   && (ret=s->session_ctx->get_session_cb(s,session_id,len,&copy))
-                      != NULL)
+               if ((ret=s->session_ctx->get_session_cb(s,session_id,len,&copy)))
                        {
                        s->session_ctx->stats.sess_cb_hit++;
 
                        {
                        s->session_ctx->stats.sess_cb_hit++;
 
@@ -501,23 +530,18 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
                                 * things are very strange */
                                SSL_CTX_add_session(s->session_ctx,ret);
                        }
                                 * things are very strange */
                                SSL_CTX_add_session(s->session_ctx,ret);
                        }
-               if (ret == NULL)
-                       goto err;
                }
 
                }
 
-       /* Now ret is non-NULL, and we own one of its reference counts. */
+       if (ret == NULL)
+               goto err;
+
+       /* Now ret is non-NULL and we own one of its reference counts. */
 
        if (ret->sid_ctx_length != s->sid_ctx_length
            || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))
                {
 
        if (ret->sid_ctx_length != s->sid_ctx_length
            || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))
                {
-               /* We've found the session named by the client, but we don't
+               /* We have the session requested by the client, but we don't
                 * want to use it in this context. */
                 * want to use it in this context. */
-
-#if 0 /* The client cannot always know when a session is not appropriate,
-       * so we shouldn't generate an error message. */
-
-               SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
-#endif
                goto err; /* treat like cache miss */
                }
        
                goto err; /* treat like cache miss */
                }
        
@@ -554,39 +578,38 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
                        goto err;
                }
 
                        goto err;
                }
 
-
-#if 0 /* This is way too late. */
-
-       /* If a thread got the session, then 'swaped', and another got
-        * it and then due to a time-out decided to 'OPENSSL_free' it we could
-        * be in trouble.  So I'll increment it now, then double decrement
-        * later - am I speaking rubbish?. */
-       CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
-#endif
-
        if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
                {
                s->session_ctx->stats.sess_timeout++;
        if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
                {
                s->session_ctx->stats.sess_timeout++;
-               /* remove it from the cache */
-               SSL_CTX_remove_session(s->session_ctx,ret);
+               if (try_session_cache)
+                       {
+                       /* session was from the cache, so remove it */
+                       SSL_CTX_remove_session(s->session_ctx,ret);
+                       }
                goto err;
                }
 
        s->session_ctx->stats.sess_hit++;
 
                goto err;
                }
 
        s->session_ctx->stats.sess_hit++;
 
-       /* ret->time=time(NULL); */ /* rezero timeout? */
-       /* again, just leave the session 
-        * if it is the same session, we have just incremented and
-        * then decremented the reference count :-) */
        if (s->session != NULL)
                SSL_SESSION_free(s->session);
        s->session=ret;
        s->verify_result = s->session->verify_result;
        if (s->session != NULL)
                SSL_SESSION_free(s->session);
        s->session=ret;
        s->verify_result = s->session->verify_result;
-       return(1);
+       return 1;
 
  err:
        if (ret != NULL)
 
  err:
        if (ret != NULL)
+               {
                SSL_SESSION_free(ret);
                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 the new session */
+                       s->tlsext_ticket_expected = 1;
+                       }
+#endif
+               }
        if (fatal)
                return -1;
        else
        if (fatal)
                return -1;
        else
@@ -715,7 +738,6 @@ void SSL_SESSION_free(SSL_SESSION *ss)
 
        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 
 
        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 
-       OPENSSL_cleanse(ss->key_arg,sizeof ss->key_arg);
        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);
        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);
@@ -765,10 +787,6 @@ int SSL_set_session(SSL *s, SSL_SESSION *session)
                        {
                        if (!SSL_set_ssl_method(s,meth))
                                return(0);
                        {
                        if (!SSL_set_ssl_method(s,meth))
                                return(0);
-                       if (s->ctx->session_timeout == 0)
-                               session->timeout=SSL_get_default_timeout(s);
-                       else
-                               session->timeout=s->ctx->session_timeout;
                        }
 
 #ifndef OPENSSL_NO_KRB5
                        }
 
 #ifndef OPENSSL_NO_KRB5
@@ -776,6 +794,11 @@ int SSL_set_session(SSL *s, SSL_SESSION *session)
                     session->krb5_client_princ_len > 0)
                 {
                     s->kssl_ctx->client_princ = (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1);
                     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';
                     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';
@@ -836,16 +859,6 @@ long SSL_SESSION_set_time(SSL_SESSION *s, long t)
        return(t);
        }
 
        return(t);
        }
 
-unsigned int SSL_SESSION_get_id_len(SSL_SESSION *s)
-       {
-       return s->session_id_length;
-       }
-
-const unsigned char *SSL_SESSION_get0_id(SSL_SESSION *s)
-       {
-       return s->session_id;
-       }
-
 X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
        {
        return s->peer;
 X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
        {
        return s->peer;
@@ -853,17 +866,17 @@ X509 *SSL_SESSION_get0_peer(SSL_SESSION *s)
 
 int SSL_SESSION_set1_id_context(SSL_SESSION *s,const unsigned char *sid_ctx,
                               unsigned int sid_ctx_len)
 
 int SSL_SESSION_set1_id_context(SSL_SESSION *s,const unsigned char *sid_ctx,
                               unsigned int sid_ctx_len)
-    {
-    if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH)
        {
        {
-       SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
-       return 0;
-       }
-    s->sid_ctx_length=sid_ctx_len;
-    memcpy(s->sid_ctx,sid_ctx,sid_ctx_len);
+       if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH)
+               {
+               SSLerr(SSL_F_SSL_SESSION_SET1_ID_CONTEXT,SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+               return 0;
+               }
+       s->sid_ctx_length=sid_ctx_len;
+       memcpy(s->sid_ctx,sid_ctx,sid_ctx_len);
 
 
-    return 1;
-    }
+       return 1;
+       }
 
 long SSL_CTX_set_timeout(SSL_CTX *s, long t)
        {
 
 long SSL_CTX_set_timeout(SSL_CTX *s, long t)
        {