Trying cherrypick:

Add support for arbitrary TLS extensions.

Contributed by Trevor Perrin.

Conflicts:

	CHANGES
	ssl/ssl.h
	ssl/ssltest.c
	test/testssl

Fix compilation due to #endif.

Cherrypicking more stuff.

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.

Conflicts:

	test/testssl
This commit is contained in:
Trevor
2013-05-12 18:55:27 -07:00
committed by Ben Laurie
parent 28c08222c0
commit e27711cfdd
20 changed files with 1151 additions and 5 deletions

View File

@@ -295,6 +295,242 @@ static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
static BIO *bio_err=NULL;
static BIO *bio_stdout=NULL;
#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 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 */
char* serverinfo_file = NULL;
int serverinfo_sct = 0;
int serverinfo_tack = 0;
/* These set based on extension callbacks */
int serverinfo_sct_seen = 0;
int serverinfo_tack_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,
const unsigned char* in, unsigned short inlen,
int* al, void* arg)
{
if (ext_type == SCT_EXT_TYPE)
serverinfo_sct_seen++;
else if (ext_type == TACK_EXT_TYPE)
serverinfo_tack_seen++;
else
serverinfo_other_seen++;
return 1;
}
static int verify_serverinfo()
{
if (serverinfo_sct != serverinfo_sct_seen)
return -1;
if (serverinfo_tack != serverinfo_tack_seen)
return -1;
if (serverinfo_other_seen)
return -1;
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 int verbose=0;
static int debug=0;
@@ -374,6 +610,10 @@ static void sv_usage(void)
fprintf(stderr," -c_support_proof - indicate client support for server_authz audit proofs\n");
fprintf(stderr," -c_require_proof - fail if no audit proof is sent\n");
#endif
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_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)
@@ -845,6 +1085,23 @@ int main(int argc, char *argv[])
tls1 = 1;
}
#endif
else if (strcmp(*argv,"-serverinfo_sct") == 0)
{
serverinfo_sct = 1;
}
else if (strcmp(*argv,"-serverinfo_tack") == 0)
{
serverinfo_tack = 1;
}
else if (strcmp(*argv,"-serverinfo_file") == 0)
{
if (--argc < 1) goto bad;
serverinfo_file = *(++argv);
}
else if (strcmp(*argv,"-custom_ext") == 0)
{
custom_ext = 1;
}
else
{
fprintf(stderr,"unknown option %s\n",*argv);
@@ -1187,6 +1444,50 @@ bad:
}
#endif
if (serverinfo_sct)
SSL_CTX_set_custom_cli_ext(c_ctx, SCT_EXT_TYPE, NULL,
serverinfo_cli_cb, NULL);
if (serverinfo_tack)
SSL_CTX_set_custom_cli_ext(c_ctx, TACK_EXT_TYPE, NULL,
serverinfo_cli_cb, NULL);
if (serverinfo_file)
if (!SSL_CTX_use_serverinfo_file(s_ctx, serverinfo_file))
{
BIO_printf(bio_err, "missing serverinfo file\n");
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);
s_ssl=SSL_new(s_ctx);
@@ -1641,6 +1942,19 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
if (verbose)
print_details(c_ssl, "DONE via BIO pair: ");
if (verify_serverinfo() < 0)
{
ret = 1;
goto err;
}
if (custom_ext_error)
{
ret = 1;
goto err;
}
end:
ret = 0;
@@ -1936,6 +2250,17 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
if (verbose)
print_details(c_ssl, "DONE: ");
if (verify_serverinfo() < 0)
{
ret = 1;
goto err;
}
if (custom_ext_error)
{
ret = 1;
goto err;
}
ret=0;
err:
/* We have to set the BIO's to NULL otherwise they will be