diff --git a/CHANGES b/CHANGES index eae69d3e37c927e7db6892da20fa46df19528b78..8023667d7527650f827a3dd8faaed5bf22f487a3 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,19 @@ Changes between 0.9.8a and 0.9.9 [xx XXX xxxx] + *) Add support for TLS extensions, specifically for the HostName extension. + The SSL_SESSION, SSL_CTX, and SSL data structures now have new members + for HostName support. + + openssl s_client has a new '-servername' option. + + openssl s_server has new options '-servername', '-cert2', and '-key2'; + this allows testing the HostName extension for a specific single + host name ('-cert' and '-key' remain fallbacks for handshakes without + HostName negotiation). + + [Peter Sylvester] + *) Whirlpool hash implementation is added. [Andy Polyakov] diff --git a/apps/s_client.c b/apps/s_client.c index c24b6e4a26d6cd6a881ad5c7daa1a5fedb45ea61..b5c044bfa710b982304f8069a3b0c10ca13db0f8 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -236,7 +236,8 @@ typedef struct tlsextctx_st { } tlsextctx; -static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) { +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) @@ -245,7 +246,7 @@ static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) { BIO_printf(bio_err,"SSL_get_tlsext_hostname does not work\n"); return SSL_ERROR_NONE; -} + } #endif int MAIN(int, char **); @@ -277,7 +278,7 @@ int MAIN(int argc, char **argv) int starttls_proto = 0; int prexit = 0, vflags = 0; const SSL_METHOD *meth=NULL; - int socketType=SOCK_STREAM; + int socket_type=SOCK_STREAM; BIO *sbio; char *inrand=NULL; #ifndef OPENSSL_NO_ENGINE @@ -296,7 +297,7 @@ int MAIN(int argc, char **argv) struct sockaddr peer; int peerlen = sizeof(peer); int enable_timeouts = 0 ; - long mtu = 0; + long socket_mtu = 0; #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_client_method(); @@ -419,14 +420,14 @@ int MAIN(int argc, char **argv) else if (strcmp(*argv,"-dtls1") == 0) { meth=DTLSv1_client_method(); - socketType=SOCK_DGRAM; + socket_type=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)); + socket_mtu = atol(*(++argv)); } #endif else if (strcmp(*argv,"-bugs") == 0) @@ -605,7 +606,7 @@ bad: /* DTLS: partial reads end up discarding unread UDP bytes :-( * Setting read ahead solves this problem. */ - if (socketType == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); + if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); if (cipher != NULL) @@ -634,22 +635,25 @@ bad: store = SSL_CTX_get_cert_store(ctx); X509_STORE_set_flags(store, vflags); #ifndef OPENSSL_NO_TLSEXT - if (servername != NULL) { + 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)){ + 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) @@ -661,7 +665,7 @@ bad: re_start: - if (init_client(&s,host,port,socketType) == 0) + if (init_client(&s,host,port,socket_type) == 0) { BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error()); SHUTDOWN(s); @@ -698,7 +702,7 @@ re_start: BIO_ctrl_set_connected(sbio, 1, &peer); - if ( enable_timeouts) + if (enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; @@ -709,10 +713,10 @@ re_start: BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } - if ( mtu > 0) + if (socket_mtu > 0) { SSL_set_options(con, SSL_OP_NO_QUERY_MTU); - SSL_set_mtu(con, mtu); + SSL_set_mtu(con, socket_mtu); } else /* want to do MTU discovery */ @@ -791,9 +795,10 @@ re_start: { in_init=0; #ifndef OPENSSL_NO_TLSEXT - if (servername != NULL && !SSL_session_reused(con)) { + 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--; diff --git a/apps/s_server.c b/apps/s_server.c index 7dc864fab9b39963412249d4398dc6c013e4d459..068e0c54b100e9df76e0c53329396bbe820347c3 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -260,7 +260,7 @@ static char *engine_id=NULL; static const char *session_id_prefix=NULL; static int enable_timeouts = 0; -static long socketMtu; +static long socket_mtu; static int cert_chain = 0; @@ -366,12 +366,11 @@ static void sv_usage(void) 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," -servername host - servername for HostName TLS extension\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 } @@ -537,24 +536,27 @@ typedef struct tlsextctx_st { } tlsextctx; -static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) { +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) { + if (!p->servername) + { SSL_set_tlsext_servername_done(s,2); return SSL_ERROR_NONE; - } + } - if (servername) { + 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 @@ -578,7 +580,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; - int socketType=SOCK_STREAM; + int socket_type=SOCK_STREAM; #ifndef OPENSSL_NO_ENGINE ENGINE *e=NULL; #endif @@ -595,9 +597,7 @@ int MAIN(int argc, char *argv[]) #endif #ifndef OPENSSL_NO_TLSEXT - tlsextctx tlsextcbp = - {NULL,NULL - }; + tlsextctx tlsextcbp = {NULL, NULL}; #endif #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_server_method(); @@ -811,14 +811,14 @@ int MAIN(int argc, char *argv[]) else if (strcmp(*argv,"-dtls1") == 0) { meth=DTLSv1_server_method(); - socketType = SOCK_DGRAM; + socket_type = SOCK_DGRAM; } else if (strcmp(*argv,"-timeout") == 0) enable_timeouts = 1; else if (strcmp(*argv,"-mtu") == 0) { if (--argc < 1) goto bad; - socketMtu = atol(*(++argv)); + socket_mtu = atol(*(++argv)); } else if (strcmp(*argv, "-chain") == 0) cert_chain = 1; @@ -915,19 +915,19 @@ bad: } #ifndef OPENSSL_NO_TLSEXT - if (tlsextcbp.servername) + if (tlsextcbp.servername) { s_key2 = load_key(bio_err, s_key_file2, s_key_format, 0, pass, e, - "second server certificate private key file"); + "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); @@ -1029,7 +1029,7 @@ bad: /* DTLS: partial reads end up discarding unread UDP bytes :-( * Setting read ahead solves this problem. */ - if (socketType == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); + if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); @@ -1058,56 +1058,59 @@ bad: 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 (s_cert2) { - 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)) + ctx2=SSL_CTX_new(meth); + if (ctx2 == NULL) { - 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 (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 (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx2, 1); - if (state) SSL_CTX_set_info_callback(ctx2,apps_ssl_info_callback); + if (state) SSL_CTX_set_info_callback(ctx2,apps_ssl_info_callback); - SSL_CTX_sess_set_cache_size(ctx2,128); + SSL_CTX_sess_set_cache_size(ctx2,128); - if ((!SSL_CTX_load_verify_locations(ctx2,CAfile,CApath)) || - (!SSL_CTX_set_default_verify_paths(ctx2))) - { + 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); } - store = SSL_CTX_get_cert_store(ctx2); - X509_STORE_set_flags(store, vflags); - - } #endif + #ifndef OPENSSL_NO_DH if (!no_dhe) { @@ -1131,20 +1134,22 @@ bad: SSL_CTX_set_tmp_dh(ctx,dh); #ifndef OPENSSL_NO_TLSEXT - if (ctx2) { - if (!dhfile) { + 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); } @@ -1213,13 +1218,14 @@ 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)) { @@ -1236,13 +1242,14 @@ bad: goto end; } #ifndef OPENSSL_NO_TLSEXT - if (ctx2) { - if (!SSL_CTX_set_tmp_rsa(ctx2,rsa)) + 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"); @@ -1257,11 +1264,12 @@ bad: goto end; } #ifndef OPENSSL_NO_TLSEXT - if (ctx2 && !SSL_CTX_set_cipher_list(ctx2,cipher)) { + 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); @@ -1269,31 +1277,33 @@ bad: sizeof s_server_session_id_context); #ifndef OPENSSL_NO_TLSEXT - if (ctx2) { + 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)); + 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)); + 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,socketType,&accept_socket,www_body, context); + do_server(port,socket_type,&accept_socket,www_body, context); else - do_server(port,socketType,&accept_socket,sv_body, context); + do_server(port,socket_type,&accept_socket,sv_body, context); print_stats(bio_s_out,ctx); ret=0; end: @@ -1404,7 +1414,7 @@ static int sv_body(char *hostname, int s, unsigned char *context) sbio=BIO_new_dgram(s,BIO_NOCLOSE); - if ( enable_timeouts) + if (enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; @@ -1415,11 +1425,10 @@ static int sv_body(char *hostname, int s, unsigned char *context) BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } - - if ( socketMtu > 0) + if (socket_mtu > 0) { SSL_set_options(con, SSL_OP_NO_QUERY_MTU); - SSL_set_mtu(con, socketMtu); + SSL_set_mtu(con, socket_mtu); } else /* want to do MTU discovery */