X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=test%2Fssltest.c;h=8018b3bd161992f188adfe680a271d632e0d02d5;hp=0912392649a5916c56321d1c58710cfcfa316da0;hb=b7dffce017aa045272c42eeb5da40804015a759a;hpb=361a1191279d5a801fa6cfe22d51ef17d6ab38ea diff --git a/test/ssltest.c b/test/ssltest.c index 0912392649..8018b3bd16 100644 --- a/test/ssltest.c +++ b/test/ssltest.c @@ -1,4 +1,3 @@ -/* ssl/ssltest.c */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -188,7 +187,11 @@ # include #endif #include +#ifndef OPENSSL_NO_CT +# include +#endif +#include "internal/threads.h" #include "../ssl/ssl_locl.h" /* @@ -205,6 +208,9 @@ # include OPENSSL_UNISTD #endif +static SSL_CTX *s_ctx = NULL; +static SSL_CTX *s_ctx2 = NULL; + /* * There is really no standard for this, so let's assign something * only for this test @@ -253,7 +259,7 @@ typedef struct srp_client_arg_st { static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg) { SRP_CLIENT_ARG *srp_client_arg = (SRP_CLIENT_ARG *)arg; - return BUF_strdup((char *)srp_client_arg->srppassin); + return OPENSSL_strdup((char *)srp_client_arg->srppassin); } /* SRP server */ @@ -364,9 +370,63 @@ static int verify_npn(SSL *client, SSL *server) #endif static const char *alpn_client; -static const char *alpn_server; +static char *alpn_server; +static char *alpn_server2; static const char *alpn_expected; static unsigned char *alpn_selected; +static const char *server_min_proto; +static const char *server_max_proto; +static const char *client_min_proto; +static const char *client_max_proto; +static const char *should_negotiate; +static const char *sn_client; +static const char *sn_server1; +static const char *sn_server2; +static int sn_expect = 0; +static const char *server_sess_out; +static const char *server_sess_in; +static const char *client_sess_out; +static const char *client_sess_in; +static SSL_SESSION *server_sess; +static SSL_SESSION *client_sess; + +static int servername_cb(SSL *s, int *ad, void *arg) +{ + const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); + if (sn_server2 == NULL) { + BIO_printf(bio_stdout, "Servername 2 is NULL\n"); + return SSL_TLSEXT_ERR_NOACK; + } + + if (servername) { + if (s_ctx2 != NULL && sn_server2 != NULL && + !strcasecmp(servername, sn_server2)) { + BIO_printf(bio_stdout, "Switching server context.\n"); + SSL_set_SSL_CTX(s, s_ctx2); + } + } + return SSL_TLSEXT_ERR_OK; +} +static int verify_servername(SSL *client, SSL *server) +{ + /* just need to see if sn_context is what we expect */ + SSL_CTX* ctx = SSL_get_SSL_CTX(server); + if (sn_expect == 0) + return 0; + if (sn_expect == 1 && ctx == s_ctx) + return 0; + if (sn_expect == 2 && ctx == s_ctx2) + return 0; + BIO_printf(bio_stdout, "Servername: expected context %d\n", sn_expect); + if (ctx == s_ctx2) + BIO_printf(bio_stdout, "Servername: context is 2\n"); + else if (ctx == s_ctx) + BIO_printf(bio_stdout, "Servername: context is 1\n"); + else + BIO_printf(bio_stdout, "Servername: context is unknown\n"); + return -1; +} + /*- * next_protos_parse parses a comma separated list of strings into a string @@ -377,7 +437,7 @@ static unsigned char *alpn_selected; * * returns: a malloced buffer or NULL on failure. */ -static unsigned char *next_protos_parse(unsigned short *outlen, +static unsigned char *next_protos_parse(size_t *outlen, const char *in) { size_t len; @@ -413,12 +473,13 @@ static int cb_server_alpn(SSL *s, const unsigned char **out, unsigned int inlen, void *arg) { unsigned char *protos; - unsigned short protos_len; + size_t protos_len; + char* alpn_str = arg; - protos = next_protos_parse(&protos_len, alpn_server); + protos = next_protos_parse(&protos_len, alpn_str); if (protos == NULL) { fprintf(stderr, "failed to parser ALPN server protocol string: %s\n", - alpn_server); + alpn_str); abort(); } @@ -484,13 +545,18 @@ static int verify_alpn(SSL *client, SSL *server) BIO_printf(bio_stdout, "', server: '"); BIO_write(bio_stdout, server_proto, server_proto_len); BIO_printf(bio_stdout, "'\n"); - BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '%s'\n", - alpn_client, alpn_server); + BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '", + alpn_client); + if (SSL_get_SSL_CTX(server) == s_ctx2) { + BIO_printf(bio_stdout, "%s'\n", + alpn_server2); + } else { + BIO_printf(bio_stdout, "%s'\n", + alpn_server); + } return -1; } -#define SCT_EXT_TYPE 18 - /* * WARNING : below extension types are *NOT* IETF assigned, and could * conflict if these types are reassigned and handled specially by OpenSSL @@ -525,7 +591,7 @@ static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *arg) { - if (ext_type == SCT_EXT_TYPE) + if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp) serverinfo_sct_seen++; else if (ext_type == TACK_EXT_TYPE) serverinfo_tack_seen++; @@ -728,6 +794,8 @@ static int debug = 0; static const char rnd_seed[] = "string to make the random number generator think it has entropy"; +int doit_localhost(SSL *s_ssl, SSL *c_ssl, int family, + long bytes, clock_t *s_time, clock_t *c_time); int doit_biopair(SSL *s_ssl, SSL *c_ssl, long bytes, clock_t *s_time, clock_t *c_time); int doit(SSL *s_ssl, SSL *c_ssl, long bytes); @@ -762,22 +830,29 @@ static void sv_usage(void) fprintf(stderr, " -no_dhe - disable DHE\n"); #endif #ifndef OPENSSL_NO_EC - fprintf(stderr, " -no_ecdhe - disable ECDHE\n"); + fprintf(stderr, " -no_ecdhe - disable ECDHE\nTODO(openssl-team): no_ecdhe was broken by auto ecdh. Make this work again.\n"); #endif #ifndef OPENSSL_NO_PSK fprintf(stderr, " -psk arg - PSK in hex (without 0x)\n"); #endif #ifndef OPENSSL_NO_SRP - fprintf(stderr, " -srpuser user - SRP username to use\n"); - fprintf(stderr, " -srppass arg - password for 'user'\n"); + fprintf(stderr, " -srpuser user - SRP username to use\n"); + fprintf(stderr, " -srppass arg - password for 'user'\n"); #endif -#ifndef OPENSSL_NO_SSL3_METHOD +#ifndef OPENSSL_NO_SSL3 fprintf(stderr, " -ssl3 - use SSLv3\n"); #endif +#ifndef OPENSSL_NO_TLS1 fprintf(stderr, " -tls1 - use TLSv1\n"); +#endif #ifndef OPENSSL_NO_DTLS + fprintf(stderr, " -dtls - use DTLS\n"); +#ifndef OPENSSL_NO_DTLS1 fprintf(stderr, " -dtls1 - use DTLSv1\n"); +#endif +#ifndef OPENSSL_NO_DTLS1_2 fprintf(stderr, " -dtls12 - use DTLSv1.2\n"); +#endif #endif fprintf(stderr, " -CApath arg - PEM format directory of CA's\n"); fprintf(stderr, " -CAfile arg - PEM format file of CA's\n"); @@ -789,16 +864,12 @@ static void sv_usage(void) " -c_key arg - Client key file (default: same as -c_cert)\n"); fprintf(stderr, " -cipher arg - The cipher list\n"); fprintf(stderr, " -bio_pair - Use BIO pairs\n"); + fprintf(stderr, " -ipv4 - Use IPv4 connection on localhost\n"); + fprintf(stderr, " -ipv6 - Use IPv6 connection on localhost\n"); fprintf(stderr, " -f - Test even cases that can't work\n"); fprintf(stderr, " -time - measure processor time used by client and server\n"); fprintf(stderr, " -zlib - use zlib compression\n"); -#ifndef OPENSSL_NO_EC - fprintf(stderr, - " -named_curve arg - Elliptic curve name to use for ephemeral ECDH keys.\n" - " Use \"openssl ecparam -list_curves\" for all names\n" - " (default is sect163r2).\n"); -#endif fprintf(stderr, " -test_cipherlist - Verifies the order of the ssl cipher lists.\n" " When this option is requested, the cipherlist\n" @@ -816,8 +887,31 @@ static void sv_usage(void) " -custom_ext - try various custom extension callbacks\n"); fprintf(stderr, " -alpn_client - have client side offer ALPN\n"); fprintf(stderr, " -alpn_server - have server side offer ALPN\n"); + fprintf(stderr, " -alpn_server1 - alias for -alpn_server\n"); + fprintf(stderr, " -alpn_server2 - have server side context 2 offer ALPN\n"); fprintf(stderr, " -alpn_expected - the ALPN protocol that should be negotiated\n"); + fprintf(stderr, " -server_min_proto - Minimum version the server should support\n"); + fprintf(stderr, " -server_max_proto - Maximum version the server should support\n"); + fprintf(stderr, " -client_min_proto - Minimum version the client should support\n"); + fprintf(stderr, " -client_max_proto - Maximum version the client should support\n"); + fprintf(stderr, " -should_negotiate - The version that should be negotiated, fail-client or fail-server\n"); +#ifndef OPENSSL_NO_CT + fprintf(stderr, " -noct - no certificate transparency\n"); + fprintf(stderr, " -requestct - request certificate transparency\n"); + fprintf(stderr, " -requirect - require certificate transparency\n"); +#endif + fprintf(stderr, " -sn_client - have client request this servername\n"); + fprintf(stderr, " -sn_server1 - have server context 1 respond to this servername\n"); + fprintf(stderr, " -sn_server2 - have server context 2 respond to this servername\n"); + fprintf(stderr, " -sn_expect1 - expected server 1\n"); + fprintf(stderr, " -sn_expect2 - expected server 2\n"); + fprintf(stderr, " -server_sess_out - Save the server session to a file\n"); + fprintf(stderr, " -server_sess_in - Read the server session from a file\n"); + fprintf(stderr, " -client_sess_out - Save the client session to a file\n"); + fprintf(stderr, " -client_sess_in - Read the client session from a file\n"); + fprintf(stderr, " -should_reuse - The expected state of reusing the session\n"); + fprintf(stderr, " -no_ticket - do not issue TLS session ticket\n"); } static void print_key_details(BIO *out, EVP_PKEY *key) @@ -888,87 +982,111 @@ static void print_details(SSL *c_ssl, const char *prefix) BIO_printf(bio_stdout, "\n"); } -static void lock_dbg_cb(int mode, int type, const char *file, int line) +/* + * protocol_from_string - converts a protocol version string to a number + * + * Returns -1 on failure or the version on success + */ +static int protocol_from_string(const char *value) +{ + struct protocol_versions { + const char *name; + int version; + }; + static const struct protocol_versions versions[] = { + {"ssl3", SSL3_VERSION}, + {"tls1", TLS1_VERSION}, + {"tls1.1", TLS1_1_VERSION}, + {"tls1.2", TLS1_2_VERSION}, + {"dtls1", DTLS1_VERSION}, + {"dtls1.2", DTLS1_2_VERSION}}; + size_t i; + size_t n = OSSL_NELEM(versions); + + for (i = 0; i < n; i++) + if (strcmp(versions[i].name, value) == 0) + return versions[i].version; + return -1; +} + +static SSL_SESSION *read_session(const char *filename) { - static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */ - const char *errstr = NULL; - int rw; + SSL_SESSION *sess; + BIO *f = BIO_new_file(filename, "r"); - rw = mode & (CRYPTO_READ | CRYPTO_WRITE); - if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE))) { - errstr = "invalid mode"; - goto err; + if (f == NULL) { + BIO_printf(bio_err, "Can't open session file %s\n", filename); + ERR_print_errors(bio_err); + return NULL; } - - if (type < 0 || type >= CRYPTO_NUM_LOCKS) { - errstr = "type out of bounds"; - goto err; + sess = PEM_read_bio_SSL_SESSION(f, NULL, 0, NULL); + if (sess == NULL) { + BIO_printf(bio_err, "Can't parse session file %s\n", filename); + ERR_print_errors(bio_err); } + BIO_free(f); + return sess; +} - if (mode & CRYPTO_LOCK) { - if (modes[type]) { - errstr = "already locked"; - /* - * must not happen in a single-threaded program (would deadlock) - */ - goto err; - } - - modes[type] = rw; - } else if (mode & CRYPTO_UNLOCK) { - if (!modes[type]) { - errstr = "not locked"; - goto err; - } - - if (modes[type] != rw) { - errstr = (rw == CRYPTO_READ) ? - "CRYPTO_r_unlock on write lock" : - "CRYPTO_w_unlock on read lock"; - } +static int write_session(const char *filename, SSL_SESSION *sess) +{ + BIO *f = BIO_new_file(filename, "w"); - modes[type] = 0; - } else { - errstr = "invalid mode"; - goto err; + if (sess == NULL) { + BIO_printf(bio_err, "No session information\n"); + return 0; + } + if (f == NULL) { + BIO_printf(bio_err, "Can't open session file %s\n", filename); + ERR_print_errors(bio_err); + return 0; } + PEM_write_bio_SSL_SESSION(f, sess); + BIO_free(f); + return 1; +} - err: - if (errstr) { - /* we cannot use bio_err here */ - fprintf(stderr, - "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n", - errstr, mode, type, file, line); +/* + * set_protocol_version - Sets protocol version minimum or maximum + * + * Returns 0 on failure and 1 on success + */ +static int set_protocol_version(const char *version, SSL *ssl, int setting) +{ + if (version != NULL) { + int ver = protocol_from_string(version); + if (ver < 0) { + BIO_printf(bio_err, "Error parsing: %s\n", version); + return 0; + } + return SSL_ctrl(ssl, setting, ver, NULL); } + return 1; } int main(int argc, char *argv[]) { char *CApath = NULL, *CAfile = NULL; int badop = 0; - int bio_pair = 0; + enum { BIO_MEM, BIO_PAIR, BIO_IPV4, BIO_IPV6 } bio_type = BIO_MEM; int force = 0; - int dtls1 = 0, dtls12 = 0, tls1 = 0, ssl3 = 0, ret = 1; + int dtls1 = 0, dtls12 = 0, dtls = 0, tls1 = 0, ssl3 = 0, ret = 1; int client_auth = 0; int server_auth = 0, i; struct app_verify_arg app_verify_arg = { APP_CALLBACK_STRING, 0, 0, NULL, NULL }; -#ifndef OPENSSL_NO_EC - char *named_curve = NULL; -#endif - SSL_CTX *s_ctx = NULL; + char *p; SSL_CTX *c_ctx = NULL; const SSL_METHOD *meth = NULL; SSL *c_ssl, *s_ssl; int number = 1, reuse = 0; + int should_reuse = -1; + int no_ticket = 0; long bytes = 256L; #ifndef OPENSSL_NO_DH DH *dh; int dhe512 = 0, dhe1024dsa = 0; #endif -#ifndef OPENSSL_NO_EC - EC_KEY *ecdh = NULL; -#endif #ifndef OPENSSL_NO_SRP /* client */ SRP_CLIENT_ARG srp_client_arg = { NULL, NULL }; @@ -976,7 +1094,6 @@ int main(int argc, char *argv[]) SRP_SERVER_ARG srp_server_arg = { NULL, NULL }; #endif int no_dhe = 0; - int no_ecdhe = 0; int no_psk = 0; int print_time = 0; clock_t s_time = 0, c_time = 0; @@ -989,11 +1106,18 @@ int main(int argc, char *argv[]) #ifdef OPENSSL_FIPS int fips_mode = 0; #endif - int no_protocol = 0; - - SSL_CONF_CTX *s_cctx = NULL, *c_cctx = NULL; + int no_protocol; + int min_version = 0, max_version = 0; +#ifndef OPENSSL_NO_CT + /* + * Disable CT validation by default, because it will interfere with + * anything using custom extension handlers to deal with SCT extensions. + */ + ct_validation_cb ct_validation = NULL; +#endif + SSL_CONF_CTX *s_cctx = NULL, *c_cctx = NULL, *s_cctx2 = NULL; STACK_OF(OPENSSL_STRING) *conf_args = NULL; - const char *arg = NULL, *argn = NULL; + char *arg = NULL, *argn = NULL; verbose = 0; debug = 0; @@ -1001,17 +1125,9 @@ int main(int argc, char *argv[]) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); - CRYPTO_set_locking_callback(lock_dbg_cb); - - /* enable memory leak checking unless explicitly disabled */ - if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) - && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off")))) { - CRYPTO_malloc_debug_init(); - CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); - } else { - /* OPENSSL_DEBUG_MEMORY=off */ - CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0); - } + p = getenv("OPENSSL_DEBUG_MEMORY"); + if (p != NULL && strcmp(p, "on") == 0) + CRYPTO_set_mem_debug(1); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); RAND_seed(rnd_seed, sizeof rnd_seed); @@ -1019,9 +1135,10 @@ int main(int argc, char *argv[]) bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT); s_cctx = SSL_CONF_CTX_new(); + s_cctx2 = SSL_CONF_CTX_new(); c_cctx = SSL_CONF_CTX_new(); - if (!s_cctx || !c_cctx) { + if (!s_cctx || !c_cctx || !s_cctx2) { ERR_print_errors(bio_err); goto end; } @@ -1030,10 +1147,18 @@ int main(int argc, char *argv[]) SSL_CONF_FLAG_CMDLINE | SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE | SSL_CONF_FLAG_REQUIRE_PRIVATE); + SSL_CONF_CTX_set_flags(s_cctx2, + SSL_CONF_FLAG_CMDLINE | SSL_CONF_FLAG_SERVER | + SSL_CONF_FLAG_CERTIFICATE | + SSL_CONF_FLAG_REQUIRE_PRIVATE); if (!SSL_CONF_CTX_set1_prefix(s_cctx, "-s_")) { ERR_print_errors(bio_err); goto end; } + if (!SSL_CONF_CTX_set1_prefix(s_cctx2, "-s_")) { + ERR_print_errors(bio_err); + goto end; + } SSL_CONF_CTX_set_flags(c_cctx, SSL_CONF_FLAG_CMDLINE | SSL_CONF_FLAG_CLIENT | @@ -1091,7 +1216,7 @@ int main(int argc, char *argv[]) } else if (strcmp(*argv, "-no_dhe") == 0) no_dhe = 1; else if (strcmp(*argv, "-no_ecdhe") == 0) - no_ecdhe = 1; + /* obsolete */; else if (strcmp(*argv, "-psk") == 0) { if (--argc < 1) goto bad; @@ -1111,31 +1236,24 @@ int main(int argc, char *argv[]) goto bad; srp_server_arg.expected_user = srp_client_arg.srplogin = *(++argv); - tls1 = 1; + min_version = TLS1_VERSION; } else if (strcmp(*argv, "-srppass") == 0) { if (--argc < 1) goto bad; srp_server_arg.pass = srp_client_arg.srppassin = *(++argv); - tls1 = 1; + min_version = TLS1_VERSION; } #endif else if (strcmp(*argv, "-tls1") == 0) { tls1 = 1; } else if (strcmp(*argv, "-ssl3") == 0) { -#ifdef OPENSSL_NO_SSL3_METHOD - no_protocol = 1; -#endif ssl3 = 1; } else if (strcmp(*argv, "-dtls1") == 0) { -#ifdef OPENSSL_NO_DTLS - no_protocol = 1; -#endif dtls1 = 1; } else if (strcmp(*argv, "-dtls12") == 0) { -#ifdef OPENSSL_NO_DTLS - no_protocol = 1; -#endif dtls12 = 1; + } else if (strcmp(*argv, "-dtls") == 0) { + dtls = 1; } else if (strncmp(*argv, "-num", 4) == 0) { if (--argc < 1) goto bad; @@ -1166,28 +1284,37 @@ int main(int argc, char *argv[]) goto bad; CAfile = *(++argv); } else if (strcmp(*argv, "-bio_pair") == 0) { - bio_pair = 1; - } else if (strcmp(*argv, "-f") == 0) { + bio_type = BIO_PAIR; + } +#ifndef OPENSSL_NO_SOCK + else if (strcmp(*argv, "-ipv4") == 0) { + bio_type = BIO_IPV4; + } else if (strcmp(*argv, "-ipv6") == 0) { + bio_type = BIO_IPV6; + } +#endif + else if (strcmp(*argv, "-f") == 0) { force = 1; } else if (strcmp(*argv, "-time") == 0) { print_time = 1; } +#ifndef OPENSSL_NO_CT + else if (strcmp(*argv, "-noct") == 0) { + ct_validation = NULL; + } + else if (strcmp(*argv, "-requestct") == 0) { + ct_validation = CT_verify_no_bad_scts; + } + else if (strcmp(*argv, "-requirect") == 0) { + ct_validation = CT_verify_at_least_one_good_sct; + } +#endif #ifndef OPENSSL_NO_COMP else if (strcmp(*argv, "-zlib") == 0) { comp = COMP_ZLIB; } #endif - else if (strcmp(*argv, "-named_curve") == 0) { - if (--argc < 1) - goto bad; -#ifndef OPENSSL_NO_EC - named_curve = *(++argv); -#else - fprintf(stderr, - "ignoring -named_curve, since I'm compiled without ECDH\n"); - ++argv; -#endif - } else if (strcmp(*argv, "-app_verify") == 0) { + else if (strcmp(*argv, "-app_verify") == 0) { app_verify_arg.app_verify = 1; } else if (strcmp(*argv, "-proxy") == 0) { app_verify_arg.allow_proxy_certs = 1; @@ -1217,14 +1344,77 @@ int main(int argc, char *argv[]) if (--argc < 1) goto bad; alpn_client = *(++argv); - } else if (strcmp(*argv, "-alpn_server") == 0) { + } else if (strcmp(*argv, "-alpn_server") == 0 || + strcmp(*argv, "-alpn_server1") == 0) { if (--argc < 1) goto bad; alpn_server = *(++argv); + } else if (strcmp(*argv, "-alpn_server2") == 0) { + if (--argc < 1) + goto bad; + alpn_server2 = *(++argv); } else if (strcmp(*argv, "-alpn_expected") == 0) { if (--argc < 1) goto bad; alpn_expected = *(++argv); + } else if (strcmp(*argv, "-server_min_proto") == 0) { + if (--argc < 1) + goto bad; + server_min_proto = *(++argv); + } else if (strcmp(*argv, "-server_max_proto") == 0) { + if (--argc < 1) + goto bad; + server_max_proto = *(++argv); + } else if (strcmp(*argv, "-client_min_proto") == 0) { + if (--argc < 1) + goto bad; + client_min_proto = *(++argv); + } else if (strcmp(*argv, "-client_max_proto") == 0) { + if (--argc < 1) + goto bad; + client_max_proto = *(++argv); + } else if (strcmp(*argv, "-should_negotiate") == 0) { + if (--argc < 1) + goto bad; + should_negotiate = *(++argv); + } else if (strcmp(*argv, "-sn_client") == 0) { + if (--argc < 1) + goto bad; + sn_client = *(++argv); + } else if (strcmp(*argv, "-sn_server1") == 0) { + if (--argc < 1) + goto bad; + sn_server1 = *(++argv); + } else if (strcmp(*argv, "-sn_server2") == 0) { + if (--argc < 1) + goto bad; + sn_server2 = *(++argv); + } else if (strcmp(*argv, "-sn_expect1") == 0) { + sn_expect = 1; + } else if (strcmp(*argv, "-sn_expect2") == 0) { + sn_expect = 2; + } else if (strcmp(*argv, "-server_sess_out") == 0) { + if (--argc < 1) + goto bad; + server_sess_out = *(++argv); + } else if (strcmp(*argv, "-server_sess_in") == 0) { + if (--argc < 1) + goto bad; + server_sess_in = *(++argv); + } else if (strcmp(*argv, "-client_sess_out") == 0) { + if (--argc < 1) + goto bad; + client_sess_out = *(++argv); + } else if (strcmp(*argv, "-client_sess_in") == 0) { + if (--argc < 1) + goto bad; + client_sess_in = *(++argv); + } else if (strcmp(*argv, "-should_reuse") == 0) { + if (--argc < 1) + goto bad; + should_reuse = !!atoi(*(++argv)); + } else if (strcmp(*argv, "-no_ticket") == 0) { + no_ticket = 1; } else { int rv; arg = argv[0]; @@ -1283,12 +1473,34 @@ int main(int argc, char *argv[]) goto end; } - if (ssl3 + tls1 + dtls1 + dtls12 > 1) { - fprintf(stderr, "At most one of -ssl3, -tls1, -dtls1 or -dtls12 should " + if (ssl3 + tls1 + dtls + dtls1 + dtls12 > 1) { + fprintf(stderr, "At most one of -ssl3, -tls1, -dtls, -dtls1 or -dtls12 should " "be requested.\n"); EXIT(1); } +#ifdef OPENSSL_NO_SSL3 + if (ssl3) + no_protocol = 1; + else +#endif +#ifdef OPENSSL_NO_TLS1 + if (tls1) + no_protocol = 1; + else +#endif +#if defined(OPENSSL_NO_DTLS) || defined(OPENSSL_NO_DTLS1) + if (dtls1) + no_protocol = 1; + else +#endif +#if defined(OPENSSL_NO_DTLS) || defined(OPENSSL_NO_DTLS1_2) + if (dtls12) + no_protocol = 1; + else +#endif + no_protocol = 0; + /* * Testing was requested for a compiled-out protocol (e.g. SSLv3). * Ideally, we would error out, but the generic test wrapper can't know @@ -1301,17 +1513,16 @@ int main(int argc, char *argv[]) goto end; } - if (!ssl3 && !tls1 && !dtls1 && !dtls12 && number > 1 && !reuse && !force) { + if (!ssl3 && !tls1 && !dtls && !dtls1 && !dtls12 && number > 1 && !reuse && !force) { fprintf(stderr, "This case cannot work. Use -f to perform " "the test anyway (and\n-d to see what happens), " - "or add one of -ssl3, -tls1, -dtls1, -dtls12, -reuse\n" + "or add one of -ssl3, -tls1, -dtls, -dtls1, -dtls12, -reuse\n" "to avoid protocol mismatch.\n"); EXIT(1); } #ifdef OPENSSL_FIPS if (fips_mode) { if (!FIPS_mode_set(1)) { - ERR_load_crypto_strings(); ERR_print_errors(bio_err); EXIT(1); } else @@ -1320,9 +1531,9 @@ int main(int argc, char *argv[]) #endif if (print_time) { - if (!bio_pair) { + if (bio_type != BIO_PAIR) { fprintf(stderr, "Using BIO pair (-bio_pair)\n"); - bio_pair = 1; + bio_type = BIO_PAIR; } if (number < 50 && !force) fprintf(stderr, @@ -1331,9 +1542,6 @@ int main(int argc, char *argv[]) /* if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */ - SSL_library_init(); - SSL_load_error_strings(); - #ifndef OPENSSL_NO_COMP if (comp == COMP_ZLIB) cm = COMP_zlib(); @@ -1363,31 +1571,32 @@ int main(int argc, char *argv[]) } #endif - /* - * At this point, ssl3/tls1 is only set if the protocol is available. - * (Otherwise we exit early.) However the compiler doesn't know this, so - * we ifdef. - */ -#ifndef OPENSSL_NO_SSL3 - if (ssl3) - meth = SSLv3_method(); - else +#ifndef OPENSSL_NO_TLS + meth = TLS_method(); + if (ssl3) { + min_version = SSL3_VERSION; + max_version = SSL3_VERSION; + } else if (tls1) { + min_version = TLS1_VERSION; + max_version = TLS1_VERSION; + } #endif #ifndef OPENSSL_NO_DTLS - if (dtls1) - meth = DTLSv1_method(); - else if (dtls12) - meth = DTLSv1_2_method(); - else + if (dtls || dtls1 || dtls12) + meth = DTLS_method(); + if (dtls1) { + min_version = DTLS1_VERSION; + max_version = DTLS1_VERSION; + } else if (dtls12) { + min_version = DTLS1_2_VERSION; + max_version = DTLS1_2_VERSION; + } #endif - if (tls1) - meth = TLSv1_method(); - else - meth = TLS_method(); c_ctx = SSL_CTX_new(meth); s_ctx = SSL_CTX_new(meth); - if ((c_ctx == NULL) || (s_ctx == NULL)) { + s_ctx2 = SSL_CTX_new(meth); /* no SSL_CTX_dup! */ + if ((c_ctx == NULL) || (s_ctx == NULL) || (s_ctx2 == NULL)) { ERR_print_errors(bio_err); goto end; } @@ -1398,18 +1607,42 @@ int main(int argc, char *argv[]) */ SSL_CTX_set_security_level(c_ctx, 0); SSL_CTX_set_security_level(s_ctx, 0); + SSL_CTX_set_security_level(s_ctx2, 0); + + if (no_ticket) { + SSL_CTX_set_options(c_ctx, SSL_OP_NO_TICKET); + SSL_CTX_set_options(s_ctx, SSL_OP_NO_TICKET); + } + + if (SSL_CTX_set_min_proto_version(c_ctx, min_version) == 0) + goto end; + if (SSL_CTX_set_max_proto_version(c_ctx, max_version) == 0) + goto end; + if (SSL_CTX_set_min_proto_version(s_ctx, min_version) == 0) + goto end; + if (SSL_CTX_set_max_proto_version(s_ctx, max_version) == 0) + goto end; if (cipher != NULL) { if (!SSL_CTX_set_cipher_list(c_ctx, cipher) - || !SSL_CTX_set_cipher_list(s_ctx, cipher)) { + || !SSL_CTX_set_cipher_list(s_ctx, cipher) + || !SSL_CTX_set_cipher_list(s_ctx2, cipher)) { ERR_print_errors(bio_err); goto end; } } +#ifndef OPENSSL_NO_CT + if (!SSL_CTX_set_ct_validation_callback(c_ctx, ct_validation, NULL)) { + ERR_print_errors(bio_err); + goto end; + } +#endif + /* Process SSL_CONF arguments */ SSL_CONF_CTX_set_ssl_ctx(c_cctx, c_ctx); SSL_CONF_CTX_set_ssl_ctx(s_cctx, s_ctx); + SSL_CONF_CTX_set_ssl_ctx(s_cctx2, s_ctx2); for (i = 0; i < sk_OPENSSL_STRING_num(conf_args); i += 2) { int rv; @@ -1417,8 +1650,11 @@ int main(int argc, char *argv[]) argn = sk_OPENSSL_STRING_value(conf_args, i + 1); rv = SSL_CONF_cmd(c_cctx, arg, argn); /* If not recognised use server context */ - if (rv == -2) - rv = SSL_CONF_cmd(s_cctx, arg, argn); + if (rv == -2) { + rv = SSL_CONF_cmd(s_cctx2, arg, argn); + if (rv > 0) + rv = SSL_CONF_cmd(s_cctx, arg, argn); + } if (rv <= 0) { BIO_printf(bio_err, "Error processing %s %s\n", arg, argn ? argn : ""); @@ -1427,7 +1663,7 @@ int main(int argc, char *argv[]) } } - if (!SSL_CONF_CTX_finish(s_cctx) || !SSL_CONF_CTX_finish(c_cctx)) { + if (!SSL_CONF_CTX_finish(s_cctx) || !SSL_CONF_CTX_finish(c_cctx) || !SSL_CONF_CTX_finish(s_cctx2)) { BIO_puts(bio_err, "Error finishing context\n"); ERR_print_errors(bio_err); goto end; @@ -1435,52 +1671,23 @@ int main(int argc, char *argv[]) #ifndef OPENSSL_NO_DH if (!no_dhe) { if (dhe1024dsa) { - /* - * use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks - */ - SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE); dh = get_dh1024dsa(); } else if (dhe512) dh = get_dh512(); else dh = get_dh1024(); SSL_CTX_set_tmp_dh(s_ctx, dh); + SSL_CTX_set_tmp_dh(s_ctx2, dh); DH_free(dh); } #else (void)no_dhe; #endif -#ifndef OPENSSL_NO_EC - if (!no_ecdhe) { - int nid; - - if (named_curve != NULL) { - nid = OBJ_sn2nid(named_curve); - if (nid == 0) { - BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve); - goto end; - } - } else { - nid = NID_X9_62_prime256v1; - } - - ecdh = EC_KEY_new_by_curve_name(nid); - if (ecdh == NULL) { - BIO_printf(bio_err, "unable to create curve\n"); - goto end; - } - - SSL_CTX_set_tmp_ecdh(s_ctx, ecdh); - SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE); - EC_KEY_free(ecdh); - } -#else - (void)no_ecdhe; -#endif - if ((!SSL_CTX_load_verify_locations(s_ctx, CAfile, CApath)) || (!SSL_CTX_set_default_verify_paths(s_ctx)) || + (!SSL_CTX_load_verify_locations(s_ctx2, CAfile, CApath)) || + (!SSL_CTX_set_default_verify_paths(s_ctx2)) || (!SSL_CTX_load_verify_locations(c_ctx, CAfile, CApath)) || (!SSL_CTX_set_default_verify_paths(c_ctx))) { /* fprintf(stderr,"SSL_load_verify_locations\n"); */ @@ -1488,13 +1695,26 @@ int main(int argc, char *argv[]) /* goto end; */ } +#ifndef OPENSSL_NO_CT + if (!SSL_CTX_set_default_ctlog_list_file(s_ctx) || + !SSL_CTX_set_default_ctlog_list_file(s_ctx2) || + !SSL_CTX_set_default_ctlog_list_file(c_ctx)) { + ERR_print_errors(bio_err); + } +#endif + if (client_auth) { printf("client authentication\n"); SSL_CTX_set_verify(s_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); + SSL_CTX_set_verify(s_ctx2, + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + verify_callback); SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, &app_verify_arg); + SSL_CTX_set_cert_verify_callback(s_ctx2, app_verify_callback, + &app_verify_arg); } if (server_auth) { printf("server authentication\n"); @@ -1506,7 +1726,9 @@ int main(int argc, char *argv[]) { int session_id_context = 0; if (!SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, - sizeof session_id_context)) { + sizeof session_id_context) || + !SSL_CTX_set_session_id_context(s_ctx2, (void *)&session_id_context, + sizeof session_id_context)) { ERR_print_errors(bio_err); goto end; } @@ -1528,9 +1750,11 @@ int main(int argc, char *argv[]) #ifndef OPENSSL_NO_PSK SSL_CTX_set_psk_client_callback(c_ctx, psk_client_callback); SSL_CTX_set_psk_server_callback(s_ctx, psk_server_callback); + SSL_CTX_set_psk_server_callback(s_ctx2, psk_server_callback); if (debug) BIO_printf(bio_err, "setting PSK identity hint to s_ctx\n"); - if (!SSL_CTX_use_psk_identity_hint(s_ctx, "ctx server identity_hint")) { + if (!SSL_CTX_use_psk_identity_hint(s_ctx, "ctx server identity_hint") || + !SSL_CTX_use_psk_identity_hint(s_ctx2, "ctx server identity_hint")) { BIO_printf(bio_err, "error setting PSK identity hint to s_ctx\n"); ERR_print_errors(bio_err); goto end; @@ -1553,172 +1777,599 @@ int main(int argc, char *argv[]) if (srp_server_arg.expected_user != NULL) { SSL_CTX_set_verify(s_ctx, SSL_VERIFY_NONE, verify_callback); + SSL_CTX_set_verify(s_ctx2, SSL_VERIFY_NONE, verify_callback); SSL_CTX_set_srp_cb_arg(s_ctx, &srp_server_arg); + SSL_CTX_set_srp_cb_arg(s_ctx2, &srp_server_arg); SSL_CTX_set_srp_username_callback(s_ctx, ssl_srp_server_param_cb); + SSL_CTX_set_srp_username_callback(s_ctx2, ssl_srp_server_param_cb); + } +#endif + +#ifndef OPENSSL_NO_NEXTPROTONEG + if (npn_client) { + SSL_CTX_set_next_proto_select_cb(c_ctx, cb_client_npn, NULL); + } + if (npn_server) { + if (npn_server_reject) { + BIO_printf(bio_err, + "Can't have both -npn_server and -npn_server_reject\n"); + goto end; + } + SSL_CTX_set_next_protos_advertised_cb(s_ctx, cb_server_npn, NULL); + SSL_CTX_set_next_protos_advertised_cb(s_ctx2, cb_server_npn, NULL); + } + if (npn_server_reject) { + SSL_CTX_set_next_protos_advertised_cb(s_ctx, cb_server_rejects_npn, + NULL); + SSL_CTX_set_next_protos_advertised_cb(s_ctx2, cb_server_rejects_npn, + NULL); } #endif -#ifndef OPENSSL_NO_NEXTPROTONEG - if (npn_client) { - SSL_CTX_set_next_proto_select_cb(c_ctx, cb_client_npn, NULL); - } - if (npn_server) { - if (npn_server_reject) { - BIO_printf(bio_err, - "Can't have both -npn_server and -npn_server_reject\n"); - goto end; + if (serverinfo_sct) { + if (!SSL_CTX_add_client_custom_ext(c_ctx, + TLSEXT_TYPE_signed_certificate_timestamp, + NULL, NULL, NULL, + serverinfo_cli_parse_cb, NULL)) { + BIO_printf(bio_err, "Error adding SCT extension\n"); + goto end; + } + } + if (serverinfo_tack) { + if (!SSL_CTX_add_client_custom_ext(c_ctx, TACK_EXT_TYPE, + NULL, NULL, NULL, + serverinfo_cli_parse_cb, NULL)) { + BIO_printf(bio_err, "Error adding TACK extension\n"); + goto end; + } + } + if (serverinfo_file) + if (!SSL_CTX_use_serverinfo_file(s_ctx, serverinfo_file) || + !SSL_CTX_use_serverinfo_file(s_ctx2, serverinfo_file)) { + BIO_printf(bio_err, "missing serverinfo file\n"); + goto end; + } + + if (custom_ext) { + if (!SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_0, + custom_ext_0_cli_add_cb, + NULL, NULL, + custom_ext_0_cli_parse_cb, NULL) + || !SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_1, + custom_ext_1_cli_add_cb, + NULL, NULL, + custom_ext_1_cli_parse_cb, NULL) + || !SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_2, + custom_ext_2_cli_add_cb, + NULL, NULL, + custom_ext_2_cli_parse_cb, NULL) + || !SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_3, + custom_ext_3_cli_add_cb, + NULL, NULL, + custom_ext_3_cli_parse_cb, NULL) + || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_0, + custom_ext_0_srv_add_cb, + NULL, NULL, + custom_ext_0_srv_parse_cb, NULL) + || !SSL_CTX_add_server_custom_ext(s_ctx2, CUSTOM_EXT_TYPE_0, + custom_ext_0_srv_add_cb, + NULL, NULL, + custom_ext_0_srv_parse_cb, NULL) + || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_1, + custom_ext_1_srv_add_cb, + NULL, NULL, + custom_ext_1_srv_parse_cb, NULL) + || !SSL_CTX_add_server_custom_ext(s_ctx2, CUSTOM_EXT_TYPE_1, + custom_ext_1_srv_add_cb, + NULL, NULL, + custom_ext_1_srv_parse_cb, NULL) + || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_2, + custom_ext_2_srv_add_cb, + NULL, NULL, + custom_ext_2_srv_parse_cb, NULL) + || !SSL_CTX_add_server_custom_ext(s_ctx2, CUSTOM_EXT_TYPE_2, + custom_ext_2_srv_add_cb, + NULL, NULL, + custom_ext_2_srv_parse_cb, NULL) + || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_3, + custom_ext_3_srv_add_cb, + NULL, NULL, + custom_ext_3_srv_parse_cb, NULL) + || !SSL_CTX_add_server_custom_ext(s_ctx2, CUSTOM_EXT_TYPE_3, + custom_ext_3_srv_add_cb, + NULL, NULL, + custom_ext_3_srv_parse_cb, NULL)) { + BIO_printf(bio_err, "Error setting custom extensions\n"); + goto end; + } + } + + if (alpn_server) + SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, alpn_server); + if (alpn_server2) + SSL_CTX_set_alpn_select_cb(s_ctx2, cb_server_alpn, alpn_server2); + + if (alpn_client) { + size_t alpn_len; + unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client); + + if (alpn == NULL) { + BIO_printf(bio_err, "Error parsing -alpn_client argument\n"); + goto end; + } + /* Returns 0 on success!! */ + if (SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len)) { + BIO_printf(bio_err, "Error setting ALPN\n"); + OPENSSL_free(alpn); + goto end; + } + OPENSSL_free(alpn); + } + + if (server_sess_in != NULL) { + server_sess = read_session(server_sess_in); + if (server_sess == NULL) + goto end; + } + if (client_sess_in != NULL) { + client_sess = read_session(client_sess_in); + if (client_sess == NULL) + goto end; + } + + if (server_sess_out != NULL || server_sess_in != NULL) { + char *keys; + long size; + + /* Use a fixed key so that we can decrypt the ticket. */ + size = SSL_CTX_set_tlsext_ticket_keys(s_ctx, NULL, 0); + keys = OPENSSL_zalloc(size); + SSL_CTX_set_tlsext_ticket_keys(s_ctx, keys, size); + OPENSSL_free(keys); + } + + if (sn_server1 != NULL || sn_server2 != NULL) + SSL_CTX_set_tlsext_servername_callback(s_ctx, servername_cb); + + c_ssl = SSL_new(c_ctx); + s_ssl = SSL_new(s_ctx); + + if (sn_client) + SSL_set_tlsext_host_name(c_ssl, sn_client); + + if (!set_protocol_version(server_min_proto, s_ssl, SSL_CTRL_SET_MIN_PROTO_VERSION)) + goto end; + if (!set_protocol_version(server_max_proto, s_ssl, SSL_CTRL_SET_MAX_PROTO_VERSION)) + goto end; + if (!set_protocol_version(client_min_proto, c_ssl, SSL_CTRL_SET_MIN_PROTO_VERSION)) + goto end; + if (!set_protocol_version(client_max_proto, c_ssl, SSL_CTRL_SET_MAX_PROTO_VERSION)) + goto end; + + if (server_sess) { + if (SSL_CTX_add_session(s_ctx, server_sess) == 0) { + BIO_printf(bio_err, "Can't add server session\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + BIO_printf(bio_stdout, "Doing handshakes=%d bytes=%ld\n", number, bytes); + for (i = 0; i < number; i++) { + if (!reuse) { + if (!SSL_set_session(c_ssl, NULL)) { + BIO_printf(bio_err, "Failed to set session\n"); + goto end; + } + } + if (client_sess_in != NULL) { + if (SSL_set_session(c_ssl, client_sess) == 0) { + BIO_printf(bio_err, "Can't set client session\n"); + ERR_print_errors(bio_err); + goto end; + } + } + switch (bio_type) { + case BIO_MEM: + ret = doit(s_ssl, c_ssl, bytes); + break; + case BIO_PAIR: + ret = doit_biopair(s_ssl, c_ssl, bytes, &s_time, &c_time); + break; +#ifndef OPENSSL_NO_SOCK + case BIO_IPV4: + ret = doit_localhost(s_ssl, c_ssl, BIO_FAMILY_IPV4, + bytes, &s_time, &c_time); + break; + case BIO_IPV6: + ret = doit_localhost(s_ssl, c_ssl, BIO_FAMILY_IPV6, + bytes, &s_time, &c_time); + break; +#else + case BIO_IPV4: + case BIO_IPV6: + ret = 1; + goto err; +#endif + } + if (ret) break; + } + + if (should_negotiate && ret == 0 && + strcmp(should_negotiate, "fail-server") != 0 && + strcmp(should_negotiate, "fail-client") != 0) { + int version = protocol_from_string(should_negotiate); + if (version < 0) { + BIO_printf(bio_err, "Error parsing: %s\n", should_negotiate); + ret = 1; + goto err; + } + if (SSL_version(c_ssl) != version) { + BIO_printf(bio_err, "Unxpected version negotiated. " + "Expected: %s, got %s\n", should_negotiate, SSL_get_version(c_ssl)); + ret = 1; + goto err; + } + } + + if (should_reuse != -1) { + if (SSL_session_reused(s_ssl) != should_reuse || + SSL_session_reused(c_ssl) != should_reuse) { + BIO_printf(bio_err, "Unexpected session reuse state. " + "Expected: %d, server: %d, client: %d\n", should_reuse, + SSL_session_reused(s_ssl), SSL_session_reused(c_ssl)); + ret = 1; + goto err; + } + } + + if (server_sess_out != NULL) { + if (write_session(server_sess_out, SSL_get_session(s_ssl)) == 0) { + ret = 1; + goto err; + } + } + if (client_sess_out != NULL) { + if (write_session(client_sess_out, SSL_get_session(c_ssl)) == 0) { + ret = 1; + goto err; + } + } + + if (!verbose) { + print_details(c_ssl, ""); + } + if (print_time) { +#ifdef CLOCKS_PER_SEC + /* + * "To determine the time in seconds, the value returned by the clock + * function should be divided by the value of the macro + * CLOCKS_PER_SEC." -- ISO/IEC 9899 + */ + BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n" + "Approximate total client time: %6.2f s\n", + (double)s_time / CLOCKS_PER_SEC, + (double)c_time / CLOCKS_PER_SEC); +#else + BIO_printf(bio_stdout, + "Approximate total server time: %6.2f units\n" + "Approximate total client time: %6.2f units\n", + (double)s_time, (double)c_time); +#endif + } + + err: + SSL_free(s_ssl); + SSL_free(c_ssl); + + end: + SSL_CTX_free(s_ctx); + SSL_CTX_free(s_ctx2); + SSL_CTX_free(c_ctx); + SSL_CONF_CTX_free(s_cctx); + SSL_CONF_CTX_free(s_cctx2); + SSL_CONF_CTX_free(c_cctx); + sk_OPENSSL_STRING_free(conf_args); + + BIO_free(bio_stdout); + + SSL_SESSION_free(server_sess); + SSL_SESSION_free(client_sess); + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + if (CRYPTO_mem_leaks(bio_err) <= 0) + ret = 1; +#endif + BIO_free(bio_err); + EXIT(ret); +} + +#ifndef OPENSSL_NO_SOCK +int doit_localhost(SSL *s_ssl, SSL *c_ssl, int family, long count, + clock_t *s_time, clock_t *c_time) +{ + long cw_num = count, cr_num = count, sw_num = count, sr_num = count; + BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL; + BIO *acpt = NULL, *server = NULL, *client = NULL; + char addr_str[40]; + int ret = 1; + int err_in_client = 0; + int err_in_server = 0; + + acpt = BIO_new_accept("0"); + if (acpt == NULL) + goto err; + BIO_set_accept_ip_family(acpt, family); + BIO_set_bind_mode(acpt, BIO_SOCK_NONBLOCK | BIO_SOCK_REUSEADDR); + if (BIO_do_accept(acpt) <= 0) + goto err; + + BIO_snprintf(addr_str, sizeof(addr_str), ":%s", BIO_get_accept_port(acpt)); + + client = BIO_new_connect(addr_str); + BIO_set_conn_ip_family(client, family); + if (!client) + goto err; + + if (BIO_set_nbio(client, 1) <= 0) + goto err; + if (BIO_set_nbio(acpt, 1) <= 0) + goto err; + + { + int st_connect = 0, st_accept = 0; + + while(!st_connect || !st_accept) { + if (!st_connect) { + if (BIO_do_connect(client) <= 0) { + if (!BIO_should_retry(client)) + goto err; + } else { + st_connect = 1; + } + } + if (!st_accept) { + if (BIO_do_accept(acpt) <= 0) { + if (!BIO_should_retry(acpt)) + goto err; + } else { + st_accept = 1; + } + } + } + } + /* We're not interested in accepting further connects */ + server = BIO_pop(acpt); + BIO_free_all(acpt); + acpt = NULL; + + s_ssl_bio = BIO_new(BIO_f_ssl()); + if (!s_ssl_bio) + goto err; + + c_ssl_bio = BIO_new(BIO_f_ssl()); + if (!c_ssl_bio) + goto err; + + SSL_set_connect_state(c_ssl); + SSL_set_bio(c_ssl, client, client); + (void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE); + + SSL_set_accept_state(s_ssl); + SSL_set_bio(s_ssl, server, server); + (void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE); + + do { + /*- + * c_ssl_bio: SSL filter BIO + * + * client: I/O for SSL library + * + * + * server: I/O for SSL library + * + * s_ssl_bio: SSL filter BIO + */ + + /* + * We have non-blocking behaviour throughout this test program, but + * can be sure that there is *some* progress in each iteration; so we + * don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE -- + * we just try everything in each iteration + */ + + { + /* CLIENT */ + + char cbuf[1024 * 8]; + int i, r; + clock_t c_clock = clock(); + + memset(cbuf, 0, sizeof(cbuf)); + + if (debug) + if (SSL_in_init(c_ssl)) + printf("client waiting in SSL_connect - %s\n", + SSL_state_string_long(c_ssl)); + + if (cw_num > 0) { + /* Write to server. */ + + if (cw_num > (long)sizeof cbuf) + i = sizeof cbuf; + else + i = (int)cw_num; + r = BIO_write(c_ssl_bio, cbuf, i); + if (r < 0) { + if (!BIO_should_retry(c_ssl_bio)) { + fprintf(stderr, "ERROR in CLIENT\n"); + err_in_client = 1; + goto err; + } + /* + * BIO_should_retry(...) can just be ignored here. The + * library expects us to call BIO_write with the same + * arguments again, and that's what we will do in the + * next iteration. + */ + } else if (r == 0) { + fprintf(stderr, "SSL CLIENT STARTUP FAILED\n"); + goto err; + } else { + if (debug) + printf("client wrote %d\n", r); + cw_num -= r; + } + } + + if (cr_num > 0) { + /* Read from server. */ + + r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf)); + if (r < 0) { + if (!BIO_should_retry(c_ssl_bio)) { + fprintf(stderr, "ERROR in CLIENT\n"); + err_in_client = 1; + goto err; + } + /* + * Again, "BIO_should_retry" can be ignored. + */ + } else if (r == 0) { + fprintf(stderr, "SSL CLIENT STARTUP FAILED\n"); + goto err; + } else { + if (debug) + printf("client read %d\n", r); + cr_num -= r; + } + } + + /* + * c_time and s_time increments will typically be very small + * (depending on machine speed and clock tick intervals), but + * sampling over a large number of connections should result in + * fairly accurate figures. We cannot guarantee a lot, however + * -- if each connection lasts for exactly one clock tick, it + * will be counted only for the client or only for the server or + * even not at all. + */ + *c_time += (clock() - c_clock); } - SSL_CTX_set_next_protos_advertised_cb(s_ctx, cb_server_npn, NULL); - } - if (npn_server_reject) { - SSL_CTX_set_next_protos_advertised_cb(s_ctx, cb_server_rejects_npn, - NULL); - } -#endif - if (serverinfo_sct) { - if (!SSL_CTX_add_client_custom_ext(c_ctx, SCT_EXT_TYPE, - NULL, NULL, NULL, - serverinfo_cli_parse_cb, NULL)) { - BIO_printf(bio_err, "Error adding SCT extension\n"); - goto end; - } - } - if (serverinfo_tack) { - if (!SSL_CTX_add_client_custom_ext(c_ctx, TACK_EXT_TYPE, - NULL, NULL, NULL, - serverinfo_cli_parse_cb, NULL)) { - BIO_printf(bio_err, "Error adding TACK extension\n"); - goto end; - } - } - if (serverinfo_file) - if (!SSL_CTX_use_serverinfo_file(s_ctx, serverinfo_file)) { - BIO_printf(bio_err, "missing serverinfo file\n"); - goto end; - } + { + /* SERVER */ - if (custom_ext) { - if (!SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_0, - custom_ext_0_cli_add_cb, - NULL, NULL, - custom_ext_0_cli_parse_cb, NULL) - || !SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_1, - custom_ext_1_cli_add_cb, - NULL, NULL, - custom_ext_1_cli_parse_cb, NULL) - || !SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_2, - custom_ext_2_cli_add_cb, - NULL, NULL, - custom_ext_2_cli_parse_cb, NULL) - || !SSL_CTX_add_client_custom_ext(c_ctx, CUSTOM_EXT_TYPE_3, - custom_ext_3_cli_add_cb, - NULL, NULL, - custom_ext_3_cli_parse_cb, NULL) - || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_0, - custom_ext_0_srv_add_cb, - NULL, NULL, - custom_ext_0_srv_parse_cb, NULL) - || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_1, - custom_ext_1_srv_add_cb, - NULL, NULL, - custom_ext_1_srv_parse_cb, NULL) - || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_2, - custom_ext_2_srv_add_cb, - NULL, NULL, - custom_ext_2_srv_parse_cb, NULL) - || !SSL_CTX_add_server_custom_ext(s_ctx, CUSTOM_EXT_TYPE_3, - custom_ext_3_srv_add_cb, - NULL, NULL, - custom_ext_3_srv_parse_cb, NULL)) { - BIO_printf(bio_err, "Error setting custom extensions\n"); - goto end; - } - } + char sbuf[1024 * 8]; + int i, r; + clock_t s_clock = clock(); - if (alpn_server) - SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, NULL); + memset(sbuf, 0, sizeof(sbuf)); - if (alpn_client) { - unsigned short alpn_len; - unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client); + if (debug) + if (SSL_in_init(s_ssl)) + printf("server waiting in SSL_accept - %s\n", + SSL_state_string_long(s_ssl)); - if (alpn == NULL) { - BIO_printf(bio_err, "Error parsing -alpn_client argument\n"); - goto end; - } - /* Returns 0 on success!! */ - if (SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len)) { - BIO_printf(bio_err, "Error setting ALPN\n"); - OPENSSL_free(alpn); - goto end; - } - OPENSSL_free(alpn); - } + if (sw_num > 0) { + /* Write to client. */ - c_ssl = SSL_new(c_ctx); - s_ssl = SSL_new(s_ctx); + if (sw_num > (long)sizeof sbuf) + i = sizeof sbuf; + else + i = (int)sw_num; + r = BIO_write(s_ssl_bio, sbuf, i); + if (r < 0) { + if (!BIO_should_retry(s_ssl_bio)) { + fprintf(stderr, "ERROR in SERVER\n"); + err_in_server = 1; + goto err; + } + /* Ignore "BIO_should_retry". */ + } else if (r == 0) { + fprintf(stderr, "SSL SERVER STARTUP FAILED\n"); + goto err; + } else { + if (debug) + printf("server wrote %d\n", r); + sw_num -= r; + } + } - BIO_printf(bio_stdout, "Doing handshakes=%d bytes=%ld\n", number, bytes); - for (i = 0; i < number; i++) { - if (!reuse) { - if (!SSL_set_session(c_ssl, NULL)) { - BIO_printf(bio_err, "Failed to set session\n"); - goto end; + if (sr_num > 0) { + /* Read from client. */ + + r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf)); + if (r < 0) { + if (!BIO_should_retry(s_ssl_bio)) { + fprintf(stderr, "ERROR in SERVER\n"); + err_in_server = 1; + goto err; + } + /* blah, blah */ + } else if (r == 0) { + fprintf(stderr, "SSL SERVER STARTUP FAILED\n"); + goto err; + } else { + if (debug) + printf("server read %d\n", r); + sr_num -= r; + } } + + *s_time += (clock() - s_clock); } - if (bio_pair) - ret = doit_biopair(s_ssl, c_ssl, bytes, &s_time, &c_time); - else - ret = doit(s_ssl, c_ssl, bytes); - if (ret) break; } + while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0); - if (!verbose) { - print_details(c_ssl, ""); + if (verbose) + print_details(c_ssl, "DONE via TCP connect: "); +# ifndef OPENSSL_NO_NEXTPROTONEG + if (verify_npn(c_ssl, s_ssl) < 0) { + ret = 1; + goto end; } - if (print_time) { -#ifdef CLOCKS_PER_SEC - /* - * "To determine the time in seconds, the value returned by the clock - * function should be divided by the value of the macro - * CLOCKS_PER_SEC." -- ISO/IEC 9899 - */ - BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n" - "Approximate total client time: %6.2f s\n", - (double)s_time / CLOCKS_PER_SEC, - (double)c_time / CLOCKS_PER_SEC); -#else - BIO_printf(bio_stdout, - "Approximate total server time: %6.2f units\n" - "Approximate total client time: %6.2f units\n", - (double)s_time, (double)c_time); -#endif +# endif + if (verify_serverinfo() < 0) { + fprintf(stderr, "Server info verify error\n"); + ret = 1; + goto err; + } + if (verify_alpn(c_ssl, s_ssl) < 0) { + ret = 1; + goto err; + } + if (verify_servername(c_ssl, s_ssl) < 0) { + ret = 1; + goto err; } - SSL_free(s_ssl); - SSL_free(c_ssl); + if (custom_ext_error) { + fprintf(stderr, "Custom extension error\n"); + ret = 1; + goto err; + } end: - SSL_CTX_free(s_ctx); - SSL_CTX_free(c_ctx); - SSL_CONF_CTX_free(s_cctx); - SSL_CONF_CTX_free(c_cctx); - sk_OPENSSL_STRING_free(conf_args); + ret = 0; - BIO_free(bio_stdout); + err: + ERR_print_errors(bio_err); -#ifndef OPENSSL_NO_ENGINE - ENGINE_cleanup(); -#endif - CRYPTO_cleanup_all_ex_data(); - ERR_free_strings(); - ERR_remove_thread_state(NULL); - EVP_cleanup(); - CRYPTO_mem_leaks(bio_err); - BIO_free(bio_err); - EXIT(ret); + BIO_free_all(acpt); + BIO_free(server); + BIO_free(client); + BIO_free(s_ssl_bio); + BIO_free(c_ssl_bio); + + if (should_negotiate != NULL && strcmp(should_negotiate, "fail-client") == 0) + ret = (err_in_client != 0) ? 0 : 1; + else if (should_negotiate != NULL && strcmp(should_negotiate, "fail-server") == 0) + ret = (err_in_server != 0) ? 0 : 1; + + return ret; } +#endif int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, clock_t *s_time, clock_t *c_time) @@ -1727,6 +2378,8 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL; BIO *server = NULL, *server_io = NULL, *client = NULL, *client_io = NULL; int ret = 1; + int err_in_client = 0; + int err_in_server = 0; size_t bufsiz = 256; /* small buffer for testing */ @@ -1819,6 +2472,7 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, if (r < 0) { if (!BIO_should_retry(c_ssl_bio)) { fprintf(stderr, "ERROR in CLIENT\n"); + err_in_client = 1; goto err; } /* @@ -1844,6 +2498,7 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, if (r < 0) { if (!BIO_should_retry(c_ssl_bio)) { fprintf(stderr, "ERROR in CLIENT\n"); + err_in_client = 1; goto err; } /* @@ -1896,6 +2551,7 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, if (r < 0) { if (!BIO_should_retry(s_ssl_bio)) { fprintf(stderr, "ERROR in SERVER\n"); + err_in_server = 1; goto err; } /* Ignore "BIO_should_retry". */ @@ -1916,6 +2572,7 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, if (r < 0) { if (!BIO_should_retry(s_ssl_bio)) { fprintf(stderr, "ERROR in SERVER\n"); + err_in_server = 1; goto err; } /* blah, blah */ @@ -2063,6 +2720,10 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, ret = 1; goto err; } + if (verify_servername(c_ssl, s_ssl) < 0) { + ret = 1; + goto err; + } if (custom_ext_error) { fprintf(stderr, "Custom extension error\n"); @@ -2083,6 +2744,11 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, BIO_free(s_ssl_bio); BIO_free(c_ssl_bio); + if (should_negotiate != NULL && strcmp(should_negotiate, "fail-client") == 0) + ret = (err_in_client != 0) ? 0 : 1; + else if (should_negotiate != NULL && strcmp(should_negotiate, "fail-server") == 0) + ret = (err_in_server != 0) ? 0 : 1; + return ret; } @@ -2108,6 +2774,8 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) int c_write, s_write; int do_server = 0, do_client = 0; int max_frag = 5 * 1024; + int err_in_client = 0; + int err_in_server = 0; bufsiz = count > 40 * 1024 ? 40 * 1024 : count; @@ -2200,6 +2868,7 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) c_w = 1; } else { fprintf(stderr, "ERROR in CLIENT\n"); + err_in_client = 1; ERR_print_errors(bio_err); goto err; } @@ -2228,6 +2897,7 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) c_w = 1; } else { fprintf(stderr, "ERROR in CLIENT\n"); + err_in_client = 1; ERR_print_errors(bio_err); goto err; } @@ -2264,6 +2934,7 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) s_w = 1; } else { fprintf(stderr, "ERROR in SERVER\n"); + err_in_server = 1; ERR_print_errors(bio_err); goto err; } @@ -2299,6 +2970,7 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) s_w = 1; } else { fprintf(stderr, "ERROR in SERVER\n"); + err_in_server = 1; ERR_print_errors(bio_err); goto err; } @@ -2369,22 +3041,29 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) OPENSSL_free(cbuf); OPENSSL_free(sbuf); + if (should_negotiate != NULL && strcmp(should_negotiate, "fail-client") == 0) + ret = (err_in_client != 0) ? 0 : 1; + else if (should_negotiate != NULL && strcmp(should_negotiate, "fail-server") == 0) + ret = (err_in_server != 0) ? 0 : 1; + return (ret); } +static CRYPTO_ONCE proxy_auth_ex_data_once = CRYPTO_ONCE_STATIC_INIT; +static volatile int proxy_auth_ex_data_idx = -1; + +static void do_get_proxy_auth_ex_data_idx(void) +{ + proxy_auth_ex_data_idx = X509_STORE_CTX_get_ex_new_index(0, + "SSLtest for verify callback", + NULL, NULL, NULL); +} + static int get_proxy_auth_ex_data_idx(void) { - static volatile int idx = -1; - if (idx < 0) { - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - if (idx < 0) { - idx = X509_STORE_CTX_get_ex_new_index(0, - "SSLtest for verify callback", - NULL, NULL, NULL); - } - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); - } - return idx; + CRYPTO_THREAD_run_once(&proxy_auth_ex_data_once, + do_get_proxy_auth_ex_data_idx); + return proxy_auth_ex_data_idx; } static int verify_callback(int ok, X509_STORE_CTX *ctx) @@ -3033,12 +3712,19 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity, static int do_test_cipherlist(void) { +#ifndef OPENSSL_NO_TLS int i = 0; const SSL_METHOD *meth; const SSL_CIPHER *ci, *tci = NULL; -#ifndef OPENSSL_NO_SSL3 - meth = SSLv3_method(); + /* + * This is required because ssltest "cheats" and uses internal headers to + * call functions, thus avoiding auto-init + */ + OPENSSL_init_crypto(0, NULL); + OPENSSL_init_ssl(0, NULL); + + meth = TLS_method(); tci = NULL; while ((ci = meth->get_cipher(i++)) != NULL) { if (tci != NULL) @@ -3050,17 +3736,6 @@ static int do_test_cipherlist(void) tci = ci; } #endif - meth = TLSv1_method(); - tci = NULL; - while ((ci = meth->get_cipher(i++)) != NULL) { - if (tci != NULL) - if (ci->id >= tci->id) { - fprintf(stderr, "testing TLSv1 cipher list order: "); - fprintf(stderr, "failed %x vs. %x\n", ci->id, tci->id); - return 0; - } - tci = ci; - } return 1; }