Fixes for TLS server_name extension
authorBodo Möller <bodo@openssl.org>
Fri, 6 Jan 2006 09:08:59 +0000 (09:08 +0000)
committerBodo Möller <bodo@openssl.org>
Fri, 6 Jan 2006 09:08:59 +0000 (09:08 +0000)
Submitted by: Peter Sylvester

CHANGES
apps/s_client.c
apps/s_server.c
ssl/s3_lib.c
ssl/ssl.h
ssl/ssl_lib.c
ssl/ssl_sess.c
ssl/tls1.h

diff --git a/CHANGES b/CHANGES
index 67c92f8..dda0354 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,9 +4,13 @@
 
  Changes between 0.9.8a and 0.9.9  [xx XXX xxxx]
 
-  *) Add support for TLS extensions, specifically for the HostName extension
-     so far.  The SSL_SESSION, SSL_CTX, and SSL data structures now have new
-     members for HostName support.
+  *) Add initial support for TLS extensions, specifically for the server_name
+     extension so far.  The SSL_SESSION, SSL_CTX, and SSL data structures now
+     have new members for a host name.  The SSL data structure has an
+     additional member SSL_CTX *initial_ctx so that new sessions can be
+     stored in that context to allow for session resumption, even after the
+     SSL has been switched to a new SSL_CTX in reaction to a client's
+     server_name extension.
 
      New functions (subject to change):
 
@@ -21,7 +25,6 @@
          SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
                                       - SSL_CTX_set_tlsext_servername_arg()
          SSL_CTRL_SET_TLSEXT_HOSTNAME           - SSL_set_tlsext_hostname()
-         SSL_CTRL_GET_TLSEXT_HOSTNAME     [similar to SSL_get_servername()]
          SSL_CTRL_SET_TLSEXT_SERVERNAME_DONE
                                          - SSL_set_tlsext_servername_done()
 
index c791667..96cf511 100644 (file)
@@ -245,7 +245,7 @@ static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg)
        else 
                BIO_printf(bio_err,"Can't use SSL_get_servername\n");
        
-       return SSL_ERROR_NONE;
+       return 1;
        }
 #endif
 
index 6c106f7..24a25d8 100644 (file)
@@ -540,24 +540,24 @@ static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg)
        {
        tlsextctx * p = (tlsextctx *) arg;
        const char * servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
-        if (servername) 
+        if (servername && p->biodebug
                BIO_printf(p->biodebug,"Hostname in TLS extension: \"%s\"\n",servername);
         
        if (!p->servername)
                {
                SSL_set_tlsext_servername_done(s,2);
-               return SSL_ERROR_NONE;
+               return 1;
                }
        
        if (servername)
                {
                if (strcmp(servername,p->servername)) 
-                       return TLS1_AD_UNRECOGNIZED_NAME;
+                       return 0;
                if (ctx2) 
                        SSL_set_SSL_CTX(s,ctx2);
                SSL_set_tlsext_servername_done(s,1);
                }
-       return SSL_ERROR_NONE;
+       return 1;
 }
 #endif
 
@@ -845,7 +845,6 @@ int MAIN(int argc, char *argv[])
                        {
                        if (--argc < 1) goto bad;
                        tlsextcbp.servername= *(++argv);
-                       /* meth=TLSv1_server_method(); */
                        }
                else if (strcmp(*argv,"-cert2") == 0)
                        {
index c3bedf2..194b95d 100644 (file)
@@ -1644,19 +1644,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
                break;
 #endif /* !OPENSSL_NO_ECDH */
 #ifndef OPENSSL_NO_TLSEXT
-       case SSL_CTRL_GET_TLSEXT_HOSTNAME:      
-               if (larg != TLSEXT_NAMETYPE_host_name)
-                       {
-                       SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
-                       return(0);
-                       }
-               /* XXX cf. SSL_get_servername() (ssl_lib.c) */
-               if (s->session && s->session->tlsext_hostname)
-                       *((char **) parg) = s->session->tlsext_hostname;
-               else
-                       *((char **) parg) = s->tlsext_hostname;
-               ret = 1;
-               break;
        case SSL_CTRL_SET_TLSEXT_HOSTNAME:
                if (larg == TLSEXT_NAMETYPE_host_name)
                        {
index 17d2103..5d4e3ce 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -993,6 +993,7 @@ struct ssl_st
                                  1 : prepare 2, allow last ack just after in server callback.
                                  2 : don't call servername callback, no ack in server hello
                               */
+       SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
 #endif
        };
 
@@ -1201,11 +1202,12 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
 #define SSL_CTRL_SET_MAX_SEND_FRAGMENT         52
 
 /* see tls.h for macros based on these */
+#ifndef OPENSSL_NO_TLSEXT
 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB      53
 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG     54
 #define SSL_CTRL_SET_TLSEXT_HOSTNAME           55
-#define SSL_CTRL_GET_TLSEXT_HOSTNAME           56
-#define SSL_CTRL_SET_TLSEXT_SERVERNAME_DONE    57
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_DONE    56
+#endif
 
 #define SSL_session_reused(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
index 841d75d..42aa874 100644 (file)
@@ -307,6 +307,10 @@ SSL *SSL_new(SSL_CTX *ctx)
 
        CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
        s->ctx=ctx;
+#ifndef OPENSSL_NO_TLSEXT
+       CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
+       s->initial_ctx=ctx;
+#endif
 
        s->verify_result=X509_V_OK;
 
@@ -493,6 +497,9 @@ void SSL_free(SSL *s)
        /* Free up if allocated */
 
        if (s->ctx) SSL_CTX_free(s->ctx);
+#ifndef OPENSSL_NO_TLSEXT
+       if (s->initial_ctx) SSL_CTX_free(s->initial_ctx);
+#endif
 
        if (s->client_CA != NULL)
                sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free);
index 16162fa..5dfc4c8 100644 (file)
 #include <openssl/rand.h>
 #include "ssl_locl.h"
 
+#ifndef OPENSSL_NO_TLSEXT
+#define session_ctx initial_ctx
+#else
+#define session_ctx ctx
+#endif
+
 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
 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);
