diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2017-07-16 18:18:11 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2017-07-16 18:18:11 +0000 |
commit | 45d22d0339e5da3a4254d566d113df8c52f33964 (patch) | |
tree | ea6eb91c7fae80ed0bd1bc6cca960bd4872f946b /regress | |
parent | 961e337099bc1438a14bc62964633048ca8e3cc0 (diff) |
Provide a new regress test for TLS extension handlers, currently covering
the newly converted SNI code.
Diffstat (limited to 'regress')
-rw-r--r-- | regress/lib/libssl/Makefile | 3 | ||||
-rw-r--r-- | regress/lib/libssl/tlsext/Makefile | 9 | ||||
-rw-r--r-- | regress/lib/libssl/tlsext/tlsexttest.c | 245 |
3 files changed, 256 insertions, 1 deletions
diff --git a/regress/lib/libssl/Makefile b/regress/lib/libssl/Makefile index d6ee2f160a0..0cc3e156a30 100644 --- a/regress/lib/libssl/Makefile +++ b/regress/lib/libssl/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.25 2017/03/05 14:15:53 jsing Exp $ +# $OpenBSD: Makefile,v 1.26 2017/07/16 18:18:10 jsing Exp $ SUBDIR= \ asn1 \ @@ -8,6 +8,7 @@ SUBDIR= \ pqueue \ server \ ssl \ + tlsext \ unit install: diff --git a/regress/lib/libssl/tlsext/Makefile b/regress/lib/libssl/tlsext/Makefile new file mode 100644 index 00000000000..48b5bc1e258 --- /dev/null +++ b/regress/lib/libssl/tlsext/Makefile @@ -0,0 +1,9 @@ +# $OpenBSD: Makefile,v 1.1 2017/07/16 18:18:10 jsing Exp $ + +PROG= tlsexttest +LDADD= ${SSL_INT} -lcrypto +DPADD= ${LIBCRYPTO} ${LIBSSL} +WARNINGS= Yes +CFLAGS+= -DLIBRESSL_INTERNAL -Wundef -Werror -I$(BSDSRCDIR)/lib/libssl + +.include <bsd.regress.mk> diff --git a/regress/lib/libssl/tlsext/tlsexttest.c b/regress/lib/libssl/tlsext/tlsexttest.c new file mode 100644 index 00000000000..557c3ca4098 --- /dev/null +++ b/regress/lib/libssl/tlsext/tlsexttest.c @@ -0,0 +1,245 @@ +/* $OpenBSD: tlsexttest.c,v 1.1 2017/07/16 18:18:10 jsing Exp $ */ +/* + * Copyright (c) 2017 Joel Sing <jsing@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <err.h> + +#include "ssl_locl.h" + +#include "bytestring.h" +#include "ssl_tlsext.h" + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +#define TEST_SNI_SERVERNAME "www.libressl.org" + +static unsigned char tlsext_sni_clienthello[] = { + 0x00, 0x13, 0x00, 0x00, 0x10, 0x77, 0x77, 0x77, + 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x65, 0x73, 0x73, + 0x6c, 0x2e, 0x6f, 0x72, 0x67, +}; + +static unsigned char tlsext_sni_serverhello[] = { +}; + +static int +test_tlsext_sni_clienthello(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + int failure = 0; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + CBB_init(&cbb, 0); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (tlsext_sni_clienthello_needs(ssl)) { + fprintf(stderr, "FAIL: clienthello should not need SNI\n"); + failure = 1; + goto done; + } + + if (!SSL_set_tlsext_host_name(ssl, TEST_SNI_SERVERNAME)) { + fprintf(stderr, "FAIL: client failed to set server name\n"); + failure = 1; + goto done; + } + + if (!tlsext_sni_clienthello_needs(ssl)) { + fprintf(stderr, "FAIL: clienthello should need SNI\n"); + failure = 1; + goto done; + } + + if (!tlsext_sni_clienthello_build(ssl, &cbb)) { + fprintf(stderr, "FAIL: clienthello failed to build SNI\n"); + failure = 1; + goto done; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_sni_clienthello)) { + fprintf(stderr, "FAIL: got clienthello SNI with length %zu, " + "want length %zu\n", dlen, sizeof(tlsext_sni_clienthello)); + failure = 1; + goto done; + } + + if (memcmp(data, tlsext_sni_clienthello, dlen) != 0) { + fprintf(stderr, "FAIL: clienthello SNI differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_sni_clienthello, sizeof(tlsext_sni_clienthello)); + failure = 1; + goto done; + } + + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + ssl->internal->hit = 0; + + CBS_init(&cbs, tlsext_sni_clienthello, sizeof(tlsext_sni_clienthello)); + if (!tlsext_sni_clienthello_parse(ssl, &cbs, &alert)) { + fprintf(stderr, "FAIL: failed to parse clienthello SNI\n"); + failure = 1; + goto done; + } + + if (ssl->session->tlsext_hostname == NULL) { + fprintf(stderr, "FAIL: no tlsext_hostname from clienthello SNI\n"); + failure = 1; + goto done; + } + + if (strlen(ssl->session->tlsext_hostname) != strlen(TEST_SNI_SERVERNAME) || + strncmp(ssl->session->tlsext_hostname, TEST_SNI_SERVERNAME, + strlen(TEST_SNI_SERVERNAME)) != 0) { + fprintf(stderr, "FAIL: got tlsext_hostname `%s', want `%s'\n", + ssl->session->tlsext_hostname, TEST_SNI_SERVERNAME); + failure = 1; + goto done; + } + + done: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static int +test_tlsext_sni_serverhello(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + int failure = 0; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + CBB_init(&cbb, 0); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + if (tlsext_sni_serverhello_needs(ssl)) { + fprintf(stderr, "FAIL: serverhello should not need SNI\n"); + failure = 1; + goto done; + } + + if (!SSL_set_tlsext_host_name(ssl, TEST_SNI_SERVERNAME)) { + fprintf(stderr, "FAIL: client failed to set server name\n"); + failure = 1; + goto done; + } + + if ((ssl->session->tlsext_hostname = strdup(TEST_SNI_SERVERNAME)) == + NULL) + errx(1, "failed to strdup tlsext_hostname"); + + if (!tlsext_sni_serverhello_needs(ssl)) { + fprintf(stderr, "FAIL: serverhello should need SNI\n"); + failure = 1; + goto done; + } + + if (!tlsext_sni_serverhello_build(ssl, &cbb)) { + fprintf(stderr, "FAIL: serverhello failed to build SNI\n"); + failure = 1; + goto done; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_sni_serverhello)) { + fprintf(stderr, "FAIL: got serverhello SNI with length %zu, " + "want length %zu\n", dlen, sizeof(tlsext_sni_serverhello)); + failure = 1; + goto done; + } + + if (memcmp(data, tlsext_sni_serverhello, dlen) != 0) { + fprintf(stderr, "FAIL: serverhello SNI differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_sni_serverhello, sizeof(tlsext_sni_serverhello)); + failure = 1; + goto done; + } + + CBS_init(&cbs, tlsext_sni_serverhello, sizeof(tlsext_sni_serverhello)); + if (!tlsext_sni_serverhello_parse(ssl, &cbs, &alert)) { + fprintf(stderr, "FAIL: failed to parse serverhello SNI\n"); + failure = 1; + goto done; + } + + /* XXX - test parse with session with mismatched name. */ + + done: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + SSL_library_init(); + + failed |= test_tlsext_sni_clienthello(); + failed |= test_tlsext_sni_serverhello(); + + return (failed); +} |