Commit 865a90eb authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Backport of TLS extension code to OpenSSL 0.9.8.

Include server name and RFC4507bis support.

This is not compiled in by default and must be explicitly enabled with
the Configure option enable-tlsext
parent 0269c450
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -4,6 +4,58 @@

 Changes between 0.9.8e and 0.9.8f  [xx XXX xxxx]
  
  *) Add RFC4507 support to OpenSSL. This includes the corrections in
     RFC4507bis. The encrypted ticket format is an encrypted encoded
     SSL_SESSION structure, that way new session features are automatically
     supported.

     If a client application caches session in an SSL_SESSION support it
     should automatically be supported because an extension includes the
     ticket in the structure. The SSL_CTX structure automatically generates
     keys for ticket protection in servers so again support should be possible
     with no application modification.

     If a client or server wishes to disable RFC4507 support then the option
     SSL_OP_NO_TICKET can be set.

     Add a TLS extension debugging callback to allow the contents of any client
     or server extensions to be examined.
     [Steve Henson]

  *) 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):

         SSL_get_servername()
         SSL_get_servername_type()
         SSL_set_SSL_CTX()

     New CTRL codes and macros (subject to change):

         SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
                                 - SSL_CTX_set_tlsext_servername_callback()
         SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
                                      - SSL_CTX_set_tlsext_servername_arg()
         SSL_CTRL_SET_TLSEXT_HOSTNAME           - SSL_set_tlsext_host_name()

     openssl s_client has a new '-servername ...' option.

     openssl s_server has new options '-servername_host ...', '-cert2 ...',
     '-key2 ...', '-servername_fatal' (subject to change).  This allows
     testing the HostName extension for a specific single host name ('-cert'
     and '-key' remain fallbacks for handshakes without HostName
     negotiation).  If the unrecogninzed_name alert has to be sent, this by
     default is a warning; it becomes fatal with the '-servername_fatal'
     option.

     [Peter Sylvester,  Remy Allais, Christophe Renou, Steve Henson]

  *) Add AES and SSE2 assembly language support to VC++ build.
     [Steve Henson]

+5 −0
Original line number Diff line number Diff line
@@ -607,6 +607,7 @@ my %disabled = ( # "what" => "comment"
                 "rfc3779"        => "default",
                 "seed"           => "default",
                 "shared"         => "default",
                 "tlsext"         => "default",
                 "zlib"           => "default",
                 "zlib-dynamic"   => "default"
               );
@@ -838,6 +839,10 @@ if (defined($disabled{"md5"}) || defined($disabled{"sha"})
	$disabled{"tls1"} = "forced";
	}

if (defined($disabled{"tls1"}))
	{
	$disabled{"tlsext"} = "forced";
	}

if ($target eq "TABLE") {
	foreach $target (sort keys %table) {
+3 −0
Original line number Diff line number Diff line
@@ -167,4 +167,7 @@ long MS_CALLBACK bio_dump_callback(BIO *bio, int cmd, const char *argp,
#ifdef HEADER_SSL_H
void MS_CALLBACK apps_ssl_info_callback(const SSL *s, int where, int ret);
void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type,
					unsigned char *data, int len,
					void *arg);
#endif
+59 −0
Original line number Diff line number Diff line
@@ -575,3 +575,62 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *
		}
	(void)BIO_flush(bio);
	}

void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type,
					unsigned char *data, int len,
					void *arg)
	{
	BIO *bio = arg;
	char *extname;

	switch(type)
		{
		case TLSEXT_TYPE_server_name:
		extname = "server name";
		break;

		case TLSEXT_TYPE_max_fragment_length:
		extname = "max fragment length";
		break;

		case TLSEXT_TYPE_client_certificate_url:
		extname = "client certificate URL";
		break;

		case TLSEXT_TYPE_trusted_ca_keys:
		extname = "trusted CA keys";
		break;

		case TLSEXT_TYPE_truncated_hmac:
		extname = "truncated HMAC";
		break;

		case TLSEXT_TYPE_status_request:
		extname = "status request";
		break;

		case TLSEXT_TYPE_elliptic_curves:
		extname = "elliptic curves";
		break;

		case TLSEXT_TYPE_ec_point_formats:
		extname = "EC point formats";
		break;

		case TLSEXT_TYPE_session_ticket:
		extname = "server ticket";
		break;


		default:
		extname = "unknown";
		break;

		}
	
	BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n",
			client_server ? "server": "client",
			extname, type, len);
	BIO_dump(bio, (char *)data, len);
	(void)BIO_flush(bio);
	}
