s_time.c 11.7 KB
Newer Older
R
Rich Salz 已提交
1 2
/*
 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
8 9
 */

10
#define NO_SHUTDOWN
11 12 13 14 15

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

M
Matt Caswell 已提交
16 17 18 19
#include <openssl/opensslconf.h>

#ifndef OPENSSL_NO_SOCK

20 21
#define USE_SOCKETS
#include "apps.h"
22 23 24
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/pem.h>
25
#include "s_apps.h"
26
#include <openssl/err.h>
27
#if !defined(OPENSSL_SYS_MSDOS)
28
# include OPENSSL_UNISTD
29
#endif
30

U
Ulf Möller 已提交
31
#undef ioctl
32 33
#define ioctl ioctlsocket

34
#define SSL_CONNECT_NAME        "localhost:4433"
35

36
/* no default cert. */
37 38 39
/*
 * #define TEST_CERT "client.pem"
 */
40 41 42 43

#undef BUFSIZZ
#define BUFSIZZ 1024*10

44 45
#define MYBUFSIZ 1024*8

46 47
#undef min
#undef max
48 49 50 51
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))

#undef SECONDS
52
#define SECONDS 30
53 54
#define SECONDSSTR "30"

55 56 57
extern int verify_depth;
extern int verify_error;

58
static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx);
59

60 61 62
typedef enum OPTION_choice {
    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
    OPT_CONNECT, OPT_CIPHER, OPT_CERT, OPT_KEY, OPT_CAPATH,
63 64
    OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NEW, OPT_REUSE, OPT_BUGS,
    OPT_VERIFY, OPT_TIME, OPT_SSL3,
65 66 67 68 69 70 71 72 73 74 75 76
    OPT_WWW
} OPTION_CHOICE;

