From 1aeb3da83f267bc5e7cb9e7bd72dc0e07a751ba3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bodo=20M=C3=B6ller?= Date: Fri, 6 Jan 2006 09:08:59 +0000 Subject: [PATCH] Fixes for TLS server_name extension Submitted by: Peter Sylvester --- CHANGES | 11 +++++++---- apps/s_client.c | 2 +- apps/s_server.c | 9 ++++----- ssl/s3_lib.c | 13 ------------- ssl/ssl.h | 6 ++++-- ssl/ssl_lib.c | 7 +++++++ ssl/ssl_sess.c | 34 ++++++++++++++++++++-------------- ssl/tls1.h | 16 ---------------- 8 files changed, 43 insertions(+), 55 deletions(-) diff --git a/CHANGES b/CHANGES index 67c92f822f..dda03549fc 100644 --- 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() diff --git a/apps/s_client.c b/apps/s_client.c index c791667741..96cf511403 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -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 diff --git a/apps/s_server.c b/apps/s_server.c index 6c106f7f02..24a25d8156 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -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) { diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index c3bedf20ff..194b95d3f1 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -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) { diff --git a/ssl/ssl.h b/ssl/ssl.h index 17d2103aac..5d4e3ceb49 100644 --- 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) diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 841d75d585..42aa874542 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -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); diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 16162fa951..5dfc4c81bc 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -114,6 +114,12 @@ #include #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,©)) + if (s->session_ctx->get_session_cb != NULL + && (ret=s->session_ctx->get_session_cb(s,session_id,len,©)) != 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 diff --git a/ssl/tls1.h b/ssl/tls1.h index b5370f20fb..274866f493 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -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 -- 2.25.1