s_time.c revision 296465
1/* apps/s_time.c */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59#define NO_SHUTDOWN 60 61/* ---------------------------------------- 62 s_time - SSL client connection timer program 63 Written and donated by Larry Streepy <streepy@healthcare.com> 64 -----------------------------------------*/ 65 66#include <stdio.h> 67#include <stdlib.h> 68#include <string.h> 69 70#define USE_SOCKETS 71#include "apps.h" 72#ifdef OPENSSL_NO_STDIO 73# define APPS_WIN16 74#endif 75#include <openssl/x509.h> 76#include <openssl/ssl.h> 77#include <openssl/pem.h> 78#include "s_apps.h" 79#include <openssl/err.h> 80#ifdef WIN32_STUFF 81# include "winmain.h" 82# include "wintext.h" 83#endif 84#if !defined(OPENSSL_SYS_MSDOS) 85# include OPENSSL_UNISTD 86#endif 87 88#if !defined(OPENSSL_SYS_NETWARE) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VXWORKS) && (!defined(OPENSSL_SYS_VMS) || defined(__DECC)) 89# define TIMES 90#endif 91 92#ifndef _IRIX 93# include <time.h> 94#endif 95#ifdef TIMES 96# include <sys/types.h> 97# include <sys/times.h> 98#endif 99 100/* 101 * Depending on the VMS version, the tms structure is perhaps defined. The 102 * __TMS macro will show if it was. If it wasn't defined, we should undefine 103 * TIMES, since that tells the rest of the program how things should be 104 * handled. -- Richard Levitte 105 */ 106#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__TMS) 107# undef TIMES 108#endif 109 110#if !defined(TIMES) && !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_NETWARE) 111# include <sys/timeb.h> 112#endif 113 114#if defined(sun) || defined(__ultrix) 115# define _POSIX_SOURCE 116# include <limits.h> 117# include <sys/param.h> 118#endif 119 120/* 121 * The following if from times(3) man page. It may need to be changed 122 */ 123#ifndef HZ 124# ifdef _SC_CLK_TCK 125# define HZ ((double)sysconf(_SC_CLK_TCK)) 126# else 127# ifndef CLK_TCK 128# ifndef _BSD_CLK_TCK_ /* FreeBSD hack */ 129# define HZ 100.0 130# else /* _BSD_CLK_TCK_ */ 131# define HZ ((double)_BSD_CLK_TCK_) 132# endif 133# else /* CLK_TCK */ 134# define HZ ((double)CLK_TCK) 135# endif 136# endif 137#endif 138 139#undef PROG 140#define PROG s_time_main 141 142#undef ioctl 143#define ioctl ioctlsocket 144 145#define SSL_CONNECT_NAME "localhost:4433" 146 147/* no default cert. */ 148/* 149 * #define TEST_CERT "client.pem" 150 */ 151 152#undef BUFSIZZ 153#define BUFSIZZ 1024*10 154 155#define MYBUFSIZ 1024*8 156 157#undef min 158#undef max 159#define min(a,b) (((a) < (b)) ? (a) : (b)) 160#define max(a,b) (((a) > (b)) ? (a) : (b)) 161 162#undef SECONDS 163#define SECONDS 30 164extern int verify_depth; 165extern int verify_error; 166 167static void s_time_usage(void); 168static int parseArgs(int argc, char **argv); 169static SSL *doConnection(SSL *scon); 170static void s_time_init(void); 171 172/*********************************************************************** 173 * Static data declarations 174 */ 175 176/* static char *port=PORT_STR;*/ 177static char *host = SSL_CONNECT_NAME; 178static char *t_cert_file = NULL; 179static char *t_key_file = NULL; 180static char *CApath = NULL; 181static char *CAfile = NULL; 182static char *tm_cipher = NULL; 183static int tm_verify = SSL_VERIFY_NONE; 184static int maxTime = SECONDS; 185static SSL_CTX *tm_ctx = NULL; 186static SSL_METHOD *s_time_meth = NULL; 187static char *s_www_path = NULL; 188static long bytes_read = 0; 189static int st_bugs = 0; 190static int perform = 0; 191#ifdef FIONBIO 192static int t_nbio = 0; 193#endif 194#ifdef OPENSSL_SYS_WIN32 195static int exitNow = 0; /* Set when it's time to exit main */ 196#endif 197 198static void s_time_init(void) 199{ 200 host = SSL_CONNECT_NAME; 201 t_cert_file = NULL; 202 t_key_file = NULL; 203 CApath = NULL; 204 CAfile = NULL; 205 tm_cipher = NULL; 206 tm_verify = SSL_VERIFY_NONE; 207 maxTime = SECONDS; 208 tm_ctx = NULL; 209 s_time_meth = NULL; 210 s_www_path = NULL; 211 bytes_read = 0; 212 st_bugs = 0; 213 perform = 0; 214 215#ifdef FIONBIO 216 t_nbio = 0; 217#endif 218#ifdef OPENSSL_SYS_WIN32 219 exitNow = 0; /* Set when it's time to exit main */ 220#endif 221} 222 223/*********************************************************************** 224 * usage - display usage message 225 */ 226static void s_time_usage(void) 227{ 228 static char umsg[] = "\ 229-time arg - max number of seconds to collect data, default %d\n\ 230-verify arg - turn on peer certificate verification, arg == depth\n\ 231-cert arg - certificate file to use, PEM format assumed\n\ 232-key arg - RSA file to use, PEM format assumed, key is in cert file\n\ 233 file if not specified by this option\n\ 234-CApath arg - PEM format directory of CA's\n\ 235-CAfile arg - PEM format file of CA's\n\ 236-cipher - preferred cipher to use, play with 'openssl ciphers'\n\n"; 237 238 printf("usage: s_time <args>\n\n"); 239 240 printf("-connect host:port - host:port to connect to (default is %s)\n", 241 SSL_CONNECT_NAME); 242#ifdef FIONBIO 243 printf("-nbio - Run with non-blocking IO\n"); 244 printf("-ssl2 - Just use SSLv2\n"); 245 printf("-ssl3 - Just use SSLv3\n"); 246 printf("-bugs - Turn on SSL bug compatibility\n"); 247 printf("-new - Just time new connections\n"); 248 printf("-reuse - Just time connection reuse\n"); 249 printf("-www page - Retrieve 'page' from the site\n"); 250#endif 251 printf(umsg, SECONDS); 252} 253 254/*********************************************************************** 255 * parseArgs - Parse command line arguments and initialize data 256 * 257 * Returns 0 if ok, -1 on bad args 258 */ 259static int parseArgs(int argc, char **argv) 260{ 261 int badop = 0; 262 263 verify_depth = 0; 264 verify_error = X509_V_OK; 265 266 argc--; 267 argv++; 268 269 while (argc >= 1) { 270 if (strcmp(*argv, "-connect") == 0) { 271 if (--argc < 1) 272 goto bad; 273 host = *(++argv); 274 } 275#if 0 276 else if (strcmp(*argv, "-host") == 0) { 277 if (--argc < 1) 278 goto bad; 279 host = *(++argv); 280 } else if (strcmp(*argv, "-port") == 0) { 281 if (--argc < 1) 282 goto bad; 283 port = *(++argv); 284 } 285#endif 286 else if (strcmp(*argv, "-reuse") == 0) 287 perform = 2; 288 else if (strcmp(*argv, "-new") == 0) 289 perform = 1; 290 else if (strcmp(*argv, "-verify") == 0) { 291 292 tm_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; 293 if (--argc < 1) 294 goto bad; 295 verify_depth = atoi(*(++argv)); 296 BIO_printf(bio_err, "verify depth is %d\n", verify_depth); 297 298 } else if (strcmp(*argv, "-cert") == 0) { 299 300 if (--argc < 1) 301 goto bad; 302 t_cert_file = *(++argv); 303 304 } else if (strcmp(*argv, "-key") == 0) { 305 306 if (--argc < 1) 307 goto bad; 308 t_key_file = *(++argv); 309 310 } else if (strcmp(*argv, "-CApath") == 0) { 311 312 if (--argc < 1) 313 goto bad; 314 CApath = *(++argv); 315 316 } else if (strcmp(*argv, "-CAfile") == 0) { 317 318 if (--argc < 1) 319 goto bad; 320 CAfile = *(++argv); 321 322 } else if (strcmp(*argv, "-cipher") == 0) { 323 324 if (--argc < 1) 325 goto bad; 326 tm_cipher = *(++argv); 327 } 328#ifdef FIONBIO 329 else if (strcmp(*argv, "-nbio") == 0) { 330 t_nbio = 1; 331 } 332#endif 333 else if (strcmp(*argv, "-www") == 0) { 334 if (--argc < 1) 335 goto bad; 336 s_www_path = *(++argv); 337 if (strlen(s_www_path) > MYBUFSIZ - 100) { 338 BIO_printf(bio_err, "-www option too long\n"); 339 badop = 1; 340 } 341 } else if (strcmp(*argv, "-bugs") == 0) 342 st_bugs = 1; 343#ifndef OPENSSL_NO_SSL2 344 else if (strcmp(*argv, "-ssl2") == 0) 345 s_time_meth = SSLv2_client_method(); 346#endif 347#ifndef OPENSSL_NO_SSL3 348 else if (strcmp(*argv, "-ssl3") == 0) 349 s_time_meth = SSLv3_client_method(); 350#endif 351 else if (strcmp(*argv, "-time") == 0) { 352 353 if (--argc < 1) 354 goto bad; 355 maxTime = atoi(*(++argv)); 356 } else { 357 BIO_printf(bio_err, "unknown option %s\n", *argv); 358 badop = 1; 359 break; 360 } 361 362 argc--; 363 argv++; 364 } 365 366 if (perform == 0) 367 perform = 3; 368 369 if (badop) { 370 bad: 371 s_time_usage(); 372 return -1; 373 } 374 375 return 0; /* Valid args */ 376} 377 378/*********************************************************************** 379 * TIME - time functions 380 */ 381#define START 0 382#define STOP 1 383 384static double tm_Time_F(int s) 385{ 386 static double ret; 387#ifdef TIMES 388 static struct tms tstart, tend; 389 390 if (s == START) { 391 times(&tstart); 392 return (0); 393 } else { 394 times(&tend); 395 ret = ((double)(tend.tms_utime - tstart.tms_utime)) / HZ; 396 return ((ret == 0.0) ? 1e-6 : ret); 397 } 398#elif defined(OPENSSL_SYS_NETWARE) 399 static clock_t tstart, tend; 400 401 if (s == START) { 402 tstart = clock(); 403 return (0); 404 } else { 405 tend = clock(); 406 ret = (double)((double)(tend) - (double)(tstart)); 407 return ((ret < 0.001) ? 0.001 : ret); 408 } 409#elif defined(OPENSSL_SYS_VXWORKS) 410 { 411 static unsigned long tick_start, tick_end; 412 413 if (s == START) { 414 tick_start = tickGet(); 415 return 0; 416 } else { 417 tick_end = tickGet(); 418 ret = (double)(tick_end - tick_start) / (double)sysClkRateGet(); 419 return ((ret == 0.0) ? 1e-6 : ret); 420 } 421 } 422#else /* !times() */ 423 static struct timeb tstart, tend; 424 long i; 425 426 if (s == START) { 427 ftime(&tstart); 428 return (0); 429 } else { 430 ftime(&tend); 431 i = (long)tend.millitm - (long)tstart.millitm; 432 ret = ((double)(tend.time - tstart.time)) + ((double)i) / 1000.0; 433 return ((ret == 0.0) ? 1e-6 : ret); 434 } 435#endif 436} 437 438/*********************************************************************** 439 * MAIN - main processing area for client 440 * real name depends on MONOLITH 441 */ 442int MAIN(int, char **); 443 444int MAIN(int argc, char **argv) 445{ 446 double totalTime = 0.0; 447 int nConn = 0; 448 SSL *scon = NULL; 449 long finishtime = 0; 450 int ret = 1, i; 451 MS_STATIC char buf[1024 * 8]; 452 int ver; 453 454 apps_startup(); 455 s_time_init(); 456 457 if (bio_err == NULL) 458 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 459 460#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) 461 s_time_meth = SSLv23_client_method(); 462#elif !defined(OPENSSL_NO_SSL3) 463 s_time_meth = SSLv3_client_method(); 464#elif !defined(OPENSSL_NO_SSL2) 465 s_time_meth = SSLv2_client_method(); 466#endif 467 468 /* parse the command line arguments */ 469 if (parseArgs(argc, argv) < 0) 470 goto end; 471 472 OpenSSL_add_ssl_algorithms(); 473 if ((tm_ctx = SSL_CTX_new(s_time_meth)) == NULL) 474 return (1); 475 476 SSL_CTX_set_quiet_shutdown(tm_ctx, 1); 477 478 if (st_bugs) 479 SSL_CTX_set_options(tm_ctx, SSL_OP_ALL); 480 SSL_CTX_set_cipher_list(tm_ctx, tm_cipher); 481 if (!set_cert_stuff(tm_ctx, t_cert_file, t_key_file)) 482 goto end; 483 484 SSL_load_error_strings(); 485 486 if ((!SSL_CTX_load_verify_locations(tm_ctx, CAfile, CApath)) || 487 (!SSL_CTX_set_default_verify_paths(tm_ctx))) { 488 /* 489 * BIO_printf(bio_err,"error setting default verify locations\n"); 490 */ 491 ERR_print_errors(bio_err); 492 /* goto end; */ 493 } 494 495 if (tm_cipher == NULL) 496 tm_cipher = getenv("SSL_CIPHER"); 497 498 if (tm_cipher == NULL) { 499 fprintf(stderr, "No CIPHER specified\n"); 500 } 501 502 if (!(perform & 1)) 503 goto next; 504 printf("Collecting connection statistics for %d seconds\n", maxTime); 505 506 /* Loop and time how long it takes to make connections */ 507 508 bytes_read = 0; 509 finishtime = (long)time(NULL) + maxTime; 510 tm_Time_F(START); 511 for (;;) { 512 if (finishtime < (long)time(NULL)) 513 break; 514#ifdef WIN32_STUFF 515 516 if (flushWinMsgs(0) == -1) 517 goto end; 518 519 if (waitingToDie || exitNow) /* we're dead */ 520 goto end; 521#endif 522 523 if ((scon = doConnection(NULL)) == NULL) 524 goto end; 525 526 if (s_www_path != NULL) { 527 BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", 528 s_www_path); 529 SSL_write(scon, buf, strlen(buf)); 530 while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) 531 bytes_read += i; 532 } 533#ifdef NO_SHUTDOWN 534 SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); 535#else 536 SSL_shutdown(scon); 537#endif 538 SHUTDOWN2(SSL_get_fd(scon)); 539 540 nConn += 1; 541 if (SSL_session_reused(scon)) 542 ver = 'r'; 543 else { 544 ver = SSL_version(scon); 545 if (ver == TLS1_VERSION) 546 ver = 't'; 547 else if (ver == SSL3_VERSION) 548 ver = '3'; 549 else if (ver == SSL2_VERSION) 550 ver = '2'; 551 else 552 ver = '*'; 553 } 554 fputc(ver, stdout); 555 fflush(stdout); 556 557 SSL_free(scon); 558 scon = NULL; 559 } 560 totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ 561 562 i = (int)((long)time(NULL) - finishtime + maxTime); 563 printf 564 ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", 565 nConn, totalTime, ((double)nConn / totalTime), bytes_read); 566 printf 567 ("%d connections in %ld real seconds, %ld bytes read per connection\n", 568 nConn, (long)time(NULL) - finishtime + maxTime, bytes_read / nConn); 569 570 /* 571 * Now loop and time connections using the same session id over and over 572 */ 573 574 next: 575 if (!(perform & 2)) 576 goto end; 577 printf("\n\nNow timing with session id reuse.\n"); 578 579 /* Get an SSL object so we can reuse the session id */ 580 if ((scon = doConnection(NULL)) == NULL) { 581 fprintf(stderr, "Unable to get connection\n"); 582 goto end; 583 } 584 585 if (s_www_path != NULL) { 586 BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", s_www_path); 587 SSL_write(scon, buf, strlen(buf)); 588 while (SSL_read(scon, buf, sizeof(buf)) > 0) ; 589 } 590#ifdef NO_SHUTDOWN 591 SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); 592#else 593 SSL_shutdown(scon); 594#endif 595 SHUTDOWN2(SSL_get_fd(scon)); 596 597 nConn = 0; 598 totalTime = 0.0; 599 600 finishtime = (long)time(NULL) + maxTime; 601 602 printf("starting\n"); 603 bytes_read = 0; 604 tm_Time_F(START); 605 606 for (;;) { 607 if (finishtime < (long)time(NULL)) 608 break; 609 610#ifdef WIN32_STUFF 611 if (flushWinMsgs(0) == -1) 612 goto end; 613 614 if (waitingToDie || exitNow) /* we're dead */ 615 goto end; 616#endif 617 618 if ((doConnection(scon)) == NULL) 619 goto end; 620 621 if (s_www_path) { 622 BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", 623 s_www_path); 624 SSL_write(scon, buf, strlen(buf)); 625 while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) 626 bytes_read += i; 627 } 628#ifdef NO_SHUTDOWN 629 SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); 630#else 631 SSL_shutdown(scon); 632#endif 633 SHUTDOWN2(SSL_get_fd(scon)); 634 635 nConn += 1; 636 if (SSL_session_reused(scon)) 637 ver = 'r'; 638 else { 639 ver = SSL_version(scon); 640 if (ver == TLS1_VERSION) 641 ver = 't'; 642 else if (ver == SSL3_VERSION) 643 ver = '3'; 644 else if (ver == SSL2_VERSION) 645 ver = '2'; 646 else 647 ver = '*'; 648 } 649 fputc(ver, stdout); 650 fflush(stdout); 651 } 652 totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ 653 654 printf 655 ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", 656 nConn, totalTime, ((double)nConn / totalTime), bytes_read); 657 printf 658 ("%d connections in %ld real seconds, %ld bytes read per connection\n", 659 nConn, (long)time(NULL) - finishtime + maxTime, bytes_read / nConn); 660 661 ret = 0; 662 end: 663 if (scon != NULL) 664 SSL_free(scon); 665 666 if (tm_ctx != NULL) { 667 SSL_CTX_free(tm_ctx); 668 tm_ctx = NULL; 669 } 670 apps_shutdown(); 671 OPENSSL_EXIT(ret); 672} 673 674/*- 675 * doConnection - make a connection 676 * Args: 677 * scon = earlier ssl connection for session id, or NULL 678 * Returns: 679 * SSL * = the connection pointer. 680 */ 681static SSL *doConnection(SSL *scon) 682{ 683 BIO *conn; 684 SSL *serverCon; 685 int width, i; 686 fd_set readfds; 687 688 if ((conn = BIO_new(BIO_s_connect())) == NULL) 689 return (NULL); 690 691/* BIO_set_conn_port(conn,port);*/ 692 BIO_set_conn_hostname(conn, host); 693 694 if (scon == NULL) 695 serverCon = SSL_new(tm_ctx); 696 else { 697 serverCon = scon; 698 SSL_set_connect_state(serverCon); 699 } 700 701 SSL_set_bio(serverCon, conn, conn); 702 703#if 0 704 if (scon != NULL) 705 SSL_set_session(serverCon, SSL_get_session(scon)); 706#endif 707 708 /* ok, lets connect */ 709 for (;;) { 710 i = SSL_connect(serverCon); 711 if (BIO_sock_should_retry(i)) { 712 BIO_printf(bio_err, "DELAY\n"); 713 714 i = SSL_get_fd(serverCon); 715 width = i + 1; 716 FD_ZERO(&readfds); 717 FD_SET(i, &readfds); 718 /* 719 * Note: under VMS with SOCKETSHR the 2nd parameter is currently 720 * of type (int *) whereas under other systems it is (void *) if 721 * you don't have a cast it will choke the compiler: if you do 722 * have a cast then you can either go for (int *) or (void *). 723 */ 724 select(width, (void *)&readfds, NULL, NULL, NULL); 725 continue; 726 } 727 break; 728 } 729 if (i <= 0) { 730 BIO_printf(bio_err, "ERROR\n"); 731 if (verify_error != X509_V_OK) 732 BIO_printf(bio_err, "verify error:%s\n", 733 X509_verify_cert_error_string(verify_error)); 734 else 735 ERR_print_errors(bio_err); 736 if (scon == NULL) 737 SSL_free(serverCon); 738 return NULL; 739 } 740 741 return serverCon; 742} 743