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