Annotation of src/usr.bin/openssl/s_time.c, Revision 1.6
1.6 ! jsing 1: /* $OpenBSD: s_time.c,v 1.5 2015/04/14 11:45:00 jsing 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: #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:
1.3 deraadt 66: #include <sys/types.h>
1.1 jsing 67: #include <sys/socket.h>
68:
69: #include <stdio.h>
70: #include <stdlib.h>
71: #include <limits.h>
72: #include <string.h>
73: #include <unistd.h>
1.3 deraadt 74: #include <poll.h>
1.1 jsing 75:
76: #include "apps.h"
77:
78: #include <openssl/err.h>
79: #include <openssl/pem.h>
80: #include <openssl/ssl.h>
81: #include <openssl/x509.h>
82:
83: #include "s_apps.h"
84:
85: #define SSL_CONNECT_NAME "localhost:4433"
86:
87: #define BUFSIZZ 1024*10
88:
89: #define MYBUFSIZ 1024*8
90:
91: #undef min
92: #undef max
93: #define min(a,b) (((a) < (b)) ? (a) : (b))
94: #define max(a,b) (((a) > (b)) ? (a) : (b))
95:
96: #define SECONDS 30
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;
115: int perform;
116: int ssl3;
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: {
186: .name = "reuse",
187: .desc = "Reuse the same session ID for each connection",
188: .type = OPTION_VALUE,
189: .opt.value = &s_time_config.perform,
190: .value = 2,
191: },
192: {
193: .name = "ssl3",
194: .desc = "Only use SSLv3",
195: .type = OPTION_FLAG,
196: .opt.flag = &s_time_config.ssl3,
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"
229: " [-nbio] [-new] [-reuse] [-ssl3] [-time seconds]\n"
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 s_time_main(int, char **);
251:
252: int
253: s_time_main(int argc, char **argv)
254: {
255: double totalTime = 0.0;
256: int nConn = 0;
257: SSL *scon = NULL;
258: long finishtime = 0;
259: int ret = 1, i;
260: char buf[1024 * 8];
261: int ver;
1.5 jsing 262:
263: s_time_meth = SSLv23_client_method();
1.1 jsing 264:
1.5 jsing 265: verify_depth = 0;
266: verify_error = X509_V_OK;
267:
268: memset(&s_time_config, 0, sizeof(s_time_config));
269:
270: s_time_config.host = SSL_CONNECT_NAME;
271: s_time_config.maxtime = SECONDS;
272: s_time_config.perform = 3;
273: s_time_config.verify = SSL_VERIFY_NONE;
274: s_time_config.verify_depth = -1;
1.1 jsing 275:
1.5 jsing 276: if (options_parse(argc, argv, s_time_options, NULL, NULL) != 0) {
277: s_time_usage();
278: goto end;
279: }
280:
281: if (s_time_config.ssl3)
282: s_time_meth = SSLv3_client_method();
283:
284: if (s_time_config.verify_depth >= 0) {
285: s_time_config.verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
286: verify_depth = s_time_config.verify_depth;
287: BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
288: }
1.1 jsing 289:
1.5 jsing 290: if (s_time_config.www_path != NULL &&
291: strlen(s_time_config.www_path) > MYBUFSIZ - 100) {
292: BIO_printf(bio_err, "-www option too long\n");
1.1 jsing 293: goto end;
1.5 jsing 294: }
1.1 jsing 295:
296: if ((tm_ctx = SSL_CTX_new(s_time_meth)) == NULL)
297: return (1);
298:
299: SSL_CTX_set_quiet_shutdown(tm_ctx, 1);
300:
1.5 jsing 301: if (s_time_config.bugs)
1.1 jsing 302: SSL_CTX_set_options(tm_ctx, SSL_OP_ALL);
1.5 jsing 303: SSL_CTX_set_cipher_list(tm_ctx, s_time_config.cipher);
304: if (!set_cert_stuff(tm_ctx, s_time_config.certfile,
305: s_time_config.keyfile))
1.1 jsing 306: goto end;
307:
1.5 jsing 308: if ((!SSL_CTX_load_verify_locations(tm_ctx, s_time_config.CAfile,
309: s_time_config.CApath)) ||
1.1 jsing 310: (!SSL_CTX_set_default_verify_paths(tm_ctx))) {
311: /*
312: * BIO_printf(bio_err,"error setting default verify
313: * locations\n");
314: */
315: ERR_print_errors(bio_err);
316: /* goto end; */
317: }
1.5 jsing 318: if (s_time_config.cipher == NULL)
319: s_time_config.cipher = getenv("SSL_CIPHER");
1.1 jsing 320:
1.5 jsing 321: if (s_time_config.cipher == NULL) {
1.1 jsing 322: fprintf(stderr, "No CIPHER specified\n");
323: }
1.5 jsing 324: if (!(s_time_config.perform & 1))
1.1 jsing 325: goto next;
1.5 jsing 326: printf("Collecting connection statistics for %d seconds\n",
327: s_time_config.maxtime);
1.1 jsing 328:
329: /* Loop and time how long it takes to make connections */
330:
331: bytes_read = 0;
1.5 jsing 332: finishtime = (long) time(NULL) + s_time_config.maxtime;
1.1 jsing 333: tm_Time_F(START);
334: for (;;) {
335: if (finishtime < (long) time(NULL))
336: break;
337: if ((scon = doConnection(NULL)) == NULL)
338: goto end;
339:
1.5 jsing 340: if (s_time_config.www_path != NULL) {
1.2 doug 341: int retval = snprintf(buf, sizeof buf,
1.5 jsing 342: "GET %s HTTP/1.0\r\n\r\n", s_time_config.www_path);
1.2 doug 343: if ((size_t)retval >= sizeof buf) {
1.1 jsing 344: fprintf(stderr, "URL too long\n");
345: goto end;
346: }
347: SSL_write(scon, buf, strlen(buf));
348: while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
349: bytes_read += i;
350: }
351: #ifdef NO_SHUTDOWN
352: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
353: #else
354: SSL_shutdown(scon);
355: #endif
356: shutdown(SSL_get_fd(scon), SHUT_RDWR);
357: close(SSL_get_fd(scon));
358:
359: nConn += 1;
360: if (SSL_session_reused(scon))
361: ver = 'r';
362: else {
363: ver = SSL_version(scon);
364: if (ver == TLS1_VERSION)
365: ver = 't';
366: else if (ver == SSL3_VERSION)
367: ver = '3';
368: else if (ver == SSL2_VERSION)
369: ver = '2';
370: else
371: ver = '*';
372: }
373: fputc(ver, stdout);
374: fflush(stdout);
375:
376: SSL_free(scon);
377: scon = NULL;
378: }
379: totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
380:
1.5 jsing 381: i = (int) ((long) time(NULL) - finishtime + s_time_config.maxtime);
1.1 jsing 382: 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 383: 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 384:
385: /*
386: * Now loop and time connections using the same session id over and
387: * over
388: */
389:
390: next:
1.5 jsing 391: if (!(s_time_config.perform & 2))
1.1 jsing 392: goto end;
393: printf("\n\nNow timing with session id reuse.\n");
394:
395: /* Get an SSL object so we can reuse the session id */
396: if ((scon = doConnection(NULL)) == NULL) {
397: fprintf(stderr, "Unable to get connection\n");
398: goto end;
399: }
1.5 jsing 400: if (s_time_config.www_path != NULL) {
1.2 doug 401: int retval = snprintf(buf, sizeof buf,
1.5 jsing 402: "GET %s HTTP/1.0\r\n\r\n", s_time_config.www_path);
1.2 doug 403: if ((size_t)retval >= sizeof buf) {
1.1 jsing 404: fprintf(stderr, "URL too long\n");
405: goto end;
406: }
407: SSL_write(scon, buf, strlen(buf));
408: while (SSL_read(scon, buf, sizeof(buf)) > 0);
409: }
410: #ifdef NO_SHUTDOWN
411: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
412: #else
413: SSL_shutdown(scon);
414: #endif
415: shutdown(SSL_get_fd(scon), SHUT_RDWR);
416: close(SSL_get_fd(scon));
417:
418: nConn = 0;
419: totalTime = 0.0;
420:
1.5 jsing 421: finishtime = (long) time(NULL) + s_time_config.maxtime;
1.1 jsing 422:
423: printf("starting\n");
424: bytes_read = 0;
425: tm_Time_F(START);
426:
427: for (;;) {
428: if (finishtime < (long) time(NULL))
429: break;
430: if ((doConnection(scon)) == NULL)
431: goto end;
432:
1.5 jsing 433: if (s_time_config.www_path) {
1.2 doug 434: int retval = snprintf(buf, sizeof buf,
1.5 jsing 435: "GET %s HTTP/1.0\r\n\r\n", s_time_config.www_path);
1.2 doug 436: if ((size_t)retval >= sizeof buf) {
1.1 jsing 437: fprintf(stderr, "URL too long\n");
438: goto end;
439: }
440: SSL_write(scon, buf, strlen(buf));
441: while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
442: bytes_read += i;
443: }
444: #ifdef NO_SHUTDOWN
445: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
446: #else
447: SSL_shutdown(scon);
448: #endif
449: shutdown(SSL_get_fd(scon), SHUT_RDWR);
450: close(SSL_get_fd(scon));
451:
452: nConn += 1;
453: if (SSL_session_reused(scon))
454: ver = 'r';
455: else {
456: ver = SSL_version(scon);
457: if (ver == TLS1_VERSION)
458: ver = 't';
459: else if (ver == SSL3_VERSION)
460: ver = '3';
461: else if (ver == SSL2_VERSION)
462: ver = '2';
463: else
464: ver = '*';
465: }
466: fputc(ver, stdout);
467: fflush(stdout);
468: }
469: totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
470:
471:
472: 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 473: 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 474:
475: ret = 0;
476: end:
477: if (scon != NULL)
478: SSL_free(scon);
479:
480: if (tm_ctx != NULL) {
481: SSL_CTX_free(tm_ctx);
482: tm_ctx = NULL;
483: }
484:
485: return (ret);
486: }
487:
488: /***********************************************************************
489: * doConnection - make a connection
490: * Args:
491: * scon = earlier ssl connection for session id, or NULL
492: * Returns:
493: * SSL * = the connection pointer.
494: */
495: static SSL *
496: doConnection(SSL * scon)
497: {
1.3 deraadt 498: struct pollfd pfd[1];
499: SSL *serverCon;
1.1 jsing 500: BIO *conn;
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");
534: if (verify_error != X509_V_OK)
535: BIO_printf(bio_err, "verify error:%s\n",
536: X509_verify_cert_error_string(verify_error));
537: else
538: ERR_print_errors(bio_err);
539: if (scon == NULL)
540: SSL_free(serverCon);
541: return NULL;
542: }
543: return serverCon;
544: }