diff options
| author | jsing <> | 2014-12-10 15:06:50 +0000 |
|---|---|---|
| committer | jsing <> | 2014-12-10 15:06:50 +0000 |
| commit | a117e2e640709457de5d7640f35807a4b578f889 (patch) | |
| tree | ca3c1ccfc79c9a642c89eb73b9079893e0443f67 | |
| parent | 6cc508de790e6c3b90a8cfe97b50ba5c7a7bea98 (diff) | |
| download | openbsd-a117e2e640709457de5d7640f35807a4b578f889.tar.gz openbsd-a117e2e640709457de5d7640f35807a4b578f889.tar.bz2 openbsd-a117e2e640709457de5d7640f35807a4b578f889.zip | |
Add regress for ALPN.
Based on OpenSSL.
Diffstat (limited to '')
| -rw-r--r-- | src/regress/lib/libssl/ssl/ssltest.c | 162 | ||||
| -rw-r--r-- | src/regress/lib/libssl/ssl/testssl | 19 |
2 files changed, 180 insertions, 1 deletions
diff --git a/src/regress/lib/libssl/ssl/ssltest.c b/src/regress/lib/libssl/ssl/ssltest.c index b1ca0d8c7d..fa869d0f24 100644 --- a/src/regress/lib/libssl/ssl/ssltest.c +++ b/src/regress/lib/libssl/ssl/ssltest.c | |||
| @@ -284,6 +284,128 @@ verify_npn(SSL *client, SSL *server) | |||
| 284 | } | 284 | } |
| 285 | #endif | 285 | #endif |
| 286 | 286 | ||
| 287 | static const char *alpn_client; | ||
| 288 | static const char *alpn_server; | ||
| 289 | static const char *alpn_expected; | ||
| 290 | static unsigned char *alpn_selected; | ||
| 291 | |||
| 292 | /* | ||
| 293 | * next_protos_parse parses a comma separated list of strings into a string | ||
| 294 | * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. | ||
| 295 | * outlen: (output) set to the length of the resulting buffer on success. | ||
| 296 | * err: (maybe NULL) on failure, an error message line is written to this BIO. | ||
| 297 | * in: a NUL terminated string like "abc,def,ghi" | ||
| 298 | * | ||
| 299 | * returns: a malloced buffer or NULL on failure. | ||
| 300 | */ | ||
| 301 | static unsigned char * | ||
| 302 | next_protos_parse(unsigned short *outlen, const char *in) | ||
| 303 | { | ||
| 304 | size_t i, len, start = 0; | ||
| 305 | unsigned char *out; | ||
| 306 | |||
| 307 | len = strlen(in); | ||
| 308 | if (len >= 65535) | ||
| 309 | return (NULL); | ||
| 310 | |||
| 311 | if ((out = malloc(strlen(in) + 1)) == NULL) | ||
| 312 | return (NULL); | ||
| 313 | |||
| 314 | for (i = 0; i <= len; ++i) { | ||
| 315 | if (i == len || in[i] == ',') { | ||
| 316 | if (i - start > 255) { | ||
| 317 | free(out); | ||
| 318 | return (NULL); | ||
| 319 | } | ||
| 320 | out[start] = i - start; | ||
| 321 | start = i + 1; | ||
| 322 | } else | ||
| 323 | out[i+1] = in[i]; | ||
| 324 | } | ||
| 325 | *outlen = len + 1; | ||
| 326 | return (out); | ||
| 327 | } | ||
| 328 | |||
| 329 | static int | ||
| 330 | cb_server_alpn(SSL *s, const unsigned char **out, unsigned char *outlen, | ||
| 331 | const unsigned char *in, unsigned int inlen, void *arg) | ||
| 332 | { | ||
| 333 | unsigned char *protos; | ||
| 334 | unsigned short protos_len; | ||
| 335 | |||
| 336 | if ((protos = next_protos_parse(&protos_len, alpn_server)) == NULL) { | ||
| 337 | fprintf(stderr, | ||
| 338 | "failed to parser ALPN server protocol string: %s\n", | ||
| 339 | alpn_server); | ||
| 340 | abort(); | ||
| 341 | } | ||
| 342 | |||
| 343 | if (SSL_select_next_proto((unsigned char **)out, outlen, protos, | ||
| 344 | protos_len, in, inlen) != OPENSSL_NPN_NEGOTIATED) { | ||
| 345 | free(protos); | ||
| 346 | return (SSL_TLSEXT_ERR_NOACK); | ||
| 347 | } | ||
| 348 | |||
| 349 | /* | ||
| 350 | * Make a copy of the selected protocol which will be freed in | ||
| 351 | * verify_alpn. | ||
| 352 | */ | ||
| 353 | if ((alpn_selected = malloc(*outlen)) == NULL) { | ||
| 354 | fprintf(stderr, "malloc failed\n"); | ||
| 355 | abort(); | ||
| 356 | } | ||
| 357 | memcpy(alpn_selected, *out, *outlen); | ||
| 358 | *out = alpn_selected; | ||
| 359 | free(protos); | ||
| 360 | |||
| 361 | return (SSL_TLSEXT_ERR_OK); | ||
| 362 | } | ||
| 363 | |||
| 364 | static int | ||
| 365 | verify_alpn(SSL *client, SSL *server) | ||
| 366 | { | ||
| 367 | const unsigned char *client_proto, *server_proto; | ||
| 368 | unsigned int client_proto_len = 0, server_proto_len = 0; | ||
| 369 | |||
| 370 | SSL_get0_alpn_selected(client, &client_proto, &client_proto_len); | ||
| 371 | SSL_get0_alpn_selected(server, &server_proto, &server_proto_len); | ||
| 372 | |||
| 373 | free(alpn_selected); | ||
| 374 | alpn_selected = NULL; | ||
| 375 | |||
| 376 | if (client_proto_len != server_proto_len || | ||
| 377 | memcmp(client_proto, server_proto, client_proto_len) != 0) { | ||
| 378 | BIO_printf(bio_stdout, "ALPN selected protocols differ!\n"); | ||
| 379 | goto err; | ||
| 380 | } | ||
| 381 | |||
| 382 | if (client_proto_len > 0 && alpn_expected == NULL) { | ||
| 383 | BIO_printf(bio_stdout, "ALPN unexpectedly negotiated\n"); | ||
| 384 | goto err; | ||
| 385 | } | ||
| 386 | |||
| 387 | if (alpn_expected != NULL && | ||
| 388 | (client_proto_len != strlen(alpn_expected) || | ||
| 389 | memcmp(client_proto, alpn_expected, client_proto_len) != 0)) { | ||
| 390 | BIO_printf(bio_stdout, "ALPN selected protocols not equal to " | ||
| 391 | "expected protocol: %s\n", alpn_expected); | ||
| 392 | goto err; | ||
| 393 | } | ||
| 394 | |||
| 395 | return (0); | ||
| 396 | |||
| 397 | err: | ||
| 398 | BIO_printf(bio_stdout, "ALPN results: client: '"); | ||
| 399 | BIO_write(bio_stdout, client_proto, client_proto_len); | ||
| 400 | BIO_printf(bio_stdout, "', server: '"); | ||
| 401 | BIO_write(bio_stdout, server_proto, server_proto_len); | ||
| 402 | BIO_printf(bio_stdout, "'\n"); | ||
| 403 | BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '%s'\n", | ||
| 404 | alpn_client, alpn_server); | ||
| 405 | |||
| 406 | return (-1); | ||
| 407 | } | ||
| 408 | |||
| 287 | static char *cipher = NULL; | 409 | static char *cipher = NULL; |
| 288 | static int verbose = 0; | 410 | static int verbose = 0; |
| 289 | static int debug = 0; | 411 | static int debug = 0; |
| @@ -334,6 +456,9 @@ sv_usage(void) | |||
| 334 | fprintf(stderr, " -npn_server - have server side offer NPN\n"); | 456 | fprintf(stderr, " -npn_server - have server side offer NPN\n"); |
| 335 | fprintf(stderr, " -npn_server_reject - have server reject NPN\n"); | 457 | fprintf(stderr, " -npn_server_reject - have server reject NPN\n"); |
| 336 | #endif | 458 | #endif |
| 459 | fprintf(stderr, " -alpn_client <string> - have client side offer ALPN\n"); | ||
| 460 | fprintf(stderr, " -alpn_server <string> - have server side offer ALPN\n"); | ||
| 461 | fprintf(stderr, " -alpn_expected <string> - the ALPN protocol that should be negotiated\n"); | ||
| 337 | } | 462 | } |
| 338 | 463 | ||
| 339 | static void | 464 | static void |
| @@ -584,7 +709,19 @@ main(int argc, char *argv[]) | |||
| 584 | npn_server_reject = 1; | 709 | npn_server_reject = 1; |
| 585 | } | 710 | } |
| 586 | #endif | 711 | #endif |
| 587 | else { | 712 | else if (strcmp(*argv, "-alpn_client") == 0) { |
| 713 | if (--argc < 1) | ||
| 714 | goto bad; | ||
| 715 | alpn_client = *(++argv); | ||
| 716 | } else if (strcmp(*argv, "-alpn_server") == 0) { | ||
| 717 | if (--argc < 1) | ||
| 718 | goto bad; | ||
| 719 | alpn_server = *(++argv); | ||
| 720 | } else if (strcmp(*argv, "-alpn_expected") == 0) { | ||
| 721 | if (--argc < 1) | ||
| 722 | goto bad; | ||
| 723 | alpn_expected = *(++argv); | ||
| 724 | } else { | ||
| 588 | fprintf(stderr, "unknown option %s\n", *argv); | 725 | fprintf(stderr, "unknown option %s\n", *argv); |
| 589 | badop = 1; | 726 | badop = 1; |
| 590 | break; | 727 | break; |
| @@ -759,6 +896,21 @@ bad: | |||
| 759 | } | 896 | } |
| 760 | #endif | 897 | #endif |
| 761 | 898 | ||
| 899 | if (alpn_server != NULL) | ||
| 900 | SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, NULL); | ||
| 901 | |||
| 902 | if (alpn_client != NULL) { | ||
| 903 | unsigned short alpn_len; | ||
| 904 | unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client); | ||
| 905 | |||
| 906 | if (alpn == NULL) { | ||
| 907 | BIO_printf(bio_err, "Error parsing -alpn_client argument\n"); | ||
| 908 | goto end; | ||
| 909 | } | ||
| 910 | SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len); | ||
| 911 | free(alpn); | ||
| 912 | } | ||
| 913 | |||
| 762 | c_ssl = SSL_new(c_ctx); | 914 | c_ssl = SSL_new(c_ctx); |
| 763 | s_ssl = SSL_new(s_ctx); | 915 | s_ssl = SSL_new(s_ctx); |
| 764 | 916 | ||
| @@ -1163,6 +1315,10 @@ doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, clock_t *s_time, | |||
| 1163 | goto err; | 1315 | goto err; |
| 1164 | } | 1316 | } |
| 1165 | #endif | 1317 | #endif |
| 1318 | if (verify_alpn(c_ssl, s_ssl) < 0) { | ||
| 1319 | ret = 1; | ||
| 1320 | goto err; | ||
| 1321 | } | ||
| 1166 | 1322 | ||
| 1167 | end: | 1323 | end: |
| 1168 | ret = 0; | 1324 | ret = 0; |
| @@ -1416,6 +1572,10 @@ doit(SSL *s_ssl, SSL *c_ssl, long count) | |||
| 1416 | goto err; | 1572 | goto err; |
| 1417 | } | 1573 | } |
| 1418 | #endif | 1574 | #endif |
| 1575 | if (verify_alpn(c_ssl, s_ssl) < 0) { | ||
| 1576 | ret = 1; | ||
| 1577 | goto err; | ||
| 1578 | } | ||
| 1419 | 1579 | ||
| 1420 | ret = 0; | 1580 | ret = 0; |
| 1421 | err: | 1581 | err: |
diff --git a/src/regress/lib/libssl/ssl/testssl b/src/regress/lib/libssl/ssl/testssl index a8ecab263e..379ddfcc50 100644 --- a/src/regress/lib/libssl/ssl/testssl +++ b/src/regress/lib/libssl/ssl/testssl | |||
| @@ -155,3 +155,22 @@ $ssltest -bio_pair -tls1 -npn_client -npn_server_reject || exit 1 | |||
| 155 | $ssltest -bio_pair -tls1 -npn_client -npn_server || exit 1 | 155 | $ssltest -bio_pair -tls1 -npn_client -npn_server || exit 1 |
| 156 | $ssltest -bio_pair -tls1 -npn_client -npn_server -num 2 || exit 1 | 156 | $ssltest -bio_pair -tls1 -npn_client -npn_server -num 2 || exit 1 |
| 157 | $ssltest -bio_pair -tls1 -npn_client -npn_server -num 2 -reuse || exit 1 | 157 | $ssltest -bio_pair -tls1 -npn_client -npn_server -num 2 -reuse || exit 1 |
| 158 | |||
| 159 | # | ||
| 160 | # ALPN tests | ||
| 161 | # | ||
| 162 | echo "Testing ALPN..." | ||
| 163 | $ssltest -bio_pair -tls1 -alpn_client foo -alpn_server bar || exit 1 | ||
| 164 | $ssltest -bio_pair -tls1 -alpn_client foo -alpn_server foo \ | ||
| 165 | -alpn_expected foo || exit 1 | ||
| 166 | $ssltest -bio_pair -tls1 -alpn_client foo,bar -alpn_server foo \ | ||
| 167 | -alpn_expected foo || exit 1 | ||
| 168 | $ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server foo \ | ||
| 169 | -alpn_expected foo || exit 1 | ||
| 170 | $ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server foo,bar \ | ||
| 171 | -alpn_expected foo || exit 1 | ||
| 172 | $ssltest -bio_pair -tls1 -alpn_client bar,foo -alpn_server bar,foo \ | ||
| 173 | -alpn_expected bar || exit 1 | ||
| 174 | $ssltest -bio_pair -tls1 -alpn_client foo,bar -alpn_server bar,foo \ | ||
| 175 | -alpn_expected bar || exit 1 | ||
| 176 | $ssltest -bio_pair -tls1 -alpn_client baz -alpn_server bar,foo || exit 1 | ||
