Support TLS extensions (specifically, HostName)

Submitted by: Peter Sylvester
This commit is contained in:
Bodo Möller 2006-01-02 23:14:37 +00:00
parent ea558241e0
commit ed3883d21b
15 changed files with 784 additions and 40 deletions

View File

@ -222,9 +222,32 @@ static void sc_usage(void)
BIO_printf(bio_err," -engine id - Initialise and use the specified engine\n");
#endif
BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
#ifndef OPENSSL_NO_TLSEXT
BIO_printf(bio_err," -servername host - Set TLS extension servername in ClientHello\n");
#endif
}
#ifndef OPENSSL_NO_TLSEXT
/* This is a context that we pass to callbacks */
typedef struct tlsextctx_st {
BIO * biodebug;
int ack;
} tlsextctx;
static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) {
tlsextctx * p = (tlsextctx *) arg;
const unsigned char * hn= SSL_get_servername(s, TLSEXT_TYPE_SERVER_host);
if (SSL_get_servername_type(s) != -1)
p->ack = !SSL_session_reused(s) && hn != NULL;
else
BIO_printf(bio_err,"SSL_get_tlsext_hostname does not work\n");
return SSL_ERROR_NONE;
}
#endif
int MAIN(int, char **);
int MAIN(int argc, char **argv)
@ -254,10 +277,7 @@ int MAIN(int argc, char **argv)
int starttls_proto = 0;
int prexit = 0, vflags = 0;
const SSL_METHOD *meth=NULL;
#ifdef sock_type
#undef sock_type
#endif
int sock_type=SOCK_STREAM;
int socketType=SOCK_STREAM;
BIO *sbio;
char *inrand=NULL;
#ifndef OPENSSL_NO_ENGINE
@ -268,6 +288,11 @@ int MAIN(int argc, char **argv)
struct timeval tv;
#endif
#ifndef OPENSSL_NO_TLSEXT
char *servername = NULL;
tlsextctx tlsextcbp =
{NULL,0};
#endif
struct sockaddr peer;
int peerlen = sizeof(peer);
int enable_timeouts = 0 ;
@ -394,7 +419,7 @@ int MAIN(int argc, char **argv)
else if (strcmp(*argv,"-dtls1") == 0)
{
meth=DTLSv1_client_method();
sock_type=SOCK_DGRAM;
socketType=SOCK_DGRAM;
}
else if (strcmp(*argv,"-timeout") == 0)
enable_timeouts=1;
@ -477,6 +502,14 @@ int MAIN(int argc, char **argv)
if (--argc < 1) goto bad;
inrand= *(++argv);
}
#ifndef OPENSSL_NO_TLSEXT
else if (strcmp(*argv,"-servername") == 0)
{
if (--argc < 1) goto bad;
servername= *(++argv);
/* meth=TLSv1_client_method(); */
}
#endif
else
{
BIO_printf(bio_err,"unknown option %s\n",*argv);
@ -572,7 +605,7 @@ bad:
/* DTLS: partial reads end up discarding unread UDP bytes :-(
* Setting read ahead solves this problem.
*/
if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);
if (socketType == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);
if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
if (cipher != NULL)
@ -600,8 +633,24 @@ bad:
store = SSL_CTX_get_cert_store(ctx);
X509_STORE_set_flags(store, vflags);
#ifndef OPENSSL_NO_TLSEXT
if (servername != NULL) {
tlsextcbp.biodebug = bio_err;
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
}
#endif
con=SSL_new(ctx);
#ifndef OPENSSL_NO_TLSEXT
if (servername != NULL){
if (!SSL_set_tlsext_hostname(con,servername)){
BIO_printf(bio_err,"Unable to set TLS servername extension.\n");
ERR_print_errors(bio_err);
goto end;
}
}
#endif
#ifndef OPENSSL_NO_KRB5
if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL)
{
@ -612,7 +661,7 @@ bad:
re_start:
if (init_client(&s,host,port,sock_type) == 0)
if (init_client(&s,host,port,socketType) == 0)
{
BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error());
SHUTDOWN(s);
@ -741,6 +790,11 @@ re_start:
if (in_init)
{
in_init=0;
#ifndef OPENSSL_NO_TLSEXT
if (servername != NULL && !SSL_session_reused(con)) {
BIO_printf(bio_c_out,"Server did %sacknowledge servername extension.\n",tlsextcbp.ack?"":"not ");
}
#endif
print_stuff(bio_c_out,con,full_log);
if (full_log > 0) full_log--;

View File

@ -221,6 +221,9 @@ static int bufsize=BUFSIZZ;
static int accept_socket= -1;
#define TEST_CERT "server.pem"
#ifndef OPENSSL_NO_TLSEXT
#define TEST_CERT2 "server2.pem"
#endif
#undef PROG
#define PROG s_server_main
@ -230,6 +233,9 @@ static char *cipher=NULL;
static int s_server_verify=SSL_VERIFY_NONE;
static int s_server_session_id_context = 1; /* anything will do */
static const char *s_cert_file=TEST_CERT,*s_key_file=NULL;
#ifndef OPENSSL_NO_TLSEXT
static const char *s_cert_file2=TEST_CERT2,*s_key_file2=NULL;
#endif
static char *s_dcert_file=NULL,*s_dkey_file=NULL;
#ifdef FIONBIO
static int s_nbio=0;
@ -237,6 +243,9 @@ static int s_nbio=0;
static int s_nbio_test=0;
int s_crlf=0;
static SSL_CTX *ctx=NULL;
#ifndef OPENSSL_NO_TLSEXT
static SSL_CTX *ctx2=NULL;
#endif
static int www=0;
static BIO *bio_s_out=NULL;
@ -251,10 +260,7 @@ static char *engine_id=NULL;
static const char *session_id_prefix=NULL;
static int enable_timeouts = 0;
#ifdef mtu
#undef mtu
#endif
static long mtu;
static long socketMtu;
static int cert_chain = 0;
@ -268,6 +274,11 @@ static void s_server_init(void)
s_dkey_file=NULL;
s_cert_file=TEST_CERT;
s_key_file=NULL;
#ifndef OPENSSL_NO_TLSEXT
s_cert_file2=TEST_CERT2;
s_key_file2=NULL;
ctx2=NULL;
#endif
#ifdef FIONBIO
s_nbio=0;
#endif
@ -354,6 +365,14 @@ static void sv_usage(void)
#endif
BIO_printf(bio_err," -id_prefix arg - Generate SSL/TLS session IDs prefixed by 'arg'\n");
BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
#ifndef OPENSSL_NO_TLSEXT
BIO_printf(bio_err," -servername host - check TLS1 servername\n");
BIO_printf(bio_err," -cert2 arg - certificate file to use for servername\n");
BIO_printf(bio_err," (default is %s)\n",TEST_CERT2);
BIO_printf(bio_err," -key2 arg - Private Key file to use for servername, in cert file if\n");
BIO_printf(bio_err," not specified (default is %s)\n",TEST_CERT2);
BIO_printf(bio_err," -servername host - check TLS1 servername\n");
#endif
}
static int local_argc=0;
@ -509,6 +528,37 @@ static int ebcdic_puts(BIO *bp, const char *str)
}
#endif
#ifndef OPENSSL_NO_TLSEXT
/* This is a context that we pass to callbacks */
typedef struct tlsextctx_st {
char * servername;
BIO * biodebug;
} tlsextctx;
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_TYPE_SERVER_host);
if (servername)
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;
}
if (servername) {
if (strcmp(servername,p->servername))
return TLS1_AD_UNRECOGNIZED_NAME;
if (ctx2)
SSL_set_SSL_CTX(s,ctx2);
SSL_set_tlsext_servername_done(s,1);
}
return SSL_ERROR_NONE;
}
#endif
int MAIN(int, char **);
int MAIN(int argc, char *argv[])
@ -528,10 +578,7 @@ int MAIN(int argc, char *argv[])
int no_tmp_rsa=0,no_dhe=0,no_ecdhe=0,nocert=0;
int state=0;
const SSL_METHOD *meth=NULL;
#ifdef sock_type
#undef sock_type
#endif
int sock_type=SOCK_STREAM;
int socketType=SOCK_STREAM;
#ifndef OPENSSL_NO_ENGINE
ENGINE *e=NULL;
#endif
@ -542,7 +589,16 @@ int MAIN(int argc, char *argv[])
int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM;
X509 *s_cert = NULL, *s_dcert = NULL;
EVP_PKEY *s_key = NULL, *s_dkey = NULL;
#ifndef OPENSSL_NO_TLSEXT
EVP_PKEY *s_key2 = NULL;
X509 *s_cert2 = NULL;
#endif
#ifndef OPENSSL_NO_TLSEXT
tlsextctx tlsextcbp =
{NULL,NULL
};
#endif
#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
meth=SSLv23_server_method();
#elif !defined(OPENSSL_NO_SSL3)
@ -755,14 +811,14 @@ int MAIN(int argc, char *argv[])
else if (strcmp(*argv,"-dtls1") == 0)
{
meth=DTLSv1_server_method();
sock_type = SOCK_DGRAM;
socketType = SOCK_DGRAM;
}
else if (strcmp(*argv,"-timeout") == 0)
enable_timeouts = 1;
else if (strcmp(*argv,"-mtu") == 0)
{
if (--argc < 1) goto bad;
mtu = atol(*(++argv));
socketMtu = atol(*(++argv));
}
else if (strcmp(*argv, "-chain") == 0)
cert_chain = 1;
@ -784,6 +840,24 @@ int MAIN(int argc, char *argv[])
if (--argc < 1) goto bad;
inrand= *(++argv);
}
#ifndef OPENSSL_NO_TLSEXT
else if (strcmp(*argv,"-servername") == 0)
{
if (--argc < 1) goto bad;
tlsextcbp.servername= *(++argv);
/* meth=TLSv1_server_method(); */
}
else if (strcmp(*argv,"-cert2") == 0)
{
if (--argc < 1) goto bad;
s_cert_file2= *(++argv);
}
else if (strcmp(*argv,"-key2") == 0)
{
if (--argc < 1) goto bad;
s_key_file2= *(++argv);
}
#endif
else
{
BIO_printf(bio_err,"unknown option %s\n",*argv);
@ -816,6 +890,10 @@ bad:
if (s_key_file == NULL)
s_key_file = s_cert_file;
#ifndef OPENSSL_NO_TLSEXT
if (s_key_file2 == NULL)
s_key_file2 = s_cert_file2;
#endif
if (nocert == 0)
{
@ -835,8 +913,31 @@ bad:
ERR_print_errors(bio_err);
goto end;
}
#ifndef OPENSSL_NO_TLSEXT
if (tlsextcbp.servername)
{
s_key2 = load_key(bio_err, s_key_file2, s_key_format, 0, pass, e,
"second server certificate private key file");
if (!s_key2)
{
ERR_print_errors(bio_err);
goto end;
}
s_cert2 = load_cert(bio_err,s_cert_file2,s_cert_format,
NULL, e, "second server certificate file");
if (!s_cert2)
{
ERR_print_errors(bio_err);
goto end;
}
}
#endif
}
if (s_dcert_file)
{
@ -893,6 +994,10 @@ bad:
s_key_file=NULL;
s_dcert_file=NULL;
s_dkey_file=NULL;
#ifndef OPENSSL_NO_TLSEXT
s_cert_file2=NULL;
s_key_file2=NULL;
#endif
}
ctx=SSL_CTX_new(meth);
@ -924,7 +1029,7 @@ bad:
/* DTLS: partial reads end up discarding unread UDP bytes :-(
* Setting read ahead solves this problem.
*/
if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);
if (socketType == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);
if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
@ -952,6 +1057,57 @@ bad:
store = SSL_CTX_get_cert_store(ctx);
X509_STORE_set_flags(store, vflags);
#ifndef OPENSSL_NO_TLSEXT
if (s_cert2) {
ctx2=SSL_CTX_new(meth);
if (ctx2 == NULL)
{
ERR_print_errors(bio_err);
goto end;
}
}
if (ctx2) {
BIO_printf(bio_s_out,"Setting secondary ctx parameters\n");
if (session_id_prefix)
{
if(strlen(session_id_prefix) >= 32)
BIO_printf(bio_err,
"warning: id_prefix is too long, only one new session will be possible\n");
else if(strlen(session_id_prefix) >= 16)
BIO_printf(bio_err,
"warning: id_prefix is too long if you use SSLv2\n");
if(!SSL_CTX_set_generate_session_id(ctx2, generate_session_id))
{
BIO_printf(bio_err,"error setting 'id_prefix'\n");
ERR_print_errors(bio_err);
goto end;
}
BIO_printf(bio_err,"id_prefix '%s' set.\n", session_id_prefix);
}
SSL_CTX_set_quiet_shutdown(ctx2,1);
if (bugs) SSL_CTX_set_options(ctx2,SSL_OP_ALL);
if (hack) SSL_CTX_set_options(ctx2,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
SSL_CTX_set_options(ctx2,off);
/* DTLS: partial reads end up discarding unread UDP bytes :-(
* Setting read ahead solves this problem.
*/
if (socketType == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx2, 1);
if (state) SSL_CTX_set_info_callback(ctx2,apps_ssl_info_callback);
SSL_CTX_sess_set_cache_size(ctx2,128);
if ((!SSL_CTX_load_verify_locations(ctx2,CAfile,CApath)) ||
(!SSL_CTX_set_default_verify_paths(ctx2)))
{
ERR_print_errors(bio_err);
}
store = SSL_CTX_get_cert_store(ctx2);
X509_STORE_set_flags(store, vflags);
}
#endif
#ifndef OPENSSL_NO_DH
if (!no_dhe)
{
@ -974,6 +1130,22 @@ bad:
(void)BIO_flush(bio_s_out);
SSL_CTX_set_tmp_dh(ctx,dh);
#ifndef OPENSSL_NO_TLSEXT
if (ctx2) {
if (!dhfile) {
DH *dh2=load_dh_param(s_cert_file2);
if (dh2 != NULL)
{
BIO_printf(bio_s_out,"Setting temp DH parameters\n");
(void)BIO_flush(bio_s_out);
DH_free(dh);
dh = dh2;
}
}
SSL_CTX_set_tmp_dh(ctx2,dh);
}
#endif
DH_free(dh);
}
#endif
@ -1019,12 +1191,20 @@ bad:
(void)BIO_flush(bio_s_out);
SSL_CTX_set_tmp_ecdh(ctx,ecdh);
#ifndef OPENSSL_NO_TLSEXT
if (ctx2)
SSL_CTX_set_tmp_ecdh(ctx2,ecdh);
#endif
EC_KEY_free(ecdh);
}
#endif
if (!set_cert_key_stuff(ctx,s_cert,s_key))
goto end;
#ifndef OPENSSL_NO_TLSEXT
if (ctx2 && !set_cert_key_stuff(ctx2,s_cert2,s_key2))
goto end;
#endif
if (s_dcert != NULL)
{
if (!set_cert_key_stuff(ctx,s_dcert,s_dkey))
@ -1033,8 +1213,13 @@ bad:
#ifndef OPENSSL_NO_RSA
#if 1
if (!no_tmp_rsa)
if (!no_tmp_rsa) {
SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb);
#ifndef OPENSSL_NO_TLSEXT
if (ctx2)
SSL_CTX_set_tmp_rsa_callback(ctx2,tmp_rsa_cb);
#endif
}
#else
if (!no_tmp_rsa && SSL_CTX_need_tmp_RSA(ctx))
{
@ -1050,30 +1235,65 @@ bad:
ERR_print_errors(bio_err);
goto end;
}
#ifndef OPENSSL_NO_TLSEXT
if (ctx2) {
if (!SSL_CTX_set_tmp_rsa(ctx2,rsa))
{
ERR_print_errors(bio_err);
goto end;
}
}
#endif
RSA_free(rsa);
BIO_printf(bio_s_out,"\n");
}
#endif
#endif
if (cipher != NULL)
if (cipher != NULL) {
if(!SSL_CTX_set_cipher_list(ctx,cipher)) {
BIO_printf(bio_err,"error setting cipher list\n");
ERR_print_errors(bio_err);
goto end;
BIO_printf(bio_err,"error setting cipher list\n");
ERR_print_errors(bio_err);
goto end;
}
#ifndef OPENSSL_NO_TLSEXT
if (ctx2 && !SSL_CTX_set_cipher_list(ctx2,cipher)) {
BIO_printf(bio_err,"error setting cipher list\n");
ERR_print_errors(bio_err);
goto end;
}
#endif
}
SSL_CTX_set_verify(ctx,s_server_verify,verify_callback);
SSL_CTX_set_session_id_context(ctx,(void*)&s_server_session_id_context,
sizeof s_server_session_id_context);
if (CAfile != NULL)
#ifndef OPENSSL_NO_TLSEXT
if (ctx2) {
SSL_CTX_set_verify(ctx2,s_server_verify,verify_callback);
SSL_CTX_set_session_id_context(ctx2,(void*)&s_server_session_id_context,
sizeof s_server_session_id_context);
}
tlsextcbp.biodebug = bio_s_out;
SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx2, &tlsextcbp);
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
#endif
if (CAfile != NULL) {
SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
#ifndef OPENSSL_NO_TLSEXT
if (ctx2)
SSL_CTX_set_client_CA_list(ctx2,SSL_load_client_CA_file(CAfile));
#endif
}
BIO_printf(bio_s_out,"ACCEPT\n");
if (www)
do_server(port,sock_type,&accept_socket,www_body, context);
do_server(port,socketType,&accept_socket,www_body, context);
else
do_server(port,sock_type,&accept_socket,sv_body, context);
do_server(port,socketType,&accept_socket,sv_body, context);
print_stats(bio_s_out,ctx);
ret=0;
end:
@ -1090,6 +1310,13 @@ end:
OPENSSL_free(pass);
if (dpass)
OPENSSL_free(dpass);
#ifndef OPENSSL_NO_TLSEXT
if (ctx2 != NULL) SSL_CTX_free(ctx2);
if (s_cert2)
X509_free(s_cert2);
if (s_key2)
EVP_PKEY_free(s_key2);
#endif
if (bio_s_out != NULL)
{
BIO_free(bio_s_out);
@ -1189,10 +1416,10 @@ static int sv_body(char *hostname, int s, unsigned char *context)
}
if ( mtu > 0)
if ( socketMtu > 0)
{
SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
SSL_set_mtu(con, mtu);
SSL_set_mtu(con, socketMtu);
}
else
/* want to do MTU discovery */

View File

@ -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;

View File

@ -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);

View File

@ -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))
{

View File

@ -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)
@ -1871,6 +1913,11 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
cert->ecdh_tmp_cb = (EC_KEY *(*)(SSL *, int, int))fp;
}
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);

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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"},

View File

@ -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)
{

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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