Add tests for ALPN functionality.
Conflicts: ssl/ssltest.c
This commit is contained in:
parent
a108f841ba
commit
a898936218
@ -1329,6 +1329,7 @@ bad:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len);
|
SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len);
|
||||||
|
OPENSSL_free(alpn);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_TLSEXT
|
#ifndef OPENSSL_NO_TLSEXT
|
||||||
|
161
ssl/ssltest.c
161
ssl/ssltest.c
@ -370,6 +370,127 @@ static int verify_npn(SSL *client, SSL *server)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const char *alpn_client;
|
||||||
|
static const char *alpn_server;
|
||||||
|
static const char *alpn_expected;
|
||||||
|
static unsigned char *alpn_selected;
|
||||||
|
|
||||||
|
/* next_protos_parse parses a comma separated list of strings into a string
|
||||||
|
* in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
|
||||||
|
* outlen: (output) set to the length of the resulting buffer on success.
|
||||||
|
* err: (maybe NULL) on failure, an error message line is written to this BIO.
|
||||||
|
* in: a NUL termianted string like "abc,def,ghi"
|
||||||
|
*
|
||||||
|
* returns: a malloced buffer or NULL on failure.
|
||||||
|
*/
|
||||||
|
static unsigned char *next_protos_parse(unsigned short *outlen, const char *in)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
unsigned char *out;
|
||||||
|
size_t i, start = 0;
|
||||||
|
|
||||||
|
len = strlen(in);
|
||||||
|
if (len >= 65535)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
out = OPENSSL_malloc(strlen(in) + 1);
|
||||||
|
if (!out)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i <= len; ++i)
|
||||||
|
{
|
||||||
|
if (i == len || in[i] == ',')
|
||||||
|
{
|
||||||
|
if (i - start > 255)
|
||||||
|
{
|
||||||
|
OPENSSL_free(out);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
out[start] = i - start;
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out[i+1] = in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
*outlen = len + 1;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cb_server_alpn(SSL *s, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
|
||||||
|
{
|
||||||
|
unsigned char *protos;
|
||||||
|
unsigned short protos_len;
|
||||||
|
|
||||||
|
protos = next_protos_parse(&protos_len, alpn_server);
|
||||||
|
if (protos == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "failed to parser ALPN server protocol string: %s\n", alpn_server);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSL_select_next_proto((unsigned char**) out, outlen, protos, protos_len, in, inlen) !=
|
||||||
|
OPENSSL_NPN_NEGOTIATED)
|
||||||
|
{
|
||||||
|
OPENSSL_free(protos);
|
||||||
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make a copy of the selected protocol which will be freed in verify_alpn. */
|
||||||
|
alpn_selected = OPENSSL_malloc(*outlen);
|
||||||
|
memcpy(alpn_selected, *out, *outlen);
|
||||||
|
*out = alpn_selected;
|
||||||
|
|
||||||
|
OPENSSL_free(protos);
|
||||||
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verify_alpn(SSL *client, SSL *server)
|
||||||
|
{
|
||||||
|
const unsigned char *client_proto, *server_proto;
|
||||||
|
unsigned int client_proto_len = 0, server_proto_len = 0;
|
||||||
|
SSL_get0_alpn_selected(client, &client_proto, &client_proto_len);
|
||||||
|
SSL_get0_alpn_selected(server, &server_proto, &server_proto_len);
|
||||||
|
|
||||||
|
if (alpn_selected != NULL)
|
||||||
|
{
|
||||||
|
OPENSSL_free(alpn_selected);
|
||||||
|
alpn_selected = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client_proto_len != server_proto_len ||
|
||||||
|
memcmp(client_proto, server_proto, client_proto_len) != 0)
|
||||||
|
{
|
||||||
|
BIO_printf(bio_stdout, "ALPN selected protocols differ!\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client_proto_len > 0 && alpn_expected == NULL)
|
||||||
|
{
|
||||||
|
BIO_printf(bio_stdout, "ALPN unexpectedly negotiated\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alpn_expected != NULL &&
|
||||||
|
(client_proto_len != strlen(alpn_expected) ||
|
||||||
|
memcmp(client_proto, alpn_expected, client_proto_len) != 0))
|
||||||
|
{
|
||||||
|
BIO_printf(bio_stdout, "ALPN selected protocols not equal to expected protocol: %s\n", alpn_expected);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
BIO_printf(bio_stdout, "ALPN results: client: '");
|
||||||
|
BIO_write(bio_stdout, client_proto, client_proto_len);
|
||||||
|
BIO_printf(bio_stdout, "', server: '");
|
||||||
|
BIO_write(bio_stdout, server_proto, server_proto_len);
|
||||||
|
BIO_printf(bio_stdout, "'\n");
|
||||||
|
BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '%s'\n", alpn_client, alpn_server);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#define SCT_EXT_TYPE 18
|
#define SCT_EXT_TYPE 18
|
||||||
|
|
||||||
/* WARNING : below extension types are *NOT* IETF assigned, and
|
/* WARNING : below extension types are *NOT* IETF assigned, and
|
||||||
@ -689,6 +810,9 @@ static void sv_usage(void)
|
|||||||
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");
|
fprintf(stderr," -custom_ext - try various custom extension callbacks\n");
|
||||||
|
fprintf(stderr," -alpn_client <string> - have client side offer ALPN\n");
|
||||||
|
fprintf(stderr," -alpn_server <string> - have server side offer ALPN\n");
|
||||||
|
fprintf(stderr," -alpn_expected <string> - the ALPN protocol that should be negotiated\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_details(SSL *c_ssl, const char *prefix)
|
static void print_details(SSL *c_ssl, const char *prefix)
|
||||||
@ -1118,6 +1242,21 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
custom_ext = 1;
|
custom_ext = 1;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(*argv,"-alpn_client") == 0)
|
||||||
|
{
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
alpn_client = *(++argv);
|
||||||
|
}
|
||||||
|
else if (strcmp(*argv,"-alpn_server") == 0)
|
||||||
|
{
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
alpn_server = *(++argv);
|
||||||
|
}
|
||||||
|
else if (strcmp(*argv,"-alpn_expected") == 0)
|
||||||
|
{
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
alpn_expected = *(++argv);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr,"unknown option %s\n",*argv);
|
fprintf(stderr,"unknown option %s\n",*argv);
|
||||||
@ -1487,6 +1626,23 @@ bad:
|
|||||||
custom_ext_3_srv_second_cb, NULL);
|
custom_ext_3_srv_second_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (alpn_server)
|
||||||
|
SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, NULL);
|
||||||
|
|
||||||
|
if (alpn_client)
|
||||||
|
{
|
||||||
|
unsigned short alpn_len;
|
||||||
|
unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client);
|
||||||
|
|
||||||
|
if (alpn == NULL)
|
||||||
|
{
|
||||||
|
BIO_printf(bio_err, "Error parsing -alpn_client argument\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len);
|
||||||
|
OPENSSL_free(alpn);
|
||||||
|
}
|
||||||
|
|
||||||
c_ssl=SSL_new(c_ctx);
|
c_ssl=SSL_new(c_ctx);
|
||||||
s_ssl=SSL_new(s_ctx);
|
s_ssl=SSL_new(s_ctx);
|
||||||
|
|
||||||
@ -1949,6 +2105,11 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
|
|||||||
ret = 1;
|
ret = 1;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
if (verify_alpn(c_ssl, s_ssl) < 0)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (custom_ext_error)
|
if (custom_ext_error)
|
||||||
{
|
{
|
||||||
|
12
test/testssl
12
test/testssl
@ -195,6 +195,18 @@ $ssltest -bio_pair -tls1 -serverinfo_file $serverinfo -serverinfo_sct -serverinf
|
|||||||
$ssltest -bio_pair -tls1 -custom_ext -serverinfo_file $serverinfo -serverinfo_sct -serverinfo_tack || exit 1
|
$ssltest -bio_pair -tls1 -custom_ext -serverinfo_file $serverinfo -serverinfo_sct -serverinfo_tack || exit 1
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# ALPN tests
|
||||||
|
|
||||||
|
$ssltest -bio_pair -tls1 -alpn_client foo -alpn_server bar || exit 1
|
||||||
|
$ssltest -bio_pair -tls1 -alpn_client foo -alpn_server foo -alpn_expected foo || exit 1
|
||||||
|
$ssltest -bio_pair -tls1 -alpn_client foo,bar -alpn_server foo -alpn_expected foo || exit 1
|
||||||
|
$ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server foo -alpn_expected foo || exit 1
|
||||||
|
$ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server foo,bar -alpn_expected foo || exit 1
|
||||||
|
$ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server bar,foo -alpn_expected bar || exit 1
|
||||||
|
$ssltest -bio_pair -tls1 -alpn_client foo,bar -alpn_server bar,foo -alpn_expected bar || exit 1
|
||||||
|
$ssltest -bio_pair -tls1 -alpn_client baz -alpn_server bar,foo || 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
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user