xref: /netbsd-src/crypto/external/bsd/openssl/dist/apps/s_time.c (revision 8fbed61efdd901c0e09614c9f45356aeeab23fe3)
15af53050Schristos /*
2542270d5Schristos  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3a89c9211Schristos  *
4*8fbed61eSchristos  * Licensed under the Apache License 2.0 (the "License").  You may not use
55af53050Schristos  * this file except in compliance with the License.  You can obtain a copy
65af53050Schristos  * in the file LICENSE in the source distribution or at
75af53050Schristos  * https://www.openssl.org/source/license.html
8a89c9211Schristos  */
9a89c9211Schristos 
10a89c9211Schristos #include <stdio.h>
11a89c9211Schristos #include <stdlib.h>
12a89c9211Schristos #include <string.h>
13a89c9211Schristos 
145af53050Schristos #include <openssl/opensslconf.h>
155af53050Schristos 
165af53050Schristos #ifndef OPENSSL_NO_SOCK
175af53050Schristos 
18a89c9211Schristos #include "apps.h"
19e0ea3921Schristos #include "progs.h"
20a89c9211Schristos #include <openssl/x509.h>
21a89c9211Schristos #include <openssl/ssl.h>
22a89c9211Schristos #include <openssl/pem.h>
23a89c9211Schristos #include "s_apps.h"
24a89c9211Schristos #include <openssl/err.h>
25*8fbed61eSchristos #include "internal/sockets.h"
26a89c9211Schristos #if !defined(OPENSSL_SYS_MSDOS)
27*8fbed61eSchristos # include <unistd.h>
28a89c9211Schristos #endif
29a89c9211Schristos 
30a89c9211Schristos #define SSL_CONNECT_NAME        "localhost:4433"
31a89c9211Schristos 
32a89c9211Schristos #define SECONDS 30
335af53050Schristos #define SECONDSSTR "30"
34a89c9211Schristos 
355af53050Schristos static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx);
36a89c9211Schristos 
37e0ea3921Schristos /*
38e0ea3921Schristos  * Define a HTTP get command globally.
39e0ea3921Schristos  * Also define the size of the command, this is two bytes less than
40e0ea3921Schristos  * the size of the string because the %s is replaced by the URL.
41e0ea3921Schristos  */
425af53050Schristos static const char fmt_http_get_cmd[] = "GET %s HTTP/1.0\r\n\r\n";
43e0ea3921Schristos static const size_t fmt_http_get_cmd_size = sizeof(fmt_http_get_cmd) - 2;
44a89c9211Schristos 
455af53050Schristos typedef enum OPTION_choice {
46*8fbed61eSchristos     OPT_COMMON,
47e0ea3921Schristos     OPT_CONNECT, OPT_CIPHER, OPT_CIPHERSUITES, OPT_CERT, OPT_NAMEOPT, OPT_KEY,
48*8fbed61eSchristos     OPT_CAPATH, OPT_CAFILE, OPT_CASTORE,
49*8fbed61eSchristos     OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
50*8fbed61eSchristos     OPT_NEW, OPT_REUSE, OPT_BUGS, OPT_VERIFY, OPT_TIME, OPT_SSL3,
51*8fbed61eSchristos     OPT_WWW, OPT_TLS1, OPT_TLS1_1, OPT_TLS1_2, OPT_TLS1_3,
52*8fbed61eSchristos     OPT_PROV_ENUM
535af53050Schristos } OPTION_CHOICE;
54a89c9211Schristos 
55e0ea3921Schristos const OPTIONS s_time_options[] = {
56*8fbed61eSchristos     OPT_SECTION("General"),
575af53050Schristos     {"help", OPT_HELP, '-', "Display this summary"},
58*8fbed61eSchristos 
59*8fbed61eSchristos     OPT_SECTION("Connection"),
605af53050Schristos     {"connect", OPT_CONNECT, 's',
615af53050Schristos      "Where to connect as post:port (default is " SSL_CONNECT_NAME ")"},
625af53050Schristos     {"new", OPT_NEW, '-', "Just time new connections"},
635af53050Schristos     {"reuse", OPT_REUSE, '-', "Just time connection reuse"},
645af53050Schristos     {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"},
65*8fbed61eSchristos     {"cipher", OPT_CIPHER, 's', "TLSv1.2 and below cipher list to be used"},
66*8fbed61eSchristos     {"ciphersuites", OPT_CIPHERSUITES, 's',
67*8fbed61eSchristos      "Specify TLSv1.3 ciphersuites to be used"},
68*8fbed61eSchristos #ifndef OPENSSL_NO_SSL3
69*8fbed61eSchristos     {"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
70*8fbed61eSchristos #endif
71*8fbed61eSchristos #ifndef OPENSSL_NO_TLS1
72*8fbed61eSchristos     {"tls1", OPT_TLS1, '-', "Just use TLSv1.0"},
73*8fbed61eSchristos #endif
74*8fbed61eSchristos #ifndef OPENSSL_NO_TLS1_1
75*8fbed61eSchristos     {"tls1_1", OPT_TLS1_1, '-', "Just use TLSv1.1"},
76*8fbed61eSchristos #endif
77*8fbed61eSchristos #ifndef OPENSSL_NO_TLS1_2
78*8fbed61eSchristos     {"tls1_2", OPT_TLS1_2, '-', "Just use TLSv1.2"},
79*8fbed61eSchristos #endif
80*8fbed61eSchristos #ifndef OPENSSL_NO_TLS1_3
81*8fbed61eSchristos     {"tls1_3", OPT_TLS1_3, '-', "Just use TLSv1.3"},
82*8fbed61eSchristos #endif
835af53050Schristos     {"verify", OPT_VERIFY, 'p',
845af53050Schristos      "Turn on peer certificate verification, set depth"},
855af53050Schristos     {"time", OPT_TIME, 'p', "Seconds to collect data, default " SECONDSSTR},
865af53050Schristos     {"www", OPT_WWW, 's', "Fetch specified page from the site"},
87*8fbed61eSchristos 
88*8fbed61eSchristos     OPT_SECTION("Certificate"),
89*8fbed61eSchristos     {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
90*8fbed61eSchristos     {"cert", OPT_CERT, '<', "Cert file to use, PEM format assumed"},
91*8fbed61eSchristos     {"key", OPT_KEY, '<', "File with key, PEM; default is -cert file"},
92*8fbed61eSchristos     {"cafile", OPT_CAFILE, '<', "PEM format file of CA's"},
93*8fbed61eSchristos     {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
94*8fbed61eSchristos     {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
95*8fbed61eSchristos     {"CAstore", OPT_CASTORE, ':', "URI to store of CA's"},
96*8fbed61eSchristos     {"no-CAfile", OPT_NOCAFILE, '-',
97*8fbed61eSchristos      "Do not load the default certificates file"},
98*8fbed61eSchristos     {"no-CApath", OPT_NOCAPATH, '-',
99*8fbed61eSchristos      "Do not load certificates from the default certificates directory"},
100*8fbed61eSchristos     {"no-CAstore", OPT_NOCASTORE, '-',
101*8fbed61eSchristos      "Do not load certificates from the default certificates store URI"},
102*8fbed61eSchristos 
103*8fbed61eSchristos     OPT_PROV_OPTIONS,
1045af53050Schristos     {NULL}
1055af53050Schristos };
106a89c9211Schristos 
107a89c9211Schristos #define START   0
108a89c9211Schristos #define STOP    1
109a89c9211Schristos 
tm_Time_F(int s)110a89c9211Schristos static double tm_Time_F(int s)
111a89c9211Schristos {
112a89c9211Schristos     return app_tminterval(s, 1);
113a89c9211Schristos }
114a89c9211Schristos 
s_time_main(int argc,char ** argv)1155af53050Schristos int s_time_main(int argc, char **argv)
116a89c9211Schristos {
1175af53050Schristos     char buf[1024 * 8];
118a89c9211Schristos     SSL *scon = NULL;
1195af53050Schristos     SSL_CTX *ctx = NULL;
1205af53050Schristos     const SSL_METHOD *meth = NULL;
121*8fbed61eSchristos     char *CApath = NULL, *CAfile = NULL, *CAstore = NULL;
122*8fbed61eSchristos     char *cipher = NULL, *ciphersuites = NULL;
123e0ea3921Schristos     char *www_path = NULL;
1245af53050Schristos     char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog;
1255af53050Schristos     double totalTime = 0.0;
126*8fbed61eSchristos     int noCApath = 0, noCAfile = 0, noCAstore = 0;
1275af53050Schristos     int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs = 0;
1285af53050Schristos     long bytes_read = 0, finishtime = 0;
1295af53050Schristos     OPTION_CHOICE o;
130*8fbed61eSchristos     int min_version = 0, max_version = 0, ver, buf_len, fd;
1315af53050Schristos     size_t buf_size;
132a89c9211Schristos 
1335af53050Schristos     meth = TLS_client_method();
134a89c9211Schristos 
1355af53050Schristos     prog = opt_init(argc, argv, s_time_options);
1365af53050Schristos     while ((o = opt_next()) != OPT_EOF) {
1375af53050Schristos         switch (o) {
1385af53050Schristos         case OPT_EOF:
1395af53050Schristos         case OPT_ERR:
1405af53050Schristos  opthelp:
1415af53050Schristos             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
1425af53050Schristos             goto end;
1435af53050Schristos         case OPT_HELP:
1445af53050Schristos             opt_help(s_time_options);
1455af53050Schristos             ret = 0;
1465af53050Schristos             goto end;
1475af53050Schristos         case OPT_CONNECT:
1485af53050Schristos             host = opt_arg();
1495af53050Schristos             break;
1505af53050Schristos         case OPT_REUSE:
1515af53050Schristos             perform = 2;
1525af53050Schristos             break;
1535af53050Schristos         case OPT_NEW:
1545af53050Schristos             perform = 1;
1555af53050Schristos             break;
1565af53050Schristos         case OPT_VERIFY:
157*8fbed61eSchristos             verify_args.depth = opt_int_arg();
1585af53050Schristos             BIO_printf(bio_err, "%s: verify depth is %d\n",
1595af53050Schristos                        prog, verify_args.depth);
1605af53050Schristos             break;
1615af53050Schristos         case OPT_CERT:
1625af53050Schristos             certfile = opt_arg();
1635af53050Schristos             break;
164e0ea3921Schristos         case OPT_NAMEOPT:
165e0ea3921Schristos             if (!set_nameopt(opt_arg()))
166e0ea3921Schristos                 goto end;
167e0ea3921Schristos             break;
1685af53050Schristos         case OPT_KEY:
1695af53050Schristos             keyfile = opt_arg();
1705af53050Schristos             break;
1715af53050Schristos         case OPT_CAPATH:
1725af53050Schristos             CApath = opt_arg();
1735af53050Schristos             break;
1745af53050Schristos         case OPT_CAFILE:
1755af53050Schristos             CAfile = opt_arg();
1765af53050Schristos             break;
1775af53050Schristos         case OPT_NOCAPATH:
1785af53050Schristos             noCApath = 1;
1795af53050Schristos             break;
1805af53050Schristos         case OPT_NOCAFILE:
1815af53050Schristos             noCAfile = 1;
1825af53050Schristos             break;
183*8fbed61eSchristos         case OPT_CASTORE:
184*8fbed61eSchristos             CAstore = opt_arg();
185*8fbed61eSchristos             break;
186*8fbed61eSchristos         case OPT_NOCASTORE:
187*8fbed61eSchristos             noCAstore = 1;
188*8fbed61eSchristos             break;
1895af53050Schristos         case OPT_CIPHER:
1905af53050Schristos             cipher = opt_arg();
1915af53050Schristos             break;
192e0ea3921Schristos         case OPT_CIPHERSUITES:
193e0ea3921Schristos             ciphersuites = opt_arg();
194e0ea3921Schristos             break;
1955af53050Schristos         case OPT_BUGS:
1965af53050Schristos             st_bugs = 1;
1975af53050Schristos             break;
1985af53050Schristos         case OPT_TIME:
199*8fbed61eSchristos             maxtime = opt_int_arg();
2005af53050Schristos             break;
2015af53050Schristos         case OPT_WWW:
2025af53050Schristos             www_path = opt_arg();
203e0ea3921Schristos             buf_size = strlen(www_path) + fmt_http_get_cmd_size;
2045af53050Schristos             if (buf_size > sizeof(buf)) {
2055af53050Schristos                 BIO_printf(bio_err, "%s: -www option is too long\n", prog);
2065af53050Schristos                 goto end;
2075af53050Schristos             }
2085af53050Schristos             break;
2095af53050Schristos         case OPT_SSL3:
210*8fbed61eSchristos             min_version = SSL3_VERSION;
2115af53050Schristos             max_version = SSL3_VERSION;
2125af53050Schristos             break;
213*8fbed61eSchristos         case OPT_TLS1:
214*8fbed61eSchristos             min_version = TLS1_VERSION;
215*8fbed61eSchristos             max_version = TLS1_VERSION;
216*8fbed61eSchristos             break;
217*8fbed61eSchristos         case OPT_TLS1_1:
218*8fbed61eSchristos             min_version = TLS1_1_VERSION;
219*8fbed61eSchristos             max_version = TLS1_1_VERSION;
220*8fbed61eSchristos             break;
221*8fbed61eSchristos         case OPT_TLS1_2:
222*8fbed61eSchristos             min_version = TLS1_2_VERSION;
223*8fbed61eSchristos             max_version = TLS1_2_VERSION;
224*8fbed61eSchristos             break;
225*8fbed61eSchristos         case OPT_TLS1_3:
226*8fbed61eSchristos             min_version = TLS1_3_VERSION;
227*8fbed61eSchristos             max_version = TLS1_3_VERSION;
228*8fbed61eSchristos             break;
229*8fbed61eSchristos         case OPT_PROV_CASES:
230*8fbed61eSchristos             if (!opt_provider(o))
231*8fbed61eSchristos                 goto end;
232*8fbed61eSchristos             break;
2335af53050Schristos         }
2345af53050Schristos     }
235*8fbed61eSchristos 
236*8fbed61eSchristos     /* No extra arguments. */
2375af53050Schristos     argc = opt_num_rest();
2385af53050Schristos     if (argc != 0)
2395af53050Schristos         goto opthelp;
240a89c9211Schristos 
2415af53050Schristos     if (cipher == NULL)
2425af53050Schristos         cipher = getenv("SSL_CIPHER");
243a89c9211Schristos 
2445af53050Schristos     if ((ctx = SSL_CTX_new(meth)) == NULL)
245a89c9211Schristos         goto end;
246a89c9211Schristos 
2475af53050Schristos     SSL_CTX_set_quiet_shutdown(ctx, 1);
248*8fbed61eSchristos     if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
249*8fbed61eSchristos         goto end;
2505af53050Schristos     if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
2515af53050Schristos         goto end;
252a89c9211Schristos 
2539cef71b6Sspz     if (st_bugs)
2545af53050Schristos         SSL_CTX_set_options(ctx, SSL_OP_ALL);
25578327f04Schristos     if (cipher != NULL && !SSL_CTX_set_cipher_list(ctx, cipher))
256345e300bSchristos         goto end;
257e0ea3921Schristos     if (ciphersuites != NULL && !SSL_CTX_set_ciphersuites(ctx, ciphersuites))
258e0ea3921Schristos         goto end;
2595af53050Schristos     if (!set_cert_stuff(ctx, certfile, keyfile))
260a89c9211Schristos         goto end;
261a89c9211Schristos 
262*8fbed61eSchristos     if (!ctx_set_verify_locations(ctx, CAfile, noCAfile, CApath, noCApath,
263*8fbed61eSchristos                                   CAstore, noCAstore)) {
264a89c9211Schristos         ERR_print_errors(bio_err);
2655af53050Schristos         goto end;
266a89c9211Schristos     }
2679cef71b6Sspz     if (!(perform & 1))
2689cef71b6Sspz         goto next;
2695af53050Schristos     printf("Collecting connection statistics for %d seconds\n", maxtime);
270a89c9211Schristos 
271a89c9211Schristos     /* Loop and time how long it takes to make connections */
272a89c9211Schristos 
273a89c9211Schristos     bytes_read = 0;
2745af53050Schristos     finishtime = (long)time(NULL) + maxtime;
275a89c9211Schristos     tm_Time_F(START);
2769cef71b6Sspz     for (;;) {
2779cef71b6Sspz         if (finishtime < (long)time(NULL))
2789cef71b6Sspz             break;
279a89c9211Schristos 
2805af53050Schristos         if ((scon = doConnection(NULL, host, ctx)) == NULL)
281a89c9211Schristos             goto end;
282a89c9211Schristos 
2835af53050Schristos         if (www_path != NULL) {
284e0ea3921Schristos             buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd,
285e0ea3921Schristos                                    www_path);
286e0ea3921Schristos             if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0)
287a89c9211Schristos                 goto end;
28878327f04Schristos             while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
28978327f04Schristos                 bytes_read += i;
290a89c9211Schristos         }
291a89c9211Schristos         SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
2925af53050Schristos         BIO_closesocket(SSL_get_fd(scon));
293a89c9211Schristos 
294a89c9211Schristos         nConn += 1;
295e0ea3921Schristos         if (SSL_session_reused(scon)) {
296a89c9211Schristos             ver = 'r';
297e0ea3921Schristos         } else {
298a89c9211Schristos             ver = SSL_version(scon);
299a89c9211Schristos             if (ver == TLS1_VERSION)
300a89c9211Schristos                 ver = 't';
301a89c9211Schristos             else if (ver == SSL3_VERSION)
302a89c9211Schristos                 ver = '3';
303a89c9211Schristos             else
304a89c9211Schristos                 ver = '*';
305a89c9211Schristos         }
306a89c9211Schristos         fputc(ver, stdout);
307a89c9211Schristos         fflush(stdout);
308a89c9211Schristos 
309a89c9211Schristos         SSL_free(scon);
310a89c9211Schristos         scon = NULL;
311a89c9211Schristos     }
312a89c9211Schristos     totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
313a89c9211Schristos 
3145af53050Schristos     i = (int)((long)time(NULL) - finishtime + maxtime);
3159cef71b6Sspz     printf
3169cef71b6Sspz         ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
3179cef71b6Sspz          nConn, totalTime, ((double)nConn / totalTime), bytes_read);
3189cef71b6Sspz     printf
3199cef71b6Sspz         ("%d connections in %ld real seconds, %ld bytes read per connection\n",
320542270d5Schristos          nConn, (long)time(NULL) - finishtime + maxtime,
321542270d5Schristos          nConn > 0 ? bytes_read / nConn : 0l);
322a89c9211Schristos 
3239cef71b6Sspz     /*
3249cef71b6Sspz      * Now loop and time connections using the same session id over and over
3259cef71b6Sspz      */
326a89c9211Schristos 
327a89c9211Schristos  next:
3289cef71b6Sspz     if (!(perform & 2))
3299cef71b6Sspz         goto end;
330a89c9211Schristos     printf("\n\nNow timing with session id reuse.\n");
331a89c9211Schristos 
332a89c9211Schristos     /* Get an SSL object so we can reuse the session id */
3335af53050Schristos     if ((scon = doConnection(NULL, host, ctx)) == NULL) {
3345af53050Schristos         BIO_printf(bio_err, "Unable to get connection\n");
335a89c9211Schristos         goto end;
336a89c9211Schristos     }
337a89c9211Schristos 
3385af53050Schristos     if (www_path != NULL) {
339e0ea3921Schristos         buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, www_path);
340e0ea3921Schristos         if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0)
3415af53050Schristos             goto end;
34278327f04Schristos         while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
3435af53050Schristos             continue;
344a89c9211Schristos     }
345a89c9211Schristos     SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
346*8fbed61eSchristos     if ((fd = SSL_get_fd(scon)) >= 0)
347*8fbed61eSchristos         BIO_closesocket(fd);
348a89c9211Schristos 
349a89c9211Schristos     nConn = 0;
350a89c9211Schristos     totalTime = 0.0;
351a89c9211Schristos 
3525af53050Schristos     finishtime = (long)time(NULL) + maxtime;
353a89c9211Schristos 
354a89c9211Schristos     printf("starting\n");
355a89c9211Schristos     bytes_read = 0;
356a89c9211Schristos     tm_Time_F(START);
357a89c9211Schristos 
3589cef71b6Sspz     for (;;) {
3599cef71b6Sspz         if (finishtime < (long)time(NULL))
3609cef71b6Sspz             break;
361a89c9211Schristos 
3625af53050Schristos         if ((doConnection(scon, host, ctx)) == NULL)
363a89c9211Schristos             goto end;
364a89c9211Schristos 
365e0ea3921Schristos         if (www_path != NULL) {
366e0ea3921Schristos             buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd,
3675af53050Schristos                                    www_path);
368e0ea3921Schristos             if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0)
3695af53050Schristos                 goto end;
37078327f04Schristos             while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
37178327f04Schristos                 bytes_read += i;
372a89c9211Schristos         }
373a89c9211Schristos         SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
374*8fbed61eSchristos         if ((fd = SSL_get_fd(scon)) >= 0)
375*8fbed61eSchristos             BIO_closesocket(fd);
376a89c9211Schristos 
377a89c9211Schristos         nConn += 1;
378e0ea3921Schristos         if (SSL_session_reused(scon)) {
379a89c9211Schristos             ver = 'r';
380e0ea3921Schristos         } else {
381a89c9211Schristos             ver = SSL_version(scon);
382a89c9211Schristos             if (ver == TLS1_VERSION)
383a89c9211Schristos                 ver = 't';
384a89c9211Schristos             else if (ver == SSL3_VERSION)
385a89c9211Schristos                 ver = '3';
386a89c9211Schristos             else
387a89c9211Schristos                 ver = '*';
388a89c9211Schristos         }
389a89c9211Schristos         fputc(ver, stdout);
390a89c9211Schristos         fflush(stdout);
391a89c9211Schristos     }
392a89c9211Schristos     totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
393a89c9211Schristos 
3949cef71b6Sspz     printf
3959cef71b6Sspz         ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
3969cef71b6Sspz          nConn, totalTime, ((double)nConn / totalTime), bytes_read);
397*8fbed61eSchristos     if (nConn > 0)
3989cef71b6Sspz         printf
3999cef71b6Sspz             ("%d connections in %ld real seconds, %ld bytes read per connection\n",
4005af53050Schristos              nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);
401*8fbed61eSchristos     else
402*8fbed61eSchristos         printf("0 connections in %ld real seconds\n",
403*8fbed61eSchristos                (long)time(NULL) - finishtime + maxtime);
404a89c9211Schristos     ret = 0;
405a89c9211Schristos 
4065af53050Schristos  end:
4075af53050Schristos     SSL_free(scon);
4085af53050Schristos     SSL_CTX_free(ctx);
409e0ea3921Schristos     return ret;
410a89c9211Schristos }
411a89c9211Schristos 
4129cef71b6Sspz /*-
413a89c9211Schristos  * doConnection - make a connection
414a89c9211Schristos  */
doConnection(SSL * scon,const char * host,SSL_CTX * ctx)4155af53050Schristos static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx)
416a89c9211Schristos {
417a89c9211Schristos     BIO *conn;
418a89c9211Schristos     SSL *serverCon;
41978327f04Schristos     int i;
420a89c9211Schristos 
421a89c9211Schristos     if ((conn = BIO_new(BIO_s_connect())) == NULL)
42278327f04Schristos         return NULL;
423a89c9211Schristos 
424*8fbed61eSchristos     if (BIO_set_conn_hostname(conn, host) <= 0
425*8fbed61eSchristos             || BIO_set_conn_mode(conn, BIO_SOCK_NODELAY) <= 0) {
426*8fbed61eSchristos         BIO_free(conn);
427*8fbed61eSchristos         return NULL;
428*8fbed61eSchristos     }
429a89c9211Schristos 
430*8fbed61eSchristos     if (scon == NULL) {
4315af53050Schristos         serverCon = SSL_new(ctx);
432*8fbed61eSchristos         if (serverCon == NULL) {
433*8fbed61eSchristos             BIO_free(conn);
434*8fbed61eSchristos             return NULL;
435*8fbed61eSchristos         }
436*8fbed61eSchristos     } else {
437a89c9211Schristos         serverCon = scon;
438a89c9211Schristos         SSL_set_connect_state(serverCon);
439a89c9211Schristos     }
440a89c9211Schristos 
441a89c9211Schristos     SSL_set_bio(serverCon, conn, conn);
442a89c9211Schristos 
443a89c9211Schristos     /* ok, lets connect */
444a89c9211Schristos     i = SSL_connect(serverCon);
4459cef71b6Sspz     if (i <= 0) {
446a89c9211Schristos         BIO_printf(bio_err, "ERROR\n");
4475af53050Schristos         if (verify_args.error != X509_V_OK)
448a89c9211Schristos             BIO_printf(bio_err, "verify error:%s\n",
4495af53050Schristos                        X509_verify_cert_error_string(verify_args.error));
450a89c9211Schristos         else
451a89c9211Schristos             ERR_print_errors(bio_err);
452a89c9211Schristos         if (scon == NULL)
453a89c9211Schristos             SSL_free(serverCon);
454a89c9211Schristos         return NULL;
455a89c9211Schristos     }
456a89c9211Schristos 
45778327f04Schristos #if defined(SOL_SOCKET) && defined(SO_LINGER)
45878327f04Schristos     {
45978327f04Schristos         struct linger no_linger;
460e0ea3921Schristos         int fd;
46178327f04Schristos 
46278327f04Schristos         no_linger.l_onoff  = 1;
46378327f04Schristos         no_linger.l_linger = 0;
464e0ea3921Schristos         fd = SSL_get_fd(serverCon);
465e0ea3921Schristos         if (fd >= 0)
466e0ea3921Schristos             (void)setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&no_linger,
467e0ea3921Schristos                              sizeof(no_linger));
46878327f04Schristos     }
46978327f04Schristos #endif
47078327f04Schristos 
471a89c9211Schristos     return serverCon;
472a89c9211Schristos }
4735af53050Schristos #endif /* OPENSSL_NO_SOCK */
474