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