00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #define NO_SHUTDOWN
00060
00061
00062
00063
00064
00065
00066 #include <stdio.h>
00067 #include <stdlib.h>
00068 #include <string.h>
00069
00070 #define USE_SOCKETS
00071 #include "apps.h"
00072 #ifdef OPENSSL_NO_STDIO
00073 #define APPS_WIN16
00074 #endif
00075 #include <openssl/x509.h>
00076 #include <openssl/ssl.h>
00077 #include <openssl/pem.h>
00078 #include "s_apps.h"
00079 #include <openssl/err.h>
00080 #ifdef WIN32_STUFF
00081 #include "winmain.h"
00082 #include "wintext.h"
00083 #endif
00084 #if !defined(OPENSSL_SYS_MSDOS)
00085 #include OPENSSL_UNISTD
00086 #endif
00087
00088 #if !defined(OPENSSL_SYS_NETWARE) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VXWORKS) && (!defined(OPENSSL_SYS_VMS) || defined(__DECC))
00089 #define TIMES
00090 #endif
00091
00092 #ifndef _IRIX
00093 #include <time.h>
00094 #endif
00095 #ifdef TIMES
00096 #include <sys/types.h>
00097 #include <sys/times.h>
00098 #endif
00099
00100
00101
00102
00103
00104 #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__TMS)
00105 #undef TIMES
00106 #endif
00107
00108 #if !defined(TIMES) && !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_NETWARE)
00109 #include <sys/timeb.h>
00110 #endif
00111
00112 #if defined(sun) || defined(__ultrix)
00113 #define _POSIX_SOURCE
00114 #include <limits.h>
00115 #include <sys/param.h>
00116 #endif
00117
00118
00119
00120 #ifndef HZ
00121 # ifdef _SC_CLK_TCK
00122 # define HZ ((double)sysconf(_SC_CLK_TCK))
00123 # else
00124 # ifndef CLK_TCK
00125 # ifndef _BSD_CLK_TCK_
00126 # define HZ 100.0
00127 # else
00128 # define HZ ((double)_BSD_CLK_TCK_)
00129 # endif
00130 # else
00131 # define HZ ((double)CLK_TCK)
00132 # endif
00133 # endif
00134 #endif
00135
00136 #undef PROG
00137 #define PROG s_time_main
00138
00139 #undef ioctl
00140 #define ioctl ioctlsocket
00141
00142 #define SSL_CONNECT_NAME "localhost:4433"
00143
00144
00145
00146 #undef BUFSIZZ
00147 #define BUFSIZZ 1024*10
00148
00149 #define MYBUFSIZ 1024*8
00150
00151 #undef min
00152 #undef max
00153 #define min(a,b) (((a) < (b)) ? (a) : (b))
00154 #define max(a,b) (((a) > (b)) ? (a) : (b))
00155
00156 #undef SECONDS
00157 #define SECONDS 30
00158 extern int verify_depth;
00159 extern int verify_error;
00160
00161 static void s_time_usage(void);
00162 static int parseArgs( int argc, char **argv );
00163 static SSL *doConnection( SSL *scon );
00164 static void s_time_init(void);
00165
00166
00167
00168
00169
00170
00171 static char *host=SSL_CONNECT_NAME;
00172 static char *t_cert_file=NULL;
00173 static char *t_key_file=NULL;
00174 static char *CApath=NULL;
00175 static char *CAfile=NULL;
00176 static char *tm_cipher=NULL;
00177 static int tm_verify = SSL_VERIFY_NONE;
00178 static int maxTime = SECONDS;
00179 static SSL_CTX *tm_ctx=NULL;
00180 static SSL_METHOD *s_time_meth=NULL;
00181 static char *s_www_path=NULL;
00182 static long bytes_read=0;
00183 static int st_bugs=0;
00184 static int perform=0;
00185 #ifdef FIONBIO
00186 static int t_nbio=0;
00187 #endif
00188 #ifdef OPENSSL_SYS_WIN32
00189 static int exitNow = 0;
00190 #endif
00191
00192 static void s_time_init(void)
00193 {
00194 host=SSL_CONNECT_NAME;
00195 t_cert_file=NULL;
00196 t_key_file=NULL;
00197 CApath=NULL;
00198 CAfile=NULL;
00199 tm_cipher=NULL;
00200 tm_verify = SSL_VERIFY_NONE;
00201 maxTime = SECONDS;
00202 tm_ctx=NULL;
00203 s_time_meth=NULL;
00204 s_www_path=NULL;
00205 bytes_read=0;
00206 st_bugs=0;
00207 perform=0;
00208
00209 #ifdef FIONBIO
00210 t_nbio=0;
00211 #endif
00212 #ifdef OPENSSL_SYS_WIN32
00213 exitNow = 0;
00214 #endif
00215 }
00216
00217
00218
00219
00220 static void s_time_usage(void)
00221 {
00222 static char umsg[] = "\
00223 -time arg - max number of seconds to collect data, default %d\n\
00224 -verify arg - turn on peer certificate verification, arg == depth\n\
00225 -cert arg - certificate file to use, PEM format assumed\n\
00226 -key arg - RSA file to use, PEM format assumed, key is in cert file\n\
00227 file if not specified by this option\n\
00228 -CApath arg - PEM format directory of CA's\n\
00229 -CAfile arg - PEM format file of CA's\n\
00230 -cipher - preferred cipher to use, play with 'openssl ciphers'\n\n";
00231
00232 printf( "usage: s_time <args>\n\n" );
00233
00234 printf("-connect host:port - host:port to connect to (default is %s)\n",SSL_CONNECT_NAME);
00235 #ifdef FIONBIO
00236 printf("-nbio - Run with non-blocking IO\n");
00237 printf("-ssl2 - Just use SSLv2\n");
00238 printf("-ssl3 - Just use SSLv3\n");
00239 printf("-bugs - Turn on SSL bug compatibility\n");
00240 printf("-new - Just time new connections\n");
00241 printf("-reuse - Just time connection reuse\n");
00242 printf("-www page - Retrieve 'page' from the site\n");
00243 #endif
00244 printf( umsg,SECONDS );
00245 }
00246
00247
00248
00249
00250
00251
00252 static int parseArgs(int argc, char **argv)
00253 {
00254 int badop = 0;
00255
00256 verify_depth=0;
00257 verify_error=X509_V_OK;
00258
00259 argc--;
00260 argv++;
00261
00262 while (argc >= 1) {
00263 if (strcmp(*argv,"-connect") == 0)
00264 {
00265 if (--argc < 1) goto bad;
00266 host= *(++argv);
00267 }
00268 #if 0
00269 else if( strcmp(*argv,"-host") == 0)
00270 {
00271 if (--argc < 1) goto bad;
00272 host= *(++argv);
00273 }
00274 else if( strcmp(*argv,"-port") == 0)
00275 {
00276 if (--argc < 1) goto bad;
00277 port= *(++argv);
00278 }
00279 #endif
00280 else if (strcmp(*argv,"-reuse") == 0)
00281 perform=2;
00282 else if (strcmp(*argv,"-new") == 0)
00283 perform=1;
00284 else if( strcmp(*argv,"-verify") == 0) {
00285
00286 tm_verify=SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE;
00287 if (--argc < 1) goto bad;
00288 verify_depth=atoi(*(++argv));
00289 BIO_printf(bio_err,"verify depth is %d\n",verify_depth);
00290
00291 } else if( strcmp(*argv,"-cert") == 0) {
00292
00293 if (--argc < 1) goto bad;
00294 t_cert_file= *(++argv);
00295
00296 } else if( strcmp(*argv,"-key") == 0) {
00297
00298 if (--argc < 1) goto bad;
00299 t_key_file= *(++argv);
00300
00301 } else if( strcmp(*argv,"-CApath") == 0) {
00302
00303 if (--argc < 1) goto bad;
00304 CApath= *(++argv);
00305
00306 } else if( strcmp(*argv,"-CAfile") == 0) {
00307
00308 if (--argc < 1) goto bad;
00309 CAfile= *(++argv);
00310
00311 } else if( strcmp(*argv,"-cipher") == 0) {
00312
00313 if (--argc < 1) goto bad;
00314 tm_cipher= *(++argv);
00315 }
00316 #ifdef FIONBIO
00317 else if(strcmp(*argv,"-nbio") == 0) {
00318 t_nbio=1;
00319 }
00320 #endif
00321 else if(strcmp(*argv,"-www") == 0)
00322 {
00323 if (--argc < 1) goto bad;
00324 s_www_path= *(++argv);
00325 if(strlen(s_www_path) > MYBUFSIZ-100)
00326 {
00327 BIO_printf(bio_err,"-www option too long\n");
00328 badop=1;
00329 }
00330 }
00331 else if(strcmp(*argv,"-bugs") == 0)
00332 st_bugs=1;
00333 #ifndef OPENSSL_NO_SSL2
00334 else if(strcmp(*argv,"-ssl2") == 0)
00335 s_time_meth=SSLv2_client_method();
00336 #endif
00337 #ifndef OPENSSL_NO_SSL3
00338 else if(strcmp(*argv,"-ssl3") == 0)
00339 s_time_meth=SSLv3_client_method();
00340 #endif
00341 else if( strcmp(*argv,"-time") == 0) {
00342
00343 if (--argc < 1) goto bad;
00344 maxTime= atoi(*(++argv));
00345 }
00346 else {
00347 BIO_printf(bio_err,"unknown option %s\n",*argv);
00348 badop=1;
00349 break;
00350 }
00351
00352 argc--;
00353 argv++;
00354 }
00355
00356 if (perform == 0) perform=3;
00357
00358 if(badop) {
00359 bad:
00360 s_time_usage();
00361 return -1;
00362 }
00363
00364 return 0;
00365 }
00366
00367
00368
00369
00370 #define START 0
00371 #define STOP 1
00372
00373 static double tm_Time_F(int s)
00374 {
00375 static double ret;
00376 #ifdef TIMES
00377 static struct tms tstart,tend;
00378
00379 if(s == START) {
00380 times(&tstart);
00381 return(0);
00382 } else {
00383 times(&tend);
00384 ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ;
00385 return((ret == 0.0)?1e-6:ret);
00386 }
00387 #elif defined(OPENSSL_SYS_NETWARE)
00388 static clock_t tstart,tend;
00389
00390 if (s == START)
00391 {
00392 tstart=clock();
00393 return(0);
00394 }
00395 else
00396 {
00397 tend=clock();
00398 ret=(double)((double)(tend)-(double)(tstart));
00399 return((ret < 0.001)?0.001:ret);
00400 }
00401 #elif defined(OPENSSL_SYS_VXWORKS)
00402 {
00403 static unsigned long tick_start, tick_end;
00404
00405 if( s == START )
00406 {
00407 tick_start = tickGet();
00408 return 0;
00409 }
00410 else
00411 {
00412 tick_end = tickGet();
00413 ret = (double)(tick_end - tick_start) / (double)sysClkRateGet();
00414 return((ret == 0.0)?1e-6:ret);
00415 }
00416 }
00417 #else
00418 static struct timeb tstart,tend;
00419 long i;
00420
00421 if(s == START) {
00422 ftime(&tstart);
00423 return(0);
00424 } else {
00425 ftime(&tend);
00426 i=(long)tend.millitm-(long)tstart.millitm;
00427 ret=((double)(tend.time-tstart.time))+((double)i)/1000.0;
00428 return((ret == 0.0)?1e-6:ret);
00429 }
00430 #endif
00431 }
00432
00433
00434
00435
00436
00437 int MAIN(int, char **);
00438
00439 int MAIN(int argc, char **argv)
00440 {
00441 double totalTime = 0.0;
00442 int nConn = 0;
00443 SSL *scon=NULL;
00444 long finishtime=0;
00445 int ret=1,i;
00446 MS_STATIC char buf[1024*8];
00447 int ver;
00448
00449 apps_startup();
00450 s_time_init();
00451
00452 if (bio_err == NULL)
00453 bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
00454
00455 #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
00456 s_time_meth=SSLv23_client_method();
00457 #elif !defined(OPENSSL_NO_SSL3)
00458 s_time_meth=SSLv3_client_method();
00459 #elif !defined(OPENSSL_NO_SSL2)
00460 s_time_meth=SSLv2_client_method();
00461 #endif
00462
00463
00464 if( parseArgs( argc, argv ) < 0 )
00465 goto end;
00466
00467 OpenSSL_add_ssl_algorithms();
00468 if ((tm_ctx=SSL_CTX_new(s_time_meth)) == NULL) return(1);
00469
00470 SSL_CTX_set_quiet_shutdown(tm_ctx,1);
00471
00472 if (st_bugs) SSL_CTX_set_options(tm_ctx,SSL_OP_ALL);
00473 SSL_CTX_set_cipher_list(tm_ctx,tm_cipher);
00474 if(!set_cert_stuff(tm_ctx,t_cert_file,t_key_file))
00475 goto end;
00476
00477 SSL_load_error_strings();
00478
00479 if ((!SSL_CTX_load_verify_locations(tm_ctx,CAfile,CApath)) ||
00480 (!SSL_CTX_set_default_verify_paths(tm_ctx)))
00481 {
00482
00483 ERR_print_errors(bio_err);
00484
00485 }
00486
00487 if (tm_cipher == NULL)
00488 tm_cipher = getenv("SSL_CIPHER");
00489
00490 if (tm_cipher == NULL ) {
00491 fprintf( stderr, "No CIPHER specified\n" );
00492 }
00493
00494 if (!(perform & 1)) goto next;
00495 printf( "Collecting connection statistics for %d seconds\n", maxTime );
00496
00497
00498
00499 bytes_read=0;
00500 finishtime=(long)time(NULL)+maxTime;
00501 tm_Time_F(START);
00502 for (;;)
00503 {
00504 if (finishtime < (long)time(NULL)) break;
00505 #ifdef WIN32_STUFF
00506
00507 if( flushWinMsgs(0) == -1 )
00508 goto end;
00509
00510 if( waitingToDie || exitNow )
00511 goto end;
00512 #endif
00513
00514 if( (scon = doConnection( NULL )) == NULL )
00515 goto end;
00516
00517 if (s_www_path != NULL)
00518 {
00519 BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path);
00520 SSL_write(scon,buf,strlen(buf));
00521 while ((i=SSL_read(scon,buf,sizeof(buf))) > 0)
00522 bytes_read+=i;
00523 }
00524
00525 #ifdef NO_SHUTDOWN
00526 SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
00527 #else
00528 SSL_shutdown(scon);
00529 #endif
00530 SHUTDOWN2(SSL_get_fd(scon));
00531
00532 nConn += 1;
00533 if (SSL_session_reused(scon))
00534 ver='r';
00535 else
00536 {
00537 ver=SSL_version(scon);
00538 if (ver == TLS1_VERSION)
00539 ver='t';
00540 else if (ver == SSL3_VERSION)
00541 ver='3';
00542 else if (ver == SSL2_VERSION)
00543 ver='2';
00544 else
00545 ver='*';
00546 }
00547 fputc(ver,stdout);
00548 fflush(stdout);
00549
00550 SSL_free( scon );
00551 scon=NULL;
00552 }
00553 totalTime += tm_Time_F(STOP);
00554
00555 i=(int)((long)time(NULL)-finishtime+maxTime);
00556 printf( "\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn/totalTime),bytes_read);
00557 printf( "%d connections in %ld real seconds, %ld bytes read per connection\n",nConn,(long)time(NULL)-finishtime+maxTime,bytes_read/nConn);
00558
00559
00560
00561 next:
00562 if (!(perform & 2)) goto end;
00563 printf( "\n\nNow timing with session id reuse.\n" );
00564
00565
00566 if( (scon = doConnection( NULL )) == NULL )
00567 {
00568 fprintf( stderr, "Unable to get connection\n" );
00569 goto end;
00570 }
00571
00572 if (s_www_path != NULL)
00573 {
00574 BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path);
00575 SSL_write(scon,buf,strlen(buf));
00576 while (SSL_read(scon,buf,sizeof(buf)) > 0)
00577 ;
00578 }
00579 #ifdef NO_SHUTDOWN
00580 SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
00581 #else
00582 SSL_shutdown(scon);
00583 #endif
00584 SHUTDOWN2(SSL_get_fd(scon));
00585
00586 nConn = 0;
00587 totalTime = 0.0;
00588
00589 finishtime=(long)time(NULL)+maxTime;
00590
00591 printf( "starting\n" );
00592 bytes_read=0;
00593 tm_Time_F(START);
00594
00595 for (;;)
00596 {
00597 if (finishtime < (long)time(NULL)) break;
00598
00599 #ifdef WIN32_STUFF
00600 if( flushWinMsgs(0) == -1 )
00601 goto end;
00602
00603 if( waitingToDie || exitNow )
00604 goto end;
00605 #endif
00606
00607 if( (doConnection( scon )) == NULL )
00608 goto end;
00609
00610 if (s_www_path)
00611 {
00612 BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path);
00613 SSL_write(scon,buf,strlen(buf));
00614 while ((i=SSL_read(scon,buf,sizeof(buf))) > 0)
00615 bytes_read+=i;
00616 }
00617
00618 #ifdef NO_SHUTDOWN
00619 SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
00620 #else
00621 SSL_shutdown(scon);
00622 #endif
00623 SHUTDOWN2(SSL_get_fd(scon));
00624
00625 nConn += 1;
00626 if (SSL_session_reused(scon))
00627 ver='r';
00628 else
00629 {
00630 ver=SSL_version(scon);
00631 if (ver == TLS1_VERSION)
00632 ver='t';
00633 else if (ver == SSL3_VERSION)
00634 ver='3';
00635 else if (ver == SSL2_VERSION)
00636 ver='2';
00637 else
00638 ver='*';
00639 }
00640 fputc(ver,stdout);
00641 fflush(stdout);
00642 }
00643 totalTime += tm_Time_F(STOP);
00644
00645
00646 printf( "\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn/totalTime),bytes_read);
00647 printf( "%d connections in %ld real seconds, %ld bytes read per connection\n",nConn,(long)time(NULL)-finishtime+maxTime,bytes_read/nConn);
00648
00649 ret=0;
00650 end:
00651 if (scon != NULL) SSL_free(scon);
00652
00653 if (tm_ctx != NULL)
00654 {
00655 SSL_CTX_free(tm_ctx);
00656 tm_ctx=NULL;
00657 }
00658 apps_shutdown();
00659 OPENSSL_EXIT(ret);
00660 }
00661
00662
00663
00664
00665
00666
00667
00668
00669 static SSL *doConnection(SSL *scon)
00670 {
00671 BIO *conn;
00672 SSL *serverCon;
00673 int width, i;
00674 fd_set readfds;
00675
00676 if ((conn=BIO_new(BIO_s_connect())) == NULL)
00677 return(NULL);
00678
00679
00680 BIO_set_conn_hostname(conn,host);
00681
00682 if (scon == NULL)
00683 serverCon=SSL_new(tm_ctx);
00684 else
00685 {
00686 serverCon=scon;
00687 SSL_set_connect_state(serverCon);
00688 }
00689
00690 SSL_set_bio(serverCon,conn,conn);
00691
00692 #if 0
00693 if( scon != NULL )
00694 SSL_set_session(serverCon,SSL_get_session(scon));
00695 #endif
00696
00697
00698 for(;;) {
00699 i=SSL_connect(serverCon);
00700 if (BIO_sock_should_retry(i))
00701 {
00702 BIO_printf(bio_err,"DELAY\n");
00703
00704 i=SSL_get_fd(serverCon);
00705 width=i+1;
00706 FD_ZERO(&readfds);
00707 FD_SET(i,&readfds);
00708
00709
00710
00711
00712
00713
00714 select(width,(void *)&readfds,NULL,NULL,NULL);
00715 continue;
00716 }
00717 break;
00718 }
00719 if(i <= 0)
00720 {
00721 BIO_printf(bio_err,"ERROR\n");
00722 if (verify_error != X509_V_OK)
00723 BIO_printf(bio_err,"verify error:%s\n",
00724 X509_verify_cert_error_string(verify_error));
00725 else
00726 ERR_print_errors(bio_err);
00727 if (scon == NULL)
00728 SSL_free(serverCon);
00729 return NULL;
00730 }
00731
00732 return serverCon;
00733 }
00734
00735