X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssltest.c;h=bebe7261921ea9adfa3451d684031ea33862a5a9;hp=ff686913d72022af6f45a53315324d33caa3d74f;hb=6f7af1524ea4a0eb9bcd0596075cef4bcaf887b1;hpb=31b8d8684441e6cd5138832bb1b2ddb10acd6ba6 diff --git a/ssl/ssltest.c b/ssl/ssltest.c index ff686913d7..bebe726192 100644 --- a/ssl/ssltest.c +++ b/ssl/ssltest.c @@ -56,55 +56,60 @@ * [including the GNU Public Licence.] */ +#include +#include +#include #include #include #include -#include -#include "e_os.h" -#include "bio.h" -#include "crypto.h" -#include "x509.h" -#include "ssl.h" -#include "err.h" + +#include "openssl/e_os.h" + +#include +#include +#include +#include +#include #ifdef WINDOWS #include "../crypto/bio/bss_file.c" #endif -#define TEST_SERVER_CERT "../apps/server.pem" -#define TEST_CLIENT_CERT "../apps/client.pem" - -#ifndef NOPROTO -int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx); -static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int export); -#ifndef NO_DSA -static DH *get_dh512(void); +#if defined(NO_RSA) && !defined(NO_SSL2) +#define NO_SSL2 #endif + +#ifdef VMS +# define TEST_SERVER_CERT "SYS$DISK:[-.APPS]SERVER.PEM" +# define TEST_CLIENT_CERT "SYS$DISK:[-.APPS]CLIENT.PEM" #else -int MS_CALLBACK verify_callback(); -static RSA MS_CALLBACK *tmp_rsa_cb(); -#ifndef NO_DSA -static DH *get_dh512(); -#endif +# define TEST_SERVER_CERT "../apps/server.pem" +# define TEST_CLIENT_CERT "../apps/client.pem" #endif -BIO *bio_err=NULL; -BIO *bio_stdout=NULL; +static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx); +#ifndef NO_RSA +static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export,int keylength); +#endif +#ifndef NO_DH +static DH *get_dh512(void); +#endif +static BIO *bio_err=NULL; +static BIO *bio_stdout=NULL; static char *cipher=NULL; int verbose=0; int debug=0; +#if 0 +/* Not used yet. */ #ifdef FIONBIO static int s_nbio=0; #endif +#endif -#ifndef NOPROTO +int doit_biopair(SSL *s_ssl,SSL *c_ssl,long bytes); int doit(SSL *s_ssl,SSL *c_ssl,long bytes); -#else -int doit(); -#endif - -static void sv_usage() +static void sv_usage(void) { fprintf(stderr,"usage: ssltest [args ...]\n"); fprintf(stderr,"\n"); @@ -115,6 +120,12 @@ static void sv_usage() fprintf(stderr," -reuse - use session-id reuse\n"); fprintf(stderr," -num - number of connections to perform\n"); fprintf(stderr," -bytes - number of bytes to swap between client/server\n"); +#if !defined NO_DH && !defined NO_DSA + fprintf(stderr," -dhe1024 - generate 1024 bit key for DHE\n"); +#endif +#if !defined NO_DH + fprintf(stderr," -no_dhe - disable DHE\n"); +#endif #ifndef NO_SSL2 fprintf(stderr," -ssl2 - use SSLv2\n"); #endif @@ -130,14 +141,16 @@ static void sv_usage() fprintf(stderr," -s_cert arg - Just the server certificate file\n"); fprintf(stderr," -c_cert arg - Just the client certificate file\n"); fprintf(stderr," -cipher arg - The cipher list\n"); + fprintf(stderr," -bio_pair - Use BIO pairs\n"); + fprintf(stderr," -f - Test even cases that can't work\n"); } -int main(argc, argv) -int argc; -char *argv[]; +int main(int argc, char *argv[]) { char *CApath=NULL,*CAfile=NULL; int badop=0; + int bio_pair=0; + int force=0; int tls1=0,ssl2=0,ssl3=0,ret=1; int client_auth=0; int server_auth=0,i; @@ -150,6 +163,7 @@ char *argv[]; int number=1,reuse=0; long bytes=1L; SSL_CIPHER *ciph; + int dhe1024 = 0, no_dhe = 0; #ifndef NO_DH DH *dh; #endif @@ -174,6 +188,10 @@ char *argv[]; debug=1; else if (strcmp(*argv,"-reuse") == 0) reuse=1; + else if (strcmp(*argv,"-dhe1024") == 0) + dhe1024=1; + else if (strcmp(*argv,"-no_dhe") == 0) + no_dhe=1; else if (strcmp(*argv,"-ssl2") == 0) ssl2=1; else if (strcmp(*argv,"-tls1") == 0) @@ -225,6 +243,14 @@ char *argv[]; if (--argc < 1) goto bad; CAfile= *(++argv); } + else if (strcmp(*argv,"-bio_pair") == 0) + { + bio_pair = 1; + } + else if (strcmp(*argv,"-f") == 0) + { + force = 1; + } else { fprintf(stderr,"unknown option %s\n",*argv); @@ -241,9 +267,20 @@ bad: goto end; } + if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force) + { + fprintf(stderr, "This case cannot work. Use -f switch to perform " + "the test anyway\n" + "(and -d to see what happens, " + "and -bio_pair to really make it happen :-)\n" + "or add one of -ssl2, -ssl3, -tls1, -reuse to " + "avoid protocol mismatch.\n"); + exit(1); + } + /* if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */ - SSLeay_add_ssl_algorithms(); + SSL_library_init(); SSL_load_error_strings(); #if !defined(NO_SSL2) && !defined(NO_SSL3) @@ -280,9 +317,36 @@ bad: } #ifndef NO_DH - dh=get_dh512(); - SSL_CTX_set_tmp_dh(s_ctx,dh); - DH_free(dh); + if (!no_dhe) + { +# ifndef NO_DSA + if (dhe1024) + { + DSA *dsa; + unsigned char seed[20]; + + if (verbose) + { + fprintf(stdout, "Creating 1024 bit DHE parameters ..."); + fflush(stdout); + } + + memcpy(seed, "Random String no. 12", 20); + dsa = DSA_generate_parameters(1024, seed, 20, NULL, NULL, 0, NULL); + dh = DSA_dup_DH(dsa); + DSA_free(dsa); + /* important: SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks */ + SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE); + + if (verbose) + fprintf(stdout, " done\n"); + } + else +# endif + dh=get_dh512(); + SSL_CTX_set_tmp_dh(s_ctx,dh); + DH_free(dh); + } #endif #ifndef NO_RSA @@ -338,7 +402,10 @@ bad: for (i=0; i 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"); + 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"); + 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; + } + } + } + + { + /* SERVER */ + + MS_STATIC char sbuf[1024*8]; + int i, r; + + if (debug) + if (SSL_in_init(s_ssl)) + printf("server waiting in SSL_accept - %s\n", + SSL_state_string_long(s_ssl)); + + if (sw_num > 0) + { + /* Write to client. */ + + 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"); + 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; + } + } + + 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"); + 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; + } + } + } + + { + /* "I/O" BETWEEN CLIENT AND SERVER. */ + + size_t r1, r2; + BIO *io1 = server_io, *io2 = client_io; + /* we use the non-copying interface for io1 + * and the standard BIO_write/BIO_read interface for io2 + */ + + static int prev_progress = 1; + int progress = 0; + + /* io1 to io2 */ + do + { + size_t num; + int r; + + r1 = BIO_ctrl_pending(io1); + r2 = BIO_ctrl_get_write_guarantee(io2); + + num = r1; + if (r2 < num) + num = r2; + if (num) + { + char *dataptr; + + if (INT_MAX < num) /* yeah, right */ + num = INT_MAX; + + r = BIO_nread(io1, &dataptr, (int)num); + assert(r > 0); + assert(r <= (int)num); + /* possibly r < num (non-contiguous data) */ + num = r; + r = BIO_write(io2, dataptr, (int)num); + if (r != (int)num) /* can't happen */ + { + fprintf(stderr, "ERROR: BIO_write could not write " + "BIO_ctrl_get_write_guarantee() bytes"); + goto err; + } + progress = 1; + + if (debug) + printf((io1 == client_io) ? + "C->S relaying: %d bytes\n" : + "S->C relaying: %d bytes\n", + (int)num); + } + } + while (r1 && r2); + + /* io2 to io1 */ + { + size_t num; + int r; + + r1 = BIO_ctrl_pending(io2); + r2 = BIO_ctrl_get_read_request(io1); + /* here we could use ..._get_write_guarantee instead of + * ..._get_read_request, but by using the latter + * we test restartability of the SSL implementation + * more thoroughly */ + num = r1; + if (r2 < num) + num = r2; + if (num) + { + char *dataptr; + + if (INT_MAX < num) + num = INT_MAX; + + if (num > 1) + --num; /* for testing restartability even more thoroughly */ + + r = BIO_nwrite(io1, &dataptr, (int)num); + assert(r > 0); + assert(r <= (int)num); + num = r; + r = BIO_read(io2, dataptr, (int)num); + if (r != (int)num) /* can't happen */ + { + fprintf(stderr, "ERROR: BIO_read could not read " + "BIO_ctrl_pending() bytes"); + goto err; + } + progress = 1; + + if (debug) + printf((io2 == client_io) ? + "C->S relaying: %d bytes\n" : + "S->C relaying: %d bytes\n", + (int)num); + } + } /* no loop, BIO_ctrl_get_read_request now returns 0 anyway */ + + if (!progress && !prev_progress) + if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0) + { + fprintf(stderr, "ERROR: got stuck\n"); + if (strcmp("SSLv2", SSL_get_version(c_ssl)) == 0) + { + fprintf(stderr, "This can happen for SSL2 because " + "CLIENT-FINISHED and SERVER-VERIFY are written \n" + "concurrently ..."); + if (strncmp("2SCF", SSL_state_string(c_ssl), 4) == 0 + && strncmp("2SSV", SSL_state_string(s_ssl), 4) == 0) + { + fprintf(stderr, " ok.\n"); + goto end; + } + } + fprintf(stderr, " ERROR.\n"); + goto err; + } + prev_progress = progress; + } + } + while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0); + + ciph = SSL_get_current_cipher(c_ssl); + if (verbose) + fprintf(stdout,"DONE via BIO pair, protocol %s, cipher %s, %s\n", + SSL_get_version(c_ssl), + SSL_CIPHER_get_version(ciph), + SSL_CIPHER_get_name(ciph)); + end: + ret = 0; + + err: + ERR_print_errors(bio_err); + + if (server) + BIO_free(server); + if (server_io) + BIO_free(server_io); + if (client) + BIO_free(client); + if (client_io) + BIO_free(client_io); + if (s_ssl_bio) + BIO_free(s_ssl_bio); + if (c_ssl_bio) + BIO_free(c_ssl_bio); + + return ret; + } + + #define W_READ 1 #define W_WRITE 2 #define C_DONE 1 #define S_DONE 2 -int doit(s_ssl,c_ssl,count) -SSL *s_ssl,*c_ssl; -long count; +int doit(SSL *s_ssl, SSL *c_ssl, long count) { MS_STATIC char cbuf[1024*8],sbuf[1024*8]; long cw_num=count,cr_num=count; @@ -674,9 +1107,7 @@ err: return(ret); } -int MS_CALLBACK verify_callback(ok, ctx) -int ok; -X509_STORE_CTX *ctx; +static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) { char *s,buf[256]; @@ -717,7 +1148,7 @@ static unsigned char dh512_g[]={ 0x02, }; -static DH *get_dh512() +static DH *get_dh512(void) { DH *dh=NULL; @@ -730,23 +1161,19 @@ static DH *get_dh512() } #endif -static RSA MS_CALLBACK *tmp_rsa_cb(s,export) -SSL *s; -int export; +#ifndef NO_RSA +static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength) { static RSA *rsa_tmp=NULL; if (rsa_tmp == NULL) { - BIO_printf(bio_err,"Generating temp (512 bit) RSA key..."); - BIO_flush(bio_err); -#ifndef NO_RSA - rsa_tmp=RSA_generate_key(512,RSA_F4,NULL,NULL); -#endif + BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength); + (void)BIO_flush(bio_err); + rsa_tmp=RSA_generate_key(keylength,RSA_F4,NULL,NULL); BIO_printf(bio_err,"\n"); - BIO_flush(bio_err); + (void)BIO_flush(bio_err); } return(rsa_tmp); } - - +#endif