diff options
| author | jsing <> | 2024-01-30 14:46:46 +0000 |
|---|---|---|
| committer | jsing <> | 2024-01-30 14:46:46 +0000 |
| commit | 58b71efb8cd73a807ec46c267e6e92a1f728420c (patch) | |
| tree | 5a80f006dd1186e196c14e6a59f87e3b8f50ccbc /src | |
| parent | 82a2b52bbca491037fb2e86f6c9567ead7b7b8b6 (diff) | |
| download | openbsd-58b71efb8cd73a807ec46c267e6e92a1f728420c.tar.gz openbsd-58b71efb8cd73a807ec46c267e6e92a1f728420c.tar.bz2 openbsd-58b71efb8cd73a807ec46c267e6e92a1f728420c.zip | |
Add a shutdown sequence regress test.
Some software relies on SSL_shutdown() returning 0 (indicating close-notify
sent) before returning 1 on a subsequent call (indicating close-notify sent
and received). It is worth noting that there is no guarantee that this will
occur in normal operation, as the peer could send a close-notify prior to
SSL_shutdown() being called.
This is currently failing for TLSv1.3.
Diffstat (limited to 'src')
| -rw-r--r-- | src/regress/lib/libssl/shutdown/shutdowntest.c | 136 |
1 files changed, 133 insertions, 3 deletions
diff --git a/src/regress/lib/libssl/shutdown/shutdowntest.c b/src/regress/lib/libssl/shutdown/shutdowntest.c index 749ccaa435..5b83add359 100644 --- a/src/regress/lib/libssl/shutdown/shutdowntest.c +++ b/src/regress/lib/libssl/shutdown/shutdowntest.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: shutdowntest.c,v 1.2 2024/01/27 14:35:13 jsing Exp $ */ | 1 | /* $OpenBSD: shutdowntest.c,v 1.3 2024/01/30 14:46:46 jsing Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2020, 2021, 2024 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2020, 2021, 2024 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -360,7 +360,7 @@ static const struct shutdown_test shutdown_tests[] = { | |||
| 360 | #define N_TLS_TESTS (sizeof(shutdown_tests) / sizeof(*shutdown_tests)) | 360 | #define N_TLS_TESTS (sizeof(shutdown_tests) / sizeof(*shutdown_tests)) |
| 361 | 361 | ||
| 362 | static int | 362 | static int |
| 363 | shutdowntest(uint16_t ssl_version, const char *ssl_version_name, | 363 | shutdown_test(uint16_t ssl_version, const char *ssl_version_name, |
| 364 | const struct shutdown_test *st) | 364 | const struct shutdown_test *st) |
| 365 | { | 365 | { |
| 366 | BIO *client_wbio = NULL, *server_wbio = NULL; | 366 | BIO *client_wbio = NULL, *server_wbio = NULL; |
| @@ -479,6 +479,135 @@ shutdowntest(uint16_t ssl_version, const char *ssl_version_name, | |||
| 479 | return failed; | 479 | return failed; |
| 480 | } | 480 | } |
| 481 | 481 | ||
| 482 | static int | ||
| 483 | shutdown_sequence_test(uint16_t ssl_version, const char *ssl_version_name) | ||
| 484 | { | ||
| 485 | BIO *client_wbio = NULL, *server_wbio = NULL; | ||
| 486 | SSL *client = NULL, *server = NULL; | ||
| 487 | int shutdown, ret; | ||
| 488 | int failed = 1; | ||
| 489 | |||
| 490 | fprintf(stderr, "\n== Testing %s, shutdown sequence... ==\n", | ||
| 491 | ssl_version_name); | ||
| 492 | |||
| 493 | if ((client_wbio = BIO_new(BIO_s_mem())) == NULL) | ||
| 494 | goto failure; | ||
| 495 | if (BIO_set_mem_eof_return(client_wbio, -1) <= 0) | ||
| 496 | goto failure; | ||
| 497 | |||
| 498 | if ((server_wbio = BIO_new(BIO_s_mem())) == NULL) | ||
| 499 | goto failure; | ||
| 500 | if (BIO_set_mem_eof_return(server_wbio, -1) <= 0) | ||
| 501 | goto failure; | ||
| 502 | |||
| 503 | if ((client = tls_client(server_wbio, client_wbio)) == NULL) | ||
| 504 | goto failure; | ||
| 505 | if (!SSL_set_min_proto_version(client, ssl_version)) | ||
| 506 | goto failure; | ||
| 507 | if (!SSL_set_max_proto_version(client, ssl_version)) | ||
| 508 | goto failure; | ||
| 509 | |||
| 510 | if ((server = tls_server(client_wbio, server_wbio)) == NULL) | ||
| 511 | goto failure; | ||
| 512 | if (!SSL_set_min_proto_version(server, ssl_version)) | ||
| 513 | goto failure; | ||
| 514 | if (!SSL_set_max_proto_version(server, ssl_version)) | ||
| 515 | goto failure; | ||
| 516 | |||
| 517 | if (!do_client_server_loop(client, do_connect, server, do_accept)) { | ||
| 518 | fprintf(stderr, "FAIL: client and server handshake failed\n"); | ||
| 519 | goto failure; | ||
| 520 | } | ||
| 521 | |||
| 522 | if (!do_client_server_loop(client, do_write, server, do_read)) { | ||
| 523 | fprintf(stderr, "FAIL: client write and server read I/O failed\n"); | ||
| 524 | goto failure; | ||
| 525 | } | ||
| 526 | |||
| 527 | if (!do_client_server_loop(client, do_read, server, do_write)) { | ||
| 528 | fprintf(stderr, "FAIL: client read and server write I/O failed\n"); | ||
| 529 | goto failure; | ||
| 530 | } | ||
| 531 | |||
| 532 | /* | ||
| 533 | * Shutdown in lock step and check return value and shutdown flags. | ||
| 534 | * | ||
| 535 | * It is not documented, however some software relies on SSL_shutdown() | ||
| 536 | * to only send a close-notify on the first call, then indicate that a | ||
| 537 | * close-notify was received on a second (or later) call. | ||
| 538 | */ | ||
| 539 | |||
| 540 | if ((shutdown = SSL_get_shutdown(client)) != 0) { | ||
| 541 | fprintf(stderr, "FAIL: client shutdown flags = %x, want %x\n", | ||
| 542 | shutdown, 0); | ||
| 543 | goto failure; | ||
| 544 | } | ||
| 545 | if ((shutdown = SSL_get_shutdown(server)) != 0) { | ||
| 546 | fprintf(stderr, "FAIL: server shutdown flags = %x, want %x\n", | ||
| 547 | shutdown, 0); | ||
| 548 | goto failure; | ||
| 549 | } | ||
| 550 | |||
| 551 | if ((ret = SSL_shutdown(client)) != 0) { | ||
| 552 | fprintf(stderr, "FAIL: client SSL_shutdown() = %d, want %d\n", | ||
| 553 | ret, 0); | ||
| 554 | goto failure; | ||
| 555 | } | ||
| 556 | if ((shutdown = SSL_get_shutdown(client)) != SSL_SENT_SHUTDOWN) { | ||
| 557 | fprintf(stderr, "FAIL: client shutdown flags = %x, want %x\n", | ||
| 558 | shutdown, SSL_SENT_SHUTDOWN); | ||
| 559 | goto failure; | ||
| 560 | } | ||
| 561 | |||
| 562 | if ((ret = SSL_shutdown(server)) != 0) { | ||
| 563 | fprintf(stderr, "FAIL: server SSL_shutdown() = %d, want %d\n", | ||
| 564 | ret, 0); | ||
| 565 | goto failure; | ||
| 566 | } | ||
| 567 | if ((shutdown = SSL_get_shutdown(server)) != SSL_SENT_SHUTDOWN) { | ||
| 568 | fprintf(stderr, "FAIL: server shutdown flags = %x, want %x\n", | ||
| 569 | shutdown, SSL_SENT_SHUTDOWN); | ||
| 570 | goto failure; | ||
| 571 | } | ||
| 572 | |||
| 573 | if ((ret = SSL_shutdown(client)) != 1) { | ||
| 574 | fprintf(stderr, "FAIL: client SSL_shutdown() = %d, want %d\n", | ||
| 575 | ret, 0); | ||
| 576 | goto failure; | ||
| 577 | } | ||
| 578 | if ((shutdown = SSL_get_shutdown(client)) != | ||
| 579 | (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN)) { | ||
| 580 | fprintf(stderr, "FAIL: client shutdown flags = %x, want %x\n", | ||
| 581 | shutdown, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); | ||
| 582 | goto failure; | ||
| 583 | } | ||
| 584 | |||
| 585 | if ((ret = SSL_shutdown(server)) != 1) { | ||
| 586 | fprintf(stderr, "FAIL: server SSL_shutdown() = %d, want %d\n", | ||
| 587 | ret, 0); | ||
| 588 | goto failure; | ||
| 589 | } | ||
| 590 | if ((shutdown = SSL_get_shutdown(server)) != | ||
| 591 | (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN)) { | ||
| 592 | fprintf(stderr, "FAIL: server shutdown flags = %x, want %x\n", | ||
| 593 | shutdown, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); | ||
| 594 | goto failure; | ||
| 595 | } | ||
| 596 | |||
| 597 | fprintf(stderr, "INFO: Done!\n"); | ||
| 598 | |||
| 599 | failed = 0; | ||
| 600 | |||
| 601 | failure: | ||
| 602 | BIO_free(client_wbio); | ||
| 603 | BIO_free(server_wbio); | ||
| 604 | |||
| 605 | SSL_free(client); | ||
| 606 | SSL_free(server); | ||
| 607 | |||
| 608 | return failed; | ||
| 609 | } | ||
| 610 | |||
| 482 | struct ssl_version { | 611 | struct ssl_version { |
| 483 | uint16_t version; | 612 | uint16_t version; |
| 484 | const char *name; | 613 | const char *name; |
| @@ -517,9 +646,10 @@ main(int argc, char **argv) | |||
| 517 | for (i = 0; i < N_SSL_VERSIONS; i++) { | 646 | for (i = 0; i < N_SSL_VERSIONS; i++) { |
| 518 | sv = &ssl_versions[i]; | 647 | sv = &ssl_versions[i]; |
| 519 | for (j = 0; j < N_TLS_TESTS; j++) { | 648 | for (j = 0; j < N_TLS_TESTS; j++) { |
| 520 | failed |= shutdowntest(sv->version, sv->name, | 649 | failed |= shutdown_test(sv->version, sv->name, |
| 521 | &shutdown_tests[j]); | 650 | &shutdown_tests[j]); |
| 522 | } | 651 | } |
| 652 | failed |= shutdown_sequence_test(sv->version, sv->name); | ||
| 523 | } | 653 | } |
| 524 | 654 | ||
| 525 | return failed; | 655 | return failed; |
