From 8b62c8d4331720d73bf79f7bef64932fc7841928 Mon Sep 17 00:00:00 2001 From: Joseph Birr-Pixton Date: Fri, 23 Feb 2024 16:19:26 +0000 Subject: [PATCH] Run an integration test covering TLS client APIs --- rustls-libssl/Makefile | 5 +- rustls-libssl/test-ca/rsa/ca.cert | 30 ++++++ rustls-libssl/test-ca/rsa/end.cert | 24 +++++ rustls-libssl/test-ca/rsa/end.key | 28 ++++++ rustls-libssl/test-ca/rsa/inter.cert | 28 ++++++ rustls-libssl/tests/client.c | 141 +++++++++++++++++++++++++++ rustls-libssl/tests/runner.rs | 89 ++++++++++++++++- 7 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 rustls-libssl/test-ca/rsa/ca.cert create mode 100644 rustls-libssl/test-ca/rsa/end.cert create mode 100644 rustls-libssl/test-ca/rsa/end.key create mode 100644 rustls-libssl/test-ca/rsa/inter.cert create mode 100644 rustls-libssl/tests/client.c diff --git a/rustls-libssl/Makefile b/rustls-libssl/Makefile index fd82113..52bcee8 100644 --- a/rustls-libssl/Makefile +++ b/rustls-libssl/Makefile @@ -19,7 +19,7 @@ ifneq (,$(TARGET)) CARGOFLAGS += --target $(TARGET) endif -all: target/ciphers target/constants target/$(PROFILE)/libssl.so.3 +all: target/ciphers target/client target/constants target/$(PROFILE)/libssl.so.3 test: all ${CARGO} test --locked @@ -42,6 +42,9 @@ target/%.o: tests/%.c | target target/ciphers: target/ciphers.o $(CC) -o $@ $^ $(LDFLAGS) $(shell pkg-config --libs openssl) +target/client: target/client.o + $(CC) -o $@ $^ $(LDFLAGS) $(shell pkg-config --libs openssl) + target/constants: target/constants.o $(CC) -o $@ $^ $(LDFLAGS) $(shell pkg-config --libs openssl) diff --git a/rustls-libssl/test-ca/rsa/ca.cert b/rustls-libssl/test-ca/rsa/ca.cert new file mode 100644 index 0000000..5dac1c9 --- /dev/null +++ b/rustls-libssl/test-ca/rsa/ca.cert @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFFTCCAv2gAwIBAgIUZBEaAuV4ORnPH4GxeJGyEiqXUN8wDQYJKoZIhvcNAQEL +BQAwGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMB4XDTIzMTIyMTE3MjMxNFoX +DTMzMTIxODE3MjMxNFowGjEYMBYGA1UEAwwPcG9ueXRvd24gUlNBIENBMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzvK/b5WhfthXBMVIHboJJuR9XuG9 ++ioSrlzwT9DW7QV31UpgBUZyf1nvT7CmDplNiWZtpqSdJ9pjskBIj5dv4m5cX8A9 +fK1IATdkd6j5/c2ZFkqi5k9iPeJa5rZY6SoGKgvBEr/Y5oiO8HZJZOFetafSr6zV +WRAsKlagrmiNS0oiWC0P0yPVWZyhlHHbtYrHtF/CuWEJ9HqzUk9KeTPwgjfphlYJ +YM0bCZzqN8TEbWPksU1WnmU15YbTgjwI0bNjUXA7W9LmMvbW7EXFJ2+LI+oiF3mk +TQEXqhfdTL9NtqAikD+cfAM1y5e5QSpi8dQuexBteFtXphRZzFk8M9DVKHyngKTH +/QZo6B4Gj9VPrNRPlbPkpbnu8JWD7hO/22VLU4YhghsdwQ/833pfokdV89NMoLo4 +JOUzbTTGtjH0bq6LWTMtLifuQ4H0D1WLtdy/EGgKptnTaeYaXNYT7+v+NNcBHaW8 +W3Orbx0s9IXgQnZTk1u03RbRdIxNxqm+HYEM8gT6S9IUymNZkzDCfZC0bC/saevd +zVE2xpZmuLOfhDl+EcalDYNPrM72+NzkAwRPFGec+bcUEhBxhvxpav+SxDiRC1gD +43qFU7hVfuqVH/EFp0lR3I3Xo8TZ5OIgEyJ5vQH5Ne1+C+sqdCqdGoqf1TZuIE80 +ZwKYcMnRwDXpiGsCAwEAAaNTMFEwHQYDVR0OBBYEFEIQj1cHn3me0sRqu6KjbEb2 +kb8rMB8GA1UdIwQYMBaAFEIQj1cHn3me0sRqu6KjbEb2kb8rMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQELBQADggIBAEKDnm8x+NOaWNrPNH5kIlGD0tGdDJvw +/KvBZmkMcgFkb4zhbbeUmlu0j5CX4+6Lck0uw62zRgP4Nw3x36W3DL7pmoV4MYHC +djNG1ruNoojvgZyyGgMaSabto0nSHSE9opAorrSXB9RoOv2WcBuQSBNl72eaCQ1F +4kAYjKN6ZwPxEdTsdEmqWyUyEPy6E5kNoM0jW1uI2ZBxzbIOYeePvQ3muUSIMtmC +jShiEOOpmYpzENsAMouY3ZN+CWVS5kB5umnYSviQlAVEKSjC764FD9vMLL+rNhfP +fz+y6EhKcnnYy7mdXIRY73uh5eMyCLUO0yr2Y2ophhD8D79f2w7KtYjaSKfAch0L +lETe9Ch+fGDxUCph3J1IuR/3n01ZjB47WXu/yDZ6s7SHGXIgPaptzP+nZkDnmlZX +bvjB5s6r4U2spuqeLxrwd/1Jin7It+LOYLVmkihpbta9+/KKiXOuSYN1rSiQ2XKp +n1ZN0XxhcZzsALklBIU+Lm11b8gPVS7rXqll/sDmaAH9Iw+AXwUYjCb62Gy58yzu +uk3Q+msRr3oVI9bBhmEXmZxyENYJrw305qOlI3+tHBoJLUSP6zQ214aEu4trJr5K +kmbF7DZRG9MSBXeRk7e5ojK13xI1/XCjgIOTkGxF4rEFbVwhc0B8zS/2x3zw0fkE +M4J0J+gz0QYr +-----END CERTIFICATE----- diff --git a/rustls-libssl/test-ca/rsa/end.cert b/rustls-libssl/test-ca/rsa/end.cert new file mode 100644 index 0000000..fc36be9 --- /dev/null +++ b/rustls-libssl/test-ca/rsa/end.cert @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEGDCCAoCgAwIBAgICAcgwDQYJKoZIhvcNAQELBQAwLDEqMCgGA1UEAwwhcG9u +eXRvd24gUlNBIGxldmVsIDIgaW50ZXJtZWRpYXRlMB4XDTIzMTIyMTE3MjMxNVoX +DTI5MDYxMjE3MjMxNVowGTEXMBUGA1UEAwwOdGVzdHNlcnZlci5jb20wggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDI1plwQmA+rr6Evlvn2hzIB/zYKlx +Tm14SPzomxpaf3OpzXzHuOn34yVvU1vTDijUl/YJbcnx052m0075SYeuW08VQB/p +zjhLrFp1ULSD272IddbB88T8Jq/VZ5dAxBB1q6Tm0vGBYQ8eIcmJv+fJQTbTXHKQ +KPHQRmVyqXVkwvwcgEJi9gpOcEEpJ6SDGdyGh1ck3wGnhrSpmsu+hwUVi7las+Ka +QUlvkmD+UGQKo8Ta91Xu8ja25QLTpjVcYxbi719rtA6I9DpX4+3aeIy/0s1xk0Xi +yMXIjSl3dn47gp3IZFRCECuoTdOwOZ9+y9ENnpHvZ84jCBXddU09qheJAgMBAAGj +gdYwgdMwDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwHQYDVR0OBBYEFAUefby7 +fPnK64BnGdIizLlWDkbPMEIGA1UdIwQ7MDmAFJCh13RFfpFyZ5LRR+A6ndRRvvGa +oR6kHDAaMRgwFgYDVQQDDA9wb255dG93biBSU0EgQ0GCAXswUwYDVR0RBEwwSoIO +dGVzdHNlcnZlci5jb22HBMYzZAGCFXNlY29uZC50ZXN0c2VydmVyLmNvbYcQIAEN +uAAAAAAAAAAAAAAAAYIJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBgQC2gxGT +c3aayDPR5/ICnuK8aVSsM67xRsGsWvzBxdyyXaB+qSGxa+sCkw8guuAp2W7MrrO/ +zu7yhXDI2nyav6ZP6NvLABFYZ6pXokV/Hj4rQpCDVxvvDVh/E/rW/wx6z580zfdo +auHqUCD9QfR97nENwtGv7ESLN6qFeU0CsJd2GE3y3pnadlpCW3AYHeLX4crm7poj +SfG1F4ipqM1i0knQN86KBzG5PO49azGJGmcsu5lPFQgTRvvR7W+Niq/kIQPu00AW +so8aSB1gp2lypUGHqwsrd51yrQ374jKvXSDt1ptc0xDI9004TuYre9XQsyjxq4Qn +VjmpnKLCbumkrlELf93oomWxT5g6Nb/vu1TUgsrdWgDAW0AZ+rfcWorrZAjbvYw9 +4MJ1PdAmeg+sk51xoh2KF7syHPaMcNCaoSBtXrB5LqrAxixdmB6ORM/KlQU7h9A7 +X+WysEwMowV2MsGr8VsHxYTOpoiE8nUPfnRmbrGPpUU24bzvqTxtxxqQU14= +-----END CERTIFICATE----- diff --git a/rustls-libssl/test-ca/rsa/end.key b/rustls-libssl/test-ca/rsa/end.key new file mode 100644 index 0000000..cb236b6 --- /dev/null +++ b/rustls-libssl/test-ca/rsa/end.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDI1plwQmA+rr6 +Evlvn2hzIB/zYKlxTm14SPzomxpaf3OpzXzHuOn34yVvU1vTDijUl/YJbcnx052m +0075SYeuW08VQB/pzjhLrFp1ULSD272IddbB88T8Jq/VZ5dAxBB1q6Tm0vGBYQ8e +IcmJv+fJQTbTXHKQKPHQRmVyqXVkwvwcgEJi9gpOcEEpJ6SDGdyGh1ck3wGnhrSp +msu+hwUVi7las+KaQUlvkmD+UGQKo8Ta91Xu8ja25QLTpjVcYxbi719rtA6I9DpX +4+3aeIy/0s1xk0XiyMXIjSl3dn47gp3IZFRCECuoTdOwOZ9+y9ENnpHvZ84jCBXd +dU09qheJAgMBAAECggEABbzZYJqPc/prWwUJzo1qXdA5AEf8U3eR4nKK9S/yU2zh +8sE3BQxb3M0SAbb6wTbuXmnlcxuGT5UAUrJt5QiTc739kktjZNWKdDcqJb7sv9/L +L+L/II7RYPSmQOkd2mqpbTxRyfOz5DD9Z85ohaNd5l4Dha13NOPvUEdxnjB7Yi4I +YbUYZ/Zq6MUosFRObS0XPBvk6d+zDI3WUZatVTNfuS7fqI1BvkXs5EkV34DQXgQs +LKb1LFAoEZoh64UnfkONIT9oG4OTbbaQ9gCbfQPpKw07GuaMdtjp0QD0yldOKvL4 +V4crSZyj2f3LnPCqCjUwcz6quKSUqUgosVApH+JCcQKBgQDpaGXy3laYTK3zbauh ++eHY5Ia+7fM2ETZx4LfwAYA1K5E84T98swpO571lZVrbOKjBukpUrbHdOcEVcBRH +BTvCh1vL1AXXWR0cCvWtp/WAbu90rDqgu6mxaD+V8wGq29URTWOCRG1WA7zeNHPB +0XAZPLQVeqeSvHGLSqyPf4aoHQKBgQDWBqvl5To7P4ZT6VFl18v0EB3zgzpRuyC3 +xKKz5mGw4tuvspdMU2XaOGQsRl5emMijGeII7JUweHbBdkq44S2FZ9wyn4+I+8Oi +Atu4Nce06ARnw+5RRcJlSs/LrExfOtxF3xp8EQqpL/jEO03n7G5cwcFwuWTKoVTI +0RwcuU4JXQKBgDBMCvRzb2W6UDBT3DT7GPGhcARoBnCEpUhxIH6IQPg/mKEJVvK9 +tX9YUod9row4MCtOGf1lp61IOxztgTSk75W0HpmRuNezt+NKnUWewJ0f12rEDKmf +y2BLWwTzMMAjFvaqldGpyRoIUfeE0QMlDFYcioL7S1uApNoWzJgw4jM9AoGBANIk +osuLku1xphbl08JHbD4rRP1AMBbnwWwuagJxhiID3OhaVivfBvaIv/Ko9Se0o+th +EorooGODJDc4So3Uqrl+DLq36Fr7uE5uuAXa6Ec8OHcZ7flmoUSLfBPjDOnEBVul +f3+py+nq7Drgb9H0VzhEFgb0QX6jgXfbudqKJ5ERAoGAR5Q6wQEoT9VT53nuKprl +3K/6agd+4wlpVQW0W1LImdrJHRHUXO7KJe7Bo5rtjL3lw8dCl3olHlLPJKg9frMn +ZWvJ2t0zca18S76rNcsPew2BecJxNRFlGwdcE1BBA2p/yzBhsZbIO7eqfh+dK5va +rnlrPNbWDhylxMaU4/CoU7k= +-----END PRIVATE KEY----- diff --git a/rustls-libssl/test-ca/rsa/inter.cert b/rustls-libssl/test-ca/rsa/inter.cert new file mode 100644 index 0000000..c46d110 --- /dev/null +++ b/rustls-libssl/test-ca/rsa/inter.cert @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEwDCCAqigAwIBAgIBezANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9wb255 +dG93biBSU0EgQ0EwHhcNMjMxMjIxMTcyMzE1WhcNMzMxMjE4MTcyMzE1WjAsMSow +KAYDVQQDDCFwb255dG93biBSU0EgbGV2ZWwgMiBpbnRlcm1lZGlhdGUwggGiMA0G +CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDC9IRIszo5zkkxlz+pkU8otrZ2Jwlf +BQ4j5heoPkpmvFss2fDElZZCVhZt54ehk2+oRuZhfgldfmuT0KCQEMnx8iN7K+pk +2LgaAVGzT4X/NBv+qamgkzRu9UvrS5NrlWutHsPPRt2TldVVJ1UEiLuWrrFMQwi+ +JATjgBHz6PhhD+UnPszZM/SJaBmtMXT99rO/sS6aaQhkZJCSDVVOnnecXafshkEF +tlMkKDRTTxxTOiTGu2NSH5MMzB3F952AiG8ZDONRSyBtxh/kpRV6+idO/4ufIQ3w +ZUPjLlRZIF9cDIGJXRU+cjYvMSV6yPzM2rP+67dPS9N7gQS1AFiMOlLQRbp3Sz9e +R6eetX/ggaHPcIzNv+pLp0L4+8PINZWhcJnZUlgkNR9Gg25mdPC6BLpWH20NH37V +VfSs40ytxHyw5QRokwwjcGUmlzXSJf0R+eUhXkJAmR+bgKbQKRbCW6M+byNdphfu +c3R2irNvRbYkwTOP3FvFkcC+cYyMIHyKihMCAwEAAaN/MH0wHQYDVR0OBBYEFJCh +13RFfpFyZ5LRR+A6ndRRvvGaMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEF +BQcDAjAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIB/jAfBgNVHSMEGDAWgBRCEI9X +B595ntLEaruio2xG9pG/KzANBgkqhkiG9w0BAQsFAAOCAgEAxyqRDyGCkF07q/2P +44Mkwg+olQdT7moiO7V7MauwLZmCNqkr4hQcAk1NKi1QdYw/xCgd/x7PQ/INVMYN +oAG/xxr4nh0whygSsPGk9LkzoeG4dfeVv7tbsYw+4o7wU9kgCM1v0c2vMskyHh3F +vdMJV+5hWZqHZLUOZY1l9ziJysz/aSD4WpMtXdwT5fFgbJ8zggcMADkIESSBPrK5 +ykjFqFnoryK938IUw8fHEdU5ZdjM+1li4Q6P3YT6ovY9aA9gXbD/xb4mUb5kG+ug +tmGV+MDvi6Qgyt1O9ZgaW0tLdbjdxzTjEgU0KwUDpK6AZ9ebcyL5PGj3JA15ZPvS +36AHH/3N+u3w1Poyxb8NxyOgNY7AX3hRQax9G1/43F3VZ1C991xVrwWL++mRD+Ai +5FhMKjZ258+8DKgYaT2JIExwNWA5taafmR2CKpxgVWSFLha/WogJH3kyyTJHXLjU +Bm5qvwqWAvS3Px+WkSbtqFKRDCs+oaj2wGGuwxqEEEriMJ26AC3Si2n9k0a17TOj +lezKgblBHlpokEgcqOkRDB8k1g/Hkx7eRX4RlBRJ4PVRFT6qSTyy3dESsWhb7Sz2 ++uB8SQIYH+5QXwD3MpNrg2BILQYtcciPiGmLNyQB3ZvJUKcj0n63CjxAfcSnbkUF +AnF6iUVbZu9AMRaBDiRdNLGnBms= +-----END CERTIFICATE----- diff --git a/rustls-libssl/tests/client.c b/rustls-libssl/tests/client.c new file mode 100644 index 0000000..a6e500e --- /dev/null +++ b/rustls-libssl/tests/client.c @@ -0,0 +1,141 @@ +/** + * Simple client test program. + * + * Expects to connect to an `openssl s_server -rev` server. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static int trace(int rc, const char *str) { + printf("%s: %d\n", str, rc); + return rc; +} + +#define TRACE(fn) trace((fn), #fn) + +static void hexdump(const char *label, const void *buf, int n) { + const uint8_t *ubuf = (const uint8_t *)buf; + printf("%s (%d bytes): ", label, n); + for (int i = 0; i < n; i++) { + printf("%02x", ubuf[i]); + } + printf("\n"); +} + +static void dump_openssl_error_stack(void) { + if (ERR_peek_error() != 0) { + printf("openssl error: "); + ERR_print_errors_fp(stdout); + } +} + +int main(int argc, char **argv) { + if (argc != 4) { + printf("%s \n\n", argv[0]); + return 1; + } + + const char *host = argv[1], *port = argv[2], *cacert = argv[3]; + + struct addrinfo *result = NULL; + TRACE(getaddrinfo(host, port, NULL, &result)); + + int sock = TRACE( + socket(result->ai_family, result->ai_socktype, result->ai_protocol)); + TRACE(connect(sock, result->ai_addr, result->ai_addrlen)); + freeaddrinfo(result); + + TRACE(OPENSSL_init_ssl(0, NULL)); + dump_openssl_error_stack(); + SSL_CTX *ctx = SSL_CTX_new(TLS_method()); + dump_openssl_error_stack(); + if (strcmp(cacert, "insecure") != 0) { + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + dump_openssl_error_stack(); + TRACE(SSL_CTX_load_verify_file(ctx, cacert)); + dump_openssl_error_stack(); + } else { + printf("certificate verification disabled\n"); + } + TRACE(SSL_CTX_set_alpn_protos(ctx, (const uint8_t *)"\x02hi\x05world", 9)); + dump_openssl_error_stack(); + SSL *ssl = SSL_new(ctx); + dump_openssl_error_stack(); + TRACE(SSL_set1_host(ssl, host)); + dump_openssl_error_stack(); + TRACE(SSL_set_fd(ssl, sock)); + dump_openssl_error_stack(); + TRACE(SSL_connect(ssl)); + dump_openssl_error_stack(); + + // check the alpn (also sees that SSL_connect completed handshake) + const uint8_t *alpn_ptr = NULL; + unsigned int alpn_len = 0; + SSL_get0_alpn_selected(ssl, &alpn_ptr, &alpn_len); + hexdump("alpn", alpn_ptr, alpn_len); + + printf("version: %s\n", SSL_get_version(ssl)); + printf("verify-result: %ld\n", SSL_get_verify_result(ssl)); + printf("cipher: %s\n", SSL_CIPHER_standard_name(SSL_get_current_cipher(ssl))); + + // check the peer certificate and chain + X509 *cert = SSL_get1_peer_certificate(ssl); + if (cert) { + char *name = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + printf("server subject: %s\n", name); + free(name); + } else { + printf("server cert absent\n"); + } + X509_free(cert); + + STACK_OF(X509) *chain = SSL_get_peer_cert_chain(ssl); + if (chain) { + printf("%d certs in server chain\n", sk_X509_num(chain)); + for (int i = 0; i < sk_X509_num(chain); i++) { + X509 *cert = sk_X509_value(chain, i); + char *name = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + printf(" %d: %s\n", i, name); + free(name); + } + } else { + printf("server cert chain absent\n"); + } + + // write some data and close + int wr = TRACE(SSL_write(ssl, "hello", 5)); + dump_openssl_error_stack(); + assert(wr == 5); + TRACE(SSL_shutdown(ssl)); + dump_openssl_error_stack(); + + // read back data, using SSL_pending on the way + char buf[10] = {0}; + int rd = TRACE(SSL_read(ssl, buf, 1)); + dump_openssl_error_stack(); + TRACE(SSL_pending(ssl)); + dump_openssl_error_stack(); + TRACE(SSL_has_pending(ssl)); + dump_openssl_error_stack(); + int rd2 = TRACE(SSL_read(ssl, buf + 1, sizeof(buf) - 1)); + hexdump("result", buf, rd + rd2); + assert(memcmp(buf, "olleh\n", 6) == 0); + + close(sock); + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf("PASS\n\n"); + return 0; +} diff --git a/rustls-libssl/tests/runner.rs b/rustls-libssl/tests/runner.rs index 1fb233b..8ec13c6 100644 --- a/rustls-libssl/tests/runner.rs +++ b/rustls-libssl/tests/runner.rs @@ -1,4 +1,5 @@ -use std::process::{Command, Output, Stdio}; +use std::process::{Child, Command, Output, Stdio}; +use std::{net, thread, time}; /* Note: * @@ -11,6 +12,67 @@ use std::process::{Command, Output, Stdio}; * to actually use OpenSSL's libssl. */ +#[test] +#[ignore] +fn client() { + let _server = KillOnDrop( + Command::new("openssl") + .args(&[ + "s_server", + "-cert", + "test-ca/rsa/end.cert", + "-cert_chain", + "test-ca/rsa/inter.cert", + "-key", + "test-ca/rsa/end.key", + "-alpn", + "hello,world", + "-accept", + "localhost:4443", + "-rev", + ]) + .env("LD_LIBRARY_PATH", "") + .spawn() + .expect("failed to start openssl s_server"), + ); + + wait_for_port(4443); + + let openssl_insecure_output = Command::new("target/client") + .env("LD_LIBRARY_PATH", "") + .args(&["localhost", "4443", "insecure"]) + .stdout(Stdio::piped()) + .output() + .map(print_output) + .unwrap(); + + let rustls_insecure_output = Command::new("target/client") + .args(&["localhost", "4443", "insecure"]) + .stdout(Stdio::piped()) + .output() + .map(print_output) + .unwrap(); + + assert_eq!(openssl_insecure_output, rustls_insecure_output); + + let openssl_secure_output = Command::new("target/client") + .env("LD_LIBRARY_PATH", "") + .args(&["localhost", "4443", "test-ca/rsa/ca.cert"]) + .stdout(Stdio::piped()) + .output() + .map(print_output) + .unwrap(); + + let rustls_secure_output = Command::new("target/client") + .args(&["localhost", "4443", "test-ca/rsa/ca.cert"]) + .stdout(Stdio::piped()) + .output() + .map(print_output) + .unwrap(); + + assert_eq!(openssl_secure_output, rustls_secure_output); +} + #[test] #[ignore] fn constants() { @@ -49,6 +111,15 @@ fn ciphers() { assert_eq!(openssl_output, rustls_output); } +struct KillOnDrop(Child); + +impl Drop for KillOnDrop { + fn drop(&mut self) { + self.0.kill().expect("failed to kill subprocess"); + self.0.wait().expect("failed to wait for killed subprocess"); + } +} + fn print_output(out: Output) -> Output { println!("status: {:?}\n", out.status); println!( @@ -61,3 +132,19 @@ fn print_output(out: Output) -> Output { ); out } + +/// Wait until we can connect to localhost:port. +fn wait_for_port(port: u16) -> Option<()> { + let mut count = 0; + loop { + thread::sleep(time::Duration::from_millis(500)); + if net::TcpStream::connect(("localhost", port)).is_ok() { + return Some(()); + } + println!("waiting for port {port}"); + count += 1; + if count == 10 { + return None; + } + } +}