Annotation of src/usr.bin/openssl/s_time.c, Revision 1.11
1.11 ! lteo 1: /* $OpenBSD: s_time.c,v 1.10 2015/09/10 06:36:45 bcook 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",
! 187: .desc = "Shutdown the connection without notifying the server",
! 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.8 doug 260:
1.5 jsing 261: s_time_meth = SSLv23_client_method();
1.1 jsing 262:
1.5 jsing 263: verify_depth = 0;
264:
265: memset(&s_time_config, 0, sizeof(s_time_config));
266:
267: s_time_config.host = SSL_CONNECT_NAME;
268: s_time_config.maxtime = SECONDS;
269: s_time_config.perform = 3;
270: s_time_config.verify = SSL_VERIFY_NONE;
271: s_time_config.verify_depth = -1;
1.1 jsing 272:
1.5 jsing 273: if (options_parse(argc, argv, s_time_options, NULL, NULL) != 0) {
274: s_time_usage();
275: goto end;
276: }
277:
278: if (s_time_config.verify_depth >= 0) {
279: s_time_config.verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
280: verify_depth = s_time_config.verify_depth;
281: BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
282: }
1.1 jsing 283:
1.5 jsing 284: if (s_time_config.www_path != NULL &&
285: strlen(s_time_config.www_path) > MYBUFSIZ - 100) {
286: BIO_printf(bio_err, "-www option too long\n");
1.1 jsing 287: goto end;
1.5 jsing 288: }
1.1 jsing 289:
290: if ((tm_ctx = SSL_CTX_new(s_time_meth)) == NULL)
291: return (1);
292:
293: SSL_CTX_set_quiet_shutdown(tm_ctx, 1);
294:
1.5 jsing 295: if (s_time_config.bugs)
1.1 jsing 296: SSL_CTX_set_options(tm_ctx, SSL_OP_ALL);
1.7 jsing 297:
298: if (s_time_config.cipher != NULL) {
299: if (!SSL_CTX_set_cipher_list(tm_ctx, s_time_config.cipher)) {
300: BIO_printf(bio_err, "error setting cipher list\n");
301: ERR_print_errors(bio_err);
302: goto end;
303: }
304: }
305:
1.10 bcook 306: SSL_CTX_set_verify(tm_ctx, s_time_config.verify, NULL);
307:
1.5 jsing 308: if (!set_cert_stuff(tm_ctx, s_time_config.certfile,
309: s_time_config.keyfile))
1.1 jsing 310: goto end;
311:
1.5 jsing 312: if ((!SSL_CTX_load_verify_locations(tm_ctx, s_time_config.CAfile,
313: s_time_config.CApath)) ||
1.1 jsing 314: (!SSL_CTX_set_default_verify_paths(tm_ctx))) {
315: /*
316: * BIO_printf(bio_err,"error setting default verify
317: * locations\n");
318: */
319: ERR_print_errors(bio_err);
320: /* goto end; */
321: }
322:
1.5 jsing 323: if (!(s_time_config.perform & 1))
1.1 jsing 324: goto next;
1.5 jsing 325: printf("Collecting connection statistics for %d seconds\n",
326: s_time_config.maxtime);
1.1 jsing 327:
328: /* Loop and time how long it takes to make connections */
329:
330: bytes_read = 0;
1.5 jsing 331: finishtime = (long) time(NULL) + s_time_config.maxtime;
1.1 jsing 332: tm_Time_F(START);
333: for (;;) {
334: if (finishtime < (long) time(NULL))
335: break;
336: if ((scon = doConnection(NULL)) == NULL)
337: goto end;
338:
1.5 jsing 339: if (s_time_config.www_path != NULL) {
1.2 doug 340: int retval = snprintf(buf, sizeof buf,
1.5 jsing 341: "GET %s HTTP/1.0\r\n\r\n", s_time_config.www_path);
1.2 doug 342: if ((size_t)retval >= sizeof buf) {
1.1 jsing 343: fprintf(stderr, "URL too long\n");
344: goto end;
345: }
346: SSL_write(scon, buf, strlen(buf));
347: while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
348: bytes_read += i;
349: }
1.11 ! lteo 350: if (s_time_config.no_shutdown)
! 351: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN |
! 352: SSL_RECEIVED_SHUTDOWN);
! 353: else
! 354: SSL_shutdown(scon);
1.1 jsing 355: shutdown(SSL_get_fd(scon), SHUT_RDWR);
356: close(SSL_get_fd(scon));
357:
358: nConn += 1;
359: if (SSL_session_reused(scon))
360: ver = 'r';
361: else {
362: ver = SSL_version(scon);
363: if (ver == TLS1_VERSION)
364: ver = 't';
365: else if (ver == SSL3_VERSION)
366: ver = '3';
367: else if (ver == SSL2_VERSION)
368: ver = '2';
369: else
370: ver = '*';
371: }
372: fputc(ver, stdout);
373: fflush(stdout);
374:
375: SSL_free(scon);
376: scon = NULL;
377: }
378: totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
379:
1.5 jsing 380: i = (int) ((long) time(NULL) - finishtime + s_time_config.maxtime);
1.1 jsing 381: 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 382: 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 383:
384: /*
385: * Now loop and time connections using the same session id over and
386: * over
387: */
388:
389: next:
1.5 jsing 390: if (!(s_time_config.perform & 2))
1.1 jsing 391: goto end;
392: printf("\n\nNow timing with session id reuse.\n");
393:
394: /* Get an SSL object so we can reuse the session id */
395: if ((scon = doConnection(NULL)) == NULL) {
396: fprintf(stderr, "Unable to get connection\n");
397: goto end;
398: }
1.5 jsing 399: if (s_time_config.www_path != NULL) {
1.2 doug 400: int retval = snprintf(buf, sizeof buf,
1.5 jsing 401: "GET %s HTTP/1.0\r\n\r\n", s_time_config.www_path);
1.2 doug 402: if ((size_t)retval >= sizeof buf) {
1.1 jsing 403: fprintf(stderr, "URL too long\n");
404: goto end;
405: }
406: SSL_write(scon, buf, strlen(buf));
407: while (SSL_read(scon, buf, sizeof(buf)) > 0);
408: }
1.11 ! lteo 409: if (s_time_config.no_shutdown)
! 410: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN |
! 411: SSL_RECEIVED_SHUTDOWN);
! 412: else
! 413: SSL_shutdown(scon);
1.1 jsing 414: shutdown(SSL_get_fd(scon), SHUT_RDWR);
415: close(SSL_get_fd(scon));
416:
417: nConn = 0;
418: totalTime = 0.0;
419:
1.5 jsing 420: finishtime = (long) time(NULL) + s_time_config.maxtime;
1.1 jsing 421:
422: printf("starting\n");
423: bytes_read = 0;
424: tm_Time_F(START);
425:
426: for (;;) {
427: if (finishtime < (long) time(NULL))
428: break;
429: if ((doConnection(scon)) == NULL)
430: goto end;
431:
1.5 jsing 432: if (s_time_config.www_path) {
1.2 doug 433: int retval = snprintf(buf, sizeof buf,
1.5 jsing 434: "GET %s HTTP/1.0\r\n\r\n", s_time_config.www_path);
1.2 doug 435: if ((size_t)retval >= sizeof buf) {
1.1 jsing 436: fprintf(stderr, "URL too long\n");
437: goto end;
438: }
439: SSL_write(scon, buf, strlen(buf));
440: while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
441: bytes_read += i;
442: }
1.11 ! lteo 443: if (s_time_config.no_shutdown)
! 444: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN |
! 445: SSL_RECEIVED_SHUTDOWN);
! 446: else
! 447: SSL_shutdown(scon);
1.1 jsing 448: shutdown(SSL_get_fd(scon), SHUT_RDWR);
449: close(SSL_get_fd(scon));
450:
451: nConn += 1;
452: if (SSL_session_reused(scon))
453: ver = 'r';
454: else {
455: ver = SSL_version(scon);
456: if (ver == TLS1_VERSION)
457: ver = 't';
458: else if (ver == SSL3_VERSION)
459: ver = '3';
460: else if (ver == SSL2_VERSION)
461: ver = '2';
462: else
463: ver = '*';
464: }
465: fputc(ver, stdout);
466: fflush(stdout);
467: }
468: totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
469:
470:
471: 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 472: 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 473:
474: ret = 0;
475: end:
476: if (scon != NULL)
477: SSL_free(scon);
478:
479: if (tm_ctx != NULL) {
480: SSL_CTX_free(tm_ctx);
481: tm_ctx = NULL;
482: }
483:
484: return (ret);
485: }
486:
487: /***********************************************************************
488: * doConnection - make a connection
489: * Args:
490: * scon = earlier ssl connection for session id, or NULL
491: * Returns:
492: * SSL * = the connection pointer.
493: */
494: static SSL *
495: doConnection(SSL * scon)
496: {
1.3 deraadt 497: struct pollfd pfd[1];
498: SSL *serverCon;
1.1 jsing 499: BIO *conn;
1.10 bcook 500: long verify_error;
1.3 deraadt 501: int i;
1.1 jsing 502:
503: if ((conn = BIO_new(BIO_s_connect())) == NULL)
504: return (NULL);
505:
506: /* BIO_set_conn_port(conn,port);*/
1.5 jsing 507: BIO_set_conn_hostname(conn, s_time_config.host);
1.1 jsing 508:
509: if (scon == NULL)
510: serverCon = SSL_new(tm_ctx);
511: else {
512: serverCon = scon;
513: SSL_set_connect_state(serverCon);
514: }
515:
516: SSL_set_bio(serverCon, conn, conn);
517:
518: /* ok, lets connect */
519: for (;;) {
520: i = SSL_connect(serverCon);
521: if (BIO_sock_should_retry(i)) {
522: BIO_printf(bio_err, "DELAY\n");
523:
524: i = SSL_get_fd(serverCon);
1.3 deraadt 525: pfd[0].fd = i;
526: pfd[0].events = POLLIN;
527: poll(pfd, 1, -1);
1.1 jsing 528: continue;
529: }
530: break;
531: }
532: if (i <= 0) {
533: BIO_printf(bio_err, "ERROR\n");
1.10 bcook 534: verify_error = SSL_get_verify_result(serverCon);
1.1 jsing 535: if (verify_error != X509_V_OK)
536: BIO_printf(bio_err, "verify error:%s\n",
537: X509_verify_cert_error_string(verify_error));
538: else
539: ERR_print_errors(bio_err);
540: if (scon == NULL)
541: SSL_free(serverCon);
542: return NULL;
543: }
544: return serverCon;
545: }