Commit 9cd50f73 authored by Trevor's avatar Trevor Committed by Ben Laurie
Browse files

Cleanup of custom extension stuff.

serverinfo rejects non-empty extensions.

Omit extension if no relevant serverinfo data.

Improve error-handling in serverinfo callback.

Cosmetic cleanups.

s_client documentation.

s_server documentation.

SSL_CTX_serverinfo documentation.

Cleaup -1 and NULL callback handling for custom extensions, add tests.

Cleanup ssl_rsa.c serverinfo code.

Whitespace cleanup.

Improve comments in ssl.h for serverinfo.

Whitespace.

Cosmetic cleanup.

Reject non-zero-len serverinfo extensions.

Whitespace.

Make it build.
parent 8ee3c7e6
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ B<openssl> B<s_client>
[B<-sess_out filename>]
[B<-sess_in filename>]
[B<-rand file(s)>]
[B<-serverinfo types>]

=head1 DESCRIPTION

@@ -256,6 +257,13 @@ Multiple files can be specified separated by a OS-dependent character.
The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
all others.

=item B<-serverinfo types>

a list of comma-separated TLS Extension Types (numbers between 0 and 
65535).  Each type will be sent as an empty ClientHello TLS Extension.
The server's response (if any) will be encoded and displayed as a PEM
file.

=back

=head1 CONNECTED COMMANDS
+9 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ B<openssl> B<s_server>
[B<-no_ticket>]
[B<-id_prefix arg>]
[B<-rand file(s)>]
[B<-serverinfo file>]

=head1 DESCRIPTION

@@ -306,6 +307,14 @@ Multiple files can be specified separated by a OS-dependent character.
The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
all others.

=item B<-serverinfo file>

a file containing one or more blocks of PEM data.  Each PEM block
must encode a TLS ServerHello extension (2 bytes type, 2 bytes length,
followed by "length" bytes of extension data).  If the client sends
an empty TLS ClientHello extension matching the type, the corresponding
ServerHello extension will be returned.

=back

=head1 CONNECTED COMMANDS
+45 −0
Original line number Diff line number Diff line
=pod

=head1 NAME

SSL_CTX_use_serverinfo, SSL_CTX_use_serverinfo_file

=head1 SYNOPSIS

 #include <openssl/ssl.h>

 int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
                            size_t serverinfo_length);

 int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file);

=head1 DESCRIPTION

These functions load "serverinfo" TLS ServerHello Extensions into the SSL_CTX.
A "serverinfo" extension is returned in response to an empty ClientHello
Extension.

SSL_CTX_use_serverinfo_file() loads one or more serverinfo extensions from
a byte array into B<ctx>. The extensions must be concatenated into a 
sequence of bytes.  Each extension must consist of a 2-byte Extension Type, 
a 2-byte length, and then length bytes of extension_data.

SSL_CTX_use_serverinfo_file() loads one or more serverinfo extensions from
B<file> into B<ctx>. The extensions must be in PEM format.  Each extension
must consist of a 2-byte Extension Type, a 2-byte length, and then length
bytes of extension_data.

=head1 NOTES

=head1 RETURN VALUES

On success, the functions return 1.
On failure, the functions return 0.  Check out the error stack to find out
the reason.

=head1 SEE ALSO

=head1 HISTORY


=cut
+4 −4
Original line number Diff line number Diff line
@@ -392,7 +392,8 @@ typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, S
 *
 *   All these functions return nonzero on success.  Zero will terminate
 *   the handshake (and return a specific TLS Fatal alert, if the function
 *   declaration has an "al" parameter).
 *   declaration has an "al" parameter).  -1 for the "sending" functions
 *   will cause the TLS Extension to be omitted.
 * 
 *   "ext_type" is a TLS "ExtensionType" from 0-65535.
 *   "in" is a pointer to TLS "extension_data" being provided to the cb.
@@ -1240,9 +1241,8 @@ const char *SSL_get_psk_identity(const SSL *s);
 *
 * For the server functions, a NULL custom_srv_ext_first_cb_fn means the
 * ClientHello extension's data will be ignored, but the extension will still
 * be noted and custom_srv_ext_second_cb_fn will still be invoked.  If 
 * custom_srv_ext_second_cb_fn is NULL, an empty ServerHello extension is 
 * sent.
 * be noted and custom_srv_ext_second_cb_fn will still be invoked.  A NULL
 * custom_srv_ext_second_cb doesn't send a ServerHello extension.
 */
