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