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.
This commit is contained in:
parent
8ee3c7e676
commit
9cd50f738f
@ -43,6 +43,7 @@ B<openssl> B<s_client>
|
|||||||
[B<-sess_out filename>]
|
[B<-sess_out filename>]
|
||||||
[B<-sess_in filename>]
|
[B<-sess_in filename>]
|
||||||
[B<-rand file(s)>]
|
[B<-rand file(s)>]
|
||||||
|
[B<-serverinfo types>]
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=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
|
The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
|
||||||
all others.
|
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
|
=back
|
||||||
|
|
||||||
=head1 CONNECTED COMMANDS
|
=head1 CONNECTED COMMANDS
|
||||||
|
@ -56,6 +56,7 @@ B<openssl> B<s_server>
|
|||||||
[B<-no_ticket>]
|
[B<-no_ticket>]
|
||||||
[B<-id_prefix arg>]
|
[B<-id_prefix arg>]
|
||||||
[B<-rand file(s)>]
|
[B<-rand file(s)>]
|
||||||
|
[B<-serverinfo file>]
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=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
|
The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
|
||||||
all others.
|
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
|
=back
|
||||||
|
|
||||||
=head1 CONNECTED COMMANDS
|
=head1 CONNECTED COMMANDS
|
||||||
|
45
doc/ssl/SSL_CTX_use_serverinfo.pod
Normal file
45
doc/ssl/SSL_CTX_use_serverinfo.pod
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
=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
|
@ -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
|
* All these functions return nonzero on success. Zero will terminate
|
||||||
* the handshake (and return a specific TLS Fatal alert, if the function
|
* 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.
|
* "ext_type" is a TLS "ExtensionType" from 0-65535.
|
||||||
* "in" is a pointer to TLS "extension_data" being provided to the cb.
|
* "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
|
* 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
|
* 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
|
* be noted and custom_srv_ext_second_cb_fn will still be invoked. A NULL
|
||||||
* custom_srv_ext_second_cb_fn is NULL, an empty ServerHello extension is
|
* custom_srv_ext_second_cb doesn't send a ServerHello extension.
|
||||||
* sent.
|
|
||||||
*/
|
*/
|
||||||
int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type,
|
int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type,
|
||||||
custom_cli_ext_first_cb_fn fn1,
|
custom_cli_ext_first_cb_fn fn1,
|
||||||
|
@ -880,58 +880,79 @@ static int serverinfo_find_extension(const unsigned char *serverinfo,
|
|||||||
|
|
||||||
/* end of serverinfo */
|
/* end of serverinfo */
|
||||||
if (serverinfo_length == 0)
|
if (serverinfo_length == 0)
|
||||||
return 0;
|
return -1; /* Extension not found */
|
||||||
|
|
||||||
/* read 2-byte type field */
|
/* read 2-byte type field */
|
||||||
if (serverinfo_length < 2)
|
if (serverinfo_length < 2)
|
||||||
return 0; /* error */
|
return 0; /* Error */
|
||||||
type = (serverinfo[0] << 8) + serverinfo[1];
|
type = (serverinfo[0] << 8) + serverinfo[1];
|
||||||
serverinfo += 2;
|
serverinfo += 2;
|
||||||
serverinfo_length -= 2;
|
serverinfo_length -= 2;
|
||||||
|
|
||||||
/* read 2-byte len field */
|
/* read 2-byte len field */
|
||||||
if (serverinfo_length < 2)
|
if (serverinfo_length < 2)
|
||||||
return 0; /* error */
|
return 0; /* Error */
|
||||||
len = (serverinfo[0] << 8) + serverinfo[1];
|
len = (serverinfo[0] << 8) + serverinfo[1];
|
||||||
serverinfo += 2;
|
serverinfo += 2;
|
||||||
serverinfo_length -= 2;
|
serverinfo_length -= 2;
|
||||||
|
|
||||||
if (len > serverinfo_length)
|
if (len > serverinfo_length)
|
||||||
return 0; /* error */
|
return 0; /* Error */
|
||||||
|
|
||||||
if (type == extension_type)
|
if (type == extension_type)
|
||||||
{
|
{
|
||||||
*extension_data = serverinfo;
|
*extension_data = serverinfo;
|
||||||
*extension_length = len;
|
*extension_length = len;
|
||||||
return 1;
|
return 1; /* Success */
|
||||||
}
|
}
|
||||||
|
|
||||||
serverinfo += len;
|
serverinfo += len;
|
||||||
serverinfo_length -= len;
|
serverinfo_length -= len;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0; /* Error */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serverinfo_srv_cb(SSL *s, unsigned short ext_type,
|
static int serverinfo_srv_first_cb(SSL *s, unsigned short ext_type,
|
||||||
const unsigned char **out, unsigned short *outlen,
|
const unsigned char *in,
|
||||||
void *arg)
|
unsigned short inlen, int *al,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
if (inlen != 0)
|
||||||
|
{
|
||||||
|
*al = SSL_AD_DECODE_ERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
const unsigned char *serverinfo = NULL;
|
||||||
size_t serverinfo_length = 0;
|
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,
|
if ((ssl_get_server_cert_serverinfo(s, &serverinfo,
|
||||||
&serverinfo_length)) != 0)
|
&serverinfo_length)) != 0)
|
||||||
{
|
{
|
||||||
/* Find the relevant extension from the serverinfo */
|
/* 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);
|
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
|
||||||
size_t serverinfo_length, SSL_CTX *ctx)
|
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)
|
if (serverinfo == NULL || serverinfo_length == 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -951,8 +972,9 @@ static int serverinfo_validate(const unsigned char *serverinfo,
|
|||||||
|
|
||||||
/* Register callbacks for extensions */
|
/* Register callbacks for extensions */
|
||||||
ext_type = (serverinfo[0] << 8) + serverinfo[1];
|
ext_type = (serverinfo[0] << 8) + serverinfo[1];
|
||||||
if (ctx && !SSL_CTX_set_custom_srv_ext(ctx, ext_type, NULL,
|
if (ctx && !SSL_CTX_set_custom_srv_ext(ctx, ext_type,
|
||||||
serverinfo_srv_cb, NULL))
|
serverinfo_srv_first_cb,
|
||||||
|
serverinfo_srv_second_cb, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
serverinfo += 2;
|
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);
|
SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,ERR_R_PASSED_NULL_PARAMETER);
|
||||||
return 0;
|
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);
|
SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,SSL_R_INVALID_SERVERINFO_DATA);
|
||||||
return(0);
|
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
|
/* Now that the serverinfo is validated and stored, go ahead and
|
||||||
* register callbacks. */
|
* 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);
|
SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,SSL_R_INVALID_SERVERINFO_DATA);
|
||||||
return(0);
|
return(0);
|
||||||
|
273
ssl/ssltest.c
273
ssl/ssltest.c
@ -371,27 +371,46 @@ static int verify_npn(SSL *client, SSL *server)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SCT_EXT_TYPE 18
|
#define SCT_EXT_TYPE 18
|
||||||
|
|
||||||
|
/* WARNING : below extension types are *NOT* IETF assigned, and
|
||||||
|
could conflict if these types are reassigned and handled
|
||||||
|
specially by OpenSSL in the future */
|
||||||
#define TACK_EXT_TYPE 62208
|
#define TACK_EXT_TYPE 62208
|
||||||
|
#define CUSTOM_EXT_TYPE_0 1000
|
||||||
|
#define CUSTOM_EXT_TYPE_1 1001
|
||||||
|
#define CUSTOM_EXT_TYPE_2 1002
|
||||||
|
#define CUSTOM_EXT_TYPE_3 1003
|
||||||
|
|
||||||
|
const char custom_ext_cli_string[] = "abc";
|
||||||
|
const char custom_ext_srv_string[] = "defg";
|
||||||
|
|
||||||
/* These set from cmdline */
|
/* These set from cmdline */
|
||||||
char* serverinfo_file = NULL;
|
char* serverinfo_file = NULL;
|
||||||
int serverinfo_sct = 0;
|
int serverinfo_sct = 0;
|
||||||
int serverinfo_tack = 0;
|
int serverinfo_tack = 0;
|
||||||
|
|
||||||
|
/* These set based on extension callbacks */
|
||||||
int serverinfo_sct_seen = 0;
|
int serverinfo_sct_seen = 0;
|
||||||
int serverinfo_tack_seen = 0;
|
int serverinfo_tack_seen = 0;
|
||||||
int serverinfo_other_seen = 0;
|
int serverinfo_other_seen = 0;
|
||||||
|
|
||||||
|
/* This set from cmdline */
|
||||||
|
int custom_ext = 0;
|
||||||
|
|
||||||
|
/* This set based on extension callbacks */
|
||||||
|
int custom_ext_error = 0;
|
||||||
|
|
||||||
static int serverinfo_cli_cb(SSL* s, unsigned short ext_type,
|
static int serverinfo_cli_cb(SSL* s, unsigned short ext_type,
|
||||||
const unsigned char* in, unsigned short inlen,
|
const unsigned char* in, unsigned short inlen,
|
||||||
int* al, void* arg)
|
int* al, void* arg)
|
||||||
{
|
{
|
||||||
if (ext_type == SCT_EXT_TYPE)
|
if (ext_type == SCT_EXT_TYPE)
|
||||||
serverinfo_sct_seen++;
|
serverinfo_sct_seen++;
|
||||||
else if (ext_type == TACK_EXT_TYPE)
|
else if (ext_type == TACK_EXT_TYPE)
|
||||||
serverinfo_tack_seen++;
|
serverinfo_tack_seen++;
|
||||||
else
|
else
|
||||||
serverinfo_other_seen++;
|
serverinfo_other_seen++;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int verify_serverinfo()
|
static int verify_serverinfo()
|
||||||
@ -405,6 +424,188 @@ static int verify_serverinfo()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Four test cases for custom extensions:
|
||||||
|
* 0 - no ClientHello extension or ServerHello response
|
||||||
|
* 1 - ClientHello with "abc", no response
|
||||||
|
* 2 - ClientHello with "abc", empty response
|
||||||
|
* 3 - ClientHello with "abc", "defg" response
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int custom_ext_0_cli_first_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char **out,
|
||||||
|
unsigned short *outlen, void *arg)
|
||||||
|
{
|
||||||
|
if (ext_type != CUSTOM_EXT_TYPE_0)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
return -1; /* Don't send an extension */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_0_cli_second_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char *in,
|
||||||
|
unsigned short inlen, int *al,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
custom_ext_error = 1; /* Shouldn't be called */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_1_cli_first_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char **out,
|
||||||
|
unsigned short *outlen, void *arg)
|
||||||
|
{
|
||||||
|
if (ext_type != CUSTOM_EXT_TYPE_1)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
*out = (const unsigned char*)custom_ext_cli_string;
|
||||||
|
*outlen = strlen(custom_ext_cli_string);
|
||||||
|
return 1; /* Send "abc" */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_1_cli_second_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char *in,
|
||||||
|
unsigned short inlen, int *al,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
custom_ext_error = 1; /* Shouldn't be called */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_2_cli_first_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char **out,
|
||||||
|
unsigned short *outlen, void *arg)
|
||||||
|
{
|
||||||
|
if (ext_type != CUSTOM_EXT_TYPE_2)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
*out = (const unsigned char*)custom_ext_cli_string;
|
||||||
|
*outlen = strlen(custom_ext_cli_string);
|
||||||
|
return 1; /* Send "abc" */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_2_cli_second_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char *in,
|
||||||
|
unsigned short inlen, int *al,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
if (ext_type != CUSTOM_EXT_TYPE_2)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
if (inlen != 0)
|
||||||
|
custom_ext_error = 1; /* Should be empty response */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_3_cli_first_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char **out,
|
||||||
|
unsigned short *outlen, void *arg)
|
||||||
|
{
|
||||||
|
if (ext_type != CUSTOM_EXT_TYPE_3)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
*out = (const unsigned char*)custom_ext_cli_string;
|
||||||
|
*outlen = strlen(custom_ext_cli_string);
|
||||||
|
return 1; /* Send "abc" */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_3_cli_second_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char *in,
|
||||||
|
unsigned short inlen, int *al,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
if (ext_type != CUSTOM_EXT_TYPE_3)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
if (inlen != strlen(custom_ext_srv_string))
|
||||||
|
custom_ext_error = 1;
|
||||||
|
if (memcmp(custom_ext_srv_string, in, inlen) != 0)
|
||||||
|
custom_ext_error = 1; /* Check for "defg" */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int custom_ext_0_srv_first_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char *in,
|
||||||
|
unsigned short inlen, int *al,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
custom_ext_error = 1;
|
||||||
|
return 0; /* Shouldn't be called */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_0_srv_second_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char **out,
|
||||||
|
unsigned short *outlen, void *arg)
|
||||||
|
{
|
||||||
|
custom_ext_error = 1;
|
||||||
|
return 0; /* Shouldn't be called */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_1_srv_first_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char *in,
|
||||||
|
unsigned short inlen, int *al,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
if (ext_type != CUSTOM_EXT_TYPE_1)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
/* Check for "abc" */
|
||||||
|
if (inlen != strlen(custom_ext_cli_string))
|
||||||
|
custom_ext_error = 1;
|
||||||
|
if (memcmp(in, custom_ext_cli_string, inlen) != 0)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_1_srv_second_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char **out,
|
||||||
|
unsigned short *outlen, void *arg)
|
||||||
|
{
|
||||||
|
return -1; /* Don't send an extension */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_2_srv_first_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char *in,
|
||||||
|
unsigned short inlen, int *al,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
if (ext_type != CUSTOM_EXT_TYPE_2)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
/* Check for "abc" */
|
||||||
|
if (inlen != strlen(custom_ext_cli_string))
|
||||||
|
custom_ext_error = 1;
|
||||||
|
if (memcmp(in, custom_ext_cli_string, inlen) != 0)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_2_srv_second_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char **out,
|
||||||
|
unsigned short *outlen, void *arg)
|
||||||
|
{
|
||||||
|
*out = NULL;
|
||||||
|
*outlen = 0;
|
||||||
|
return 1; /* Send empty extension */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_3_srv_first_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char *in,
|
||||||
|
unsigned short inlen, int *al,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
if (ext_type != CUSTOM_EXT_TYPE_3)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
/* Check for "abc" */
|
||||||
|
if (inlen != strlen(custom_ext_cli_string))
|
||||||
|
custom_ext_error = 1;
|
||||||
|
if (memcmp(in, custom_ext_cli_string, inlen) != 0)
|
||||||
|
custom_ext_error = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int custom_ext_3_srv_second_cb(SSL *s, unsigned short ext_type,
|
||||||
|
const unsigned char **out,
|
||||||
|
unsigned short *outlen, void *arg)
|
||||||
|
{
|
||||||
|
*out = (const unsigned char*)custom_ext_srv_string;
|
||||||
|
*outlen = strlen(custom_ext_srv_string);
|
||||||
|
return 1; /* Send "defg" */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *cipher=NULL;
|
static char *cipher=NULL;
|
||||||
static int verbose=0;
|
static int verbose=0;
|
||||||
static int debug=0;
|
static int debug=0;
|
||||||
@ -484,9 +685,10 @@ static void sv_usage(void)
|
|||||||
fprintf(stderr," -npn_server - have server side offer NPN\n");
|
fprintf(stderr," -npn_server - have server side offer NPN\n");
|
||||||
fprintf(stderr," -npn_server_reject - have server reject NPN\n");
|
fprintf(stderr," -npn_server_reject - have server reject NPN\n");
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr," -serverinfo_file - have server use this file\n");
|
fprintf(stderr," -serverinfo_file file - have server use this file\n");
|
||||||
fprintf(stderr," -serverinfo_sct - have client offer and expect SCT\n");
|
fprintf(stderr," -serverinfo_sct - have client offer and expect SCT\n");
|
||||||
fprintf(stderr," -serverinfo_tack - have client offer and expect TACK\n");
|
fprintf(stderr," -serverinfo_tack - have client offer and expect TACK\n");
|
||||||
|
fprintf(stderr," -custom_ext - try various custom extension callbacks\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_details(SSL *c_ssl, const char *prefix)
|
static void print_details(SSL *c_ssl, const char *prefix)
|
||||||
@ -912,6 +1114,10 @@ int main(int argc, char *argv[])
|
|||||||
if (--argc < 1) goto bad;
|
if (--argc < 1) goto bad;
|
||||||
serverinfo_file = *(++argv);
|
serverinfo_file = *(++argv);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(*argv,"-custom_ext") == 0)
|
||||||
|
{
|
||||||
|
custom_ext = 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr,"unknown option %s\n",*argv);
|
fprintf(stderr,"unknown option %s\n",*argv);
|
||||||
@ -1238,9 +1444,11 @@ bad:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (serverinfo_sct)
|
if (serverinfo_sct)
|
||||||
SSL_CTX_set_custom_cli_ext(c_ctx, SCT_EXT_TYPE, NULL, serverinfo_cli_cb, NULL);
|
SSL_CTX_set_custom_cli_ext(c_ctx, SCT_EXT_TYPE, NULL,
|
||||||
|
serverinfo_cli_cb, NULL);
|
||||||
if (serverinfo_tack)
|
if (serverinfo_tack)
|
||||||
SSL_CTX_set_custom_cli_ext(c_ctx, TACK_EXT_TYPE, NULL, serverinfo_cli_cb, NULL);
|
SSL_CTX_set_custom_cli_ext(c_ctx, TACK_EXT_TYPE, NULL,
|
||||||
|
serverinfo_cli_cb, NULL);
|
||||||
|
|
||||||
if (serverinfo_file)
|
if (serverinfo_file)
|
||||||
if (!SSL_CTX_use_serverinfo_file(s_ctx, serverinfo_file))
|
if (!SSL_CTX_use_serverinfo_file(s_ctx, serverinfo_file))
|
||||||
@ -1249,6 +1457,36 @@ bad:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (custom_ext)
|
||||||
|
{
|
||||||
|
SSL_CTX_set_custom_cli_ext(c_ctx, CUSTOM_EXT_TYPE_0,
|
||||||
|
custom_ext_0_cli_first_cb,
|
||||||
|
custom_ext_0_cli_second_cb, NULL);
|
||||||
|
SSL_CTX_set_custom_cli_ext(c_ctx, CUSTOM_EXT_TYPE_1,
|
||||||
|
custom_ext_1_cli_first_cb,
|
||||||
|
custom_ext_1_cli_second_cb, NULL);
|
||||||
|
SSL_CTX_set_custom_cli_ext(c_ctx, CUSTOM_EXT_TYPE_2,
|
||||||
|
custom_ext_2_cli_first_cb,
|
||||||
|
custom_ext_2_cli_second_cb, NULL);
|
||||||
|
SSL_CTX_set_custom_cli_ext(c_ctx, CUSTOM_EXT_TYPE_3,
|
||||||
|
custom_ext_3_cli_first_cb,
|
||||||
|
custom_ext_3_cli_second_cb, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
SSL_CTX_set_custom_srv_ext(s_ctx, CUSTOM_EXT_TYPE_0,
|
||||||
|
custom_ext_0_srv_first_cb,
|
||||||
|
custom_ext_0_srv_second_cb, NULL);
|
||||||
|
SSL_CTX_set_custom_srv_ext(s_ctx, CUSTOM_EXT_TYPE_1,
|
||||||
|
custom_ext_1_srv_first_cb,
|
||||||
|
custom_ext_1_srv_second_cb, NULL);
|
||||||
|
SSL_CTX_set_custom_srv_ext(s_ctx, CUSTOM_EXT_TYPE_2,
|
||||||
|
custom_ext_2_srv_first_cb,
|
||||||
|
custom_ext_2_srv_second_cb, NULL);
|
||||||
|
SSL_CTX_set_custom_srv_ext(s_ctx, CUSTOM_EXT_TYPE_3,
|
||||||
|
custom_ext_3_srv_first_cb,
|
||||||
|
custom_ext_3_srv_second_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
c_ssl=SSL_new(c_ctx);
|
c_ssl=SSL_new(c_ctx);
|
||||||
s_ssl=SSL_new(s_ctx);
|
s_ssl=SSL_new(s_ctx);
|
||||||
|
|
||||||
@ -1712,6 +1950,12 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (custom_ext_error)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
@ -2019,6 +2263,11 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
|
|||||||
ret = 1;
|
ret = 1;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
if (custom_ext_error)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
ret=0;
|
ret=0;
|
||||||
err:
|
err:
|
||||||
/* We have to set the BIO's to NULL otherwise they will be
|
/* We have to set the BIO's to NULL otherwise they will be
|
||||||
|
32
ssl/t1_lib.c
32
ssl/t1_lib.c
@ -1455,10 +1455,19 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
|
|||||||
unsigned short outlen = 0;
|
unsigned short outlen = 0;
|
||||||
|
|
||||||
record = &s->ctx->custom_cli_ext_records[i];
|
record = &s->ctx->custom_cli_ext_records[i];
|
||||||
if (record->fn1 && !record->fn1(s, record->ext_type,
|
/* NULL callback sends empty extension */
|
||||||
|
/* -1 from callback omits extension */
|
||||||
|
if (record->fn1)
|
||||||
|
{
|
||||||
|
int cb_retval = 0;
|
||||||
|
cb_retval = record->fn1(s, record->ext_type,
|
||||||
&out, &outlen,
|
&out, &outlen,
|
||||||
record->arg))
|
record->arg);
|
||||||
return NULL;
|
if (cb_retval == 0)
|
||||||
|
return NULL; /* error */
|
||||||
|
if (cb_retval == -1)
|
||||||
|
continue; /* skip this extension */
|
||||||
|
}
|
||||||
if (limit < ret + 4 + outlen)
|
if (limit < ret + 4 + outlen)
|
||||||
return NULL;
|
return NULL;
|
||||||
s2n(record->ext_type, ret);
|
s2n(record->ext_type, ret);
|
||||||
@ -1751,11 +1760,18 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
|
|||||||
{
|
{
|
||||||
const unsigned char *out = NULL;
|
const unsigned char *out = NULL;
|
||||||
unsigned short outlen = 0;
|
unsigned short outlen = 0;
|
||||||
if (record->fn2
|
int cb_retval = 0;
|
||||||
&& !record->fn2(s, record->ext_type,
|
|
||||||
&out, &outlen,
|
/* NULL callback or -1 omits extension */
|
||||||
record->arg))
|
if (!record->fn2)
|
||||||
return NULL;
|
break;
|
||||||
|
cb_retval = record->fn2(s, record->ext_type,
|
||||||
|
&out, &outlen,
|
||||||
|
record->arg);
|
||||||
|
if (cb_retval == 0)
|
||||||
|
return NULL; /* error */
|
||||||
|
if (cb_retval == -1)
|
||||||
|
break; /* skip this extension */
|
||||||
if (limit < ret + 4 + outlen)
|
if (limit < ret + 4 + outlen)
|
||||||
return NULL;
|
return NULL;
|
||||||
s2n(record->ext_type, ret);
|
s2n(record->ext_type, ret);
|
||||||
|
@ -178,13 +178,22 @@ $ssltest -bio_pair -tls1 -npn_client -npn_server || exit 1
|
|||||||
$ssltest -bio_pair -tls1 -npn_client -npn_server -num 2 || exit 1
|
$ssltest -bio_pair -tls1 -npn_client -npn_server -num 2 || exit 1
|
||||||
$ssltest -bio_pair -tls1 -npn_client -npn_server -num 2 -reuse || exit 1
|
$ssltest -bio_pair -tls1 -npn_client -npn_server -num 2 -reuse || exit 1
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Custom Extension tests
|
||||||
|
|
||||||
|
echo test tls1 with custom extensions
|
||||||
|
$ssltest -bio_pair -tls1 -custom_ext || exit 1
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# Serverinfo tests
|
# Serverinfo tests
|
||||||
|
|
||||||
|
echo test tls1 with serverinfo
|
||||||
$ssltest -bio_pair -tls1 -serverinfo_file $serverinfo || exit 1
|
$ssltest -bio_pair -tls1 -serverinfo_file $serverinfo || exit 1
|
||||||
$ssltest -bio_pair -tls1 -serverinfo_file $serverinfo -serverinfo_sct || exit 1
|
$ssltest -bio_pair -tls1 -serverinfo_file $serverinfo -serverinfo_sct || exit 1
|
||||||
$ssltest -bio_pair -tls1 -serverinfo_file $serverinfo -serverinfo_tack || exit 1
|
$ssltest -bio_pair -tls1 -serverinfo_file $serverinfo -serverinfo_tack || exit 1
|
||||||
$ssltest -bio_pair -tls1 -serverinfo_file $serverinfo -serverinfo_sct -serverinfo_tack || exit 1
|
$ssltest -bio_pair -tls1 -serverinfo_file $serverinfo -serverinfo_sct -serverinfo_tack || exit 1
|
||||||
|
$ssltest -bio_pair -tls1 -custom_ext -serverinfo_file $serverinfo -serverinfo_sct -serverinfo_tack || exit 1
|
||||||
|
|
||||||
|
|
||||||
if ../util/shlib_wrap.sh ../apps/openssl no-srp; then
|
if ../util/shlib_wrap.sh ../apps/openssl no-srp; then
|
||||||
echo skipping SRP tests
|
echo skipping SRP tests
|
||||||
|
Loading…
x
Reference in New Issue
Block a user