@@ -233,7 +239,7 @@ int ssl_get_new_session(SSL *s, int session)
        if ((ss=SSL_SESSION_new()) == NULL) return(0);
 
        /* If the context has a default timeout, use it */
-       if (s->ctx->session_timeout == 0)
+       if (s->session_ctx->session_timeout == 0)
                ss->timeout=SSL_get_default_timeout(s);
        else
                ss->timeout=s->ctx->session_timeout;
@@ -276,8 +282,8 @@ int ssl_get_new_session(SSL *s, int session)
                CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
                if(s->generate_session_id)
                        cb = s->generate_session_id;
-               else if(s->ctx->generate_session_id)
-                       cb = s->ctx->generate_session_id;
+               else if(s->session_ctx->generate_session_id)
+                       cb = s->session_ctx->generate_session_id;
                CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
                /* Choose a session ID */
                tmp = ss->session_id_length;
@@ -347,10 +353,10 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len)
                goto err;
        memcpy(data.session_id,session_id,len);
 
-       if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+       if (!(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
                {
                CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
-               ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data);
+               ret=(SSL_SESSION *)lh_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);
@@ -361,13 +367,13 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len)
                {
                int copy=1;
        
-               s->ctx->stats.sess_miss++;
+               s->session_ctx->stats.sess_miss++;
                ret=NULL;
-               if (s->ctx->get_session_cb != NULL
-                   && (ret=s->ctx->get_session_cb(s,session_id,len,&copy))
+               if (s->session_ctx->get_session_cb != NULL
+                   && (ret=s->session_ctx->get_session_cb(s,session_id,len,&copy))
                       != NULL)
                        {
-                       s->ctx->stats.sess_cb_hit++;
+                       s->session_ctx->stats.sess_cb_hit++;
 
                        /* Increment reference count now if the session callback
                         * asks us to do so (note that if the session structures
@@ -379,10 +385,10 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len)
 
                        /* Add the externally cached session to the internal
                         * cache as well if and only if we are supposed to. */
-                       if(!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE))
+                       if(!(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE))
                                /* The following should not return 1, otherwise,
                                 * things are very strange */
-                               SSL_CTX_add_session(s->ctx,ret);
+                               SSL_CTX_add_session(s->session_ctx,ret);
                        }
                if (ret == NULL)
                        goto err;
@@ -447,13 +453,13 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len)
 
        if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
                {
-               s->ctx->stats.sess_timeout++;
+               s->session_ctx->stats.sess_timeout++;
                /* remove it from the cache */
-               SSL_CTX_remove_session(s->ctx,ret);
+               SSL_CTX_remove_session(s->session_ctx,ret);
                goto err;
                }
 
-       s->ctx->stats.sess_hit++;
+       s->session_ctx->stats.sess_hit++;
 
        /* ret->time=time(NULL); */ /* rezero timeout? */
        /* again, just leave the session 
index b5370f2..274866f 100644 (file)
@@ -158,9 +158,6 @@ extern "C" {
 #define TLSEXT_TYPE_trusted_ca_keys            3
 #define TLSEXT_TYPE_truncated_hmac             4
 #define TLSEXT_TYPE_status_request             5
-#if 0
-#define TLSEXT_TYPE_srp                                6
-#endif
 
 /* NameType value from RFC 3546 */
 #define TLSEXT_NAMETYPE_host_name 0
@@ -181,19 +178,6 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg)
 
 #define SSL_set_tlsext_servername_done(s,t) \
 SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_SERVERNAME_DONE,t, NULL)
-
-#if 0
-#  if 0
-
-       #define SSL_get_tlsext_hostname(s,psn) \
-       SSL_ctrl(s,SSL_CTRL_GET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name, (void *)psn)
-#  else
-       /* XXX this looks weird for a macro, define a function instead? */
-        * or just used SSL_get_servername() directly ... */
-       #define SSL_get_tlsext_hostname(s,psn) \
-       (*psn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name),*psn != NULL)
-#  endif
-#endif
   
 #endif