s_client.c revision 273415
155714Skris/* apps/s_client.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 58109998Smarkm/* ==================================================================== 59109998Smarkm * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 60109998Smarkm * 61109998Smarkm * Redistribution and use in source and binary forms, with or without 62109998Smarkm * modification, are permitted provided that the following conditions 63109998Smarkm * are met: 64109998Smarkm * 65109998Smarkm * 1. Redistributions of source code must retain the above copyright 66109998Smarkm * notice, this list of conditions and the following disclaimer. 67109998Smarkm * 68109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 69109998Smarkm * notice, this list of conditions and the following disclaimer in 70109998Smarkm * the documentation and/or other materials provided with the 71109998Smarkm * distribution. 72109998Smarkm * 73109998Smarkm * 3. All advertising materials mentioning features or use of this 74109998Smarkm * software must display the following acknowledgment: 75109998Smarkm * "This product includes software developed by the OpenSSL Project 76109998Smarkm * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77109998Smarkm * 78109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79109998Smarkm * endorse or promote products derived from this software without 80109998Smarkm * prior written permission. For written permission, please contact 81109998Smarkm * openssl-core@openssl.org. 82109998Smarkm * 83109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 84109998Smarkm * nor may "OpenSSL" appear in their names without prior written 85109998Smarkm * permission of the OpenSSL Project. 86109998Smarkm * 87109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 88109998Smarkm * acknowledgment: 89109998Smarkm * "This product includes software developed by the OpenSSL Project 90109998Smarkm * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 91109998Smarkm * 92109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 93109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 95109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 96109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 97109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 98109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 99109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 101109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 103109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 104109998Smarkm * ==================================================================== 105109998Smarkm * 106109998Smarkm * This product includes cryptographic software written by Eric Young 107109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 108109998Smarkm * Hudson (tjh@cryptsoft.com). 109109998Smarkm * 110109998Smarkm */ 11155714Skris 11259191Skris#include <assert.h> 11355714Skris#include <stdio.h> 11455714Skris#include <stdlib.h> 11555714Skris#include <string.h> 116109998Smarkm#include <openssl/e_os2.h> 117109998Smarkm#ifdef OPENSSL_NO_STDIO 11855714Skris#define APPS_WIN16 11955714Skris#endif 12055714Skris 12155714Skris/* With IPv6, it looks like Digital has mixed up the proper order of 12255714Skris recursive header file inclusion, resulting in the compiler complaining 12355714Skris that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which 12455714Skris is needed to have fileno() declared correctly... So let's define u_int */ 125109998Smarkm#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) 12655714Skris#define __U_INT 12755714Skristypedef unsigned int u_int; 12855714Skris#endif 12955714Skris 13055714Skris#define USE_SOCKETS 13155714Skris#include "apps.h" 13255714Skris#include <openssl/x509.h> 13355714Skris#include <openssl/ssl.h> 13455714Skris#include <openssl/err.h> 13555714Skris#include <openssl/pem.h> 13676866Skris#include <openssl/rand.h> 137194206Ssimon#include <openssl/ocsp.h> 13855714Skris#include "s_apps.h" 139160814Ssimon#include "timeouts.h" 14055714Skris 141109998Smarkm#ifdef OPENSSL_SYS_WINCE 142109998Smarkm/* Windows CE incorrectly defines fileno as returning void*, so to avoid problems below... */ 143109998Smarkm#ifdef fileno 144109998Smarkm#undef fileno 145109998Smarkm#endif 146109998Smarkm#define fileno(a) (int)_fileno(a) 147109998Smarkm#endif 14859191Skris 149109998Smarkm 150109998Smarkm#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) 15155714Skris/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ 15255714Skris#undef FIONBIO 15355714Skris#endif 15455714Skris 15555714Skris#undef PROG 15655714Skris#define PROG s_client_main 15755714Skris 15855714Skris/*#define SSL_HOST_NAME "www.netscape.com" */ 15955714Skris/*#define SSL_HOST_NAME "193.118.187.102" */ 16055714Skris#define SSL_HOST_NAME "localhost" 16155714Skris 16255714Skris/*#define TEST_CERT "client.pem" */ /* no default cert. */ 16355714Skris 16455714Skris#undef BUFSIZZ 16555714Skris#define BUFSIZZ 1024*8 16655714Skris 16755714Skrisextern int verify_depth; 16855714Skrisextern int verify_error; 16955714Skris 17055714Skris#ifdef FIONBIO 17155714Skrisstatic int c_nbio=0; 17255714Skris#endif 17355714Skrisstatic int c_Pause=0; 17455714Skrisstatic int c_debug=0; 175194206Ssimon#ifndef OPENSSL_NO_TLSEXT 176194206Ssimonstatic int c_tlsextdebug=0; 177194206Ssimonstatic int c_status_req=0; 178194206Ssimon#endif 179109998Smarkmstatic int c_msg=0; 18055714Skrisstatic int c_showcerts=0; 18155714Skris 18255714Skrisstatic void sc_usage(void); 18355714Skrisstatic void print_stuff(BIO *berr,SSL *con,int full); 184194206Ssimon#ifndef OPENSSL_NO_TLSEXT 185194206Ssimonstatic int ocsp_resp_cb(SSL *s, void *arg); 186194206Ssimon#endif 18755714Skrisstatic BIO *bio_c_out=NULL; 18855714Skrisstatic int c_quiet=0; 18959191Skrisstatic int c_ign_eof=0; 19055714Skris 19155714Skrisstatic void sc_usage(void) 19255714Skris { 19355714Skris BIO_printf(bio_err,"usage: s_client args\n"); 19455714Skris BIO_printf(bio_err,"\n"); 19555714Skris BIO_printf(bio_err," -host host - use -connect instead\n"); 19655714Skris BIO_printf(bio_err," -port port - use -connect instead\n"); 19755714Skris BIO_printf(bio_err," -connect host:port - who to connect to (default is %s:%s)\n",SSL_HOST_NAME,PORT_STR); 19855714Skris 199160814Ssimon BIO_printf(bio_err," -verify depth - turn on peer certificate verification\n"); 20055714Skris BIO_printf(bio_err," -cert arg - certificate file to use, PEM format assumed\n"); 201160814Ssimon BIO_printf(bio_err," -certform arg - certificate format (PEM or DER) PEM default\n"); 202160814Ssimon BIO_printf(bio_err," -key arg - Private key file to use, in cert file if\n"); 20355714Skris BIO_printf(bio_err," not specified but cert file is.\n"); 204160814Ssimon BIO_printf(bio_err," -keyform arg - key format (PEM or DER) PEM default\n"); 205160814Ssimon BIO_printf(bio_err," -pass arg - private key file pass phrase source\n"); 20655714Skris BIO_printf(bio_err," -CApath arg - PEM format directory of CA's\n"); 20755714Skris BIO_printf(bio_err," -CAfile arg - PEM format file of CA's\n"); 20855714Skris BIO_printf(bio_err," -reconnect - Drop and re-make the connection with the same Session-ID\n"); 20955714Skris BIO_printf(bio_err," -pause - sleep(1) after each read(2) and write(2) system call\n"); 21055714Skris BIO_printf(bio_err," -showcerts - show all certificates in the chain\n"); 21155714Skris BIO_printf(bio_err," -debug - extra output\n"); 212160814Ssimon#ifdef WATT32 213160814Ssimon BIO_printf(bio_err," -wdebug - WATT-32 tcp debugging\n"); 214160814Ssimon#endif 215109998Smarkm BIO_printf(bio_err," -msg - Show protocol messages\n"); 21655714Skris BIO_printf(bio_err," -nbio_test - more ssl protocol testing\n"); 21755714Skris BIO_printf(bio_err," -state - print the 'ssl' states\n"); 21855714Skris#ifdef FIONBIO 21955714Skris BIO_printf(bio_err," -nbio - Run with non-blocking IO\n"); 22055714Skris#endif 22155714Skris BIO_printf(bio_err," -crlf - convert LF from terminal into CRLF\n"); 22255714Skris BIO_printf(bio_err," -quiet - no s_client output\n"); 22359191Skris BIO_printf(bio_err," -ign_eof - ignore input eof (default when -quiet)\n"); 224194206Ssimon BIO_printf(bio_err," -no_ign_eof - don't ignore input eof\n"); 22555714Skris BIO_printf(bio_err," -ssl2 - just use SSLv2\n"); 22655714Skris BIO_printf(bio_err," -ssl3 - just use SSLv3\n"); 22755714Skris BIO_printf(bio_err," -tls1 - just use TLSv1\n"); 228160814Ssimon BIO_printf(bio_err," -dtls1 - just use DTLSv1\n"); 229273415Sdelphij BIO_printf(bio_err," -fallback_scsv - send TLS_FALLBACK_SCSV\n"); 230205128Ssimon BIO_printf(bio_err," -mtu - set the link layer MTU\n"); 23155714Skris BIO_printf(bio_err," -no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n"); 23255714Skris BIO_printf(bio_err," -bugs - Switch on all SSL implementation bug workarounds\n"); 233109998Smarkm BIO_printf(bio_err," -serverpref - Use server's cipher preferences (only SSLv2)\n"); 23459191Skris BIO_printf(bio_err," -cipher - preferred cipher to use, use the 'openssl ciphers'\n"); 23555714Skris BIO_printf(bio_err," command to see what is available\n"); 236109998Smarkm BIO_printf(bio_err," -starttls prot - use the STARTTLS command before starting TLS\n"); 237109998Smarkm BIO_printf(bio_err," for those protocols that support it, where\n"); 238109998Smarkm BIO_printf(bio_err," 'prot' defines which one to assume. Currently,\n"); 239194206Ssimon BIO_printf(bio_err," only \"smtp\", \"pop3\", \"imap\", \"ftp\" and \"xmpp\"\n"); 240194206Ssimon BIO_printf(bio_err," are supported.\n"); 241111147Snectar#ifndef OPENSSL_NO_ENGINE 242109998Smarkm BIO_printf(bio_err," -engine id - Initialise and use the specified engine\n"); 243111147Snectar#endif 24476866Skris BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); 245194206Ssimon BIO_printf(bio_err," -sess_out arg - file to write SSL session to\n"); 246194206Ssimon BIO_printf(bio_err," -sess_in arg - file to read SSL session from\n"); 247194206Ssimon#ifndef OPENSSL_NO_TLSEXT 248194206Ssimon BIO_printf(bio_err," -servername host - Set TLS extension servername in ClientHello\n"); 249194206Ssimon BIO_printf(bio_err," -tlsextdebug - hex dump of all TLS extensions received\n"); 250194206Ssimon BIO_printf(bio_err," -status - request certificate status from server\n"); 251194206Ssimon BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n"); 252194206Ssimon#endif 253205128Ssimon BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n"); 254194206Ssimon } 25555714Skris 256194206Ssimon#ifndef OPENSSL_NO_TLSEXT 257194206Ssimon 258194206Ssimon/* This is a context that we pass to callbacks */ 259194206Ssimontypedef struct tlsextctx_st { 260194206Ssimon BIO * biodebug; 261194206Ssimon int ack; 262194206Ssimon} tlsextctx; 263194206Ssimon 264194206Ssimon 265194206Ssimonstatic int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) 266194206Ssimon { 267194206Ssimon tlsextctx * p = (tlsextctx *) arg; 268194206Ssimon const char * hn= SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); 269194206Ssimon if (SSL_get_servername_type(s) != -1) 270194206Ssimon p->ack = !SSL_session_reused(s) && hn != NULL; 271194206Ssimon else 272194206Ssimon BIO_printf(bio_err,"Can't use SSL_get_servername\n"); 273194206Ssimon 274194206Ssimon return SSL_TLSEXT_ERR_OK; 27555714Skris } 276194206Ssimon#endif 277167612Ssimonenum 278167612Ssimon{ 279167612Ssimon PROTO_OFF = 0, 280167612Ssimon PROTO_SMTP, 281167612Ssimon PROTO_POP3, 282167612Ssimon PROTO_IMAP, 283194206Ssimon PROTO_FTP, 284194206Ssimon PROTO_XMPP 285167612Ssimon}; 286167612Ssimon 28759191Skrisint MAIN(int, char **); 28859191Skris 28955714Skrisint MAIN(int argc, char **argv) 29055714Skris { 291205128Ssimon int off=0, clr = 0; 29255714Skris SSL *con=NULL,*con2=NULL; 293109998Smarkm X509_STORE *store = NULL; 29455714Skris int s,k,width,state=0; 295109998Smarkm char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL; 29655714Skris int cbuf_len,cbuf_off; 29755714Skris int sbuf_len,sbuf_off; 29855714Skris fd_set readfds,writefds; 29955714Skris short port=PORT; 30055714Skris int full_log=1; 30155714Skris char *host=SSL_HOST_NAME; 30255714Skris char *cert_file=NULL,*key_file=NULL; 303160814Ssimon int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; 304160814Ssimon char *passarg = NULL, *pass = NULL; 305160814Ssimon X509 *cert = NULL; 306160814Ssimon EVP_PKEY *key = NULL; 30755714Skris char *CApath=NULL,*CAfile=NULL,*cipher=NULL; 30855714Skris int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0; 30955714Skris int crlf=0; 31055714Skris int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending; 31155714Skris SSL_CTX *ctx=NULL; 31255714Skris int ret=1,in_init=1,i,nbio_test=0; 313167612Ssimon int starttls_proto = PROTO_OFF; 314109998Smarkm int prexit = 0, vflags = 0; 31555714Skris SSL_METHOD *meth=NULL; 316160814Ssimon#ifdef sock_type 317160814Ssimon#undef sock_type 318160814Ssimon#endif 319160814Ssimon int sock_type=SOCK_STREAM; 32055714Skris BIO *sbio; 32176866Skris char *inrand=NULL; 322167612Ssimon int mbuf_len=0; 323205128Ssimon struct timeval timeout, *timeoutp; 324111147Snectar#ifndef OPENSSL_NO_ENGINE 325109998Smarkm char *engine_id=NULL; 326194206Ssimon char *ssl_client_engine_id=NULL; 327194206Ssimon ENGINE *ssl_client_engine=NULL; 328194206Ssimon#endif 329109998Smarkm ENGINE *e=NULL; 330160814Ssimon#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) 33159191Skris struct timeval tv; 33259191Skris#endif 33355714Skris 334194206Ssimon#ifndef OPENSSL_NO_TLSEXT 335194206Ssimon char *servername = NULL; 336194206Ssimon tlsextctx tlsextcbp = 337194206Ssimon {NULL,0}; 338194206Ssimon#endif 339194206Ssimon char *sess_in = NULL; 340194206Ssimon char *sess_out = NULL; 341160814Ssimon struct sockaddr peer; 342160814Ssimon int peerlen = sizeof(peer); 343273415Sdelphij int fallback_scsv = 0; 344160814Ssimon int enable_timeouts = 0 ; 345205128Ssimon long socket_mtu = 0; 346194206Ssimon#ifndef OPENSSL_NO_JPAKE 347194206Ssimon char *jpake_secret = NULL; 348194206Ssimon#endif 349160814Ssimon 35055714Skris meth=SSLv23_client_method(); 35155714Skris 35255714Skris apps_startup(); 35355714Skris c_Pause=0; 35455714Skris c_quiet=0; 35559191Skris c_ign_eof=0; 35655714Skris c_debug=0; 357109998Smarkm c_msg=0; 35855714Skris c_showcerts=0; 35955714Skris 36055714Skris if (bio_err == NULL) 36155714Skris bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); 36255714Skris 363109998Smarkm if (!load_config(bio_err, NULL)) 364109998Smarkm goto end; 365109998Smarkm 36668651Skris if ( ((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || 367109998Smarkm ((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || 368109998Smarkm ((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL)) 36955714Skris { 37055714Skris BIO_printf(bio_err,"out of memory\n"); 37155714Skris goto end; 37255714Skris } 37355714Skris 37455714Skris verify_depth=0; 37555714Skris verify_error=X509_V_OK; 37655714Skris#ifdef FIONBIO 37755714Skris c_nbio=0; 37855714Skris#endif 37955714Skris 38055714Skris argc--; 38155714Skris argv++; 38255714Skris while (argc >= 1) 38355714Skris { 38455714Skris if (strcmp(*argv,"-host") == 0) 38555714Skris { 38655714Skris if (--argc < 1) goto bad; 38755714Skris host= *(++argv); 38855714Skris } 38955714Skris else if (strcmp(*argv,"-port") == 0) 39055714Skris { 39155714Skris if (--argc < 1) goto bad; 39255714Skris port=atoi(*(++argv)); 39355714Skris if (port == 0) goto bad; 39455714Skris } 39555714Skris else if (strcmp(*argv,"-connect") == 0) 39655714Skris { 39755714Skris if (--argc < 1) goto bad; 39855714Skris if (!extract_host_port(*(++argv),&host,NULL,&port)) 39955714Skris goto bad; 40055714Skris } 40155714Skris else if (strcmp(*argv,"-verify") == 0) 40255714Skris { 40355714Skris verify=SSL_VERIFY_PEER; 40455714Skris if (--argc < 1) goto bad; 40555714Skris verify_depth=atoi(*(++argv)); 40655714Skris BIO_printf(bio_err,"verify depth is %d\n",verify_depth); 40755714Skris } 40855714Skris else if (strcmp(*argv,"-cert") == 0) 40955714Skris { 41055714Skris if (--argc < 1) goto bad; 41155714Skris cert_file= *(++argv); 41255714Skris } 413194206Ssimon else if (strcmp(*argv,"-sess_out") == 0) 414194206Ssimon { 415194206Ssimon if (--argc < 1) goto bad; 416194206Ssimon sess_out = *(++argv); 417194206Ssimon } 418194206Ssimon else if (strcmp(*argv,"-sess_in") == 0) 419194206Ssimon { 420194206Ssimon if (--argc < 1) goto bad; 421194206Ssimon sess_in = *(++argv); 422194206Ssimon } 423160814Ssimon else if (strcmp(*argv,"-certform") == 0) 424160814Ssimon { 425160814Ssimon if (--argc < 1) goto bad; 426160814Ssimon cert_format = str2fmt(*(++argv)); 427160814Ssimon } 428109998Smarkm else if (strcmp(*argv,"-crl_check") == 0) 429109998Smarkm vflags |= X509_V_FLAG_CRL_CHECK; 430109998Smarkm else if (strcmp(*argv,"-crl_check_all") == 0) 431109998Smarkm vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; 43259191Skris else if (strcmp(*argv,"-prexit") == 0) 43359191Skris prexit=1; 43455714Skris else if (strcmp(*argv,"-crlf") == 0) 43555714Skris crlf=1; 43655714Skris else if (strcmp(*argv,"-quiet") == 0) 43759191Skris { 43855714Skris c_quiet=1; 43959191Skris c_ign_eof=1; 44059191Skris } 44159191Skris else if (strcmp(*argv,"-ign_eof") == 0) 44259191Skris c_ign_eof=1; 443194206Ssimon else if (strcmp(*argv,"-no_ign_eof") == 0) 444194206Ssimon c_ign_eof=0; 44555714Skris else if (strcmp(*argv,"-pause") == 0) 44655714Skris c_Pause=1; 44755714Skris else if (strcmp(*argv,"-debug") == 0) 44855714Skris c_debug=1; 449194206Ssimon#ifndef OPENSSL_NO_TLSEXT 450194206Ssimon else if (strcmp(*argv,"-tlsextdebug") == 0) 451194206Ssimon c_tlsextdebug=1; 452194206Ssimon else if (strcmp(*argv,"-status") == 0) 453194206Ssimon c_status_req=1; 454194206Ssimon#endif 455160814Ssimon#ifdef WATT32 456160814Ssimon else if (strcmp(*argv,"-wdebug") == 0) 457160814Ssimon dbug_init(); 458160814Ssimon#endif 459109998Smarkm else if (strcmp(*argv,"-msg") == 0) 460109998Smarkm c_msg=1; 46155714Skris else if (strcmp(*argv,"-showcerts") == 0) 46255714Skris c_showcerts=1; 46355714Skris else if (strcmp(*argv,"-nbio_test") == 0) 46455714Skris nbio_test=1; 46555714Skris else if (strcmp(*argv,"-state") == 0) 46655714Skris state=1; 467109998Smarkm#ifndef OPENSSL_NO_SSL2 46855714Skris else if (strcmp(*argv,"-ssl2") == 0) 46955714Skris meth=SSLv2_client_method(); 47055714Skris#endif 471109998Smarkm#ifndef OPENSSL_NO_SSL3 47255714Skris else if (strcmp(*argv,"-ssl3") == 0) 47355714Skris meth=SSLv3_client_method(); 47455714Skris#endif 475109998Smarkm#ifndef OPENSSL_NO_TLS1 47655714Skris else if (strcmp(*argv,"-tls1") == 0) 47755714Skris meth=TLSv1_client_method(); 47855714Skris#endif 479160814Ssimon#ifndef OPENSSL_NO_DTLS1 480160814Ssimon else if (strcmp(*argv,"-dtls1") == 0) 481160814Ssimon { 482160814Ssimon meth=DTLSv1_client_method(); 483160814Ssimon sock_type=SOCK_DGRAM; 484160814Ssimon } 485160814Ssimon else if (strcmp(*argv,"-timeout") == 0) 486160814Ssimon enable_timeouts=1; 487160814Ssimon else if (strcmp(*argv,"-mtu") == 0) 488160814Ssimon { 489160814Ssimon if (--argc < 1) goto bad; 490205128Ssimon socket_mtu = atol(*(++argv)); 491160814Ssimon } 492160814Ssimon#endif 493273415Sdelphij else if (strcmp(*argv,"-fallback_scsv") == 0) 494273415Sdelphij { 495273415Sdelphij fallback_scsv = 1; 496273415Sdelphij } 49755714Skris else if (strcmp(*argv,"-bugs") == 0) 49855714Skris bugs=1; 499160814Ssimon else if (strcmp(*argv,"-keyform") == 0) 500160814Ssimon { 501160814Ssimon if (--argc < 1) goto bad; 502160814Ssimon key_format = str2fmt(*(++argv)); 503160814Ssimon } 504160814Ssimon else if (strcmp(*argv,"-pass") == 0) 505160814Ssimon { 506160814Ssimon if (--argc < 1) goto bad; 507160814Ssimon passarg = *(++argv); 508160814Ssimon } 50955714Skris else if (strcmp(*argv,"-key") == 0) 51055714Skris { 51155714Skris if (--argc < 1) goto bad; 51255714Skris key_file= *(++argv); 51355714Skris } 51455714Skris else if (strcmp(*argv,"-reconnect") == 0) 51555714Skris { 51655714Skris reconnect=5; 51755714Skris } 51855714Skris else if (strcmp(*argv,"-CApath") == 0) 51955714Skris { 52055714Skris if (--argc < 1) goto bad; 52155714Skris CApath= *(++argv); 52255714Skris } 52355714Skris else if (strcmp(*argv,"-CAfile") == 0) 52455714Skris { 52555714Skris if (--argc < 1) goto bad; 52655714Skris CAfile= *(++argv); 52755714Skris } 52855714Skris else if (strcmp(*argv,"-no_tls1") == 0) 52955714Skris off|=SSL_OP_NO_TLSv1; 53055714Skris else if (strcmp(*argv,"-no_ssl3") == 0) 53155714Skris off|=SSL_OP_NO_SSLv3; 53255714Skris else if (strcmp(*argv,"-no_ssl2") == 0) 53355714Skris off|=SSL_OP_NO_SSLv2; 534194206Ssimon#ifndef OPENSSL_NO_TLSEXT 535194206Ssimon else if (strcmp(*argv,"-no_ticket") == 0) 536194206Ssimon { off|=SSL_OP_NO_TICKET; } 537194206Ssimon#endif 538109998Smarkm else if (strcmp(*argv,"-serverpref") == 0) 539109998Smarkm off|=SSL_OP_CIPHER_SERVER_PREFERENCE; 540205128Ssimon else if (strcmp(*argv,"-legacy_renegotiation") == 0) 541205128Ssimon off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; 542205128Ssimon else if (strcmp(*argv,"-legacy_server_connect") == 0) 543205128Ssimon { off|=SSL_OP_LEGACY_SERVER_CONNECT; } 544205128Ssimon else if (strcmp(*argv,"-no_legacy_server_connect") == 0) 545205128Ssimon { clr|=SSL_OP_LEGACY_SERVER_CONNECT; } 54655714Skris else if (strcmp(*argv,"-cipher") == 0) 54755714Skris { 54855714Skris if (--argc < 1) goto bad; 54955714Skris cipher= *(++argv); 55055714Skris } 55155714Skris#ifdef FIONBIO 55255714Skris else if (strcmp(*argv,"-nbio") == 0) 55355714Skris { c_nbio=1; } 55455714Skris#endif 555109998Smarkm else if (strcmp(*argv,"-starttls") == 0) 556109998Smarkm { 557109998Smarkm if (--argc < 1) goto bad; 558109998Smarkm ++argv; 559109998Smarkm if (strcmp(*argv,"smtp") == 0) 560167612Ssimon starttls_proto = PROTO_SMTP; 561120631Snectar else if (strcmp(*argv,"pop3") == 0) 562167612Ssimon starttls_proto = PROTO_POP3; 563167612Ssimon else if (strcmp(*argv,"imap") == 0) 564167612Ssimon starttls_proto = PROTO_IMAP; 565167612Ssimon else if (strcmp(*argv,"ftp") == 0) 566167612Ssimon starttls_proto = PROTO_FTP; 567194206Ssimon else if (strcmp(*argv, "xmpp") == 0) 568194206Ssimon starttls_proto = PROTO_XMPP; 569109998Smarkm else 570109998Smarkm goto bad; 571109998Smarkm } 572111147Snectar#ifndef OPENSSL_NO_ENGINE 573109998Smarkm else if (strcmp(*argv,"-engine") == 0) 574109998Smarkm { 575109998Smarkm if (--argc < 1) goto bad; 576109998Smarkm engine_id = *(++argv); 577109998Smarkm } 578194206Ssimon else if (strcmp(*argv,"-ssl_client_engine") == 0) 579194206Ssimon { 580194206Ssimon if (--argc < 1) goto bad; 581194206Ssimon ssl_client_engine_id = *(++argv); 582194206Ssimon } 583111147Snectar#endif 58476866Skris else if (strcmp(*argv,"-rand") == 0) 58576866Skris { 58676866Skris if (--argc < 1) goto bad; 58776866Skris inrand= *(++argv); 58876866Skris } 589194206Ssimon#ifndef OPENSSL_NO_TLSEXT 590194206Ssimon else if (strcmp(*argv,"-servername") == 0) 591194206Ssimon { 592194206Ssimon if (--argc < 1) goto bad; 593194206Ssimon servername= *(++argv); 594194206Ssimon /* meth=TLSv1_client_method(); */ 595194206Ssimon } 596194206Ssimon#endif 597194206Ssimon#ifndef OPENSSL_NO_JPAKE 598194206Ssimon else if (strcmp(*argv,"-jpake") == 0) 599194206Ssimon { 600194206Ssimon if (--argc < 1) goto bad; 601194206Ssimon jpake_secret = *++argv; 602194206Ssimon } 603194206Ssimon#endif 60455714Skris else 60555714Skris { 60655714Skris BIO_printf(bio_err,"unknown option %s\n",*argv); 60755714Skris badop=1; 60855714Skris break; 60955714Skris } 61055714Skris argc--; 61155714Skris argv++; 61255714Skris } 61355714Skris if (badop) 61455714Skris { 61555714Skrisbad: 61655714Skris sc_usage(); 61755714Skris goto end; 61855714Skris } 61955714Skris 620109998Smarkm OpenSSL_add_ssl_algorithms(); 621109998Smarkm SSL_load_error_strings(); 622109998Smarkm 623111147Snectar#ifndef OPENSSL_NO_ENGINE 624109998Smarkm e = setup_engine(bio_err, engine_id, 1); 625194206Ssimon if (ssl_client_engine_id) 626194206Ssimon { 627194206Ssimon ssl_client_engine = ENGINE_by_id(ssl_client_engine_id); 628194206Ssimon if (!ssl_client_engine) 629194206Ssimon { 630194206Ssimon BIO_printf(bio_err, 631194206Ssimon "Error getting client auth engine\n"); 632194206Ssimon goto end; 633194206Ssimon } 634194206Ssimon } 635111147Snectar#endif 636160814Ssimon if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) 637160814Ssimon { 638160814Ssimon BIO_printf(bio_err, "Error getting password\n"); 639160814Ssimon goto end; 640160814Ssimon } 641109998Smarkm 642160814Ssimon if (key_file == NULL) 643160814Ssimon key_file = cert_file; 644160814Ssimon 645160814Ssimon 646160814Ssimon if (key_file) 647160814Ssimon 648160814Ssimon { 649160814Ssimon 650160814Ssimon key = load_key(bio_err, key_file, key_format, 0, pass, e, 651160814Ssimon "client certificate private key file"); 652160814Ssimon if (!key) 653160814Ssimon { 654160814Ssimon ERR_print_errors(bio_err); 655160814Ssimon goto end; 656160814Ssimon } 657160814Ssimon 658160814Ssimon } 659160814Ssimon 660160814Ssimon if (cert_file) 661160814Ssimon 662160814Ssimon { 663160814Ssimon cert = load_cert(bio_err,cert_file,cert_format, 664160814Ssimon NULL, e, "client certificate file"); 665160814Ssimon 666160814Ssimon if (!cert) 667160814Ssimon { 668160814Ssimon ERR_print_errors(bio_err); 669160814Ssimon goto end; 670160814Ssimon } 671160814Ssimon } 672160814Ssimon 67376866Skris if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL 67476866Skris && !RAND_status()) 67576866Skris { 67676866Skris BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); 67776866Skris } 67876866Skris if (inrand != NULL) 67976866Skris BIO_printf(bio_err,"%ld semi-random bytes loaded\n", 68076866Skris app_RAND_load_files(inrand)); 68159191Skris 68255714Skris if (bio_c_out == NULL) 68355714Skris { 684109998Smarkm if (c_quiet && !c_debug && !c_msg) 68555714Skris { 68655714Skris bio_c_out=BIO_new(BIO_s_null()); 68755714Skris } 68855714Skris else 68955714Skris { 69055714Skris if (bio_c_out == NULL) 69155714Skris bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE); 69255714Skris } 69355714Skris } 69455714Skris 69555714Skris ctx=SSL_CTX_new(meth); 69655714Skris if (ctx == NULL) 69755714Skris { 69855714Skris ERR_print_errors(bio_err); 69955714Skris goto end; 70055714Skris } 70155714Skris 702194206Ssimon#ifndef OPENSSL_NO_ENGINE 703194206Ssimon if (ssl_client_engine) 704194206Ssimon { 705194206Ssimon if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) 706194206Ssimon { 707194206Ssimon BIO_puts(bio_err, "Error setting client auth engine\n"); 708194206Ssimon ERR_print_errors(bio_err); 709194206Ssimon ENGINE_free(ssl_client_engine); 710194206Ssimon goto end; 711194206Ssimon } 712194206Ssimon ENGINE_free(ssl_client_engine); 713194206Ssimon } 714194206Ssimon#endif 715194206Ssimon 71655714Skris if (bugs) 71755714Skris SSL_CTX_set_options(ctx,SSL_OP_ALL|off); 71855714Skris else 71955714Skris SSL_CTX_set_options(ctx,off); 720205128Ssimon 721205128Ssimon if (clr) 722205128Ssimon SSL_CTX_clear_options(ctx, clr); 723160814Ssimon /* DTLS: partial reads end up discarding unread UDP bytes :-( 724160814Ssimon * Setting read ahead solves this problem. 725160814Ssimon */ 726160814Ssimon if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); 72755714Skris 72855714Skris if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); 72955714Skris if (cipher != NULL) 73059191Skris if(!SSL_CTX_set_cipher_list(ctx,cipher)) { 73159191Skris BIO_printf(bio_err,"error setting cipher list\n"); 73259191Skris ERR_print_errors(bio_err); 73359191Skris goto end; 73459191Skris } 73555714Skris#if 0 73655714Skris else 73755714Skris SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER")); 73855714Skris#endif 73955714Skris 74055714Skris SSL_CTX_set_verify(ctx,verify,verify_callback); 741160814Ssimon if (!set_cert_key_stuff(ctx,cert,key)) 74255714Skris goto end; 74355714Skris 74455714Skris if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) || 74555714Skris (!SSL_CTX_set_default_verify_paths(ctx))) 74655714Skris { 74759191Skris /* BIO_printf(bio_err,"error setting default verify locations\n"); */ 74855714Skris ERR_print_errors(bio_err); 74955714Skris /* goto end; */ 75055714Skris } 75155714Skris 752109998Smarkm store = SSL_CTX_get_cert_store(ctx); 753109998Smarkm X509_STORE_set_flags(store, vflags); 754194206Ssimon#ifndef OPENSSL_NO_TLSEXT 755194206Ssimon if (servername != NULL) 756194206Ssimon { 757194206Ssimon tlsextcbp.biodebug = bio_err; 758194206Ssimon SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); 759194206Ssimon SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); 760194206Ssimon } 761194206Ssimon#endif 76255714Skris 76359191Skris con=SSL_new(ctx); 764194206Ssimon if (sess_in) 765194206Ssimon { 766194206Ssimon SSL_SESSION *sess; 767194206Ssimon BIO *stmp = BIO_new_file(sess_in, "r"); 768194206Ssimon if (!stmp) 769194206Ssimon { 770194206Ssimon BIO_printf(bio_err, "Can't open session file %s\n", 771194206Ssimon sess_in); 772194206Ssimon ERR_print_errors(bio_err); 773194206Ssimon goto end; 774194206Ssimon } 775194206Ssimon sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); 776194206Ssimon BIO_free(stmp); 777194206Ssimon if (!sess) 778194206Ssimon { 779194206Ssimon BIO_printf(bio_err, "Can't open session file %s\n", 780194206Ssimon sess_in); 781194206Ssimon ERR_print_errors(bio_err); 782194206Ssimon goto end; 783194206Ssimon } 784194206Ssimon SSL_set_session(con, sess); 785194206Ssimon SSL_SESSION_free(sess); 786194206Ssimon } 787273415Sdelphij 788273415Sdelphij if (fallback_scsv) 789273415Sdelphij SSL_set_mode(con, SSL_MODE_SEND_FALLBACK_SCSV); 790273415Sdelphij 791194206Ssimon#ifndef OPENSSL_NO_TLSEXT 792194206Ssimon if (servername != NULL) 793194206Ssimon { 794194206Ssimon if (!SSL_set_tlsext_host_name(con,servername)) 795194206Ssimon { 796194206Ssimon BIO_printf(bio_err,"Unable to set TLS servername extension.\n"); 797194206Ssimon ERR_print_errors(bio_err); 798194206Ssimon goto end; 799194206Ssimon } 800194206Ssimon } 801194206Ssimon#endif 802194206Ssimon 803109998Smarkm#ifndef OPENSSL_NO_KRB5 804109998Smarkm if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL) 805109998Smarkm { 806109998Smarkm kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host); 807109998Smarkm } 808109998Smarkm#endif /* OPENSSL_NO_KRB5 */ 80955714Skris/* SSL_set_cipher_list(con,"RC4-MD5"); */ 81055714Skris 81155714Skrisre_start: 81255714Skris 813160814Ssimon if (init_client(&s,host,port,sock_type) == 0) 81455714Skris { 81555714Skris BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error()); 81655714Skris SHUTDOWN(s); 81755714Skris goto end; 81855714Skris } 81955714Skris BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s); 82055714Skris 82155714Skris#ifdef FIONBIO 82255714Skris if (c_nbio) 82355714Skris { 82455714Skris unsigned long l=1; 82555714Skris BIO_printf(bio_c_out,"turning on non blocking io\n"); 82655714Skris if (BIO_socket_ioctl(s,FIONBIO,&l) < 0) 82755714Skris { 82855714Skris ERR_print_errors(bio_err); 82955714Skris goto end; 83055714Skris } 83155714Skris } 83255714Skris#endif 83355714Skris if (c_Pause & 0x01) con->debug=1; 83455714Skris 835160814Ssimon if ( SSL_version(con) == DTLS1_VERSION) 836160814Ssimon { 837160814Ssimon 838160814Ssimon sbio=BIO_new_dgram(s,BIO_NOCLOSE); 839160814Ssimon if (getsockname(s, &peer, (void *)&peerlen) < 0) 840160814Ssimon { 841160814Ssimon BIO_printf(bio_err, "getsockname:errno=%d\n", 842160814Ssimon get_last_socket_error()); 843160814Ssimon SHUTDOWN(s); 844160814Ssimon goto end; 845160814Ssimon } 846160814Ssimon 847194206Ssimon (void)BIO_ctrl_set_connected(sbio, 1, &peer); 848160814Ssimon 849160814Ssimon if ( enable_timeouts) 850160814Ssimon { 851160814Ssimon timeout.tv_sec = 0; 852160814Ssimon timeout.tv_usec = DGRAM_RCV_TIMEOUT; 853160814Ssimon BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); 854160814Ssimon 855160814Ssimon timeout.tv_sec = 0; 856160814Ssimon timeout.tv_usec = DGRAM_SND_TIMEOUT; 857160814Ssimon BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); 858160814Ssimon } 859160814Ssimon 860205128Ssimon if (socket_mtu > 28) 861160814Ssimon { 862160814Ssimon SSL_set_options(con, SSL_OP_NO_QUERY_MTU); 863205128Ssimon SSL_set_mtu(con, socket_mtu - 28); 864160814Ssimon } 865160814Ssimon else 866160814Ssimon /* want to do MTU discovery */ 867160814Ssimon BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); 868160814Ssimon } 869160814Ssimon else 870160814Ssimon sbio=BIO_new_socket(s,BIO_NOCLOSE); 871160814Ssimon 87255714Skris if (nbio_test) 87355714Skris { 87455714Skris BIO *test; 87555714Skris 87655714Skris test=BIO_new(BIO_f_nbio_test()); 87755714Skris sbio=BIO_push(test,sbio); 87855714Skris } 87955714Skris 88055714Skris if (c_debug) 88155714Skris { 88255714Skris con->debug=1; 883160814Ssimon BIO_set_callback(sbio,bio_dump_callback); 884167612Ssimon BIO_set_callback_arg(sbio,(char *)bio_c_out); 88555714Skris } 886109998Smarkm if (c_msg) 887109998Smarkm { 888109998Smarkm SSL_set_msg_callback(con, msg_cb); 889109998Smarkm SSL_set_msg_callback_arg(con, bio_c_out); 890109998Smarkm } 891194206Ssimon#ifndef OPENSSL_NO_TLSEXT 892194206Ssimon if (c_tlsextdebug) 893194206Ssimon { 894194206Ssimon SSL_set_tlsext_debug_callback(con, tlsext_cb); 895194206Ssimon SSL_set_tlsext_debug_arg(con, bio_c_out); 896194206Ssimon } 897194206Ssimon if (c_status_req) 898194206Ssimon { 899194206Ssimon SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp); 900194206Ssimon SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb); 901194206Ssimon SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out); 902194206Ssimon#if 0 903194206Ssimon{ 904194206SsimonSTACK_OF(OCSP_RESPID) *ids = sk_OCSP_RESPID_new_null(); 905194206SsimonOCSP_RESPID *id = OCSP_RESPID_new(); 906194206Ssimonid->value.byKey = ASN1_OCTET_STRING_new(); 907194206Ssimonid->type = V_OCSP_RESPID_KEY; 908194206SsimonASN1_STRING_set(id->value.byKey, "Hello World", -1); 909194206Ssimonsk_OCSP_RESPID_push(ids, id); 910194206SsimonSSL_set_tlsext_status_ids(con, ids); 911194206Ssimon} 912194206Ssimon#endif 913194206Ssimon } 914194206Ssimon#endif 915194206Ssimon#ifndef OPENSSL_NO_JPAKE 916194206Ssimon if (jpake_secret) 917194206Ssimon jpake_client_auth(bio_c_out, sbio, jpake_secret); 918194206Ssimon#endif 91955714Skris 92055714Skris SSL_set_bio(con,sbio,sbio); 92155714Skris SSL_set_connect_state(con); 92255714Skris 92355714Skris /* ok, lets connect */ 92455714Skris width=SSL_get_fd(con)+1; 92555714Skris 92655714Skris read_tty=1; 92755714Skris write_tty=0; 92855714Skris tty_on=0; 92955714Skris read_ssl=1; 93055714Skris write_ssl=1; 93155714Skris 93255714Skris cbuf_len=0; 93355714Skris cbuf_off=0; 93455714Skris sbuf_len=0; 93555714Skris sbuf_off=0; 93655714Skris 937109998Smarkm /* This is an ugly hack that does a lot of assumptions */ 938167612Ssimon /* We do have to handle multi-line responses which may come 939167612Ssimon in a single packet or not. We therefore have to use 940167612Ssimon BIO_gets() which does need a buffering BIO. So during 941167612Ssimon the initial chitchat we do push a buffering BIO into the 942167612Ssimon chain that is removed again later on to not disturb the 943167612Ssimon rest of the s_client operation. */ 944167612Ssimon if (starttls_proto == PROTO_SMTP) 945109998Smarkm { 946167612Ssimon int foundit=0; 947167612Ssimon BIO *fbio = BIO_new(BIO_f_buffer()); 948167612Ssimon BIO_push(fbio, sbio); 949167612Ssimon /* wait for multi-line response to end from SMTP */ 950167612Ssimon do 951167612Ssimon { 952167612Ssimon mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); 953167612Ssimon } 954167612Ssimon while (mbuf_len>3 && mbuf[3]=='-'); 955167612Ssimon /* STARTTLS command requires EHLO... */ 956167612Ssimon BIO_printf(fbio,"EHLO openssl.client.net\r\n"); 957194206Ssimon (void)BIO_flush(fbio); 958167612Ssimon /* wait for multi-line response to end EHLO SMTP response */ 959167612Ssimon do 960167612Ssimon { 961167612Ssimon mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); 962167612Ssimon if (strstr(mbuf,"STARTTLS")) 963167612Ssimon foundit=1; 964167612Ssimon } 965167612Ssimon while (mbuf_len>3 && mbuf[3]=='-'); 966194206Ssimon (void)BIO_flush(fbio); 967167612Ssimon BIO_pop(fbio); 968167612Ssimon BIO_free(fbio); 969167612Ssimon if (!foundit) 970167612Ssimon BIO_printf(bio_err, 971167612Ssimon "didn't found starttls in server response," 972167612Ssimon " try anyway...\n"); 973109998Smarkm BIO_printf(sbio,"STARTTLS\r\n"); 974109998Smarkm BIO_read(sbio,sbuf,BUFSIZZ); 975109998Smarkm } 976167612Ssimon else if (starttls_proto == PROTO_POP3) 977120631Snectar { 978120631Snectar BIO_read(sbio,mbuf,BUFSIZZ); 979120631Snectar BIO_printf(sbio,"STLS\r\n"); 980120631Snectar BIO_read(sbio,sbuf,BUFSIZZ); 981120631Snectar } 982167612Ssimon else if (starttls_proto == PROTO_IMAP) 983167612Ssimon { 984167612Ssimon int foundit=0; 985167612Ssimon BIO *fbio = BIO_new(BIO_f_buffer()); 986167612Ssimon BIO_push(fbio, sbio); 987167612Ssimon BIO_gets(fbio,mbuf,BUFSIZZ); 988167612Ssimon /* STARTTLS command requires CAPABILITY... */ 989167612Ssimon BIO_printf(fbio,". CAPABILITY\r\n"); 990194206Ssimon (void)BIO_flush(fbio); 991167612Ssimon /* wait for multi-line CAPABILITY response */ 992167612Ssimon do 993167612Ssimon { 994167612Ssimon mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); 995167612Ssimon if (strstr(mbuf,"STARTTLS")) 996167612Ssimon foundit=1; 997167612Ssimon } 998167612Ssimon while (mbuf_len>3 && mbuf[0]!='.'); 999194206Ssimon (void)BIO_flush(fbio); 1000167612Ssimon BIO_pop(fbio); 1001167612Ssimon BIO_free(fbio); 1002167612Ssimon if (!foundit) 1003167612Ssimon BIO_printf(bio_err, 1004167612Ssimon "didn't found STARTTLS in server response," 1005167612Ssimon " try anyway...\n"); 1006167612Ssimon BIO_printf(sbio,". STARTTLS\r\n"); 1007167612Ssimon BIO_read(sbio,sbuf,BUFSIZZ); 1008167612Ssimon } 1009167612Ssimon else if (starttls_proto == PROTO_FTP) 1010167612Ssimon { 1011167612Ssimon BIO *fbio = BIO_new(BIO_f_buffer()); 1012167612Ssimon BIO_push(fbio, sbio); 1013167612Ssimon /* wait for multi-line response to end from FTP */ 1014167612Ssimon do 1015167612Ssimon { 1016167612Ssimon mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); 1017167612Ssimon } 1018167612Ssimon while (mbuf_len>3 && mbuf[3]=='-'); 1019194206Ssimon (void)BIO_flush(fbio); 1020167612Ssimon BIO_pop(fbio); 1021167612Ssimon BIO_free(fbio); 1022167612Ssimon BIO_printf(sbio,"AUTH TLS\r\n"); 1023167612Ssimon BIO_read(sbio,sbuf,BUFSIZZ); 1024167612Ssimon } 1025194206Ssimon if (starttls_proto == PROTO_XMPP) 1026194206Ssimon { 1027194206Ssimon int seen = 0; 1028194206Ssimon BIO_printf(sbio,"<stream:stream " 1029194206Ssimon "xmlns:stream='http://etherx.jabber.org/streams' " 1030194206Ssimon "xmlns='jabber:client' to='%s' version='1.0'>", host); 1031194206Ssimon seen = BIO_read(sbio,mbuf,BUFSIZZ); 1032194206Ssimon mbuf[seen] = 0; 1033194206Ssimon while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")) 1034194206Ssimon { 1035194206Ssimon if (strstr(mbuf, "/stream:features>")) 1036194206Ssimon goto shut; 1037194206Ssimon seen = BIO_read(sbio,mbuf,BUFSIZZ); 1038194206Ssimon mbuf[seen] = 0; 1039194206Ssimon } 1040194206Ssimon BIO_printf(sbio, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); 1041194206Ssimon seen = BIO_read(sbio,sbuf,BUFSIZZ); 1042194206Ssimon sbuf[seen] = 0; 1043194206Ssimon if (!strstr(sbuf, "<proceed")) 1044194206Ssimon goto shut; 1045194206Ssimon mbuf[0] = 0; 1046194206Ssimon } 1047109998Smarkm 104855714Skris for (;;) 104955714Skris { 105055714Skris FD_ZERO(&readfds); 105155714Skris FD_ZERO(&writefds); 105255714Skris 1053205128Ssimon if ((SSL_version(con) == DTLS1_VERSION) && 1054205128Ssimon DTLSv1_get_timeout(con, &timeout)) 1055205128Ssimon timeoutp = &timeout; 1056205128Ssimon else 1057205128Ssimon timeoutp = NULL; 1058205128Ssimon 105955714Skris if (SSL_in_init(con) && !SSL_total_renegotiations(con)) 106055714Skris { 106155714Skris in_init=1; 106255714Skris tty_on=0; 106355714Skris } 106455714Skris else 106555714Skris { 106655714Skris tty_on=1; 106755714Skris if (in_init) 106855714Skris { 106955714Skris in_init=0; 1070194206Ssimon if (sess_out) 1071194206Ssimon { 1072194206Ssimon BIO *stmp = BIO_new_file(sess_out, "w"); 1073194206Ssimon if (stmp) 1074194206Ssimon { 1075194206Ssimon PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con)); 1076194206Ssimon BIO_free(stmp); 1077194206Ssimon } 1078194206Ssimon else 1079194206Ssimon BIO_printf(bio_err, "Error writing session file %s\n", sess_out); 1080194206Ssimon } 108155714Skris print_stuff(bio_c_out,con,full_log); 108255714Skris if (full_log > 0) full_log--; 108355714Skris 1084120631Snectar if (starttls_proto) 1085109998Smarkm { 1086109998Smarkm BIO_printf(bio_err,"%s",mbuf); 1087109998Smarkm /* We don't need to know any more */ 1088167612Ssimon starttls_proto = PROTO_OFF; 1089109998Smarkm } 1090109998Smarkm 109155714Skris if (reconnect) 109255714Skris { 109355714Skris reconnect--; 109455714Skris BIO_printf(bio_c_out,"drop connection and then reconnect\n"); 109555714Skris SSL_shutdown(con); 109655714Skris SSL_set_connect_state(con); 109755714Skris SHUTDOWN(SSL_get_fd(con)); 109855714Skris goto re_start; 109955714Skris } 110055714Skris } 110155714Skris } 110255714Skris 110355714Skris ssl_pending = read_ssl && SSL_pending(con); 110455714Skris 110555714Skris if (!ssl_pending) 110655714Skris { 1107160814Ssimon#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) 110855714Skris if (tty_on) 110955714Skris { 111055714Skris if (read_tty) FD_SET(fileno(stdin),&readfds); 111155714Skris if (write_tty) FD_SET(fileno(stdout),&writefds); 111255714Skris } 111355714Skris if (read_ssl) 111455714Skris FD_SET(SSL_get_fd(con),&readfds); 111555714Skris if (write_ssl) 111655714Skris FD_SET(SSL_get_fd(con),&writefds); 111759191Skris#else 111859191Skris if(!tty_on || !write_tty) { 111959191Skris if (read_ssl) 112059191Skris FD_SET(SSL_get_fd(con),&readfds); 112159191Skris if (write_ssl) 112259191Skris FD_SET(SSL_get_fd(con),&writefds); 112359191Skris } 112459191Skris#endif 112555714Skris/* printf("mode tty(%d %d%d) ssl(%d%d)\n", 112655714Skris tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ 112755714Skris 112855714Skris /* Note: under VMS with SOCKETSHR the second parameter 112955714Skris * is currently of type (int *) whereas under other 113055714Skris * systems it is (void *) if you don't have a cast it 113155714Skris * will choke the compiler: if you do have a cast then 113255714Skris * you can either go for (int *) or (void *). 113355714Skris */ 1134120631Snectar#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) 1135120631Snectar /* Under Windows/DOS we make the assumption that we can 113659191Skris * always write to the tty: therefore if we need to 113759191Skris * write to the tty we just fall through. Otherwise 113859191Skris * we timeout the select every second and see if there 113959191Skris * are any keypresses. Note: this is a hack, in a proper 114059191Skris * Windows application we wouldn't do this. 114159191Skris */ 114259191Skris i=0; 114359191Skris if(!write_tty) { 114459191Skris if(read_tty) { 114559191Skris tv.tv_sec = 1; 114659191Skris tv.tv_usec = 0; 114759191Skris i=select(width,(void *)&readfds,(void *)&writefds, 114859191Skris NULL,&tv); 1149120631Snectar#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) 1150109998Smarkm if(!i && (!_kbhit() || !read_tty) ) continue; 1151109998Smarkm#else 115268651Skris if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue; 1153109998Smarkm#endif 115459191Skris } else i=select(width,(void *)&readfds,(void *)&writefds, 1155205128Ssimon NULL,timeoutp); 115659191Skris } 1157160814Ssimon#elif defined(OPENSSL_SYS_NETWARE) 1158160814Ssimon if(!write_tty) { 1159160814Ssimon if(read_tty) { 1160160814Ssimon tv.tv_sec = 1; 1161160814Ssimon tv.tv_usec = 0; 1162160814Ssimon i=select(width,(void *)&readfds,(void *)&writefds, 1163160814Ssimon NULL,&tv); 1164160814Ssimon } else i=select(width,(void *)&readfds,(void *)&writefds, 1165205128Ssimon NULL,timeoutp); 1166160814Ssimon } 116759191Skris#else 116855714Skris i=select(width,(void *)&readfds,(void *)&writefds, 1169205128Ssimon NULL,timeoutp); 117059191Skris#endif 117155714Skris if ( i < 0) 117255714Skris { 117355714Skris BIO_printf(bio_err,"bad select %d\n", 117455714Skris get_last_socket_error()); 117555714Skris goto shut; 117655714Skris /* goto end; */ 117755714Skris } 117855714Skris } 117955714Skris 1180205128Ssimon if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) 1181205128Ssimon { 1182205128Ssimon BIO_printf(bio_err,"TIMEOUT occured\n"); 1183205128Ssimon } 1184205128Ssimon 118555714Skris if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds)) 118655714Skris { 118755714Skris k=SSL_write(con,&(cbuf[cbuf_off]), 118855714Skris (unsigned int)cbuf_len); 118955714Skris switch (SSL_get_error(con,k)) 119055714Skris { 119155714Skris case SSL_ERROR_NONE: 119255714Skris cbuf_off+=k; 119355714Skris cbuf_len-=k; 119455714Skris if (k <= 0) goto end; 119555714Skris /* we have done a write(con,NULL,0); */ 119655714Skris if (cbuf_len <= 0) 119755714Skris { 119855714Skris read_tty=1; 119955714Skris write_ssl=0; 120055714Skris } 120155714Skris else /* if (cbuf_len > 0) */ 120255714Skris { 120355714Skris read_tty=0; 120455714Skris write_ssl=1; 120555714Skris } 120655714Skris break; 120755714Skris case SSL_ERROR_WANT_WRITE: 120855714Skris BIO_printf(bio_c_out,"write W BLOCK\n"); 120955714Skris write_ssl=1; 121055714Skris read_tty=0; 121155714Skris break; 121255714Skris case SSL_ERROR_WANT_READ: 121355714Skris BIO_printf(bio_c_out,"write R BLOCK\n"); 121455714Skris write_tty=0; 121555714Skris read_ssl=1; 121655714Skris write_ssl=0; 121755714Skris break; 121855714Skris case SSL_ERROR_WANT_X509_LOOKUP: 121955714Skris BIO_printf(bio_c_out,"write X BLOCK\n"); 122055714Skris break; 122155714Skris case SSL_ERROR_ZERO_RETURN: 122255714Skris if (cbuf_len != 0) 122355714Skris { 122455714Skris BIO_printf(bio_c_out,"shutdown\n"); 122555714Skris goto shut; 122655714Skris } 122755714Skris else 122855714Skris { 122955714Skris read_tty=1; 123055714Skris write_ssl=0; 123155714Skris break; 123255714Skris } 123355714Skris 123455714Skris case SSL_ERROR_SYSCALL: 123555714Skris if ((k != 0) || (cbuf_len != 0)) 123655714Skris { 123755714Skris BIO_printf(bio_err,"write:errno=%d\n", 123855714Skris get_last_socket_error()); 123955714Skris goto shut; 124055714Skris } 124155714Skris else 124255714Skris { 124355714Skris read_tty=1; 124455714Skris write_ssl=0; 124555714Skris } 124655714Skris break; 124755714Skris case SSL_ERROR_SSL: 124855714Skris ERR_print_errors(bio_err); 124955714Skris goto shut; 125055714Skris } 125155714Skris } 1252160814Ssimon#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) 1253109998Smarkm /* Assume Windows/DOS can always write */ 125459191Skris else if (!ssl_pending && write_tty) 125559191Skris#else 125655714Skris else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds)) 125759191Skris#endif 125855714Skris { 125955714Skris#ifdef CHARSET_EBCDIC 126055714Skris ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len); 126155714Skris#endif 126255714Skris i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len); 126355714Skris 126455714Skris if (i <= 0) 126555714Skris { 126655714Skris BIO_printf(bio_c_out,"DONE\n"); 126755714Skris goto shut; 126855714Skris /* goto end; */ 126955714Skris } 127055714Skris 127155714Skris sbuf_len-=i;; 127255714Skris sbuf_off+=i; 127355714Skris if (sbuf_len <= 0) 127455714Skris { 127555714Skris read_ssl=1; 127655714Skris write_tty=0; 127755714Skris } 127855714Skris } 127955714Skris else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds)) 128055714Skris { 128155714Skris#ifdef RENEG 128255714Skris{ static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } } 128355714Skris#endif 128455714Skris#if 1 128555714Skris k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ ); 128655714Skris#else 128755714Skris/* Demo for pending and peek :-) */ 128855714Skris k=SSL_read(con,sbuf,16); 128955714Skris{ char zbuf[10240]; 129055714Skrisprintf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240)); 129155714Skris} 129255714Skris#endif 129355714Skris 129455714Skris switch (SSL_get_error(con,k)) 129555714Skris { 129655714Skris case SSL_ERROR_NONE: 129755714Skris if (k <= 0) 129855714Skris goto end; 129955714Skris sbuf_off=0; 130055714Skris sbuf_len=k; 130155714Skris 130255714Skris read_ssl=0; 130355714Skris write_tty=1; 130455714Skris break; 130555714Skris case SSL_ERROR_WANT_WRITE: 130655714Skris BIO_printf(bio_c_out,"read W BLOCK\n"); 130755714Skris write_ssl=1; 130855714Skris read_tty=0; 130955714Skris break; 131055714Skris case SSL_ERROR_WANT_READ: 131155714Skris BIO_printf(bio_c_out,"read R BLOCK\n"); 131255714Skris write_tty=0; 131355714Skris read_ssl=1; 131455714Skris if ((read_tty == 0) && (write_ssl == 0)) 131555714Skris write_ssl=1; 131655714Skris break; 131755714Skris case SSL_ERROR_WANT_X509_LOOKUP: 131855714Skris BIO_printf(bio_c_out,"read X BLOCK\n"); 131955714Skris break; 132055714Skris case SSL_ERROR_SYSCALL: 132155714Skris BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error()); 132255714Skris goto shut; 132355714Skris case SSL_ERROR_ZERO_RETURN: 132455714Skris BIO_printf(bio_c_out,"closed\n"); 132555714Skris goto shut; 132655714Skris case SSL_ERROR_SSL: 132755714Skris ERR_print_errors(bio_err); 132855714Skris goto shut; 132955714Skris /* break; */ 133055714Skris } 133155714Skris } 133255714Skris 1333120631Snectar#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) 1334120631Snectar#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) 1335109998Smarkm else if (_kbhit()) 1336109998Smarkm#else 133768651Skris else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) 1338109998Smarkm#endif 1339160814Ssimon#elif defined (OPENSSL_SYS_NETWARE) 1340160814Ssimon else if (_kbhit()) 134159191Skris#else 134255714Skris else if (FD_ISSET(fileno(stdin),&readfds)) 134359191Skris#endif 134455714Skris { 134555714Skris if (crlf) 134655714Skris { 134755714Skris int j, lf_num; 134855714Skris 134955714Skris i=read(fileno(stdin),cbuf,BUFSIZZ/2); 135055714Skris lf_num = 0; 135155714Skris /* both loops are skipped when i <= 0 */ 135255714Skris for (j = 0; j < i; j++) 135355714Skris if (cbuf[j] == '\n') 135455714Skris lf_num++; 135555714Skris for (j = i-1; j >= 0; j--) 135655714Skris { 135755714Skris cbuf[j+lf_num] = cbuf[j]; 135855714Skris if (cbuf[j] == '\n') 135955714Skris { 136055714Skris lf_num--; 136155714Skris i++; 136255714Skris cbuf[j+lf_num] = '\r'; 136355714Skris } 136455714Skris } 136555714Skris assert(lf_num == 0); 136655714Skris } 136755714Skris else 136855714Skris i=read(fileno(stdin),cbuf,BUFSIZZ); 136955714Skris 137059191Skris if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) 137155714Skris { 137255714Skris BIO_printf(bio_err,"DONE\n"); 137355714Skris goto shut; 137455714Skris } 137555714Skris 137659191Skris if ((!c_ign_eof) && (cbuf[0] == 'R')) 137755714Skris { 137855714Skris BIO_printf(bio_err,"RENEGOTIATING\n"); 137955714Skris SSL_renegotiate(con); 138055714Skris cbuf_len=0; 138155714Skris } 138255714Skris else 138355714Skris { 138455714Skris cbuf_len=i; 138555714Skris cbuf_off=0; 138655714Skris#ifdef CHARSET_EBCDIC 138755714Skris ebcdic2ascii(cbuf, cbuf, i); 138855714Skris#endif 138955714Skris } 139055714Skris 139155714Skris write_ssl=1; 139255714Skris read_tty=0; 139355714Skris } 139455714Skris } 139555714Skrisshut: 139655714Skris SSL_shutdown(con); 139755714Skris SHUTDOWN(SSL_get_fd(con)); 139855714Skris ret=0; 139955714Skrisend: 140059191Skris if(prexit) print_stuff(bio_c_out,con,1); 140155714Skris if (con != NULL) SSL_free(con); 140255714Skris if (con2 != NULL) SSL_free(con2); 140355714Skris if (ctx != NULL) SSL_CTX_free(ctx); 1404160814Ssimon if (cert) 1405160814Ssimon X509_free(cert); 1406160814Ssimon if (key) 1407160814Ssimon EVP_PKEY_free(key); 1408160814Ssimon if (pass) 1409160814Ssimon OPENSSL_free(pass); 1410109998Smarkm if (cbuf != NULL) { OPENSSL_cleanse(cbuf,BUFSIZZ); OPENSSL_free(cbuf); } 1411109998Smarkm if (sbuf != NULL) { OPENSSL_cleanse(sbuf,BUFSIZZ); OPENSSL_free(sbuf); } 1412109998Smarkm if (mbuf != NULL) { OPENSSL_cleanse(mbuf,BUFSIZZ); OPENSSL_free(mbuf); } 141355714Skris if (bio_c_out != NULL) 141455714Skris { 141555714Skris BIO_free(bio_c_out); 141655714Skris bio_c_out=NULL; 141755714Skris } 1418109998Smarkm apps_shutdown(); 1419109998Smarkm OPENSSL_EXIT(ret); 142055714Skris } 142155714Skris 142255714Skris 142355714Skrisstatic void print_stuff(BIO *bio, SSL *s, int full) 142455714Skris { 142555714Skris X509 *peer=NULL; 142655714Skris char *p; 1427160814Ssimon static const char *space=" "; 142855714Skris char buf[BUFSIZ]; 142955714Skris STACK_OF(X509) *sk; 143055714Skris STACK_OF(X509_NAME) *sk2; 143155714Skris SSL_CIPHER *c; 143255714Skris X509_NAME *xn; 143355714Skris int j,i; 1434160814Ssimon#ifndef OPENSSL_NO_COMP 1435160814Ssimon const COMP_METHOD *comp, *expansion; 1436160814Ssimon#endif 143755714Skris 143855714Skris if (full) 143955714Skris { 144055714Skris int got_a_chain = 0; 144155714Skris 144255714Skris sk=SSL_get_peer_cert_chain(s); 144355714Skris if (sk != NULL) 144455714Skris { 144555714Skris got_a_chain = 1; /* we don't have it for SSL2 (yet) */ 144655714Skris 144755714Skris BIO_printf(bio,"---\nCertificate chain\n"); 144855714Skris for (i=0; i<sk_X509_num(sk); i++) 144955714Skris { 145055714Skris X509_NAME_oneline(X509_get_subject_name( 1451109998Smarkm sk_X509_value(sk,i)),buf,sizeof buf); 145255714Skris BIO_printf(bio,"%2d s:%s\n",i,buf); 145355714Skris X509_NAME_oneline(X509_get_issuer_name( 1454109998Smarkm sk_X509_value(sk,i)),buf,sizeof buf); 145555714Skris BIO_printf(bio," i:%s\n",buf); 145655714Skris if (c_showcerts) 145755714Skris PEM_write_bio_X509(bio,sk_X509_value(sk,i)); 145855714Skris } 145955714Skris } 146055714Skris 146155714Skris BIO_printf(bio,"---\n"); 146255714Skris peer=SSL_get_peer_certificate(s); 146355714Skris if (peer != NULL) 146455714Skris { 146555714Skris BIO_printf(bio,"Server certificate\n"); 146655714Skris if (!(c_showcerts && got_a_chain)) /* Redundant if we showed the whole chain */ 146755714Skris PEM_write_bio_X509(bio,peer); 146855714Skris X509_NAME_oneline(X509_get_subject_name(peer), 1469109998Smarkm buf,sizeof buf); 147055714Skris BIO_printf(bio,"subject=%s\n",buf); 147155714Skris X509_NAME_oneline(X509_get_issuer_name(peer), 1472109998Smarkm buf,sizeof buf); 147355714Skris BIO_printf(bio,"issuer=%s\n",buf); 147455714Skris } 147555714Skris else 147655714Skris BIO_printf(bio,"no peer certificate available\n"); 147755714Skris 147855714Skris sk2=SSL_get_client_CA_list(s); 147955714Skris if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) 148055714Skris { 148155714Skris BIO_printf(bio,"---\nAcceptable client certificate CA names\n"); 148255714Skris for (i=0; i<sk_X509_NAME_num(sk2); i++) 148355714Skris { 148455714Skris xn=sk_X509_NAME_value(sk2,i); 148555714Skris X509_NAME_oneline(xn,buf,sizeof(buf)); 148655714Skris BIO_write(bio,buf,strlen(buf)); 148755714Skris BIO_write(bio,"\n",1); 148855714Skris } 148955714Skris } 149055714Skris else 149155714Skris { 149255714Skris BIO_printf(bio,"---\nNo client certificate CA names sent\n"); 149355714Skris } 1494109998Smarkm p=SSL_get_shared_ciphers(s,buf,sizeof buf); 149555714Skris if (p != NULL) 149655714Skris { 149755714Skris /* This works only for SSL 2. In later protocol 149855714Skris * versions, the client does not know what other 149955714Skris * ciphers (in addition to the one to be used 150055714Skris * in the current connection) the server supports. */ 150155714Skris 150255714Skris BIO_printf(bio,"---\nCiphers common between both SSL endpoints:\n"); 150355714Skris j=i=0; 150455714Skris while (*p) 150555714Skris { 150655714Skris if (*p == ':') 150755714Skris { 150855714Skris BIO_write(bio,space,15-j%25); 150955714Skris i++; 151055714Skris j=0; 151155714Skris BIO_write(bio,((i%3)?" ":"\n"),1); 151255714Skris } 151355714Skris else 151455714Skris { 151555714Skris BIO_write(bio,p,1); 151655714Skris j++; 151755714Skris } 151855714Skris p++; 151955714Skris } 152055714Skris BIO_write(bio,"\n",1); 152155714Skris } 152255714Skris 152355714Skris BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n", 152455714Skris BIO_number_read(SSL_get_rbio(s)), 152555714Skris BIO_number_written(SSL_get_wbio(s))); 152655714Skris } 152755714Skris BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, ")); 152855714Skris c=SSL_get_current_cipher(s); 152955714Skris BIO_printf(bio,"%s, Cipher is %s\n", 153055714Skris SSL_CIPHER_get_version(c), 153155714Skris SSL_CIPHER_get_name(c)); 153255714Skris if (peer != NULL) { 153355714Skris EVP_PKEY *pktmp; 153455714Skris pktmp = X509_get_pubkey(peer); 153555714Skris BIO_printf(bio,"Server public key is %d bit\n", 153655714Skris EVP_PKEY_bits(pktmp)); 153755714Skris EVP_PKEY_free(pktmp); 153855714Skris } 1539205128Ssimon BIO_printf(bio, "Secure Renegotiation IS%s supported\n", 1540205128Ssimon SSL_get_secure_renegotiation_support(s) ? "" : " NOT"); 1541160814Ssimon#ifndef OPENSSL_NO_COMP 1542160814Ssimon comp=SSL_get_current_compression(s); 1543160814Ssimon expansion=SSL_get_current_expansion(s); 1544160814Ssimon BIO_printf(bio,"Compression: %s\n", 1545160814Ssimon comp ? SSL_COMP_get_name(comp) : "NONE"); 1546160814Ssimon BIO_printf(bio,"Expansion: %s\n", 1547160814Ssimon expansion ? SSL_COMP_get_name(expansion) : "NONE"); 1548160814Ssimon#endif 154955714Skris SSL_SESSION_print(bio,SSL_get_session(s)); 155055714Skris BIO_printf(bio,"---\n"); 155155714Skris if (peer != NULL) 155255714Skris X509_free(peer); 155389837Skris /* flush, or debugging output gets mixed with http response */ 1554194206Ssimon (void)BIO_flush(bio); 155555714Skris } 155655714Skris 1557194206Ssimon#ifndef OPENSSL_NO_TLSEXT 1558194206Ssimon 1559194206Ssimonstatic int ocsp_resp_cb(SSL *s, void *arg) 1560194206Ssimon { 1561194206Ssimon const unsigned char *p; 1562194206Ssimon int len; 1563194206Ssimon OCSP_RESPONSE *rsp; 1564194206Ssimon len = SSL_get_tlsext_status_ocsp_resp(s, &p); 1565194206Ssimon BIO_puts(arg, "OCSP response: "); 1566194206Ssimon if (!p) 1567194206Ssimon { 1568194206Ssimon BIO_puts(arg, "no response sent\n"); 1569194206Ssimon return 1; 1570194206Ssimon } 1571194206Ssimon rsp = d2i_OCSP_RESPONSE(NULL, &p, len); 1572194206Ssimon if (!rsp) 1573194206Ssimon { 1574194206Ssimon BIO_puts(arg, "response parse error\n"); 1575194206Ssimon BIO_dump_indent(arg, (char *)p, len, 4); 1576194206Ssimon return 0; 1577194206Ssimon } 1578194206Ssimon BIO_puts(arg, "\n======================================\n"); 1579194206Ssimon OCSP_RESPONSE_print(arg, rsp, 0); 1580194206Ssimon BIO_puts(arg, "======================================\n"); 1581194206Ssimon OCSP_RESPONSE_free(rsp); 1582194206Ssimon return 1; 1583194206Ssimon } 1584194206Ssimon#endif /* ndef OPENSSL_NO_TLSEXT */ 1585