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. 8296465Sdelphij * 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). 15296465Sdelphij * 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. 22296465Sdelphij * 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 :-). 37296465Sdelphij * 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)" 40296465Sdelphij * 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. 52296465Sdelphij * 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 66296465Sdelphij * 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 118296465Sdelphij# define APPS_WIN16 11955714Skris#endif 12055714Skris 121296465Sdelphij/* 122296465Sdelphij * With IPv6, it looks like Digital has mixed up the proper order of 123296465Sdelphij * recursive header file inclusion, resulting in the compiler complaining 124296465Sdelphij * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is 125296465Sdelphij * needed to have fileno() declared correctly... So let's define u_int 126296465Sdelphij */ 127109998Smarkm#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) 128296465Sdelphij# define __U_INT 12955714Skristypedef unsigned int u_int; 13055714Skris#endif 13155714Skris 13255714Skris#define USE_SOCKETS 13355714Skris#include "apps.h" 13455714Skris#include <openssl/x509.h> 13555714Skris#include <openssl/ssl.h> 13655714Skris#include <openssl/err.h> 13755714Skris#include <openssl/pem.h> 13876866Skris#include <openssl/rand.h> 139194206Ssimon#include <openssl/ocsp.h> 14055714Skris#include "s_apps.h" 141160814Ssimon#include "timeouts.h" 14255714Skris 143109998Smarkm#ifdef OPENSSL_SYS_WINCE 144296465Sdelphij/* 145296465Sdelphij * Windows CE incorrectly defines fileno as returning void*, so to avoid 146296465Sdelphij * problems below... 147296465Sdelphij */ 148296465Sdelphij# ifdef fileno 149296465Sdelphij# undef fileno 150296465Sdelphij# endif 151296465Sdelphij# define fileno(a) (int)_fileno(a) 152109998Smarkm#endif 15359191Skris 154109998Smarkm#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) 15555714Skris/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ 156296465Sdelphij# undef FIONBIO 15755714Skris#endif 15855714Skris 15955714Skris#undef PROG 160296465Sdelphij#define PROG s_client_main 16155714Skris 162296465Sdelphij/* 163296465Sdelphij * #define SSL_HOST_NAME "www.netscape.com" 164296465Sdelphij */ 165296465Sdelphij/* 166296465Sdelphij * #define SSL_HOST_NAME "193.118.187.102" 167296465Sdelphij */ 168296465Sdelphij#define SSL_HOST_NAME "localhost" 16955714Skris 170296465Sdelphij/* no default cert. */ 171296465Sdelphij/* 172296465Sdelphij * #define TEST_CERT "client.pem" 173296465Sdelphij */ 17455714Skris 17555714Skris#undef BUFSIZZ 17655714Skris#define BUFSIZZ 1024*8 17755714Skris 17855714Skrisextern int verify_depth; 17955714Skrisextern int verify_error; 18055714Skris 18155714Skris#ifdef FIONBIO 182296465Sdelphijstatic int c_nbio = 0; 18355714Skris#endif 184296465Sdelphijstatic int c_Pause = 0; 185296465Sdelphijstatic int c_debug = 0; 186194206Ssimon#ifndef OPENSSL_NO_TLSEXT 187296465Sdelphijstatic int c_tlsextdebug = 0; 188296465Sdelphijstatic int c_status_req = 0; 189194206Ssimon#endif 190296465Sdelphijstatic int c_msg = 0; 191296465Sdelphijstatic int c_showcerts = 0; 19255714Skris 19355714Skrisstatic void sc_usage(void); 194296465Sdelphijstatic void print_stuff(BIO *berr, SSL *con, int full); 195194206Ssimon#ifndef OPENSSL_NO_TLSEXT 196194206Ssimonstatic int ocsp_resp_cb(SSL *s, void *arg); 197194206Ssimon#endif 198296465Sdelphijstatic BIO *bio_c_out = NULL; 199296465Sdelphijstatic int c_quiet = 0; 200296465Sdelphijstatic int c_ign_eof = 0; 20155714Skris 20255714Skrisstatic void sc_usage(void) 203296465Sdelphij{ 204296465Sdelphij BIO_printf(bio_err, "usage: s_client args\n"); 205296465Sdelphij BIO_printf(bio_err, "\n"); 206296465Sdelphij BIO_printf(bio_err, " -host host - use -connect instead\n"); 207296465Sdelphij BIO_printf(bio_err, " -port port - use -connect instead\n"); 208296465Sdelphij BIO_printf(bio_err, 209296465Sdelphij " -connect host:port - who to connect to (default is %s:%s)\n", 210296465Sdelphij SSL_HOST_NAME, PORT_STR); 21155714Skris 212296465Sdelphij BIO_printf(bio_err, 213296465Sdelphij " -verify depth - turn on peer certificate verification\n"); 214296465Sdelphij BIO_printf(bio_err, 215296465Sdelphij " -cert arg - certificate file to use, PEM format assumed\n"); 216296465Sdelphij BIO_printf(bio_err, 217296465Sdelphij " -certform arg - certificate format (PEM or DER) PEM default\n"); 218296465Sdelphij BIO_printf(bio_err, 219296465Sdelphij " -key arg - Private key file to use, in cert file if\n"); 220296465Sdelphij BIO_printf(bio_err, " not specified but cert file is.\n"); 221296465Sdelphij BIO_printf(bio_err, 222296465Sdelphij " -keyform arg - key format (PEM or DER) PEM default\n"); 223296465Sdelphij BIO_printf(bio_err, 224296465Sdelphij " -pass arg - private key file pass phrase source\n"); 225296465Sdelphij BIO_printf(bio_err, " -CApath arg - PEM format directory of CA's\n"); 226296465Sdelphij BIO_printf(bio_err, " -CAfile arg - PEM format file of CA's\n"); 227296465Sdelphij BIO_printf(bio_err, 228296465Sdelphij " -reconnect - Drop and re-make the connection with the same Session-ID\n"); 229296465Sdelphij BIO_printf(bio_err, 230296465Sdelphij " -pause - sleep(1) after each read(2) and write(2) system call\n"); 231296465Sdelphij BIO_printf(bio_err, 232296465Sdelphij " -showcerts - show all certificates in the chain\n"); 233296465Sdelphij BIO_printf(bio_err, " -debug - extra output\n"); 234160814Ssimon#ifdef WATT32 235296465Sdelphij BIO_printf(bio_err, " -wdebug - WATT-32 tcp debugging\n"); 236160814Ssimon#endif 237296465Sdelphij BIO_printf(bio_err, " -msg - Show protocol messages\n"); 238296465Sdelphij BIO_printf(bio_err, " -nbio_test - more ssl protocol testing\n"); 239296465Sdelphij BIO_printf(bio_err, " -state - print the 'ssl' states\n"); 24055714Skris#ifdef FIONBIO 241296465Sdelphij BIO_printf(bio_err, " -nbio - Run with non-blocking IO\n"); 24255714Skris#endif 243296465Sdelphij BIO_printf(bio_err, 244296465Sdelphij " -crlf - convert LF from terminal into CRLF\n"); 245296465Sdelphij BIO_printf(bio_err, " -quiet - no s_client output\n"); 246296465Sdelphij BIO_printf(bio_err, 247296465Sdelphij " -ign_eof - ignore input eof (default when -quiet)\n"); 248296465Sdelphij BIO_printf(bio_err, " -no_ign_eof - don't ignore input eof\n"); 249296465Sdelphij BIO_printf(bio_err, " -ssl2 - just use SSLv2\n"); 250296465Sdelphij BIO_printf(bio_err, " -ssl3 - just use SSLv3\n"); 251296465Sdelphij BIO_printf(bio_err, " -tls1 - just use TLSv1\n"); 252296465Sdelphij BIO_printf(bio_err, " -dtls1 - just use DTLSv1\n"); 253296465Sdelphij BIO_printf(bio_err, " -fallback_scsv - send TLS_FALLBACK_SCSV\n"); 254296465Sdelphij BIO_printf(bio_err, " -mtu - set the link layer MTU\n"); 255296465Sdelphij BIO_printf(bio_err, 256296465Sdelphij " -no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n"); 257296465Sdelphij BIO_printf(bio_err, 258296465Sdelphij " -bugs - Switch on all SSL implementation bug workarounds\n"); 259296465Sdelphij BIO_printf(bio_err, 260296465Sdelphij " -serverpref - Use server's cipher preferences (only SSLv2)\n"); 261296465Sdelphij BIO_printf(bio_err, 262296465Sdelphij " -cipher - preferred cipher to use, use the 'openssl ciphers'\n"); 263296465Sdelphij BIO_printf(bio_err, 264296465Sdelphij " command to see what is available\n"); 265296465Sdelphij BIO_printf(bio_err, 266296465Sdelphij " -starttls prot - use the STARTTLS command before starting TLS\n"); 267296465Sdelphij BIO_printf(bio_err, 268296465Sdelphij " for those protocols that support it, where\n"); 269296465Sdelphij BIO_printf(bio_err, 270296465Sdelphij " 'prot' defines which one to assume. Currently,\n"); 271296465Sdelphij BIO_printf(bio_err, 272296465Sdelphij " only \"smtp\", \"pop3\", \"imap\", \"ftp\" and \"xmpp\"\n"); 273296465Sdelphij BIO_printf(bio_err, " are supported.\n"); 274111147Snectar#ifndef OPENSSL_NO_ENGINE 275296465Sdelphij BIO_printf(bio_err, 276296465Sdelphij " -engine id - Initialise and use the specified engine\n"); 277111147Snectar#endif 278296465Sdelphij BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, 279296465Sdelphij LIST_SEPARATOR_CHAR); 280296465Sdelphij BIO_printf(bio_err, " -sess_out arg - file to write SSL session to\n"); 281296465Sdelphij BIO_printf(bio_err, " -sess_in arg - file to read SSL session from\n"); 282194206Ssimon#ifndef OPENSSL_NO_TLSEXT 283296465Sdelphij BIO_printf(bio_err, 284296465Sdelphij " -servername host - Set TLS extension servername in ClientHello\n"); 285296465Sdelphij BIO_printf(bio_err, 286296465Sdelphij " -tlsextdebug - hex dump of all TLS extensions received\n"); 287296465Sdelphij BIO_printf(bio_err, 288296465Sdelphij " -status - request certificate status from server\n"); 289296465Sdelphij BIO_printf(bio_err, 290296465Sdelphij " -no_ticket - disable use of RFC4507bis session tickets\n"); 291194206Ssimon#endif 292296465Sdelphij BIO_printf(bio_err, 293296465Sdelphij " -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n"); 294296465Sdelphij} 29555714Skris 296194206Ssimon#ifndef OPENSSL_NO_TLSEXT 297194206Ssimon 298194206Ssimon/* This is a context that we pass to callbacks */ 299194206Ssimontypedef struct tlsextctx_st { 300296465Sdelphij BIO *biodebug; 301296465Sdelphij int ack; 302194206Ssimon} tlsextctx; 303194206Ssimon 304296465Sdelphijstatic int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg) 305296465Sdelphij{ 306296465Sdelphij tlsextctx *p = (tlsextctx *) arg; 307296465Sdelphij const char *hn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); 308296465Sdelphij if (SSL_get_servername_type(s) != -1) 309296465Sdelphij p->ack = !SSL_session_reused(s) && hn != NULL; 310296465Sdelphij else 311296465Sdelphij BIO_printf(bio_err, "Can't use SSL_get_servername\n"); 312194206Ssimon 313296465Sdelphij return SSL_TLSEXT_ERR_OK; 314296465Sdelphij} 315194206Ssimon#endif 316296465Sdelphijenum { 317296465Sdelphij PROTO_OFF = 0, 318296465Sdelphij PROTO_SMTP, 319296465Sdelphij PROTO_POP3, 320296465Sdelphij PROTO_IMAP, 321296465Sdelphij PROTO_FTP, 322296465Sdelphij PROTO_XMPP 323167612Ssimon}; 324167612Ssimon 32559191Skrisint MAIN(int, char **); 32659191Skris 32755714Skrisint MAIN(int argc, char **argv) 328296465Sdelphij{ 329296465Sdelphij int off = 0, clr = 0; 330296465Sdelphij SSL *con = NULL, *con2 = NULL; 331296465Sdelphij X509_STORE *store = NULL; 332296465Sdelphij int s, k, width, state = 0; 333296465Sdelphij char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL; 334296465Sdelphij int cbuf_len, cbuf_off; 335296465Sdelphij int sbuf_len, sbuf_off; 336296465Sdelphij fd_set readfds, writefds; 337296465Sdelphij short port = PORT; 338296465Sdelphij int full_log = 1; 339296465Sdelphij char *host = SSL_HOST_NAME; 340296465Sdelphij char *cert_file = NULL, *key_file = NULL; 341296465Sdelphij int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; 342296465Sdelphij char *passarg = NULL, *pass = NULL; 343296465Sdelphij X509 *cert = NULL; 344296465Sdelphij EVP_PKEY *key = NULL; 345296465Sdelphij char *CApath = NULL, *CAfile = NULL, *cipher = NULL; 346296465Sdelphij int reconnect = 0, badop = 0, verify = SSL_VERIFY_NONE, bugs = 0; 347296465Sdelphij int crlf = 0; 348296465Sdelphij int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; 349296465Sdelphij SSL_CTX *ctx = NULL; 350296465Sdelphij int ret = 1, in_init = 1, i, nbio_test = 0; 351296465Sdelphij int starttls_proto = PROTO_OFF; 352296465Sdelphij int prexit = 0, vflags = 0; 353296465Sdelphij SSL_METHOD *meth = NULL; 354160814Ssimon#ifdef sock_type 355296465Sdelphij# undef sock_type 356160814Ssimon#endif 357296465Sdelphij int sock_type = SOCK_STREAM; 358296465Sdelphij BIO *sbio; 359296465Sdelphij char *inrand = NULL; 360296465Sdelphij int mbuf_len = 0; 361296465Sdelphij struct timeval timeout, *timeoutp; 362111147Snectar#ifndef OPENSSL_NO_ENGINE 363296465Sdelphij char *engine_id = NULL; 364296465Sdelphij char *ssl_client_engine_id = NULL; 365296465Sdelphij ENGINE *ssl_client_engine = NULL; 366194206Ssimon#endif 367296465Sdelphij ENGINE *e = NULL; 368160814Ssimon#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) 369296465Sdelphij struct timeval tv; 37059191Skris#endif 37155714Skris 372194206Ssimon#ifndef OPENSSL_NO_TLSEXT 373296465Sdelphij char *servername = NULL; 374296465Sdelphij tlsextctx tlsextcbp = { NULL, 0 }; 375194206Ssimon#endif 376296465Sdelphij char *sess_in = NULL; 377296465Sdelphij char *sess_out = NULL; 378296465Sdelphij struct sockaddr peer; 379296465Sdelphij int peerlen = sizeof(peer); 380296465Sdelphij int fallback_scsv = 0; 381296465Sdelphij int enable_timeouts = 0; 382296465Sdelphij long socket_mtu = 0; 383194206Ssimon#ifndef OPENSSL_NO_JPAKE 384296465Sdelphij char *jpake_secret = NULL; 385194206Ssimon#endif 386160814Ssimon 387296465Sdelphij meth = SSLv23_client_method(); 38855714Skris 389296465Sdelphij apps_startup(); 390296465Sdelphij c_Pause = 0; 391296465Sdelphij c_quiet = 0; 392296465Sdelphij c_ign_eof = 0; 393296465Sdelphij c_debug = 0; 394296465Sdelphij c_msg = 0; 395296465Sdelphij c_showcerts = 0; 39655714Skris 397296465Sdelphij if (bio_err == NULL) 398296465Sdelphij bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 39955714Skris 400296465Sdelphij if (!load_config(bio_err, NULL)) 401296465Sdelphij goto end; 402109998Smarkm 403296465Sdelphij if (((cbuf = OPENSSL_malloc(BUFSIZZ)) == NULL) || 404296465Sdelphij ((sbuf = OPENSSL_malloc(BUFSIZZ)) == NULL) || 405296465Sdelphij ((mbuf = OPENSSL_malloc(BUFSIZZ)) == NULL)) { 406296465Sdelphij BIO_printf(bio_err, "out of memory\n"); 407296465Sdelphij goto end; 408296465Sdelphij } 40955714Skris 410296465Sdelphij verify_depth = 0; 411296465Sdelphij verify_error = X509_V_OK; 41255714Skris#ifdef FIONBIO 413296465Sdelphij c_nbio = 0; 41455714Skris#endif 41555714Skris 416296465Sdelphij argc--; 417296465Sdelphij argv++; 418296465Sdelphij while (argc >= 1) { 419296465Sdelphij if (strcmp(*argv, "-host") == 0) { 420296465Sdelphij if (--argc < 1) 421296465Sdelphij goto bad; 422296465Sdelphij host = *(++argv); 423296465Sdelphij } else if (strcmp(*argv, "-port") == 0) { 424296465Sdelphij if (--argc < 1) 425296465Sdelphij goto bad; 426296465Sdelphij port = atoi(*(++argv)); 427296465Sdelphij if (port == 0) 428296465Sdelphij goto bad; 429296465Sdelphij } else if (strcmp(*argv, "-connect") == 0) { 430296465Sdelphij if (--argc < 1) 431296465Sdelphij goto bad; 432296465Sdelphij if (!extract_host_port(*(++argv), &host, NULL, &port)) 433296465Sdelphij goto bad; 434296465Sdelphij } else if (strcmp(*argv, "-verify") == 0) { 435296465Sdelphij verify = SSL_VERIFY_PEER; 436296465Sdelphij if (--argc < 1) 437296465Sdelphij goto bad; 438296465Sdelphij verify_depth = atoi(*(++argv)); 439296465Sdelphij BIO_printf(bio_err, "verify depth is %d\n", verify_depth); 440296465Sdelphij } else if (strcmp(*argv, "-cert") == 0) { 441296465Sdelphij if (--argc < 1) 442296465Sdelphij goto bad; 443296465Sdelphij cert_file = *(++argv); 444296465Sdelphij } else if (strcmp(*argv, "-sess_out") == 0) { 445296465Sdelphij if (--argc < 1) 446296465Sdelphij goto bad; 447296465Sdelphij sess_out = *(++argv); 448296465Sdelphij } else if (strcmp(*argv, "-sess_in") == 0) { 449296465Sdelphij if (--argc < 1) 450296465Sdelphij goto bad; 451296465Sdelphij sess_in = *(++argv); 452296465Sdelphij } else if (strcmp(*argv, "-certform") == 0) { 453296465Sdelphij if (--argc < 1) 454296465Sdelphij goto bad; 455296465Sdelphij cert_format = str2fmt(*(++argv)); 456296465Sdelphij } else if (strcmp(*argv, "-crl_check") == 0) 457296465Sdelphij vflags |= X509_V_FLAG_CRL_CHECK; 458296465Sdelphij else if (strcmp(*argv, "-crl_check_all") == 0) 459296465Sdelphij vflags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL; 460296465Sdelphij else if (strcmp(*argv, "-prexit") == 0) 461296465Sdelphij prexit = 1; 462296465Sdelphij else if (strcmp(*argv, "-crlf") == 0) 463296465Sdelphij crlf = 1; 464296465Sdelphij else if (strcmp(*argv, "-quiet") == 0) { 465296465Sdelphij c_quiet = 1; 466296465Sdelphij c_ign_eof = 1; 467296465Sdelphij } else if (strcmp(*argv, "-ign_eof") == 0) 468296465Sdelphij c_ign_eof = 1; 469296465Sdelphij else if (strcmp(*argv, "-no_ign_eof") == 0) 470296465Sdelphij c_ign_eof = 0; 471296465Sdelphij else if (strcmp(*argv, "-pause") == 0) 472296465Sdelphij c_Pause = 1; 473296465Sdelphij else if (strcmp(*argv, "-debug") == 0) 474296465Sdelphij c_debug = 1; 475194206Ssimon#ifndef OPENSSL_NO_TLSEXT 476296465Sdelphij else if (strcmp(*argv, "-tlsextdebug") == 0) 477296465Sdelphij c_tlsextdebug = 1; 478296465Sdelphij else if (strcmp(*argv, "-status") == 0) 479296465Sdelphij c_status_req = 1; 480194206Ssimon#endif 481160814Ssimon#ifdef WATT32 482296465Sdelphij else if (strcmp(*argv, "-wdebug") == 0) 483296465Sdelphij dbug_init(); 484160814Ssimon#endif 485296465Sdelphij else if (strcmp(*argv, "-msg") == 0) 486296465Sdelphij c_msg = 1; 487296465Sdelphij else if (strcmp(*argv, "-showcerts") == 0) 488296465Sdelphij c_showcerts = 1; 489296465Sdelphij else if (strcmp(*argv, "-nbio_test") == 0) 490296465Sdelphij nbio_test = 1; 491296465Sdelphij else if (strcmp(*argv, "-state") == 0) 492296465Sdelphij state = 1; 493109998Smarkm#ifndef OPENSSL_NO_SSL2 494296465Sdelphij else if (strcmp(*argv, "-ssl2") == 0) 495296465Sdelphij meth = SSLv2_client_method(); 49655714Skris#endif 497109998Smarkm#ifndef OPENSSL_NO_SSL3 498296465Sdelphij else if (strcmp(*argv, "-ssl3") == 0) 499296465Sdelphij meth = SSLv3_client_method(); 50055714Skris#endif 501109998Smarkm#ifndef OPENSSL_NO_TLS1 502296465Sdelphij else if (strcmp(*argv, "-tls1") == 0) 503296465Sdelphij meth = TLSv1_client_method(); 50455714Skris#endif 505160814Ssimon#ifndef OPENSSL_NO_DTLS1 506296465Sdelphij else if (strcmp(*argv, "-dtls1") == 0) { 507296465Sdelphij meth = DTLSv1_client_method(); 508296465Sdelphij sock_type = SOCK_DGRAM; 509296465Sdelphij } else if (strcmp(*argv, "-timeout") == 0) 510296465Sdelphij enable_timeouts = 1; 511296465Sdelphij else if (strcmp(*argv, "-mtu") == 0) { 512296465Sdelphij if (--argc < 1) 513296465Sdelphij goto bad; 514296465Sdelphij socket_mtu = atol(*(++argv)); 515296465Sdelphij } 516160814Ssimon#endif 517296465Sdelphij else if (strcmp(*argv, "-fallback_scsv") == 0) { 518296465Sdelphij fallback_scsv = 1; 519296465Sdelphij } else if (strcmp(*argv, "-bugs") == 0) 520296465Sdelphij bugs = 1; 521296465Sdelphij else if (strcmp(*argv, "-keyform") == 0) { 522296465Sdelphij if (--argc < 1) 523296465Sdelphij goto bad; 524296465Sdelphij key_format = str2fmt(*(++argv)); 525296465Sdelphij } else if (strcmp(*argv, "-pass") == 0) { 526296465Sdelphij if (--argc < 1) 527296465Sdelphij goto bad; 528296465Sdelphij passarg = *(++argv); 529296465Sdelphij } else if (strcmp(*argv, "-key") == 0) { 530296465Sdelphij if (--argc < 1) 531296465Sdelphij goto bad; 532296465Sdelphij key_file = *(++argv); 533296465Sdelphij } else if (strcmp(*argv, "-reconnect") == 0) { 534296465Sdelphij reconnect = 5; 535296465Sdelphij } else if (strcmp(*argv, "-CApath") == 0) { 536296465Sdelphij if (--argc < 1) 537296465Sdelphij goto bad; 538296465Sdelphij CApath = *(++argv); 539296465Sdelphij } else if (strcmp(*argv, "-CAfile") == 0) { 540296465Sdelphij if (--argc < 1) 541296465Sdelphij goto bad; 542296465Sdelphij CAfile = *(++argv); 543296465Sdelphij } else if (strcmp(*argv, "-no_tls1") == 0) 544296465Sdelphij off |= SSL_OP_NO_TLSv1; 545296465Sdelphij else if (strcmp(*argv, "-no_ssl3") == 0) 546296465Sdelphij off |= SSL_OP_NO_SSLv3; 547296465Sdelphij else if (strcmp(*argv, "-no_ssl2") == 0) 548296465Sdelphij off |= SSL_OP_NO_SSLv2; 549194206Ssimon#ifndef OPENSSL_NO_TLSEXT 550296465Sdelphij else if (strcmp(*argv, "-no_ticket") == 0) { 551296465Sdelphij off |= SSL_OP_NO_TICKET; 552296465Sdelphij } 553194206Ssimon#endif 554296465Sdelphij else if (strcmp(*argv, "-serverpref") == 0) 555296465Sdelphij off |= SSL_OP_CIPHER_SERVER_PREFERENCE; 556296465Sdelphij else if (strcmp(*argv, "-legacy_renegotiation") == 0) 557296465Sdelphij off |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; 558296465Sdelphij else if (strcmp(*argv, "-legacy_server_connect") == 0) { 559296465Sdelphij off |= SSL_OP_LEGACY_SERVER_CONNECT; 560296465Sdelphij } else if (strcmp(*argv, "-no_legacy_server_connect") == 0) { 561296465Sdelphij clr |= SSL_OP_LEGACY_SERVER_CONNECT; 562296465Sdelphij } else if (strcmp(*argv, "-cipher") == 0) { 563296465Sdelphij if (--argc < 1) 564296465Sdelphij goto bad; 565296465Sdelphij cipher = *(++argv); 566296465Sdelphij } 56755714Skris#ifdef FIONBIO 568296465Sdelphij else if (strcmp(*argv, "-nbio") == 0) { 569296465Sdelphij c_nbio = 1; 570296465Sdelphij } 57155714Skris#endif 572296465Sdelphij else if (strcmp(*argv, "-starttls") == 0) { 573296465Sdelphij if (--argc < 1) 574296465Sdelphij goto bad; 575296465Sdelphij ++argv; 576296465Sdelphij if (strcmp(*argv, "smtp") == 0) 577296465Sdelphij starttls_proto = PROTO_SMTP; 578296465Sdelphij else if (strcmp(*argv, "pop3") == 0) 579296465Sdelphij starttls_proto = PROTO_POP3; 580296465Sdelphij else if (strcmp(*argv, "imap") == 0) 581296465Sdelphij starttls_proto = PROTO_IMAP; 582296465Sdelphij else if (strcmp(*argv, "ftp") == 0) 583296465Sdelphij starttls_proto = PROTO_FTP; 584296465Sdelphij else if (strcmp(*argv, "xmpp") == 0) 585296465Sdelphij starttls_proto = PROTO_XMPP; 586296465Sdelphij else 587296465Sdelphij goto bad; 588296465Sdelphij } 589111147Snectar#ifndef OPENSSL_NO_ENGINE 590296465Sdelphij else if (strcmp(*argv, "-engine") == 0) { 591296465Sdelphij if (--argc < 1) 592296465Sdelphij goto bad; 593296465Sdelphij engine_id = *(++argv); 594296465Sdelphij } else if (strcmp(*argv, "-ssl_client_engine") == 0) { 595296465Sdelphij if (--argc < 1) 596296465Sdelphij goto bad; 597296465Sdelphij ssl_client_engine_id = *(++argv); 598296465Sdelphij } 599111147Snectar#endif 600296465Sdelphij else if (strcmp(*argv, "-rand") == 0) { 601296465Sdelphij if (--argc < 1) 602296465Sdelphij goto bad; 603296465Sdelphij inrand = *(++argv); 604296465Sdelphij } 605194206Ssimon#ifndef OPENSSL_NO_TLSEXT 606296465Sdelphij else if (strcmp(*argv, "-servername") == 0) { 607296465Sdelphij if (--argc < 1) 608296465Sdelphij goto bad; 609296465Sdelphij servername = *(++argv); 610296465Sdelphij /* meth=TLSv1_client_method(); */ 611296465Sdelphij } 612194206Ssimon#endif 613194206Ssimon#ifndef OPENSSL_NO_JPAKE 614296465Sdelphij else if (strcmp(*argv, "-jpake") == 0) { 615296465Sdelphij if (--argc < 1) 616296465Sdelphij goto bad; 617296465Sdelphij jpake_secret = *++argv; 618296465Sdelphij } 619194206Ssimon#endif 620296465Sdelphij else { 621296465Sdelphij BIO_printf(bio_err, "unknown option %s\n", *argv); 622296465Sdelphij badop = 1; 623296465Sdelphij break; 624296465Sdelphij } 625296465Sdelphij argc--; 626296465Sdelphij argv++; 627296465Sdelphij } 628296465Sdelphij if (badop) { 629296465Sdelphij bad: 630296465Sdelphij sc_usage(); 631296465Sdelphij goto end; 632296465Sdelphij } 63355714Skris 634296465Sdelphij OpenSSL_add_ssl_algorithms(); 635296465Sdelphij SSL_load_error_strings(); 636109998Smarkm 637111147Snectar#ifndef OPENSSL_NO_ENGINE 638296465Sdelphij e = setup_engine(bio_err, engine_id, 1); 639296465Sdelphij if (ssl_client_engine_id) { 640296465Sdelphij ssl_client_engine = ENGINE_by_id(ssl_client_engine_id); 641296465Sdelphij if (!ssl_client_engine) { 642296465Sdelphij BIO_printf(bio_err, "Error getting client auth engine\n"); 643296465Sdelphij goto end; 644296465Sdelphij } 645296465Sdelphij } 646111147Snectar#endif 647296465Sdelphij if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { 648296465Sdelphij BIO_printf(bio_err, "Error getting password\n"); 649296465Sdelphij goto end; 650296465Sdelphij } 651109998Smarkm 652296465Sdelphij if (key_file == NULL) 653296465Sdelphij key_file = cert_file; 654160814Ssimon 655296465Sdelphij if (key_file) { 656160814Ssimon 657296465Sdelphij key = load_key(bio_err, key_file, key_format, 0, pass, e, 658296465Sdelphij "client certificate private key file"); 659296465Sdelphij if (!key) { 660296465Sdelphij ERR_print_errors(bio_err); 661296465Sdelphij goto end; 662296465Sdelphij } 663160814Ssimon 664296465Sdelphij } 665160814Ssimon 666296465Sdelphij if (cert_file) { 667296465Sdelphij cert = load_cert(bio_err, cert_file, cert_format, 668296465Sdelphij NULL, e, "client certificate file"); 669160814Ssimon 670296465Sdelphij if (!cert) { 671296465Sdelphij ERR_print_errors(bio_err); 672296465Sdelphij goto end; 673296465Sdelphij } 674296465Sdelphij } 675160814Ssimon 676296465Sdelphij if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL 677296465Sdelphij && !RAND_status()) { 678296465Sdelphij BIO_printf(bio_err, 679296465Sdelphij "warning, not much extra random data, consider using the -rand option\n"); 680296465Sdelphij } 681296465Sdelphij if (inrand != NULL) 682296465Sdelphij BIO_printf(bio_err, "%ld semi-random bytes loaded\n", 683296465Sdelphij app_RAND_load_files(inrand)); 684160814Ssimon 685296465Sdelphij if (bio_c_out == NULL) { 686296465Sdelphij if (c_quiet && !c_debug && !c_msg) { 687296465Sdelphij bio_c_out = BIO_new(BIO_s_null()); 688296465Sdelphij } else { 689296465Sdelphij if (bio_c_out == NULL) 690296465Sdelphij bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE); 691296465Sdelphij } 692296465Sdelphij } 693160814Ssimon 694296465Sdelphij ctx = SSL_CTX_new(meth); 695296465Sdelphij if (ctx == NULL) { 696296465Sdelphij ERR_print_errors(bio_err); 697296465Sdelphij goto end; 698296465Sdelphij } 699194206Ssimon#ifndef OPENSSL_NO_ENGINE 700296465Sdelphij if (ssl_client_engine) { 701296465Sdelphij if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) { 702296465Sdelphij BIO_puts(bio_err, "Error setting client auth engine\n"); 703296465Sdelphij ERR_print_errors(bio_err); 704296465Sdelphij ENGINE_free(ssl_client_engine); 705296465Sdelphij goto end; 706296465Sdelphij } 707296465Sdelphij ENGINE_free(ssl_client_engine); 708296465Sdelphij } 709194206Ssimon#endif 710194206Ssimon 711296465Sdelphij if (bugs) 712296465Sdelphij SSL_CTX_set_options(ctx, SSL_OP_ALL | off); 713296465Sdelphij else 714296465Sdelphij SSL_CTX_set_options(ctx, off); 715205128Ssimon 716296465Sdelphij if (clr) 717296465Sdelphij SSL_CTX_clear_options(ctx, clr); 718296465Sdelphij /* 719296465Sdelphij * DTLS: partial reads end up discarding unread UDP bytes :-( Setting 720296465Sdelphij * read ahead solves this problem. 721296465Sdelphij */ 722296465Sdelphij if (sock_type == SOCK_DGRAM) 723296465Sdelphij SSL_CTX_set_read_ahead(ctx, 1); 72455714Skris 725296465Sdelphij if (state) 726296465Sdelphij SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); 727296465Sdelphij if (cipher != NULL) 728296465Sdelphij if (!SSL_CTX_set_cipher_list(ctx, cipher)) { 729296465Sdelphij BIO_printf(bio_err, "error setting cipher list\n"); 730296465Sdelphij ERR_print_errors(bio_err); 731296465Sdelphij goto end; 732296465Sdelphij } 73355714Skris#if 0 734296465Sdelphij else 735296465Sdelphij SSL_CTX_set_cipher_list(ctx, getenv("SSL_CIPHER")); 73655714Skris#endif 73755714Skris 738296465Sdelphij SSL_CTX_set_verify(ctx, verify, verify_callback); 739296465Sdelphij if (!set_cert_key_stuff(ctx, cert, key)) 740296465Sdelphij goto end; 74155714Skris 742296465Sdelphij if ((!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) || 743296465Sdelphij (!SSL_CTX_set_default_verify_paths(ctx))) { 744296465Sdelphij /* 745296465Sdelphij * BIO_printf(bio_err,"error setting default verify locations\n"); 746296465Sdelphij */ 747296465Sdelphij ERR_print_errors(bio_err); 748296465Sdelphij /* goto end; */ 749296465Sdelphij } 75055714Skris 751296465Sdelphij store = SSL_CTX_get_cert_store(ctx); 752296465Sdelphij X509_STORE_set_flags(store, vflags); 753194206Ssimon#ifndef OPENSSL_NO_TLSEXT 754296465Sdelphij if (servername != NULL) { 755296465Sdelphij tlsextcbp.biodebug = bio_err; 756296465Sdelphij SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); 757296465Sdelphij SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); 758296465Sdelphij } 759194206Ssimon#endif 76055714Skris 761296465Sdelphij con = SSL_new(ctx); 762296465Sdelphij if (sess_in) { 763296465Sdelphij SSL_SESSION *sess; 764296465Sdelphij BIO *stmp = BIO_new_file(sess_in, "r"); 765296465Sdelphij if (!stmp) { 766296465Sdelphij BIO_printf(bio_err, "Can't open session file %s\n", sess_in); 767296465Sdelphij ERR_print_errors(bio_err); 768296465Sdelphij goto end; 769296465Sdelphij } 770296465Sdelphij sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); 771296465Sdelphij BIO_free(stmp); 772296465Sdelphij if (!sess) { 773296465Sdelphij BIO_printf(bio_err, "Can't open session file %s\n", sess_in); 774296465Sdelphij ERR_print_errors(bio_err); 775296465Sdelphij goto end; 776296465Sdelphij } 777296465Sdelphij SSL_set_session(con, sess); 778296465Sdelphij SSL_SESSION_free(sess); 779296465Sdelphij } 780273415Sdelphij 781296465Sdelphij if (fallback_scsv) 782296465Sdelphij SSL_set_mode(con, SSL_MODE_SEND_FALLBACK_SCSV); 783273415Sdelphij 784194206Ssimon#ifndef OPENSSL_NO_TLSEXT 785296465Sdelphij if (servername != NULL) { 786296465Sdelphij if (!SSL_set_tlsext_host_name(con, servername)) { 787296465Sdelphij BIO_printf(bio_err, "Unable to set TLS servername extension.\n"); 788296465Sdelphij ERR_print_errors(bio_err); 789296465Sdelphij goto end; 790296465Sdelphij } 791296465Sdelphij } 792194206Ssimon#endif 793194206Ssimon 794109998Smarkm#ifndef OPENSSL_NO_KRB5 795296465Sdelphij if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL) { 796296465Sdelphij kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host); 797296465Sdelphij } 798296465Sdelphij#endif /* OPENSSL_NO_KRB5 */ 799296465Sdelphij/* SSL_set_cipher_list(con,"RC4-MD5"); */ 80055714Skris 801296465Sdelphij re_start: 80255714Skris 803296465Sdelphij if (init_client(&s, host, port, sock_type) == 0) { 804296465Sdelphij BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error()); 805296465Sdelphij SHUTDOWN(s); 806296465Sdelphij goto end; 807296465Sdelphij } 808296465Sdelphij BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); 80955714Skris 81055714Skris#ifdef FIONBIO 811296465Sdelphij if (c_nbio) { 812296465Sdelphij unsigned long l = 1; 813296465Sdelphij BIO_printf(bio_c_out, "turning on non blocking io\n"); 814296465Sdelphij if (BIO_socket_ioctl(s, FIONBIO, &l) < 0) { 815296465Sdelphij ERR_print_errors(bio_err); 816296465Sdelphij goto end; 817296465Sdelphij } 818296465Sdelphij } 819296465Sdelphij#endif 820296465Sdelphij if (c_Pause & 0x01) 821296465Sdelphij con->debug = 1; 82255714Skris 823296465Sdelphij if (SSL_version(con) == DTLS1_VERSION) { 824160814Ssimon 825296465Sdelphij sbio = BIO_new_dgram(s, BIO_NOCLOSE); 826296465Sdelphij if (getsockname(s, &peer, (void *)&peerlen) < 0) { 827296465Sdelphij BIO_printf(bio_err, "getsockname:errno=%d\n", 828296465Sdelphij get_last_socket_error()); 829296465Sdelphij SHUTDOWN(s); 830296465Sdelphij goto end; 831296465Sdelphij } 832160814Ssimon 833296465Sdelphij (void)BIO_ctrl_set_connected(sbio, 1, &peer); 834160814Ssimon 835296465Sdelphij if (enable_timeouts) { 836296465Sdelphij timeout.tv_sec = 0; 837296465Sdelphij timeout.tv_usec = DGRAM_RCV_TIMEOUT; 838296465Sdelphij BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); 839160814Ssimon 840296465Sdelphij timeout.tv_sec = 0; 841296465Sdelphij timeout.tv_usec = DGRAM_SND_TIMEOUT; 842296465Sdelphij BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); 843296465Sdelphij } 844160814Ssimon 845296465Sdelphij if (socket_mtu > 28) { 846296465Sdelphij SSL_set_options(con, SSL_OP_NO_QUERY_MTU); 847296465Sdelphij SSL_set_mtu(con, socket_mtu - 28); 848296465Sdelphij } else 849296465Sdelphij /* want to do MTU discovery */ 850296465Sdelphij BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); 851296465Sdelphij } else 852296465Sdelphij sbio = BIO_new_socket(s, BIO_NOCLOSE); 85355714Skris 854296465Sdelphij if (nbio_test) { 855296465Sdelphij BIO *test; 85655714Skris 857296465Sdelphij test = BIO_new(BIO_f_nbio_test()); 858296465Sdelphij sbio = BIO_push(test, sbio); 859296465Sdelphij } 860296465Sdelphij 861296465Sdelphij if (c_debug) { 862296465Sdelphij con->debug = 1; 863296465Sdelphij BIO_set_callback(sbio, bio_dump_callback); 864296465Sdelphij BIO_set_callback_arg(sbio, (char *)bio_c_out); 865296465Sdelphij } 866296465Sdelphij if (c_msg) { 867296465Sdelphij SSL_set_msg_callback(con, msg_cb); 868296465Sdelphij SSL_set_msg_callback_arg(con, bio_c_out); 869296465Sdelphij } 870194206Ssimon#ifndef OPENSSL_NO_TLSEXT 871296465Sdelphij if (c_tlsextdebug) { 872296465Sdelphij SSL_set_tlsext_debug_callback(con, tlsext_cb); 873296465Sdelphij SSL_set_tlsext_debug_arg(con, bio_c_out); 874296465Sdelphij } 875296465Sdelphij if (c_status_req) { 876296465Sdelphij SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp); 877296465Sdelphij SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb); 878296465Sdelphij SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out); 879296465Sdelphij# if 0 880296465Sdelphij { 881296465Sdelphij STACK_OF(OCSP_RESPID) *ids = sk_OCSP_RESPID_new_null(); 882296465Sdelphij OCSP_RESPID *id = OCSP_RESPID_new(); 883296465Sdelphij id->value.byKey = ASN1_OCTET_STRING_new(); 884296465Sdelphij id->type = V_OCSP_RESPID_KEY; 885296465Sdelphij ASN1_STRING_set(id->value.byKey, "Hello World", -1); 886296465Sdelphij sk_OCSP_RESPID_push(ids, id); 887296465Sdelphij SSL_set_tlsext_status_ids(con, ids); 888296465Sdelphij } 889296465Sdelphij# endif 890296465Sdelphij } 891194206Ssimon#endif 892194206Ssimon#ifndef OPENSSL_NO_JPAKE 893296465Sdelphij if (jpake_secret) 894296465Sdelphij jpake_client_auth(bio_c_out, sbio, jpake_secret); 895194206Ssimon#endif 89655714Skris 897296465Sdelphij SSL_set_bio(con, sbio, sbio); 898296465Sdelphij SSL_set_connect_state(con); 89955714Skris 900296465Sdelphij /* ok, lets connect */ 901296465Sdelphij width = SSL_get_fd(con) + 1; 90255714Skris 903296465Sdelphij read_tty = 1; 904296465Sdelphij write_tty = 0; 905296465Sdelphij tty_on = 0; 906296465Sdelphij read_ssl = 1; 907296465Sdelphij write_ssl = 1; 90855714Skris 909296465Sdelphij cbuf_len = 0; 910296465Sdelphij cbuf_off = 0; 911296465Sdelphij sbuf_len = 0; 912296465Sdelphij sbuf_off = 0; 913109998Smarkm 914296465Sdelphij /* This is an ugly hack that does a lot of assumptions */ 915296465Sdelphij /* 916296465Sdelphij * We do have to handle multi-line responses which may come in a single 917296465Sdelphij * packet or not. We therefore have to use BIO_gets() which does need a 918296465Sdelphij * buffering BIO. So during the initial chitchat we do push a buffering 919296465Sdelphij * BIO into the chain that is removed again later on to not disturb the 920296465Sdelphij * rest of the s_client operation. 921296465Sdelphij */ 922296465Sdelphij if (starttls_proto == PROTO_SMTP) { 923296465Sdelphij int foundit = 0; 924296465Sdelphij BIO *fbio = BIO_new(BIO_f_buffer()); 925296465Sdelphij BIO_push(fbio, sbio); 926296465Sdelphij /* wait for multi-line response to end from SMTP */ 927296465Sdelphij do { 928296465Sdelphij mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); 929296465Sdelphij } 930296465Sdelphij while (mbuf_len > 3 && mbuf[3] == '-'); 931296465Sdelphij /* STARTTLS command requires EHLO... */ 932296465Sdelphij BIO_printf(fbio, "EHLO openssl.client.net\r\n"); 933296465Sdelphij (void)BIO_flush(fbio); 934296465Sdelphij /* wait for multi-line response to end EHLO SMTP response */ 935296465Sdelphij do { 936296465Sdelphij mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); 937296465Sdelphij if (strstr(mbuf, "STARTTLS")) 938296465Sdelphij foundit = 1; 939296465Sdelphij } 940296465Sdelphij while (mbuf_len > 3 && mbuf[3] == '-'); 941296465Sdelphij (void)BIO_flush(fbio); 942296465Sdelphij BIO_pop(fbio); 943296465Sdelphij BIO_free(fbio); 944296465Sdelphij if (!foundit) 945296465Sdelphij BIO_printf(bio_err, 946296465Sdelphij "didn't found starttls in server response," 947296465Sdelphij " try anyway...\n"); 948296465Sdelphij BIO_printf(sbio, "STARTTLS\r\n"); 949296465Sdelphij BIO_read(sbio, sbuf, BUFSIZZ); 950296465Sdelphij } else if (starttls_proto == PROTO_POP3) { 951296465Sdelphij BIO_read(sbio, mbuf, BUFSIZZ); 952296465Sdelphij BIO_printf(sbio, "STLS\r\n"); 953296465Sdelphij BIO_read(sbio, sbuf, BUFSIZZ); 954296465Sdelphij } else if (starttls_proto == PROTO_IMAP) { 955296465Sdelphij int foundit = 0; 956296465Sdelphij BIO *fbio = BIO_new(BIO_f_buffer()); 957296465Sdelphij BIO_push(fbio, sbio); 958296465Sdelphij BIO_gets(fbio, mbuf, BUFSIZZ); 959296465Sdelphij /* STARTTLS command requires CAPABILITY... */ 960296465Sdelphij BIO_printf(fbio, ". CAPABILITY\r\n"); 961296465Sdelphij (void)BIO_flush(fbio); 962296465Sdelphij /* wait for multi-line CAPABILITY response */ 963296465Sdelphij do { 964296465Sdelphij mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); 965296465Sdelphij if (strstr(mbuf, "STARTTLS")) 966296465Sdelphij foundit = 1; 967296465Sdelphij } 968296465Sdelphij while (mbuf_len > 3 && mbuf[0] != '.'); 969296465Sdelphij (void)BIO_flush(fbio); 970296465Sdelphij BIO_pop(fbio); 971296465Sdelphij BIO_free(fbio); 972296465Sdelphij if (!foundit) 973296465Sdelphij BIO_printf(bio_err, 974296465Sdelphij "didn't found STARTTLS in server response," 975296465Sdelphij " try anyway...\n"); 976296465Sdelphij BIO_printf(sbio, ". STARTTLS\r\n"); 977296465Sdelphij BIO_read(sbio, sbuf, BUFSIZZ); 978296465Sdelphij } else if (starttls_proto == PROTO_FTP) { 979296465Sdelphij BIO *fbio = BIO_new(BIO_f_buffer()); 980296465Sdelphij BIO_push(fbio, sbio); 981296465Sdelphij /* wait for multi-line response to end from FTP */ 982296465Sdelphij do { 983296465Sdelphij mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); 984296465Sdelphij } 985296465Sdelphij while (mbuf_len > 3 && mbuf[3] == '-'); 986296465Sdelphij (void)BIO_flush(fbio); 987296465Sdelphij BIO_pop(fbio); 988296465Sdelphij BIO_free(fbio); 989296465Sdelphij BIO_printf(sbio, "AUTH TLS\r\n"); 990296465Sdelphij BIO_read(sbio, sbuf, BUFSIZZ); 991296465Sdelphij } 992296465Sdelphij if (starttls_proto == PROTO_XMPP) { 993296465Sdelphij int seen = 0; 994296465Sdelphij BIO_printf(sbio, "<stream:stream " 995296465Sdelphij "xmlns:stream='http://etherx.jabber.org/streams' " 996296465Sdelphij "xmlns='jabber:client' to='%s' version='1.0'>", host); 997296465Sdelphij seen = BIO_read(sbio, mbuf, BUFSIZZ); 998296465Sdelphij mbuf[seen] = 0; 999296465Sdelphij while (!strstr 1000296465Sdelphij (mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")) { 1001296465Sdelphij if (strstr(mbuf, "/stream:features>")) 1002296465Sdelphij goto shut; 1003296465Sdelphij seen = BIO_read(sbio, mbuf, BUFSIZZ); 1004296465Sdelphij mbuf[seen] = 0; 1005296465Sdelphij } 1006296465Sdelphij BIO_printf(sbio, 1007296465Sdelphij "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); 1008296465Sdelphij seen = BIO_read(sbio, sbuf, BUFSIZZ); 1009296465Sdelphij sbuf[seen] = 0; 1010296465Sdelphij if (!strstr(sbuf, "<proceed")) 1011296465Sdelphij goto shut; 1012296465Sdelphij mbuf[0] = 0; 1013296465Sdelphij } 101455714Skris 1015296465Sdelphij for (;;) { 1016296465Sdelphij FD_ZERO(&readfds); 1017296465Sdelphij FD_ZERO(&writefds); 1018205128Ssimon 1019296465Sdelphij if ((SSL_version(con) == DTLS1_VERSION) && 1020296465Sdelphij DTLSv1_get_timeout(con, &timeout)) 1021296465Sdelphij timeoutp = &timeout; 1022296465Sdelphij else 1023296465Sdelphij timeoutp = NULL; 102455714Skris 1025296465Sdelphij if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { 1026296465Sdelphij in_init = 1; 1027296465Sdelphij tty_on = 0; 1028296465Sdelphij } else { 1029296465Sdelphij tty_on = 1; 1030296465Sdelphij if (in_init) { 1031296465Sdelphij in_init = 0; 1032296465Sdelphij if (sess_out) { 1033296465Sdelphij BIO *stmp = BIO_new_file(sess_out, "w"); 1034296465Sdelphij if (stmp) { 1035296465Sdelphij PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con)); 1036296465Sdelphij BIO_free(stmp); 1037296465Sdelphij } else 1038296465Sdelphij BIO_printf(bio_err, "Error writing session file %s\n", 1039296465Sdelphij sess_out); 1040296465Sdelphij } 1041296465Sdelphij print_stuff(bio_c_out, con, full_log); 1042296465Sdelphij if (full_log > 0) 1043296465Sdelphij full_log--; 1044109998Smarkm 1045296465Sdelphij if (starttls_proto) { 1046296465Sdelphij BIO_printf(bio_err, "%s", mbuf); 1047296465Sdelphij /* We don't need to know any more */ 1048296465Sdelphij starttls_proto = PROTO_OFF; 1049296465Sdelphij } 105055714Skris 1051296465Sdelphij if (reconnect) { 1052296465Sdelphij reconnect--; 1053296465Sdelphij BIO_printf(bio_c_out, 1054296465Sdelphij "drop connection and then reconnect\n"); 1055296465Sdelphij SSL_shutdown(con); 1056296465Sdelphij SSL_set_connect_state(con); 1057296465Sdelphij SHUTDOWN(SSL_get_fd(con)); 1058296465Sdelphij goto re_start; 1059296465Sdelphij } 1060296465Sdelphij } 1061296465Sdelphij } 106255714Skris 1063296465Sdelphij ssl_pending = read_ssl && SSL_pending(con); 1064296465Sdelphij 1065296465Sdelphij if (!ssl_pending) { 1066160814Ssimon#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) 1067296465Sdelphij if (tty_on) { 1068296465Sdelphij if (read_tty) 1069296465Sdelphij FD_SET(fileno(stdin), &readfds); 1070296465Sdelphij if (write_tty) 1071296465Sdelphij FD_SET(fileno(stdout), &writefds); 1072296465Sdelphij } 1073296465Sdelphij if (read_ssl) 1074296465Sdelphij FD_SET(SSL_get_fd(con), &readfds); 1075296465Sdelphij if (write_ssl) 1076296465Sdelphij FD_SET(SSL_get_fd(con), &writefds); 107759191Skris#else 1078296465Sdelphij if (!tty_on || !write_tty) { 1079296465Sdelphij if (read_ssl) 1080296465Sdelphij FD_SET(SSL_get_fd(con), &readfds); 1081296465Sdelphij if (write_ssl) 1082296465Sdelphij FD_SET(SSL_get_fd(con), &writefds); 1083296465Sdelphij } 108459191Skris#endif 1085296465Sdelphij/*- printf("mode tty(%d %d%d) ssl(%d%d)\n", 1086296465Sdelphij tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ 108755714Skris 1088296465Sdelphij /* 1089296465Sdelphij * Note: under VMS with SOCKETSHR the second parameter is 1090296465Sdelphij * currently of type (int *) whereas under other systems it is 1091296465Sdelphij * (void *) if you don't have a cast it will choke the compiler: 1092296465Sdelphij * if you do have a cast then you can either go for (int *) or 1093296465Sdelphij * (void *). 1094296465Sdelphij */ 1095120631Snectar#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) 1096296465Sdelphij /* 1097296465Sdelphij * Under Windows/DOS we make the assumption that we can always 1098296465Sdelphij * write to the tty: therefore if we need to write to the tty we 1099296465Sdelphij * just fall through. Otherwise we timeout the select every 1100296465Sdelphij * second and see if there are any keypresses. Note: this is a 1101296465Sdelphij * hack, in a proper Windows application we wouldn't do this. 1102296465Sdelphij */ 1103296465Sdelphij i = 0; 1104296465Sdelphij if (!write_tty) { 1105296465Sdelphij if (read_tty) { 1106296465Sdelphij tv.tv_sec = 1; 1107296465Sdelphij tv.tv_usec = 0; 1108296465Sdelphij i = select(width, (void *)&readfds, (void *)&writefds, 1109296465Sdelphij NULL, &tv); 1110296465Sdelphij# if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) 1111296465Sdelphij if (!i && (!_kbhit() || !read_tty)) 1112296465Sdelphij continue; 1113296465Sdelphij# else 1114296465Sdelphij if (!i && (!((_kbhit()) 1115296465Sdelphij || (WAIT_OBJECT_0 == 1116296465Sdelphij WaitForSingleObject(GetStdHandle 1117296465Sdelphij (STD_INPUT_HANDLE), 1118296465Sdelphij 0))) 1119296465Sdelphij || !read_tty)) 1120296465Sdelphij continue; 1121296465Sdelphij# endif 1122296465Sdelphij } else 1123296465Sdelphij i = select(width, (void *)&readfds, (void *)&writefds, 1124296465Sdelphij NULL, timeoutp); 1125296465Sdelphij } 1126160814Ssimon#elif defined(OPENSSL_SYS_NETWARE) 1127296465Sdelphij if (!write_tty) { 1128296465Sdelphij if (read_tty) { 1129296465Sdelphij tv.tv_sec = 1; 1130296465Sdelphij tv.tv_usec = 0; 1131296465Sdelphij i = select(width, (void *)&readfds, (void *)&writefds, 1132296465Sdelphij NULL, &tv); 1133296465Sdelphij } else 1134296465Sdelphij i = select(width, (void *)&readfds, (void *)&writefds, 1135296465Sdelphij NULL, timeoutp); 1136296465Sdelphij } 113759191Skris#else 1138296465Sdelphij i = select(width, (void *)&readfds, (void *)&writefds, 1139296465Sdelphij NULL, timeoutp); 114059191Skris#endif 1141296465Sdelphij if (i < 0) { 1142296465Sdelphij BIO_printf(bio_err, "bad select %d\n", 1143296465Sdelphij get_last_socket_error()); 1144296465Sdelphij goto shut; 1145296465Sdelphij /* goto end; */ 1146296465Sdelphij } 1147296465Sdelphij } 114855714Skris 1149296465Sdelphij if ((SSL_version(con) == DTLS1_VERSION) 1150296465Sdelphij && DTLSv1_handle_timeout(con) > 0) { 1151296465Sdelphij BIO_printf(bio_err, "TIMEOUT occured\n"); 1152296465Sdelphij } 1153205128Ssimon 1154296465Sdelphij if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) { 1155296465Sdelphij k = SSL_write(con, &(cbuf[cbuf_off]), (unsigned int)cbuf_len); 1156296465Sdelphij switch (SSL_get_error(con, k)) { 1157296465Sdelphij case SSL_ERROR_NONE: 1158296465Sdelphij cbuf_off += k; 1159296465Sdelphij cbuf_len -= k; 1160296465Sdelphij if (k <= 0) 1161296465Sdelphij goto end; 1162296465Sdelphij /* we have done a write(con,NULL,0); */ 1163296465Sdelphij if (cbuf_len <= 0) { 1164296465Sdelphij read_tty = 1; 1165296465Sdelphij write_ssl = 0; 1166296465Sdelphij } else { /* if (cbuf_len > 0) */ 1167296465Sdelphij 1168296465Sdelphij read_tty = 0; 1169296465Sdelphij write_ssl = 1; 1170296465Sdelphij } 1171296465Sdelphij break; 1172296465Sdelphij case SSL_ERROR_WANT_WRITE: 1173296465Sdelphij BIO_printf(bio_c_out, "write W BLOCK\n"); 1174296465Sdelphij write_ssl = 1; 1175296465Sdelphij read_tty = 0; 1176296465Sdelphij break; 1177296465Sdelphij case SSL_ERROR_WANT_READ: 1178296465Sdelphij BIO_printf(bio_c_out, "write R BLOCK\n"); 1179296465Sdelphij write_tty = 0; 1180296465Sdelphij read_ssl = 1; 1181296465Sdelphij write_ssl = 0; 1182296465Sdelphij break; 1183296465Sdelphij case SSL_ERROR_WANT_X509_LOOKUP: 1184296465Sdelphij BIO_printf(bio_c_out, "write X BLOCK\n"); 1185296465Sdelphij break; 1186296465Sdelphij case SSL_ERROR_ZERO_RETURN: 1187296465Sdelphij if (cbuf_len != 0) { 1188296465Sdelphij BIO_printf(bio_c_out, "shutdown\n"); 1189296465Sdelphij goto shut; 1190296465Sdelphij } else { 1191296465Sdelphij read_tty = 1; 1192296465Sdelphij write_ssl = 0; 1193296465Sdelphij break; 1194296465Sdelphij } 1195296465Sdelphij 1196296465Sdelphij case SSL_ERROR_SYSCALL: 1197296465Sdelphij if ((k != 0) || (cbuf_len != 0)) { 1198296465Sdelphij BIO_printf(bio_err, "write:errno=%d\n", 1199296465Sdelphij get_last_socket_error()); 1200296465Sdelphij goto shut; 1201296465Sdelphij } else { 1202296465Sdelphij read_tty = 1; 1203296465Sdelphij write_ssl = 0; 1204296465Sdelphij } 1205296465Sdelphij break; 1206296465Sdelphij case SSL_ERROR_SSL: 1207296465Sdelphij ERR_print_errors(bio_err); 1208296465Sdelphij goto shut; 1209296465Sdelphij } 1210296465Sdelphij } 1211160814Ssimon#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) 1212296465Sdelphij /* Assume Windows/DOS can always write */ 1213296465Sdelphij else if (!ssl_pending && write_tty) 121459191Skris#else 1215296465Sdelphij else if (!ssl_pending && FD_ISSET(fileno(stdout), &writefds)) 121659191Skris#endif 1217296465Sdelphij { 121855714Skris#ifdef CHARSET_EBCDIC 1219296465Sdelphij ascii2ebcdic(&(sbuf[sbuf_off]), &(sbuf[sbuf_off]), sbuf_len); 122055714Skris#endif 1221296465Sdelphij i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len); 122255714Skris 1223296465Sdelphij if (i <= 0) { 1224296465Sdelphij BIO_printf(bio_c_out, "DONE\n"); 1225296465Sdelphij goto shut; 1226296465Sdelphij /* goto end; */ 1227296465Sdelphij } 122855714Skris 1229296465Sdelphij sbuf_len -= i;; 1230296465Sdelphij sbuf_off += i; 1231296465Sdelphij if (sbuf_len <= 0) { 1232296465Sdelphij read_ssl = 1; 1233296465Sdelphij write_tty = 0; 1234296465Sdelphij } 1235296465Sdelphij } else if (ssl_pending || FD_ISSET(SSL_get_fd(con), &readfds)) { 123655714Skris#ifdef RENEG 1237296465Sdelphij { 1238296465Sdelphij static int iiii; 1239296465Sdelphij if (++iiii == 52) { 1240296465Sdelphij SSL_renegotiate(con); 1241296465Sdelphij iiii = 0; 1242296465Sdelphij } 1243296465Sdelphij } 124455714Skris#endif 124555714Skris#if 1 1246296465Sdelphij k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ ); 124755714Skris#else 124855714Skris/* Demo for pending and peek :-) */ 1249296465Sdelphij k = SSL_read(con, sbuf, 16); 1250296465Sdelphij { 1251296465Sdelphij char zbuf[10240]; 1252296465Sdelphij printf("read=%d pending=%d peek=%d\n", k, SSL_pending(con), 1253296465Sdelphij SSL_peek(con, zbuf, 10240)); 1254296465Sdelphij } 125555714Skris#endif 125655714Skris 1257296465Sdelphij switch (SSL_get_error(con, k)) { 1258296465Sdelphij case SSL_ERROR_NONE: 1259296465Sdelphij if (k <= 0) 1260296465Sdelphij goto end; 1261296465Sdelphij sbuf_off = 0; 1262296465Sdelphij sbuf_len = k; 126355714Skris 1264296465Sdelphij read_ssl = 0; 1265296465Sdelphij write_tty = 1; 1266296465Sdelphij break; 1267296465Sdelphij case SSL_ERROR_WANT_WRITE: 1268296465Sdelphij BIO_printf(bio_c_out, "read W BLOCK\n"); 1269296465Sdelphij write_ssl = 1; 1270296465Sdelphij read_tty = 0; 1271296465Sdelphij break; 1272296465Sdelphij case SSL_ERROR_WANT_READ: 1273296465Sdelphij BIO_printf(bio_c_out, "read R BLOCK\n"); 1274296465Sdelphij write_tty = 0; 1275296465Sdelphij read_ssl = 1; 1276296465Sdelphij if ((read_tty == 0) && (write_ssl == 0)) 1277296465Sdelphij write_ssl = 1; 1278296465Sdelphij break; 1279296465Sdelphij case SSL_ERROR_WANT_X509_LOOKUP: 1280296465Sdelphij BIO_printf(bio_c_out, "read X BLOCK\n"); 1281296465Sdelphij break; 1282296465Sdelphij case SSL_ERROR_SYSCALL: 1283296465Sdelphij BIO_printf(bio_err, "read:errno=%d\n", 1284296465Sdelphij get_last_socket_error()); 1285296465Sdelphij goto shut; 1286296465Sdelphij case SSL_ERROR_ZERO_RETURN: 1287296465Sdelphij BIO_printf(bio_c_out, "closed\n"); 1288296465Sdelphij goto shut; 1289296465Sdelphij case SSL_ERROR_SSL: 1290296465Sdelphij ERR_print_errors(bio_err); 1291296465Sdelphij goto shut; 1292296465Sdelphij /* break; */ 1293296465Sdelphij } 1294296465Sdelphij } 1295120631Snectar#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) 1296296465Sdelphij# if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) 1297296465Sdelphij else if (_kbhit()) 1298296465Sdelphij# else 1299296465Sdelphij else if ((_kbhit()) 1300296465Sdelphij || (WAIT_OBJECT_0 == 1301296465Sdelphij WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) 1302296465Sdelphij# endif 1303160814Ssimon#elif defined (OPENSSL_SYS_NETWARE) 1304160814Ssimon else if (_kbhit()) 130559191Skris#else 1306296465Sdelphij else if (FD_ISSET(fileno(stdin), &readfds)) 130759191Skris#endif 1308296465Sdelphij { 1309296465Sdelphij if (crlf) { 1310296465Sdelphij int j, lf_num; 131155714Skris 1312296465Sdelphij i = read(fileno(stdin), cbuf, BUFSIZZ / 2); 1313296465Sdelphij lf_num = 0; 1314296465Sdelphij /* both loops are skipped when i <= 0 */ 1315296465Sdelphij for (j = 0; j < i; j++) 1316296465Sdelphij if (cbuf[j] == '\n') 1317296465Sdelphij lf_num++; 1318296465Sdelphij for (j = i - 1; j >= 0; j--) { 1319296465Sdelphij cbuf[j + lf_num] = cbuf[j]; 1320296465Sdelphij if (cbuf[j] == '\n') { 1321296465Sdelphij lf_num--; 1322296465Sdelphij i++; 1323296465Sdelphij cbuf[j + lf_num] = '\r'; 1324296465Sdelphij } 1325296465Sdelphij } 1326296465Sdelphij assert(lf_num == 0); 1327296465Sdelphij } else 1328296465Sdelphij i = read(fileno(stdin), cbuf, BUFSIZZ); 132955714Skris 1330296465Sdelphij if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) { 1331296465Sdelphij BIO_printf(bio_err, "DONE\n"); 1332296465Sdelphij goto shut; 1333296465Sdelphij } 133455714Skris 1335296465Sdelphij if ((!c_ign_eof) && (cbuf[0] == 'R')) { 1336296465Sdelphij BIO_printf(bio_err, "RENEGOTIATING\n"); 1337296465Sdelphij SSL_renegotiate(con); 1338296465Sdelphij cbuf_len = 0; 1339296465Sdelphij } else { 1340296465Sdelphij cbuf_len = i; 1341296465Sdelphij cbuf_off = 0; 134255714Skris#ifdef CHARSET_EBCDIC 1343296465Sdelphij ebcdic2ascii(cbuf, cbuf, i); 134455714Skris#endif 1345296465Sdelphij } 134655714Skris 1347296465Sdelphij write_ssl = 1; 1348296465Sdelphij read_tty = 0; 1349296465Sdelphij } 1350296465Sdelphij } 1351296465Sdelphij shut: 1352296465Sdelphij SSL_shutdown(con); 1353296465Sdelphij SHUTDOWN(SSL_get_fd(con)); 1354296465Sdelphij ret = 0; 1355296465Sdelphij end: 1356296465Sdelphij if (prexit) 1357296465Sdelphij print_stuff(bio_c_out, con, 1); 1358296465Sdelphij if (con != NULL) 1359296465Sdelphij SSL_free(con); 1360296465Sdelphij if (con2 != NULL) 1361296465Sdelphij SSL_free(con2); 1362296465Sdelphij if (ctx != NULL) 1363296465Sdelphij SSL_CTX_free(ctx); 1364296465Sdelphij if (cert) 1365296465Sdelphij X509_free(cert); 1366296465Sdelphij if (key) 1367296465Sdelphij EVP_PKEY_free(key); 1368296465Sdelphij if (pass) 1369296465Sdelphij OPENSSL_free(pass); 1370296465Sdelphij if (cbuf != NULL) { 1371296465Sdelphij OPENSSL_cleanse(cbuf, BUFSIZZ); 1372296465Sdelphij OPENSSL_free(cbuf); 1373296465Sdelphij } 1374296465Sdelphij if (sbuf != NULL) { 1375296465Sdelphij OPENSSL_cleanse(sbuf, BUFSIZZ); 1376296465Sdelphij OPENSSL_free(sbuf); 1377296465Sdelphij } 1378296465Sdelphij if (mbuf != NULL) { 1379296465Sdelphij OPENSSL_cleanse(mbuf, BUFSIZZ); 1380296465Sdelphij OPENSSL_free(mbuf); 1381296465Sdelphij } 1382296465Sdelphij if (bio_c_out != NULL) { 1383296465Sdelphij BIO_free(bio_c_out); 1384296465Sdelphij bio_c_out = NULL; 1385296465Sdelphij } 1386296465Sdelphij apps_shutdown(); 1387296465Sdelphij OPENSSL_EXIT(ret); 1388296465Sdelphij} 138955714Skris 139055714Skrisstatic void print_stuff(BIO *bio, SSL *s, int full) 1391296465Sdelphij{ 1392296465Sdelphij X509 *peer = NULL; 1393296465Sdelphij char *p; 1394296465Sdelphij static const char *space = " "; 1395296465Sdelphij char buf[BUFSIZ]; 1396296465Sdelphij STACK_OF(X509) *sk; 1397296465Sdelphij STACK_OF(X509_NAME) *sk2; 1398296465Sdelphij SSL_CIPHER *c; 1399296465Sdelphij X509_NAME *xn; 1400296465Sdelphij int j, i; 1401160814Ssimon#ifndef OPENSSL_NO_COMP 1402296465Sdelphij const COMP_METHOD *comp, *expansion; 1403160814Ssimon#endif 140455714Skris 1405296465Sdelphij if (full) { 1406296465Sdelphij int got_a_chain = 0; 140755714Skris 1408296465Sdelphij sk = SSL_get_peer_cert_chain(s); 1409296465Sdelphij if (sk != NULL) { 1410296465Sdelphij got_a_chain = 1; /* we don't have it for SSL2 (yet) */ 141155714Skris 1412296465Sdelphij BIO_printf(bio, "---\nCertificate chain\n"); 1413296465Sdelphij for (i = 0; i < sk_X509_num(sk); i++) { 1414296465Sdelphij X509_NAME_oneline(X509_get_subject_name(sk_X509_value(sk, i)), 1415296465Sdelphij buf, sizeof buf); 1416296465Sdelphij BIO_printf(bio, "%2d s:%s\n", i, buf); 1417296465Sdelphij X509_NAME_oneline(X509_get_issuer_name(sk_X509_value(sk, i)), 1418296465Sdelphij buf, sizeof buf); 1419296465Sdelphij BIO_printf(bio, " i:%s\n", buf); 1420296465Sdelphij if (c_showcerts) 1421296465Sdelphij PEM_write_bio_X509(bio, sk_X509_value(sk, i)); 1422296465Sdelphij } 1423296465Sdelphij } 142455714Skris 1425296465Sdelphij BIO_printf(bio, "---\n"); 1426296465Sdelphij peer = SSL_get_peer_certificate(s); 1427296465Sdelphij if (peer != NULL) { 1428296465Sdelphij BIO_printf(bio, "Server certificate\n"); 142955714Skris 1430296465Sdelphij /* Redundant if we showed the whole chain */ 1431296465Sdelphij if (!(c_showcerts && got_a_chain)) 1432296465Sdelphij PEM_write_bio_X509(bio, peer); 1433296465Sdelphij X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof buf); 1434296465Sdelphij BIO_printf(bio, "subject=%s\n", buf); 1435296465Sdelphij X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof buf); 1436296465Sdelphij BIO_printf(bio, "issuer=%s\n", buf); 1437296465Sdelphij } else 1438296465Sdelphij BIO_printf(bio, "no peer certificate available\n"); 143955714Skris 1440296465Sdelphij sk2 = SSL_get_client_CA_list(s); 1441296465Sdelphij if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) { 1442296465Sdelphij BIO_printf(bio, "---\nAcceptable client certificate CA names\n"); 1443296465Sdelphij for (i = 0; i < sk_X509_NAME_num(sk2); i++) { 1444296465Sdelphij xn = sk_X509_NAME_value(sk2, i); 1445296465Sdelphij X509_NAME_oneline(xn, buf, sizeof(buf)); 1446296465Sdelphij BIO_write(bio, buf, strlen(buf)); 1447296465Sdelphij BIO_write(bio, "\n", 1); 1448296465Sdelphij } 1449296465Sdelphij } else { 1450296465Sdelphij BIO_printf(bio, "---\nNo client certificate CA names sent\n"); 1451296465Sdelphij } 1452296465Sdelphij p = SSL_get_shared_ciphers(s, buf, sizeof buf); 1453296465Sdelphij if (p != NULL) { 1454296465Sdelphij /* 1455296465Sdelphij * This works only for SSL 2. In later protocol versions, the 1456296465Sdelphij * client does not know what other ciphers (in addition to the 1457296465Sdelphij * one to be used in the current connection) the server supports. 1458296465Sdelphij */ 145955714Skris 1460296465Sdelphij BIO_printf(bio, 1461296465Sdelphij "---\nCiphers common between both SSL endpoints:\n"); 1462296465Sdelphij j = i = 0; 1463296465Sdelphij while (*p) { 1464296465Sdelphij if (*p == ':') { 1465296465Sdelphij BIO_write(bio, space, 15 - j % 25); 1466296465Sdelphij i++; 1467296465Sdelphij j = 0; 1468296465Sdelphij BIO_write(bio, ((i % 3) ? " " : "\n"), 1); 1469296465Sdelphij } else { 1470296465Sdelphij BIO_write(bio, p, 1); 1471296465Sdelphij j++; 1472296465Sdelphij } 1473296465Sdelphij p++; 1474296465Sdelphij } 1475296465Sdelphij BIO_write(bio, "\n", 1); 1476296465Sdelphij } 1477296465Sdelphij 1478296465Sdelphij BIO_printf(bio, 1479296465Sdelphij "---\nSSL handshake has read %ld bytes and written %ld bytes\n", 1480296465Sdelphij BIO_number_read(SSL_get_rbio(s)), 1481296465Sdelphij BIO_number_written(SSL_get_wbio(s))); 1482296465Sdelphij } 1483296465Sdelphij BIO_printf(bio, ((s->hit) ? "---\nReused, " : "---\nNew, ")); 1484296465Sdelphij c = SSL_get_current_cipher(s); 1485296465Sdelphij BIO_printf(bio, "%s, Cipher is %s\n", 1486296465Sdelphij SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); 1487296465Sdelphij if (peer != NULL) { 1488296465Sdelphij EVP_PKEY *pktmp; 1489296465Sdelphij pktmp = X509_get_pubkey(peer); 1490296465Sdelphij BIO_printf(bio, "Server public key is %d bit\n", 1491296465Sdelphij EVP_PKEY_bits(pktmp)); 1492296465Sdelphij EVP_PKEY_free(pktmp); 1493296465Sdelphij } 1494296465Sdelphij BIO_printf(bio, "Secure Renegotiation IS%s supported\n", 1495296465Sdelphij SSL_get_secure_renegotiation_support(s) ? "" : " NOT"); 1496160814Ssimon#ifndef OPENSSL_NO_COMP 1497296465Sdelphij comp = SSL_get_current_compression(s); 1498296465Sdelphij expansion = SSL_get_current_expansion(s); 1499296465Sdelphij BIO_printf(bio, "Compression: %s\n", 1500296465Sdelphij comp ? SSL_COMP_get_name(comp) : "NONE"); 1501296465Sdelphij BIO_printf(bio, "Expansion: %s\n", 1502296465Sdelphij expansion ? SSL_COMP_get_name(expansion) : "NONE"); 1503160814Ssimon#endif 1504296465Sdelphij SSL_SESSION_print(bio, SSL_get_session(s)); 1505296465Sdelphij BIO_printf(bio, "---\n"); 1506296465Sdelphij if (peer != NULL) 1507296465Sdelphij X509_free(peer); 1508296465Sdelphij /* flush, or debugging output gets mixed with http response */ 1509296465Sdelphij (void)BIO_flush(bio); 1510296465Sdelphij} 151155714Skris 1512194206Ssimon#ifndef OPENSSL_NO_TLSEXT 1513194206Ssimon 1514194206Ssimonstatic int ocsp_resp_cb(SSL *s, void *arg) 1515296465Sdelphij{ 1516296465Sdelphij const unsigned char *p; 1517296465Sdelphij int len; 1518296465Sdelphij OCSP_RESPONSE *rsp; 1519296465Sdelphij len = SSL_get_tlsext_status_ocsp_resp(s, &p); 1520296465Sdelphij BIO_puts(arg, "OCSP response: "); 1521296465Sdelphij if (!p) { 1522296465Sdelphij BIO_puts(arg, "no response sent\n"); 1523296465Sdelphij return 1; 1524296465Sdelphij } 1525296465Sdelphij rsp = d2i_OCSP_RESPONSE(NULL, &p, len); 1526296465Sdelphij if (!rsp) { 1527296465Sdelphij BIO_puts(arg, "response parse error\n"); 1528296465Sdelphij BIO_dump_indent(arg, (char *)p, len, 4); 1529296465Sdelphij return 0; 1530296465Sdelphij } 1531296465Sdelphij BIO_puts(arg, "\n======================================\n"); 1532296465Sdelphij OCSP_RESPONSE_print(arg, rsp, 0); 1533296465Sdelphij BIO_puts(arg, "======================================\n"); 1534296465Sdelphij OCSP_RESPONSE_free(rsp); 1535296465Sdelphij return 1; 1536296465Sdelphij} 1537296465Sdelphij#endif /* ndef OPENSSL_NO_TLSEXT */ 1538