+121 −1
Original line number Diff line number Diff line
@@ -171,6 +171,9 @@ static int c_nbio=0;
#endif
static int c_Pause=0;
static int c_debug=0;
#ifndef OPENSSL_NO_TLSEXT
static int c_tlsextdebug=0;
#endif
static int c_msg=0;
static int c_showcerts=0;

@@ -231,9 +234,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 char * hn= SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
	if (SSL_get_servername_type(s) != -1) 
 	        p->ack = !SSL_session_reused(s) && hn != NULL;
	else 
		BIO_printf(bio_err,"Can't use SSL_get_servername\n");
	
	return SSL_TLSEXT_ERR_OK;
	}
#endif
enum
{
	PROTO_OFF	= 0,
@@ -287,6 +313,13 @@ int MAIN(int argc, char **argv)
	struct timeval tv;
#endif

#ifndef OPENSSL_NO_TLSEXT
	char *servername = NULL; 
        tlsextctx tlsextcbp = 
        {NULL,0};
#endif
	char *sess_in = NULL;
	char *sess_out = NULL;
	struct sockaddr peer;
	int peerlen = sizeof(peer);
	int enable_timeouts = 0 ;
@@ -361,6 +394,16 @@ int MAIN(int argc, char **argv)
			if (--argc < 1) goto bad;
			cert_file= *(++argv);
			}
		else if	(strcmp(*argv,"-sess_out") == 0)
			{
			if (--argc < 1) goto bad;
			sess_out = *(++argv);
			}
		else if	(strcmp(*argv,"-sess_in") == 0)
			{
			if (--argc < 1) goto bad;
			sess_in = *(++argv);
			}
		else if	(strcmp(*argv,"-certform") == 0)
			{
			if (--argc < 1) goto bad;
@@ -385,6 +428,10 @@ int MAIN(int argc, char **argv)
			c_Pause=1;
		else if	(strcmp(*argv,"-debug") == 0)
			c_debug=1;
#ifndef OPENSSL_NO_TLSEXT
		else if	(strcmp(*argv,"-tlsextdebug") == 0)
			c_tlsextdebug=1;
#endif
#ifdef WATT32
		else if (strcmp(*argv,"-wdebug") == 0)
			dbug_init();
@@ -460,6 +507,10 @@ int MAIN(int argc, char **argv)
			off|=SSL_OP_NO_SSLv3;
		else if (strcmp(*argv,"-no_ssl2") == 0)
			off|=SSL_OP_NO_SSLv2;
#ifndef OPENSSL_NO_TLSEXT
		else if	(strcmp(*argv,"-no_ticket") == 0)
			{ off|=SSL_OP_NO_TICKET; }
#endif
		else if (strcmp(*argv,"-serverpref") == 0)
			off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
		else if	(strcmp(*argv,"-cipher") == 0)
@@ -498,6 +549,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);
@@ -621,8 +680,51 @@ 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);
	if (sess_in)
		{
		SSL_SESSION *sess;
		BIO *stmp = BIO_new_file(sess_in, "r");
		if (!stmp)
			{
			BIO_printf(bio_err, "Can't open session file %s\n",
						sess_in);
			ERR_print_errors(bio_err);
			goto end;
			}
		sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
		BIO_free(stmp);
		if (!sess)
			{
			BIO_printf(bio_err, "Can't open session file %s\n",
						sess_in);
			ERR_print_errors(bio_err);
			goto end;
			}
		SSL_set_session(con, sess);
		SSL_SESSION_free(sess);
		}
#ifndef OPENSSL_NO_TLSEXT
	if (servername != NULL)
		{
		if (!SSL_set_tlsext_host_name(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)
                {
@@ -714,6 +816,13 @@ re_start:
		SSL_set_msg_callback(con, msg_cb);
		SSL_set_msg_callback_arg(con, bio_c_out);
		}
#ifndef OPENSSL_NO_TLSEXT
	if (c_tlsextdebug)
		{
		SSL_set_tlsext_debug_callback(con, tlsext_cb);
		SSL_set_tlsext_debug_arg(con, bio_c_out);
		}
#endif

	SSL_set_bio(con,sbio,sbio);
	SSL_set_connect_state(con);
@@ -837,6 +946,17 @@ re_start:
			if (in_init)
				{
				in_init=0;
				if (sess_out)
					{
					BIO *stmp = BIO_new_file(sess_out, "w");
					if (stmp)
						{
						PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con));
						BIO_free(stmp);
						}
					else 
						BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
					}
				print_stuff(bio_c_out,con,full_log);
				if (full_log > 0) full_log--;

Loading