int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type,
			       custom_cli_ext_first_cb_fn fn1, 
+42 −20
Original line number Diff line number Diff line
@@ -880,57 +880,78 @@ static int serverinfo_find_extension(const unsigned char *serverinfo,

		/* end of serverinfo */
		if (serverinfo_length == 0)
			return 0;
			return -1; /* Extension not found */

		/* read 2-byte type field */
		if (serverinfo_length < 2)
			return 0;	/* error */
			return 0; /* Error */
		type = (serverinfo[0] << 8) + serverinfo[1];
		serverinfo += 2;
		serverinfo_length -= 2;

		/* read 2-byte len field */
		if (serverinfo_length < 2)
			return 0;	/* error */
			return 0; /* Error */
		len = (serverinfo[0] << 8) + serverinfo[1];
		serverinfo += 2;
		serverinfo_length -= 2;

		if (len > serverinfo_length)
			return 0;	/* error */
			return 0; /* Error */

		if (type == extension_type)
			{
			*extension_data = serverinfo;
			*extension_length = len;
			return 1;
			return 1; /* Success */
			}

		serverinfo += len;
		serverinfo_length -= len;
		}
	return 0; /* Error */
	}

static int serverinfo_srv_first_cb(SSL *s, unsigned short ext_type,
				   const unsigned char *in,
				   unsigned short inlen, int *al,
				   void *arg)
	{
	if (inlen != 0)
		{
		*al = SSL_AD_DECODE_ERROR;
		return 0;
		}
	return 1;
	}

static int serverinfo_srv_cb(SSL *s, unsigned short ext_type,
static int serverinfo_srv_second_cb(SSL *s, unsigned short ext_type,
			            const unsigned char **out, unsigned short *outlen, 
			            void *arg)
	{
	const unsigned char *serverinfo = NULL;
	size_t serverinfo_length = 0;

	/* Is there a serverinfo for the chosen server cert? */
	/* Is there serverinfo data for the chosen server cert? */
	if ((ssl_get_server_cert_serverinfo(s, &serverinfo,
					    &serverinfo_length)) != 0)
		{
		/* Find the relevant extension from the serverinfo */
		serverinfo_find_extension(serverinfo, serverinfo_length,
		int retval = serverinfo_find_extension(serverinfo, serverinfo_length,
					      	       ext_type, out, outlen);
		if (retval == 0)
			return 0; /* Error */
		if (retval == -1)
			return -1; /* No extension found, don't send extension */
		return 1; /* Send extension */
		}
		return 1;
	return -1; /* No serverinfo data found, don't send extension */
	}

static int serverinfo_validate(const unsigned char *serverinfo, 
/* With a NULL context, this function just checks that the serverinfo data
   parses correctly.  With a non-NULL context, it registers callbacks for 
   the included extensions. */
static int serverinfo_process_buffer(const unsigned char *serverinfo, 
			    	     size_t serverinfo_length, SSL_CTX *ctx)
	{
	if (serverinfo == NULL || serverinfo_length == 0)
@@ -951,8 +972,9 @@ static int serverinfo_validate(const unsigned char *serverinfo,

		/* Register callbacks for extensions */
		ext_type = (serverinfo[0] << 8) + serverinfo[1];
		if (ctx && !SSL_CTX_set_custom_srv_ext(ctx, ext_type, NULL,
						       serverinfo_srv_cb, NULL))
		if (ctx && !SSL_CTX_set_custom_srv_ext(ctx, ext_type, 
						       serverinfo_srv_first_cb,
						       serverinfo_srv_second_cb, NULL))
			return 0;

		serverinfo += 2;
@@ -1058,7 +1080,7 @@ int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
		SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,ERR_R_PASSED_NULL_PARAMETER);
		return 0;
		}
	if (!serverinfo_validate(serverinfo, serverinfo_length, NULL))
	if (!serverinfo_process_buffer(serverinfo, serverinfo_length, NULL))
		{
		SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,SSL_R_INVALID_SERVERINFO_DATA);
		return(0);
@@ -1085,7 +1107,7 @@ int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,

	/* Now that the serverinfo is validated and stored, go ahead and 
	 * register callbacks. */
	if (!serverinfo_validate(serverinfo, serverinfo_length, ctx))
	if (!serverinfo_process_buffer(serverinfo, serverinfo_length, ctx))
		{
		SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,SSL_R_INVALID_SERVERINFO_DATA);
		return(0);
Loading