Annotation of src/usr.bin/openssl/s_time.c, Revision 1.13
1.13 ! doug 1: /* $OpenBSD: s_time.c,v 1.12 2015/09/11 14:43:57 lteo Exp $ */
1.1 jsing 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: /*-----------------------------------------
60: s_time - SSL client connection timer program
61: Written and donated by Larry Streepy <streepy@healthcare.com>
62: -----------------------------------------*/
63:
1.3 deraadt 64: #include <sys/types.h>
1.1 jsing 65: #include <sys/socket.h>
66:
67: #include <stdio.h>
68: #include <stdlib.h>
69: #include <limits.h>
70: #include <string.h>
71: #include <unistd.h>
1.3 deraadt 72: #include <poll.h>
1.1 jsing 73:
74: #include "apps.h"
75:
76: #include <openssl/err.h>
77: #include <openssl/pem.h>
78: #include <openssl/ssl.h>
79: #include <openssl/x509.h>
80:
81: #include "s_apps.h"
82:
83: #define SSL_CONNECT_NAME "localhost:4433"
84:
85: #define BUFSIZZ 1024*10
86:
87: #define MYBUFSIZ 1024*8
88:
89: #undef min
90: #undef max
91: #define min(a,b) (((a) < (b)) ? (a) : (b))
92: #define max(a,b) (((a) > (b)) ? (a) : (b))
93:
94: #define SECONDS 30
1.7 jsing 95: extern int verify_depth;
96: extern int verify_error;
1.1 jsing 97:
98: static void s_time_usage(void);
99: static SSL *doConnection(SSL * scon);
100:
101: static SSL_CTX *tm_ctx = NULL;
102: static const SSL_METHOD *s_time_meth = NULL;
103: static long bytes_read = 0;
104:
1.5 jsing 105: struct {
106: int bugs;
107: char *CAfile;
108: char *CApath;
109: char *certfile;
110: char *cipher;
111: char *host;
112: char *keyfile;
113: int maxtime;
114: int nbio;
1.11 lteo 115: int no_shutdown;
1.5 jsing 116: int perform;
117: int verify;
118: int verify_depth;
119: char *www_path;
120: } s_time_config;
121:
122: struct option s_time_options[] = {
123: {
124: .name = "bugs",
125: .desc = "Enable workarounds for known SSL/TLS bugs",
126: .type = OPTION_FLAG,
127: .opt.flag = &s_time_config.bugs,
128: },
129: {
130: .name = "CAfile",
131: .argname = "file",
132: .desc = "File containing trusted certificates in PEM format",
133: .type = OPTION_ARG,
134: .opt.arg = &s_time_config.CAfile,
135: },
136: {
137: .name = "CApath",
138: .argname = "path",
139: .desc = "Directory containing trusted certificates",
140: .type = OPTION_ARG,
141: .opt.arg = &s_time_config.CApath,
142: },
143: {
144: .name = "cert",
145: .argname = "file",
146: .desc = "Client certificate to use, if one is requested",
147: .type = OPTION_ARG,
148: .opt.arg = &s_time_config.certfile,
149: },
150: {
151: .name = "cipher",
152: .argname = "list",
153: .desc = "List of cipher suites to send to the server",
154: .type = OPTION_ARG,
155: .opt.arg = &s_time_config.cipher,
156: },
157: {
158: .name = "connect",
159: .argname = "host:port",
160: .desc = "Host and port to connect to (default "
161: SSL_CONNECT_NAME ")",
162: .type = OPTION_ARG,
163: .opt.arg = &s_time_config.host,
164: },
165: {
166: .name = "key",
167: .argname = "file",
168: .desc = "Client private key to use, if one is required",
169: .type = OPTION_ARG,
170: .opt.arg = &s_time_config.keyfile,
171: },
172: {
173: .name = "nbio",
174: .desc = "Use non-blocking I/O",
175: .type = OPTION_FLAG,
176: .opt.flag = &s_time_config.nbio,
177: },
178: {
179: .name = "new",
180: .desc = "Use a new session ID for each connection",
181: .type = OPTION_VALUE,
182: .opt.value = &s_time_config.perform,
183: .value = 1,
184: },
185: {
1.11 lteo 186: .name = "no_shutdown",
1.12 lteo 187: .desc = "Shut down the connection without notifying the server",
1.11 lteo 188: .type = OPTION_FLAG,
189: .opt.flag = &s_time_config.no_shutdown,
190: },
191: {
1.5 jsing 192: .name = "reuse",
193: .desc = "Reuse the same session ID for each connection",
194: .type = OPTION_VALUE,
195: .opt.value = &s_time_config.perform,
196: .value = 2,
197: },
198: {
199: .name = "time",
200: .argname = "seconds",
201: .desc = "Duration to perform timing tests for (default 30)",
202: .type = OPTION_ARG_INT,
203: .opt.value = &s_time_config.maxtime,
204: },
205: {
206: .name = "verify",
207: .argname = "depth",
208: .desc = "Enable peer certificate verification with given depth",
209: .type = OPTION_ARG_INT,
210: .opt.value = &s_time_config.verify_depth,
211: },
212: {
213: .name = "www",
214: .argname = "page",
215: .desc = "Page to GET from the server (default none)",
216: .type = OPTION_ARG,
217: .opt.arg = &s_time_config.www_path,
218: },
219: { NULL },
220: };
1.1 jsing 221:
222: static void
223: s_time_usage(void)
224: {
1.5 jsing 225: fprintf(stderr,
226: "usage: s_time "
227: "[-bugs] [-CAfile file] [-CApath directory] [-cert file]\n"
228: " [-cipher cipherlist] [-connect host:port] [-key keyfile]\n"
1.11 lteo 229: " [-nbio] [-new] [-no_shutdown] [-reuse] [-time seconds]\n"
1.5 jsing 230: " [-verify depth] [-www page]\n\n");
231: options_usage(s_time_options);
1.1 jsing 232: }
233:
234: /***********************************************************************
235: * TIME - time functions
236: */
237: #define START 0
238: #define STOP 1
239:
240: static double
241: tm_Time_F(int s)
242: {
243: return app_tminterval(s, 1);
244: }
245:
246: /***********************************************************************
247: * MAIN - main processing area for client
248: * real name depends on MONOLITH
249: */
250: int
251: s_time_main(int argc, char **argv)
252: {
253: double totalTime = 0.0;
254: int nConn = 0;
255: SSL *scon = NULL;
256: long finishtime = 0;
257: int ret = 1, i;
258: char buf[1024 * 8];
259: int ver;
1.13 ! doug 260:
! 261: if (single_execution) {
! 262: if (pledge("stdio inet rpath", NULL) == -1)
! 263: perror("pledge");
! 264: }
1.8 doug 265:
1.5 jsing 266: s_time_meth = SSLv23_client_method();
1.1 jsing 267:
1.5 jsing 268: verify_depth = 0;
269:
270: memset(&s_time_config, 0, sizeof(s_time_config));
271:
272: s_time_config.host = SSL_CONNECT_NAME;
273: s_time_config.maxtime = SECONDS;
274: s_time_config.perform = 3;
275: s_time_config.verify = SSL_VERIFY_NONE;
276: s_time_config.verify_depth = -1;
1.1 jsing 277:
1.5 jsing 278: if (options_parse(argc, argv, s_time_options, NULL, NULL) != 0) {
279: s_time_usage();
280: goto end;
281: }
282:
283: if (s_time_config.verify_depth >= 0) {
284: s_time_config.verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
285: verify_depth = s_time_config.verify_depth;
286: BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
287: }
1.1 jsing 288:
1.5 jsing 289: if (s_time_config.www_path != NULL &&
290: strlen(s_time_config.www_path) > MYBUFSIZ - 100) {
291: BIO_printf(bio_err, "-www option too long\n");
1.1 jsing 292: goto end;
1.5 jsing 293: }
1.1 jsing 294:
295: if ((tm_ctx = SSL_CTX_new(s_time_meth)) == NULL)
296: return (1);
297:
298: SSL_CTX_set_quiet_shutdown(tm_ctx, 1);
299:
1.5 jsing 300: if (s_time_config.bugs)
1.1 jsing 301: SSL_CTX_set_options(tm_ctx, SSL_OP_ALL);
1.7 jsing 302:
303: if (s_time_config.cipher != NULL) {
304: if (!SSL_CTX_set_cipher_list(tm_ctx, s_time_config.cipher)) {
305: BIO_printf(bio_err, "error setting cipher list\n");
306: ERR_print_errors(bio_err);
307: goto end;
308: }
309: }
310:
1.10 bcook 311: SSL_CTX_set_verify(tm_ctx, s_time_config.verify, NULL);
312:
1.5 jsing 313: if (!set_cert_stuff(tm_ctx, s_time_config.certfile,
314: s_time_config.keyfile))
1.1 jsing 315: goto end;
316:
1.5 jsing 317: if ((!SSL_CTX_load_verify_locations(tm_ctx, s_time_config.CAfile,
318: s_time_config.CApath)) ||
1.1 jsing 319: (!SSL_CTX_set_default_verify_paths(tm_ctx))) {
320: /*
321: * BIO_printf(bio_err,"error setting default verify
322: * locations\n");
323: */
324: ERR_print_errors(bio_err);
325: /* goto end; */
326: }
327:
1.5 jsing 328: if (!(s_time_config.perform & 1))
1.1 jsing 329: goto next;
1.5 jsing 330: printf("Collecting connection statistics for %d seconds\n",
331: s_time_config.maxtime);
1.1 jsing 332:
333: /* Loop and time how long it takes to make connections */
334:
335: bytes_read = 0;
1.5 jsing 336: finishtime = (long) time(NULL) + s_time_config.maxtime;
1.1 jsing 337: tm_Time_F(START);
338: for (;;) {
339: if (finishtime < (long) time(NULL))
340: break;
341: if ((scon = doConnection(NULL)) == NULL)
342: goto end;
343:
1.5 jsing 344: if (s_time_config.www_path != NULL) {
1.2 doug 345: int retval = snprintf(buf, sizeof buf,
1.5 jsing 346: "GET %s HTTP/1.0\r\n\r\n", s_time_config.www_path);
1.2 doug 347: if ((size_t)retval >= sizeof buf) {
1.1 jsing 348: fprintf(stderr, "URL too long\n");
349: goto end;
350: }
351: SSL_write(scon, buf, strlen(buf));
352: while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
353: bytes_read += i;
354: }
1.11 lteo 355: if (s_time_config.no_shutdown)
356: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN |
357: SSL_RECEIVED_SHUTDOWN);
358: else
359: SSL_shutdown(scon);
1.1 jsing 360: shutdown(SSL_get_fd(scon), SHUT_RDWR);
361: close(SSL_get_fd(scon));
362:
363: nConn += 1;
364: if (SSL_session_reused(scon))
365: ver = 'r';
366: else {
367: ver = SSL_version(scon);
368: if (ver == TLS1_VERSION)
369: ver = 't';
370: else if (ver == SSL3_VERSION)
371: ver = '3';
372: else if (ver == SSL2_VERSION)
373: ver = '2';
374: else
375: ver = '*';
376: }
377: fputc(ver, stdout);
378: fflush(stdout);
379:
380: SSL_free(scon);
381: scon = NULL;
382: }
383: totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
384:
1.5 jsing 385: i = (int) ((long) time(NULL) - finishtime + s_time_config.maxtime);
1.1 jsing 386: printf("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double) nConn / totalTime), bytes_read);
1.5 jsing 387: printf("%d connections in %ld real seconds, %ld bytes read per connection\n", nConn, (long) time(NULL) - finishtime + s_time_config.maxtime, bytes_read / nConn);
1.1 jsing 388:
389: /*
390: * Now loop and time connections using the same session id over and
391: * over
392: */
393:
394: next:
1.5 jsing 395: if (!(s_time_config.perform & 2))
1.1 jsing 396: goto end;
397: printf("\n\nNow timing with session id reuse.\n");
398:
399: /* Get an SSL object so we can reuse the session id */
400: if ((scon = doConnection(NULL)) == NULL) {
401: fprintf(stderr, "Unable to get connection\n");
402: goto end;
403: }
1.5 jsing 404: if (s_time_config.www_path != NULL) {
1.2 doug 405: int retval = snprintf(buf, sizeof buf,
1.5 jsing 406: "GET %s HTTP/1.0\r\n\r\n", s_time_config.www_path);
1.2 doug 407: if ((size_t)retval >= sizeof buf) {
1.1 jsing 408: fprintf(stderr, "URL too long\n");
409: goto end;
410: }
411: SSL_write(scon, buf, strlen(buf));
412: while (SSL_read(scon, buf, sizeof(buf)) > 0);
413: }
1.11 lteo 414: if (s_time_config.no_shutdown)
415: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN |
416: SSL_RECEIVED_SHUTDOWN);
417: else
418: SSL_shutdown(scon);
1.1 jsing 419: shutdown(SSL_get_fd(scon), SHUT_RDWR);
420: close(SSL_get_fd(scon));
421:
422: nConn = 0;
423: totalTime = 0.0;
424:
1.5 jsing 425: finishtime = (long) time(NULL) + s_time_config.maxtime;
1.1 jsing 426:
427: printf("starting\n");
428: bytes_read = 0;
429: tm_Time_F(START);
430:
431: for (;;) {
432: if (finishtime < (long) time(NULL))
433: break;
434: if ((doConnection(scon)) == NULL)
435: goto end;
436:
1.5 jsing 437: if (s_time_config.www_path) {
1.2 doug 438: int retval = snprintf(buf, sizeof buf,
1.5 jsing 439: "GET %s HTTP/1.0\r\n\r\n", s_time_config.www_path);
1.2 doug 440: if ((size_t)retval >= sizeof buf) {
1.1 jsing 441: fprintf(stderr, "URL too long\n");
442: goto end;
443: }
444: SSL_write(scon, buf, strlen(buf));
445: while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
446: bytes_read += i;
447: }
1.11 lteo 448: if (s_time_config.no_shutdown)
449: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN |
450: SSL_RECEIVED_SHUTDOWN);
451: else
452: SSL_shutdown(scon);
1.1 jsing 453: shutdown(SSL_get_fd(scon), SHUT_RDWR);
454: close(SSL_get_fd(scon));
455:
456: nConn += 1;
457: if (SSL_session_reused(scon))
458: ver = 'r';
459: else {
460: ver = SSL_version(scon);
461: if (ver == TLS1_VERSION)
462: ver = 't';
463: else if (ver == SSL3_VERSION)
464: ver = '3';
465: else if (ver == SSL2_VERSION)
466: ver = '2';
467: else
468: ver = '*';
469: }
470: fputc(ver, stdout);
471: fflush(stdout);
472: }
473: totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
474:
475:
476: printf("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double) nConn / totalTime), bytes_read);
1.5 jsing 477: printf("%d connections in %ld real seconds, %ld bytes read per connection\n", nConn, (long) time(NULL) - finishtime + s_time_config.maxtime, bytes_read / nConn);
1.1 jsing 478:
479: ret = 0;
480: end:
481: if (scon != NULL)
482: SSL_free(scon);
483:
484: if (tm_ctx != NULL) {
485: SSL_CTX_free(tm_ctx);
486: tm_ctx = NULL;
487: }
488:
489: return (ret);
490: }
491:
492: /***********************************************************************
493: * doConnection - make a connection
494: * Args:
495: * scon = earlier ssl connection for session id, or NULL
496: * Returns:
497: * SSL * = the connection pointer.
498: */
499: static SSL *
500: doConnection(SSL * scon)
501: {
1.3 deraadt 502: struct pollfd pfd[1];
503: SSL *serverCon;
1.1 jsing 504: BIO *conn;
1.10 bcook 505: long verify_error;
1.3 deraadt 506: int i;
1.1 jsing 507:
508: if ((conn = BIO_new(BIO_s_connect())) == NULL)
509: return (NULL);
510:
511: /* BIO_set_conn_port(conn,port);*/
1.5 jsing 512: BIO_set_conn_hostname(conn, s_time_config.host);
1.1 jsing 513:
514: if (scon == NULL)
515: serverCon = SSL_new(tm_ctx);
516: else {
517: serverCon = scon;
518: SSL_set_connect_state(serverCon);
519: }
520:
521: SSL_set_bio(serverCon, conn, conn);
522:
523: /* ok, lets connect */
524: for (;;) {
525: i = SSL_connect(serverCon);
526: if (BIO_sock_should_retry(i)) {
527: BIO_printf(bio_err, "DELAY\n");
528:
529: i = SSL_get_fd(serverCon);
1.3 deraadt 530: pfd[0].fd = i;
531: pfd[0].events = POLLIN;
532: poll(pfd, 1, -1);
1.1 jsing 533: continue;
534: }
535: break;
536: }
537: if (i <= 0) {
538: BIO_printf(bio_err, "ERROR\n");
1.10 bcook 539: verify_error = SSL_get_verify_result(serverCon);
1.1 jsing 540: if (verify_error != X509_V_OK)
541: BIO_printf(bio_err, "verify error:%s\n",
542: X509_verify_cert_error_string(verify_error));
543: else
544: ERR_print_errors(bio_err);
545: if (scon == NULL)
546: SSL_free(serverCon);
547: return NULL;
548: }
549: return serverCon;
550: }