1*276e91b2Stb /* $OpenBSD: s_client.c,v 1.67 2025/01/02 16:07:41 tb Exp $ */ 2dab3f910Sjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3dab3f910Sjsing * All rights reserved. 4dab3f910Sjsing * 5dab3f910Sjsing * This package is an SSL implementation written 6dab3f910Sjsing * by Eric Young (eay@cryptsoft.com). 7dab3f910Sjsing * The implementation was written so as to conform with Netscapes SSL. 8dab3f910Sjsing * 9dab3f910Sjsing * This library is free for commercial and non-commercial use as long as 10dab3f910Sjsing * the following conditions are aheared to. The following conditions 11dab3f910Sjsing * apply to all code found in this distribution, be it the RC4, RSA, 12dab3f910Sjsing * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13dab3f910Sjsing * included with this distribution is covered by the same copyright terms 14dab3f910Sjsing * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15dab3f910Sjsing * 16dab3f910Sjsing * Copyright remains Eric Young's, and as such any Copyright notices in 17dab3f910Sjsing * the code are not to be removed. 18dab3f910Sjsing * If this package is used in a product, Eric Young should be given attribution 19dab3f910Sjsing * as the author of the parts of the library used. 20dab3f910Sjsing * This can be in the form of a textual message at program startup or 21dab3f910Sjsing * in documentation (online or textual) provided with the package. 22dab3f910Sjsing * 23dab3f910Sjsing * Redistribution and use in source and binary forms, with or without 24dab3f910Sjsing * modification, are permitted provided that the following conditions 25dab3f910Sjsing * are met: 26dab3f910Sjsing * 1. Redistributions of source code must retain the copyright 27dab3f910Sjsing * notice, this list of conditions and the following disclaimer. 28dab3f910Sjsing * 2. Redistributions in binary form must reproduce the above copyright 29dab3f910Sjsing * notice, this list of conditions and the following disclaimer in the 30dab3f910Sjsing * documentation and/or other materials provided with the distribution. 31dab3f910Sjsing * 3. All advertising materials mentioning features or use of this software 32dab3f910Sjsing * must display the following acknowledgement: 33dab3f910Sjsing * "This product includes cryptographic software written by 34dab3f910Sjsing * Eric Young (eay@cryptsoft.com)" 35dab3f910Sjsing * The word 'cryptographic' can be left out if the rouines from the library 36dab3f910Sjsing * being used are not cryptographic related :-). 37dab3f910Sjsing * 4. If you include any Windows specific code (or a derivative thereof) from 38dab3f910Sjsing * the apps directory (application code) you must include an acknowledgement: 39dab3f910Sjsing * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40dab3f910Sjsing * 41dab3f910Sjsing * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42dab3f910Sjsing * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43dab3f910Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44dab3f910Sjsing * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45dab3f910Sjsing * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46dab3f910Sjsing * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47dab3f910Sjsing * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48dab3f910Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49dab3f910Sjsing * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50dab3f910Sjsing * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51dab3f910Sjsing * SUCH DAMAGE. 52dab3f910Sjsing * 53dab3f910Sjsing * The licence and distribution terms for any publically available version or 54dab3f910Sjsing * derivative of this code cannot be changed. i.e. this code cannot simply be 55dab3f910Sjsing * copied and put under another distribution licence 56dab3f910Sjsing * [including the GNU Public Licence.] 57dab3f910Sjsing */ 58dab3f910Sjsing /* ==================================================================== 59dab3f910Sjsing * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. 60dab3f910Sjsing * 61dab3f910Sjsing * Redistribution and use in source and binary forms, with or without 62dab3f910Sjsing * modification, are permitted provided that the following conditions 63dab3f910Sjsing * are met: 64dab3f910Sjsing * 65dab3f910Sjsing * 1. Redistributions of source code must retain the above copyright 66dab3f910Sjsing * notice, this list of conditions and the following disclaimer. 67dab3f910Sjsing * 68dab3f910Sjsing * 2. Redistributions in binary form must reproduce the above copyright 69dab3f910Sjsing * notice, this list of conditions and the following disclaimer in 70dab3f910Sjsing * the documentation and/or other materials provided with the 71dab3f910Sjsing * distribution. 72dab3f910Sjsing * 73dab3f910Sjsing * 3. All advertising materials mentioning features or use of this 74dab3f910Sjsing * software must display the following acknowledgment: 75dab3f910Sjsing * "This product includes software developed by the OpenSSL Project 76dab3f910Sjsing * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77dab3f910Sjsing * 78dab3f910Sjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79dab3f910Sjsing * endorse or promote products derived from this software without 80dab3f910Sjsing * prior written permission. For written permission, please contact 81dab3f910Sjsing * openssl-core@openssl.org. 82dab3f910Sjsing * 83dab3f910Sjsing * 5. Products derived from this software may not be called "OpenSSL" 84dab3f910Sjsing * nor may "OpenSSL" appear in their names without prior written 85dab3f910Sjsing * permission of the OpenSSL Project. 86dab3f910Sjsing * 87dab3f910Sjsing * 6. Redistributions of any form whatsoever must retain the following 88dab3f910Sjsing * acknowledgment: 89dab3f910Sjsing * "This product includes software developed by the OpenSSL Project 90dab3f910Sjsing * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 91dab3f910Sjsing * 92dab3f910Sjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 93dab3f910Sjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94dab3f910Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 95dab3f910Sjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 96dab3f910Sjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 97dab3f910Sjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 98dab3f910Sjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 99dab3f910Sjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100dab3f910Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 101dab3f910Sjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102dab3f910Sjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 103dab3f910Sjsing * OF THE POSSIBILITY OF SUCH DAMAGE. 104dab3f910Sjsing * ==================================================================== 105dab3f910Sjsing * 106dab3f910Sjsing * This product includes cryptographic software written by Eric Young 107dab3f910Sjsing * (eay@cryptsoft.com). This product includes software written by Tim 108dab3f910Sjsing * Hudson (tjh@cryptsoft.com). 109dab3f910Sjsing * 110dab3f910Sjsing */ 111dab3f910Sjsing /* ==================================================================== 112dab3f910Sjsing * Copyright 2005 Nokia. All rights reserved. 113dab3f910Sjsing * 114dab3f910Sjsing * The portions of the attached software ("Contribution") is developed by 115dab3f910Sjsing * Nokia Corporation and is licensed pursuant to the OpenSSL open source 116dab3f910Sjsing * license. 117dab3f910Sjsing * 118dab3f910Sjsing * The Contribution, originally written by Mika Kousa and Pasi Eronen of 119dab3f910Sjsing * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites 120dab3f910Sjsing * support (see RFC 4279) to OpenSSL. 121dab3f910Sjsing * 122dab3f910Sjsing * No patent licenses or other rights except those expressly stated in 123dab3f910Sjsing * the OpenSSL open source license shall be deemed granted or received 124dab3f910Sjsing * expressly, by implication, estoppel, or otherwise. 125dab3f910Sjsing * 126dab3f910Sjsing * No assurances are provided by Nokia that the Contribution does not 127dab3f910Sjsing * infringe the patent or other intellectual property rights of any third 128dab3f910Sjsing * party or that the license provides you with all the necessary rights 129dab3f910Sjsing * to make use of the Contribution. 130dab3f910Sjsing * 131dab3f910Sjsing * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN 132dab3f910Sjsing * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA 133dab3f910Sjsing * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY 134dab3f910Sjsing * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR 135dab3f910Sjsing * OTHERWISE. 136dab3f910Sjsing */ 137dab3f910Sjsing 138dab3f910Sjsing #include <sys/types.h> 139dab3f910Sjsing #include <sys/socket.h> 140dab3f910Sjsing 141dab3f910Sjsing #include <netinet/in.h> 142dab3f910Sjsing 143dab3f910Sjsing #include <assert.h> 144dab3f910Sjsing #include <ctype.h> 145dab3f910Sjsing #include <limits.h> 146dab3f910Sjsing #include <netdb.h> 147dab3f910Sjsing #include <stdio.h> 148dab3f910Sjsing #include <stdlib.h> 149dab3f910Sjsing #include <string.h> 150dab3f910Sjsing #include <unistd.h> 1519c8ea7b6Sderaadt #include <poll.h> 152dab3f910Sjsing 153dab3f910Sjsing #include "apps.h" 154dab3f910Sjsing 155dab3f910Sjsing #include <openssl/bn.h> 156dab3f910Sjsing #include <openssl/err.h> 157dab3f910Sjsing #include <openssl/ocsp.h> 158dab3f910Sjsing #include <openssl/pem.h> 159dab3f910Sjsing #include <openssl/ssl.h> 160dab3f910Sjsing #include <openssl/x509.h> 161dab3f910Sjsing 162dab3f910Sjsing #define SSL_HOST_NAME "localhost" 163dab3f910Sjsing 164dab3f910Sjsing #define BUFSIZZ 1024*8 165dab3f910Sjsing 166dab3f910Sjsing static void sc_usage(void); 167dab3f910Sjsing static void print_stuff(BIO *berr, SSL *con, int full); 168dab3f910Sjsing static int ocsp_resp_cb(SSL *s, void *arg); 169a2111520Sinoguchi static int ssl_servername_cb(SSL *s, int *ad, void *arg); 170dab3f910Sjsing 17110281ad2Sinoguchi enum { 17210281ad2Sinoguchi PROTO_OFF = 0, 17310281ad2Sinoguchi PROTO_SMTP, 17410281ad2Sinoguchi PROTO_LMTP, 17510281ad2Sinoguchi PROTO_POP3, 17610281ad2Sinoguchi PROTO_IMAP, 17710281ad2Sinoguchi PROTO_FTP, 17810281ad2Sinoguchi PROTO_XMPP, 17910281ad2Sinoguchi }; 18010281ad2Sinoguchi 181a2111520Sinoguchi /* This is a context that we pass to callbacks */ 182a2111520Sinoguchi typedef struct tlsextctx_st { 183a2111520Sinoguchi BIO *biodebug; 184a2111520Sinoguchi int ack; 185a2111520Sinoguchi } tlsextctx; 186a2111520Sinoguchi 18710281ad2Sinoguchi static struct { 18810281ad2Sinoguchi int af; 18910281ad2Sinoguchi char *alpn_in; 19010281ad2Sinoguchi int bugs; 19110281ad2Sinoguchi char *CAfile; 19210281ad2Sinoguchi char *CApath; 19310281ad2Sinoguchi char *cert_file; 19410281ad2Sinoguchi int cert_format; 19510281ad2Sinoguchi char *cipher; 19610281ad2Sinoguchi unsigned int clr; 19710281ad2Sinoguchi char *connect; 19810281ad2Sinoguchi int crlf; 1996dcdcd8fSinoguchi int debug; 20010281ad2Sinoguchi int enable_timeouts; 20110281ad2Sinoguchi const char *errstr; 20210281ad2Sinoguchi char *groups_in; 20310281ad2Sinoguchi char *host; 2046dcdcd8fSinoguchi int ign_eof; 20510281ad2Sinoguchi char *key_file; 20610281ad2Sinoguchi int key_format; 20710281ad2Sinoguchi char *keymatexportlabel; 20810281ad2Sinoguchi int keymatexportlen; 20910281ad2Sinoguchi uint16_t max_version; 21010281ad2Sinoguchi uint16_t min_version; 21110281ad2Sinoguchi const SSL_METHOD *meth; 2126dcdcd8fSinoguchi int msg; 2136dcdcd8fSinoguchi int nbio; 21410281ad2Sinoguchi int nbio_test; 215cb7cbc09Sjsing int no_servername; 21610281ad2Sinoguchi char *npn_in; 21710281ad2Sinoguchi unsigned int off; 21810281ad2Sinoguchi char *passarg; 21910281ad2Sinoguchi int peekaboo; 22010281ad2Sinoguchi char *port; 22110281ad2Sinoguchi int prexit; 22210281ad2Sinoguchi char *proxy; 2236dcdcd8fSinoguchi int quiet; 22410281ad2Sinoguchi int reconnect; 22510281ad2Sinoguchi char *servername; 22610281ad2Sinoguchi char *sess_in; 22710281ad2Sinoguchi char *sess_out; 2286dcdcd8fSinoguchi int showcerts; 22910281ad2Sinoguchi int socket_type; 23010281ad2Sinoguchi long socket_mtu; 23110281ad2Sinoguchi #ifndef OPENSSL_NO_SRTP 23210281ad2Sinoguchi char *srtp_profiles; 23310281ad2Sinoguchi #endif 23410281ad2Sinoguchi int starttls_proto; 23510281ad2Sinoguchi int state; 2366dcdcd8fSinoguchi int status_req; 2376dcdcd8fSinoguchi int tlsextdebug; 23810281ad2Sinoguchi int verify; 23910281ad2Sinoguchi X509_VERIFY_PARAM *vpm; 24010281ad2Sinoguchi char *xmpphost; 241e7718adaStb } cfg; 24210281ad2Sinoguchi 24310281ad2Sinoguchi static int 24410281ad2Sinoguchi s_client_opt_keymatexportlen(char *arg) 24510281ad2Sinoguchi { 246e7718adaStb cfg.keymatexportlen = strtonum(arg, 1, INT_MAX, 247e7718adaStb &cfg.errstr); 248e7718adaStb if (cfg.errstr != NULL) { 24910281ad2Sinoguchi BIO_printf(bio_err, "invalid argument %s: %s\n", 250e7718adaStb arg, cfg.errstr); 25110281ad2Sinoguchi return (1); 25210281ad2Sinoguchi } 25310281ad2Sinoguchi return (0); 25410281ad2Sinoguchi } 25510281ad2Sinoguchi 25693dafd19Sjsing #ifndef OPENSSL_NO_DTLS 25710281ad2Sinoguchi static int 25810281ad2Sinoguchi s_client_opt_mtu(char *arg) 25910281ad2Sinoguchi { 260e7718adaStb cfg.socket_mtu = strtonum(arg, 0, LONG_MAX, 261e7718adaStb &cfg.errstr); 262e7718adaStb if (cfg.errstr != NULL) { 26310281ad2Sinoguchi BIO_printf(bio_err, "invalid argument %s: %s\n", 264e7718adaStb arg, cfg.errstr); 26510281ad2Sinoguchi return (1); 26610281ad2Sinoguchi } 26710281ad2Sinoguchi return (0); 26810281ad2Sinoguchi } 26910281ad2Sinoguchi #endif 27010281ad2Sinoguchi 27110281ad2Sinoguchi static int 27210281ad2Sinoguchi s_client_opt_port(char *arg) 27310281ad2Sinoguchi { 27410281ad2Sinoguchi if (*arg == '\0') 27510281ad2Sinoguchi return (1); 27610281ad2Sinoguchi 277e7718adaStb cfg.port = arg; 27810281ad2Sinoguchi return (0); 27910281ad2Sinoguchi } 28010281ad2Sinoguchi 28193dafd19Sjsing #ifndef OPENSSL_NO_DTLS 28293dafd19Sjsing static int 28393dafd19Sjsing s_client_opt_protocol_version_dtls(void) 28493dafd19Sjsing { 285e7718adaStb cfg.meth = DTLS_client_method(); 286e7718adaStb cfg.socket_type = SOCK_DGRAM; 28793dafd19Sjsing return (0); 28893dafd19Sjsing } 28993dafd19Sjsing #endif 29093dafd19Sjsing 29193dafd19Sjsing #ifndef OPENSSL_NO_DTLS1_2 29293dafd19Sjsing static int 29393dafd19Sjsing s_client_opt_protocol_version_dtls1_2(void) 29493dafd19Sjsing { 295e7718adaStb cfg.meth = DTLS_client_method(); 296e7718adaStb cfg.min_version = DTLS1_2_VERSION; 297e7718adaStb cfg.max_version = DTLS1_2_VERSION; 298e7718adaStb cfg.socket_type = SOCK_DGRAM; 29910281ad2Sinoguchi return (0); 30010281ad2Sinoguchi } 30110281ad2Sinoguchi #endif 30210281ad2Sinoguchi 30310281ad2Sinoguchi static int 30410281ad2Sinoguchi s_client_opt_protocol_version_tls1_2(void) 30510281ad2Sinoguchi { 306e7718adaStb cfg.min_version = TLS1_2_VERSION; 307e7718adaStb cfg.max_version = TLS1_2_VERSION; 30810281ad2Sinoguchi return (0); 30910281ad2Sinoguchi } 31010281ad2Sinoguchi 31110281ad2Sinoguchi static int 31210281ad2Sinoguchi s_client_opt_protocol_version_tls1_3(void) 31310281ad2Sinoguchi { 314e7718adaStb cfg.min_version = TLS1_3_VERSION; 315e7718adaStb cfg.max_version = TLS1_3_VERSION; 31610281ad2Sinoguchi return (0); 31710281ad2Sinoguchi } 31810281ad2Sinoguchi 31910281ad2Sinoguchi static int 32010281ad2Sinoguchi s_client_opt_quiet(void) 32110281ad2Sinoguchi { 322e7718adaStb cfg.quiet = 1; 323e7718adaStb cfg.ign_eof = 1; 32410281ad2Sinoguchi return (0); 32510281ad2Sinoguchi } 32610281ad2Sinoguchi 32710281ad2Sinoguchi static int 32810281ad2Sinoguchi s_client_opt_starttls(char *arg) 32910281ad2Sinoguchi { 33010281ad2Sinoguchi if (strcmp(arg, "smtp") == 0) 331e7718adaStb cfg.starttls_proto = PROTO_SMTP; 33210281ad2Sinoguchi else if (strcmp(arg, "lmtp") == 0) 333e7718adaStb cfg.starttls_proto = PROTO_LMTP; 33410281ad2Sinoguchi else if (strcmp(arg, "pop3") == 0) 335e7718adaStb cfg.starttls_proto = PROTO_POP3; 33610281ad2Sinoguchi else if (strcmp(arg, "imap") == 0) 337e7718adaStb cfg.starttls_proto = PROTO_IMAP; 33810281ad2Sinoguchi else if (strcmp(arg, "ftp") == 0) 339e7718adaStb cfg.starttls_proto = PROTO_FTP; 34010281ad2Sinoguchi else if (strcmp(arg, "xmpp") == 0) 341e7718adaStb cfg.starttls_proto = PROTO_XMPP; 34210281ad2Sinoguchi else 34310281ad2Sinoguchi return (1); 34410281ad2Sinoguchi return (0); 34510281ad2Sinoguchi } 34610281ad2Sinoguchi 34710281ad2Sinoguchi static int 34810281ad2Sinoguchi s_client_opt_verify(char *arg) 34910281ad2Sinoguchi { 350e7718adaStb cfg.verify = SSL_VERIFY_PEER; 35110281ad2Sinoguchi 352e7718adaStb verify_depth = strtonum(arg, 0, INT_MAX, &cfg.errstr); 353e7718adaStb if (cfg.errstr != NULL) { 35410281ad2Sinoguchi BIO_printf(bio_err, "invalid argument %s: %s\n", 355e7718adaStb arg, cfg.errstr); 35610281ad2Sinoguchi return (1); 35710281ad2Sinoguchi } 35810281ad2Sinoguchi BIO_printf(bio_err, "verify depth is %d\n", verify_depth); 35910281ad2Sinoguchi return (0); 36010281ad2Sinoguchi } 36110281ad2Sinoguchi 36210281ad2Sinoguchi static int 36310281ad2Sinoguchi s_client_opt_verify_param(int argc, char **argv, int *argsused) 36410281ad2Sinoguchi { 36510281ad2Sinoguchi char **pargs = argv; 36610281ad2Sinoguchi int pargc = argc; 36710281ad2Sinoguchi int badarg = 0; 36810281ad2Sinoguchi 36910281ad2Sinoguchi if (!args_verify(&pargs, &pargc, &badarg, bio_err, 370e7718adaStb &cfg.vpm)) { 37110281ad2Sinoguchi BIO_printf(bio_err, "unknown option %s\n", *argv); 37210281ad2Sinoguchi return (1); 37310281ad2Sinoguchi } 37410281ad2Sinoguchi if (badarg) 37510281ad2Sinoguchi return (1); 37610281ad2Sinoguchi 37710281ad2Sinoguchi *argsused = argc - pargc; 37810281ad2Sinoguchi return (0); 37910281ad2Sinoguchi } 38010281ad2Sinoguchi 38110281ad2Sinoguchi static const struct option s_client_options[] = { 38210281ad2Sinoguchi { 38310281ad2Sinoguchi .name = "4", 38410281ad2Sinoguchi .desc = "Use IPv4 only", 38510281ad2Sinoguchi .type = OPTION_VALUE, 386e7718adaStb .opt.value = &cfg.af, 38710281ad2Sinoguchi .value = AF_INET, 38810281ad2Sinoguchi }, 38910281ad2Sinoguchi { 39010281ad2Sinoguchi .name = "6", 39110281ad2Sinoguchi .desc = "Use IPv6 only", 39210281ad2Sinoguchi .type = OPTION_VALUE, 393e7718adaStb .opt.value = &cfg.af, 39410281ad2Sinoguchi .value = AF_INET6, 39510281ad2Sinoguchi }, 39610281ad2Sinoguchi { 39710281ad2Sinoguchi .name = "alpn", 39810281ad2Sinoguchi .argname = "protocols", 39910281ad2Sinoguchi .desc = "Set the advertised protocols for ALPN" 40010281ad2Sinoguchi " (comma-separated list)", 40110281ad2Sinoguchi .type = OPTION_ARG, 402e7718adaStb .opt.arg = &cfg.alpn_in, 40310281ad2Sinoguchi }, 40410281ad2Sinoguchi { 40510281ad2Sinoguchi .name = "bugs", 40610281ad2Sinoguchi .desc = "Enable various workarounds for buggy implementations", 40710281ad2Sinoguchi .type = OPTION_FLAG, 408e7718adaStb .opt.flag = &cfg.bugs, 40910281ad2Sinoguchi }, 41010281ad2Sinoguchi { 41110281ad2Sinoguchi .name = "CAfile", 41210281ad2Sinoguchi .argname = "file", 41310281ad2Sinoguchi .desc = "PEM format file of CA certificates", 41410281ad2Sinoguchi .type = OPTION_ARG, 415e7718adaStb .opt.arg = &cfg.CAfile, 41610281ad2Sinoguchi }, 41710281ad2Sinoguchi { 41810281ad2Sinoguchi .name = "CApath", 41910281ad2Sinoguchi .argname = "directory", 42010281ad2Sinoguchi .desc = "PEM format directory of CA certificates", 42110281ad2Sinoguchi .type = OPTION_ARG, 422e7718adaStb .opt.arg = &cfg.CApath, 42310281ad2Sinoguchi }, 42410281ad2Sinoguchi { 42510281ad2Sinoguchi .name = "cert", 42610281ad2Sinoguchi .argname = "file", 42710281ad2Sinoguchi .desc = "Certificate file to use, PEM format assumed", 42810281ad2Sinoguchi .type = OPTION_ARG, 429e7718adaStb .opt.arg = &cfg.cert_file, 43010281ad2Sinoguchi }, 43110281ad2Sinoguchi { 43210281ad2Sinoguchi .name = "certform", 43310281ad2Sinoguchi .argname = "fmt", 43410281ad2Sinoguchi .desc = "Certificate format (PEM or DER) PEM default", 43510281ad2Sinoguchi .type = OPTION_ARG_FORMAT, 436e7718adaStb .opt.value = &cfg.cert_format, 43710281ad2Sinoguchi }, 43810281ad2Sinoguchi { 43910281ad2Sinoguchi .name = "cipher", 44010281ad2Sinoguchi .argname = "cipherlist", 44110281ad2Sinoguchi .desc = "Preferred cipher to use (see 'openssl ciphers')", 44210281ad2Sinoguchi .type = OPTION_ARG, 443e7718adaStb .opt.arg = &cfg.cipher, 44410281ad2Sinoguchi }, 44510281ad2Sinoguchi { 44610281ad2Sinoguchi .name = "connect", 44710281ad2Sinoguchi .argname = "host:port", 44810281ad2Sinoguchi .desc = "Who to connect to (default is localhost:4433)", 44910281ad2Sinoguchi .type = OPTION_ARG, 450e7718adaStb .opt.arg = &cfg.connect, 45110281ad2Sinoguchi }, 45210281ad2Sinoguchi { 45310281ad2Sinoguchi .name = "crlf", 45410281ad2Sinoguchi .desc = "Convert LF from terminal into CRLF", 45510281ad2Sinoguchi .type = OPTION_FLAG, 456e7718adaStb .opt.flag = &cfg.crlf, 45710281ad2Sinoguchi }, 45810281ad2Sinoguchi { 45910281ad2Sinoguchi .name = "debug", 46010281ad2Sinoguchi .desc = "Print extensive debugging information", 46110281ad2Sinoguchi .type = OPTION_FLAG, 462e7718adaStb .opt.flag = &cfg.debug, 46310281ad2Sinoguchi }, 46493dafd19Sjsing #ifndef OPENSSL_NO_DTLS 46593dafd19Sjsing { 46693dafd19Sjsing .name = "dtls", 46793dafd19Sjsing .desc = "Use any version of DTLS", 46893dafd19Sjsing .type = OPTION_FUNC, 46993dafd19Sjsing .opt.func = s_client_opt_protocol_version_dtls, 47093dafd19Sjsing }, 47193dafd19Sjsing #endif 47293dafd19Sjsing #ifndef OPENSSL_NO_DTLS1_2 47393dafd19Sjsing { 47493dafd19Sjsing .name = "dtls1_2", 47593dafd19Sjsing .desc = "Just use DTLSv1.2", 47693dafd19Sjsing .type = OPTION_FUNC, 47793dafd19Sjsing .opt.func = s_client_opt_protocol_version_dtls1_2, 47893dafd19Sjsing }, 47993dafd19Sjsing #endif 48010281ad2Sinoguchi { 48110281ad2Sinoguchi .name = "groups", 48210281ad2Sinoguchi .argname = "list", 48310281ad2Sinoguchi .desc = "Specify EC groups (colon-separated list)", 48410281ad2Sinoguchi .type = OPTION_ARG, 485e7718adaStb .opt.arg = &cfg.groups_in, 48610281ad2Sinoguchi }, 48710281ad2Sinoguchi { 48810281ad2Sinoguchi .name = "host", 48910281ad2Sinoguchi .argname = "host", 49010281ad2Sinoguchi .desc = "Use -connect instead", 49110281ad2Sinoguchi .type = OPTION_ARG, 492e7718adaStb .opt.arg = &cfg.host, 49310281ad2Sinoguchi }, 49410281ad2Sinoguchi { 49510281ad2Sinoguchi .name = "ign_eof", 49610281ad2Sinoguchi .desc = "Ignore input EOF (default when -quiet)", 49710281ad2Sinoguchi .type = OPTION_VALUE, 498e7718adaStb .opt.value = &cfg.ign_eof, 49910281ad2Sinoguchi .value = 1, 50010281ad2Sinoguchi }, 50110281ad2Sinoguchi { 50210281ad2Sinoguchi .name = "key", 50310281ad2Sinoguchi .argname = "file", 50410281ad2Sinoguchi .desc = "Private key file to use, if not, -cert file is used", 50510281ad2Sinoguchi .type = OPTION_ARG, 506e7718adaStb .opt.arg = &cfg.key_file, 50710281ad2Sinoguchi }, 50810281ad2Sinoguchi { 50910281ad2Sinoguchi .name = "keyform", 51010281ad2Sinoguchi .argname = "fmt", 51110281ad2Sinoguchi .desc = "Key format (PEM or DER) PEM default", 51210281ad2Sinoguchi .type = OPTION_ARG_FORMAT, 513e7718adaStb .opt.value = &cfg.key_format, 51410281ad2Sinoguchi }, 51510281ad2Sinoguchi { 51610281ad2Sinoguchi .name = "keymatexport", 51710281ad2Sinoguchi .argname = "label", 51810281ad2Sinoguchi .desc = "Export keying material using label", 51910281ad2Sinoguchi .type = OPTION_ARG, 520e7718adaStb .opt.arg = &cfg.keymatexportlabel, 52110281ad2Sinoguchi }, 52210281ad2Sinoguchi { 52310281ad2Sinoguchi .name = "keymatexportlen", 52410281ad2Sinoguchi .argname = "len", 52510281ad2Sinoguchi .desc = "Export len bytes of keying material (default 20)", 52610281ad2Sinoguchi .type = OPTION_ARG_FUNC, 52710281ad2Sinoguchi .opt.argfunc = s_client_opt_keymatexportlen, 52810281ad2Sinoguchi }, 52910281ad2Sinoguchi { 53010281ad2Sinoguchi .name = "legacy_renegotiation", 53110281ad2Sinoguchi .type = OPTION_DISCARD, 53210281ad2Sinoguchi }, 53310281ad2Sinoguchi { 53410281ad2Sinoguchi .name = "legacy_server_connect", 53510281ad2Sinoguchi .desc = "Allow initial connection to servers that don't support RI", 53610281ad2Sinoguchi .type = OPTION_VALUE_OR, 537e7718adaStb .opt.value = &cfg.off, 53810281ad2Sinoguchi .value = SSL_OP_LEGACY_SERVER_CONNECT, 53910281ad2Sinoguchi }, 54010281ad2Sinoguchi { 54110281ad2Sinoguchi .name = "msg", 54210281ad2Sinoguchi .desc = "Show all protocol messages with hex dump", 54310281ad2Sinoguchi .type = OPTION_FLAG, 544e7718adaStb .opt.flag = &cfg.msg, 54510281ad2Sinoguchi }, 54693dafd19Sjsing #ifndef OPENSSL_NO_DTLS 54710281ad2Sinoguchi { 54810281ad2Sinoguchi .name = "mtu", 54910281ad2Sinoguchi .argname = "mtu", 55010281ad2Sinoguchi .desc = "Set the link layer MTU on DTLS connections", 55110281ad2Sinoguchi .type = OPTION_ARG_FUNC, 55210281ad2Sinoguchi .opt.argfunc = s_client_opt_mtu, 55310281ad2Sinoguchi }, 55410281ad2Sinoguchi #endif 55510281ad2Sinoguchi { 55610281ad2Sinoguchi .name = "nbio", 55710281ad2Sinoguchi .desc = "Turn on non-blocking I/O", 55810281ad2Sinoguchi .type = OPTION_FLAG, 559e7718adaStb .opt.flag = &cfg.nbio, 56010281ad2Sinoguchi }, 56110281ad2Sinoguchi { 56210281ad2Sinoguchi .name = "nbio_test", 56310281ad2Sinoguchi .desc = "Test non-blocking I/O", 56410281ad2Sinoguchi .type = OPTION_FLAG, 565e7718adaStb .opt.flag = &cfg.nbio_test, 56610281ad2Sinoguchi }, 56710281ad2Sinoguchi { 56810281ad2Sinoguchi .name = "nextprotoneg", 56910281ad2Sinoguchi .argname = "protocols", 57010281ad2Sinoguchi .type = OPTION_ARG, 571e7718adaStb .opt.arg = &cfg.npn_in, /* Ignored. */ 57210281ad2Sinoguchi }, 57310281ad2Sinoguchi { 57410281ad2Sinoguchi .name = "no_comp", 57510281ad2Sinoguchi .type = OPTION_VALUE_OR, 576e7718adaStb .opt.value = &cfg.off, 57710281ad2Sinoguchi .value = SSL_OP_NO_COMPRESSION, 57810281ad2Sinoguchi }, 57910281ad2Sinoguchi { 58010281ad2Sinoguchi .name = "no_ign_eof", 58110281ad2Sinoguchi .desc = "Don't ignore input EOF", 58210281ad2Sinoguchi .type = OPTION_VALUE, 583e7718adaStb .opt.value = &cfg.ign_eof, 58410281ad2Sinoguchi .value = 0, 58510281ad2Sinoguchi }, 58610281ad2Sinoguchi { 58710281ad2Sinoguchi .name = "no_legacy_server_connect", 58810281ad2Sinoguchi .desc = "Disallow initial connection to servers that don't support RI", 58910281ad2Sinoguchi .type = OPTION_VALUE_OR, 590e7718adaStb .opt.value = &cfg.clr, 59110281ad2Sinoguchi .value = SSL_OP_LEGACY_SERVER_CONNECT, 59210281ad2Sinoguchi }, 59310281ad2Sinoguchi { 594cb7cbc09Sjsing .name = "no_servername", 595cb7cbc09Sjsing .desc = "Do not send a Server Name Indication (SNI) extension", 596cb7cbc09Sjsing .type = OPTION_FLAG, 597e7718adaStb .opt.value = &cfg.no_servername, 598cb7cbc09Sjsing }, 599cb7cbc09Sjsing { 60010281ad2Sinoguchi .name = "no_ssl2", 60110281ad2Sinoguchi .type = OPTION_VALUE_OR, 602e7718adaStb .opt.value = &cfg.off, 60310281ad2Sinoguchi .value = SSL_OP_NO_SSLv2, 60410281ad2Sinoguchi }, 60510281ad2Sinoguchi { 60610281ad2Sinoguchi .name = "no_ssl3", 60710281ad2Sinoguchi .type = OPTION_VALUE_OR, 608e7718adaStb .opt.value = &cfg.off, 60910281ad2Sinoguchi .value = SSL_OP_NO_SSLv3, 61010281ad2Sinoguchi }, 61110281ad2Sinoguchi { 61210281ad2Sinoguchi .name = "no_ticket", 61310281ad2Sinoguchi .desc = "Disable use of RFC4507 session ticket support", 61410281ad2Sinoguchi .type = OPTION_VALUE_OR, 615e7718adaStb .opt.value = &cfg.off, 61610281ad2Sinoguchi .value = SSL_OP_NO_TICKET, 61710281ad2Sinoguchi }, 61810281ad2Sinoguchi { 619b5c24d4fSbeck .name = "no_tls1", 620b5c24d4fSbeck .type = OPTION_DISCARD, 621b5c24d4fSbeck }, 622b5c24d4fSbeck { 623b5c24d4fSbeck .name = "no_tls1_1", 624b5c24d4fSbeck .type = OPTION_DISCARD, 625b5c24d4fSbeck }, 626b5c24d4fSbeck { 62710281ad2Sinoguchi .name = "no_tls1_2", 62810281ad2Sinoguchi .desc = "Disable the use of TLSv1.2", 62910281ad2Sinoguchi .type = OPTION_VALUE_OR, 630e7718adaStb .opt.value = &cfg.off, 63110281ad2Sinoguchi .value = SSL_OP_NO_TLSv1_2, 63210281ad2Sinoguchi }, 63310281ad2Sinoguchi { 63410281ad2Sinoguchi .name = "no_tls1_3", 63510281ad2Sinoguchi .desc = "Disable the use of TLSv1.3", 63610281ad2Sinoguchi .type = OPTION_VALUE_OR, 637e7718adaStb .opt.value = &cfg.off, 63810281ad2Sinoguchi .value = SSL_OP_NO_TLSv1_3, 63910281ad2Sinoguchi }, 64010281ad2Sinoguchi { 641cb7cbc09Sjsing .name = "noservername", 642cb7cbc09Sjsing .type = OPTION_FLAG, 643e7718adaStb .opt.value = &cfg.no_servername, 644cb7cbc09Sjsing }, 645cb7cbc09Sjsing { 64610281ad2Sinoguchi .name = "pass", 64710281ad2Sinoguchi .argname = "arg", 64810281ad2Sinoguchi .desc = "Private key file pass phrase source", 64910281ad2Sinoguchi .type = OPTION_ARG, 650e7718adaStb .opt.arg = &cfg.passarg, 65110281ad2Sinoguchi }, 65210281ad2Sinoguchi { 65310281ad2Sinoguchi .name = "pause", 6544578675dStb .type = OPTION_DISCARD, 65510281ad2Sinoguchi }, 65610281ad2Sinoguchi { 65710281ad2Sinoguchi .name = "peekaboo", 65810281ad2Sinoguchi .type = OPTION_FLAG, 659e7718adaStb .opt.flag = &cfg.peekaboo, 66010281ad2Sinoguchi }, 66110281ad2Sinoguchi { 66210281ad2Sinoguchi .name = "port", 66310281ad2Sinoguchi .argname = "port", 66410281ad2Sinoguchi .desc = "Use -connect instead", 66510281ad2Sinoguchi .type = OPTION_ARG_FUNC, 66610281ad2Sinoguchi .opt.argfunc = s_client_opt_port, 66710281ad2Sinoguchi }, 66810281ad2Sinoguchi { 66910281ad2Sinoguchi .name = "prexit", 67010281ad2Sinoguchi .desc = "Print session information when the program exits", 67110281ad2Sinoguchi .type = OPTION_FLAG, 672e7718adaStb .opt.flag = &cfg.prexit, 67310281ad2Sinoguchi }, 67410281ad2Sinoguchi { 67510281ad2Sinoguchi .name = "proxy", 67610281ad2Sinoguchi .argname = "host:port", 67710281ad2Sinoguchi .desc = "Connect to http proxy", 67810281ad2Sinoguchi .type = OPTION_ARG, 679e7718adaStb .opt.arg = &cfg.proxy, 68010281ad2Sinoguchi }, 68110281ad2Sinoguchi { 68210281ad2Sinoguchi .name = "quiet", 68310281ad2Sinoguchi .desc = "Inhibit printing of session and certificate info", 68410281ad2Sinoguchi .type = OPTION_FUNC, 68510281ad2Sinoguchi .opt.func = s_client_opt_quiet, 68610281ad2Sinoguchi }, 68710281ad2Sinoguchi { 68810281ad2Sinoguchi .name = "reconnect", 68910281ad2Sinoguchi .desc = "Drop and re-make the connection with the same Session-ID", 69010281ad2Sinoguchi .type = OPTION_VALUE, 691e7718adaStb .opt.value = &cfg.reconnect, 69210281ad2Sinoguchi .value = 5, 69310281ad2Sinoguchi }, 69410281ad2Sinoguchi { 69510281ad2Sinoguchi .name = "servername", 69610281ad2Sinoguchi .argname = "name", 69710281ad2Sinoguchi .desc = "Set TLS extension servername in ClientHello (SNI)", 69810281ad2Sinoguchi .type = OPTION_ARG, 699e7718adaStb .opt.arg = &cfg.servername, 70010281ad2Sinoguchi }, 70110281ad2Sinoguchi { 70210281ad2Sinoguchi .name = "serverpref", 70310281ad2Sinoguchi .desc = "Use server's cipher preferences", 70410281ad2Sinoguchi .type = OPTION_VALUE_OR, 705e7718adaStb .opt.value = &cfg.off, 70610281ad2Sinoguchi .value = SSL_OP_CIPHER_SERVER_PREFERENCE, 70710281ad2Sinoguchi }, 70810281ad2Sinoguchi { 70910281ad2Sinoguchi .name = "sess_in", 71010281ad2Sinoguchi .argname = "file", 71110281ad2Sinoguchi .desc = "File to read TLS session from", 71210281ad2Sinoguchi .type = OPTION_ARG, 713e7718adaStb .opt.arg = &cfg.sess_in, 71410281ad2Sinoguchi }, 71510281ad2Sinoguchi { 71610281ad2Sinoguchi .name = "sess_out", 71710281ad2Sinoguchi .argname = "file", 71810281ad2Sinoguchi .desc = "File to write TLS session to", 71910281ad2Sinoguchi .type = OPTION_ARG, 720e7718adaStb .opt.arg = &cfg.sess_out, 72110281ad2Sinoguchi }, 72210281ad2Sinoguchi { 72310281ad2Sinoguchi .name = "showcerts", 72410281ad2Sinoguchi .desc = "Show all server certificates in the chain", 72510281ad2Sinoguchi .type = OPTION_FLAG, 726e7718adaStb .opt.flag = &cfg.showcerts, 72710281ad2Sinoguchi }, 72810281ad2Sinoguchi { 72910281ad2Sinoguchi .name = "starttls", 73010281ad2Sinoguchi .argname = "protocol", 73110281ad2Sinoguchi .desc = "Use the STARTTLS command before starting TLS,\n" 73210281ad2Sinoguchi "smtp, lmtp, pop3, imap, ftp and xmpp are supported.", 73310281ad2Sinoguchi .type = OPTION_ARG_FUNC, 73410281ad2Sinoguchi .opt.argfunc = s_client_opt_starttls, 73510281ad2Sinoguchi }, 73610281ad2Sinoguchi { 73710281ad2Sinoguchi .name = "state", 73810281ad2Sinoguchi .desc = "Print the TLS session states", 73910281ad2Sinoguchi .type = OPTION_FLAG, 740e7718adaStb .opt.flag = &cfg.state, 74110281ad2Sinoguchi }, 74210281ad2Sinoguchi { 74310281ad2Sinoguchi .name = "status", 74410281ad2Sinoguchi .desc = "Send a certificate status request to the server (OCSP)", 74510281ad2Sinoguchi .type = OPTION_FLAG, 746e7718adaStb .opt.flag = &cfg.status_req, 74710281ad2Sinoguchi }, 74893dafd19Sjsing #ifndef OPENSSL_NO_DTLS 74910281ad2Sinoguchi { 75010281ad2Sinoguchi .name = "timeout", 75110281ad2Sinoguchi .desc = "Enable send/receive timeout on DTLS connections", 75210281ad2Sinoguchi .type = OPTION_FLAG, 753e7718adaStb .opt.flag = &cfg.enable_timeouts, 75410281ad2Sinoguchi }, 75510281ad2Sinoguchi #endif 75610281ad2Sinoguchi { 75710281ad2Sinoguchi .name = "tls1_2", 75810281ad2Sinoguchi .desc = "Just use TLSv1.2", 75910281ad2Sinoguchi .type = OPTION_FUNC, 76010281ad2Sinoguchi .opt.func = s_client_opt_protocol_version_tls1_2, 76110281ad2Sinoguchi }, 76210281ad2Sinoguchi { 76310281ad2Sinoguchi .name = "tls1_3", 76410281ad2Sinoguchi .desc = "Just use TLSv1.3", 76510281ad2Sinoguchi .type = OPTION_FUNC, 76610281ad2Sinoguchi .opt.func = s_client_opt_protocol_version_tls1_3, 76710281ad2Sinoguchi }, 76810281ad2Sinoguchi { 76910281ad2Sinoguchi .name = "tlsextdebug", 77010281ad2Sinoguchi .desc = "Hex dump of all TLS extensions received", 77110281ad2Sinoguchi .type = OPTION_FLAG, 772e7718adaStb .opt.flag = &cfg.tlsextdebug, 77310281ad2Sinoguchi }, 77410281ad2Sinoguchi #ifndef OPENSSL_NO_SRTP 77510281ad2Sinoguchi { 77610281ad2Sinoguchi .name = "use_srtp", 77710281ad2Sinoguchi .argname = "profiles", 77810281ad2Sinoguchi .desc = "Offer SRTP key management with a colon-separated profiles", 77910281ad2Sinoguchi .type = OPTION_ARG, 780e7718adaStb .opt.arg = &cfg.srtp_profiles, 78110281ad2Sinoguchi }, 78210281ad2Sinoguchi #endif 78310281ad2Sinoguchi { 78410281ad2Sinoguchi .name = "verify", 78510281ad2Sinoguchi .argname = "depth", 78610281ad2Sinoguchi .desc = "Turn on peer certificate verification, with a max of depth", 78710281ad2Sinoguchi .type = OPTION_ARG_FUNC, 78810281ad2Sinoguchi .opt.argfunc = s_client_opt_verify, 78910281ad2Sinoguchi }, 79010281ad2Sinoguchi { 79110281ad2Sinoguchi .name = "verify_return_error", 79210281ad2Sinoguchi .desc = "Return verification error", 79310281ad2Sinoguchi .type = OPTION_FLAG, 79410281ad2Sinoguchi .opt.flag = &verify_return_error, 79510281ad2Sinoguchi }, 79610281ad2Sinoguchi { 79710281ad2Sinoguchi .name = "xmpphost", 79810281ad2Sinoguchi .argname = "host", 79910281ad2Sinoguchi .desc = "Connect to this virtual host on the xmpp server", 80010281ad2Sinoguchi .type = OPTION_ARG, 801e7718adaStb .opt.arg = &cfg.xmpphost, 80210281ad2Sinoguchi }, 80310281ad2Sinoguchi { 80410281ad2Sinoguchi .name = NULL, 80510281ad2Sinoguchi .desc = "", 80610281ad2Sinoguchi .type = OPTION_ARGV_FUNC, 80710281ad2Sinoguchi .opt.argvfunc = s_client_opt_verify_param, 80810281ad2Sinoguchi }, 80910281ad2Sinoguchi { NULL }, 81010281ad2Sinoguchi }; 811dab3f910Sjsing 812dab3f910Sjsing static void 813dab3f910Sjsing sc_usage(void) 814dab3f910Sjsing { 81510281ad2Sinoguchi fprintf(stderr, "usage: s_client " 81610281ad2Sinoguchi "[-4 | -6] [-alpn protocols] [-bugs] [-CAfile file]\n" 81710281ad2Sinoguchi " [-CApath directory] [-cert file] [-certform der | pem] [-check_ss_sig]\n" 81810281ad2Sinoguchi " [-cipher cipherlist] [-connect host[:port]] [-crl_check]\n" 81991e7614aSbeck " [-crl_check_all] [-crlf] [-debug] [-dtls] [-dtls1_2] [-extended_crl]\n" 82010281ad2Sinoguchi " [-groups list] [-host host] [-ign_eof] [-ignore_critical]\n" 82110281ad2Sinoguchi " [-issuer_checks] [-key keyfile] [-keyform der | pem]\n" 82210281ad2Sinoguchi " [-keymatexport label] [-keymatexportlen len] [-legacy_server_connect]\n" 82310281ad2Sinoguchi " [-msg] [-mtu mtu] [-nbio] [-nbio_test] [-no_comp] [-no_ign_eof]\n" 82491e7614aSbeck " [-no_legacy_server_connect] [-no_ticket] \n" 8254578675dStb " [-no_tls1_2] [-no_tls1_3] [-pass arg] [-policy_check]\n" 82610281ad2Sinoguchi " [-port port] [-prexit] [-proxy host:port] [-quiet] [-reconnect]\n" 82710281ad2Sinoguchi " [-servername name] [-serverpref] [-sess_in file] [-sess_out file]\n" 82810281ad2Sinoguchi " [-showcerts] [-starttls protocol] [-state] [-status] [-timeout]\n" 82991e7614aSbeck " [-tls1_2] [-tls1_3] [-tlsextdebug]\n" 83010281ad2Sinoguchi " [-use_srtp profiles] [-verify depth] [-verify_return_error]\n" 83110281ad2Sinoguchi " [-x509_strict] [-xmpphost host]\n"); 83210281ad2Sinoguchi fprintf(stderr, "\n"); 83310281ad2Sinoguchi options_usage(s_client_options); 83410281ad2Sinoguchi fprintf(stderr, "\n"); 835dab3f910Sjsing } 836dab3f910Sjsing 837dab3f910Sjsing int 838dab3f910Sjsing s_client_main(int argc, char **argv) 839dab3f910Sjsing { 840dab3f910Sjsing SSL *con = NULL; 84110281ad2Sinoguchi int s, k, p = 0, pending = 0; 8429c84cee0Sbeck char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL, *pbuf = NULL; 843dab3f910Sjsing int cbuf_len, cbuf_off; 844dab3f910Sjsing int sbuf_len, sbuf_off; 845dab3f910Sjsing int full_log = 1; 846cb7cbc09Sjsing const char *servername; 84710281ad2Sinoguchi char *pass = NULL; 848dab3f910Sjsing X509 *cert = NULL; 849dab3f910Sjsing EVP_PKEY *key = NULL; 85010281ad2Sinoguchi int badop = 0; 851dab3f910Sjsing int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; 852dab3f910Sjsing SSL_CTX *ctx = NULL; 85310281ad2Sinoguchi int ret = 1, in_init = 1, i; 8545042ef37Sinoguchi BIO *bio_c_out = NULL; 855dab3f910Sjsing BIO *sbio; 856dab3f910Sjsing int mbuf_len = 0; 8579c8ea7b6Sderaadt struct timeval timeout; 85841eb9d41Sjsing tlsextctx tlsextcbp = {NULL, 0}; 859f91d157aSderaadt struct sockaddr_storage peer; 860dab3f910Sjsing int peerlen = sizeof(peer); 861dab3f910Sjsing 86251811eadSderaadt if (pledge("stdio cpath wpath rpath inet dns tty", NULL) == -1) { 8639bc487adSdoug perror("pledge"); 864e370f0eeSdoug exit(1); 865e370f0eeSdoug } 8669bc487adSdoug 867e7718adaStb memset(&cfg, 0, sizeof(cfg)); 868e7718adaStb cfg.af = AF_UNSPEC; 869e7718adaStb cfg.cert_format = FORMAT_PEM; 870e7718adaStb cfg.host = SSL_HOST_NAME; 871e7718adaStb cfg.key_format = FORMAT_PEM; 872e7718adaStb cfg.keymatexportlen = 20; 873e7718adaStb cfg.meth = TLS_client_method(); 874e7718adaStb cfg.port = PORT_STR; 875e7718adaStb cfg.socket_type = SOCK_STREAM; 876e7718adaStb cfg.starttls_proto = PROTO_OFF; 877e7718adaStb cfg.verify = SSL_VERIFY_NONE; 878dab3f910Sjsing 879dab3f910Sjsing if (((cbuf = malloc(BUFSIZZ)) == NULL) || 880dab3f910Sjsing ((sbuf = malloc(BUFSIZZ)) == NULL) || 8819c84cee0Sbeck ((pbuf = malloc(BUFSIZZ)) == NULL) || 882dab3f910Sjsing ((mbuf = malloc(BUFSIZZ + 1)) == NULL)) { /* NUL byte */ 883dab3f910Sjsing BIO_printf(bio_err, "out of memory\n"); 884dab3f910Sjsing goto end; 885dab3f910Sjsing } 886dab3f910Sjsing verify_depth = 0; 887dab3f910Sjsing 88810281ad2Sinoguchi if (options_parse(argc, argv, s_client_options, NULL, NULL) != 0) { 889dab3f910Sjsing badop = 1; 890eb4b0597Sbluhm goto bad; 89110281ad2Sinoguchi } 892e7718adaStb if (cfg.proxy != NULL) { 893e7718adaStb if (!extract_host_port(cfg.proxy, 894e7718adaStb &cfg.host, NULL, &cfg.port)) 89510281ad2Sinoguchi goto bad; 896e7718adaStb if (cfg.connect == NULL) 897e7718adaStb cfg.connect = SSL_HOST_NAME; 898e7718adaStb } else if (cfg.connect != NULL) { 899e7718adaStb if (!extract_host_port(cfg.connect, 900e7718adaStb &cfg.host, NULL, &cfg.port)) 901eb4b0597Sbluhm goto bad; 902eb4b0597Sbluhm } 903dab3f910Sjsing if (badop) { 904dab3f910Sjsing bad: 905e7718adaStb if (cfg.errstr == NULL) 906dab3f910Sjsing sc_usage(); 907dab3f910Sjsing goto end; 908dab3f910Sjsing } 909dab3f910Sjsing 910e7718adaStb if (!app_passwd(bio_err, cfg.passarg, NULL, &pass, NULL)) { 911dab3f910Sjsing BIO_printf(bio_err, "Error getting password\n"); 912dab3f910Sjsing goto end; 913dab3f910Sjsing } 914e7718adaStb if (cfg.key_file == NULL) 915e7718adaStb cfg.key_file = cfg.cert_file; 916dab3f910Sjsing 917dab3f910Sjsing 918e7718adaStb if (cfg.key_file) { 919dab3f910Sjsing 920e7718adaStb key = load_key(bio_err, cfg.key_file, 921e7718adaStb cfg.key_format, 0, pass, 922dab3f910Sjsing "client certificate private key file"); 923dab3f910Sjsing if (!key) { 924dab3f910Sjsing ERR_print_errors(bio_err); 925dab3f910Sjsing goto end; 926dab3f910Sjsing } 927dab3f910Sjsing } 928e7718adaStb if (cfg.cert_file) { 929e7718adaStb cert = load_cert(bio_err, cfg.cert_file, 930e7718adaStb cfg.cert_format, 9315284dfeaSbcook NULL, "client certificate file"); 932dab3f910Sjsing 933dab3f910Sjsing if (!cert) { 934dab3f910Sjsing ERR_print_errors(bio_err); 935dab3f910Sjsing goto end; 936dab3f910Sjsing } 937dab3f910Sjsing } 938e7718adaStb if (cfg.quiet && !cfg.debug && 939e7718adaStb !cfg.msg) { 9405042ef37Sinoguchi if ((bio_c_out = BIO_new(BIO_s_null())) == NULL) 9415042ef37Sinoguchi goto end; 942dab3f910Sjsing } else { 9435042ef37Sinoguchi if ((bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL) 9445042ef37Sinoguchi goto end; 945dab3f910Sjsing } 946dab3f910Sjsing 947e7718adaStb ctx = SSL_CTX_new(cfg.meth); 948dab3f910Sjsing if (ctx == NULL) { 949dab3f910Sjsing ERR_print_errors(bio_err); 950dab3f910Sjsing goto end; 951dab3f910Sjsing } 952f4cc3564Stb 953f4cc3564Stb SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY); 954f4cc3564Stb 955e7718adaStb if (cfg.vpm) 956e7718adaStb SSL_CTX_set1_param(ctx, cfg.vpm); 957dab3f910Sjsing 958e7718adaStb if (!SSL_CTX_set_min_proto_version(ctx, cfg.min_version)) 959428703dcSjsing goto end; 960e7718adaStb if (!SSL_CTX_set_max_proto_version(ctx, cfg.max_version)) 961428703dcSjsing goto end; 962428703dcSjsing 963dab3f910Sjsing #ifndef OPENSSL_NO_SRTP 964e7718adaStb if (cfg.srtp_profiles != NULL) 965e7718adaStb SSL_CTX_set_tlsext_use_srtp(ctx, cfg.srtp_profiles); 966dab3f910Sjsing #endif 967e7718adaStb if (cfg.bugs) 968e7718adaStb SSL_CTX_set_options(ctx, SSL_OP_ALL | cfg.off); 969dab3f910Sjsing else 970e7718adaStb SSL_CTX_set_options(ctx, cfg.off); 971dab3f910Sjsing 972e7718adaStb if (cfg.clr) 973e7718adaStb SSL_CTX_clear_options(ctx, cfg.clr); 974dab3f910Sjsing 975e7718adaStb if (cfg.alpn_in) { 9761b4c9cadSjsing unsigned short alpn_len; 9776369f9f8Sinoguchi unsigned char *alpn; 9781b4c9cadSjsing 979e7718adaStb alpn = next_protos_parse(&alpn_len, cfg.alpn_in); 9801b4c9cadSjsing if (alpn == NULL) { 9811b4c9cadSjsing BIO_printf(bio_err, "Error parsing -alpn argument\n"); 9821b4c9cadSjsing goto end; 9831b4c9cadSjsing } 9841b4c9cadSjsing SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len); 9851b4c9cadSjsing free(alpn); 9861b4c9cadSjsing } 987e7718adaStb if (cfg.groups_in != NULL) { 988e7718adaStb if (SSL_CTX_set1_groups_list(ctx, cfg.groups_in) != 1) { 989c4d6b74bSjsing BIO_printf(bio_err, "Failed to set groups '%s'\n", 990e7718adaStb cfg.groups_in); 991c4d6b74bSjsing goto end; 992c4d6b74bSjsing } 993c4d6b74bSjsing } 994dab3f910Sjsing 995e7718adaStb if (cfg.state) 996dab3f910Sjsing SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); 997e7718adaStb if (cfg.cipher != NULL) 998e7718adaStb if (!SSL_CTX_set_cipher_list(ctx, cfg.cipher)) { 999dab3f910Sjsing BIO_printf(bio_err, "error setting cipher list\n"); 1000dab3f910Sjsing ERR_print_errors(bio_err); 1001dab3f910Sjsing goto end; 1002dab3f910Sjsing } 1003dab3f910Sjsing 1004e7718adaStb SSL_CTX_set_verify(ctx, cfg.verify, verify_callback); 1005dab3f910Sjsing if (!set_cert_key_stuff(ctx, cert, key)) 1006dab3f910Sjsing goto end; 1007dab3f910Sjsing 1008e7718adaStb if ((cfg.CAfile || cfg.CApath) 1009e7718adaStb && !SSL_CTX_load_verify_locations(ctx, cfg.CAfile, 1010e7718adaStb cfg.CApath)) 1011dab3f910Sjsing ERR_print_errors(bio_err); 1012bbc7462fSbcook 1013bbc7462fSbcook if (!SSL_CTX_set_default_verify_paths(ctx)) 1014bbc7462fSbcook ERR_print_errors(bio_err); 1015bbc7462fSbcook 1016dab3f910Sjsing con = SSL_new(ctx); 1017e7718adaStb if (cfg.sess_in) { 1018dab3f910Sjsing SSL_SESSION *sess; 1019e7718adaStb BIO *stmp = BIO_new_file(cfg.sess_in, "r"); 1020dab3f910Sjsing if (!stmp) { 1021dab3f910Sjsing BIO_printf(bio_err, "Can't open session file %s\n", 1022e7718adaStb cfg.sess_in); 1023dab3f910Sjsing ERR_print_errors(bio_err); 1024dab3f910Sjsing goto end; 1025dab3f910Sjsing } 1026dab3f910Sjsing sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); 1027dab3f910Sjsing BIO_free(stmp); 1028dab3f910Sjsing if (!sess) { 1029dab3f910Sjsing BIO_printf(bio_err, "Can't open session file %s\n", 1030e7718adaStb cfg.sess_in); 1031dab3f910Sjsing ERR_print_errors(bio_err); 1032dab3f910Sjsing goto end; 1033dab3f910Sjsing } 1034dab3f910Sjsing SSL_set_session(con, sess); 1035dab3f910Sjsing SSL_SESSION_free(sess); 1036dab3f910Sjsing } 1037cb7cbc09Sjsing 1038cb7cbc09Sjsing /* Attempt to opportunistically use the host name for SNI. */ 1039e7718adaStb servername = cfg.servername; 1040cb7cbc09Sjsing if (servername == NULL) 1041e7718adaStb servername = cfg.host; 1042cb7cbc09Sjsing 1043e7718adaStb if (!cfg.no_servername && servername != NULL && 1044cb7cbc09Sjsing !SSL_set_tlsext_host_name(con, servername)) { 1045cb7cbc09Sjsing long ssl_err = ERR_peek_error(); 1046cb7cbc09Sjsing 1047e7718adaStb if (cfg.servername != NULL || 1048cb7cbc09Sjsing ERR_GET_LIB(ssl_err) != ERR_LIB_SSL || 1049cb7cbc09Sjsing ERR_GET_REASON(ssl_err) != SSL_R_SSL3_EXT_INVALID_SERVERNAME) { 10506369f9f8Sinoguchi BIO_printf(bio_err, 10516369f9f8Sinoguchi "Unable to set TLS servername extension.\n"); 1052dab3f910Sjsing ERR_print_errors(bio_err); 1053dab3f910Sjsing goto end; 1054dab3f910Sjsing } 1055cb7cbc09Sjsing servername = NULL; 1056cb7cbc09Sjsing ERR_clear_error(); 1057dab3f910Sjsing } 1058e7718adaStb if (!cfg.no_servername && servername != NULL) { 1059cb7cbc09Sjsing tlsextcbp.biodebug = bio_err; 1060cb7cbc09Sjsing SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); 1061cb7cbc09Sjsing SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); 1062cb7cbc09Sjsing } 1063dab3f910Sjsing 1064dab3f910Sjsing re_start: 1065dab3f910Sjsing 1066e7718adaStb if (init_client(&s, cfg.host, cfg.port, 1067e7718adaStb cfg.socket_type, cfg.af) == 0) { 1068dab3f910Sjsing BIO_printf(bio_err, "connect:errno=%d\n", errno); 1069dab3f910Sjsing goto end; 1070dab3f910Sjsing } 1071dab3f910Sjsing BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); 1072dab3f910Sjsing 1073e7718adaStb if (cfg.nbio) { 1074e7718adaStb if (!cfg.quiet) 1075dab3f910Sjsing BIO_printf(bio_c_out, "turning on non blocking io\n"); 1076fcc700e7Sbcook if (!BIO_socket_nbio(s, 1)) { 1077dab3f910Sjsing ERR_print_errors(bio_err); 1078dab3f910Sjsing goto end; 1079dab3f910Sjsing } 1080dab3f910Sjsing } 1081dab3f910Sjsing 108293dafd19Sjsing if (SSL_is_dtls(con)) { 1083dab3f910Sjsing sbio = BIO_new_dgram(s, BIO_NOCLOSE); 1084f91d157aSderaadt if (getsockname(s, (struct sockaddr *)&peer, 1085f91d157aSderaadt (void *)&peerlen) == -1) { 1086dab3f910Sjsing BIO_printf(bio_err, "getsockname:errno=%d\n", 1087dab3f910Sjsing errno); 1088dab3f910Sjsing shutdown(s, SHUT_RD); 1089dab3f910Sjsing close(s); 1090dab3f910Sjsing goto end; 1091dab3f910Sjsing } 1092dab3f910Sjsing (void) BIO_ctrl_set_connected(sbio, 1, &peer); 1093dab3f910Sjsing 1094e7718adaStb if (cfg.enable_timeouts) { 1095dab3f910Sjsing timeout.tv_sec = 0; 1096dab3f910Sjsing timeout.tv_usec = DGRAM_RCV_TIMEOUT; 10976369f9f8Sinoguchi BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, 10986369f9f8Sinoguchi &timeout); 1099dab3f910Sjsing 1100dab3f910Sjsing timeout.tv_sec = 0; 1101dab3f910Sjsing timeout.tv_usec = DGRAM_SND_TIMEOUT; 11026369f9f8Sinoguchi BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, 11036369f9f8Sinoguchi &timeout); 1104dab3f910Sjsing } 1105e7718adaStb if (cfg.socket_mtu > 28) { 1106dab3f910Sjsing SSL_set_options(con, SSL_OP_NO_QUERY_MTU); 1107e7718adaStb SSL_set_mtu(con, cfg.socket_mtu - 28); 1108dab3f910Sjsing } else 1109dab3f910Sjsing /* want to do MTU discovery */ 1110dab3f910Sjsing BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); 1111dab3f910Sjsing } else 1112dab3f910Sjsing sbio = BIO_new_socket(s, BIO_NOCLOSE); 1113dab3f910Sjsing 1114e7718adaStb if (cfg.nbio_test) { 1115dab3f910Sjsing BIO *test; 1116dab3f910Sjsing 1117dab3f910Sjsing test = BIO_new(BIO_f_nbio_test()); 1118dab3f910Sjsing sbio = BIO_push(test, sbio); 1119dab3f910Sjsing } 1120e7718adaStb if (cfg.debug) { 1121dab3f910Sjsing BIO_set_callback(sbio, bio_dump_callback); 1122dab3f910Sjsing BIO_set_callback_arg(sbio, (char *) bio_c_out); 1123dab3f910Sjsing } 1124e7718adaStb if (cfg.msg) { 1125dab3f910Sjsing SSL_set_msg_callback(con, msg_cb); 1126dab3f910Sjsing SSL_set_msg_callback_arg(con, bio_c_out); 1127dab3f910Sjsing } 1128e7718adaStb if (cfg.tlsextdebug) { 1129dab3f910Sjsing SSL_set_tlsext_debug_callback(con, tlsext_cb); 1130dab3f910Sjsing SSL_set_tlsext_debug_arg(con, bio_c_out); 1131dab3f910Sjsing } 1132e7718adaStb if (cfg.status_req) { 1133dab3f910Sjsing SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp); 1134dab3f910Sjsing SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb); 1135dab3f910Sjsing SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out); 1136dab3f910Sjsing } 1137dab3f910Sjsing 1138dab3f910Sjsing SSL_set_bio(con, sbio, sbio); 1139dab3f910Sjsing SSL_set_connect_state(con); 1140dab3f910Sjsing 1141dab3f910Sjsing /* ok, lets connect */ 1142dab3f910Sjsing read_tty = 1; 1143dab3f910Sjsing write_tty = 0; 1144dab3f910Sjsing tty_on = 0; 1145dab3f910Sjsing read_ssl = 1; 1146dab3f910Sjsing write_ssl = 1; 1147dab3f910Sjsing 1148dab3f910Sjsing cbuf_len = 0; 1149dab3f910Sjsing cbuf_off = 0; 1150dab3f910Sjsing sbuf_len = 0; 1151dab3f910Sjsing sbuf_off = 0; 1152dab3f910Sjsing 1153dab3f910Sjsing /* This is an ugly hack that does a lot of assumptions */ 1154dab3f910Sjsing /* 1155dab3f910Sjsing * We do have to handle multi-line responses which may come in a 1156dab3f910Sjsing * single packet or not. We therefore have to use BIO_gets() which 1157dab3f910Sjsing * does need a buffering BIO. So during the initial chitchat we do 1158dab3f910Sjsing * push a buffering BIO into the chain that is removed again later on 1159dab3f910Sjsing * to not disturb the rest of the s_client operation. 1160dab3f910Sjsing */ 1161e7718adaStb if (cfg.starttls_proto == PROTO_SMTP || 1162e7718adaStb cfg.starttls_proto == PROTO_LMTP) { 1163dab3f910Sjsing int foundit = 0; 1164dab3f910Sjsing BIO *fbio = BIO_new(BIO_f_buffer()); 1165dab3f910Sjsing BIO_push(fbio, sbio); 1166dab3f910Sjsing /* wait for multi-line response to end from SMTP */ 1167dab3f910Sjsing do { 1168dab3f910Sjsing mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); 1169dab3f910Sjsing } 1170dab3f910Sjsing while (mbuf_len > 3 && mbuf[3] == '-'); 1171dab3f910Sjsing /* STARTTLS command requires EHLO... */ 1172dab3f910Sjsing BIO_printf(fbio, "%cHLO openssl.client.net\r\n", 1173e7718adaStb cfg.starttls_proto == PROTO_SMTP ? 'E' : 'L'); 1174dab3f910Sjsing (void) BIO_flush(fbio); 1175dab3f910Sjsing /* wait for multi-line response to end EHLO SMTP response */ 1176dab3f910Sjsing do { 1177dab3f910Sjsing mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); 1178dab3f910Sjsing if (strstr(mbuf, "STARTTLS")) 1179dab3f910Sjsing foundit = 1; 1180dab3f910Sjsing } 1181dab3f910Sjsing while (mbuf_len > 3 && mbuf[3] == '-'); 1182dab3f910Sjsing (void) BIO_flush(fbio); 1183dab3f910Sjsing BIO_pop(fbio); 1184dab3f910Sjsing BIO_free(fbio); 1185dab3f910Sjsing if (!foundit) 1186dab3f910Sjsing BIO_printf(bio_err, 11875651377cSjmc "didn't find starttls in server response," 1188dab3f910Sjsing " try anyway...\n"); 1189dab3f910Sjsing BIO_printf(sbio, "STARTTLS\r\n"); 1190dab3f910Sjsing BIO_read(sbio, sbuf, BUFSIZZ); 1191e7718adaStb } else if (cfg.starttls_proto == PROTO_POP3) { 1192dab3f910Sjsing mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); 1193dab3f910Sjsing if (mbuf_len == -1) { 1194dab3f910Sjsing BIO_printf(bio_err, "BIO_read failed\n"); 1195dab3f910Sjsing goto end; 1196dab3f910Sjsing } 1197dab3f910Sjsing BIO_printf(sbio, "STLS\r\n"); 1198dab3f910Sjsing BIO_read(sbio, sbuf, BUFSIZZ); 1199e7718adaStb } else if (cfg.starttls_proto == PROTO_IMAP) { 1200dab3f910Sjsing int foundit = 0; 1201dab3f910Sjsing BIO *fbio = BIO_new(BIO_f_buffer()); 1202dab3f910Sjsing BIO_push(fbio, sbio); 1203dab3f910Sjsing BIO_gets(fbio, mbuf, BUFSIZZ); 1204dab3f910Sjsing /* STARTTLS command requires CAPABILITY... */ 1205dab3f910Sjsing BIO_printf(fbio, ". CAPABILITY\r\n"); 1206dab3f910Sjsing (void) BIO_flush(fbio); 1207dab3f910Sjsing /* wait for multi-line CAPABILITY response */ 1208dab3f910Sjsing do { 1209dab3f910Sjsing mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); 1210dab3f910Sjsing if (strstr(mbuf, "STARTTLS")) 1211dab3f910Sjsing foundit = 1; 1212dab3f910Sjsing } 1213dab3f910Sjsing while (mbuf_len > 3 && mbuf[0] != '.'); 1214dab3f910Sjsing (void) BIO_flush(fbio); 1215dab3f910Sjsing BIO_pop(fbio); 1216dab3f910Sjsing BIO_free(fbio); 1217dab3f910Sjsing if (!foundit) 1218dab3f910Sjsing BIO_printf(bio_err, 1219f60aeedaStb "didn't find STARTTLS in server response," 1220dab3f910Sjsing " try anyway...\n"); 1221dab3f910Sjsing BIO_printf(sbio, ". STARTTLS\r\n"); 1222dab3f910Sjsing BIO_read(sbio, sbuf, BUFSIZZ); 1223e7718adaStb } else if (cfg.starttls_proto == PROTO_FTP) { 1224dab3f910Sjsing BIO *fbio = BIO_new(BIO_f_buffer()); 1225dab3f910Sjsing BIO_push(fbio, sbio); 1226dab3f910Sjsing /* wait for multi-line response to end from FTP */ 1227dab3f910Sjsing do { 1228dab3f910Sjsing mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); 1229dab3f910Sjsing } 1230dab3f910Sjsing while (mbuf_len > 3 && mbuf[3] == '-'); 1231dab3f910Sjsing (void) BIO_flush(fbio); 1232dab3f910Sjsing BIO_pop(fbio); 1233dab3f910Sjsing BIO_free(fbio); 1234dab3f910Sjsing BIO_printf(sbio, "AUTH TLS\r\n"); 1235dab3f910Sjsing BIO_read(sbio, sbuf, BUFSIZZ); 1236e7718adaStb } else if (cfg.starttls_proto == PROTO_XMPP) { 1237dab3f910Sjsing int seen = 0; 1238dab3f910Sjsing BIO_printf(sbio, "<stream:stream " 1239dab3f910Sjsing "xmlns:stream='http://etherx.jabber.org/streams' " 12406369f9f8Sinoguchi "xmlns='jabber:client' to='%s' version='1.0'>", 1241e7718adaStb cfg.xmpphost ? 1242e7718adaStb cfg.xmpphost : cfg.host); 1243dab3f910Sjsing seen = BIO_read(sbio, mbuf, BUFSIZZ); 12442c0bb1ecSlandry 12452c0bb1ecSlandry if (seen <= 0) 1246dab3f910Sjsing goto shut; 12472c0bb1ecSlandry 12482c0bb1ecSlandry mbuf[seen] = 0; 12492c0bb1ecSlandry while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'") && 12502c0bb1ecSlandry !strstr(mbuf, "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"")) { 1251dab3f910Sjsing seen = BIO_read(sbio, mbuf, BUFSIZZ); 12522c0bb1ecSlandry 12532c0bb1ecSlandry if (seen <= 0) 12542c0bb1ecSlandry goto shut; 12552c0bb1ecSlandry 1256dab3f910Sjsing mbuf[seen] = 0; 1257dab3f910Sjsing } 12586369f9f8Sinoguchi BIO_printf(sbio, 12596369f9f8Sinoguchi "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); 1260dab3f910Sjsing seen = BIO_read(sbio, sbuf, BUFSIZZ); 1261dab3f910Sjsing sbuf[seen] = 0; 1262dab3f910Sjsing if (!strstr(sbuf, "<proceed")) 1263dab3f910Sjsing goto shut; 1264dab3f910Sjsing mbuf[0] = 0; 1265e7718adaStb } else if (cfg.proxy != NULL) { 12666369f9f8Sinoguchi BIO_printf(sbio, "CONNECT %s HTTP/1.0\r\n\r\n", 1267e7718adaStb cfg.connect); 1268eb4b0597Sbluhm mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); 1269eb4b0597Sbluhm if (mbuf_len == -1) { 1270eb4b0597Sbluhm BIO_printf(bio_err, "BIO_read failed\n"); 1271eb4b0597Sbluhm goto end; 1272eb4b0597Sbluhm } 1273dab3f910Sjsing } 1274dab3f910Sjsing for (;;) { 12759c8ea7b6Sderaadt struct pollfd pfd[3]; /* stdin, stdout, socket */ 12769c8ea7b6Sderaadt int ptimeout = -1; 1277dab3f910Sjsing 127893dafd19Sjsing if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout)) 12796369f9f8Sinoguchi ptimeout = timeout.tv_sec * 1000 + 12806369f9f8Sinoguchi timeout.tv_usec / 1000; 1281dab3f910Sjsing 1282dab3f910Sjsing if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { 1283dab3f910Sjsing in_init = 1; 1284dab3f910Sjsing tty_on = 0; 1285dab3f910Sjsing } else { 1286dab3f910Sjsing tty_on = 1; 1287dab3f910Sjsing if (in_init) { 1288dab3f910Sjsing in_init = 0; 1289e7718adaStb if (cfg.sess_out) { 12906369f9f8Sinoguchi BIO *stmp = BIO_new_file( 1291e7718adaStb cfg.sess_out, "w"); 1292dab3f910Sjsing if (stmp) { 12936369f9f8Sinoguchi PEM_write_bio_SSL_SESSION(stmp, 12946369f9f8Sinoguchi SSL_get_session(con)); 1295dab3f910Sjsing BIO_free(stmp); 1296dab3f910Sjsing } else 12976369f9f8Sinoguchi BIO_printf(bio_err, 12986369f9f8Sinoguchi "Error writing session file %s\n", 1299e7718adaStb cfg.sess_out); 1300dab3f910Sjsing } 1301dab3f910Sjsing print_stuff(bio_c_out, con, full_log); 1302dab3f910Sjsing if (full_log > 0) 1303dab3f910Sjsing full_log--; 1304dab3f910Sjsing 1305e7718adaStb if (cfg.starttls_proto) { 1306dab3f910Sjsing BIO_write(bio_err, mbuf, mbuf_len); 1307dab3f910Sjsing /* We don't need to know any more */ 1308e7718adaStb cfg.starttls_proto = PROTO_OFF; 1309dab3f910Sjsing } 1310e7718adaStb if (cfg.reconnect) { 1311e7718adaStb cfg.reconnect--; 13126369f9f8Sinoguchi BIO_printf(bio_c_out, 13136369f9f8Sinoguchi "drop connection and then reconnect\n"); 1314dab3f910Sjsing SSL_shutdown(con); 1315dab3f910Sjsing SSL_set_connect_state(con); 1316dab3f910Sjsing shutdown(SSL_get_fd(con), SHUT_RD); 1317dab3f910Sjsing close(SSL_get_fd(con)); 1318dab3f910Sjsing goto re_start; 1319dab3f910Sjsing } 1320dab3f910Sjsing } 1321dab3f910Sjsing } 1322dab3f910Sjsing 1323dab3f910Sjsing ssl_pending = read_ssl && SSL_pending(con); 1324dab3f910Sjsing 13259c8ea7b6Sderaadt pfd[0].fd = -1; 13269c8ea7b6Sderaadt pfd[1].fd = -1; 1327dab3f910Sjsing if (!ssl_pending) { 1328dab3f910Sjsing if (tty_on) { 13299c8ea7b6Sderaadt if (read_tty) { 13309c8ea7b6Sderaadt pfd[0].fd = fileno(stdin); 13319c8ea7b6Sderaadt pfd[0].events = POLLIN; 1332dab3f910Sjsing } 13339c8ea7b6Sderaadt if (write_tty) { 13349c8ea7b6Sderaadt pfd[1].fd = fileno(stdout); 13359c8ea7b6Sderaadt pfd[1].events = POLLOUT; 13369c8ea7b6Sderaadt } 13379c8ea7b6Sderaadt } 13389c8ea7b6Sderaadt 13399c8ea7b6Sderaadt pfd[2].fd = SSL_get_fd(con); 13409c8ea7b6Sderaadt pfd[2].events = 0; 1341dab3f910Sjsing if (read_ssl) 13429c8ea7b6Sderaadt pfd[2].events |= POLLIN; 1343dab3f910Sjsing if (write_ssl) 13449c8ea7b6Sderaadt pfd[2].events |= POLLOUT; 13459c8ea7b6Sderaadt 1346dab3f910Sjsing /* printf("mode tty(%d %d%d) ssl(%d%d)\n", 1347dab3f910Sjsing tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ 1348dab3f910Sjsing 13499c8ea7b6Sderaadt i = poll(pfd, 3, ptimeout); 13503aaa63ebSderaadt if (i == -1) { 1351dab3f910Sjsing BIO_printf(bio_err, "bad select %d\n", 1352dab3f910Sjsing errno); 1353dab3f910Sjsing goto shut; 1354dab3f910Sjsing /* goto end; */ 1355dab3f910Sjsing } 1356dab3f910Sjsing } 135793dafd19Sjsing if (SSL_is_dtls(con) && 135893dafd19Sjsing DTLSv1_handle_timeout(con) > 0) 1359dab3f910Sjsing BIO_printf(bio_err, "TIMEOUT occured\n"); 13606369f9f8Sinoguchi if (!ssl_pending && 13616369f9f8Sinoguchi (pfd[2].revents & (POLLOUT|POLLERR|POLLNVAL))) { 13629c8ea7b6Sderaadt if (pfd[2].revents & (POLLERR|POLLNVAL)) { 13639c8ea7b6Sderaadt BIO_printf(bio_err, "poll error"); 13649c8ea7b6Sderaadt goto shut; 13659c8ea7b6Sderaadt } 1366dab3f910Sjsing k = SSL_write(con, &(cbuf[cbuf_off]), 1367dab3f910Sjsing (unsigned int) cbuf_len); 1368dab3f910Sjsing switch (SSL_get_error(con, k)) { 1369dab3f910Sjsing case SSL_ERROR_NONE: 1370dab3f910Sjsing cbuf_off += k; 1371dab3f910Sjsing cbuf_len -= k; 1372dab3f910Sjsing if (k <= 0) 1373dab3f910Sjsing goto end; 1374dab3f910Sjsing /* we have done a write(con,NULL,0); */ 1375dab3f910Sjsing if (cbuf_len <= 0) { 1376dab3f910Sjsing read_tty = 1; 1377dab3f910Sjsing write_ssl = 0; 1378dab3f910Sjsing } else { /* if (cbuf_len > 0) */ 1379dab3f910Sjsing read_tty = 0; 1380dab3f910Sjsing write_ssl = 1; 1381dab3f910Sjsing } 1382dab3f910Sjsing break; 1383dab3f910Sjsing case SSL_ERROR_WANT_WRITE: 1384dab3f910Sjsing BIO_printf(bio_c_out, "write W BLOCK\n"); 1385dab3f910Sjsing write_ssl = 1; 1386dab3f910Sjsing read_tty = 0; 1387dab3f910Sjsing break; 1388dab3f910Sjsing case SSL_ERROR_WANT_READ: 1389dab3f910Sjsing BIO_printf(bio_c_out, "write R BLOCK\n"); 1390dab3f910Sjsing write_tty = 0; 1391dab3f910Sjsing read_ssl = 1; 1392dab3f910Sjsing write_ssl = 0; 1393dab3f910Sjsing break; 1394dab3f910Sjsing case SSL_ERROR_WANT_X509_LOOKUP: 1395dab3f910Sjsing BIO_printf(bio_c_out, "write X BLOCK\n"); 1396dab3f910Sjsing break; 1397dab3f910Sjsing case SSL_ERROR_ZERO_RETURN: 1398dab3f910Sjsing if (cbuf_len != 0) { 1399dab3f910Sjsing BIO_printf(bio_c_out, "shutdown\n"); 1400dab3f910Sjsing ret = 0; 1401dab3f910Sjsing goto shut; 1402dab3f910Sjsing } else { 1403dab3f910Sjsing read_tty = 1; 1404dab3f910Sjsing write_ssl = 0; 1405dab3f910Sjsing break; 1406dab3f910Sjsing } 1407dab3f910Sjsing 1408dab3f910Sjsing case SSL_ERROR_SYSCALL: 1409dab3f910Sjsing if ((k != 0) || (cbuf_len != 0)) { 1410dab3f910Sjsing BIO_printf(bio_err, "write:errno=%d\n", 1411dab3f910Sjsing errno); 1412dab3f910Sjsing goto shut; 1413dab3f910Sjsing } else { 1414dab3f910Sjsing read_tty = 1; 1415dab3f910Sjsing write_ssl = 0; 1416dab3f910Sjsing } 1417dab3f910Sjsing break; 1418dab3f910Sjsing case SSL_ERROR_SSL: 1419dab3f910Sjsing ERR_print_errors(bio_err); 1420dab3f910Sjsing goto shut; 1421dab3f910Sjsing } 14229c8ea7b6Sderaadt } else if (!ssl_pending && 14239c8ea7b6Sderaadt (pfd[1].revents & (POLLOUT|POLLERR|POLLNVAL))) { 14249c8ea7b6Sderaadt if (pfd[1].revents & (POLLERR|POLLNVAL)) { 14259c8ea7b6Sderaadt BIO_printf(bio_err, "poll error"); 14269c8ea7b6Sderaadt goto shut; 14279c8ea7b6Sderaadt } 1428dab3f910Sjsing i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len); 1429dab3f910Sjsing 1430dab3f910Sjsing if (i <= 0) { 1431dab3f910Sjsing BIO_printf(bio_c_out, "DONE\n"); 1432dab3f910Sjsing ret = 0; 1433dab3f910Sjsing goto shut; 1434dab3f910Sjsing /* goto end; */ 1435dab3f910Sjsing } 1436dab3f910Sjsing sbuf_len -= i; 1437dab3f910Sjsing sbuf_off += i; 1438dab3f910Sjsing if (sbuf_len <= 0) { 1439dab3f910Sjsing read_ssl = 1; 1440dab3f910Sjsing write_tty = 0; 1441dab3f910Sjsing } 14429c8ea7b6Sderaadt } else if (ssl_pending || (pfd[2].revents & (POLLIN|POLLHUP))) { 1443dab3f910Sjsing #ifdef RENEG 1444dab3f910Sjsing { 1445dab3f910Sjsing static int iiii; 1446dab3f910Sjsing if (++iiii == 52) { 1447dab3f910Sjsing SSL_renegotiate(con); 1448dab3f910Sjsing iiii = 0; 1449dab3f910Sjsing } 1450dab3f910Sjsing } 1451dab3f910Sjsing #endif 1452e7718adaStb if (cfg.peekaboo) { 1453bfef4384Sjsing k = p = SSL_peek(con, pbuf, 1024 /* BUFSIZZ */ ); 1454586463feSbeck pending = SSL_pending(con); 1455bfef4384Sjsing if (SSL_get_error(con, p) == SSL_ERROR_NONE) { 14569c84cee0Sbeck if (p <= 0) 14579c84cee0Sbeck goto end; 14589c84cee0Sbeck 1459bfef4384Sjsing k = SSL_read(con, sbuf, p); 14609c84cee0Sbeck } 1461bfef4384Sjsing } else { 1462dab3f910Sjsing k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ ); 1463bfef4384Sjsing } 1464dab3f910Sjsing 1465dab3f910Sjsing switch (SSL_get_error(con, k)) { 1466dab3f910Sjsing case SSL_ERROR_NONE: 1467dab3f910Sjsing if (k <= 0) 1468dab3f910Sjsing goto end; 1469dab3f910Sjsing sbuf_off = 0; 1470dab3f910Sjsing sbuf_len = k; 1471e7718adaStb if (cfg.peekaboo) { 1472586463feSbeck if (p != pending) { 1473586463feSbeck ret = -1; 1474586463feSbeck BIO_printf(bio_err, 14756369f9f8Sinoguchi "peeked %d but pending %d!\n", 14766369f9f8Sinoguchi p, pending); 1477586463feSbeck goto shut; 1478586463feSbeck } 14799c84cee0Sbeck if (k < p) { 14809c84cee0Sbeck ret = -1; 14819c84cee0Sbeck BIO_printf(bio_err, 14829c84cee0Sbeck "read less than peek!\n"); 14839c84cee0Sbeck goto shut; 14849c84cee0Sbeck } 14856369f9f8Sinoguchi if (p > 0 && 14866369f9f8Sinoguchi (memcmp(sbuf, pbuf, p) != 0)) { 14879c84cee0Sbeck ret = -1; 14889c84cee0Sbeck BIO_printf(bio_err, 14899c84cee0Sbeck "peek of %d different from read of %d!\n", 14909c84cee0Sbeck p, k); 14919c84cee0Sbeck goto shut; 14929c84cee0Sbeck } 14939c84cee0Sbeck } 1494dab3f910Sjsing read_ssl = 0; 1495dab3f910Sjsing write_tty = 1; 1496dab3f910Sjsing break; 1497dab3f910Sjsing case SSL_ERROR_WANT_WRITE: 1498dab3f910Sjsing BIO_printf(bio_c_out, "read W BLOCK\n"); 1499dab3f910Sjsing write_ssl = 1; 1500dab3f910Sjsing read_tty = 0; 1501dab3f910Sjsing break; 1502dab3f910Sjsing case SSL_ERROR_WANT_READ: 1503dab3f910Sjsing BIO_printf(bio_c_out, "read R BLOCK\n"); 1504dab3f910Sjsing write_tty = 0; 1505dab3f910Sjsing read_ssl = 1; 1506dab3f910Sjsing if ((read_tty == 0) && (write_ssl == 0)) 1507dab3f910Sjsing write_ssl = 1; 1508dab3f910Sjsing break; 1509dab3f910Sjsing case SSL_ERROR_WANT_X509_LOOKUP: 1510dab3f910Sjsing BIO_printf(bio_c_out, "read X BLOCK\n"); 1511dab3f910Sjsing break; 1512dab3f910Sjsing case SSL_ERROR_SYSCALL: 1513dab3f910Sjsing ret = errno; 1514dab3f910Sjsing BIO_printf(bio_err, "read:errno=%d\n", ret); 1515dab3f910Sjsing goto shut; 1516dab3f910Sjsing case SSL_ERROR_ZERO_RETURN: 1517dab3f910Sjsing BIO_printf(bio_c_out, "closed\n"); 1518dab3f910Sjsing ret = 0; 1519dab3f910Sjsing goto shut; 1520dab3f910Sjsing case SSL_ERROR_SSL: 1521dab3f910Sjsing ERR_print_errors(bio_err); 1522dab3f910Sjsing goto shut; 1523dab3f910Sjsing /* break; */ 1524dab3f910Sjsing } 15259c8ea7b6Sderaadt } else if (pfd[0].revents) { 15269c8ea7b6Sderaadt if (pfd[0].revents & (POLLERR|POLLNVAL)) { 15279c8ea7b6Sderaadt BIO_printf(bio_err, "poll error"); 15289c8ea7b6Sderaadt goto shut; 15299c8ea7b6Sderaadt } 1530e7718adaStb if (cfg.crlf) { 1531dab3f910Sjsing int j, lf_num; 1532dab3f910Sjsing 1533dab3f910Sjsing i = read(fileno(stdin), cbuf, BUFSIZZ / 2); 1534dab3f910Sjsing lf_num = 0; 1535dab3f910Sjsing /* both loops are skipped when i <= 0 */ 1536dab3f910Sjsing for (j = 0; j < i; j++) 1537dab3f910Sjsing if (cbuf[j] == '\n') 1538dab3f910Sjsing lf_num++; 1539dab3f910Sjsing for (j = i - 1; j >= 0; j--) { 1540dab3f910Sjsing cbuf[j + lf_num] = cbuf[j]; 1541dab3f910Sjsing if (cbuf[j] == '\n') { 1542dab3f910Sjsing lf_num--; 1543dab3f910Sjsing i++; 1544dab3f910Sjsing cbuf[j + lf_num] = '\r'; 1545dab3f910Sjsing } 1546dab3f910Sjsing } 1547dab3f910Sjsing assert(lf_num == 0); 1548dab3f910Sjsing } else 1549dab3f910Sjsing i = read(fileno(stdin), cbuf, BUFSIZZ); 1550dab3f910Sjsing 1551e7718adaStb if ((!cfg.ign_eof) && 15526369f9f8Sinoguchi ((i <= 0) || (cbuf[0] == 'Q'))) { 1553dab3f910Sjsing BIO_printf(bio_err, "DONE\n"); 1554dab3f910Sjsing ret = 0; 1555dab3f910Sjsing goto shut; 1556dab3f910Sjsing } 1557e7718adaStb if ((!cfg.ign_eof) && (cbuf[0] == 'R')) { 1558dab3f910Sjsing BIO_printf(bio_err, "RENEGOTIATING\n"); 1559dab3f910Sjsing SSL_renegotiate(con); 1560dab3f910Sjsing cbuf_len = 0; 1561dab3f910Sjsing } else { 1562dab3f910Sjsing cbuf_len = i; 1563dab3f910Sjsing cbuf_off = 0; 1564dab3f910Sjsing } 1565dab3f910Sjsing 1566dab3f910Sjsing write_ssl = 1; 1567dab3f910Sjsing read_tty = 0; 1568dab3f910Sjsing } 1569dab3f910Sjsing } 1570dab3f910Sjsing 1571dab3f910Sjsing ret = 0; 1572dab3f910Sjsing shut: 1573dab3f910Sjsing if (in_init) 1574dab3f910Sjsing print_stuff(bio_c_out, con, full_log); 1575dab3f910Sjsing SSL_shutdown(con); 1576dab3f910Sjsing shutdown(SSL_get_fd(con), SHUT_RD); 1577dab3f910Sjsing close(SSL_get_fd(con)); 1578dab3f910Sjsing end: 1579dab3f910Sjsing if (con != NULL) { 1580e7718adaStb if (cfg.prexit != 0) 1581dab3f910Sjsing print_stuff(bio_c_out, con, 1); 1582dab3f910Sjsing SSL_free(con); 1583dab3f910Sjsing } 1584dab3f910Sjsing SSL_CTX_free(ctx); 1585dab3f910Sjsing X509_free(cert); 1586dab3f910Sjsing EVP_PKEY_free(key); 1587dab3f910Sjsing free(pass); 1588e7718adaStb X509_VERIFY_PARAM_free(cfg.vpm); 1589cf4db30dSderaadt freezero(cbuf, BUFSIZZ); 1590cf4db30dSderaadt freezero(sbuf, BUFSIZZ); 15911b9cd2daStb freezero(pbuf, BUFSIZZ); 1592cf4db30dSderaadt freezero(mbuf, BUFSIZZ); 1593dab3f910Sjsing BIO_free(bio_c_out); 1594dab3f910Sjsing 1595dab3f910Sjsing return (ret); 1596dab3f910Sjsing } 1597dab3f910Sjsing 1598dab3f910Sjsing static void 1599dab3f910Sjsing print_stuff(BIO *bio, SSL *s, int full) 1600dab3f910Sjsing { 1601dab3f910Sjsing X509 *peer = NULL; 1602dab3f910Sjsing char *p; 1603dab3f910Sjsing static const char *space = " "; 1604dab3f910Sjsing char buf[BUFSIZ]; 1605dab3f910Sjsing STACK_OF(X509) *sk; 1606dab3f910Sjsing STACK_OF(X509_NAME) *sk2; 1607dab3f910Sjsing const SSL_CIPHER *c; 1608dab3f910Sjsing X509_NAME *xn; 1609dab3f910Sjsing int j, i; 1610dab3f910Sjsing unsigned char *exportedkeymat; 1611dab3f910Sjsing 1612dab3f910Sjsing if (full) { 1613dab3f910Sjsing int got_a_chain = 0; 1614dab3f910Sjsing 1615dab3f910Sjsing sk = SSL_get_peer_cert_chain(s); 1616dab3f910Sjsing if (sk != NULL) { 1617dab3f910Sjsing got_a_chain = 1; /* we don't have it for SSL2 1618dab3f910Sjsing * (yet) */ 1619dab3f910Sjsing 1620dab3f910Sjsing BIO_printf(bio, "---\nCertificate chain\n"); 1621dab3f910Sjsing for (i = 0; i < sk_X509_num(sk); i++) { 1622dab3f910Sjsing X509_NAME_oneline(X509_get_subject_name( 1623dab3f910Sjsing sk_X509_value(sk, i)), buf, sizeof buf); 1624dab3f910Sjsing BIO_printf(bio, "%2d s:%s\n", i, buf); 1625dab3f910Sjsing X509_NAME_oneline(X509_get_issuer_name( 1626dab3f910Sjsing sk_X509_value(sk, i)), buf, sizeof buf); 1627dab3f910Sjsing BIO_printf(bio, " i:%s\n", buf); 1628e7718adaStb if (cfg.showcerts) 16296369f9f8Sinoguchi PEM_write_bio_X509(bio, 16306369f9f8Sinoguchi sk_X509_value(sk, i)); 1631dab3f910Sjsing } 1632dab3f910Sjsing } 1633dab3f910Sjsing BIO_printf(bio, "---\n"); 1634dab3f910Sjsing peer = SSL_get_peer_certificate(s); 1635dab3f910Sjsing if (peer != NULL) { 1636dab3f910Sjsing BIO_printf(bio, "Server certificate\n"); 1637e7718adaStb if (!(cfg.showcerts && got_a_chain)) { 16386369f9f8Sinoguchi /* Redundant if we showed the whole chain */ 1639dab3f910Sjsing PEM_write_bio_X509(bio, peer); 16406369f9f8Sinoguchi } 1641dab3f910Sjsing X509_NAME_oneline(X509_get_subject_name(peer), 1642dab3f910Sjsing buf, sizeof buf); 1643dab3f910Sjsing BIO_printf(bio, "subject=%s\n", buf); 1644dab3f910Sjsing X509_NAME_oneline(X509_get_issuer_name(peer), 1645dab3f910Sjsing buf, sizeof buf); 1646dab3f910Sjsing BIO_printf(bio, "issuer=%s\n", buf); 1647dab3f910Sjsing } else 1648dab3f910Sjsing BIO_printf(bio, "no peer certificate available\n"); 1649dab3f910Sjsing 1650dab3f910Sjsing sk2 = SSL_get_client_CA_list(s); 1651dab3f910Sjsing if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) { 16526369f9f8Sinoguchi BIO_printf(bio, 16536369f9f8Sinoguchi "---\nAcceptable client certificate CA names\n"); 1654dab3f910Sjsing for (i = 0; i < sk_X509_NAME_num(sk2); i++) { 1655dab3f910Sjsing xn = sk_X509_NAME_value(sk2, i); 1656dab3f910Sjsing X509_NAME_oneline(xn, buf, sizeof(buf)); 1657dab3f910Sjsing BIO_write(bio, buf, strlen(buf)); 1658dab3f910Sjsing BIO_write(bio, "\n", 1); 1659dab3f910Sjsing } 1660dab3f910Sjsing } else { 16616369f9f8Sinoguchi BIO_printf(bio, 16626369f9f8Sinoguchi "---\nNo client certificate CA names sent\n"); 1663dab3f910Sjsing } 1664dab3f910Sjsing p = SSL_get_shared_ciphers(s, buf, sizeof buf); 1665dab3f910Sjsing if (p != NULL) { 1666dab3f910Sjsing /* 1667dab3f910Sjsing * This works only for SSL 2. In later protocol 1668dab3f910Sjsing * versions, the client does not know what other 1669dab3f910Sjsing * ciphers (in addition to the one to be used in the 1670dab3f910Sjsing * current connection) the server supports. 1671dab3f910Sjsing */ 1672dab3f910Sjsing 16736369f9f8Sinoguchi BIO_printf(bio, 16746369f9f8Sinoguchi "---\nCiphers common between both SSL endpoints:\n"); 1675dab3f910Sjsing j = i = 0; 1676dab3f910Sjsing while (*p) { 1677dab3f910Sjsing if (*p == ':') { 1678dab3f910Sjsing BIO_write(bio, space, 15 - j % 25); 1679dab3f910Sjsing i++; 1680dab3f910Sjsing j = 0; 16816369f9f8Sinoguchi BIO_write(bio, 16826369f9f8Sinoguchi ((i % 3) ? " " : "\n"), 1); 1683dab3f910Sjsing } else { 1684dab3f910Sjsing BIO_write(bio, p, 1); 1685dab3f910Sjsing j++; 1686dab3f910Sjsing } 1687dab3f910Sjsing p++; 1688dab3f910Sjsing } 1689dab3f910Sjsing BIO_write(bio, "\n", 1); 1690dab3f910Sjsing } 169157a9ba28Sjsing 169257a9ba28Sjsing ssl_print_tmp_key(bio, s); 169357a9ba28Sjsing 16946369f9f8Sinoguchi BIO_printf(bio, 16956369f9f8Sinoguchi "---\nSSL handshake has read %ld bytes and written %ld bytes\n", 1696dab3f910Sjsing BIO_number_read(SSL_get_rbio(s)), 1697dab3f910Sjsing BIO_number_written(SSL_get_wbio(s))); 1698dab3f910Sjsing } 1699dab3f910Sjsing BIO_printf(bio, (SSL_cache_hit(s) ? "---\nReused, " : "---\nNew, ")); 1700dab3f910Sjsing c = SSL_get_current_cipher(s); 1701dab3f910Sjsing BIO_printf(bio, "%s, Cipher is %s\n", 1702dab3f910Sjsing SSL_CIPHER_get_version(c), 1703dab3f910Sjsing SSL_CIPHER_get_name(c)); 1704dab3f910Sjsing if (peer != NULL) { 1705dab3f910Sjsing EVP_PKEY *pktmp; 170684dd6e9aStb 170784dd6e9aStb pktmp = X509_get0_pubkey(peer); 1708dab3f910Sjsing BIO_printf(bio, "Server public key is %d bit\n", 1709dab3f910Sjsing EVP_PKEY_bits(pktmp)); 1710dab3f910Sjsing } 1711dab3f910Sjsing BIO_printf(bio, "Secure Renegotiation IS%s supported\n", 1712dab3f910Sjsing SSL_get_secure_renegotiation_support(s) ? "" : " NOT"); 1713dab3f910Sjsing 1714dab3f910Sjsing /* Compression is not supported and will always be none. */ 1715dab3f910Sjsing BIO_printf(bio, "Compression: NONE\n"); 1716dab3f910Sjsing BIO_printf(bio, "Expansion: NONE\n"); 1717dab3f910Sjsing 1718dab3f910Sjsing #ifdef SSL_DEBUG 1719dab3f910Sjsing { 1720dab3f910Sjsing /* Print out local port of connection: useful for debugging */ 1721dab3f910Sjsing int sock; 1722dab3f910Sjsing struct sockaddr_in ladd; 1723dab3f910Sjsing socklen_t ladd_size = sizeof(ladd); 1724dab3f910Sjsing sock = SSL_get_fd(s); 1725dab3f910Sjsing getsockname(sock, (struct sockaddr *) & ladd, &ladd_size); 17265042ef37Sinoguchi BIO_printf(bio, "LOCAL PORT is %u\n", 17276369f9f8Sinoguchi ntohs(ladd.sin_port)); 1728dab3f910Sjsing } 1729dab3f910Sjsing #endif 1730dab3f910Sjsing 17311b4c9cadSjsing { 17321b4c9cadSjsing const unsigned char *proto; 17331b4c9cadSjsing unsigned int proto_len; 17341b4c9cadSjsing SSL_get0_alpn_selected(s, &proto, &proto_len); 17351b4c9cadSjsing if (proto_len > 0) { 17361b4c9cadSjsing BIO_printf(bio, "ALPN protocol: "); 17371b4c9cadSjsing BIO_write(bio, proto, proto_len); 17381b4c9cadSjsing BIO_write(bio, "\n", 1); 17391b4c9cadSjsing } else 17401b4c9cadSjsing BIO_printf(bio, "No ALPN negotiated\n"); 17411b4c9cadSjsing } 1742dab3f910Sjsing 1743dab3f910Sjsing #ifndef OPENSSL_NO_SRTP 1744dab3f910Sjsing { 17456369f9f8Sinoguchi SRTP_PROTECTION_PROFILE *srtp_profile; 1746dab3f910Sjsing 17476369f9f8Sinoguchi srtp_profile = SSL_get_selected_srtp_profile(s); 1748dab3f910Sjsing if (srtp_profile) 17496369f9f8Sinoguchi BIO_printf(bio, 17506369f9f8Sinoguchi "SRTP Extension negotiated, profile=%s\n", 1751dab3f910Sjsing srtp_profile->name); 1752dab3f910Sjsing } 1753dab3f910Sjsing #endif 1754dab3f910Sjsing 1755dab3f910Sjsing SSL_SESSION_print(bio, SSL_get_session(s)); 1756e7718adaStb if (cfg.keymatexportlabel != NULL) { 1757dab3f910Sjsing BIO_printf(bio, "Keying material exporter:\n"); 17586369f9f8Sinoguchi BIO_printf(bio, " Label: '%s'\n", 1759e7718adaStb cfg.keymatexportlabel); 17606369f9f8Sinoguchi BIO_printf(bio, " Length: %i bytes\n", 1761e7718adaStb cfg.keymatexportlen); 1762e7718adaStb exportedkeymat = malloc(cfg.keymatexportlen); 1763dab3f910Sjsing if (exportedkeymat != NULL) { 1764dab3f910Sjsing if (!SSL_export_keying_material(s, exportedkeymat, 1765e7718adaStb cfg.keymatexportlen, 1766e7718adaStb cfg.keymatexportlabel, 1767e7718adaStb strlen(cfg.keymatexportlabel), 1768dab3f910Sjsing NULL, 0, 0)) { 1769dab3f910Sjsing BIO_printf(bio, " Error\n"); 1770dab3f910Sjsing } else { 1771dab3f910Sjsing BIO_printf(bio, " Keying material: "); 1772e7718adaStb for (i = 0; i < cfg.keymatexportlen; i++) 1773dab3f910Sjsing BIO_printf(bio, "%02X", 1774dab3f910Sjsing exportedkeymat[i]); 1775dab3f910Sjsing BIO_printf(bio, "\n"); 1776dab3f910Sjsing } 1777dab3f910Sjsing free(exportedkeymat); 1778dab3f910Sjsing } 1779dab3f910Sjsing } 1780dab3f910Sjsing BIO_printf(bio, "---\n"); 1781dab3f910Sjsing X509_free(peer); 1782dab3f910Sjsing /* flush, or debugging output gets mixed with http response */ 1783dab3f910Sjsing (void) BIO_flush(bio); 1784dab3f910Sjsing } 1785dab3f910Sjsing 1786dab3f910Sjsing static int 1787dab3f910Sjsing ocsp_resp_cb(SSL *s, void *arg) 1788dab3f910Sjsing { 1789dab3f910Sjsing const unsigned char *p; 1790dab3f910Sjsing int len; 1791dab3f910Sjsing OCSP_RESPONSE *rsp; 1792dab3f910Sjsing len = SSL_get_tlsext_status_ocsp_resp(s, &p); 1793dab3f910Sjsing BIO_puts(arg, "OCSP response: "); 1794dab3f910Sjsing if (!p) { 1795dab3f910Sjsing BIO_puts(arg, "no response sent\n"); 1796dab3f910Sjsing return 1; 1797dab3f910Sjsing } 1798dab3f910Sjsing rsp = d2i_OCSP_RESPONSE(NULL, &p, len); 1799dab3f910Sjsing if (!rsp) { 1800dab3f910Sjsing BIO_puts(arg, "response parse error\n"); 1801dab3f910Sjsing BIO_dump_indent(arg, (char *) p, len, 4); 1802dab3f910Sjsing return 0; 1803dab3f910Sjsing } 1804dab3f910Sjsing BIO_puts(arg, "\n======================================\n"); 1805dab3f910Sjsing OCSP_RESPONSE_print(arg, rsp, 0); 1806dab3f910Sjsing BIO_puts(arg, "======================================\n"); 1807dab3f910Sjsing OCSP_RESPONSE_free(rsp); 1808dab3f910Sjsing return 1; 1809dab3f910Sjsing } 1810dab3f910Sjsing 1811a2111520Sinoguchi static int 1812a2111520Sinoguchi ssl_servername_cb(SSL *s, int *ad, void *arg) 1813a2111520Sinoguchi { 1814a2111520Sinoguchi tlsextctx *p = (tlsextctx *) arg; 1815a2111520Sinoguchi const char *hn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); 1816a2111520Sinoguchi if (SSL_get_servername_type(s) != -1) 1817a2111520Sinoguchi p->ack = !SSL_session_reused(s) && hn != NULL; 1818a2111520Sinoguchi else 1819a2111520Sinoguchi BIO_printf(bio_err, "Can't use SSL_get_servername\n"); 1820a2111520Sinoguchi 1821a2111520Sinoguchi return SSL_TLSEXT_ERR_OK; 1822a2111520Sinoguchi } 1823a2111520Sinoguchi 1824