From: Matt Caswell Date: Thu, 9 Jun 2016 12:33:27 +0000 (+0100) Subject: Add some session API tests X-Git-Tag: OpenSSL_1_1_0-pre6~473 X-Git-Url: https://git.openssl.org/?p=openssl.git;a=commitdiff_plain;h=2cb4b5f63ac8d78506652725d0afe299f99d1437;ds=sidebyside Add some session API tests This commit adds some session API tests, and in particular tests the modified behaviour of SSL_set_session() introduced in the last commit. To do this I have factored out some common code from the asynciotest into a new ssltestlib.c file. I've also renamed getsettest to sslapitest as this more closely matches what it now is! Reviewed-by: Rich Salz --- diff --git a/test/asynciotest.c b/test/asynciotest.c index f80425eb92..de67cce3e7 100644 --- a/test/asynciotest.c +++ b/test/asynciotest.c @@ -15,6 +15,8 @@ #include "../ssl/packet_locl.h" +#include "ssltestlib.h" + /* Should we fragment records or not? 0 = no, !0 = yes*/ static int fragment = 0; @@ -232,16 +234,12 @@ static int async_puts(BIO *bio, const char *str) return async_write(bio, str, strlen(str)); } -#define MAXLOOPS 100000 - int main(int argc, char *argv[]) { SSL_CTX *serverctx = NULL, *clientctx = NULL; SSL *serverssl = NULL, *clientssl = NULL; - BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL; BIO *s_to_c_fbio = NULL, *c_to_s_fbio = NULL; - int retc = -1, rets = -1, err, abortctr; - int test; + int test, err = 1; CRYPTO_set_mem_debug(1); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); @@ -251,24 +249,9 @@ int main(int argc, char *argv[]) goto end; } - serverctx = SSL_CTX_new(TLS_server_method()); - clientctx = SSL_CTX_new(TLS_client_method()); - if (serverctx == NULL || clientctx == NULL) { - printf("Failed to create SSL_CTX\n"); - goto end; - } - - if (SSL_CTX_use_certificate_file(serverctx, argv[1], - SSL_FILETYPE_PEM) <= 0) { - printf("Failed to load server certificate\n"); - goto end; - } - if (SSL_CTX_use_PrivateKey_file(serverctx, argv[2], - SSL_FILETYPE_PEM) <= 0) { - printf("Failed to load server private key\n"); - } - if (SSL_CTX_check_private_key(serverctx) <= 0) { - printf("Failed to check private key\n"); + if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), + &serverctx, &clientctx, argv[1], argv[2])) { + printf("Failed to create SSL_CTX pair\n"); goto end; } @@ -279,82 +262,26 @@ int main(int argc, char *argv[]) * CCS) */ for (test = 1; test < 3; test++) { - abortctr = 0; - retc = rets = -1; if (test == 2) fragment = 1; - serverssl = SSL_new(serverctx); - clientssl = SSL_new(clientctx); - if (serverssl == NULL || clientssl == NULL) { - printf("Failed to create SSL object\n"); - goto end; - } - - s_to_c_bio = BIO_new(BIO_s_mem()); - c_to_s_bio = BIO_new(BIO_s_mem()); - if (s_to_c_bio == NULL || c_to_s_bio == NULL) { - printf("Failed to create mem BIOs\n"); - goto end; - } s_to_c_fbio = BIO_new(bio_f_async_filter()); c_to_s_fbio = BIO_new(bio_f_async_filter()); if (s_to_c_fbio == NULL || c_to_s_fbio == NULL) { printf("Failed to create filter BIOs\n"); + BIO_free(s_to_c_fbio); + BIO_free(c_to_s_fbio); goto end; } - s_to_c_bio = BIO_push(s_to_c_fbio, s_to_c_bio); - c_to_s_bio = BIO_push(c_to_s_fbio, c_to_s_bio); - if (s_to_c_bio == NULL || c_to_s_bio == NULL) { - printf("Failed to create chained BIOs\n"); + /* BIOs get freed on error */ + if (!create_ssl_connection(serverctx, clientctx, &serverssl, &clientssl, + s_to_c_fbio, c_to_s_fbio)) { + printf("Test %d failed: Create SSL connection failed\n", test); goto end; } - /* Set Non-blocking IO behaviour */ - BIO_set_mem_eof_return(s_to_c_bio, -1); - BIO_set_mem_eof_return(c_to_s_bio, -1); - - /* Up ref these as we are passing them to two SSL objects */ - BIO_up_ref(s_to_c_bio); - BIO_up_ref(c_to_s_bio); - - SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio); - SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio); - - do { - err = SSL_ERROR_WANT_WRITE; - while (retc <= 0 && err == SSL_ERROR_WANT_WRITE) { - retc = SSL_connect(clientssl); - if (retc <= 0) - err = SSL_get_error(clientssl, retc); - } - - if (retc <= 0 && err != SSL_ERROR_WANT_READ) { - printf("Test %d failed: SSL_connect() failed %d, %d\n", - test, retc, err); - goto end; - } - - err = SSL_ERROR_WANT_WRITE; - while (rets <= 0 && err == SSL_ERROR_WANT_WRITE) { - rets = SSL_accept(serverssl); - if (rets <= 0) - err = SSL_get_error(serverssl, rets); - } - - if (rets <= 0 && err != SSL_ERROR_WANT_READ) { - printf("Test %d failed: SSL_accept() failed %d, %d\n", - test, retc, err); - goto end; - } - if (++abortctr == MAXLOOPS) { - printf("Test %d failed: No progress made\n", test); - goto end; - } - } while (retc <=0 || rets <= 0); - /* Also frees the BIOs */ SSL_free(clientssl); SSL_free(serverssl); @@ -363,8 +290,9 @@ int main(int argc, char *argv[]) printf("Test success\n"); + err = 0; end: - if (retc <= 0 || rets <= 0) + if (err) ERR_print_errors_fp(stderr); SSL_free(clientssl); @@ -376,5 +304,5 @@ int main(int argc, char *argv[]) CRYPTO_mem_leaks_fp(stderr); # endif - return (retc > 0 && rets > 0) ? 0 : 1; + return err; } diff --git a/test/build.info b/test/build.info index e9228d0dce..ffb8802db1 100644 --- a/test/build.info +++ b/test/build.info @@ -17,7 +17,7 @@ IF[{- !$disabled{tests} -}] packettest asynctest secmemtest srptest memleaktest \ dtlsv1listentest ct_test threadstest afalgtest d2i_test \ ssl_test_ctx_test ssl_test x509aux cipherlist_test asynciotest \ - bioprinttest getsettest + bioprinttest sslapitest SOURCE[aborttest]=aborttest.c INCLUDE[aborttest]="{- rel2abs(catdir($builddir,"../include")) -}" ../include @@ -246,12 +246,13 @@ IF[{- !$disabled{tests} -}] INCLUDE[testutil.o]=.. INCLUDE[ssl_test_ctx.o]="{- rel2abs(catdir($builddir,"../include")) -}" ../include INCLUDE[handshake_helper.o]="{- rel2abs(catdir($builddir,"../include")) -}" ../include + INCLUDE[ssltestlib.o]="{- rel2abs(catdir($builddir,"../include")) -}" ../include SOURCE[x509aux]=x509aux.c INCLUDE[x509aux]="{- rel2abs(catdir($builddir,"../include")) -}" ../include DEPEND[x509aux]=../libcrypto - SOURCE[asynciotest]=asynciotest.c + SOURCE[asynciotest]=asynciotest.c ssltestlib.c INCLUDE[asynciotest]="{- rel2abs(catdir($builddir,"../include")) -}" ../include DEPEND[asynciotest]=../libcrypto ../libssl @@ -285,7 +286,7 @@ _____ } -} - SOURCE[getsettest]=getsettest.c - INCLUDE[getsettest]="{- rel2abs(catdir($builddir,"../include")) -}" ../include - DEPEND[getsettest]=../libcrypto ../libssl + SOURCE[sslapitest]=sslapitest.c ssltestlib.c + INCLUDE[sslapitest]="{- rel2abs(catdir($builddir,"../include")) -}" ../include + DEPEND[sslapitest]=../libcrypto ../libssl ENDIF diff --git a/test/getsettest.c b/test/getsettest.c deleted file mode 100644 index 97d1b357cc..0000000000 --- a/test/getsettest.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include - - -int main(int argc, char *argv[]) -{ - SSL_CTX *ctx = NULL; - SSL *con = NULL; - BIO *err; - int testresult = 0; - - err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); - - CRYPTO_set_mem_debug(1); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - - /* Test tlsext_status_type */ - ctx = SSL_CTX_new(TLS_method()); - - if (SSL_CTX_get_tlsext_status_type(ctx) != -1) { - printf("Unexpected initial value for " - "SSL_CTX_get_tlsext_status_type()\n"); - goto end; - } - - con = SSL_new(ctx); - - if (SSL_get_tlsext_status_type(con) != -1) { - printf("Unexpected initial value for SSL_get_tlsext_status_type()\n"); - goto end; - } - - if (!SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp)) { - printf("Unexpected fail for SSL_set_tlsext_status_type()\n"); - goto end; - } - - if (SSL_get_tlsext_status_type(con) != TLSEXT_STATUSTYPE_ocsp) { - printf("Unexpected result for SSL_get_tlsext_status_type()\n"); - goto end; - } - - SSL_free(con); - con = NULL; - - if (!SSL_CTX_set_tlsext_status_type(ctx, TLSEXT_STATUSTYPE_ocsp)) { - printf("Unexpected fail for SSL_CTX_set_tlsext_status_type()\n"); - goto end; - } - - if (SSL_CTX_get_tlsext_status_type(ctx) != TLSEXT_STATUSTYPE_ocsp) { - printf("Unexpected result for SSL_CTX_get_tlsext_status_type()\n"); - goto end; - } - - con = SSL_new(ctx); - - if (SSL_get_tlsext_status_type(con) != TLSEXT_STATUSTYPE_ocsp) { - printf("Unexpected result for SSL_get_tlsext_status_type() (test 2)\n"); - goto end; - } - - testresult = 1; - - end: - SSL_free(con); - SSL_CTX_free(ctx); - -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - if (CRYPTO_mem_leaks(err) <= 0) - testresult = 0; -#endif - BIO_free(err); - - if (testresult) - printf("PASS\n"); - - return testresult?0:1; -} diff --git a/test/recipes/90-test_getset.t b/test/recipes/90-test_sslapi.t similarity index 73% rename from test/recipes/90-test_getset.t rename to test/recipes/90-test_sslapi.t index 3e245c12ab..ec525a1ffa 100644 --- a/test/recipes/90-test_getset.t +++ b/test/recipes/90-test_sslapi.t @@ -9,12 +9,14 @@ use OpenSSL::Test; use OpenSSL::Test::Utils; +use OpenSSL::Test qw/:DEFAULT srctop_file/; -setup("test_getset"); +setup("test_sslapi"); plan skip_all => "No TLS/SSL protocols are supported by this OpenSSL build" if alldisabled(grep { $_ ne "ssl3" } available_protocols("tls")); plan tests => 1; -ok(run(test(["getsettest"])), "running getsettest"); +ok(run(test(["sslapitest", srctop_file("apps", "server.pem"), + srctop_file("apps", "server.pem")])), "running sslapitest"); diff --git a/test/sslapitest.c b/test/sslapitest.c new file mode 100644 index 0000000000..4c94f27cbc --- /dev/null +++ b/test/sslapitest.c @@ -0,0 +1,220 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include + +#include "ssltestlib.h" + +static char *cert = NULL; +static char *privkey = NULL; + +static int test_tlsext_status_type(void) +{ + SSL_CTX *ctx = NULL; + SSL *con = NULL; + int testresult = 0; + + /* Test tlsext_status_type */ + ctx = SSL_CTX_new(TLS_method()); + + if (SSL_CTX_get_tlsext_status_type(ctx) != -1) { + printf("Unexpected initial value for " + "SSL_CTX_get_tlsext_status_type()\n"); + goto end; + } + + con = SSL_new(ctx); + + if (SSL_get_tlsext_status_type(con) != -1) { + printf("Unexpected initial value for SSL_get_tlsext_status_type()\n"); + goto end; + } + + if (!SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp)) { + printf("Unexpected fail for SSL_set_tlsext_status_type()\n"); + goto end; + } + + if (SSL_get_tlsext_status_type(con) != TLSEXT_STATUSTYPE_ocsp) { + printf("Unexpected result for SSL_get_tlsext_status_type()\n"); + goto end; + } + + SSL_free(con); + con = NULL; + + if (!SSL_CTX_set_tlsext_status_type(ctx, TLSEXT_STATUSTYPE_ocsp)) { + printf("Unexpected fail for SSL_CTX_set_tlsext_status_type()\n"); + goto end; + } + + if (SSL_CTX_get_tlsext_status_type(ctx) != TLSEXT_STATUSTYPE_ocsp) { + printf("Unexpected result for SSL_CTX_get_tlsext_status_type()\n"); + goto end; + } + + con = SSL_new(ctx); + + if (SSL_get_tlsext_status_type(con) != TLSEXT_STATUSTYPE_ocsp) { + printf("Unexpected result for SSL_get_tlsext_status_type() (test 2)\n"); + goto end; + } + + testresult = 1; + + end: + SSL_free(con); + SSL_CTX_free(ctx); + + return testresult; +} + +static int test_session(void) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl1 = NULL, *clientssl1 = NULL; + SSL *serverssl2 = NULL, *clientssl2 = NULL; + SSL_SESSION *sess1 = NULL, *sess2 = NULL; + int testresult = 0; + + if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), &sctx, + &cctx, cert, privkey)) { + printf("Unable to create SSL_CTX pair\n"); + return 0; + } + + /* Turn on client session cache */ + SSL_CTX_set_session_cache_mode(cctx, SSL_SESS_CACHE_CLIENT); + + if (!create_ssl_connection(sctx, cctx, &serverssl1, &clientssl1, NULL, + NULL)) { + printf("Unable to create SSL connection\n"); + goto end; + } + + sess1 = SSL_get1_session(clientssl1); + if (sess1 == NULL) { + printf("Unexpected NULL session\n"); + goto end; + } + + if (SSL_CTX_add_session(cctx, sess1)) { + /* Should have failed because it should already be in the cache */ + printf("Unexpected success adding session to cache\n"); + goto end; + } + + if (!create_ssl_connection(sctx, cctx, &serverssl2, &clientssl2, NULL, + NULL)) { + printf("Unable to create second SSL connection\n"); + goto end; + } + + sess2 = SSL_get1_session(clientssl2); + if (sess2 == NULL) { + printf("Unexpected NULL session from clientssl2\n"); + goto end; + } + + /* + * This should clear sess2 from the cache because it is a "bad" session. See + * SSL_set_session() documentation. + */ + if (!SSL_set_session(clientssl2, sess1)) { + printf("Unexpected failure setting session\n"); + goto end; + } + + if (SSL_get_session(clientssl2) != sess1) { + printf("Unexpected session found\n"); + goto end; + } + + if (!SSL_CTX_add_session(cctx, sess2)) { + /* + * Should have succeeded because it should not already be in the cache + */ + printf("Unexpected failure adding session to cache\n"); + goto end; + } + + if (!SSL_CTX_remove_session(cctx, sess2)) { + printf("Unexpected failure removing session from cache\n"); + goto end; + } + + if (SSL_CTX_remove_session(cctx, sess2)) { + printf("Unexpected success removing session from cache\n"); + goto end; + } + + testresult = 1; + end: + SSL_free(serverssl1); + SSL_free(clientssl1); + SSL_free(serverssl2); + SSL_free(clientssl2); + SSL_SESSION_free(sess1); + SSL_SESSION_free(sess2); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + +#define RUNTEST(testname) \ + do { \ + printf("Testing " #testname "..."); \ + if (test_##testname()) {\ + printf("ok\n"); \ + } else { \ + printf("not ok\n"); \ + goto end; \ + } \ + } while(0) + +int main(int argc, char *argv[]) +{ + BIO *err; + int testresult = 0; + + if (argc != 3) { + printf("Invalid argument count\n"); + goto end; + } + + cert = argv[1]; + privkey = argv[2]; + + err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); + + CRYPTO_set_mem_debug(1); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + + RUNTEST(tlsext_status_type); + RUNTEST(session); + + testresult = 1; + + end: + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + if (CRYPTO_mem_leaks(err) <= 0) + testresult = 0; +#endif + BIO_free(err); + + if (testresult) + printf("PASS\n"); + + return testresult ? 0 : 1; +} diff --git a/test/ssltestlib.c b/test/ssltestlib.c new file mode 100644 index 0000000000..5f780d75b8 --- /dev/null +++ b/test/ssltestlib.c @@ -0,0 +1,145 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ssltestlib.h" + +int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm, + SSL_CTX **sctx, SSL_CTX **cctx, char *certfile, + char *privkeyfile) +{ + SSL_CTX *serverctx = NULL; + SSL_CTX *clientctx = NULL; + + serverctx = SSL_CTX_new(TLS_server_method()); + clientctx = SSL_CTX_new(TLS_client_method()); + if (serverctx == NULL || clientctx == NULL) { + printf("Failed to create SSL_CTX\n"); + goto err; + } + + if (SSL_CTX_use_certificate_file(serverctx, certfile, + SSL_FILETYPE_PEM) <= 0) { + printf("Failed to load server certificate\n"); + goto err; + } + if (SSL_CTX_use_PrivateKey_file(serverctx, privkeyfile, + SSL_FILETYPE_PEM) <= 0) { + printf("Failed to load server private key\n"); + } + if (SSL_CTX_check_private_key(serverctx) <= 0) { + printf("Failed to check private key\n"); + goto err; + } + + *sctx = serverctx; + *cctx = clientctx; + + return 1; + err: + SSL_CTX_free(serverctx); + SSL_CTX_free(clientctx); + return 0; +} + +#define MAXLOOPS 100000 + +/* + * NOTE: Transfers control of the BIOs - this function will free them on error + */ +int create_ssl_connection(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl, + SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio) +{ + int retc = -1, rets = -1, err, abortctr = 0; + SSL *serverssl, *clientssl; + BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL; + + serverssl = SSL_new(serverctx); + clientssl = SSL_new(clientctx); + + if (serverssl == NULL || clientssl == NULL) { + printf("Failed to create SSL object\n"); + goto error; + } + + s_to_c_bio = BIO_new(BIO_s_mem()); + c_to_s_bio = BIO_new(BIO_s_mem()); + if (s_to_c_bio == NULL || c_to_s_bio == NULL) { + printf("Failed to create mem BIOs\n"); + goto error; + } + + if (s_to_c_fbio != NULL) + s_to_c_bio = BIO_push(s_to_c_fbio, s_to_c_bio); + if (c_to_s_fbio != NULL) + c_to_s_bio = BIO_push(c_to_s_fbio, c_to_s_bio); + if (s_to_c_bio == NULL || c_to_s_bio == NULL) { + printf("Failed to create chained BIOs\n"); + goto error; + } + + /* Set Non-blocking IO behaviour */ + BIO_set_mem_eof_return(s_to_c_bio, -1); + BIO_set_mem_eof_return(c_to_s_bio, -1); + + /* Up ref these as we are passing them to two SSL objects */ + BIO_up_ref(s_to_c_bio); + BIO_up_ref(c_to_s_bio); + + SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio); + SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio); + + /* BIOs will now be freed when SSL objects are freed */ + s_to_c_bio = c_to_s_bio = NULL; + s_to_c_fbio = c_to_s_fbio = NULL; + + do { + err = SSL_ERROR_WANT_WRITE; + while (retc <= 0 && err == SSL_ERROR_WANT_WRITE) { + retc = SSL_connect(clientssl); + if (retc <= 0) + err = SSL_get_error(clientssl, retc); + } + + if (retc <= 0 && err != SSL_ERROR_WANT_READ) { + printf("SSL_connect() failed %d, %d\n", retc, err); + goto error; + } + + err = SSL_ERROR_WANT_WRITE; + while (rets <= 0 && err == SSL_ERROR_WANT_WRITE) { + rets = SSL_accept(serverssl); + if (rets <= 0) + err = SSL_get_error(serverssl, rets); + } + + if (rets <= 0 && err != SSL_ERROR_WANT_READ) { + printf("SSL_accept() failed %d, %d\n", retc, err); + goto error; + } + if (++abortctr == MAXLOOPS) { + printf("No progress made\n"); + goto error; + } + } while (retc <=0 || rets <= 0); + + *sssl = serverssl; + *cssl = clientssl; + + return 1; + + error: + SSL_free(serverssl); + SSL_free(clientssl); + BIO_free(s_to_c_bio); + BIO_free(c_to_s_bio); + BIO_free(s_to_c_fbio); + BIO_free(c_to_s_fbio); + + return 0; +} diff --git a/test/ssltestlib.h b/test/ssltestlib.h new file mode 100644 index 0000000000..f05878aaa5 --- /dev/null +++ b/test/ssltestlib.h @@ -0,0 +1,21 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_SSLTESTLIB_H +# define HEADER_SSLTESTLIB_H + +# include + +int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm, + SSL_CTX **sctx, SSL_CTX **cctx, char *certfile, + char *privkeyfile); +int create_ssl_connection(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl, + SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio); + +#endif /* HEADER_SSLTESTLIB_H */