Annotation of src/usr.bin/openssl/s_client.c, Revision 1.62
1.62 ! beck 1: /* $OpenBSD: s_client.c,v 1.61 2023/07/03 06:22:07 beck 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: * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
60: *
61: * Redistribution and use in source and binary forms, with or without
62: * modification, are permitted provided that the following conditions
63: * are met:
64: *
65: * 1. Redistributions of source code must retain the above copyright
66: * notice, this list of conditions and the following disclaimer.
67: *
68: * 2. Redistributions in binary form must reproduce the above copyright
69: * notice, this list of conditions and the following disclaimer in
70: * the documentation and/or other materials provided with the
71: * distribution.
72: *
73: * 3. All advertising materials mentioning features or use of this
74: * software must display the following acknowledgment:
75: * "This product includes software developed by the OpenSSL Project
76: * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77: *
78: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79: * endorse or promote products derived from this software without
80: * prior written permission. For written permission, please contact
81: * openssl-core@openssl.org.
82: *
83: * 5. Products derived from this software may not be called "OpenSSL"
84: * nor may "OpenSSL" appear in their names without prior written
85: * permission of the OpenSSL Project.
86: *
87: * 6. Redistributions of any form whatsoever must retain the following
88: * acknowledgment:
89: * "This product includes software developed by the OpenSSL Project
90: * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91: *
92: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
96: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103: * OF THE POSSIBILITY OF SUCH DAMAGE.
104: * ====================================================================
105: *
106: * This product includes cryptographic software written by Eric Young
107: * (eay@cryptsoft.com). This product includes software written by Tim
108: * Hudson (tjh@cryptsoft.com).
109: *
110: */
111: /* ====================================================================
112: * Copyright 2005 Nokia. All rights reserved.
113: *
114: * The portions of the attached software ("Contribution") is developed by
115: * Nokia Corporation and is licensed pursuant to the OpenSSL open source
116: * license.
117: *
118: * The Contribution, originally written by Mika Kousa and Pasi Eronen of
119: * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
120: * support (see RFC 4279) to OpenSSL.
121: *
122: * No patent licenses or other rights except those expressly stated in
123: * the OpenSSL open source license shall be deemed granted or received
124: * expressly, by implication, estoppel, or otherwise.
125: *
126: * No assurances are provided by Nokia that the Contribution does not
127: * infringe the patent or other intellectual property rights of any third
128: * party or that the license provides you with all the necessary rights
129: * to make use of the Contribution.
130: *
131: * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
132: * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
133: * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
134: * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
135: * OTHERWISE.
136: */
137:
138: #include <sys/types.h>
139: #include <sys/socket.h>
140:
141: #include <netinet/in.h>
142:
143: #include <assert.h>
144: #include <ctype.h>
145: #include <limits.h>
146: #include <netdb.h>
147: #include <stdio.h>
148: #include <stdlib.h>
149: #include <string.h>
150: #include <unistd.h>
1.9 deraadt 151: #include <poll.h>
1.1 jsing 152:
153: #include "apps.h"
154:
155: #include <openssl/bn.h>
156: #include <openssl/err.h>
157: #include <openssl/ocsp.h>
158: #include <openssl/pem.h>
159: #include <openssl/ssl.h>
160: #include <openssl/x509.h>
161:
162: #include "s_apps.h"
163: #include "timeouts.h"
164:
165: /*#define SSL_HOST_NAME "www.netscape.com" */
166: /*#define SSL_HOST_NAME "193.118.187.102" */
167: #define SSL_HOST_NAME "localhost"
168:
169: /*#define TEST_CERT "client.pem" *//* no default cert. */
170:
171: #define BUFSIZZ 1024*8
172:
173: static void sc_usage(void);
1.51 inoguchi 174: static void print_stuff(BIO *berr, SSL *con, int full);
175: static int ocsp_resp_cb(SSL *s, void *arg);
176: static int ssl_servername_cb(SSL *s, int *ad, void *arg);
1.1 jsing 177:
1.47 inoguchi 178: enum {
179: PROTO_OFF = 0,
180: PROTO_SMTP,
181: PROTO_LMTP,
182: PROTO_POP3,
183: PROTO_IMAP,
184: PROTO_FTP,
185: PROTO_XMPP,
186: };
187:
1.51 inoguchi 188: /* This is a context that we pass to callbacks */
189: typedef struct tlsextctx_st {
190: BIO *biodebug;
191: int ack;
192: } tlsextctx;
193:
1.47 inoguchi 194: static struct {
195: int af;
196: char *alpn_in;
197: int bugs;
198: char *CAfile;
199: char *CApath;
200: char *cert_file;
201: int cert_format;
202: char *cipher;
203: unsigned int clr;
204: char *connect;
205: int crlf;
1.48 inoguchi 206: int debug;
1.47 inoguchi 207: int enable_timeouts;
208: const char *errstr;
209: char *groups_in;
210: char *host;
1.48 inoguchi 211: int ign_eof;
1.47 inoguchi 212: char *key_file;
213: int key_format;
214: char *keymatexportlabel;
215: int keymatexportlen;
216: uint16_t max_version;
217: uint16_t min_version;
218: const SSL_METHOD *meth;
1.48 inoguchi 219: int msg;
220: int nbio;
1.47 inoguchi 221: int nbio_test;
1.57 jsing 222: int no_servername;
1.47 inoguchi 223: char *npn_in;
224: unsigned int off;
225: char *passarg;
1.48 inoguchi 226: int pause;
1.47 inoguchi 227: int peekaboo;
228: char *port;
229: int prexit;
230: char *proxy;
1.48 inoguchi 231: int quiet;
1.47 inoguchi 232: int reconnect;
233: char *servername;
234: char *sess_in;
235: char *sess_out;
1.48 inoguchi 236: int showcerts;
1.47 inoguchi 237: int socket_type;
238: long socket_mtu;
239: #ifndef OPENSSL_NO_SRTP
240: char *srtp_profiles;
241: #endif
242: int starttls_proto;
243: int state;
1.48 inoguchi 244: int status_req;
245: int tlsextdebug;
1.47 inoguchi 246: int verify;
247: X509_VERIFY_PARAM *vpm;
248: char *xmpphost;
1.60 tb 249: } cfg;
1.47 inoguchi 250:
251: static int
252: s_client_opt_keymatexportlen(char *arg)
253: {
1.60 tb 254: cfg.keymatexportlen = strtonum(arg, 1, INT_MAX,
255: &cfg.errstr);
256: if (cfg.errstr != NULL) {
1.47 inoguchi 257: BIO_printf(bio_err, "invalid argument %s: %s\n",
1.60 tb 258: arg, cfg.errstr);
1.47 inoguchi 259: return (1);
260: }
261: return (0);
262: }
263:
1.53 jsing 264: #ifndef OPENSSL_NO_DTLS
1.47 inoguchi 265: static int
266: s_client_opt_mtu(char *arg)
267: {
1.60 tb 268: cfg.socket_mtu = strtonum(arg, 0, LONG_MAX,
269: &cfg.errstr);
270: if (cfg.errstr != NULL) {
1.47 inoguchi 271: BIO_printf(bio_err, "invalid argument %s: %s\n",
1.60 tb 272: arg, cfg.errstr);
1.47 inoguchi 273: return (1);
274: }
275: return (0);
276: }
277: #endif
278:
279: static int
280: s_client_opt_port(char *arg)
281: {
282: if (*arg == '\0')
283: return (1);
284:
1.60 tb 285: cfg.port = arg;
1.47 inoguchi 286: return (0);
287: }
288:
1.53 jsing 289: #ifndef OPENSSL_NO_DTLS
290: static int
291: s_client_opt_protocol_version_dtls(void)
292: {
1.60 tb 293: cfg.meth = DTLS_client_method();
294: cfg.socket_type = SOCK_DGRAM;
1.53 jsing 295: return (0);
296: }
297: #endif
298:
299: #ifndef OPENSSL_NO_DTLS1_2
300: static int
301: s_client_opt_protocol_version_dtls1_2(void)
302: {
1.60 tb 303: cfg.meth = DTLS_client_method();
304: cfg.min_version = DTLS1_2_VERSION;
305: cfg.max_version = DTLS1_2_VERSION;
306: cfg.socket_type = SOCK_DGRAM;
1.47 inoguchi 307: return (0);
308: }
309: #endif
310:
311: static int
312: s_client_opt_protocol_version_tls1_2(void)
313: {
1.60 tb 314: cfg.min_version = TLS1_2_VERSION;
315: cfg.max_version = TLS1_2_VERSION;
1.47 inoguchi 316: return (0);
317: }
318:
319: static int
320: s_client_opt_protocol_version_tls1_3(void)
321: {
1.60 tb 322: cfg.min_version = TLS1_3_VERSION;
323: cfg.max_version = TLS1_3_VERSION;
1.47 inoguchi 324: return (0);
325: }
326:
327: static int
328: s_client_opt_quiet(void)
329: {
1.60 tb 330: cfg.quiet = 1;
331: cfg.ign_eof = 1;
1.47 inoguchi 332: return (0);
333: }
334:
335: static int
336: s_client_opt_starttls(char *arg)
337: {
338: if (strcmp(arg, "smtp") == 0)
1.60 tb 339: cfg.starttls_proto = PROTO_SMTP;
1.47 inoguchi 340: else if (strcmp(arg, "lmtp") == 0)
1.60 tb 341: cfg.starttls_proto = PROTO_LMTP;
1.47 inoguchi 342: else if (strcmp(arg, "pop3") == 0)
1.60 tb 343: cfg.starttls_proto = PROTO_POP3;
1.47 inoguchi 344: else if (strcmp(arg, "imap") == 0)
1.60 tb 345: cfg.starttls_proto = PROTO_IMAP;
1.47 inoguchi 346: else if (strcmp(arg, "ftp") == 0)
1.60 tb 347: cfg.starttls_proto = PROTO_FTP;
1.47 inoguchi 348: else if (strcmp(arg, "xmpp") == 0)
1.60 tb 349: cfg.starttls_proto = PROTO_XMPP;
1.47 inoguchi 350: else
351: return (1);
352: return (0);
353: }
354:
355: static int
356: s_client_opt_verify(char *arg)
357: {
1.60 tb 358: cfg.verify = SSL_VERIFY_PEER;
1.47 inoguchi 359:
1.60 tb 360: verify_depth = strtonum(arg, 0, INT_MAX, &cfg.errstr);
361: if (cfg.errstr != NULL) {
1.47 inoguchi 362: BIO_printf(bio_err, "invalid argument %s: %s\n",
1.60 tb 363: arg, cfg.errstr);
1.47 inoguchi 364: return (1);
365: }
366: BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
367: return (0);
368: }
369:
370: static int
371: s_client_opt_verify_param(int argc, char **argv, int *argsused)
372: {
373: char **pargs = argv;
374: int pargc = argc;
375: int badarg = 0;
376:
377: if (!args_verify(&pargs, &pargc, &badarg, bio_err,
1.60 tb 378: &cfg.vpm)) {
1.47 inoguchi 379: BIO_printf(bio_err, "unknown option %s\n", *argv);
380: return (1);
381: }
382: if (badarg)
383: return (1);
384:
385: *argsused = argc - pargc;
386: return (0);
387: }
388:
389: static const struct option s_client_options[] = {
390: {
391: .name = "4",
392: .desc = "Use IPv4 only",
393: .type = OPTION_VALUE,
1.60 tb 394: .opt.value = &cfg.af,
1.47 inoguchi 395: .value = AF_INET,
396: },
397: {
398: .name = "6",
399: .desc = "Use IPv6 only",
400: .type = OPTION_VALUE,
1.60 tb 401: .opt.value = &cfg.af,
1.47 inoguchi 402: .value = AF_INET6,
403: },
404: {
405: .name = "alpn",
406: .argname = "protocols",
407: .desc = "Set the advertised protocols for ALPN"
408: " (comma-separated list)",
409: .type = OPTION_ARG,
1.60 tb 410: .opt.arg = &cfg.alpn_in,
1.47 inoguchi 411: },
412: {
413: .name = "bugs",
414: .desc = "Enable various workarounds for buggy implementations",
415: .type = OPTION_FLAG,
1.60 tb 416: .opt.flag = &cfg.bugs,
1.47 inoguchi 417: },
418: {
419: .name = "CAfile",
420: .argname = "file",
421: .desc = "PEM format file of CA certificates",
422: .type = OPTION_ARG,
1.60 tb 423: .opt.arg = &cfg.CAfile,
1.47 inoguchi 424: },
425: {
426: .name = "CApath",
427: .argname = "directory",
428: .desc = "PEM format directory of CA certificates",
429: .type = OPTION_ARG,
1.60 tb 430: .opt.arg = &cfg.CApath,
1.47 inoguchi 431: },
432: {
433: .name = "cert",
434: .argname = "file",
435: .desc = "Certificate file to use, PEM format assumed",
436: .type = OPTION_ARG,
1.60 tb 437: .opt.arg = &cfg.cert_file,
1.47 inoguchi 438: },
439: {
440: .name = "certform",
441: .argname = "fmt",
442: .desc = "Certificate format (PEM or DER) PEM default",
443: .type = OPTION_ARG_FORMAT,
1.60 tb 444: .opt.value = &cfg.cert_format,
1.47 inoguchi 445: },
446: {
447: .name = "cipher",
448: .argname = "cipherlist",
449: .desc = "Preferred cipher to use (see 'openssl ciphers')",
450: .type = OPTION_ARG,
1.60 tb 451: .opt.arg = &cfg.cipher,
1.47 inoguchi 452: },
453: {
454: .name = "connect",
455: .argname = "host:port",
456: .desc = "Who to connect to (default is localhost:4433)",
457: .type = OPTION_ARG,
1.60 tb 458: .opt.arg = &cfg.connect,
1.47 inoguchi 459: },
460: {
461: .name = "crlf",
462: .desc = "Convert LF from terminal into CRLF",
463: .type = OPTION_FLAG,
1.60 tb 464: .opt.flag = &cfg.crlf,
1.47 inoguchi 465: },
466: {
467: .name = "debug",
468: .desc = "Print extensive debugging information",
469: .type = OPTION_FLAG,
1.60 tb 470: .opt.flag = &cfg.debug,
1.47 inoguchi 471: },
1.53 jsing 472: #ifndef OPENSSL_NO_DTLS
473: {
474: .name = "dtls",
475: .desc = "Use any version of DTLS",
476: .type = OPTION_FUNC,
477: .opt.func = s_client_opt_protocol_version_dtls,
478: },
479: #endif
480: #ifndef OPENSSL_NO_DTLS1_2
481: {
482: .name = "dtls1_2",
483: .desc = "Just use DTLSv1.2",
484: .type = OPTION_FUNC,
485: .opt.func = s_client_opt_protocol_version_dtls1_2,
486: },
487: #endif
1.47 inoguchi 488: {
489: .name = "groups",
490: .argname = "list",
491: .desc = "Specify EC groups (colon-separated list)",
492: .type = OPTION_ARG,
1.60 tb 493: .opt.arg = &cfg.groups_in,
1.47 inoguchi 494: },
495: {
496: .name = "host",
497: .argname = "host",
498: .desc = "Use -connect instead",
499: .type = OPTION_ARG,
1.60 tb 500: .opt.arg = &cfg.host,
1.47 inoguchi 501: },
502: {
503: .name = "ign_eof",
504: .desc = "Ignore input EOF (default when -quiet)",
505: .type = OPTION_VALUE,
1.60 tb 506: .opt.value = &cfg.ign_eof,
1.47 inoguchi 507: .value = 1,
508: },
509: {
510: .name = "key",
511: .argname = "file",
512: .desc = "Private key file to use, if not, -cert file is used",
513: .type = OPTION_ARG,
1.60 tb 514: .opt.arg = &cfg.key_file,
1.47 inoguchi 515: },
516: {
517: .name = "keyform",
518: .argname = "fmt",
519: .desc = "Key format (PEM or DER) PEM default",
520: .type = OPTION_ARG_FORMAT,
1.60 tb 521: .opt.value = &cfg.key_format,
1.47 inoguchi 522: },
523: {
524: .name = "keymatexport",
525: .argname = "label",
526: .desc = "Export keying material using label",
527: .type = OPTION_ARG,
1.60 tb 528: .opt.arg = &cfg.keymatexportlabel,
1.47 inoguchi 529: },
530: {
531: .name = "keymatexportlen",
532: .argname = "len",
533: .desc = "Export len bytes of keying material (default 20)",
534: .type = OPTION_ARG_FUNC,
535: .opt.argfunc = s_client_opt_keymatexportlen,
536: },
537: {
538: .name = "legacy_renegotiation",
539: .type = OPTION_DISCARD,
540: },
541: {
542: .name = "legacy_server_connect",
543: .desc = "Allow initial connection to servers that don't support RI",
544: .type = OPTION_VALUE_OR,
1.60 tb 545: .opt.value = &cfg.off,
1.47 inoguchi 546: .value = SSL_OP_LEGACY_SERVER_CONNECT,
547: },
548: {
549: .name = "msg",
550: .desc = "Show all protocol messages with hex dump",
551: .type = OPTION_FLAG,
1.60 tb 552: .opt.flag = &cfg.msg,
1.47 inoguchi 553: },
1.53 jsing 554: #ifndef OPENSSL_NO_DTLS
1.47 inoguchi 555: {
556: .name = "mtu",
557: .argname = "mtu",
558: .desc = "Set the link layer MTU on DTLS connections",
559: .type = OPTION_ARG_FUNC,
560: .opt.argfunc = s_client_opt_mtu,
561: },
562: #endif
563: {
564: .name = "nbio",
565: .desc = "Turn on non-blocking I/O",
566: .type = OPTION_FLAG,
1.60 tb 567: .opt.flag = &cfg.nbio,
1.47 inoguchi 568: },
569: {
570: .name = "nbio_test",
571: .desc = "Test non-blocking I/O",
572: .type = OPTION_FLAG,
1.60 tb 573: .opt.flag = &cfg.nbio_test,
1.47 inoguchi 574: },
575: {
576: .name = "nextprotoneg",
577: .argname = "protocols",
578: .type = OPTION_ARG,
1.60 tb 579: .opt.arg = &cfg.npn_in, /* Ignored. */
1.47 inoguchi 580: },
581: {
582: .name = "no_comp",
583: .type = OPTION_VALUE_OR,
1.60 tb 584: .opt.value = &cfg.off,
1.47 inoguchi 585: .value = SSL_OP_NO_COMPRESSION,
586: },
587: {
588: .name = "no_ign_eof",
589: .desc = "Don't ignore input EOF",
590: .type = OPTION_VALUE,
1.60 tb 591: .opt.value = &cfg.ign_eof,
1.47 inoguchi 592: .value = 0,
593: },
594: {
595: .name = "no_legacy_server_connect",
596: .desc = "Disallow initial connection to servers that don't support RI",
597: .type = OPTION_VALUE_OR,
1.60 tb 598: .opt.value = &cfg.clr,
1.47 inoguchi 599: .value = SSL_OP_LEGACY_SERVER_CONNECT,
600: },
601: {
1.57 jsing 602: .name = "no_servername",
603: .desc = "Do not send a Server Name Indication (SNI) extension",
604: .type = OPTION_FLAG,
1.60 tb 605: .opt.value = &cfg.no_servername,
1.57 jsing 606: },
607: {
1.47 inoguchi 608: .name = "no_ssl2",
609: .type = OPTION_VALUE_OR,
1.60 tb 610: .opt.value = &cfg.off,
1.47 inoguchi 611: .value = SSL_OP_NO_SSLv2,
612: },
613: {
614: .name = "no_ssl3",
615: .type = OPTION_VALUE_OR,
1.60 tb 616: .opt.value = &cfg.off,
1.47 inoguchi 617: .value = SSL_OP_NO_SSLv3,
618: },
619: {
620: .name = "no_ticket",
621: .desc = "Disable use of RFC4507 session ticket support",
622: .type = OPTION_VALUE_OR,
1.60 tb 623: .opt.value = &cfg.off,
1.47 inoguchi 624: .value = SSL_OP_NO_TICKET,
1.62 ! beck 625: },
! 626: {
! 627: .name = "no_tls1",
! 628: .type = OPTION_DISCARD,
! 629: },
! 630: {
! 631: .name = "no_tls1_1",
! 632: .type = OPTION_DISCARD,
1.47 inoguchi 633: },
634: {
635: .name = "no_tls1_2",
636: .desc = "Disable the use of TLSv1.2",
637: .type = OPTION_VALUE_OR,
1.60 tb 638: .opt.value = &cfg.off,
1.47 inoguchi 639: .value = SSL_OP_NO_TLSv1_2,
640: },
641: {
642: .name = "no_tls1_3",
643: .desc = "Disable the use of TLSv1.3",
644: .type = OPTION_VALUE_OR,
1.60 tb 645: .opt.value = &cfg.off,
1.47 inoguchi 646: .value = SSL_OP_NO_TLSv1_3,
647: },
648: {
1.57 jsing 649: .name = "noservername",
650: .type = OPTION_FLAG,
1.60 tb 651: .opt.value = &cfg.no_servername,
1.57 jsing 652: },
653: {
1.47 inoguchi 654: .name = "pass",
655: .argname = "arg",
656: .desc = "Private key file pass phrase source",
657: .type = OPTION_ARG,
1.60 tb 658: .opt.arg = &cfg.passarg,
1.47 inoguchi 659: },
660: {
661: .name = "pause",
662: .desc = "Pause 1 second between each read and write call",
663: .type = OPTION_FLAG,
1.60 tb 664: .opt.flag = &cfg.pause,
1.47 inoguchi 665: },
666: {
667: .name = "peekaboo",
668: .type = OPTION_FLAG,
1.60 tb 669: .opt.flag = &cfg.peekaboo,
1.47 inoguchi 670: },
671: {
672: .name = "port",
673: .argname = "port",
674: .desc = "Use -connect instead",
675: .type = OPTION_ARG_FUNC,
676: .opt.argfunc = s_client_opt_port,
677: },
678: {
679: .name = "prexit",
680: .desc = "Print session information when the program exits",
681: .type = OPTION_FLAG,
1.60 tb 682: .opt.flag = &cfg.prexit,
1.47 inoguchi 683: },
684: {
685: .name = "proxy",
686: .argname = "host:port",
687: .desc = "Connect to http proxy",
688: .type = OPTION_ARG,
1.60 tb 689: .opt.arg = &cfg.proxy,
1.47 inoguchi 690: },
691: {
692: .name = "quiet",
693: .desc = "Inhibit printing of session and certificate info",
694: .type = OPTION_FUNC,
695: .opt.func = s_client_opt_quiet,
696: },
697: {
698: .name = "reconnect",
699: .desc = "Drop and re-make the connection with the same Session-ID",
700: .type = OPTION_VALUE,
1.60 tb 701: .opt.value = &cfg.reconnect,
1.47 inoguchi 702: .value = 5,
703: },
704: {
705: .name = "servername",
706: .argname = "name",
707: .desc = "Set TLS extension servername in ClientHello (SNI)",
708: .type = OPTION_ARG,
1.60 tb 709: .opt.arg = &cfg.servername,
1.47 inoguchi 710: },
711: {
712: .name = "serverpref",
713: .desc = "Use server's cipher preferences",
714: .type = OPTION_VALUE_OR,
1.60 tb 715: .opt.value = &cfg.off,
1.47 inoguchi 716: .value = SSL_OP_CIPHER_SERVER_PREFERENCE,
717: },
718: {
719: .name = "sess_in",
720: .argname = "file",
721: .desc = "File to read TLS session from",
722: .type = OPTION_ARG,
1.60 tb 723: .opt.arg = &cfg.sess_in,
1.47 inoguchi 724: },
725: {
726: .name = "sess_out",
727: .argname = "file",
728: .desc = "File to write TLS session to",
729: .type = OPTION_ARG,
1.60 tb 730: .opt.arg = &cfg.sess_out,
1.47 inoguchi 731: },
732: {
733: .name = "showcerts",
734: .desc = "Show all server certificates in the chain",
735: .type = OPTION_FLAG,
1.60 tb 736: .opt.flag = &cfg.showcerts,
1.47 inoguchi 737: },
738: {
739: .name = "starttls",
740: .argname = "protocol",
741: .desc = "Use the STARTTLS command before starting TLS,\n"
742: "smtp, lmtp, pop3, imap, ftp and xmpp are supported.",
743: .type = OPTION_ARG_FUNC,
744: .opt.argfunc = s_client_opt_starttls,
745: },
746: {
747: .name = "state",
748: .desc = "Print the TLS session states",
749: .type = OPTION_FLAG,
1.60 tb 750: .opt.flag = &cfg.state,
1.47 inoguchi 751: },
752: {
753: .name = "status",
754: .desc = "Send a certificate status request to the server (OCSP)",
755: .type = OPTION_FLAG,
1.60 tb 756: .opt.flag = &cfg.status_req,
1.47 inoguchi 757: },
1.53 jsing 758: #ifndef OPENSSL_NO_DTLS
1.47 inoguchi 759: {
760: .name = "timeout",
761: .desc = "Enable send/receive timeout on DTLS connections",
762: .type = OPTION_FLAG,
1.60 tb 763: .opt.flag = &cfg.enable_timeouts,
1.47 inoguchi 764: },
765: #endif
766: {
767: .name = "tls1_2",
768: .desc = "Just use TLSv1.2",
769: .type = OPTION_FUNC,
770: .opt.func = s_client_opt_protocol_version_tls1_2,
771: },
772: {
773: .name = "tls1_3",
774: .desc = "Just use TLSv1.3",
775: .type = OPTION_FUNC,
776: .opt.func = s_client_opt_protocol_version_tls1_3,
777: },
778: {
779: .name = "tlsextdebug",
780: .desc = "Hex dump of all TLS extensions received",
781: .type = OPTION_FLAG,
1.60 tb 782: .opt.flag = &cfg.tlsextdebug,
1.47 inoguchi 783: },
784: #ifndef OPENSSL_NO_SRTP
785: {
786: .name = "use_srtp",
787: .argname = "profiles",
788: .desc = "Offer SRTP key management with a colon-separated profiles",
789: .type = OPTION_ARG,
1.60 tb 790: .opt.arg = &cfg.srtp_profiles,
1.47 inoguchi 791: },
792: #endif
793: {
794: .name = "verify",
795: .argname = "depth",
796: .desc = "Turn on peer certificate verification, with a max of depth",
797: .type = OPTION_ARG_FUNC,
798: .opt.argfunc = s_client_opt_verify,
799: },
800: {
801: .name = "verify_return_error",
802: .desc = "Return verification error",
803: .type = OPTION_FLAG,
804: .opt.flag = &verify_return_error,
805: },
806: {
807: .name = "xmpphost",
808: .argname = "host",
809: .desc = "Connect to this virtual host on the xmpp server",
810: .type = OPTION_ARG,
1.60 tb 811: .opt.arg = &cfg.xmpphost,
1.47 inoguchi 812: },
813: {
814: .name = NULL,
815: .desc = "",
816: .type = OPTION_ARGV_FUNC,
817: .opt.argvfunc = s_client_opt_verify_param,
818: },
819: { NULL },
820: };
1.1 jsing 821:
822: static void
823: sc_usage(void)
824: {
1.47 inoguchi 825: fprintf(stderr, "usage: s_client "
826: "[-4 | -6] [-alpn protocols] [-bugs] [-CAfile file]\n"
827: " [-CApath directory] [-cert file] [-certform der | pem] [-check_ss_sig]\n"
828: " [-cipher cipherlist] [-connect host[:port]] [-crl_check]\n"
1.61 beck 829: " [-crl_check_all] [-crlf] [-debug] [-dtls] [-dtls1_2] [-extended_crl]\n"
1.47 inoguchi 830: " [-groups list] [-host host] [-ign_eof] [-ignore_critical]\n"
831: " [-issuer_checks] [-key keyfile] [-keyform der | pem]\n"
832: " [-keymatexport label] [-keymatexportlen len] [-legacy_server_connect]\n"
833: " [-msg] [-mtu mtu] [-nbio] [-nbio_test] [-no_comp] [-no_ign_eof]\n"
1.61 beck 834: " [-no_legacy_server_connect] [-no_ticket] \n"
1.47 inoguchi 835: " [-no_tls1_2] [-no_tls1_3] [-pass arg] [-pause] [-policy_check]\n"
836: " [-port port] [-prexit] [-proxy host:port] [-quiet] [-reconnect]\n"
837: " [-servername name] [-serverpref] [-sess_in file] [-sess_out file]\n"
838: " [-showcerts] [-starttls protocol] [-state] [-status] [-timeout]\n"
1.61 beck 839: " [-tls1_2] [-tls1_3] [-tlsextdebug]\n"
1.47 inoguchi 840: " [-use_srtp profiles] [-verify depth] [-verify_return_error]\n"
841: " [-x509_strict] [-xmpphost host]\n");
842: fprintf(stderr, "\n");
843: options_usage(s_client_options);
844: fprintf(stderr, "\n");
1.1 jsing 845: }
846:
847: int
848: s_client_main(int argc, char **argv)
849: {
850: SSL *con = NULL;
1.47 inoguchi 851: int s, k, p = 0, pending = 0;
1.39 beck 852: char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL, *pbuf = NULL;
1.1 jsing 853: int cbuf_len, cbuf_off;
854: int sbuf_len, sbuf_off;
855: int full_log = 1;
1.57 jsing 856: const char *servername;
1.47 inoguchi 857: char *pass = NULL;
1.1 jsing 858: X509 *cert = NULL;
859: EVP_PKEY *key = NULL;
1.47 inoguchi 860: int badop = 0;
1.1 jsing 861: int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending;
862: SSL_CTX *ctx = NULL;
1.47 inoguchi 863: int ret = 1, in_init = 1, i;
1.50 inoguchi 864: BIO *bio_c_out = NULL;
1.1 jsing 865: BIO *sbio;
866: int mbuf_len = 0;
1.9 deraadt 867: struct timeval timeout;
1.33 jsing 868: tlsextctx tlsextcbp = {NULL, 0};
1.45 deraadt 869: struct sockaddr_storage peer;
1.1 jsing 870: int peerlen = sizeof(peer);
1.21 doug 871:
1.59 joshua 872: if (pledge("stdio cpath wpath rpath inet dns tty", NULL) == -1) {
873: perror("pledge");
874: exit(1);
1.21 doug 875: }
1.1 jsing 876:
1.60 tb 877: memset(&cfg, 0, sizeof(cfg));
878: cfg.af = AF_UNSPEC;
879: cfg.cert_format = FORMAT_PEM;
880: cfg.host = SSL_HOST_NAME;
881: cfg.key_format = FORMAT_PEM;
882: cfg.keymatexportlen = 20;
883: cfg.meth = TLS_client_method();
884: cfg.port = PORT_STR;
885: cfg.socket_type = SOCK_STREAM;
886: cfg.starttls_proto = PROTO_OFF;
887: cfg.verify = SSL_VERIFY_NONE;
1.1 jsing 888:
889: if (((cbuf = malloc(BUFSIZZ)) == NULL) ||
890: ((sbuf = malloc(BUFSIZZ)) == NULL) ||
1.39 beck 891: ((pbuf = malloc(BUFSIZZ)) == NULL) ||
1.1 jsing 892: ((mbuf = malloc(BUFSIZZ + 1)) == NULL)) { /* NUL byte */
893: BIO_printf(bio_err, "out of memory\n");
894: goto end;
895: }
896: verify_depth = 0;
897:
1.47 inoguchi 898: if (options_parse(argc, argv, s_client_options, NULL, NULL) != 0) {
899: badop = 1;
900: goto bad;
1.1 jsing 901: }
1.60 tb 902: if (cfg.proxy != NULL) {
903: if (!extract_host_port(cfg.proxy,
904: &cfg.host, NULL, &cfg.port))
1.12 bluhm 905: goto bad;
1.60 tb 906: if (cfg.connect == NULL)
907: cfg.connect = SSL_HOST_NAME;
908: } else if (cfg.connect != NULL) {
909: if (!extract_host_port(cfg.connect,
910: &cfg.host, NULL, &cfg.port))
1.12 bluhm 911: goto bad;
912: }
1.1 jsing 913: if (badop) {
1.35 jsing 914: bad:
1.60 tb 915: if (cfg.errstr == NULL)
1.1 jsing 916: sc_usage();
917: goto end;
918: }
919:
1.60 tb 920: if (!app_passwd(bio_err, cfg.passarg, NULL, &pass, NULL)) {
1.1 jsing 921: BIO_printf(bio_err, "Error getting password\n");
922: goto end;
923: }
1.60 tb 924: if (cfg.key_file == NULL)
925: cfg.key_file = cfg.cert_file;
1.1 jsing 926:
927:
1.60 tb 928: if (cfg.key_file) {
1.1 jsing 929:
1.60 tb 930: key = load_key(bio_err, cfg.key_file,
931: cfg.key_format, 0, pass,
1.1 jsing 932: "client certificate private key file");
933: if (!key) {
934: ERR_print_errors(bio_err);
935: goto end;
936: }
937: }
1.60 tb 938: if (cfg.cert_file) {
939: cert = load_cert(bio_err, cfg.cert_file,
940: cfg.cert_format,
1.19 bcook 941: NULL, "client certificate file");
1.1 jsing 942:
943: if (!cert) {
944: ERR_print_errors(bio_err);
945: goto end;
946: }
947: }
1.60 tb 948: if (cfg.quiet && !cfg.debug &&
949: !cfg.msg) {
1.50 inoguchi 950: if ((bio_c_out = BIO_new(BIO_s_null())) == NULL)
951: goto end;
952: } else {
953: if ((bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL)
954: goto end;
1.1 jsing 955: }
956:
1.60 tb 957: ctx = SSL_CTX_new(cfg.meth);
1.1 jsing 958: if (ctx == NULL) {
959: ERR_print_errors(bio_err);
960: goto end;
961: }
1.46 tb 962:
963: SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY);
964:
1.60 tb 965: if (cfg.vpm)
966: SSL_CTX_set1_param(ctx, cfg.vpm);
1.42 jsing 967:
1.60 tb 968: if (!SSL_CTX_set_min_proto_version(ctx, cfg.min_version))
1.42 jsing 969: goto end;
1.60 tb 970: if (!SSL_CTX_set_max_proto_version(ctx, cfg.max_version))
1.42 jsing 971: goto end;
1.1 jsing 972:
973: #ifndef OPENSSL_NO_SRTP
1.60 tb 974: if (cfg.srtp_profiles != NULL)
975: SSL_CTX_set_tlsext_use_srtp(ctx, cfg.srtp_profiles);
1.1 jsing 976: #endif
1.60 tb 977: if (cfg.bugs)
978: SSL_CTX_set_options(ctx, SSL_OP_ALL | cfg.off);
1.1 jsing 979: else
1.60 tb 980: SSL_CTX_set_options(ctx, cfg.off);
1.1 jsing 981:
1.60 tb 982: if (cfg.clr)
983: SSL_CTX_clear_options(ctx, cfg.clr);
1.1 jsing 984:
1.60 tb 985: if (cfg.alpn_in) {
1.10 jsing 986: unsigned short alpn_len;
1.49 inoguchi 987: unsigned char *alpn;
1.10 jsing 988:
1.60 tb 989: alpn = next_protos_parse(&alpn_len, cfg.alpn_in);
1.10 jsing 990: if (alpn == NULL) {
991: BIO_printf(bio_err, "Error parsing -alpn argument\n");
992: goto end;
993: }
994: SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len);
995: free(alpn);
1.31 jsing 996: }
1.60 tb 997: if (cfg.groups_in != NULL) {
998: if (SSL_CTX_set1_groups_list(ctx, cfg.groups_in) != 1) {
1.31 jsing 999: BIO_printf(bio_err, "Failed to set groups '%s'\n",
1.60 tb 1000: cfg.groups_in);
1.31 jsing 1001: goto end;
1002: }
1.10 jsing 1003: }
1.1 jsing 1004:
1.60 tb 1005: if (cfg.state)
1.1 jsing 1006: SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
1.60 tb 1007: if (cfg.cipher != NULL)
1008: if (!SSL_CTX_set_cipher_list(ctx, cfg.cipher)) {
1.1 jsing 1009: BIO_printf(bio_err, "error setting cipher list\n");
1010: ERR_print_errors(bio_err);
1011: goto end;
1012: }
1013:
1.60 tb 1014: SSL_CTX_set_verify(ctx, cfg.verify, verify_callback);
1.1 jsing 1015: if (!set_cert_key_stuff(ctx, cert, key))
1016: goto end;
1017:
1.60 tb 1018: if ((cfg.CAfile || cfg.CApath)
1019: && !SSL_CTX_load_verify_locations(ctx, cfg.CAfile,
1020: cfg.CApath))
1.1 jsing 1021: ERR_print_errors(bio_err);
1.28 bcook 1022:
1023: if (!SSL_CTX_set_default_verify_paths(ctx))
1024: ERR_print_errors(bio_err);
1025:
1.1 jsing 1026: con = SSL_new(ctx);
1.60 tb 1027: if (cfg.sess_in) {
1.1 jsing 1028: SSL_SESSION *sess;
1.60 tb 1029: BIO *stmp = BIO_new_file(cfg.sess_in, "r");
1.1 jsing 1030: if (!stmp) {
1031: BIO_printf(bio_err, "Can't open session file %s\n",
1.60 tb 1032: cfg.sess_in);
1.1 jsing 1033: ERR_print_errors(bio_err);
1034: goto end;
1035: }
1036: sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
1037: BIO_free(stmp);
1038: if (!sess) {
1039: BIO_printf(bio_err, "Can't open session file %s\n",
1.60 tb 1040: cfg.sess_in);
1.1 jsing 1041: ERR_print_errors(bio_err);
1042: goto end;
1043: }
1044: SSL_set_session(con, sess);
1045: SSL_SESSION_free(sess);
1046: }
1.57 jsing 1047:
1048: /* Attempt to opportunistically use the host name for SNI. */
1.60 tb 1049: servername = cfg.servername;
1.57 jsing 1050: if (servername == NULL)
1.60 tb 1051: servername = cfg.host;
1.57 jsing 1052:
1.60 tb 1053: if (!cfg.no_servername && servername != NULL &&
1.57 jsing 1054: !SSL_set_tlsext_host_name(con, servername)) {
1055: long ssl_err = ERR_peek_error();
1056:
1.60 tb 1057: if (cfg.servername != NULL ||
1.57 jsing 1058: ERR_GET_LIB(ssl_err) != ERR_LIB_SSL ||
1059: ERR_GET_REASON(ssl_err) != SSL_R_SSL3_EXT_INVALID_SERVERNAME) {
1.49 inoguchi 1060: BIO_printf(bio_err,
1061: "Unable to set TLS servername extension.\n");
1.1 jsing 1062: ERR_print_errors(bio_err);
1063: goto end;
1064: }
1.57 jsing 1065: servername = NULL;
1066: ERR_clear_error();
1067: }
1.60 tb 1068: if (!cfg.no_servername && servername != NULL) {
1.57 jsing 1069: tlsextcbp.biodebug = bio_err;
1070: SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
1071: SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
1.1 jsing 1072: }
1073:
1.49 inoguchi 1074: re_start:
1.1 jsing 1075:
1.60 tb 1076: if (init_client(&s, cfg.host, cfg.port,
1077: cfg.socket_type, cfg.af) == 0) {
1.1 jsing 1078: BIO_printf(bio_err, "connect:errno=%d\n", errno);
1079: goto end;
1080: }
1081: BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);
1082:
1.60 tb 1083: if (cfg.nbio) {
1084: if (!cfg.quiet)
1.3 bcook 1085: BIO_printf(bio_c_out, "turning on non blocking io\n");
1086: if (!BIO_socket_nbio(s, 1)) {
1.1 jsing 1087: ERR_print_errors(bio_err);
1088: goto end;
1089: }
1090: }
1.60 tb 1091: if (cfg.pause & 0x01)
1.1 jsing 1092: SSL_set_debug(con, 1);
1093:
1.53 jsing 1094: if (SSL_is_dtls(con)) {
1.1 jsing 1095: sbio = BIO_new_dgram(s, BIO_NOCLOSE);
1.45 deraadt 1096: if (getsockname(s, (struct sockaddr *)&peer,
1097: (void *)&peerlen) == -1) {
1.1 jsing 1098: BIO_printf(bio_err, "getsockname:errno=%d\n",
1099: errno);
1100: shutdown(s, SHUT_RD);
1101: close(s);
1102: goto end;
1103: }
1104: (void) BIO_ctrl_set_connected(sbio, 1, &peer);
1105:
1.60 tb 1106: if (cfg.enable_timeouts) {
1.1 jsing 1107: timeout.tv_sec = 0;
1108: timeout.tv_usec = DGRAM_RCV_TIMEOUT;
1.49 inoguchi 1109: BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0,
1110: &timeout);
1.1 jsing 1111:
1112: timeout.tv_sec = 0;
1113: timeout.tv_usec = DGRAM_SND_TIMEOUT;
1.49 inoguchi 1114: BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0,
1115: &timeout);
1.1 jsing 1116: }
1.60 tb 1117: if (cfg.socket_mtu > 28) {
1.1 jsing 1118: SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
1.60 tb 1119: SSL_set_mtu(con, cfg.socket_mtu - 28);
1.1 jsing 1120: } else
1121: /* want to do MTU discovery */
1122: BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
1123: } else
1124: sbio = BIO_new_socket(s, BIO_NOCLOSE);
1125:
1.60 tb 1126: if (cfg.nbio_test) {
1.1 jsing 1127: BIO *test;
1128:
1129: test = BIO_new(BIO_f_nbio_test());
1130: sbio = BIO_push(test, sbio);
1131: }
1.60 tb 1132: if (cfg.debug) {
1.1 jsing 1133: SSL_set_debug(con, 1);
1134: BIO_set_callback(sbio, bio_dump_callback);
1135: BIO_set_callback_arg(sbio, (char *) bio_c_out);
1136: }
1.60 tb 1137: if (cfg.msg) {
1.1 jsing 1138: SSL_set_msg_callback(con, msg_cb);
1139: SSL_set_msg_callback_arg(con, bio_c_out);
1140: }
1.60 tb 1141: if (cfg.tlsextdebug) {
1.1 jsing 1142: SSL_set_tlsext_debug_callback(con, tlsext_cb);
1143: SSL_set_tlsext_debug_arg(con, bio_c_out);
1144: }
1.60 tb 1145: if (cfg.status_req) {
1.1 jsing 1146: SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp);
1147: SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb);
1148: SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out);
1149: }
1150:
1151: SSL_set_bio(con, sbio, sbio);
1152: SSL_set_connect_state(con);
1153:
1154: /* ok, lets connect */
1155: read_tty = 1;
1156: write_tty = 0;
1157: tty_on = 0;
1158: read_ssl = 1;
1159: write_ssl = 1;
1160:
1161: cbuf_len = 0;
1162: cbuf_off = 0;
1163: sbuf_len = 0;
1164: sbuf_off = 0;
1165:
1166: /* This is an ugly hack that does a lot of assumptions */
1167: /*
1168: * We do have to handle multi-line responses which may come in a
1169: * single packet or not. We therefore have to use BIO_gets() which
1170: * does need a buffering BIO. So during the initial chitchat we do
1171: * push a buffering BIO into the chain that is removed again later on
1172: * to not disturb the rest of the s_client operation.
1173: */
1.60 tb 1174: if (cfg.starttls_proto == PROTO_SMTP ||
1175: cfg.starttls_proto == PROTO_LMTP) {
1.1 jsing 1176: int foundit = 0;
1177: BIO *fbio = BIO_new(BIO_f_buffer());
1178: BIO_push(fbio, sbio);
1179: /* wait for multi-line response to end from SMTP */
1180: do {
1181: mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
1182: }
1183: while (mbuf_len > 3 && mbuf[3] == '-');
1184: /* STARTTLS command requires EHLO... */
1185: BIO_printf(fbio, "%cHLO openssl.client.net\r\n",
1.60 tb 1186: cfg.starttls_proto == PROTO_SMTP ? 'E' : 'L');
1.1 jsing 1187: (void) BIO_flush(fbio);
1188: /* wait for multi-line response to end EHLO SMTP response */
1189: do {
1190: mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
1191: if (strstr(mbuf, "STARTTLS"))
1192: foundit = 1;
1193: }
1194: while (mbuf_len > 3 && mbuf[3] == '-');
1195: (void) BIO_flush(fbio);
1196: BIO_pop(fbio);
1197: BIO_free(fbio);
1198: if (!foundit)
1199: BIO_printf(bio_err,
1.36 jmc 1200: "didn't find starttls in server response,"
1.1 jsing 1201: " try anyway...\n");
1202: BIO_printf(sbio, "STARTTLS\r\n");
1203: BIO_read(sbio, sbuf, BUFSIZZ);
1.60 tb 1204: } else if (cfg.starttls_proto == PROTO_POP3) {
1.1 jsing 1205: mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
1206: if (mbuf_len == -1) {
1207: BIO_printf(bio_err, "BIO_read failed\n");
1208: goto end;
1209: }
1210: BIO_printf(sbio, "STLS\r\n");
1211: BIO_read(sbio, sbuf, BUFSIZZ);
1.60 tb 1212: } else if (cfg.starttls_proto == PROTO_IMAP) {
1.1 jsing 1213: int foundit = 0;
1214: BIO *fbio = BIO_new(BIO_f_buffer());
1215: BIO_push(fbio, sbio);
1216: BIO_gets(fbio, mbuf, BUFSIZZ);
1217: /* STARTTLS command requires CAPABILITY... */
1218: BIO_printf(fbio, ". CAPABILITY\r\n");
1219: (void) BIO_flush(fbio);
1220: /* wait for multi-line CAPABILITY response */
1221: do {
1222: mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
1223: if (strstr(mbuf, "STARTTLS"))
1224: foundit = 1;
1225: }
1226: while (mbuf_len > 3 && mbuf[0] != '.');
1227: (void) BIO_flush(fbio);
1228: BIO_pop(fbio);
1229: BIO_free(fbio);
1230: if (!foundit)
1231: BIO_printf(bio_err,
1.37 tb 1232: "didn't find STARTTLS in server response,"
1.1 jsing 1233: " try anyway...\n");
1234: BIO_printf(sbio, ". STARTTLS\r\n");
1235: BIO_read(sbio, sbuf, BUFSIZZ);
1.60 tb 1236: } else if (cfg.starttls_proto == PROTO_FTP) {
1.1 jsing 1237: BIO *fbio = BIO_new(BIO_f_buffer());
1238: BIO_push(fbio, sbio);
1239: /* wait for multi-line response to end from FTP */
1240: do {
1241: mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
1242: }
1243: while (mbuf_len > 3 && mbuf[3] == '-');
1244: (void) BIO_flush(fbio);
1245: BIO_pop(fbio);
1246: BIO_free(fbio);
1247: BIO_printf(sbio, "AUTH TLS\r\n");
1248: BIO_read(sbio, sbuf, BUFSIZZ);
1.60 tb 1249: } else if (cfg.starttls_proto == PROTO_XMPP) {
1.1 jsing 1250: int seen = 0;
1251: BIO_printf(sbio, "<stream:stream "
1252: "xmlns:stream='http://etherx.jabber.org/streams' "
1.49 inoguchi 1253: "xmlns='jabber:client' to='%s' version='1.0'>",
1.60 tb 1254: cfg.xmpphost ?
1255: cfg.xmpphost : cfg.host);
1.1 jsing 1256: seen = BIO_read(sbio, mbuf, BUFSIZZ);
1.15 landry 1257:
1258: if (seen <= 0)
1259: goto shut;
1260:
1.1 jsing 1261: mbuf[seen] = 0;
1.15 landry 1262: while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'") &&
1263: !strstr(mbuf, "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"")) {
1264: seen = BIO_read(sbio, mbuf, BUFSIZZ);
1265:
1266: if (seen <= 0)
1.1 jsing 1267: goto shut;
1.15 landry 1268:
1.1 jsing 1269: mbuf[seen] = 0;
1270: }
1.49 inoguchi 1271: BIO_printf(sbio,
1272: "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
1.1 jsing 1273: seen = BIO_read(sbio, sbuf, BUFSIZZ);
1274: sbuf[seen] = 0;
1275: if (!strstr(sbuf, "<proceed"))
1276: goto shut;
1277: mbuf[0] = 0;
1.60 tb 1278: } else if (cfg.proxy != NULL) {
1.49 inoguchi 1279: BIO_printf(sbio, "CONNECT %s HTTP/1.0\r\n\r\n",
1.60 tb 1280: cfg.connect);
1.12 bluhm 1281: mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
1282: if (mbuf_len == -1) {
1283: BIO_printf(bio_err, "BIO_read failed\n");
1284: goto end;
1285: }
1.1 jsing 1286: }
1287: for (;;) {
1.9 deraadt 1288: struct pollfd pfd[3]; /* stdin, stdout, socket */
1289: int ptimeout = -1;
1.1 jsing 1290:
1.53 jsing 1291: if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout))
1.49 inoguchi 1292: ptimeout = timeout.tv_sec * 1000 +
1293: timeout.tv_usec / 1000;
1.1 jsing 1294:
1295: if (SSL_in_init(con) && !SSL_total_renegotiations(con)) {
1296: in_init = 1;
1297: tty_on = 0;
1298: } else {
1299: tty_on = 1;
1300: if (in_init) {
1301: in_init = 0;
1.60 tb 1302: if (cfg.sess_out) {
1.49 inoguchi 1303: BIO *stmp = BIO_new_file(
1.60 tb 1304: cfg.sess_out, "w");
1.1 jsing 1305: if (stmp) {
1.49 inoguchi 1306: PEM_write_bio_SSL_SESSION(stmp,
1307: SSL_get_session(con));
1.1 jsing 1308: BIO_free(stmp);
1309: } else
1.49 inoguchi 1310: BIO_printf(bio_err,
1311: "Error writing session file %s\n",
1.60 tb 1312: cfg.sess_out);
1.1 jsing 1313: }
1314: print_stuff(bio_c_out, con, full_log);
1315: if (full_log > 0)
1316: full_log--;
1317:
1.60 tb 1318: if (cfg.starttls_proto) {
1.1 jsing 1319: BIO_write(bio_err, mbuf, mbuf_len);
1320: /* We don't need to know any more */
1.60 tb 1321: cfg.starttls_proto = PROTO_OFF;
1.1 jsing 1322: }
1.60 tb 1323: if (cfg.reconnect) {
1324: cfg.reconnect--;
1.49 inoguchi 1325: BIO_printf(bio_c_out,
1326: "drop connection and then reconnect\n");
1.1 jsing 1327: SSL_shutdown(con);
1328: SSL_set_connect_state(con);
1329: shutdown(SSL_get_fd(con), SHUT_RD);
1330: close(SSL_get_fd(con));
1331: goto re_start;
1332: }
1333: }
1334: }
1335:
1336: ssl_pending = read_ssl && SSL_pending(con);
1337:
1.9 deraadt 1338: pfd[0].fd = -1;
1339: pfd[1].fd = -1;
1.1 jsing 1340: if (!ssl_pending) {
1341: if (tty_on) {
1.9 deraadt 1342: if (read_tty) {
1343: pfd[0].fd = fileno(stdin);
1344: pfd[0].events = POLLIN;
1345: }
1346: if (write_tty) {
1347: pfd[1].fd = fileno(stdout);
1348: pfd[1].events = POLLOUT;
1349: }
1.1 jsing 1350: }
1.9 deraadt 1351:
1352: pfd[2].fd = SSL_get_fd(con);
1353: pfd[2].events = 0;
1.1 jsing 1354: if (read_ssl)
1.9 deraadt 1355: pfd[2].events |= POLLIN;
1.1 jsing 1356: if (write_ssl)
1.9 deraadt 1357: pfd[2].events |= POLLOUT;
1358:
1.1 jsing 1359: /* printf("mode tty(%d %d%d) ssl(%d%d)\n",
1360: tty_on,read_tty,write_tty,read_ssl,write_ssl);*/
1361:
1.9 deraadt 1362: i = poll(pfd, 3, ptimeout);
1.38 deraadt 1363: if (i == -1) {
1.1 jsing 1364: BIO_printf(bio_err, "bad select %d\n",
1365: errno);
1366: goto shut;
1367: /* goto end; */
1368: }
1369: }
1.53 jsing 1370: if (SSL_is_dtls(con) &&
1371: DTLSv1_handle_timeout(con) > 0)
1.1 jsing 1372: BIO_printf(bio_err, "TIMEOUT occured\n");
1.49 inoguchi 1373: if (!ssl_pending &&
1374: (pfd[2].revents & (POLLOUT|POLLERR|POLLNVAL))) {
1.9 deraadt 1375: if (pfd[2].revents & (POLLERR|POLLNVAL)) {
1376: BIO_printf(bio_err, "poll error");
1377: goto shut;
1378: }
1.1 jsing 1379: k = SSL_write(con, &(cbuf[cbuf_off]),
1380: (unsigned int) cbuf_len);
1381: switch (SSL_get_error(con, k)) {
1382: case SSL_ERROR_NONE:
1383: cbuf_off += k;
1384: cbuf_len -= k;
1385: if (k <= 0)
1386: goto end;
1387: /* we have done a write(con,NULL,0); */
1388: if (cbuf_len <= 0) {
1389: read_tty = 1;
1390: write_ssl = 0;
1391: } else { /* if (cbuf_len > 0) */
1392: read_tty = 0;
1393: write_ssl = 1;
1394: }
1395: break;
1396: case SSL_ERROR_WANT_WRITE:
1397: BIO_printf(bio_c_out, "write W BLOCK\n");
1398: write_ssl = 1;
1399: read_tty = 0;
1400: break;
1401: case SSL_ERROR_WANT_READ:
1402: BIO_printf(bio_c_out, "write R BLOCK\n");
1403: write_tty = 0;
1404: read_ssl = 1;
1405: write_ssl = 0;
1406: break;
1407: case SSL_ERROR_WANT_X509_LOOKUP:
1408: BIO_printf(bio_c_out, "write X BLOCK\n");
1409: break;
1410: case SSL_ERROR_ZERO_RETURN:
1411: if (cbuf_len != 0) {
1412: BIO_printf(bio_c_out, "shutdown\n");
1413: ret = 0;
1414: goto shut;
1415: } else {
1416: read_tty = 1;
1417: write_ssl = 0;
1418: break;
1419: }
1420:
1421: case SSL_ERROR_SYSCALL:
1422: if ((k != 0) || (cbuf_len != 0)) {
1423: BIO_printf(bio_err, "write:errno=%d\n",
1424: errno);
1425: goto shut;
1426: } else {
1427: read_tty = 1;
1428: write_ssl = 0;
1429: }
1430: break;
1431: case SSL_ERROR_SSL:
1432: ERR_print_errors(bio_err);
1433: goto shut;
1434: }
1.9 deraadt 1435: } else if (!ssl_pending &&
1436: (pfd[1].revents & (POLLOUT|POLLERR|POLLNVAL))) {
1437: if (pfd[1].revents & (POLLERR|POLLNVAL)) {
1438: BIO_printf(bio_err, "poll error");
1439: goto shut;
1440: }
1.1 jsing 1441: i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len);
1442:
1443: if (i <= 0) {
1444: BIO_printf(bio_c_out, "DONE\n");
1445: ret = 0;
1446: goto shut;
1447: /* goto end; */
1448: }
1449: sbuf_len -= i;
1450: sbuf_off += i;
1451: if (sbuf_len <= 0) {
1452: read_ssl = 1;
1453: write_tty = 0;
1454: }
1.9 deraadt 1455: } else if (ssl_pending || (pfd[2].revents & (POLLIN|POLLHUP))) {
1.1 jsing 1456: #ifdef RENEG
1457: {
1458: static int iiii;
1459: if (++iiii == 52) {
1460: SSL_renegotiate(con);
1461: iiii = 0;
1462: }
1463: }
1464: #endif
1.60 tb 1465: if (cfg.peekaboo) {
1.40 jsing 1466: k = p = SSL_peek(con, pbuf, 1024 /* BUFSIZZ */ );
1.41 beck 1467: pending = SSL_pending(con);
1.40 jsing 1468: if (SSL_get_error(con, p) == SSL_ERROR_NONE) {
1.39 beck 1469: if (p <= 0)
1470: goto end;
1471:
1.40 jsing 1472: k = SSL_read(con, sbuf, p);
1.39 beck 1473: }
1.40 jsing 1474: } else {
1475: k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ );
1.39 beck 1476: }
1.1 jsing 1477:
1478: switch (SSL_get_error(con, k)) {
1479: case SSL_ERROR_NONE:
1480: if (k <= 0)
1481: goto end;
1482: sbuf_off = 0;
1483: sbuf_len = k;
1.60 tb 1484: if (cfg.peekaboo) {
1.41 beck 1485: if (p != pending) {
1486: ret = -1;
1487: BIO_printf(bio_err,
1.49 inoguchi 1488: "peeked %d but pending %d!\n",
1489: p, pending);
1.41 beck 1490: goto shut;
1491: }
1.39 beck 1492: if (k < p) {
1493: ret = -1;
1494: BIO_printf(bio_err,
1495: "read less than peek!\n");
1496: goto shut;
1497: }
1.49 inoguchi 1498: if (p > 0 &&
1499: (memcmp(sbuf, pbuf, p) != 0)) {
1.39 beck 1500: ret = -1;
1501: BIO_printf(bio_err,
1502: "peek of %d different from read of %d!\n",
1503: p, k);
1504: goto shut;
1505: }
1506: }
1.1 jsing 1507: read_ssl = 0;
1508: write_tty = 1;
1509: break;
1510: case SSL_ERROR_WANT_WRITE:
1511: BIO_printf(bio_c_out, "read W BLOCK\n");
1512: write_ssl = 1;
1513: read_tty = 0;
1514: break;
1515: case SSL_ERROR_WANT_READ:
1516: BIO_printf(bio_c_out, "read R BLOCK\n");
1517: write_tty = 0;
1518: read_ssl = 1;
1519: if ((read_tty == 0) && (write_ssl == 0))
1520: write_ssl = 1;
1521: break;
1522: case SSL_ERROR_WANT_X509_LOOKUP:
1523: BIO_printf(bio_c_out, "read X BLOCK\n");
1524: break;
1525: case SSL_ERROR_SYSCALL:
1526: ret = errno;
1527: BIO_printf(bio_err, "read:errno=%d\n", ret);
1528: goto shut;
1529: case SSL_ERROR_ZERO_RETURN:
1530: BIO_printf(bio_c_out, "closed\n");
1531: ret = 0;
1532: goto shut;
1533: case SSL_ERROR_SSL:
1534: ERR_print_errors(bio_err);
1535: goto shut;
1536: /* break; */
1537: }
1.9 deraadt 1538: } else if (pfd[0].revents) {
1539: if (pfd[0].revents & (POLLERR|POLLNVAL)) {
1540: BIO_printf(bio_err, "poll error");
1541: goto shut;
1542: }
1.60 tb 1543: if (cfg.crlf) {
1.1 jsing 1544: int j, lf_num;
1545:
1546: i = read(fileno(stdin), cbuf, BUFSIZZ / 2);
1547: lf_num = 0;
1548: /* both loops are skipped when i <= 0 */
1549: for (j = 0; j < i; j++)
1550: if (cbuf[j] == '\n')
1551: lf_num++;
1552: for (j = i - 1; j >= 0; j--) {
1553: cbuf[j + lf_num] = cbuf[j];
1554: if (cbuf[j] == '\n') {
1555: lf_num--;
1556: i++;
1557: cbuf[j + lf_num] = '\r';
1558: }
1559: }
1560: assert(lf_num == 0);
1561: } else
1562: i = read(fileno(stdin), cbuf, BUFSIZZ);
1563:
1.60 tb 1564: if ((!cfg.ign_eof) &&
1.49 inoguchi 1565: ((i <= 0) || (cbuf[0] == 'Q'))) {
1.1 jsing 1566: BIO_printf(bio_err, "DONE\n");
1567: ret = 0;
1568: goto shut;
1569: }
1.60 tb 1570: if ((!cfg.ign_eof) && (cbuf[0] == 'R')) {
1.1 jsing 1571: BIO_printf(bio_err, "RENEGOTIATING\n");
1572: SSL_renegotiate(con);
1573: cbuf_len = 0;
1574: } else {
1575: cbuf_len = i;
1576: cbuf_off = 0;
1577: }
1578:
1579: write_ssl = 1;
1580: read_tty = 0;
1581: }
1582: }
1583:
1584: ret = 0;
1.35 jsing 1585: shut:
1.1 jsing 1586: if (in_init)
1587: print_stuff(bio_c_out, con, full_log);
1588: SSL_shutdown(con);
1589: shutdown(SSL_get_fd(con), SHUT_RD);
1590: close(SSL_get_fd(con));
1.35 jsing 1591: end:
1.1 jsing 1592: if (con != NULL) {
1.60 tb 1593: if (cfg.prexit != 0)
1.1 jsing 1594: print_stuff(bio_c_out, con, 1);
1595: SSL_free(con);
1596: }
1.34 jsing 1597: SSL_CTX_free(ctx);
1598: X509_free(cert);
1599: EVP_PKEY_free(key);
1.1 jsing 1600: free(pass);
1.60 tb 1601: X509_VERIFY_PARAM_free(cfg.vpm);
1.32 deraadt 1602: freezero(cbuf, BUFSIZZ);
1603: freezero(sbuf, BUFSIZZ);
1.52 tb 1604: freezero(pbuf, BUFSIZZ);
1.32 deraadt 1605: freezero(mbuf, BUFSIZZ);
1.50 inoguchi 1606: BIO_free(bio_c_out);
1.1 jsing 1607:
1608: return (ret);
1609: }
1610:
1611: static void
1.51 inoguchi 1612: print_stuff(BIO *bio, SSL *s, int full)
1.1 jsing 1613: {
1614: X509 *peer = NULL;
1615: char *p;
1616: static const char *space = " ";
1617: char buf[BUFSIZ];
1.51 inoguchi 1618: STACK_OF(X509) *sk;
1619: STACK_OF(X509_NAME) *sk2;
1.1 jsing 1620: const SSL_CIPHER *c;
1621: X509_NAME *xn;
1622: int j, i;
1623: unsigned char *exportedkeymat;
1624:
1625: if (full) {
1626: int got_a_chain = 0;
1627:
1628: sk = SSL_get_peer_cert_chain(s);
1629: if (sk != NULL) {
1630: got_a_chain = 1; /* we don't have it for SSL2
1631: * (yet) */
1632:
1633: BIO_printf(bio, "---\nCertificate chain\n");
1634: for (i = 0; i < sk_X509_num(sk); i++) {
1635: X509_NAME_oneline(X509_get_subject_name(
1636: sk_X509_value(sk, i)), buf, sizeof buf);
1637: BIO_printf(bio, "%2d s:%s\n", i, buf);
1638: X509_NAME_oneline(X509_get_issuer_name(
1639: sk_X509_value(sk, i)), buf, sizeof buf);
1640: BIO_printf(bio, " i:%s\n", buf);
1.60 tb 1641: if (cfg.showcerts)
1.49 inoguchi 1642: PEM_write_bio_X509(bio,
1643: sk_X509_value(sk, i));
1.1 jsing 1644: }
1645: }
1646: BIO_printf(bio, "---\n");
1647: peer = SSL_get_peer_certificate(s);
1648: if (peer != NULL) {
1649: BIO_printf(bio, "Server certificate\n");
1.60 tb 1650: if (!(cfg.showcerts && got_a_chain)) {
1.49 inoguchi 1651: /* Redundant if we showed the whole chain */
1.1 jsing 1652: PEM_write_bio_X509(bio, peer);
1.49 inoguchi 1653: }
1.1 jsing 1654: X509_NAME_oneline(X509_get_subject_name(peer),
1655: buf, sizeof buf);
1656: BIO_printf(bio, "subject=%s\n", buf);
1657: X509_NAME_oneline(X509_get_issuer_name(peer),
1658: buf, sizeof buf);
1659: BIO_printf(bio, "issuer=%s\n", buf);
1660: } else
1661: BIO_printf(bio, "no peer certificate available\n");
1662:
1663: sk2 = SSL_get_client_CA_list(s);
1664: if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) {
1.49 inoguchi 1665: BIO_printf(bio,
1666: "---\nAcceptable client certificate CA names\n");
1.1 jsing 1667: for (i = 0; i < sk_X509_NAME_num(sk2); i++) {
1668: xn = sk_X509_NAME_value(sk2, i);
1669: X509_NAME_oneline(xn, buf, sizeof(buf));
1670: BIO_write(bio, buf, strlen(buf));
1671: BIO_write(bio, "\n", 1);
1672: }
1673: } else {
1.49 inoguchi 1674: BIO_printf(bio,
1675: "---\nNo client certificate CA names sent\n");
1.1 jsing 1676: }
1677: p = SSL_get_shared_ciphers(s, buf, sizeof buf);
1678: if (p != NULL) {
1679: /*
1680: * This works only for SSL 2. In later protocol
1681: * versions, the client does not know what other
1682: * ciphers (in addition to the one to be used in the
1683: * current connection) the server supports.
1684: */
1685:
1.49 inoguchi 1686: BIO_printf(bio,
1687: "---\nCiphers common between both SSL endpoints:\n");
1.1 jsing 1688: j = i = 0;
1689: while (*p) {
1690: if (*p == ':') {
1691: BIO_write(bio, space, 15 - j % 25);
1692: i++;
1693: j = 0;
1.49 inoguchi 1694: BIO_write(bio,
1695: ((i % 3) ? " " : "\n"), 1);
1.1 jsing 1696: } else {
1697: BIO_write(bio, p, 1);
1698: j++;
1699: }
1700: p++;
1701: }
1702: BIO_write(bio, "\n", 1);
1703: }
1.29 jsing 1704:
1705: ssl_print_tmp_key(bio, s);
1706:
1.49 inoguchi 1707: BIO_printf(bio,
1708: "---\nSSL handshake has read %ld bytes and written %ld bytes\n",
1.1 jsing 1709: BIO_number_read(SSL_get_rbio(s)),
1710: BIO_number_written(SSL_get_wbio(s)));
1711: }
1712: BIO_printf(bio, (SSL_cache_hit(s) ? "---\nReused, " : "---\nNew, "));
1713: c = SSL_get_current_cipher(s);
1714: BIO_printf(bio, "%s, Cipher is %s\n",
1715: SSL_CIPHER_get_version(c),
1716: SSL_CIPHER_get_name(c));
1717: if (peer != NULL) {
1718: EVP_PKEY *pktmp;
1.58 tb 1719:
1720: pktmp = X509_get0_pubkey(peer);
1.1 jsing 1721: BIO_printf(bio, "Server public key is %d bit\n",
1722: EVP_PKEY_bits(pktmp));
1723: }
1724: BIO_printf(bio, "Secure Renegotiation IS%s supported\n",
1725: SSL_get_secure_renegotiation_support(s) ? "" : " NOT");
1726:
1727: /* Compression is not supported and will always be none. */
1728: BIO_printf(bio, "Compression: NONE\n");
1729: BIO_printf(bio, "Expansion: NONE\n");
1730:
1731: #ifdef SSL_DEBUG
1732: {
1733: /* Print out local port of connection: useful for debugging */
1734: int sock;
1735: struct sockaddr_in ladd;
1736: socklen_t ladd_size = sizeof(ladd);
1737: sock = SSL_get_fd(s);
1738: getsockname(sock, (struct sockaddr *) & ladd, &ladd_size);
1.50 inoguchi 1739: BIO_printf(bio, "LOCAL PORT is %u\n",
1.49 inoguchi 1740: ntohs(ladd.sin_port));
1.1 jsing 1741: }
1742: #endif
1743:
1.10 jsing 1744: {
1745: const unsigned char *proto;
1746: unsigned int proto_len;
1747: SSL_get0_alpn_selected(s, &proto, &proto_len);
1748: if (proto_len > 0) {
1749: BIO_printf(bio, "ALPN protocol: ");
1750: BIO_write(bio, proto, proto_len);
1751: BIO_write(bio, "\n", 1);
1752: } else
1753: BIO_printf(bio, "No ALPN negotiated\n");
1754: }
1.1 jsing 1755:
1756: #ifndef OPENSSL_NO_SRTP
1757: {
1.49 inoguchi 1758: SRTP_PROTECTION_PROFILE *srtp_profile;
1.1 jsing 1759:
1.49 inoguchi 1760: srtp_profile = SSL_get_selected_srtp_profile(s);
1.1 jsing 1761: if (srtp_profile)
1.49 inoguchi 1762: BIO_printf(bio,
1763: "SRTP Extension negotiated, profile=%s\n",
1.1 jsing 1764: srtp_profile->name);
1765: }
1766: #endif
1767:
1768: SSL_SESSION_print(bio, SSL_get_session(s));
1.60 tb 1769: if (cfg.keymatexportlabel != NULL) {
1.1 jsing 1770: BIO_printf(bio, "Keying material exporter:\n");
1.49 inoguchi 1771: BIO_printf(bio, " Label: '%s'\n",
1.60 tb 1772: cfg.keymatexportlabel);
1.49 inoguchi 1773: BIO_printf(bio, " Length: %i bytes\n",
1.60 tb 1774: cfg.keymatexportlen);
1775: exportedkeymat = malloc(cfg.keymatexportlen);
1.1 jsing 1776: if (exportedkeymat != NULL) {
1777: if (!SSL_export_keying_material(s, exportedkeymat,
1.60 tb 1778: cfg.keymatexportlen,
1779: cfg.keymatexportlabel,
1780: strlen(cfg.keymatexportlabel),
1.1 jsing 1781: NULL, 0, 0)) {
1782: BIO_printf(bio, " Error\n");
1783: } else {
1784: BIO_printf(bio, " Keying material: ");
1.60 tb 1785: for (i = 0; i < cfg.keymatexportlen; i++)
1.1 jsing 1786: BIO_printf(bio, "%02X",
1787: exportedkeymat[i]);
1788: BIO_printf(bio, "\n");
1789: }
1790: free(exportedkeymat);
1791: }
1792: }
1793: BIO_printf(bio, "---\n");
1.34 jsing 1794: X509_free(peer);
1.1 jsing 1795: /* flush, or debugging output gets mixed with http response */
1796: (void) BIO_flush(bio);
1797: }
1798:
1799: static int
1.51 inoguchi 1800: ocsp_resp_cb(SSL *s, void *arg)
1.1 jsing 1801: {
1802: const unsigned char *p;
1803: int len;
1804: OCSP_RESPONSE *rsp;
1805: len = SSL_get_tlsext_status_ocsp_resp(s, &p);
1806: BIO_puts(arg, "OCSP response: ");
1807: if (!p) {
1808: BIO_puts(arg, "no response sent\n");
1809: return 1;
1810: }
1811: rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
1812: if (!rsp) {
1813: BIO_puts(arg, "response parse error\n");
1814: BIO_dump_indent(arg, (char *) p, len, 4);
1815: return 0;
1816: }
1817: BIO_puts(arg, "\n======================================\n");
1818: OCSP_RESPONSE_print(arg, rsp, 0);
1819: BIO_puts(arg, "======================================\n");
1820: OCSP_RESPONSE_free(rsp);
1821: return 1;
1.51 inoguchi 1822: }
1823:
1824: static int
1825: ssl_servername_cb(SSL *s, int *ad, void *arg)
1826: {
1827: tlsextctx *p = (tlsextctx *) arg;
1828: const char *hn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
1829: if (SSL_get_servername_type(s) != -1)
1830: p->ack = !SSL_session_reused(s) && hn != NULL;
1831: else
1832: BIO_printf(bio_err, "Can't use SSL_get_servername\n");
1833:
1834: return SSL_TLSEXT_ERR_OK;
1.1 jsing 1835: }
1836: