diff options
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/s23_clnt.c | 12 | ||||
-rw-r--r-- | ssl/s23_srvr.c | 10 | ||||
-rw-r--r-- | ssl/s3_clnt.c | 27 | ||||
-rw-r--r-- | ssl/s3_lib.c | 47 | ||||
-rw-r--r-- | ssl/s3_srvr.c | 29 | ||||
-rw-r--r-- | ssl/ssl.h | 32 | ||||
-rw-r--r-- | ssl/ssl_asn1.c | 37 | ||||
-rw-r--r-- | ssl/ssl_err.c | 5 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 38 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 8 | ||||
-rw-r--r-- | ssl/ssl_sess.c | 7 | ||||
-rw-r--r-- | ssl/t1_lib.c | 186 | ||||
-rw-r--r-- | ssl/tls1.h | 47 |
13 files changed, 474 insertions, 11 deletions
diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c index 1d1110b6f0..5a07db158f 100644 --- a/ssl/s23_clnt.c +++ b/ssl/s23_clnt.c @@ -349,6 +349,10 @@ static int ssl23_client_hello(SSL *s) p+=i; /* COMPRESSION */ +#ifdef OPENSSL_NO_COMP + *(p++)=1; +#else + if ((s->options & SSL_OP_NO_COMPRESSION) || !s->ctx->comp_methods) j=0; @@ -360,7 +364,15 @@ static int ssl23_client_hello(SSL *s) comp=sk_SSL_COMP_value(s->ctx->comp_methods,i); *(p++)=comp->id; } +#endif *(p++)=0; /* Add the NULL method */ +#ifndef OPENSSL_NO_TLSEXT + if ((p = ssl_add_ClientHello_TLS_extensions(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) + { + SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); + return -1; + } +#endif l = p-d; *p = 42; diff --git a/ssl/s23_srvr.c b/ssl/s23_srvr.c index b33b699a1c..8bf044e15f 100644 --- a/ssl/s23_srvr.c +++ b/ssl/s23_srvr.c @@ -140,7 +140,7 @@ IMPLEMENT_ssl23_meth_func(SSLv23_server_method, int ssl23_accept(SSL *s) { BUF_MEM *buf; - unsigned long Time=(unsigned long)time(NULL); + unsigned long Time=time(NULL); void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; int new_state,state; @@ -416,7 +416,7 @@ int ssl23_get_client_hello(SSL *s) n2s(p,sil); n2s(p,cl); d=(unsigned char *)s->init_buf->data; - if ((csl+sil+cl+11) != s->packet_length) + if ((csl+sil+cl+11) > s->packet_length) { SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH); goto err; @@ -459,6 +459,12 @@ int ssl23_get_client_hello(SSL *s) *(d++)=1; *(d++)=0; + /* copy any remaining data with may be extensions */ + p = p+csl+sil+cl ; + while (p < s->packet+s->packet_length) { + *(d++)=*(p++); + } + i = (d-(unsigned char *)s->init_buf->data) - 4; l2n3((long)i, d_len); diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 0098f56178..7a4f256642 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -255,6 +255,16 @@ int ssl3_connect(SSL *s) case SSL3_ST_CR_SRVR_HELLO_B: ret=ssl3_get_server_hello(s); if (ret <= 0) goto end; +#ifndef OPENSSL_NO_TLSEXT + { + int extension_error = 0,al; + if ((al = ssl_check_Hello_TLS_extensions(s,&extension_error)) != SSL_ERROR_NONE){ + ret = -1; + SSLerr(SSL_F_SSL3_CONNECT,SSL_R_SERVERHELLO_TLS_EXT); + goto end; + } + } +#endif if (s->hit) s->state=SSL3_ST_CR_FINISHED_A; else @@ -602,6 +612,13 @@ int ssl3_client_hello(SSL *s) } #endif *(p++)=0; /* Add the NULL method */ +#ifndef OPENSSL_NO_TLSEXT + if ((p = ssl_add_ClientHello_TLS_extensions(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) + { + SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); + goto err; + } +#endif l=(p-d); d=buf; @@ -786,6 +803,16 @@ int ssl3_get_server_hello(SSL *s) s->s3->tmp.new_compression=comp; } #endif +#ifndef OPENSSL_NO_TLSEXT + /* TLS extensions*/ + if (s->version > SSL3_VERSION) + { + if ((al = ssl_parse_ServerHello_TLS_extensions(s,&p,d,n)) != SSL_ERROR_NONE){ + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLS_EXT); + goto f_err; + } + } +#endif if (p != (d+n)) { diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 791c5e987c..845e5a16c5 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -1643,6 +1643,43 @@ 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_TYPE_SERVER_host) + { + SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE); + return(0); + } + *((char **) parg) = s->session&&s->session->tlsext_hostname?s->session->tlsext_hostname:s->tlsext_hostname; + ret = 1; + break; + case SSL_CTRL_SET_TLSEXT_HOSTNAME: + if (larg == TLSEXT_TYPE_SERVER_host) { + if (s->tlsext_hostname != NULL) + OPENSSL_free(s->tlsext_hostname); + s->tlsext_hostname = NULL; + + ret = 1; + if (parg == NULL) + break; + if (strlen((char *)parg) > 255) { + SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME); + return 0; + } + if ((s->tlsext_hostname = BUF_strdup((char *)parg)) == NULL) { + SSLerr(SSL_F_SSL3_CTRL, ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE); + return 0; + } + s->options |= SSL_OP_NO_SSLv2; + break; + case SSL_CTRL_SET_TLSEXT_SERVERNAME_DONE: + s->servername_done = larg; + break; +#endif /* !OPENSSL_NO_TLSEXT */ default: break; } @@ -1827,6 +1864,11 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) } break; #endif /* !OPENSSL_NO_ECDH */ +#ifndef OPENSSL_NO_TLSEXT + case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG: + ctx->tlsext_servername_arg=parg; + break; +#endif /* !OPENSSL_NO_TLSEXT */ /* A Thawte special :-) */ case SSL_CTRL_EXTRA_CHAIN_CERT: if (ctx->extra_certs == NULL) @@ -1872,6 +1914,11 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) } break; #endif +#ifndef OPENSSL_NO_TLSEXT + case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB: + ctx->tlsext_servername_callback=(int (*)(SSL *,int *,void *))fp; + break; +#endif default: return(0); } diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 18030842b8..25b56fa6fa 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -281,6 +281,17 @@ int ssl3_accept(SSL *s) s->shutdown=0; ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; +#ifndef OPENSSL_NO_TLSEXT + { + int extension_error = 0,al; + if ((al = ssl_check_Hello_TLS_extensions(s,&extension_error)) != SSL_ERROR_NONE){ + ret = -1; + SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLS_EXT); + ssl3_send_alert(s,al,extension_error); + goto end; + } + } +#endif s->new_session = 2; s->state=SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; @@ -942,6 +953,17 @@ int ssl3_get_client_hello(SSL *s) } } #endif +#ifndef OPENSSL_NO_TLSEXT + /* TLS extensions*/ + if (s->version > SSL3_VERSION) + { + if ((al = ssl_parse_ClientHello_TLS_extensions(s,&p,d,n)) != SSL_ERROR_NONE){ + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLS_EXT); + ssl3_send_alert(s,SSL3_AL_WARNING,al); + return (ret = al); + } + } +#endif /* Given s->session->ciphers and SSL_get_ciphers, we must * pick a cipher */ @@ -1086,6 +1108,13 @@ int ssl3_send_server_hello(SSL *s) else *(p++)=s->s3->tmp.new_compression->id; #endif +#ifndef OPENSSL_NO_TLSEXT + if ((p = ssl_add_ServerHello_TLS_extensions(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR); + return -1; + } +#endif /* do the header */ l=(p-d); @@ -172,6 +172,11 @@ #include <openssl/e_os2.h> +#ifdef OPENSSL_NO_TLS1 +# ifndef OPENSSL_NO_TLSEXT +# define OPENSSL_NO_TLSEXT +# endif +#endif #ifndef OPENSSL_NO_COMP #include <openssl/comp.h> #endif @@ -439,6 +444,9 @@ typedef struct ssl_session_st unsigned int krb5_client_princ_len; unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH]; #endif /* OPENSSL_NO_KRB5 */ +#ifndef OPENSSL_NO_TLSEXT + char *tlsext_hostname; +#endif int not_resumable; @@ -755,6 +763,13 @@ struct ssl_ctx_st * padding and MAC overheads. */ unsigned int max_send_fragment; + +#ifndef OPENSSL_NO_TLSEXT + /* TLS extensions servername callback */ + int (*tlsext_servername_callback)(SSL*, int *, void *); + void *tlsext_servername_arg; +#endif + }; #define SSL_SESS_CACHE_OFF 0x0000 @@ -977,6 +992,14 @@ struct ssl_st int client_version; /* what was passed, used for * SSLv3/TLS rollback check */ unsigned int max_send_fragment; +#ifndef OPENSSL_NO_TLSEXT + char *tlsext_hostname; + int servername_done; /* no further mod of servername + 0 : call the servername extension callback. + 1 : prepare 2, allow last ack just after in server callback. + 2 : don't call servername callback, no ack in server hello + */ +#endif }; #ifdef __cplusplus @@ -1122,6 +1145,9 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count); #define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR /* fatal */ #define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED #define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION +#ifndef OPENSSL_NO_TLSEXT +#define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME +#endif #define SSL_ERROR_NONE 0 #define SSL_ERROR_SSL 1 @@ -1454,6 +1480,7 @@ int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, SSL_SESSION *SSL_get_session(const SSL *ssl); SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */ SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl); +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx); void SSL_set_info_callback(SSL *ssl, void (*cb)(const SSL *ssl,int type,int val)); void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val); @@ -1777,6 +1804,7 @@ void ERR_load_SSL_strings(void); #define SSL_R_CIPHER_CODE_WRONG_LENGTH 137 #define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 138 #define SSL_R_CIPHER_TABLE_SRC_ERROR 139 +#define SSL_R_CLIENTHELLO_TLS_EXT 2003 #define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140 #define SSL_R_COMPRESSION_FAILURE 141 #define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE 1120 @@ -1861,6 +1889,7 @@ void ERR_load_SSL_strings(void); #define SSL_R_NULL_SSL_METHOD_PASSED 196 #define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 #define SSL_R_PACKET_LENGTH_TOO_LONG 198 +#define SSL_R_PARSE_TLS_EXT 2004 #define SSL_R_PATH_TOO_LONG 270 #define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199 #define SSL_R_PEER_ERROR 200 @@ -1884,11 +1913,14 @@ void ERR_load_SSL_strings(void); #define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 216 #define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 217 #define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 218 +#define SSL_R_SERVERHELLO_TLS_EXT 2005 #define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277 #define SSL_R_SHORT_READ 219 #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220 #define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221 #define SSL_R_SSL2_CONNECTION_ID_TOO_LONG 1114 +#define SSL_R_SSL3_EXT_INVALID_SERVERNAME 2006 +#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 2007 #define SSL_R_SSL3_SESSION_ID_TOO_LONG 1113 #define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222 #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c index d129acc329..e98a47fc9d 100644 --- a/ssl/ssl_asn1.c +++ b/ssl/ssl_asn1.c @@ -78,12 +78,15 @@ typedef struct ssl_session_asn1_st ASN1_INTEGER time; ASN1_INTEGER timeout; ASN1_INTEGER verify_result; +#ifndef OPENSSL_NO_TLSEXT + ASN1_OCTET_STRING tlsext_hostname; +#endif /* OPENSSL_NO_TLSEXT */ } SSL_SESSION_ASN1; int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) { #define LSIZE2 (sizeof(long)*2) - int v1=0,v2=0,v3=0,v4=0,v5=0; + int v1=0,v2=0,v3=0,v4=0,v5=0,v6=0; unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2]; unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2]; long l; @@ -178,6 +181,14 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) ASN1_INTEGER_set(&a.verify_result,in->verify_result); } +#ifndef OPENSSL_NO_TLSEXT + if (in->tlsext_hostname) + { + a.tlsext_hostname.length=strlen(in->tlsext_hostname); + a.tlsext_hostname.type=V_ASN1_OCTET_STRING; + a.tlsext_hostname.data=in->tlsext_hostname; + } +#endif /* OPENSSL_NO_TLSEXT */ M_ASN1_I2D_len(&(a.version), i2d_ASN1_INTEGER); M_ASN1_I2D_len(&(a.ssl_version), i2d_ASN1_INTEGER); @@ -200,6 +211,10 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) if (in->verify_result != X509_V_OK) M_ASN1_I2D_len_EXP_opt(&(a.verify_result),i2d_ASN1_INTEGER,5,v5); +#ifndef OPENSSL_NO_TLSEXT + if (in->tlsext_hostname) + M_ASN1_I2D_len_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6); +#endif /* OPENSSL_NO_TLSEXT */ M_ASN1_I2D_seq_total(); M_ASN1_I2D_put(&(a.version), i2d_ASN1_INTEGER); @@ -223,6 +238,10 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) v4); if (in->verify_result != X509_V_OK) M_ASN1_I2D_put_EXP_opt(&a.verify_result,i2d_ASN1_INTEGER,5,v5); +#ifndef OPENSSL_NO_TLSEXT + if (in->tlsext_hostname) + M_ASN1_I2D_put_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6); +#endif /* OPENSSL_NO_TLSEXT */ M_ASN1_I2D_finish(); } @@ -394,5 +413,21 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, else ret->verify_result=X509_V_OK; +#ifndef OPENSSL_NO_TLSEXT + os.length=0; + os.data=NULL; + M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,6); + if (os.data) + { + ret->tlsext_hostname = BUF_strndup(os.data, os.length); + OPENSSL_free(os.data); + os.data = NULL; + os.length = 0; + } + else + ret->tlsext_hostname=NULL; + +#endif /* OPENSSL_NO_TLSEXT */ + M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION); } diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 282f1a6755..133c4a7447 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -292,6 +292,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH),"cipher code wrong length"}, {ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE),"cipher or hash unavailable"}, {ERR_REASON(SSL_R_CIPHER_TABLE_SRC_ERROR),"cipher table src error"}, +{ERR_REASON(SSL_R_CLIENTHELLO_TLS_EXT) ,"clienthello tls ext"}, {ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG),"compressed length too long"}, {ERR_REASON(SSL_R_COMPRESSION_FAILURE) ,"compression failure"}, {ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE),"compression id not within private range"}, @@ -376,6 +377,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED),"null ssl method passed"}, {ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"}, {ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet length too long"}, +{ERR_REASON(SSL_R_PARSE_TLS_EXT) ,"parse tls ext"}, {ERR_REASON(SSL_R_PATH_TOO_LONG) ,"path too long"}, {ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE),"peer did not return a certificate"}, {ERR_REASON(SSL_R_PEER_ERROR) ,"peer error"}, @@ -399,11 +401,14 @@ static ERR_STRING_DATA SSL_str_reasons[]= {ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO),"reuse cert length not zero"}, {ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO),"reuse cert type not zero"}, {ERR_REASON(SSL_R_REUSE_CIPHER_LIST_NOT_ZERO),"reuse cipher list not zero"}, +{ERR_REASON(SSL_R_SERVERHELLO_TLS_EXT) ,"serverhello tls ext"}, {ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),"session id context uninitialized"}, {ERR_REASON(SSL_R_SHORT_READ) ,"short read"}, {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"}, {ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"}, {ERR_REASON(SSL_R_SSL2_CONNECTION_ID_TOO_LONG),"ssl2 connection id too long"}, +{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME),"ssl3 ext invalid servername"}, +{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),"ssl3 ext invalid servername type"}, {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG),"ssl3 session id too long"}, {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_SHORT),"ssl3 session id too short"}, {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE),"sslv3 alert bad certificate"}, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index b79ac1c9a2..afe7162ab7 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1315,6 +1315,27 @@ err: return(NULL); } +#ifndef OPENSSL_TLSEXT +/** return a servername extension value if provided in CLIENT HELLO + * or NULL. + * For the moment, only hostname types are supported. + */ + +const char *SSL_get_servername(const SSL *s, const int type) { + + if (type != TLSEXT_TYPE_SERVER_host) + return NULL; + return s->session /*&&s->session->tlsext_hostname*/?s->session->tlsext_hostname:s->tlsext_hostname; +} + +int SSL_get_servername_type(const SSL *s) { + + if (s->session &&s->session->tlsext_hostname ?s->session->tlsext_hostname:s->tlsext_hostname) + return TLSEXT_TYPE_SERVER_host; + return -1; +} + +#endif unsigned long SSL_SESSION_hash(const SSL_SESSION *a) { unsigned long l; @@ -1466,6 +1487,10 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; +#ifndef OPENSSL_NO_TLSEXT + ret->tlsext_servername_callback = NULL; + ret->tlsext_servername_arg = NULL; +#endif return(ret); err: SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE); @@ -2415,6 +2440,19 @@ SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) return(ssl->ctx); } +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx) + { + + if (ssl->cert != NULL) + ssl_cert_free(ssl->cert); + ssl->cert = ssl_cert_dup(ctx->cert); + CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); + if (ssl->ctx != NULL) + SSL_CTX_free(ssl->ctx); /* decrement reference count */ + ssl->ctx = ctx; + return(ssl->ctx); + } + #ifndef OPENSSL_NO_STDIO int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) { diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 6a56384a8c..26a062fdcd 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -940,5 +940,11 @@ int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs); SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n); - +#ifndef OPENSSL_NO_TLSEXT +unsigned char *ssl_add_ClientHello_TLS_extensions(SSL *s, unsigned char *p, unsigned char *limit); +unsigned char *ssl_add_ServerHello_TLS_extensions(SSL *s, unsigned char *p, unsigned char *limit); +int ssl_parse_ClientHello_TLS_extensions(SSL *s, unsigned char **data, unsigned char *d, int n); +int ssl_parse_ServerHello_TLS_extensions(SSL *s, unsigned char **data, unsigned char *d, int n); +int ssl_check_Hello_TLS_extensions(SSL *s,int *ad); +#endif #endif diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 7a4bb92b5c..6c2c04bf0f 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -122,6 +122,9 @@ SSL_SESSION *SSL_SESSION_new(void) ss->prev=NULL; ss->next=NULL; ss->compress_meth=0; +#ifndef OPENSSL_NO_TLSEXT + ss->tlsext_hostname = NULL; +#endif CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); return(ss); } @@ -546,6 +549,10 @@ void SSL_SESSION_free(SSL_SESSION *ss) 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); +#endif OPENSSL_cleanse(ss,sizeof(*ss)); OPENSSL_free(ss); } diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index fd0d8215b0..ff5bc58ce7 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -101,14 +101,186 @@ void tls1_clear(SSL *s) s->version=TLS1_VERSION; } -#if 0 -long tls1_ctrl(SSL *s, int cmd, long larg, char *parg) - { - return(0); +#ifndef OPENSSL_NO_TLSEXT +unsigned char *ssl_add_ClientHello_TLS_extensions(SSL *s, unsigned char *p, unsigned char *limit) { + int extdatalen=0; + unsigned char *ret = p; + + ret+=2; + + if (ret>=limit) return NULL; /* this really never occurs, but ... */ + if (s->servername_done == 0 && s->tlsext_hostname != NULL) { + /* Add TLS extension servername to the Client Hello message */ + unsigned long size_str; + long lenmax; + + if ((lenmax = limit - p - 7) < 0) return NULL; + if ((size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) return NULL; + + s2n(TLSEXT_TYPE_server_name,ret); + s2n(size_str+3,ret); + *(ret++) = (unsigned char) TLSEXT_TYPE_SERVER_host; + s2n(size_str,ret); + + memcpy(ret, s->tlsext_hostname, size_str); + ret+=size_str; } -long tls1_callback_ctrl(SSL *s, int cmd, void *(*fp)()) - { - return(0); + + if ((extdatalen = ret-p-2)== 0) + return p; + + s2n(extdatalen,p); + return ret; + +} + +unsigned char *ssl_add_ServerHello_TLS_extensions(SSL *s, unsigned char *p, unsigned char *limit) { + int extdatalen=0; + unsigned char *ret = p; + if (s->hit || s->servername_done == 2) + return p; + ret+=2; + if (s->servername_done == 1) + s->servername_done = 2; + + if (ret>=limit) return NULL; /* this really never occurs, but ... */ + + if (s->session->tlsext_hostname != NULL) { + + if (limit - p - 4 < 0) return NULL; + + s2n(TLSEXT_TYPE_server_name,ret); + s2n(0,ret); } + + + if ((extdatalen = ret-p-2)== 0) + return p; + + s2n(extdatalen,p); + return ret; + +} + +int ssl_parse_ClientHello_TLS_extensions(SSL *s, unsigned char **p, unsigned char *d, int n) { + unsigned short type; + unsigned short size; + unsigned short len; + unsigned char * data = *p; + + if (data >= (d+n-2)) + return SSL_ERROR_NONE; + n2s(data,len); + + if (data > (d+n-len)) + return SSL_ERROR_NONE; + + while(data <= (d+n-4)){ + n2s(data,type); + n2s(data,size); + + if (data+size > (d+n)) + return SSL_ERROR_SSL; + + if (type == TLSEXT_TYPE_server_name) { + unsigned char *sdata = data; + int servname_type; + int dsize = size-3 ; + + if (dsize > 0 ) { + servname_type = *(sdata++); + n2s(sdata,len); + if (len != dsize) + return SSL_ERROR_SSL; + + switch (servname_type) { + case TLSEXT_TYPE_SERVER_host: + if (s->session->tlsext_hostname == NULL) { + if (len > 255 || + ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL)) + return SSL_ERROR_SSL; + memcpy(s->session->tlsext_hostname, sdata, len); + s->session->tlsext_hostname[len]='\0'; + } + break; + default: + break; + } + + } + } + + data+=size; + } + *p = data; + + return SSL_ERROR_NONE; +} +int ssl_parse_ServerHello_TLS_extensions(SSL *s, unsigned char **p, unsigned char *d, int n) { + unsigned short type; + unsigned short size; + unsigned short len; + unsigned char *data = *p; + + int tlsext_servername = 0; + + if (data >= (d+n-2)) + return SSL_ERROR_NONE; + + + n2s(data,len); + + while(data <= (d+n-4)){ + n2s(data,type); + n2s(data,size); + + if (data+size > (d+n)) + return SSL_ERROR_SSL; + + if (type == TLSEXT_TYPE_server_name) { + if ( s->tlsext_hostname == NULL || size > 0 ) { + return SSL_ERROR_SSL; + } + tlsext_servername = 1; + } + + data+=size; + } + + + + if (data != d+n) + return SSL_ERROR_SSL; + + if (!s->hit && tlsext_servername == 1) { + if (s->tlsext_hostname) { + if (s->session->tlsext_hostname == NULL) { + s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname); + if (!s->session->tlsext_hostname) + return SSL_ERROR_SSL; + } + } else + return SSL_ERROR_SSL; + } + *p = data; + + return SSL_ERROR_NONE; +} + +int ssl_check_Hello_TLS_extensions(SSL *s,int *ad) +{ + int ret = SSL_ERROR_NONE; + + *ad = SSL_AD_UNRECOGNIZED_NAME; + if (s->servername_done == 0 && (s->ctx != NULL && s->ctx->tlsext_servername_callback != NULL) + && ((ret = s->ctx->tlsext_servername_callback(s, ad, s->ctx->tlsext_servername_arg))!= SSL_ERROR_NONE)) + return ret; + + else if (s->servername_done == 1) + s->servername_done = 2; + + return ret; +} #endif + diff --git a/ssl/tls1.h b/ssl/tls1.h index e7eaa835db..4c8a5daa56 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -97,6 +97,53 @@ extern "C" { #define TLS1_AD_USER_CANCELLED 90 #define TLS1_AD_NO_RENEGOTIATION 100 +#ifndef OPENSSL_NO_TLSEXT +#define TLS1_AD_UNRECOGNIZED_NAME 122 + +#define TLSEXT_TYPE_server_name 0 +#define TLSEXT_TYPE_max_fragment_length 1 +#define TLSEXT_TYPE_client_certificate_url 2 +#define TLSEXT_TYPE_trusted_ca_keys 3 +#define TLSEXT_TYPE_truncated_hmac 4 +#define TLSEXT_TYPE_status_request 5 +#define TLSEXT_TYPE_srp 6 + +#define TLSEXT_TYPE_SERVER_host 0 + +#define SSL_CTX_set_tlsext_hostname(ctx,name) \ +SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_TYPE_SERVER_host,(char *)name) +#define SSL_set_tlsext_hostname(s,name) \ +SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_TYPE_SERVER_host,(char *)name) + +#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ +SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb) +#define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \ +SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg) + + +const char *SSL_get_servername(const SSL *s, const int type) ; +int SSL_get_servername_type(const SSL *s) ; + +#if 0 + #define SSL_get_tlsext_hostname(s,psn) \ + SSL_ctrl(s,SSL_CTRL_GET_TLSEXT_HOSTNAME,TLSEXT_TYPE_SERVER_host, (void *)psn) +#else + #define SSL_get_tlsext_hostname(s,psn) \ + (*psn = SSL_get_servername(s, TLSEXT_TYPE_SERVER_host),*psn != NULL) +#endif + #define SSL_set_tlsext_servername_done(s,t) \ + SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_SERVERNAME_DONE,t, NULL) + +void SSL_set_ctx(SSL *s, SSL_CTX *ctx) ; + +#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 + +#endif + /* Additional TLS ciphersuites from expired Internet Draft * draft-ietf-tls-56-bit-ciphersuites-01.txt * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see |