Annotation of src/usr.bin/openssl/s_time.c, Revision 1.2
1.2 ! doug 1: /* $OpenBSD: s_time.c,v 1.1 2014/08/26 17:47:25 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:
66: #include <sys/select.h>
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>
74:
75: #include "apps.h"
76:
77: #include <openssl/err.h>
78: #include <openssl/pem.h>
79: #include <openssl/ssl.h>
80: #include <openssl/x509.h>
81:
82: #include "s_apps.h"
83:
84: #define SSL_CONNECT_NAME "localhost:4433"
85:
86: /*#define TEST_CERT "client.pem" *//* no default cert. */
87:
88: #define BUFSIZZ 1024*10
89:
90: #define MYBUFSIZ 1024*8
91:
92: #undef min
93: #undef max
94: #define min(a,b) (((a) < (b)) ? (a) : (b))
95: #define max(a,b) (((a) > (b)) ? (a) : (b))
96:
97: #define SECONDS 30
98: extern int verify_depth;
99: extern int verify_error;
100:
101: static void s_time_usage(void);
102: static int parseArgs(int argc, char **argv);
103: static SSL *doConnection(SSL * scon);
104: static void s_time_init(void);
105:
106: /***********************************************************************
107: * Static data declarations
108: */
109:
110: /* static char *port=PORT_STR;*/
111: static char *host = SSL_CONNECT_NAME;
112: static char *t_cert_file = NULL;
113: static char *t_key_file = NULL;
114: static char *CApath = NULL;
115: static char *CAfile = NULL;
116: static char *tm_cipher = NULL;
117: static int tm_verify = SSL_VERIFY_NONE;
118: static int maxTime = SECONDS;
119: static SSL_CTX *tm_ctx = NULL;
120: static const SSL_METHOD *s_time_meth = NULL;
121: static char *s_www_path = NULL;
122: static long bytes_read = 0;
123: static int st_bugs = 0;
124: static int perform = 0;
125: static int t_nbio = 0;
126:
127: static void
128: s_time_init(void)
129: {
130: host = SSL_CONNECT_NAME;
131: t_cert_file = NULL;
132: t_key_file = NULL;
133: CApath = NULL;
134: CAfile = NULL;
135: tm_cipher = NULL;
136: tm_verify = SSL_VERIFY_NONE;
137: maxTime = SECONDS;
138: tm_ctx = NULL;
139: s_time_meth = NULL;
140: s_www_path = NULL;
141: bytes_read = 0;
142: st_bugs = 0;
143: perform = 0;
144:
145: t_nbio = 0;
146: }
147:
148: /***********************************************************************
149: * usage - display usage message
150: */
151: static void
152: s_time_usage(void)
153: {
154: static const char umsg[] = "\
155: -time arg - max number of seconds to collect data, default %d\n\
156: -verify arg - turn on peer certificate verification, arg == depth\n\
157: -cert arg - certificate file to use, PEM format assumed\n\
158: -key arg - RSA file to use, PEM format assumed, key is in cert file\n\
159: file if not specified by this option\n\
160: -CApath arg - PEM format directory of CA's\n\
161: -CAfile arg - PEM format file of CA's\n\
162: -cipher - preferred cipher to use, play with 'openssl ciphers'\n\n";
163:
164: printf("usage: s_time <args>\n\n");
165:
166: printf("-connect host:port - host:port to connect to (default is %s)\n", SSL_CONNECT_NAME);
167: printf("-nbio - Run with non-blocking IO\n");
168: printf("-ssl2 - Just use SSLv2\n");
169: printf("-ssl3 - Just use SSLv3\n");
170: printf("-bugs - Turn on SSL bug compatibility\n");
171: printf("-new - Just time new connections\n");
172: printf("-reuse - Just time connection reuse\n");
173: printf("-www page - Retrieve 'page' from the site\n");
174: printf(umsg, SECONDS);
175: }
176:
177: /***********************************************************************
178: * parseArgs - Parse command line arguments and initialize data
179: *
180: * Returns 0 if ok, -1 on bad args
181: */
182: static int
183: parseArgs(int argc, char **argv)
184: {
185: int badop = 0;
186: const char *errstr;
187:
188: verify_depth = 0;
189: verify_error = X509_V_OK;
190:
191: argc--;
192: argv++;
193:
194: while (argc >= 1) {
195: if (strcmp(*argv, "-connect") == 0) {
196: if (--argc < 1)
197: goto bad;
198: host = *(++argv);
199: }
200: #if 0
201: else if (strcmp(*argv, "-host") == 0) {
202: if (--argc < 1)
203: goto bad;
204: host = *(++argv);
205: } else if (strcmp(*argv, "-port") == 0) {
206: if (--argc < 1)
207: goto bad;
208: port = *(++argv);
209: }
210: #endif
211: else if (strcmp(*argv, "-reuse") == 0)
212: perform = 2;
213: else if (strcmp(*argv, "-new") == 0)
214: perform = 1;
215: else if (strcmp(*argv, "-verify") == 0) {
216: tm_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
217: if (--argc < 1)
218: goto bad;
219: verify_depth = strtonum(*(++argv), 0, INT_MAX, &errstr);
220: if (errstr)
221: goto bad;
222: BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
223:
224: } else if (strcmp(*argv, "-cert") == 0) {
225:
226: if (--argc < 1)
227: goto bad;
228: t_cert_file = *(++argv);
229:
230: } else if (strcmp(*argv, "-key") == 0) {
231:
232: if (--argc < 1)
233: goto bad;
234: t_key_file = *(++argv);
235:
236: } else if (strcmp(*argv, "-CApath") == 0) {
237:
238: if (--argc < 1)
239: goto bad;
240: CApath = *(++argv);
241:
242: } else if (strcmp(*argv, "-CAfile") == 0) {
243:
244: if (--argc < 1)
245: goto bad;
246: CAfile = *(++argv);
247:
248: } else if (strcmp(*argv, "-cipher") == 0) {
249:
250: if (--argc < 1)
251: goto bad;
252: tm_cipher = *(++argv);
253: }
254: else if (strcmp(*argv, "-nbio") == 0) {
255: t_nbio = 1;
256: }
257: else if (strcmp(*argv, "-www") == 0) {
258: if (--argc < 1)
259: goto bad;
260: s_www_path = *(++argv);
261: if (strlen(s_www_path) > MYBUFSIZ - 100) {
262: BIO_printf(bio_err, "-www option too long\n");
263: badop = 1;
264: }
265: } else if (strcmp(*argv, "-bugs") == 0)
266: st_bugs = 1;
267: else if (strcmp(*argv, "-ssl3") == 0)
268: s_time_meth = SSLv3_client_method();
269: else if (strcmp(*argv, "-time") == 0) {
270:
271: if (--argc < 1)
272: goto bad;
273: maxTime = strtonum(*(++argv), 0, INT_MAX, &errstr);
274: if (errstr)
275: goto bad;
276: } else {
277: BIO_printf(bio_err, "unknown option %s\n", *argv);
278: badop = 1;
279: break;
280: }
281:
282: argc--;
283: argv++;
284: }
285:
286: if (perform == 0)
287: perform = 3;
288:
289: if (badop) {
290: bad:
291: s_time_usage();
292: return -1;
293: }
294: return 0; /* Valid args */
295: }
296:
297: /***********************************************************************
298: * TIME - time functions
299: */
300: #define START 0
301: #define STOP 1
302:
303: static double
304: tm_Time_F(int s)
305: {
306: return app_tminterval(s, 1);
307: }
308:
309: /***********************************************************************
310: * MAIN - main processing area for client
311: * real name depends on MONOLITH
312: */
313: int s_time_main(int, char **);
314:
315: int
316: s_time_main(int argc, char **argv)
317: {
318: double totalTime = 0.0;
319: int nConn = 0;
320: SSL *scon = NULL;
321: long finishtime = 0;
322: int ret = 1, i;
323: char buf[1024 * 8];
324: int ver;
325:
326: s_time_init();
327:
328: s_time_meth = SSLv23_client_method();
329:
330: /* parse the command line arguments */
331: if (parseArgs(argc, argv) < 0)
332: goto end;
333:
334: if ((tm_ctx = SSL_CTX_new(s_time_meth)) == NULL)
335: return (1);
336:
337: SSL_CTX_set_quiet_shutdown(tm_ctx, 1);
338:
339: if (st_bugs)
340: SSL_CTX_set_options(tm_ctx, SSL_OP_ALL);
341: SSL_CTX_set_cipher_list(tm_ctx, tm_cipher);
342: if (!set_cert_stuff(tm_ctx, t_cert_file, t_key_file))
343: goto end;
344:
345: if ((!SSL_CTX_load_verify_locations(tm_ctx, CAfile, CApath)) ||
346: (!SSL_CTX_set_default_verify_paths(tm_ctx))) {
347: /*
348: * BIO_printf(bio_err,"error setting default verify
349: * locations\n");
350: */
351: ERR_print_errors(bio_err);
352: /* goto end; */
353: }
354: if (tm_cipher == NULL)
355: tm_cipher = getenv("SSL_CIPHER");
356:
357: if (tm_cipher == NULL) {
358: fprintf(stderr, "No CIPHER specified\n");
359: }
360: if (!(perform & 1))
361: goto next;
362: printf("Collecting connection statistics for %d seconds\n", maxTime);
363:
364: /* Loop and time how long it takes to make connections */
365:
366: bytes_read = 0;
367: finishtime = (long) time(NULL) + maxTime;
368: tm_Time_F(START);
369: for (;;) {
370: if (finishtime < (long) time(NULL))
371: break;
372: if ((scon = doConnection(NULL)) == NULL)
373: goto end;
374:
375: if (s_www_path != NULL) {
1.2 ! doug 376: int retval = snprintf(buf, sizeof buf,
1.1 jsing 377: "GET %s HTTP/1.0\r\n\r\n", s_www_path);
1.2 ! doug 378: if ((size_t)retval >= sizeof buf) {
1.1 jsing 379: fprintf(stderr, "URL too long\n");
380: goto end;
381: }
382: SSL_write(scon, buf, strlen(buf));
383: while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
384: bytes_read += i;
385: }
386: #ifdef NO_SHUTDOWN
387: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
388: #else
389: SSL_shutdown(scon);
390: #endif
391: shutdown(SSL_get_fd(scon), SHUT_RDWR);
392: close(SSL_get_fd(scon));
393:
394: nConn += 1;
395: if (SSL_session_reused(scon))
396: ver = 'r';
397: else {
398: ver = SSL_version(scon);
399: if (ver == TLS1_VERSION)
400: ver = 't';
401: else if (ver == SSL3_VERSION)
402: ver = '3';
403: else if (ver == SSL2_VERSION)
404: ver = '2';
405: else
406: ver = '*';
407: }
408: fputc(ver, stdout);
409: fflush(stdout);
410:
411: SSL_free(scon);
412: scon = NULL;
413: }
414: totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
415:
416: i = (int) ((long) time(NULL) - finishtime + maxTime);
417: printf("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double) nConn / totalTime), bytes_read);
418: printf("%d connections in %ld real seconds, %ld bytes read per connection\n", nConn, (long) time(NULL) - finishtime + maxTime, bytes_read / nConn);
419:
420: /*
421: * Now loop and time connections using the same session id over and
422: * over
423: */
424:
425: next:
426: if (!(perform & 2))
427: goto end;
428: printf("\n\nNow timing with session id reuse.\n");
429:
430: /* Get an SSL object so we can reuse the session id */
431: if ((scon = doConnection(NULL)) == NULL) {
432: fprintf(stderr, "Unable to get connection\n");
433: goto end;
434: }
435: if (s_www_path != NULL) {
1.2 ! doug 436: int retval = snprintf(buf, sizeof buf,
1.1 jsing 437: "GET %s HTTP/1.0\r\n\r\n", s_www_path);
1.2 ! doug 438: if ((size_t)retval >= sizeof buf) {
1.1 jsing 439: fprintf(stderr, "URL too long\n");
440: goto end;
441: }
442: SSL_write(scon, buf, strlen(buf));
443: while (SSL_read(scon, buf, sizeof(buf)) > 0);
444: }
445: #ifdef NO_SHUTDOWN
446: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
447: #else
448: SSL_shutdown(scon);
449: #endif
450: shutdown(SSL_get_fd(scon), SHUT_RDWR);
451: close(SSL_get_fd(scon));
452:
453: nConn = 0;
454: totalTime = 0.0;
455:
456: finishtime = (long) time(NULL) + maxTime;
457:
458: printf("starting\n");
459: bytes_read = 0;
460: tm_Time_F(START);
461:
462: for (;;) {
463: if (finishtime < (long) time(NULL))
464: break;
465: if ((doConnection(scon)) == NULL)
466: goto end;
467:
468: if (s_www_path) {
1.2 ! doug 469: int retval = snprintf(buf, sizeof buf,
1.1 jsing 470: "GET %s HTTP/1.0\r\n\r\n", s_www_path);
1.2 ! doug 471: if ((size_t)retval >= sizeof buf) {
1.1 jsing 472: fprintf(stderr, "URL too long\n");
473: goto end;
474: }
475: SSL_write(scon, buf, strlen(buf));
476: while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
477: bytes_read += i;
478: }
479: #ifdef NO_SHUTDOWN
480: SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
481: #else
482: SSL_shutdown(scon);
483: #endif
484: shutdown(SSL_get_fd(scon), SHUT_RDWR);
485: close(SSL_get_fd(scon));
486:
487: nConn += 1;
488: if (SSL_session_reused(scon))
489: ver = 'r';
490: else {
491: ver = SSL_version(scon);
492: if (ver == TLS1_VERSION)
493: ver = 't';
494: else if (ver == SSL3_VERSION)
495: ver = '3';
496: else if (ver == SSL2_VERSION)
497: ver = '2';
498: else
499: ver = '*';
500: }
501: fputc(ver, stdout);
502: fflush(stdout);
503: }
504: totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
505:
506:
507: printf("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double) nConn / totalTime), bytes_read);
508: printf("%d connections in %ld real seconds, %ld bytes read per connection\n", nConn, (long) time(NULL) - finishtime + maxTime, bytes_read / nConn);
509:
510: ret = 0;
511: end:
512: if (scon != NULL)
513: SSL_free(scon);
514:
515: if (tm_ctx != NULL) {
516: SSL_CTX_free(tm_ctx);
517: tm_ctx = NULL;
518: }
519:
520: return (ret);
521: }
522:
523: /***********************************************************************
524: * doConnection - make a connection
525: * Args:
526: * scon = earlier ssl connection for session id, or NULL
527: * Returns:
528: * SSL * = the connection pointer.
529: */
530: static SSL *
531: doConnection(SSL * scon)
532: {
533: BIO *conn;
534: SSL *serverCon;
535: int width, i;
536: fd_set readfds;
537:
538: if ((conn = BIO_new(BIO_s_connect())) == NULL)
539: return (NULL);
540:
541: /* BIO_set_conn_port(conn,port);*/
542: BIO_set_conn_hostname(conn, host);
543:
544: if (scon == NULL)
545: serverCon = SSL_new(tm_ctx);
546: else {
547: serverCon = scon;
548: SSL_set_connect_state(serverCon);
549: }
550:
551: SSL_set_bio(serverCon, conn, conn);
552:
553: #if 0
554: if (scon != NULL)
555: SSL_set_session(serverCon, SSL_get_session(scon));
556: #endif
557:
558: /* ok, lets connect */
559: for (;;) {
560: i = SSL_connect(serverCon);
561: if (BIO_sock_should_retry(i)) {
562: BIO_printf(bio_err, "DELAY\n");
563:
564: i = SSL_get_fd(serverCon);
565: width = i + 1;
566: FD_ZERO(&readfds);
567: FD_SET(i, &readfds);
568: select(width, &readfds, NULL, NULL, NULL);
569: continue;
570: }
571: break;
572: }
573: if (i <= 0) {
574: BIO_printf(bio_err, "ERROR\n");
575: if (verify_error != X509_V_OK)
576: BIO_printf(bio_err, "verify error:%s\n",
577: X509_verify_cert_error_string(verify_error));
578: else
579: ERR_print_errors(bio_err);
580: if (scon == NULL)
581: SSL_free(serverCon);
582: return NULL;
583: }
584: return serverCon;
585: }