Commit 2cb4b5f6 authored by Matt Caswell's avatar Matt Caswell
Browse files

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: default avatarRich Salz <rsalz@openssl.org>
parent e70656cf
Loading
Loading
Loading
Loading
+15 −87
Original line number Diff line number Diff line
@@ -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,81 +262,25 @@ 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");
            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);
        /* 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;
        }
        } while (retc <=0 || rets <= 0);

        /* Also frees the BIOs */
        SSL_free(clientssl);
@@ -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;
}
+6 −5
Original line number Diff line number Diff line
@@ -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
+4 −2
Original line number Diff line number Diff line
@@ -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");
+220 −0
Original line number Diff line number Diff line
@@ -12,19 +12,17 @@
#include <openssl/crypto.h>
#include <openssl/ssl.h>

#include "ssltestlib.h"

int main(int argc, char *argv[])
static char *cert = NULL;
static char *privkey = NULL;

static int test_tlsext_status_type(void)
{
    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());

@@ -77,6 +75,138 @@ int main(int argc, char *argv[])
    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;

test/ssltestlib.c

0 → 100644
+145 −0
Original line number Diff line number Diff line
/*
 * 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;
}
Loading