OPTIONS s_time_options[] = {
    {"help", OPT_HELP, '-', "Display this summary"},
    {"connect", OPT_CONNECT, 's',
     "Where to connect as post:port (default is " SSL_CONNECT_NAME ")"},
    {"cipher", OPT_CIPHER, 's', "Cipher to use, see 'openssl ciphers'"},
    {"cert", OPT_CERT, '<', "Cert file to use, PEM format assumed"},
    {"key", OPT_KEY, '<', "File with key, PEM; default is -cert file"},
    {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
    {"cafile", OPT_CAFILE, '<', "PEM format file of CA's"},
77 78 79 80
    {"no-CAfile", OPT_NOCAFILE, '-',
     "Do not load the default certificates file"},
    {"no-CApath", OPT_NOCAPATH, '-',
     "Do not load certificates from the default certificates directory"},
81 82 83 84 85
    {"new", OPT_NEW, '-', "Just time new connections"},
    {"reuse", OPT_REUSE, '-', "Just time connection reuse"},
    {"bugs", OPT_BUGS, '-', "Turn on SSL bug compatibility"},
    {"verify", OPT_VERIFY, 'p',
     "Turn on peer certificate verification, set depth"},
86
    {"time", OPT_TIME, 'p', "Seconds to collect data, default " SECONDSSTR},
87 88 89
    {"www", OPT_WWW, 's', "Fetch specified page from the site"},
#ifndef OPENSSL_NO_SSL3
    {"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
90
#endif
91 92
    {NULL}
};
93

94 95
#define START   0
#define STOP    1
96

97
static double tm_Time_F(int s)
98
{
99
    return app_tminterval(s, 1);
100 101
}

102
int s_time_main(int argc, char **argv)
103
{
104 105 106 107 108 109 110
    char buf[1024 * 8];
    SSL *scon = NULL;
    SSL_CTX *ctx = NULL;
    const SSL_METHOD *meth = NULL;
    char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *www_path = NULL;
    char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog;
    double totalTime = 0.0;
111
    int noCApath = 0, noCAfile = 0;
112 113 114 115
    int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs =
        0, ver;
    long bytes_read = 0, finishtime = 0;
    OPTION_CHOICE o;
116
    int max_version = 0;
117

118
    meth = TLS_client_method();
119 120
    verify_depth = 0;
    verify_error = X509_V_OK;
121

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    prog = opt_init(argc, argv, s_time_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(s_time_options);
            ret = 0;
            goto end;
        case OPT_CONNECT:
            host = opt_arg();
            break;
        case OPT_REUSE:
138
            perform = 2;
139 140
            break;
        case OPT_NEW:
141
            perform = 1;
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
            break;
        case OPT_VERIFY:
            if (!opt_int(opt_arg(), &verify_depth))
                goto opthelp;
            BIO_printf(bio_err, "%s: verify depth is %d\n",
                       prog, verify_depth);
            break;
        case OPT_CERT:
            certfile = opt_arg();
            break;
        case OPT_KEY:
            keyfile = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
161 162 163 164 165 166
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
167 168 169 170
        case OPT_CIPHER:
            cipher = opt_arg();
            break;
        case OPT_BUGS:
171
            st_bugs = 1;
172 173 174 175 176 177 178 179 180 181
            break;
        case OPT_TIME:
            if (!opt_int(opt_arg(), &maxtime))
                goto opthelp;
            break;
        case OPT_WWW:
            www_path = opt_arg();
            if (strlen(www_path) > MYBUFSIZ - 100) {
                BIO_printf(bio_err, "%s: -www option too long\n", prog);
                goto end;
M
Matt Caswell 已提交
182
            }
183
            break;
184
        case OPT_SSL3:
185
            max_version = SSL3_VERSION;
186
            break;
187
        }
188
    }
189
    argc = opt_num_rest();
K
Kurt Roeckx 已提交
190 191
    if (argc != 0)
        goto opthelp;
192

193 194 195
    if (cipher == NULL)
        cipher = getenv("SSL_CIPHER");
    if (cipher == NULL) {
R
Rich Salz 已提交
196
        BIO_printf(bio_err, "No CIPHER specified\n");
197
        goto end;
198 199
    }

200
    if ((ctx = SSL_CTX_new(meth)) == NULL)
201 202
        goto end;

203
    SSL_CTX_set_quiet_shutdown(ctx, 1);
204 205
    if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
        goto end;
206 207

    if (st_bugs)
208 209
        SSL_CTX_set_options(ctx, SSL_OP_ALL);
    if (!SSL_CTX_set_cipher_list(ctx, cipher))
M
Matt Caswell 已提交
210
        goto end;
211
    if (!set_cert_stuff(ctx, certfile, keyfile))
212 213
        goto end;

214
    if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
215
        ERR_print_errors(bio_err);
216
        goto end;
217 218 219
    }
    if (!(perform & 1))
        goto next;
220
    printf("Collecting connection statistics for %d seconds\n", maxtime);
221

222
    /* Loop and time how long it takes to make connections */
223

224
    bytes_read = 0;
225
    finishtime = (long)time(NULL) + maxtime;
226 227 228 229
    tm_Time_F(START);
    for (;;) {
        if (finishtime < (long)time(NULL))
            break;
230

231
        if ((scon = doConnection(NULL, host, ctx)) == NULL)
232
            goto end;
233

234
        if (www_path != NULL) {
235
            BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n",
236
                         www_path);
V
Viktor Dukhovni 已提交
237
            if (SSL_write(scon, buf, strlen(buf)) <= 0)
M
Matt Caswell 已提交
238
                goto end;
239 240 241
            while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
                bytes_read += i;
        }
242
#ifdef NO_SHUTDOWN
243
        SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
244
#else
245
        SSL_shutdown(scon);
246
#endif
R
Rich Salz 已提交
247
        BIO_closesocket(SSL_get_fd(scon));
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268

        nConn += 1;
        if (SSL_session_reused(scon))
            ver = 'r';
        else {
            ver = SSL_version(scon);
            if (ver == TLS1_VERSION)
                ver = 't';
            else if (ver == SSL3_VERSION)
                ver = '3';
            else
                ver = '*';
        }
        fputc(ver, stdout);
        fflush(stdout);

        SSL_free(scon);
        scon = NULL;
    }
    totalTime += tm_Time_F(STOP); /* Add the time for this iteration */

269
    i = (int)((long)time(NULL) - finishtime + maxtime);
270 271 272 273 274
    printf
        ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
         nConn, totalTime, ((double)nConn / totalTime), bytes_read);
    printf
        ("%d connections in %ld real seconds, %ld bytes read per connection\n",
275
         nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);
276 277 278 279 280 281 282 283 284 285 286

    /*
     * Now loop and time connections using the same session id over and over
     */

 next:
    if (!(perform & 2))
        goto end;
    printf("\n\nNow timing with session id reuse.\n");

    /* Get an SSL object so we can reuse the session id */
287
    if ((scon = doConnection(NULL, host, ctx)) == NULL) {
R
Rich Salz 已提交
288
        BIO_printf(bio_err, "Unable to get connection\n");
289 290 291
        goto end;
    }

292 293
    if (www_path != NULL) {
        BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", www_path);
V
Viktor Dukhovni 已提交
294
        if (SSL_write(scon, buf, strlen(buf)) <= 0)
M
Matt Caswell 已提交
295
            goto end;
296 297
        while (SSL_read(scon, buf, sizeof(buf)) > 0)
            continue;
298
    }
299
#ifdef NO_SHUTDOWN
300
    SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
301
#else
302
    SSL_shutdown(scon);
303
#endif
R
Rich Salz 已提交
304
    BIO_closesocket(SSL_get_fd(scon));
305 306 307

    nConn = 0;
    totalTime = 0.0;
308

309
    finishtime = (long)time(NULL) + maxtime;
310

311 312 313
    printf("starting\n");
    bytes_read = 0;
    tm_Time_F(START);
314

315 316 317
    for (;;) {
        if (finishtime < (long)time(NULL))
            break;
318

319
        if ((doConnection(scon, host, ctx)) == NULL)
320
            goto end;
321

322
        if (www_path) {
323
            BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n",
324
                         www_path);
V
Viktor Dukhovni 已提交
325
            if (SSL_write(scon, buf, strlen(buf)) <= 0)
M
Matt Caswell 已提交
326
                goto end;
327 328 329
            while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
                bytes_read += i;
        }
330
#ifdef NO_SHUTDOWN
331
        SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
332
#else
333
        SSL_shutdown(scon);
334
#endif
R
Rich Salz 已提交
335
        BIO_closesocket(SSL_get_fd(scon));
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358

        nConn += 1;
        if (SSL_session_reused(scon))
            ver = 'r';
        else {
            ver = SSL_version(scon);
            if (ver == TLS1_VERSION)
                ver = 't';
            else if (ver == SSL3_VERSION)
                ver = '3';
            else
                ver = '*';
        }
        fputc(ver, stdout);
        fflush(stdout);
    }
    totalTime += tm_Time_F(STOP); /* Add the time for this iteration */

    printf
        ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
         nConn, totalTime, ((double)nConn / totalTime), bytes_read);
    printf
        ("%d connections in %ld real seconds, %ld bytes read per connection\n",
359
         nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);
360 361

    ret = 0;
362

363
 end:
R
Rich Salz 已提交
364
    SSL_free(scon);
365 366
    SSL_CTX_free(ctx);
    return (ret);
367
}
368

369
/*-
370 371
 * doConnection - make a connection
 */
372
static SSL *doConnection(SSL *scon, const char *host, SSL_CTX *ctx)
373 374 375 376 377 378 379 380 381 382 383 384
{
    BIO *conn;
    SSL *serverCon;
    int width, i;
    fd_set readfds;

    if ((conn = BIO_new(BIO_s_connect())) == NULL)
        return (NULL);

    BIO_set_conn_hostname(conn, host);

    if (scon == NULL)
385
        serverCon = SSL_new(ctx);
386 387 388 389
    else {
        serverCon = scon;
        SSL_set_connect_state(serverCon);
    }
390

391
    SSL_set_bio(serverCon, conn, conn);
392

393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
    /* ok, lets connect */
    for (;;) {
        i = SSL_connect(serverCon);
        if (BIO_sock_should_retry(i)) {
            BIO_printf(bio_err, "DELAY\n");

            i = SSL_get_fd(serverCon);
            width = i + 1;
            FD_ZERO(&readfds);
            openssl_fdset(i, &readfds);
            /*
             * Note: under VMS with SOCKETSHR the 2nd parameter is currently
             * of type (int *) whereas under other systems it is (void *) if
             * you don't have a cast it will choke the compiler: if you do
             * have a cast then you can either go for (int *) or (void *).
             */
            select(width, (void *)&readfds, NULL, NULL, NULL);
            continue;
        }
        break;
    }
    if (i <= 0) {
        BIO_printf(bio_err, "ERROR\n");
        if (verify_error != X509_V_OK)
            BIO_printf(bio_err, "verify error:%s\n",
                       X509_verify_cert_error_string(verify_error));
        else
            ERR_print_errors(bio_err);
        if (scon == NULL)
            SSL_free(serverCon);
        return NULL;
    }
425

426 427
    return serverCon;
}
M
Matt Caswell 已提交
428
#endif /* OPENSSL_NO_SOCK */