155714Skris/* ssl/ssltest.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.
8296341Sdelphij *
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).
15296341Sdelphij *
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.
22296341Sdelphij *
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 :-).
37296341Sdelphij * 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)"
40296341Sdelphij *
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.
52296341Sdelphij *
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-2000 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
66296341Sdelphij *    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 */
111160814Ssimon/* ====================================================================
112160814Ssimon * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
113296341Sdelphij * ECC cipher suite support in OpenSSL originally developed by
114160814Ssimon * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
115160814Ssimon */
116238405Sjkim/* ====================================================================
117238405Sjkim * Copyright 2005 Nokia. All rights reserved.
118238405Sjkim *
119238405Sjkim * The portions of the attached software ("Contribution") is developed by
120238405Sjkim * Nokia Corporation and is licensed pursuant to the OpenSSL open source
121238405Sjkim * license.
122238405Sjkim *
123238405Sjkim * The Contribution, originally written by Mika Kousa and Pasi Eronen of
124238405Sjkim * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
125238405Sjkim * support (see RFC 4279) to OpenSSL.
126238405Sjkim *
127238405Sjkim * No patent licenses or other rights except those expressly stated in
128238405Sjkim * the OpenSSL open source license shall be deemed granted or received
129238405Sjkim * expressly, by implication, estoppel, or otherwise.
130238405Sjkim *
131238405Sjkim * No assurances are provided by Nokia that the Contribution does not
132238405Sjkim * infringe the patent or other intellectual property rights of any third
133238405Sjkim * party or that the license provides you with all the necessary rights
134238405Sjkim * to make use of the Contribution.
135238405Sjkim *
136238405Sjkim * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
137238405Sjkim * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
138238405Sjkim * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
139238405Sjkim * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
140238405Sjkim * OTHERWISE.
141238405Sjkim */
14255714Skris
143296341Sdelphij/* Or gethostname won't be declared properly on Linux and GNU platforms. */
144296341Sdelphij#define _BSD_SOURCE 1
145109998Smarkm
14659191Skris#include <assert.h>
14759191Skris#include <errno.h>
14859191Skris#include <limits.h>
14955714Skris#include <stdio.h>
15055714Skris#include <stdlib.h>
15155714Skris#include <string.h>
15259191Skris#include <time.h>
15355714Skris
154109998Smarkm#define USE_SOCKETS
155109998Smarkm#include "e_os.h"
15655714Skris
157238405Sjkim#ifdef OPENSSL_SYS_VMS
158296341Sdelphij/*
159296341Sdelphij * Or isascii won't be declared properly on VMS (at least with DECompHP C).
160296341Sdelphij */
161296341Sdelphij# define _XOPEN_SOURCE 500
162238405Sjkim#endif
163238405Sjkim
164160814Ssimon#include <ctype.h>
165160814Ssimon
16655714Skris#include <openssl/bio.h>
16755714Skris#include <openssl/crypto.h>
16859191Skris#include <openssl/evp.h>
16955714Skris#include <openssl/x509.h>
170160814Ssimon#include <openssl/x509v3.h>
17155714Skris#include <openssl/ssl.h>
172111147Snectar#ifndef OPENSSL_NO_ENGINE
173296341Sdelphij# include <openssl/engine.h>
174111147Snectar#endif
17555714Skris#include <openssl/err.h>
17659191Skris#include <openssl/rand.h>
177160814Ssimon#ifndef OPENSSL_NO_RSA
178296341Sdelphij# include <openssl/rsa.h>
179160814Ssimon#endif
180160814Ssimon#ifndef OPENSSL_NO_DSA
181296341Sdelphij# include <openssl/dsa.h>
182160814Ssimon#endif
183160814Ssimon#ifndef OPENSSL_NO_DH
184296341Sdelphij# include <openssl/dh.h>
185160814Ssimon#endif
186238405Sjkim#ifndef OPENSSL_NO_SRP
187296341Sdelphij# include <openssl/srp.h>
188238405Sjkim#endif
189160814Ssimon#include <openssl/bn.h>
190109998Smarkm
191296341Sdelphij/*
192296341Sdelphij * Or gethostname won't be declared properly
193296341Sdelphij * on Compaq platforms (at least with DEC C).
194296341Sdelphij * Do not try to put it earlier, or IPv6 includes
195296341Sdelphij * get screwed...
196296341Sdelphij */
197296341Sdelphij#define _XOPEN_SOURCE_EXTENDED  1
198109998Smarkm
199109998Smarkm#ifdef OPENSSL_SYS_WINDOWS
200296341Sdelphij# include <winsock.h>
201109998Smarkm#else
202296341Sdelphij# include OPENSSL_UNISTD
20355714Skris#endif
20455714Skris
205109998Smarkm#ifdef OPENSSL_SYS_VMS
206296341Sdelphij# define TEST_SERVER_CERT "SYS$DISK:[-.APPS]SERVER.PEM"
207296341Sdelphij# define TEST_CLIENT_CERT "SYS$DISK:[-.APPS]CLIENT.PEM"
208109998Smarkm#elif defined(OPENSSL_SYS_WINCE)
209296341Sdelphij# define TEST_SERVER_CERT "\\OpenSSL\\server.pem"
210296341Sdelphij# define TEST_CLIENT_CERT "\\OpenSSL\\client.pem"
211160814Ssimon#elif defined(OPENSSL_SYS_NETWARE)
212296341Sdelphij# define TEST_SERVER_CERT "\\openssl\\apps\\server.pem"
213296341Sdelphij# define TEST_CLIENT_CERT "\\openssl\\apps\\client.pem"
21455714Skris#else
215296341Sdelphij# define TEST_SERVER_CERT "../apps/server.pem"
216296341Sdelphij# define TEST_CLIENT_CERT "../apps/client.pem"
21755714Skris#endif
21855714Skris
219296341Sdelphij/*
220296341Sdelphij * There is really no standard for this, so let's assign some tentative
221296341Sdelphij * numbers.  In any case, these numbers are only for this test
222296341Sdelphij */
223296341Sdelphij#define COMP_RLE        255
224296341Sdelphij#define COMP_ZLIB       1
225109998Smarkm
22659191Skrisstatic int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
227109998Smarkm#ifndef OPENSSL_NO_RSA
228296341Sdelphijstatic RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength);
22968651Skrisstatic void free_tmp_rsa(void);
23055714Skris#endif
231109998Smarkmstatic int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg);
232160814Ssimon#define APP_CALLBACK_STRING "Test Callback Argument"
233296341Sdelphijstruct app_verify_arg {
234296341Sdelphij    char *string;
235296341Sdelphij    int app_verify;
236296341Sdelphij    int allow_proxy_certs;
237296341Sdelphij    char *proxy_auth;
238296341Sdelphij    char *proxy_cond;
239296341Sdelphij};
240109998Smarkm
241109998Smarkm#ifndef OPENSSL_NO_DH
24255714Skrisstatic DH *get_dh512(void);
24359191Skrisstatic DH *get_dh1024(void);
24459191Skrisstatic DH *get_dh1024dsa(void);
24555714Skris#endif
24655714Skris
247296341Sdelphijstatic char *psk_key = NULL;    /* by default PSK is not used */
248238405Sjkim#ifndef OPENSSL_NO_PSK
249296341Sdelphijstatic unsigned int psk_client_callback(SSL *ssl, const char *hint,
250296341Sdelphij                                        char *identity,
251296341Sdelphij                                        unsigned int max_identity_len,
252296341Sdelphij                                        unsigned char *psk,
253296341Sdelphij                                        unsigned int max_psk_len);
254296341Sdelphijstatic unsigned int psk_server_callback(SSL *ssl, const char *identity,
255296341Sdelphij                                        unsigned char *psk,
256296341Sdelphij                                        unsigned int max_psk_len);
257238405Sjkim#endif
258238405Sjkim
259238405Sjkim#ifndef OPENSSL_NO_SRP
260238405Sjkim/* SRP client */
261238405Sjkim/* This is a context that we pass to all callbacks */
262296341Sdelphijtypedef struct srp_client_arg_st {
263296341Sdelphij    char *srppassin;
264296341Sdelphij    char *srplogin;
265296341Sdelphij} SRP_CLIENT_ARG;
266238405Sjkim
267296341Sdelphij# define PWD_STRLEN 1024
268238405Sjkim
269296341Sdelphijstatic char *MS_CALLBACK ssl_give_srp_client_pwd_cb(SSL *s, void *arg)
270296341Sdelphij{
271296341Sdelphij    SRP_CLIENT_ARG *srp_client_arg = (SRP_CLIENT_ARG *)arg;
272296341Sdelphij    return BUF_strdup((char *)srp_client_arg->srppassin);
273296341Sdelphij}
274238405Sjkim
275238405Sjkim/* SRP server */
276238405Sjkim/* This is a context that we pass to SRP server callbacks */
277296341Sdelphijtypedef struct srp_server_arg_st {
278296341Sdelphij    char *expected_user;
279296341Sdelphij    char *pass;
280296341Sdelphij} SRP_SERVER_ARG;
281238405Sjkim
282238405Sjkimstatic int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
283296341Sdelphij{
284296341Sdelphij    SRP_SERVER_ARG *p = (SRP_SERVER_ARG *)arg;
285238405Sjkim
286296341Sdelphij    if (strcmp(p->expected_user, SSL_get_srp_username(s)) != 0) {
287296341Sdelphij        fprintf(stderr, "User %s doesn't exist\n", SSL_get_srp_username(s));
288296341Sdelphij        return SSL3_AL_FATAL;
289296341Sdelphij    }
290296341Sdelphij    if (SSL_set_srp_server_param_pw(s, p->expected_user, p->pass, "1024") < 0) {
291296341Sdelphij        *ad = SSL_AD_INTERNAL_ERROR;
292296341Sdelphij        return SSL3_AL_FATAL;
293296341Sdelphij    }
294296341Sdelphij    return SSL_ERROR_NONE;
295296341Sdelphij}
296238405Sjkim#endif
297238405Sjkim
298296341Sdelphijstatic BIO *bio_err = NULL;
299296341Sdelphijstatic BIO *bio_stdout = NULL;
30059191Skris
301296341Sdelphijstatic char *cipher = NULL;
302296341Sdelphijstatic int verbose = 0;
303296341Sdelphijstatic int debug = 0;
30455714Skris#if 0
30555714Skris/* Not used yet. */
306296341Sdelphij# ifdef FIONBIO
307296341Sdelphijstatic int s_nbio = 0;
308296341Sdelphij# endif
30955714Skris#endif
31055714Skris
311296341Sdelphijstatic const char rnd_seed[] =
312296341Sdelphij    "string to make the random number generator think it has entropy";
31355714Skris
314296341Sdelphijint doit_biopair(SSL *s_ssl, SSL *c_ssl, long bytes, clock_t *s_time,
315296341Sdelphij                 clock_t *c_time);
316296341Sdelphijint doit(SSL *s_ssl, SSL *c_ssl, long bytes);
317160814Ssimonstatic int do_test_cipherlist(void);
31855714Skrisstatic void sv_usage(void)
319296341Sdelphij{
320296341Sdelphij    fprintf(stderr, "usage: ssltest [args ...]\n");
321296341Sdelphij    fprintf(stderr, "\n");
322194206Ssimon#ifdef OPENSSL_FIPS
323296341Sdelphij    fprintf(stderr, "-F             - run test in FIPS mode\n");
324194206Ssimon#endif
325296341Sdelphij    fprintf(stderr, " -server_auth  - check server certificate\n");
326296341Sdelphij    fprintf(stderr, " -client_auth  - do client authentication\n");
327296341Sdelphij    fprintf(stderr, " -proxy        - allow proxy certificates\n");
328296341Sdelphij    fprintf(stderr, " -proxy_auth <val> - set proxy policy rights\n");
329296341Sdelphij    fprintf(stderr,
330296341Sdelphij            " -proxy_cond <val> - experssion to test proxy policy rights\n");
331296341Sdelphij    fprintf(stderr, " -v            - more output\n");
332296341Sdelphij    fprintf(stderr, " -d            - debug output\n");
333296341Sdelphij    fprintf(stderr, " -reuse        - use session-id reuse\n");
334296341Sdelphij    fprintf(stderr, " -num <val>    - number of connections to perform\n");
335296341Sdelphij    fprintf(stderr,
336296341Sdelphij            " -bytes <val>  - number of bytes to swap between client/server\n");
337109998Smarkm#ifndef OPENSSL_NO_DH
338296341Sdelphij    fprintf(stderr,
339296341Sdelphij            " -dhe512       - use 512 bit key for DHE (to test failure)\n");
340296341Sdelphij    fprintf(stderr,
341296341Sdelphij            " -dhe1024      - use 1024 bit key (safe prime) for DHE (default, no-op)\n");
342296341Sdelphij    fprintf(stderr,
343296341Sdelphij            " -dhe1024dsa   - use 1024 bit key (with 160-bit subprime) for DHE\n");
344296341Sdelphij    fprintf(stderr, " -no_dhe       - disable DHE\n");
34555714Skris#endif
346160814Ssimon#ifndef OPENSSL_NO_ECDH
347296341Sdelphij    fprintf(stderr, " -no_ecdhe     - disable ECDHE\n");
348160814Ssimon#endif
349238405Sjkim#ifndef OPENSSL_NO_PSK
350296341Sdelphij    fprintf(stderr, " -psk arg      - PSK in hex (without 0x)\n");
351238405Sjkim#endif
352238405Sjkim#ifndef OPENSSL_NO_SRP
353296341Sdelphij    fprintf(stderr, " -srpuser user  - SRP username to use\n");
354296341Sdelphij    fprintf(stderr, " -srppass arg   - password for 'user'\n");
355238405Sjkim#endif
356109998Smarkm#ifndef OPENSSL_NO_SSL2
357296341Sdelphij    fprintf(stderr, " -ssl2         - use SSLv2\n");
35855714Skris#endif
359279264Sdelphij#ifndef OPENSSL_NO_SSL3_METHOD
360296341Sdelphij    fprintf(stderr, " -ssl3         - use SSLv3\n");
36155714Skris#endif
362109998Smarkm#ifndef OPENSSL_NO_TLS1
363296341Sdelphij    fprintf(stderr, " -tls1         - use TLSv1\n");
36455714Skris#endif
365296341Sdelphij    fprintf(stderr, " -CApath arg   - PEM format directory of CA's\n");
366296341Sdelphij    fprintf(stderr, " -CAfile arg   - PEM format file of CA's\n");
367296341Sdelphij    fprintf(stderr, " -cert arg     - Server certificate file\n");
368296341Sdelphij    fprintf(stderr,
369296341Sdelphij            " -key arg      - Server key file (default: same as -cert)\n");
370296341Sdelphij    fprintf(stderr, " -c_cert arg   - Client certificate file\n");
371296341Sdelphij    fprintf(stderr,
372296341Sdelphij            " -c_key arg    - Client key file (default: same as -c_cert)\n");
373296341Sdelphij    fprintf(stderr, " -cipher arg   - The cipher list\n");
374296341Sdelphij    fprintf(stderr, " -bio_pair     - Use BIO pairs\n");
375296341Sdelphij    fprintf(stderr, " -f            - Test even cases that can't work\n");
376296341Sdelphij    fprintf(stderr,
377296341Sdelphij            " -time         - measure processor time used by client and server\n");
378296341Sdelphij    fprintf(stderr, " -zlib         - use zlib compression\n");
379296341Sdelphij    fprintf(stderr, " -rle          - use rle compression\n");
380160814Ssimon#ifndef OPENSSL_NO_ECDH
381296341Sdelphij    fprintf(stderr,
382296341Sdelphij            " -named_curve arg  - Elliptic curve name to use for ephemeral ECDH keys.\n"
383296341Sdelphij            "                 Use \"openssl ecparam -list_curves\" for all names\n"
384296341Sdelphij            "                 (default is sect163r2).\n");
385160814Ssimon#endif
386296341Sdelphij    fprintf(stderr,
387296341Sdelphij            " -test_cipherlist - Verifies the order of the ssl cipher lists.\n"
388296341Sdelphij            "                    When this option is requested, the cipherlist\n"
389296341Sdelphij            "                    tests are run instead of handshake tests.\n");
390296341Sdelphij}
39155714Skris
39259191Skrisstatic void print_details(SSL *c_ssl, const char *prefix)
393296341Sdelphij{
394296341Sdelphij    const SSL_CIPHER *ciph;
395296341Sdelphij    X509 *cert;
396296341Sdelphij
397296341Sdelphij    ciph = SSL_get_current_cipher(c_ssl);
398296341Sdelphij    BIO_printf(bio_stdout, "%s%s, cipher %s %s",
399296341Sdelphij               prefix,
400296341Sdelphij               SSL_get_version(c_ssl),
401296341Sdelphij               SSL_CIPHER_get_version(ciph), SSL_CIPHER_get_name(ciph));
402296341Sdelphij    cert = SSL_get_peer_certificate(c_ssl);
403296341Sdelphij    if (cert != NULL) {
404296341Sdelphij        EVP_PKEY *pkey = X509_get_pubkey(cert);
405296341Sdelphij        if (pkey != NULL) {
406296341Sdelphij            if (0) ;
407109998Smarkm#ifndef OPENSSL_NO_RSA
408296341Sdelphij            else if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL
409296341Sdelphij                     && pkey->pkey.rsa->n != NULL) {
410296341Sdelphij                BIO_printf(bio_stdout, ", %d bit RSA",
411296341Sdelphij                           BN_num_bits(pkey->pkey.rsa->n));
412296341Sdelphij            }
41359191Skris#endif
414109998Smarkm#ifndef OPENSSL_NO_DSA
415296341Sdelphij            else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL
416296341Sdelphij                     && pkey->pkey.dsa->p != NULL) {
417296341Sdelphij                BIO_printf(bio_stdout, ", %d bit DSA",
418296341Sdelphij                           BN_num_bits(pkey->pkey.dsa->p));
419296341Sdelphij            }
42059191Skris#endif
421296341Sdelphij            EVP_PKEY_free(pkey);
422296341Sdelphij        }
423296341Sdelphij        X509_free(cert);
424296341Sdelphij    }
425296341Sdelphij    /*
426296341Sdelphij     * The SSL API does not allow us to look at temporary RSA/DH keys,
427296341Sdelphij     * otherwise we should print their lengths too
428296341Sdelphij     */
429296341Sdelphij    BIO_printf(bio_stdout, "\n");
430296341Sdelphij}
43159191Skris
432109998Smarkmstatic void lock_dbg_cb(int mode, int type, const char *file, int line)
433296341Sdelphij{
434296341Sdelphij    static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
435296341Sdelphij    const char *errstr = NULL;
436296341Sdelphij    int rw;
437109998Smarkm
438296341Sdelphij    rw = mode & (CRYPTO_READ | CRYPTO_WRITE);
439296341Sdelphij    if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE))) {
440296341Sdelphij        errstr = "invalid mode";
441296341Sdelphij        goto err;
442296341Sdelphij    }
443109998Smarkm
444296341Sdelphij    if (type < 0 || type >= CRYPTO_NUM_LOCKS) {
445296341Sdelphij        errstr = "type out of bounds";
446296341Sdelphij        goto err;
447296341Sdelphij    }
448109998Smarkm
449296341Sdelphij    if (mode & CRYPTO_LOCK) {
450296341Sdelphij        if (modes[type]) {
451296341Sdelphij            errstr = "already locked";
452296341Sdelphij            /*
453296341Sdelphij             * must not happen in a single-threaded program (would deadlock)
454296341Sdelphij             */
455296341Sdelphij            goto err;
456296341Sdelphij        }
457109998Smarkm
458296341Sdelphij        modes[type] = rw;
459296341Sdelphij    } else if (mode & CRYPTO_UNLOCK) {
460296341Sdelphij        if (!modes[type]) {
461296341Sdelphij            errstr = "not locked";
462296341Sdelphij            goto err;
463296341Sdelphij        }
464109998Smarkm
465296341Sdelphij        if (modes[type] != rw) {
466296341Sdelphij            errstr = (rw == CRYPTO_READ) ?
467296341Sdelphij                "CRYPTO_r_unlock on write lock" :
468296341Sdelphij                "CRYPTO_w_unlock on read lock";
469296341Sdelphij        }
470296341Sdelphij
471296341Sdelphij        modes[type] = 0;
472296341Sdelphij    } else {
473296341Sdelphij        errstr = "invalid mode";
474296341Sdelphij        goto err;
475296341Sdelphij    }
476296341Sdelphij
477109998Smarkm err:
478296341Sdelphij    if (errstr) {
479296341Sdelphij        /* we cannot use bio_err here */
480296341Sdelphij        fprintf(stderr,
481296341Sdelphij                "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
482296341Sdelphij                errstr, mode, type, file, line);
483296341Sdelphij    }
484296341Sdelphij}
485109998Smarkm
486238405Sjkim#ifdef TLSEXT_TYPE_opaque_prf_input
487296341Sdelphijstruct cb_info_st {
488296341Sdelphij    void *input;
489296341Sdelphij    size_t len;
490296341Sdelphij    int ret;
491296341Sdelphij};
492238405Sjkimstruct cb_info_st co1 = { "C", 1, 1 }; /* try to negotiate oqaque PRF input */
493238405Sjkimstruct cb_info_st co2 = { "C", 1, 2 }; /* insist on oqaque PRF input */
494238405Sjkimstruct cb_info_st so1 = { "S", 1, 1 }; /* try to negotiate oqaque PRF input */
495238405Sjkimstruct cb_info_st so2 = { "S", 1, 2 }; /* insist on oqaque PRF input */
496160814Ssimon
497238405Sjkimint opaque_prf_input_cb(SSL *ssl, void *peerinput, size_t len, void *arg_)
498296341Sdelphij{
499296341Sdelphij    struct cb_info_st *arg = arg_;
500238405Sjkim
501296341Sdelphij    if (arg == NULL)
502296341Sdelphij        return 1;
503296341Sdelphij
504296341Sdelphij    if (!SSL_set_tlsext_opaque_prf_input(ssl, arg->input, arg->len))
505296341Sdelphij        return 0;
506296341Sdelphij    return arg->ret;
507296341Sdelphij}
508238405Sjkim#endif
509238405Sjkim
51055714Skrisint main(int argc, char *argv[])
511296341Sdelphij{
512296341Sdelphij    char *CApath = NULL, *CAfile = NULL;
513296341Sdelphij    int badop = 0;
514296341Sdelphij    int bio_pair = 0;
515296341Sdelphij    int force = 0;
516296341Sdelphij    int tls1 = 0, ssl2 = 0, ssl3 = 0, ret = 1;
517296341Sdelphij    int client_auth = 0;
518296341Sdelphij    int server_auth = 0, i;
519296341Sdelphij    struct app_verify_arg app_verify_arg =
520296341Sdelphij        { APP_CALLBACK_STRING, 0, 0, NULL, NULL };
521296341Sdelphij    char *server_cert = TEST_SERVER_CERT;
522296341Sdelphij    char *server_key = NULL;
523296341Sdelphij    char *client_cert = TEST_CLIENT_CERT;
524296341Sdelphij    char *client_key = NULL;
525160814Ssimon#ifndef OPENSSL_NO_ECDH
526296341Sdelphij    char *named_curve = NULL;
527160814Ssimon#endif
528296341Sdelphij    SSL_CTX *s_ctx = NULL;
529296341Sdelphij    SSL_CTX *c_ctx = NULL;
530296341Sdelphij    const SSL_METHOD *meth = NULL;
531296341Sdelphij    SSL *c_ssl, *s_ssl;
532296341Sdelphij    int number = 1, reuse = 0;
533296341Sdelphij    long bytes = 256L;
534109998Smarkm#ifndef OPENSSL_NO_DH
535296341Sdelphij    DH *dh;
536296341Sdelphij    int dhe512 = 0, dhe1024dsa = 0;
53755714Skris#endif
538160814Ssimon#ifndef OPENSSL_NO_ECDH
539296341Sdelphij    EC_KEY *ecdh = NULL;
540160814Ssimon#endif
541238405Sjkim#ifndef OPENSSL_NO_SRP
542296341Sdelphij    /* client */
543296341Sdelphij    SRP_CLIENT_ARG srp_client_arg = { NULL, NULL };
544296341Sdelphij    /* server */
545296341Sdelphij    SRP_SERVER_ARG srp_server_arg = { NULL, NULL };
546238405Sjkim#endif
547296341Sdelphij    int no_dhe = 0;
548296341Sdelphij    int no_ecdhe = 0;
549296341Sdelphij    int no_psk = 0;
550296341Sdelphij    int print_time = 0;
551296341Sdelphij    clock_t s_time = 0, c_time = 0;
552296341Sdelphij    int comp = 0;
553160814Ssimon#ifndef OPENSSL_NO_COMP
554296341Sdelphij    COMP_METHOD *cm = NULL;
555296341Sdelphij    STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
556142425Snectar#endif
557296341Sdelphij    int test_cipherlist = 0;
558194206Ssimon#ifdef OPENSSL_FIPS
559296341Sdelphij    int fips_mode = 0;
560194206Ssimon#endif
561296341Sdelphij    int no_protocol = 0;
56255714Skris
563296341Sdelphij    verbose = 0;
564296341Sdelphij    debug = 0;
565296341Sdelphij    cipher = 0;
566109998Smarkm
567296341Sdelphij    bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
568109998Smarkm
569296341Sdelphij    CRYPTO_set_locking_callback(lock_dbg_cb);
570109998Smarkm
571296341Sdelphij    /* enable memory leak checking unless explicitly disabled */
572296341Sdelphij    if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL)
573296341Sdelphij          && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off")))) {
574296341Sdelphij        CRYPTO_malloc_debug_init();
575296341Sdelphij        CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
576296341Sdelphij    } else {
577296341Sdelphij        /* OPENSSL_DEBUG_MEMORY=off */
578296341Sdelphij        CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
579296341Sdelphij    }
580296341Sdelphij    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
58159191Skris
582296341Sdelphij    RAND_seed(rnd_seed, sizeof rnd_seed);
58359191Skris
584296341Sdelphij    bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT);
58555714Skris
586296341Sdelphij    argc--;
587296341Sdelphij    argv++;
58855714Skris
589296341Sdelphij    while (argc >= 1) {
590296341Sdelphij        if (!strcmp(*argv, "-F")) {
591194206Ssimon#ifdef OPENSSL_FIPS
592296341Sdelphij            fips_mode = 1;
593194206Ssimon#else
594296341Sdelphij            fprintf(stderr,
595296341Sdelphij                    "not compiled with FIPS support, so exitting without running.\n");
596296341Sdelphij            EXIT(0);
597194206Ssimon#endif
598296341Sdelphij        } else if (strcmp(*argv, "-server_auth") == 0)
599296341Sdelphij            server_auth = 1;
600296341Sdelphij        else if (strcmp(*argv, "-client_auth") == 0)
601296341Sdelphij            client_auth = 1;
602296341Sdelphij        else if (strcmp(*argv, "-proxy_auth") == 0) {
603296341Sdelphij            if (--argc < 1)
604296341Sdelphij                goto bad;
605296341Sdelphij            app_verify_arg.proxy_auth = *(++argv);
606296341Sdelphij        } else if (strcmp(*argv, "-proxy_cond") == 0) {
607296341Sdelphij            if (--argc < 1)
608296341Sdelphij                goto bad;
609296341Sdelphij            app_verify_arg.proxy_cond = *(++argv);
610296341Sdelphij        } else if (strcmp(*argv, "-v") == 0)
611296341Sdelphij            verbose = 1;
612296341Sdelphij        else if (strcmp(*argv, "-d") == 0)
613296341Sdelphij            debug = 1;
614296341Sdelphij        else if (strcmp(*argv, "-reuse") == 0)
615296341Sdelphij            reuse = 1;
616296341Sdelphij        else if (strcmp(*argv, "-dhe512") == 0) {
617109998Smarkm#ifndef OPENSSL_NO_DH
618296341Sdelphij            dhe512 = 1;
619109998Smarkm#else
620296341Sdelphij            fprintf(stderr,
621296341Sdelphij                    "ignoring -dhe512, since I'm compiled without DH\n");
622109998Smarkm#endif
623296341Sdelphij        } else if (strcmp(*argv, "-dhe1024dsa") == 0) {
624109998Smarkm#ifndef OPENSSL_NO_DH
625296341Sdelphij            dhe1024dsa = 1;
626109998Smarkm#else
627296341Sdelphij            fprintf(stderr,
628296341Sdelphij                    "ignoring -dhe1024dsa, since I'm compiled without DH\n");
62959191Skris#endif
630296341Sdelphij        } else if (strcmp(*argv, "-no_dhe") == 0)
631296341Sdelphij            no_dhe = 1;
632296341Sdelphij        else if (strcmp(*argv, "-no_ecdhe") == 0)
633296341Sdelphij            no_ecdhe = 1;
634296341Sdelphij        else if (strcmp(*argv, "-psk") == 0) {
635296341Sdelphij            if (--argc < 1)
636296341Sdelphij                goto bad;
637296341Sdelphij            psk_key = *(++argv);
638238405Sjkim#ifndef OPENSSL_NO_PSK
639296341Sdelphij            if (strspn(psk_key, "abcdefABCDEF1234567890") != strlen(psk_key)) {
640296341Sdelphij                BIO_printf(bio_err, "Not a hex number '%s'\n", *argv);
641296341Sdelphij                goto bad;
642296341Sdelphij            }
643238405Sjkim#else
644296341Sdelphij            no_psk = 1;
645238405Sjkim#endif
646296341Sdelphij        }
647238405Sjkim#ifndef OPENSSL_NO_SRP
648296341Sdelphij        else if (strcmp(*argv, "-srpuser") == 0) {
649296341Sdelphij            if (--argc < 1)
650296341Sdelphij                goto bad;
651296341Sdelphij            srp_server_arg.expected_user = srp_client_arg.srplogin =
652296341Sdelphij                *(++argv);
653296341Sdelphij            tls1 = 1;
654296341Sdelphij        } else if (strcmp(*argv, "-srppass") == 0) {
655296341Sdelphij            if (--argc < 1)
656296341Sdelphij                goto bad;
657296341Sdelphij            srp_server_arg.pass = srp_client_arg.srppassin = *(++argv);
658296341Sdelphij            tls1 = 1;
659296341Sdelphij        }
660238405Sjkim#endif
661296341Sdelphij        else if (strcmp(*argv, "-ssl2") == 0) {
662279264Sdelphij#ifdef OPENSSL_NO_SSL2
663296341Sdelphij            no_protocol = 1;
664279264Sdelphij#endif
665296341Sdelphij            ssl2 = 1;
666296341Sdelphij        } else if (strcmp(*argv, "-tls1") == 0) {
667279264Sdelphij#ifdef OPENSSL_NO_TLS1
668296341Sdelphij            no_protocol = 1;
669279264Sdelphij#endif
670296341Sdelphij            tls1 = 1;
671296341Sdelphij        } else if (strcmp(*argv, "-ssl3") == 0) {
672279264Sdelphij#ifdef OPENSSL_NO_SSL3_METHOD
673296341Sdelphij            no_protocol = 1;
674279264Sdelphij#endif
675296341Sdelphij            ssl3 = 1;
676296341Sdelphij        } else if (strncmp(*argv, "-num", 4) == 0) {
677296341Sdelphij            if (--argc < 1)
678296341Sdelphij                goto bad;
679296341Sdelphij            number = atoi(*(++argv));
680296341Sdelphij            if (number == 0)
681296341Sdelphij                number = 1;
682296341Sdelphij        } else if (strcmp(*argv, "-bytes") == 0) {
683296341Sdelphij            if (--argc < 1)
684296341Sdelphij                goto bad;
685296341Sdelphij            bytes = atol(*(++argv));
686296341Sdelphij            if (bytes == 0L)
687296341Sdelphij                bytes = 1L;
688296341Sdelphij            i = strlen(argv[0]);
689296341Sdelphij            if (argv[0][i - 1] == 'k')
690296341Sdelphij                bytes *= 1024L;
691296341Sdelphij            if (argv[0][i - 1] == 'm')
692296341Sdelphij                bytes *= 1024L * 1024L;
693296341Sdelphij        } else if (strcmp(*argv, "-cert") == 0) {
694296341Sdelphij            if (--argc < 1)
695296341Sdelphij                goto bad;
696296341Sdelphij            server_cert = *(++argv);
697296341Sdelphij        } else if (strcmp(*argv, "-s_cert") == 0) {
698296341Sdelphij            if (--argc < 1)
699296341Sdelphij                goto bad;
700296341Sdelphij            server_cert = *(++argv);
701296341Sdelphij        } else if (strcmp(*argv, "-key") == 0) {
702296341Sdelphij            if (--argc < 1)
703296341Sdelphij                goto bad;
704296341Sdelphij            server_key = *(++argv);
705296341Sdelphij        } else if (strcmp(*argv, "-s_key") == 0) {
706296341Sdelphij            if (--argc < 1)
707296341Sdelphij                goto bad;
708296341Sdelphij            server_key = *(++argv);
709296341Sdelphij        } else if (strcmp(*argv, "-c_cert") == 0) {
710296341Sdelphij            if (--argc < 1)
711296341Sdelphij                goto bad;
712296341Sdelphij            client_cert = *(++argv);
713296341Sdelphij        } else if (strcmp(*argv, "-c_key") == 0) {
714296341Sdelphij            if (--argc < 1)
715296341Sdelphij                goto bad;
716296341Sdelphij            client_key = *(++argv);
717296341Sdelphij        } else if (strcmp(*argv, "-cipher") == 0) {
718296341Sdelphij            if (--argc < 1)
719296341Sdelphij                goto bad;
720296341Sdelphij            cipher = *(++argv);
721296341Sdelphij        } else if (strcmp(*argv, "-CApath") == 0) {
722296341Sdelphij            if (--argc < 1)
723296341Sdelphij                goto bad;
724296341Sdelphij            CApath = *(++argv);
725296341Sdelphij        } else if (strcmp(*argv, "-CAfile") == 0) {
726296341Sdelphij            if (--argc < 1)
727296341Sdelphij                goto bad;
728296341Sdelphij            CAfile = *(++argv);
729296341Sdelphij        } else if (strcmp(*argv, "-bio_pair") == 0) {
730296341Sdelphij            bio_pair = 1;
731296341Sdelphij        } else if (strcmp(*argv, "-f") == 0) {
732296341Sdelphij            force = 1;
733296341Sdelphij        } else if (strcmp(*argv, "-time") == 0) {
734296341Sdelphij            print_time = 1;
735296341Sdelphij        } else if (strcmp(*argv, "-zlib") == 0) {
736296341Sdelphij            comp = COMP_ZLIB;
737296341Sdelphij        } else if (strcmp(*argv, "-rle") == 0) {
738296341Sdelphij            comp = COMP_RLE;
739296341Sdelphij        } else if (strcmp(*argv, "-named_curve") == 0) {
740296341Sdelphij            if (--argc < 1)
741296341Sdelphij                goto bad;
742296341Sdelphij#ifndef OPENSSL_NO_ECDH
743296341Sdelphij            named_curve = *(++argv);
744160814Ssimon#else
745296341Sdelphij            fprintf(stderr,
746296341Sdelphij                    "ignoring -named_curve, since I'm compiled without ECDH\n");
747296341Sdelphij            ++argv;
748160814Ssimon#endif
749296341Sdelphij        } else if (strcmp(*argv, "-app_verify") == 0) {
750296341Sdelphij            app_verify_arg.app_verify = 1;
751296341Sdelphij        } else if (strcmp(*argv, "-proxy") == 0) {
752296341Sdelphij            app_verify_arg.allow_proxy_certs = 1;
753296341Sdelphij        } else if (strcmp(*argv, "-test_cipherlist") == 0) {
754296341Sdelphij            test_cipherlist = 1;
755296341Sdelphij        } else {
756296341Sdelphij            fprintf(stderr, "unknown option %s\n", *argv);
757296341Sdelphij            badop = 1;
758296341Sdelphij            break;
759296341Sdelphij        }
760296341Sdelphij        argc--;
761296341Sdelphij        argv++;
762296341Sdelphij    }
763296341Sdelphij    if (badop) {
764296341Sdelphij bad:
765296341Sdelphij        sv_usage();
766296341Sdelphij        goto end;
767296341Sdelphij    }
76855714Skris
769296341Sdelphij    /*
770296341Sdelphij     * test_cipherlist prevails over protocol switch: we test the cipherlist
771296341Sdelphij     * for all enabled protocols.
772296341Sdelphij     */
773296341Sdelphij    if (test_cipherlist == 1) {
774296341Sdelphij        /*
775296341Sdelphij         * ensure that the cipher list are correctly sorted and exit
776296341Sdelphij         */
777296341Sdelphij        fprintf(stdout, "Testing cipherlist order only. Ignoring all "
778296341Sdelphij                "other options.\n");
779296341Sdelphij        if (do_test_cipherlist() == 0)
780296341Sdelphij            EXIT(1);
781296341Sdelphij        ret = 0;
782296341Sdelphij        goto end;
783296341Sdelphij    }
784142425Snectar
785296341Sdelphij    if (ssl2 + ssl3 + tls1 > 1) {
786296341Sdelphij        fprintf(stderr, "At most one of -ssl2, -ssl3, or -tls1 should "
787296341Sdelphij                "be requested.\n");
788296341Sdelphij        EXIT(1);
789296341Sdelphij    }
790279264Sdelphij
791296341Sdelphij    /*
792296341Sdelphij     * Testing was requested for a compiled-out protocol (e.g. SSLv2).
793296341Sdelphij     * Ideally, we would error out, but the generic test wrapper can't know
794296341Sdelphij     * when to expect failure. So we do nothing and return success.
795296341Sdelphij     */
796296341Sdelphij    if (no_protocol) {
797296341Sdelphij        fprintf(stderr, "Testing was requested for a disabled protocol. "
798296341Sdelphij                "Skipping tests.\n");
799296341Sdelphij        ret = 0;
800296341Sdelphij        goto end;
801296341Sdelphij    }
802279264Sdelphij
803296341Sdelphij    if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force) {
804296341Sdelphij        fprintf(stderr, "This case cannot work.  Use -f to perform "
805296341Sdelphij                "the test anyway (and\n-d to see what happens), "
806296341Sdelphij                "or add one of -ssl2, -ssl3, -tls1, -reuse\n"
807296341Sdelphij                "to avoid protocol mismatch.\n");
808296341Sdelphij        EXIT(1);
809296341Sdelphij    }
810194206Ssimon#ifdef OPENSSL_FIPS
811296341Sdelphij    if (fips_mode) {
812296341Sdelphij        if (!FIPS_mode_set(1)) {
813296341Sdelphij            ERR_load_crypto_strings();
814296341Sdelphij            ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));
815296341Sdelphij            EXIT(1);
816296341Sdelphij        } else
817296341Sdelphij            fprintf(stderr, "*** IN FIPS MODE ***\n");
818296341Sdelphij    }
819194206Ssimon#endif
820194206Ssimon
821296341Sdelphij    if (print_time) {
822296341Sdelphij        if (!bio_pair) {
823296341Sdelphij            fprintf(stderr, "Using BIO pair (-bio_pair)\n");
824296341Sdelphij            bio_pair = 1;
825296341Sdelphij        }
826296341Sdelphij        if (number < 50 && !force)
827296341Sdelphij            fprintf(stderr,
828296341Sdelphij                    "Warning: For accurate timings, use more connections (e.g. -num 1000)\n");
829296341Sdelphij    }
83059191Skris
831296341Sdelphij/*      if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */
83255714Skris
833296341Sdelphij    SSL_library_init();
834296341Sdelphij    SSL_load_error_strings();
83555714Skris
836160814Ssimon#ifndef OPENSSL_NO_COMP
837296341Sdelphij    if (comp == COMP_ZLIB)
838296341Sdelphij        cm = COMP_zlib();
839296341Sdelphij    if (comp == COMP_RLE)
840296341Sdelphij        cm = COMP_rle();
841296341Sdelphij    if (cm != NULL) {
842296341Sdelphij        if (cm->type != NID_undef) {
843296341Sdelphij            if (SSL_COMP_add_compression_method(comp, cm) != 0) {
844296341Sdelphij                fprintf(stderr, "Failed to add compression method\n");
845296341Sdelphij                ERR_print_errors_fp(stderr);
846296341Sdelphij            }
847296341Sdelphij        } else {
848296341Sdelphij            fprintf(stderr,
849296341Sdelphij                    "Warning: %s compression not supported\n",
850296341Sdelphij                    (comp == COMP_RLE ? "rle" :
851296341Sdelphij                     (comp == COMP_ZLIB ? "zlib" : "unknown")));
852296341Sdelphij            ERR_print_errors_fp(stderr);
853296341Sdelphij        }
854296341Sdelphij    }
855296341Sdelphij    ssl_comp_methods = SSL_COMP_get_compression_methods();
856296341Sdelphij    fprintf(stderr, "Available compression methods:\n");
857296341Sdelphij    {
858296341Sdelphij        int j, n = sk_SSL_COMP_num(ssl_comp_methods);
859296341Sdelphij        if (n == 0)
860296341Sdelphij            fprintf(stderr, "  NONE\n");
861296341Sdelphij        else
862296341Sdelphij            for (j = 0; j < n; j++) {
863296341Sdelphij                SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j);
864296341Sdelphij                fprintf(stderr, "  %d: %s\n", c->id, c->name);
865296341Sdelphij            }
866296341Sdelphij    }
867160814Ssimon#endif
868109998Smarkm
869296341Sdelphij    /*
870296341Sdelphij     * At this point, ssl2/ssl3/tls1 is only set if the protocol is
871296341Sdelphij     * available. (Otherwise we exit early.) However the compiler doesn't
872296341Sdelphij     * know this, so we ifdef.
873296341Sdelphij     */
874279264Sdelphij#ifndef OPENSSL_NO_SSL2
875296341Sdelphij    if (ssl2)
876296341Sdelphij        meth = SSLv2_method();
877296341Sdelphij    else
878279264Sdelphij#endif
879279264Sdelphij#ifndef OPENSSL_NO_SSL3
880296341Sdelphij    if (ssl3)
881296341Sdelphij        meth = SSLv3_method();
882296341Sdelphij    else
883279264Sdelphij#endif
884279264Sdelphij#ifndef OPENSSL_NO_TLS1
885296341Sdelphij    if (tls1)
886296341Sdelphij        meth = TLSv1_method();
887296341Sdelphij    else
88855714Skris#endif
889296341Sdelphij        meth = SSLv23_method();
89055714Skris
891296341Sdelphij    c_ctx = SSL_CTX_new(meth);
892296341Sdelphij    s_ctx = SSL_CTX_new(meth);
893296341Sdelphij    if ((c_ctx == NULL) || (s_ctx == NULL)) {
894296341Sdelphij        ERR_print_errors(bio_err);
895296341Sdelphij        goto end;
896296341Sdelphij    }
89755714Skris
898296341Sdelphij    if (cipher != NULL) {
899296341Sdelphij        SSL_CTX_set_cipher_list(c_ctx, cipher);
900296341Sdelphij        SSL_CTX_set_cipher_list(s_ctx, cipher);
901296341Sdelphij    }
902109998Smarkm#ifndef OPENSSL_NO_DH
903296341Sdelphij    if (!no_dhe) {
904296341Sdelphij        if (dhe1024dsa) {
905296341Sdelphij            /*
906296341Sdelphij             * use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks
907296341Sdelphij             */
908296341Sdelphij            SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
909296341Sdelphij            dh = get_dh1024dsa();
910296341Sdelphij        } else if (dhe512)
911296341Sdelphij            dh = get_dh512();
912296341Sdelphij        else
913296341Sdelphij            dh = get_dh1024();
914296341Sdelphij        SSL_CTX_set_tmp_dh(s_ctx, dh);
915296341Sdelphij        DH_free(dh);
916296341Sdelphij    }
91759191Skris#else
918296341Sdelphij    (void)no_dhe;
91955714Skris#endif
92055714Skris
921160814Ssimon#ifndef OPENSSL_NO_ECDH
922296341Sdelphij    if (!no_ecdhe) {
923296341Sdelphij        int nid;
924160814Ssimon
925296341Sdelphij        if (named_curve != NULL) {
926296341Sdelphij            nid = OBJ_sn2nid(named_curve);
927296341Sdelphij            if (nid == 0) {
928296341Sdelphij                BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve);
929296341Sdelphij                goto end;
930296341Sdelphij            }
931296341Sdelphij        } else
932296341Sdelphij# ifdef OPENSSL_NO_EC2M
933296341Sdelphij            nid = NID_X9_62_prime256v1;
934296341Sdelphij# else
935296341Sdelphij            nid = NID_sect163r2;
936296341Sdelphij# endif
937160814Ssimon
938296341Sdelphij        ecdh = EC_KEY_new_by_curve_name(nid);
939296341Sdelphij        if (ecdh == NULL) {
940296341Sdelphij            BIO_printf(bio_err, "unable to create curve\n");
941296341Sdelphij            goto end;
942296341Sdelphij        }
943160814Ssimon
944296341Sdelphij        SSL_CTX_set_tmp_ecdh(s_ctx, ecdh);
945296341Sdelphij        SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE);
946296341Sdelphij        EC_KEY_free(ecdh);
947296341Sdelphij    }
948160814Ssimon#else
949296341Sdelphij    (void)no_ecdhe;
950160814Ssimon#endif
951160814Ssimon
952109998Smarkm#ifndef OPENSSL_NO_RSA
953296341Sdelphij    SSL_CTX_set_tmp_rsa_callback(s_ctx, tmp_rsa_cb);
95455714Skris#endif
95555714Skris
956238405Sjkim#ifdef TLSEXT_TYPE_opaque_prf_input
957296341Sdelphij    SSL_CTX_set_tlsext_opaque_prf_input_callback(c_ctx, opaque_prf_input_cb);
958296341Sdelphij    SSL_CTX_set_tlsext_opaque_prf_input_callback(s_ctx, opaque_prf_input_cb);
959296341Sdelphij    /* or &co2 or NULL */
960296341Sdelphij    SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(c_ctx, &co1);
961296341Sdelphij    /* or &so2 or NULL */
962296341Sdelphij    SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(s_ctx, &so1);
963238405Sjkim#endif
964238405Sjkim
965296341Sdelphij    if (!SSL_CTX_use_certificate_file(s_ctx, server_cert, SSL_FILETYPE_PEM)) {
966296341Sdelphij        ERR_print_errors(bio_err);
967296341Sdelphij    } else if (!SSL_CTX_use_PrivateKey_file(s_ctx,
968296341Sdelphij                                            (server_key ? server_key :
969296341Sdelphij                                             server_cert),
970296341Sdelphij                                            SSL_FILETYPE_PEM)) {
971296341Sdelphij        ERR_print_errors(bio_err);
972296341Sdelphij        goto end;
973296341Sdelphij    }
97455714Skris
975296341Sdelphij    if (client_auth) {
976296341Sdelphij        SSL_CTX_use_certificate_file(c_ctx, client_cert, SSL_FILETYPE_PEM);
977296341Sdelphij        SSL_CTX_use_PrivateKey_file(c_ctx,
978296341Sdelphij                                    (client_key ? client_key : client_cert),
979296341Sdelphij                                    SSL_FILETYPE_PEM);
980296341Sdelphij    }
98155714Skris
982296341Sdelphij    if ((!SSL_CTX_load_verify_locations(s_ctx, CAfile, CApath)) ||
983296341Sdelphij        (!SSL_CTX_set_default_verify_paths(s_ctx)) ||
984296341Sdelphij        (!SSL_CTX_load_verify_locations(c_ctx, CAfile, CApath)) ||
985296341Sdelphij        (!SSL_CTX_set_default_verify_paths(c_ctx))) {
986296341Sdelphij        /* fprintf(stderr,"SSL_load_verify_locations\n"); */
987296341Sdelphij        ERR_print_errors(bio_err);
988296341Sdelphij        /* goto end; */
989296341Sdelphij    }
99055714Skris
991296341Sdelphij    if (client_auth) {
992296341Sdelphij        BIO_printf(bio_err, "client authentication\n");
993296341Sdelphij        SSL_CTX_set_verify(s_ctx,
994296341Sdelphij                           SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
995296341Sdelphij                           verify_callback);
996296341Sdelphij        SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback,
997296341Sdelphij                                         &app_verify_arg);
998296341Sdelphij    }
999296341Sdelphij    if (server_auth) {
1000296341Sdelphij        BIO_printf(bio_err, "server authentication\n");
1001296341Sdelphij        SSL_CTX_set_verify(c_ctx, SSL_VERIFY_PEER, verify_callback);
1002296341Sdelphij        SSL_CTX_set_cert_verify_callback(c_ctx, app_verify_callback,
1003296341Sdelphij                                         &app_verify_arg);
1004296341Sdelphij    }
100555714Skris
1006296341Sdelphij    {
1007296341Sdelphij        int session_id_context = 0;
1008296341Sdelphij        SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context,
1009296341Sdelphij                                       sizeof session_id_context);
1010296341Sdelphij    }
1011296341Sdelphij
1012296341Sdelphij    /* Use PSK only if PSK key is given */
1013296341Sdelphij    if (psk_key != NULL) {
1014296341Sdelphij        /*
1015296341Sdelphij         * no_psk is used to avoid putting psk command to openssl tool
1016296341Sdelphij         */
1017296341Sdelphij        if (no_psk) {
1018296341Sdelphij            /*
1019296341Sdelphij             * if PSK is not compiled in and psk key is given, do nothing and
1020296341Sdelphij             * exit successfully
1021296341Sdelphij             */
1022296341Sdelphij            ret = 0;
1023296341Sdelphij            goto end;
1024296341Sdelphij        }
1025238405Sjkim#ifndef OPENSSL_NO_PSK
1026296341Sdelphij        SSL_CTX_set_psk_client_callback(c_ctx, psk_client_callback);
1027296341Sdelphij        SSL_CTX_set_psk_server_callback(s_ctx, psk_server_callback);
1028296341Sdelphij        if (debug)
1029296341Sdelphij            BIO_printf(bio_err, "setting PSK identity hint to s_ctx\n");
1030296341Sdelphij        if (!SSL_CTX_use_psk_identity_hint(s_ctx, "ctx server identity_hint")) {
1031296341Sdelphij            BIO_printf(bio_err, "error setting PSK identity hint to s_ctx\n");
1032296341Sdelphij            ERR_print_errors(bio_err);
1033296341Sdelphij            goto end;
1034296341Sdelphij        }
1035238405Sjkim#endif
1036296341Sdelphij    }
1037238405Sjkim#ifndef OPENSSL_NO_SRP
1038296341Sdelphij    if (srp_client_arg.srplogin) {
1039296341Sdelphij        if (!SSL_CTX_set_srp_username(c_ctx, srp_client_arg.srplogin)) {
1040296341Sdelphij            BIO_printf(bio_err, "Unable to set SRP username\n");
1041296341Sdelphij            goto end;
1042296341Sdelphij        }
1043296341Sdelphij        SSL_CTX_set_srp_cb_arg(c_ctx, &srp_client_arg);
1044296341Sdelphij        SSL_CTX_set_srp_client_pwd_callback(c_ctx,
1045296341Sdelphij                                            ssl_give_srp_client_pwd_cb);
1046296341Sdelphij        /*
1047296341Sdelphij         * SSL_CTX_set_srp_strength(c_ctx, srp_client_arg.strength);
1048296341Sdelphij         */
1049296341Sdelphij    }
1050238405Sjkim
1051296341Sdelphij    if (srp_server_arg.expected_user != NULL) {
1052296341Sdelphij        SSL_CTX_set_verify(s_ctx, SSL_VERIFY_NONE, verify_callback);
1053296341Sdelphij        SSL_CTX_set_srp_cb_arg(s_ctx, &srp_server_arg);
1054296341Sdelphij        SSL_CTX_set_srp_username_callback(s_ctx, ssl_srp_server_param_cb);
1055296341Sdelphij    }
1056238405Sjkim#endif
1057238405Sjkim
1058296341Sdelphij    c_ssl = SSL_new(c_ctx);
1059296341Sdelphij    s_ssl = SSL_new(s_ctx);
106055714Skris
1061109998Smarkm#ifndef OPENSSL_NO_KRB5
1062296341Sdelphij    if (c_ssl && c_ssl->kssl_ctx) {
1063296341Sdelphij        char localhost[MAXHOSTNAMELEN + 2];
1064109998Smarkm
1065296341Sdelphij        if (gethostname(localhost, sizeof localhost - 1) == 0) {
1066296341Sdelphij            localhost[sizeof localhost - 1] = '\0';
1067296341Sdelphij            if (strlen(localhost) == sizeof localhost - 1) {
1068296341Sdelphij                BIO_printf(bio_err, "localhost name too long\n");
1069296341Sdelphij                goto end;
1070296341Sdelphij            }
1071296341Sdelphij            kssl_ctx_setstring(c_ssl->kssl_ctx, KSSL_SERVER, localhost);
1072296341Sdelphij        }
1073296341Sdelphij    }
1074296341Sdelphij#endif                          /* OPENSSL_NO_KRB5 */
1075109998Smarkm
1076296341Sdelphij    for (i = 0; i < number; i++) {
1077296341Sdelphij        if (!reuse)
1078296341Sdelphij            SSL_set_session(c_ssl, NULL);
1079296341Sdelphij        if (bio_pair)
1080296341Sdelphij            ret = doit_biopair(s_ssl, c_ssl, bytes, &s_time, &c_time);
1081296341Sdelphij        else
1082296341Sdelphij            ret = doit(s_ssl, c_ssl, bytes);
1083296341Sdelphij    }
108455714Skris
1085296341Sdelphij    if (!verbose) {
1086296341Sdelphij        print_details(c_ssl, "");
1087296341Sdelphij    }
1088296341Sdelphij    if ((number > 1) || (bytes > 1L))
1089296341Sdelphij        BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n", number,
1090296341Sdelphij                   bytes);
1091296341Sdelphij    if (print_time) {
109259191Skris#ifdef CLOCKS_PER_SEC
1093296341Sdelphij        /*
1094296341Sdelphij         * "To determine the time in seconds, the value returned by the clock
1095296341Sdelphij         * function should be divided by the value of the macro
1096296341Sdelphij         * CLOCKS_PER_SEC." -- ISO/IEC 9899
1097296341Sdelphij         */
1098296341Sdelphij        BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n"
1099296341Sdelphij                   "Approximate total client time: %6.2f s\n",
1100296341Sdelphij                   (double)s_time / CLOCKS_PER_SEC,
1101296341Sdelphij                   (double)c_time / CLOCKS_PER_SEC);
110259191Skris#else
1103296341Sdelphij        /*
1104296341Sdelphij         * "`CLOCKS_PER_SEC' undeclared (first use this function)" -- cc on
1105296341Sdelphij         * NeXTstep/OpenStep
1106296341Sdelphij         */
1107296341Sdelphij        BIO_printf(bio_stdout,
1108296341Sdelphij                   "Approximate total server time: %6.2f units\n"
1109296341Sdelphij                   "Approximate total client time: %6.2f units\n",
1110296341Sdelphij                   (double)s_time, (double)c_time);
111159191Skris#endif
1112296341Sdelphij    }
111355714Skris
1114296341Sdelphij    SSL_free(s_ssl);
1115296341Sdelphij    SSL_free(c_ssl);
111655714Skris
1117296341Sdelphij end:
1118296341Sdelphij    if (s_ctx != NULL)
1119296341Sdelphij        SSL_CTX_free(s_ctx);
1120296341Sdelphij    if (c_ctx != NULL)
1121296341Sdelphij        SSL_CTX_free(c_ctx);
112255714Skris
1123296341Sdelphij    if (bio_stdout != NULL)
1124296341Sdelphij        BIO_free(bio_stdout);
112555714Skris
1126109998Smarkm#ifndef OPENSSL_NO_RSA
1127296341Sdelphij    free_tmp_rsa();
112868651Skris#endif
1129111147Snectar#ifndef OPENSSL_NO_ENGINE
1130296341Sdelphij    ENGINE_cleanup();
1131111147Snectar#endif
1132296341Sdelphij    CRYPTO_cleanup_all_ex_data();
1133296341Sdelphij    ERR_free_strings();
1134296341Sdelphij    ERR_remove_thread_state(NULL);
1135296341Sdelphij    EVP_cleanup();
1136296341Sdelphij    CRYPTO_mem_leaks(bio_err);
1137296341Sdelphij    if (bio_err != NULL)
1138296341Sdelphij        BIO_free(bio_err);
1139296341Sdelphij    EXIT(ret);
1140296341Sdelphij    return ret;
1141296341Sdelphij}
114255714Skris
114359191Skrisint doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
1144296341Sdelphij                 clock_t *s_time, clock_t *c_time)
1145296341Sdelphij{
1146296341Sdelphij    long cw_num = count, cr_num = count, sw_num = count, sr_num = count;
1147296341Sdelphij    BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL;
1148296341Sdelphij    BIO *server = NULL, *server_io = NULL, *client = NULL, *client_io = NULL;
1149296341Sdelphij    int ret = 1;
115055714Skris
1151296341Sdelphij    size_t bufsiz = 256;        /* small buffer for testing */
115255714Skris
1153296341Sdelphij    if (!BIO_new_bio_pair(&server, bufsiz, &server_io, bufsiz))
1154296341Sdelphij        goto err;
1155296341Sdelphij    if (!BIO_new_bio_pair(&client, bufsiz, &client_io, bufsiz))
1156296341Sdelphij        goto err;
115755714Skris
1158296341Sdelphij    s_ssl_bio = BIO_new(BIO_f_ssl());
1159296341Sdelphij    if (!s_ssl_bio)
1160296341Sdelphij        goto err;
116155714Skris
1162296341Sdelphij    c_ssl_bio = BIO_new(BIO_f_ssl());
1163296341Sdelphij    if (!c_ssl_bio)
1164296341Sdelphij        goto err;
116555714Skris
1166296341Sdelphij    SSL_set_connect_state(c_ssl);
1167296341Sdelphij    SSL_set_bio(c_ssl, client, client);
1168296341Sdelphij    (void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE);
116955714Skris
1170296341Sdelphij    SSL_set_accept_state(s_ssl);
1171296341Sdelphij    SSL_set_bio(s_ssl, server, server);
1172296341Sdelphij    (void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE);
117355714Skris
1174296341Sdelphij    do {
1175296341Sdelphij        /*-
1176296341Sdelphij         * c_ssl_bio:          SSL filter BIO
1177296341Sdelphij         *
1178296341Sdelphij         * client:             pseudo-I/O for SSL library
1179296341Sdelphij         *
1180296341Sdelphij         * client_io:          client's SSL communication; usually to be
1181296341Sdelphij         *                     relayed over some I/O facility, but in this
1182296341Sdelphij         *                     test program, we're the server, too:
1183296341Sdelphij         *
1184296341Sdelphij         * server_io:          server's SSL communication
1185296341Sdelphij         *
1186296341Sdelphij         * server:             pseudo-I/O for SSL library
1187296341Sdelphij         *
1188296341Sdelphij         * s_ssl_bio:          SSL filter BIO
1189296341Sdelphij         *
1190296341Sdelphij         * The client and the server each employ a "BIO pair":
1191296341Sdelphij         * client + client_io, server + server_io.
1192296341Sdelphij         * BIO pairs are symmetric.  A BIO pair behaves similar
1193296341Sdelphij         * to a non-blocking socketpair (but both endpoints must
1194296341Sdelphij         * be handled by the same thread).
1195296341Sdelphij         * [Here we could connect client and server to the ends
1196296341Sdelphij         * of a single BIO pair, but then this code would be less
1197296341Sdelphij         * suitable as an example for BIO pairs in general.]
1198296341Sdelphij         *
1199296341Sdelphij         * Useful functions for querying the state of BIO pair endpoints:
1200296341Sdelphij         *
1201296341Sdelphij         * BIO_ctrl_pending(bio)              number of bytes we can read now
1202296341Sdelphij         * BIO_ctrl_get_read_request(bio)     number of bytes needed to fulfil
1203296341Sdelphij         *                                      other side's read attempt
1204296341Sdelphij         * BIO_ctrl_get_write_guarantee(bio)   number of bytes we can write now
1205296341Sdelphij         *
1206296341Sdelphij         * ..._read_request is never more than ..._write_guarantee;
1207296341Sdelphij         * it depends on the application which one you should use.
1208296341Sdelphij         */
120955714Skris
1210296341Sdelphij        /*
1211296341Sdelphij         * We have non-blocking behaviour throughout this test program, but
1212296341Sdelphij         * can be sure that there is *some* progress in each iteration; so we
1213296341Sdelphij         * don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE --
1214296341Sdelphij         * we just try everything in each iteration
1215296341Sdelphij         */
1216109998Smarkm
1217296341Sdelphij        {
1218296341Sdelphij            /* CLIENT */
121955714Skris
1220296341Sdelphij            MS_STATIC char cbuf[1024 * 8];
1221296341Sdelphij            int i, r;
1222296341Sdelphij            clock_t c_clock = clock();
122355714Skris
1224296341Sdelphij            memset(cbuf, 0, sizeof(cbuf));
122555714Skris
1226296341Sdelphij            if (debug)
1227296341Sdelphij                if (SSL_in_init(c_ssl))
1228296341Sdelphij                    printf("client waiting in SSL_connect - %s\n",
1229296341Sdelphij                           SSL_state_string_long(c_ssl));
123059191Skris
1231296341Sdelphij            if (cw_num > 0) {
1232296341Sdelphij                /* Write to server. */
123355714Skris
1234296341Sdelphij                if (cw_num > (long)sizeof cbuf)
1235296341Sdelphij                    i = sizeof cbuf;
1236296341Sdelphij                else
1237296341Sdelphij                    i = (int)cw_num;
1238296341Sdelphij                r = BIO_write(c_ssl_bio, cbuf, i);
1239296341Sdelphij                if (r < 0) {
1240296341Sdelphij                    if (!BIO_should_retry(c_ssl_bio)) {
1241296341Sdelphij                        fprintf(stderr, "ERROR in CLIENT\n");
1242296341Sdelphij                        goto err;
1243296341Sdelphij                    }
1244296341Sdelphij                    /*
1245296341Sdelphij                     * BIO_should_retry(...) can just be ignored here. The
1246296341Sdelphij                     * library expects us to call BIO_write with the same
1247296341Sdelphij                     * arguments again, and that's what we will do in the
1248296341Sdelphij                     * next iteration.
1249296341Sdelphij                     */
1250296341Sdelphij                } else if (r == 0) {
1251296341Sdelphij                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
1252296341Sdelphij                    goto err;
1253296341Sdelphij                } else {
1254296341Sdelphij                    if (debug)
1255296341Sdelphij                        printf("client wrote %d\n", r);
1256296341Sdelphij                    cw_num -= r;
1257296341Sdelphij                }
1258296341Sdelphij            }
125955714Skris
1260296341Sdelphij            if (cr_num > 0) {
1261296341Sdelphij                /* Read from server. */
1262109998Smarkm
1263296341Sdelphij                r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf));
1264296341Sdelphij                if (r < 0) {
1265296341Sdelphij                    if (!BIO_should_retry(c_ssl_bio)) {
1266296341Sdelphij                        fprintf(stderr, "ERROR in CLIENT\n");
1267296341Sdelphij                        goto err;
1268296341Sdelphij                    }
1269296341Sdelphij                    /*
1270296341Sdelphij                     * Again, "BIO_should_retry" can be ignored.
1271296341Sdelphij                     */
1272296341Sdelphij                } else if (r == 0) {
1273296341Sdelphij                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
1274296341Sdelphij                    goto err;
1275296341Sdelphij                } else {
1276296341Sdelphij                    if (debug)
1277296341Sdelphij                        printf("client read %d\n", r);
1278296341Sdelphij                    cr_num -= r;
1279296341Sdelphij                }
1280296341Sdelphij            }
128155714Skris
1282296341Sdelphij            /*
1283296341Sdelphij             * c_time and s_time increments will typically be very small
1284296341Sdelphij             * (depending on machine speed and clock tick intervals), but
1285296341Sdelphij             * sampling over a large number of connections should result in
1286296341Sdelphij             * fairly accurate figures.  We cannot guarantee a lot, however
1287296341Sdelphij             * -- if each connection lasts for exactly one clock tick, it
1288296341Sdelphij             * will be counted only for the client or only for the server or
1289296341Sdelphij             * even not at all.
1290296341Sdelphij             */
1291296341Sdelphij            *c_time += (clock() - c_clock);
1292296341Sdelphij        }
129355714Skris
1294296341Sdelphij        {
1295296341Sdelphij            /* SERVER */
129655714Skris
1297296341Sdelphij            MS_STATIC char sbuf[1024 * 8];
1298296341Sdelphij            int i, r;
1299296341Sdelphij            clock_t s_clock = clock();
130059191Skris
1301296341Sdelphij            memset(sbuf, 0, sizeof(sbuf));
130255714Skris
1303296341Sdelphij            if (debug)
1304296341Sdelphij                if (SSL_in_init(s_ssl))
1305296341Sdelphij                    printf("server waiting in SSL_accept - %s\n",
1306296341Sdelphij                           SSL_state_string_long(s_ssl));
130755714Skris
1308296341Sdelphij            if (sw_num > 0) {
1309296341Sdelphij                /* Write to client. */
131059191Skris
1311296341Sdelphij                if (sw_num > (long)sizeof sbuf)
1312296341Sdelphij                    i = sizeof sbuf;
1313296341Sdelphij                else
1314296341Sdelphij                    i = (int)sw_num;
1315296341Sdelphij                r = BIO_write(s_ssl_bio, sbuf, i);
1316296341Sdelphij                if (r < 0) {
1317296341Sdelphij                    if (!BIO_should_retry(s_ssl_bio)) {
1318296341Sdelphij                        fprintf(stderr, "ERROR in SERVER\n");
1319296341Sdelphij                        goto err;
1320296341Sdelphij                    }
1321296341Sdelphij                    /* Ignore "BIO_should_retry". */
1322296341Sdelphij                } else if (r == 0) {
1323296341Sdelphij                    fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
1324296341Sdelphij                    goto err;
1325296341Sdelphij                } else {
1326296341Sdelphij                    if (debug)
1327296341Sdelphij                        printf("server wrote %d\n", r);
1328296341Sdelphij                    sw_num -= r;
1329296341Sdelphij                }
1330296341Sdelphij            }
133159191Skris
1332296341Sdelphij            if (sr_num > 0) {
1333296341Sdelphij                /* Read from client. */
133455714Skris
1335296341Sdelphij                r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf));
1336296341Sdelphij                if (r < 0) {
1337296341Sdelphij                    if (!BIO_should_retry(s_ssl_bio)) {
1338296341Sdelphij                        fprintf(stderr, "ERROR in SERVER\n");
1339296341Sdelphij                        goto err;
1340296341Sdelphij                    }
1341296341Sdelphij                    /* blah, blah */
1342296341Sdelphij                } else if (r == 0) {
1343296341Sdelphij                    fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
1344296341Sdelphij                    goto err;
1345296341Sdelphij                } else {
1346296341Sdelphij                    if (debug)
1347296341Sdelphij                        printf("server read %d\n", r);
1348296341Sdelphij                    sr_num -= r;
1349296341Sdelphij                }
1350296341Sdelphij            }
135155714Skris
1352296341Sdelphij            *s_time += (clock() - s_clock);
1353296341Sdelphij        }
135455714Skris
1355296341Sdelphij        {
1356296341Sdelphij            /* "I/O" BETWEEN CLIENT AND SERVER. */
135759191Skris
1358296341Sdelphij            size_t r1, r2;
1359296341Sdelphij            BIO *io1 = server_io, *io2 = client_io;
1360296341Sdelphij            /*
1361296341Sdelphij             * we use the non-copying interface for io1 and the standard
1362296341Sdelphij             * BIO_write/BIO_read interface for io2
1363296341Sdelphij             */
136455714Skris
1365296341Sdelphij            static int prev_progress = 1;
1366296341Sdelphij            int progress = 0;
136755714Skris
1368296341Sdelphij            /* io1 to io2 */
1369296341Sdelphij            do {
1370296341Sdelphij                size_t num;
1371296341Sdelphij                int r;
137255714Skris
1373296341Sdelphij                r1 = BIO_ctrl_pending(io1);
1374296341Sdelphij                r2 = BIO_ctrl_get_write_guarantee(io2);
1375296341Sdelphij
1376296341Sdelphij                num = r1;
1377296341Sdelphij                if (r2 < num)
1378296341Sdelphij                    num = r2;
1379296341Sdelphij                if (num) {
1380296341Sdelphij                    char *dataptr;
1381296341Sdelphij
1382296341Sdelphij                    if (INT_MAX < num) /* yeah, right */
1383296341Sdelphij                        num = INT_MAX;
1384296341Sdelphij
1385296341Sdelphij                    r = BIO_nread(io1, &dataptr, (int)num);
1386296341Sdelphij                    assert(r > 0);
1387296341Sdelphij                    assert(r <= (int)num);
1388296341Sdelphij                    /*
1389296341Sdelphij                     * possibly r < num (non-contiguous data)
1390296341Sdelphij                     */
1391296341Sdelphij                    num = r;
1392296341Sdelphij                    r = BIO_write(io2, dataptr, (int)num);
1393296341Sdelphij                    if (r != (int)num) { /* can't happen */
1394296341Sdelphij                        fprintf(stderr, "ERROR: BIO_write could not write "
1395296341Sdelphij                                "BIO_ctrl_get_write_guarantee() bytes");
1396296341Sdelphij                        goto err;
1397296341Sdelphij                    }
1398296341Sdelphij                    progress = 1;
1399296341Sdelphij
1400296341Sdelphij                    if (debug)
1401296341Sdelphij                        printf((io1 == client_io) ?
1402296341Sdelphij                               "C->S relaying: %d bytes\n" :
1403296341Sdelphij                               "S->C relaying: %d bytes\n", (int)num);
1404296341Sdelphij                }
1405296341Sdelphij            }
1406296341Sdelphij            while (r1 && r2);
1407296341Sdelphij
1408296341Sdelphij            /* io2 to io1 */
1409296341Sdelphij            {
1410296341Sdelphij                size_t num;
1411296341Sdelphij                int r;
1412296341Sdelphij
1413296341Sdelphij                r1 = BIO_ctrl_pending(io2);
1414296341Sdelphij                r2 = BIO_ctrl_get_read_request(io1);
1415296341Sdelphij                /*
1416296341Sdelphij                 * here we could use ..._get_write_guarantee instead of
1417296341Sdelphij                 * ..._get_read_request, but by using the latter we test
1418296341Sdelphij                 * restartability of the SSL implementation more thoroughly
1419296341Sdelphij                 */
1420296341Sdelphij                num = r1;
1421296341Sdelphij                if (r2 < num)
1422296341Sdelphij                    num = r2;
1423296341Sdelphij                if (num) {
1424296341Sdelphij                    char *dataptr;
1425296341Sdelphij
1426296341Sdelphij                    if (INT_MAX < num)
1427296341Sdelphij                        num = INT_MAX;
1428296341Sdelphij
1429296341Sdelphij                    if (num > 1)
1430296341Sdelphij                        --num;  /* test restartability even more thoroughly */
1431296341Sdelphij
1432296341Sdelphij                    r = BIO_nwrite0(io1, &dataptr);
1433296341Sdelphij                    assert(r > 0);
1434296341Sdelphij                    if (r < (int)num)
1435296341Sdelphij                        num = r;
1436296341Sdelphij                    r = BIO_read(io2, dataptr, (int)num);
1437296341Sdelphij                    if (r != (int)num) { /* can't happen */
1438296341Sdelphij                        fprintf(stderr, "ERROR: BIO_read could not read "
1439296341Sdelphij                                "BIO_ctrl_pending() bytes");
1440296341Sdelphij                        goto err;
1441296341Sdelphij                    }
1442296341Sdelphij                    progress = 1;
1443296341Sdelphij                    r = BIO_nwrite(io1, &dataptr, (int)num);
1444296341Sdelphij                    if (r != (int)num) { /* can't happen */
1445296341Sdelphij                        fprintf(stderr, "ERROR: BIO_nwrite() did not accept "
1446296341Sdelphij                                "BIO_nwrite0() bytes");
1447296341Sdelphij                        goto err;
1448296341Sdelphij                    }
1449296341Sdelphij
1450296341Sdelphij                    if (debug)
1451296341Sdelphij                        printf((io2 == client_io) ?
1452296341Sdelphij                               "C->S relaying: %d bytes\n" :
1453296341Sdelphij                               "S->C relaying: %d bytes\n", (int)num);
1454296341Sdelphij                }
1455296341Sdelphij            }                   /* no loop, BIO_ctrl_get_read_request now
1456296341Sdelphij                                 * returns 0 anyway */
1457296341Sdelphij
1458296341Sdelphij            if (!progress && !prev_progress)
1459296341Sdelphij                if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0) {
1460296341Sdelphij                    fprintf(stderr, "ERROR: got stuck\n");
1461296341Sdelphij                    if (strcmp("SSLv2", SSL_get_version(c_ssl)) == 0) {
1462296341Sdelphij                        fprintf(stderr, "This can happen for SSL2 because "
1463296341Sdelphij                                "CLIENT-FINISHED and SERVER-VERIFY are written \n"
1464296341Sdelphij                                "concurrently ...");
1465296341Sdelphij                        if (strncmp("2SCF", SSL_state_string(c_ssl), 4) == 0
1466296341Sdelphij                            && strncmp("2SSV", SSL_state_string(s_ssl),
1467296341Sdelphij                                       4) == 0) {
1468296341Sdelphij                            fprintf(stderr, " ok.\n");
1469296341Sdelphij                            goto end;
1470296341Sdelphij                        }
1471296341Sdelphij                    }
1472296341Sdelphij                    fprintf(stderr, " ERROR.\n");
1473296341Sdelphij                    goto err;
1474296341Sdelphij                }
1475296341Sdelphij            prev_progress = progress;
1476296341Sdelphij        }
1477296341Sdelphij    }
1478296341Sdelphij    while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0);
1479296341Sdelphij
1480296341Sdelphij    if (verbose)
1481296341Sdelphij        print_details(c_ssl, "DONE via BIO pair: ");
1482296341Sdelphij end:
1483296341Sdelphij    ret = 0;
1484296341Sdelphij
148555714Skris err:
1486296341Sdelphij    ERR_print_errors(bio_err);
148755714Skris
1488296341Sdelphij    if (server)
1489296341Sdelphij        BIO_free(server);
1490296341Sdelphij    if (server_io)
1491296341Sdelphij        BIO_free(server_io);
1492296341Sdelphij    if (client)
1493296341Sdelphij        BIO_free(client);
1494296341Sdelphij    if (client_io)
1495296341Sdelphij        BIO_free(client_io);
1496296341Sdelphij    if (s_ssl_bio)
1497296341Sdelphij        BIO_free(s_ssl_bio);
1498296341Sdelphij    if (c_ssl_bio)
1499296341Sdelphij        BIO_free(c_ssl_bio);
150055714Skris
1501296341Sdelphij    return ret;
1502296341Sdelphij}
150355714Skris
1504296341Sdelphij#define W_READ  1
1505296341Sdelphij#define W_WRITE 2
1506296341Sdelphij#define C_DONE  1
1507296341Sdelphij#define S_DONE  2
150855714Skris
150955714Skrisint doit(SSL *s_ssl, SSL *c_ssl, long count)
1510296341Sdelphij{
1511296341Sdelphij    MS_STATIC char cbuf[1024 * 8], sbuf[1024 * 8];
1512296341Sdelphij    long cw_num = count, cr_num = count;
1513296341Sdelphij    long sw_num = count, sr_num = count;
1514296341Sdelphij    int ret = 1;
1515296341Sdelphij    BIO *c_to_s = NULL;
1516296341Sdelphij    BIO *s_to_c = NULL;
1517296341Sdelphij    BIO *c_bio = NULL;
1518296341Sdelphij    BIO *s_bio = NULL;
1519296341Sdelphij    int c_r, c_w, s_r, s_w;
1520296341Sdelphij    int i, j;
1521296341Sdelphij    int done = 0;
1522296341Sdelphij    int c_write, s_write;
1523296341Sdelphij    int do_server = 0, do_client = 0;
152455714Skris
1525296341Sdelphij    memset(cbuf, 0, sizeof(cbuf));
1526296341Sdelphij    memset(sbuf, 0, sizeof(sbuf));
1527109998Smarkm
1528296341Sdelphij    c_to_s = BIO_new(BIO_s_mem());
1529296341Sdelphij    s_to_c = BIO_new(BIO_s_mem());
1530296341Sdelphij    if ((s_to_c == NULL) || (c_to_s == NULL)) {
1531296341Sdelphij        ERR_print_errors(bio_err);
1532296341Sdelphij        goto err;
1533296341Sdelphij    }
153455714Skris
1535296341Sdelphij    c_bio = BIO_new(BIO_f_ssl());
1536296341Sdelphij    s_bio = BIO_new(BIO_f_ssl());
1537296341Sdelphij    if ((c_bio == NULL) || (s_bio == NULL)) {
1538296341Sdelphij        ERR_print_errors(bio_err);
1539296341Sdelphij        goto err;
1540296341Sdelphij    }
154155714Skris
1542296341Sdelphij    SSL_set_connect_state(c_ssl);
1543296341Sdelphij    SSL_set_bio(c_ssl, s_to_c, c_to_s);
1544296341Sdelphij    BIO_set_ssl(c_bio, c_ssl, BIO_NOCLOSE);
154555714Skris
1546296341Sdelphij    SSL_set_accept_state(s_ssl);
1547296341Sdelphij    SSL_set_bio(s_ssl, c_to_s, s_to_c);
1548296341Sdelphij    BIO_set_ssl(s_bio, s_ssl, BIO_NOCLOSE);
154955714Skris
1550296341Sdelphij    c_r = 0;
1551296341Sdelphij    s_r = 1;
1552296341Sdelphij    c_w = 1;
1553296341Sdelphij    s_w = 0;
1554296341Sdelphij    c_write = 1, s_write = 0;
155555714Skris
1556296341Sdelphij    /* We can always do writes */
1557296341Sdelphij    for (;;) {
1558296341Sdelphij        do_server = 0;
1559296341Sdelphij        do_client = 0;
156055714Skris
1561296341Sdelphij        i = (int)BIO_pending(s_bio);
1562296341Sdelphij        if ((i && s_r) || s_w)
1563296341Sdelphij            do_server = 1;
156455714Skris
1565296341Sdelphij        i = (int)BIO_pending(c_bio);
1566296341Sdelphij        if ((i && c_r) || c_w)
1567296341Sdelphij            do_client = 1;
156855714Skris
1569296341Sdelphij        if (do_server && debug) {
1570296341Sdelphij            if (SSL_in_init(s_ssl))
1571296341Sdelphij                printf("server waiting in SSL_accept - %s\n",
1572296341Sdelphij                       SSL_state_string_long(s_ssl));
1573296341Sdelphij/*-
1574296341Sdelphij            else if (s_write)
1575296341Sdelphij                printf("server:SSL_write()\n");
1576296341Sdelphij            else
1577296341Sdelphij                printf("server:SSL_read()\n"); */
1578296341Sdelphij        }
157955714Skris
1580296341Sdelphij        if (do_client && debug) {
1581296341Sdelphij            if (SSL_in_init(c_ssl))
1582296341Sdelphij                printf("client waiting in SSL_connect - %s\n",
1583296341Sdelphij                       SSL_state_string_long(c_ssl));
1584296341Sdelphij/*-
1585296341Sdelphij            else if (c_write)
1586296341Sdelphij                printf("client:SSL_write()\n");
1587296341Sdelphij            else
1588296341Sdelphij                printf("client:SSL_read()\n"); */
1589296341Sdelphij        }
159055714Skris
1591296341Sdelphij        if (!do_client && !do_server) {
1592296341Sdelphij            fprintf(stdout, "ERROR IN STARTUP\n");
1593296341Sdelphij            ERR_print_errors(bio_err);
1594296341Sdelphij            goto err;
1595296341Sdelphij        }
1596296341Sdelphij        if (do_client && !(done & C_DONE)) {
1597296341Sdelphij            if (c_write) {
1598296341Sdelphij                j = (cw_num > (long)sizeof(cbuf)) ?
1599296341Sdelphij                    (int)sizeof(cbuf) : (int)cw_num;
1600296341Sdelphij                i = BIO_write(c_bio, cbuf, j);
1601296341Sdelphij                if (i < 0) {
1602296341Sdelphij                    c_r = 0;
1603296341Sdelphij                    c_w = 0;
1604296341Sdelphij                    if (BIO_should_retry(c_bio)) {
1605296341Sdelphij                        if (BIO_should_read(c_bio))
1606296341Sdelphij                            c_r = 1;
1607296341Sdelphij                        if (BIO_should_write(c_bio))
1608296341Sdelphij                            c_w = 1;
1609296341Sdelphij                    } else {
1610296341Sdelphij                        fprintf(stderr, "ERROR in CLIENT\n");
1611296341Sdelphij                        ERR_print_errors(bio_err);
1612296341Sdelphij                        goto err;
1613296341Sdelphij                    }
1614296341Sdelphij                } else if (i == 0) {
1615296341Sdelphij                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
1616296341Sdelphij                    goto err;
1617296341Sdelphij                } else {
1618296341Sdelphij                    if (debug)
1619296341Sdelphij                        printf("client wrote %d\n", i);
1620296341Sdelphij                    /* ok */
1621296341Sdelphij                    s_r = 1;
1622296341Sdelphij                    c_write = 0;
1623296341Sdelphij                    cw_num -= i;
1624296341Sdelphij                }
1625296341Sdelphij            } else {
1626296341Sdelphij                i = BIO_read(c_bio, cbuf, sizeof(cbuf));
1627296341Sdelphij                if (i < 0) {
1628296341Sdelphij                    c_r = 0;
1629296341Sdelphij                    c_w = 0;
1630296341Sdelphij                    if (BIO_should_retry(c_bio)) {
1631296341Sdelphij                        if (BIO_should_read(c_bio))
1632296341Sdelphij                            c_r = 1;
1633296341Sdelphij                        if (BIO_should_write(c_bio))
1634296341Sdelphij                            c_w = 1;
1635296341Sdelphij                    } else {
1636296341Sdelphij                        fprintf(stderr, "ERROR in CLIENT\n");
1637296341Sdelphij                        ERR_print_errors(bio_err);
1638296341Sdelphij                        goto err;
1639296341Sdelphij                    }
1640296341Sdelphij                } else if (i == 0) {
1641296341Sdelphij                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
1642296341Sdelphij                    goto err;
1643296341Sdelphij                } else {
1644296341Sdelphij                    if (debug)
1645296341Sdelphij                        printf("client read %d\n", i);
1646296341Sdelphij                    cr_num -= i;
1647296341Sdelphij                    if (sw_num > 0) {
1648296341Sdelphij                        s_write = 1;
1649296341Sdelphij                        s_w = 1;
1650296341Sdelphij                    }
1651296341Sdelphij                    if (cr_num <= 0) {
1652296341Sdelphij                        s_write = 1;
1653296341Sdelphij                        s_w = 1;
1654296341Sdelphij                        done = S_DONE | C_DONE;
1655296341Sdelphij                    }
1656296341Sdelphij                }
1657296341Sdelphij            }
1658296341Sdelphij        }
165955714Skris
1660296341Sdelphij        if (do_server && !(done & S_DONE)) {
1661296341Sdelphij            if (!s_write) {
1662296341Sdelphij                i = BIO_read(s_bio, sbuf, sizeof(cbuf));
1663296341Sdelphij                if (i < 0) {
1664296341Sdelphij                    s_r = 0;
1665296341Sdelphij                    s_w = 0;
1666296341Sdelphij                    if (BIO_should_retry(s_bio)) {
1667296341Sdelphij                        if (BIO_should_read(s_bio))
1668296341Sdelphij                            s_r = 1;
1669296341Sdelphij                        if (BIO_should_write(s_bio))
1670296341Sdelphij                            s_w = 1;
1671296341Sdelphij                    } else {
1672296341Sdelphij                        fprintf(stderr, "ERROR in SERVER\n");
1673296341Sdelphij                        ERR_print_errors(bio_err);
1674296341Sdelphij                        goto err;
1675296341Sdelphij                    }
1676296341Sdelphij                } else if (i == 0) {
1677296341Sdelphij                    ERR_print_errors(bio_err);
1678296341Sdelphij                    fprintf(stderr,
1679296341Sdelphij                            "SSL SERVER STARTUP FAILED in SSL_read\n");
1680296341Sdelphij                    goto err;
1681296341Sdelphij                } else {
1682296341Sdelphij                    if (debug)
1683296341Sdelphij                        printf("server read %d\n", i);
1684296341Sdelphij                    sr_num -= i;
1685296341Sdelphij                    if (cw_num > 0) {
1686296341Sdelphij                        c_write = 1;
1687296341Sdelphij                        c_w = 1;
1688296341Sdelphij                    }
1689296341Sdelphij                    if (sr_num <= 0) {
1690296341Sdelphij                        s_write = 1;
1691296341Sdelphij                        s_w = 1;
1692296341Sdelphij                        c_write = 0;
1693296341Sdelphij                    }
1694296341Sdelphij                }
1695296341Sdelphij            } else {
1696296341Sdelphij                j = (sw_num > (long)sizeof(sbuf)) ?
1697296341Sdelphij                    (int)sizeof(sbuf) : (int)sw_num;
1698296341Sdelphij                i = BIO_write(s_bio, sbuf, j);
1699296341Sdelphij                if (i < 0) {
1700296341Sdelphij                    s_r = 0;
1701296341Sdelphij                    s_w = 0;
1702296341Sdelphij                    if (BIO_should_retry(s_bio)) {
1703296341Sdelphij                        if (BIO_should_read(s_bio))
1704296341Sdelphij                            s_r = 1;
1705296341Sdelphij                        if (BIO_should_write(s_bio))
1706296341Sdelphij                            s_w = 1;
1707296341Sdelphij                    } else {
1708296341Sdelphij                        fprintf(stderr, "ERROR in SERVER\n");
1709296341Sdelphij                        ERR_print_errors(bio_err);
1710296341Sdelphij                        goto err;
1711296341Sdelphij                    }
1712296341Sdelphij                } else if (i == 0) {
1713296341Sdelphij                    ERR_print_errors(bio_err);
1714296341Sdelphij                    fprintf(stderr,
1715296341Sdelphij                            "SSL SERVER STARTUP FAILED in SSL_write\n");
1716296341Sdelphij                    goto err;
1717296341Sdelphij                } else {
1718296341Sdelphij                    if (debug)
1719296341Sdelphij                        printf("server wrote %d\n", i);
1720296341Sdelphij                    sw_num -= i;
1721296341Sdelphij                    s_write = 0;
1722296341Sdelphij                    c_r = 1;
1723296341Sdelphij                    if (sw_num <= 0)
1724296341Sdelphij                        done |= S_DONE;
1725296341Sdelphij                }
1726296341Sdelphij            }
1727296341Sdelphij        }
172855714Skris
1729296341Sdelphij        if ((done & S_DONE) && (done & C_DONE))
1730296341Sdelphij            break;
1731296341Sdelphij    }
173255714Skris
1733296341Sdelphij    if (verbose)
1734296341Sdelphij        print_details(c_ssl, "DONE: ");
1735296341Sdelphij    ret = 0;
1736296341Sdelphij err:
1737296341Sdelphij    /*
1738296341Sdelphij     * We have to set the BIO's to NULL otherwise they will be
1739296341Sdelphij     * OPENSSL_free()ed twice.  Once when th s_ssl is SSL_free()ed and again
1740296341Sdelphij     * when c_ssl is SSL_free()ed. This is a hack required because s_ssl and
1741296341Sdelphij     * c_ssl are sharing the same BIO structure and SSL_set_bio() and
1742296341Sdelphij     * SSL_free() automatically BIO_free non NULL entries. You should not
1743296341Sdelphij     * normally do this or be required to do this
1744296341Sdelphij     */
1745296341Sdelphij    if (s_ssl != NULL) {
1746296341Sdelphij        s_ssl->rbio = NULL;
1747296341Sdelphij        s_ssl->wbio = NULL;
1748296341Sdelphij    }
1749296341Sdelphij    if (c_ssl != NULL) {
1750296341Sdelphij        c_ssl->rbio = NULL;
1751296341Sdelphij        c_ssl->wbio = NULL;
1752296341Sdelphij    }
175355714Skris
1754296341Sdelphij    if (c_to_s != NULL)
1755296341Sdelphij        BIO_free(c_to_s);
1756296341Sdelphij    if (s_to_c != NULL)
1757296341Sdelphij        BIO_free(s_to_c);
1758296341Sdelphij    if (c_bio != NULL)
1759296341Sdelphij        BIO_free_all(c_bio);
1760296341Sdelphij    if (s_bio != NULL)
1761296341Sdelphij        BIO_free_all(s_bio);
1762296341Sdelphij    return (ret);
1763296341Sdelphij}
176455714Skris
1765160814Ssimonstatic int get_proxy_auth_ex_data_idx(void)
1766296341Sdelphij{
1767296341Sdelphij    static volatile int idx = -1;
1768296341Sdelphij    if (idx < 0) {
1769296341Sdelphij        CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
1770296341Sdelphij        if (idx < 0) {
1771296341Sdelphij            idx = X509_STORE_CTX_get_ex_new_index(0,
1772296341Sdelphij                                                  "SSLtest for verify callback",
1773296341Sdelphij                                                  NULL, NULL, NULL);
1774296341Sdelphij        }
1775296341Sdelphij        CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
1776296341Sdelphij    }
1777296341Sdelphij    return idx;
1778296341Sdelphij}
1779160814Ssimon
178059191Skrisstatic int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
1781296341Sdelphij{
1782296341Sdelphij    char *s, buf[256];
178355714Skris
1784296341Sdelphij    s = X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf,
1785296341Sdelphij                          sizeof buf);
1786296341Sdelphij    if (s != NULL) {
1787296341Sdelphij        if (ok)
1788296341Sdelphij            fprintf(stderr, "depth=%d %s\n", ctx->error_depth, buf);
1789296341Sdelphij        else {
1790296341Sdelphij            fprintf(stderr, "depth=%d error=%d %s\n",
1791296341Sdelphij                    ctx->error_depth, ctx->error, buf);
1792296341Sdelphij        }
1793296341Sdelphij    }
179455714Skris
1795296341Sdelphij    if (ok == 0) {
1796296341Sdelphij        fprintf(stderr, "Error string: %s\n",
1797296341Sdelphij                X509_verify_cert_error_string(ctx->error));
1798296341Sdelphij        switch (ctx->error) {
1799296341Sdelphij        case X509_V_ERR_CERT_NOT_YET_VALID:
1800296341Sdelphij        case X509_V_ERR_CERT_HAS_EXPIRED:
1801296341Sdelphij        case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
1802296341Sdelphij            fprintf(stderr, "  ... ignored.\n");
1803296341Sdelphij            ok = 1;
1804296341Sdelphij        }
1805296341Sdelphij    }
180655714Skris
1807296341Sdelphij    if (ok == 1) {
1808296341Sdelphij        X509 *xs = ctx->current_cert;
1809160814Ssimon#if 0
1810296341Sdelphij        X509 *xi = ctx->current_issuer;
1811160814Ssimon#endif
1812160814Ssimon
1813296341Sdelphij        if (xs->ex_flags & EXFLAG_PROXY) {
1814296341Sdelphij            unsigned int *letters = X509_STORE_CTX_get_ex_data(ctx,
1815296341Sdelphij                                                               get_proxy_auth_ex_data_idx
1816296341Sdelphij                                                               ());
1817160814Ssimon
1818296341Sdelphij            if (letters) {
1819296341Sdelphij                int found_any = 0;
1820296341Sdelphij                int i;
1821296341Sdelphij                PROXY_CERT_INFO_EXTENSION *pci =
1822296341Sdelphij                    X509_get_ext_d2i(xs, NID_proxyCertInfo,
1823296341Sdelphij                                     NULL, NULL);
1824160814Ssimon
1825296341Sdelphij                switch (OBJ_obj2nid(pci->proxyPolicy->policyLanguage)) {
1826296341Sdelphij                case NID_Independent:
1827296341Sdelphij                    /*
1828296341Sdelphij                     * Completely meaningless in this program, as there's no
1829296341Sdelphij                     * way to grant explicit rights to a specific PrC.
1830296341Sdelphij                     * Basically, using id-ppl-Independent is the perfect way
1831296341Sdelphij                     * to grant no rights at all.
1832296341Sdelphij                     */
1833296341Sdelphij                    fprintf(stderr, "  Independent proxy certificate");
1834296341Sdelphij                    for (i = 0; i < 26; i++)
1835296341Sdelphij                        letters[i] = 0;
1836296341Sdelphij                    break;
1837296341Sdelphij                case NID_id_ppl_inheritAll:
1838296341Sdelphij                    /*
1839296341Sdelphij                     * This is basically a NOP, we simply let the current
1840296341Sdelphij                     * rights stand as they are.
1841296341Sdelphij                     */
1842296341Sdelphij                    fprintf(stderr, "  Proxy certificate inherits all");
1843296341Sdelphij                    break;
1844296341Sdelphij                default:
1845296341Sdelphij                    s = (char *)
1846296341Sdelphij                        pci->proxyPolicy->policy->data;
1847296341Sdelphij                    i = pci->proxyPolicy->policy->length;
1848160814Ssimon
1849296341Sdelphij                    /*
1850296341Sdelphij                     * The algorithm works as follows: it is assumed that
1851296341Sdelphij                     * previous iterations or the initial granted rights has
1852296341Sdelphij                     * already set some elements of `letters'.  What we need
1853296341Sdelphij                     * to do is to clear those that weren't granted by the
1854296341Sdelphij                     * current PrC as well.  The easiest way to do this is to
1855296341Sdelphij                     * add 1 to all the elements whose letters are given with
1856296341Sdelphij                     * the current policy. That way, all elements that are
1857296341Sdelphij                     * set by the current policy and were already set by
1858296341Sdelphij                     * earlier policies and through the original grant of
1859296341Sdelphij                     * rights will get the value 2 or higher. The last thing
1860296341Sdelphij                     * to do is to sweep through `letters' and keep the
1861296341Sdelphij                     * elements having the value 2 as set, and clear all the
1862296341Sdelphij                     * others.
1863296341Sdelphij                     */
1864160814Ssimon
1865296341Sdelphij                    fprintf(stderr, "  Certificate proxy rights = %*.*s", i,
1866296341Sdelphij                            i, s);
1867296341Sdelphij                    while (i-- > 0) {
1868296341Sdelphij                        int c = *s++;
1869296341Sdelphij                        if (isascii(c) && isalpha(c)) {
1870296341Sdelphij                            if (islower(c))
1871296341Sdelphij                                c = toupper(c);
1872296341Sdelphij                            letters[c - 'A']++;
1873296341Sdelphij                        }
1874296341Sdelphij                    }
1875296341Sdelphij                    for (i = 0; i < 26; i++)
1876296341Sdelphij                        if (letters[i] < 2)
1877296341Sdelphij                            letters[i] = 0;
1878296341Sdelphij                        else
1879296341Sdelphij                            letters[i] = 1;
1880296341Sdelphij                }
1881160814Ssimon
1882296341Sdelphij                found_any = 0;
1883296341Sdelphij                fprintf(stderr, ", resulting proxy rights = ");
1884296341Sdelphij                for (i = 0; i < 26; i++)
1885296341Sdelphij                    if (letters[i]) {
1886296341Sdelphij                        fprintf(stderr, "%c", i + 'A');
1887296341Sdelphij                        found_any = 1;
1888296341Sdelphij                    }
1889296341Sdelphij                if (!found_any)
1890296341Sdelphij                    fprintf(stderr, "none");
1891296341Sdelphij                fprintf(stderr, "\n");
1892160814Ssimon
1893296341Sdelphij                PROXY_CERT_INFO_EXTENSION_free(pci);
1894296341Sdelphij            }
1895296341Sdelphij        }
1896296341Sdelphij    }
1897160814Ssimon
1898296341Sdelphij    return (ok);
1899296341Sdelphij}
190055714Skris
1901160814Ssimonstatic void process_proxy_debug(int indent, const char *format, ...)
1902296341Sdelphij{
1903296341Sdelphij    /* That's 80 > */
1904296341Sdelphij    static const char indentation[] =
1905296341Sdelphij        ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
1906296341Sdelphij        ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
1907296341Sdelphij    char my_format[256];
1908296341Sdelphij    va_list args;
1909160814Ssimon
1910296341Sdelphij    BIO_snprintf(my_format, sizeof(my_format), "%*.*s %s",
1911296341Sdelphij                 indent, indent, indentation, format);
1912160814Ssimon
1913296341Sdelphij    va_start(args, format);
1914296341Sdelphij    vfprintf(stderr, my_format, args);
1915296341Sdelphij    va_end(args);
1916296341Sdelphij}
1917296341Sdelphij
1918296341Sdelphij/*-
1919296341Sdelphij * Priority levels:
1920296341Sdelphij *  0   [!]var, ()
1921296341Sdelphij *  1   & ^
1922296341Sdelphij *  2   |
1923296341Sdelphij */
1924160814Ssimonstatic int process_proxy_cond_adders(unsigned int letters[26],
1925296341Sdelphij                                     const char *cond, const char **cond_end,
1926296341Sdelphij                                     int *pos, int indent);
1927296341Sdelphijstatic int process_proxy_cond_val(unsigned int letters[26], const char *cond,
1928296341Sdelphij                                  const char **cond_end, int *pos, int indent)
1929296341Sdelphij{
1930296341Sdelphij    int c;
1931296341Sdelphij    int ok = 1;
1932296341Sdelphij    int negate = 0;
1933160814Ssimon
1934296341Sdelphij    while (isspace((int)*cond)) {
1935296341Sdelphij        cond++;
1936296341Sdelphij        (*pos)++;
1937296341Sdelphij    }
1938296341Sdelphij    c = *cond;
1939160814Ssimon
1940296341Sdelphij    if (debug)
1941296341Sdelphij        process_proxy_debug(indent,
1942296341Sdelphij                            "Start process_proxy_cond_val at position %d: %s\n",
1943296341Sdelphij                            *pos, cond);
1944160814Ssimon
1945296341Sdelphij    while (c == '!') {
1946296341Sdelphij        negate = !negate;
1947296341Sdelphij        cond++;
1948296341Sdelphij        (*pos)++;
1949296341Sdelphij        while (isspace((int)*cond)) {
1950296341Sdelphij            cond++;
1951296341Sdelphij            (*pos)++;
1952296341Sdelphij        }
1953296341Sdelphij        c = *cond;
1954296341Sdelphij    }
1955160814Ssimon
1956296341Sdelphij    if (c == '(') {
1957296341Sdelphij        cond++;
1958296341Sdelphij        (*pos)++;
1959296341Sdelphij        ok = process_proxy_cond_adders(letters, cond, cond_end, pos,
1960296341Sdelphij                                       indent + 1);
1961296341Sdelphij        cond = *cond_end;
1962296341Sdelphij        if (ok < 0)
1963296341Sdelphij            goto end;
1964296341Sdelphij        while (isspace((int)*cond)) {
1965296341Sdelphij            cond++;
1966296341Sdelphij            (*pos)++;
1967296341Sdelphij        }
1968296341Sdelphij        c = *cond;
1969296341Sdelphij        if (c != ')') {
1970296341Sdelphij            fprintf(stderr,
1971296341Sdelphij                    "Weird condition character in position %d: "
1972296341Sdelphij                    "%c\n", *pos, c);
1973296341Sdelphij            ok = -1;
1974296341Sdelphij            goto end;
1975296341Sdelphij        }
1976296341Sdelphij        cond++;
1977296341Sdelphij        (*pos)++;
1978296341Sdelphij    } else if (isascii(c) && isalpha(c)) {
1979296341Sdelphij        if (islower(c))
1980296341Sdelphij            c = toupper(c);
1981296341Sdelphij        ok = letters[c - 'A'];
1982296341Sdelphij        cond++;
1983296341Sdelphij        (*pos)++;
1984296341Sdelphij    } else {
1985296341Sdelphij        fprintf(stderr,
1986296341Sdelphij                "Weird condition character in position %d: " "%c\n", *pos, c);
1987296341Sdelphij        ok = -1;
1988296341Sdelphij        goto end;
1989296341Sdelphij    }
1990160814Ssimon end:
1991296341Sdelphij    *cond_end = cond;
1992296341Sdelphij    if (ok >= 0 && negate)
1993296341Sdelphij        ok = !ok;
1994160814Ssimon
1995296341Sdelphij    if (debug)
1996296341Sdelphij        process_proxy_debug(indent,
1997296341Sdelphij                            "End process_proxy_cond_val at position %d: %s, returning %d\n",
1998296341Sdelphij                            *pos, cond, ok);
1999160814Ssimon
2000296341Sdelphij    return ok;
2001296341Sdelphij}
2002296341Sdelphij
2003160814Ssimonstatic int process_proxy_cond_multipliers(unsigned int letters[26],
2004296341Sdelphij                                          const char *cond,
2005296341Sdelphij                                          const char **cond_end, int *pos,
2006296341Sdelphij                                          int indent)
2007296341Sdelphij{
2008296341Sdelphij    int ok;
2009296341Sdelphij    char c;
2010160814Ssimon
2011296341Sdelphij    if (debug)
2012296341Sdelphij        process_proxy_debug(indent,
2013296341Sdelphij                            "Start process_proxy_cond_multipliers at position %d: %s\n",
2014296341Sdelphij                            *pos, cond);
2015160814Ssimon
2016296341Sdelphij    ok = process_proxy_cond_val(letters, cond, cond_end, pos, indent + 1);
2017296341Sdelphij    cond = *cond_end;
2018296341Sdelphij    if (ok < 0)
2019296341Sdelphij        goto end;
2020160814Ssimon
2021296341Sdelphij    while (ok >= 0) {
2022296341Sdelphij        while (isspace((int)*cond)) {
2023296341Sdelphij            cond++;
2024296341Sdelphij            (*pos)++;
2025296341Sdelphij        }
2026296341Sdelphij        c = *cond;
2027160814Ssimon
2028296341Sdelphij        switch (c) {
2029296341Sdelphij        case '&':
2030296341Sdelphij        case '^':
2031296341Sdelphij            {
2032296341Sdelphij                int save_ok = ok;
2033160814Ssimon
2034296341Sdelphij                cond++;
2035296341Sdelphij                (*pos)++;
2036296341Sdelphij                ok = process_proxy_cond_val(letters,
2037296341Sdelphij                                            cond, cond_end, pos, indent + 1);
2038296341Sdelphij                cond = *cond_end;
2039296341Sdelphij                if (ok < 0)
2040296341Sdelphij                    break;
2041160814Ssimon
2042296341Sdelphij                switch (c) {
2043296341Sdelphij                case '&':
2044296341Sdelphij                    ok &= save_ok;
2045296341Sdelphij                    break;
2046296341Sdelphij                case '^':
2047296341Sdelphij                    ok ^= save_ok;
2048296341Sdelphij                    break;
2049296341Sdelphij                default:
2050296341Sdelphij                    fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!"
2051296341Sdelphij                            " STOPPING\n");
2052296341Sdelphij                    EXIT(1);
2053296341Sdelphij                }
2054296341Sdelphij            }
2055296341Sdelphij            break;
2056296341Sdelphij        default:
2057296341Sdelphij            goto end;
2058296341Sdelphij        }
2059296341Sdelphij    }
2060160814Ssimon end:
2061296341Sdelphij    if (debug)
2062296341Sdelphij        process_proxy_debug(indent,
2063296341Sdelphij                            "End process_proxy_cond_multipliers at position %d: %s, returning %d\n",
2064296341Sdelphij                            *pos, cond, ok);
2065160814Ssimon
2066296341Sdelphij    *cond_end = cond;
2067296341Sdelphij    return ok;
2068296341Sdelphij}
2069296341Sdelphij
2070160814Ssimonstatic int process_proxy_cond_adders(unsigned int letters[26],
2071296341Sdelphij                                     const char *cond, const char **cond_end,
2072296341Sdelphij                                     int *pos, int indent)
2073296341Sdelphij{
2074296341Sdelphij    int ok;
2075296341Sdelphij    char c;
2076160814Ssimon
2077296341Sdelphij    if (debug)
2078296341Sdelphij        process_proxy_debug(indent,
2079296341Sdelphij                            "Start process_proxy_cond_adders at position %d: %s\n",
2080296341Sdelphij                            *pos, cond);
2081160814Ssimon
2082296341Sdelphij    ok = process_proxy_cond_multipliers(letters, cond, cond_end, pos,
2083296341Sdelphij                                        indent + 1);
2084296341Sdelphij    cond = *cond_end;
2085296341Sdelphij    if (ok < 0)
2086296341Sdelphij        goto end;
2087160814Ssimon
2088296341Sdelphij    while (ok >= 0) {
2089296341Sdelphij        while (isspace((int)*cond)) {
2090296341Sdelphij            cond++;
2091296341Sdelphij            (*pos)++;
2092296341Sdelphij        }
2093296341Sdelphij        c = *cond;
2094160814Ssimon
2095296341Sdelphij        switch (c) {
2096296341Sdelphij        case '|':
2097296341Sdelphij            {
2098296341Sdelphij                int save_ok = ok;
2099160814Ssimon
2100296341Sdelphij                cond++;
2101296341Sdelphij                (*pos)++;
2102296341Sdelphij                ok = process_proxy_cond_multipliers(letters,
2103296341Sdelphij                                                    cond, cond_end, pos,
2104296341Sdelphij                                                    indent + 1);
2105296341Sdelphij                cond = *cond_end;
2106296341Sdelphij                if (ok < 0)
2107296341Sdelphij                    break;
2108160814Ssimon
2109296341Sdelphij                switch (c) {
2110296341Sdelphij                case '|':
2111296341Sdelphij                    ok |= save_ok;
2112296341Sdelphij                    break;
2113296341Sdelphij                default:
2114296341Sdelphij                    fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!"
2115296341Sdelphij                            " STOPPING\n");
2116296341Sdelphij                    EXIT(1);
2117296341Sdelphij                }
2118296341Sdelphij            }
2119296341Sdelphij            break;
2120296341Sdelphij        default:
2121296341Sdelphij            goto end;
2122296341Sdelphij        }
2123296341Sdelphij    }
2124160814Ssimon end:
2125296341Sdelphij    if (debug)
2126296341Sdelphij        process_proxy_debug(indent,
2127296341Sdelphij                            "End process_proxy_cond_adders at position %d: %s, returning %d\n",
2128296341Sdelphij                            *pos, cond, ok);
2129160814Ssimon
2130296341Sdelphij    *cond_end = cond;
2131296341Sdelphij    return ok;
2132296341Sdelphij}
2133160814Ssimon
2134160814Ssimonstatic int process_proxy_cond(unsigned int letters[26],
2135296341Sdelphij                              const char *cond, const char **cond_end)
2136296341Sdelphij{
2137296341Sdelphij    int pos = 1;
2138296341Sdelphij    return process_proxy_cond_adders(letters, cond, cond_end, &pos, 1);
2139296341Sdelphij}
2140160814Ssimon
2141109998Smarkmstatic int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg)
2142296341Sdelphij{
2143296341Sdelphij    int ok = 1;
2144296341Sdelphij    struct app_verify_arg *cb_arg = arg;
2145296341Sdelphij    unsigned int letters[26];   /* only used with proxy_auth */
2146109998Smarkm
2147296341Sdelphij    if (cb_arg->app_verify) {
2148296341Sdelphij        char *s = NULL, buf[256];
2149160814Ssimon
2150296341Sdelphij        fprintf(stderr, "In app_verify_callback, allowing cert. ");
2151296341Sdelphij        fprintf(stderr, "Arg is: %s\n", cb_arg->string);
2152296341Sdelphij        fprintf(stderr,
2153296341Sdelphij                "Finished printing do we have a context? 0x%p a cert? 0x%p\n",
2154296341Sdelphij                (void *)ctx, (void *)ctx->cert);
2155296341Sdelphij        if (ctx->cert)
2156296341Sdelphij            s = X509_NAME_oneline(X509_get_subject_name(ctx->cert), buf, 256);
2157296341Sdelphij        if (s != NULL) {
2158296341Sdelphij            fprintf(stderr, "cert depth=%d %s\n", ctx->error_depth, buf);
2159296341Sdelphij        }
2160296341Sdelphij        return (1);
2161296341Sdelphij    }
2162296341Sdelphij    if (cb_arg->proxy_auth) {
2163296341Sdelphij        int found_any = 0, i;
2164296341Sdelphij        char *sp;
2165109998Smarkm
2166296341Sdelphij        for (i = 0; i < 26; i++)
2167296341Sdelphij            letters[i] = 0;
2168296341Sdelphij        for (sp = cb_arg->proxy_auth; *sp; sp++) {
2169296341Sdelphij            int c = *sp;
2170296341Sdelphij            if (isascii(c) && isalpha(c)) {
2171296341Sdelphij                if (islower(c))
2172296341Sdelphij                    c = toupper(c);
2173296341Sdelphij                letters[c - 'A'] = 1;
2174296341Sdelphij            }
2175296341Sdelphij        }
2176160814Ssimon
2177296341Sdelphij        fprintf(stderr, "  Initial proxy rights = ");
2178296341Sdelphij        for (i = 0; i < 26; i++)
2179296341Sdelphij            if (letters[i]) {
2180296341Sdelphij                fprintf(stderr, "%c", i + 'A');
2181296341Sdelphij                found_any = 1;
2182296341Sdelphij            }
2183296341Sdelphij        if (!found_any)
2184296341Sdelphij            fprintf(stderr, "none");
2185296341Sdelphij        fprintf(stderr, "\n");
2186160814Ssimon
2187296341Sdelphij        X509_STORE_CTX_set_ex_data(ctx,
2188296341Sdelphij                                   get_proxy_auth_ex_data_idx(), letters);
2189296341Sdelphij    }
2190296341Sdelphij    if (cb_arg->allow_proxy_certs) {
2191296341Sdelphij        X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
2192296341Sdelphij    }
2193160814Ssimon#ifndef OPENSSL_NO_X509_VERIFY
2194296341Sdelphij    ok = X509_verify_cert(ctx);
2195160814Ssimon#endif
2196160814Ssimon
2197296341Sdelphij    if (cb_arg->proxy_auth) {
2198296341Sdelphij        if (ok > 0) {
2199296341Sdelphij            const char *cond_end = NULL;
2200160814Ssimon
2201296341Sdelphij            ok = process_proxy_cond(letters, cb_arg->proxy_cond, &cond_end);
2202160814Ssimon
2203296341Sdelphij            if (ok < 0)
2204296341Sdelphij                EXIT(3);
2205296341Sdelphij            if (*cond_end) {
2206296341Sdelphij                fprintf(stderr,
2207296341Sdelphij                        "Stopped processing condition before it's end.\n");
2208296341Sdelphij                ok = 0;
2209296341Sdelphij            }
2210296341Sdelphij            if (!ok)
2211296341Sdelphij                fprintf(stderr,
2212296341Sdelphij                        "Proxy rights check with condition '%s' proved invalid\n",
2213296341Sdelphij                        cb_arg->proxy_cond);
2214296341Sdelphij            else
2215296341Sdelphij                fprintf(stderr,
2216296341Sdelphij                        "Proxy rights check with condition '%s' proved valid\n",
2217296341Sdelphij                        cb_arg->proxy_cond);
2218296341Sdelphij        }
2219296341Sdelphij    }
2220296341Sdelphij    return (ok);
2221296341Sdelphij}
2222109998Smarkm
2223109998Smarkm#ifndef OPENSSL_NO_RSA
2224296341Sdelphijstatic RSA *rsa_tmp = NULL;
222568651Skris
222655714Skrisstatic RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength)
2227296341Sdelphij{
2228296341Sdelphij    BIGNUM *bn = NULL;
2229296341Sdelphij    if (rsa_tmp == NULL) {
2230296341Sdelphij        bn = BN_new();
2231296341Sdelphij        rsa_tmp = RSA_new();
2232296341Sdelphij        if (!bn || !rsa_tmp || !BN_set_word(bn, RSA_F4)) {
2233296341Sdelphij            BIO_printf(bio_err, "Memory error...");
2234296341Sdelphij            goto end;
2235296341Sdelphij        }
2236296341Sdelphij        BIO_printf(bio_err, "Generating temp (%d bit) RSA key...", keylength);
2237296341Sdelphij        (void)BIO_flush(bio_err);
2238296341Sdelphij        if (!RSA_generate_key_ex(rsa_tmp, keylength, bn, NULL)) {
2239296341Sdelphij            BIO_printf(bio_err, "Error generating key.");
2240296341Sdelphij            RSA_free(rsa_tmp);
2241296341Sdelphij            rsa_tmp = NULL;
2242296341Sdelphij        }
2243296341Sdelphij end:
2244296341Sdelphij        BIO_printf(bio_err, "\n");
2245296341Sdelphij        (void)BIO_flush(bio_err);
2246296341Sdelphij    }
2247296341Sdelphij    if (bn)
2248296341Sdelphij        BN_free(bn);
2249296341Sdelphij    return (rsa_tmp);
2250296341Sdelphij}
225168651Skris
225268651Skrisstatic void free_tmp_rsa(void)
2253296341Sdelphij{
2254296341Sdelphij    if (rsa_tmp != NULL) {
2255296341Sdelphij        RSA_free(rsa_tmp);
2256296341Sdelphij        rsa_tmp = NULL;
2257296341Sdelphij    }
2258296341Sdelphij}
225955714Skris#endif
226059191Skris
2261109998Smarkm#ifndef OPENSSL_NO_DH
2262296341Sdelphij/*-
2263296341Sdelphij * These DH parameters have been generated as follows:
226459191Skris *    $ openssl dhparam -C -noout 512
226559191Skris *    $ openssl dhparam -C -noout 1024
226659191Skris *    $ openssl dhparam -C -noout -dsaparam 1024
226759191Skris * (The third function has been renamed to avoid name conflicts.)
226859191Skris */
2269109998Smarkmstatic DH *get_dh512()
2270296341Sdelphij{
2271296341Sdelphij    static unsigned char dh512_p[] = {
2272296341Sdelphij        0xCB, 0xC8, 0xE1, 0x86, 0xD0, 0x1F, 0x94, 0x17, 0xA6, 0x99, 0xF0,
2273296341Sdelphij        0xC6,
2274296341Sdelphij        0x1F, 0x0D, 0xAC, 0xB6, 0x25, 0x3E, 0x06, 0x39, 0xCA, 0x72, 0x04,
2275296341Sdelphij        0xB0,
2276296341Sdelphij        0x6E, 0xDA, 0xC0, 0x61, 0xE6, 0x7A, 0x77, 0x25, 0xE8, 0x3B, 0xB9,
2277296341Sdelphij        0x5F,
2278296341Sdelphij        0x9A, 0xB6, 0xB5, 0xFE, 0x99, 0x0B, 0xA1, 0x93, 0x4E, 0x35, 0x33,
2279296341Sdelphij        0xB8,
2280296341Sdelphij        0xE1, 0xF1, 0x13, 0x4F, 0x59, 0x1A, 0xD2, 0x57, 0xC0, 0x26, 0x21,
2281296341Sdelphij        0x33,
2282296341Sdelphij        0x02, 0xC5, 0xAE, 0x23,
2283296341Sdelphij    };
2284296341Sdelphij    static unsigned char dh512_g[] = {
2285296341Sdelphij        0x02,
2286296341Sdelphij    };
2287296341Sdelphij    DH *dh;
228859191Skris
2289296341Sdelphij    if ((dh = DH_new()) == NULL)
2290296341Sdelphij        return (NULL);
2291296341Sdelphij    dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
2292296341Sdelphij    dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
2293296341Sdelphij    if ((dh->p == NULL) || (dh->g == NULL)) {
2294296341Sdelphij        DH_free(dh);
2295296341Sdelphij        return (NULL);
2296296341Sdelphij    }
2297296341Sdelphij    return (dh);
2298296341Sdelphij}
229959191Skris
2300109998Smarkmstatic DH *get_dh1024()
2301296341Sdelphij{
2302296341Sdelphij    static unsigned char dh1024_p[] = {
2303296341Sdelphij        0xF8, 0x81, 0x89, 0x7D, 0x14, 0x24, 0xC5, 0xD1, 0xE6, 0xF7, 0xBF,
2304296341Sdelphij        0x3A,
2305296341Sdelphij        0xE4, 0x90, 0xF4, 0xFC, 0x73, 0xFB, 0x34, 0xB5, 0xFA, 0x4C, 0x56,
2306296341Sdelphij        0xA2,
2307296341Sdelphij        0xEA, 0xA7, 0xE9, 0xC0, 0xC0, 0xCE, 0x89, 0xE1, 0xFA, 0x63, 0x3F,
2308296341Sdelphij        0xB0,
2309296341Sdelphij        0x6B, 0x32, 0x66, 0xF1, 0xD1, 0x7B, 0xB0, 0x00, 0x8F, 0xCA, 0x87,
2310296341Sdelphij        0xC2,
2311296341Sdelphij        0xAE, 0x98, 0x89, 0x26, 0x17, 0xC2, 0x05, 0xD2, 0xEC, 0x08, 0xD0,
2312296341Sdelphij        0x8C,
2313296341Sdelphij        0xFF, 0x17, 0x52, 0x8C, 0xC5, 0x07, 0x93, 0x03, 0xB1, 0xF6, 0x2F,
2314296341Sdelphij        0xB8,
2315296341Sdelphij        0x1C, 0x52, 0x47, 0x27, 0x1B, 0xDB, 0xD1, 0x8D, 0x9D, 0x69, 0x1D,
2316296341Sdelphij        0x52,
2317296341Sdelphij        0x4B, 0x32, 0x81, 0xAA, 0x7F, 0x00, 0xC8, 0xDC, 0xE6, 0xD9, 0xCC,
2318296341Sdelphij        0xC1,
2319296341Sdelphij        0x11, 0x2D, 0x37, 0x34, 0x6C, 0xEA, 0x02, 0x97, 0x4B, 0x0E, 0xBB,
2320296341Sdelphij        0xB1,
2321296341Sdelphij        0x71, 0x33, 0x09, 0x15, 0xFD, 0xDD, 0x23, 0x87, 0x07, 0x5E, 0x89,
2322296341Sdelphij        0xAB,
2323296341Sdelphij        0x6B, 0x7C, 0x5F, 0xEC, 0xA6, 0x24, 0xDC, 0x53,
2324296341Sdelphij    };
2325296341Sdelphij    static unsigned char dh1024_g[] = {
2326296341Sdelphij        0x02,
2327296341Sdelphij    };
2328296341Sdelphij    DH *dh;
232959191Skris
2330296341Sdelphij    if ((dh = DH_new()) == NULL)
2331296341Sdelphij        return (NULL);
2332296341Sdelphij    dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
2333296341Sdelphij    dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
2334296341Sdelphij    if ((dh->p == NULL) || (dh->g == NULL)) {
2335296341Sdelphij        DH_free(dh);
2336296341Sdelphij        return (NULL);
2337296341Sdelphij    }
2338296341Sdelphij    return (dh);
2339296341Sdelphij}
234059191Skris
2341109998Smarkmstatic DH *get_dh1024dsa()
2342296341Sdelphij{
2343296341Sdelphij    static unsigned char dh1024_p[] = {
2344296341Sdelphij        0xC8, 0x00, 0xF7, 0x08, 0x07, 0x89, 0x4D, 0x90, 0x53, 0xF3, 0xD5,
2345296341Sdelphij        0x00,
2346296341Sdelphij        0x21, 0x1B, 0xF7, 0x31, 0xA6, 0xA2, 0xDA, 0x23, 0x9A, 0xC7, 0x87,
2347296341Sdelphij        0x19,
2348296341Sdelphij        0x3B, 0x47, 0xB6, 0x8C, 0x04, 0x6F, 0xFF, 0xC6, 0x9B, 0xB8, 0x65,
2349296341Sdelphij        0xD2,
2350296341Sdelphij        0xC2, 0x5F, 0x31, 0x83, 0x4A, 0xA7, 0x5F, 0x2F, 0x88, 0x38, 0xB6,
2351296341Sdelphij        0x55,
2352296341Sdelphij        0xCF, 0xD9, 0x87, 0x6D, 0x6F, 0x9F, 0xDA, 0xAC, 0xA6, 0x48, 0xAF,
2353296341Sdelphij        0xFC,
2354296341Sdelphij        0x33, 0x84, 0x37, 0x5B, 0x82, 0x4A, 0x31, 0x5D, 0xE7, 0xBD, 0x52,
2355296341Sdelphij        0x97,
2356296341Sdelphij        0xA1, 0x77, 0xBF, 0x10, 0x9E, 0x37, 0xEA, 0x64, 0xFA, 0xCA, 0x28,
2357296341Sdelphij        0x8D,
2358296341Sdelphij        0x9D, 0x3B, 0xD2, 0x6E, 0x09, 0x5C, 0x68, 0xC7, 0x45, 0x90, 0xFD,
2359296341Sdelphij        0xBB,
2360296341Sdelphij        0x70, 0xC9, 0x3A, 0xBB, 0xDF, 0xD4, 0x21, 0x0F, 0xC4, 0x6A, 0x3C,
2361296341Sdelphij        0xF6,
2362296341Sdelphij        0x61, 0xCF, 0x3F, 0xD6, 0x13, 0xF1, 0x5F, 0xBC, 0xCF, 0xBC, 0x26,
2363296341Sdelphij        0x9E,
2364296341Sdelphij        0xBC, 0x0B, 0xBD, 0xAB, 0x5D, 0xC9, 0x54, 0x39,
2365296341Sdelphij    };
2366296341Sdelphij    static unsigned char dh1024_g[] = {
2367296341Sdelphij        0x3B, 0x40, 0x86, 0xE7, 0xF3, 0x6C, 0xDE, 0x67, 0x1C, 0xCC, 0x80,
2368296341Sdelphij        0x05,
2369296341Sdelphij        0x5A, 0xDF, 0xFE, 0xBD, 0x20, 0x27, 0x74, 0x6C, 0x24, 0xC9, 0x03,
2370296341Sdelphij        0xF3,
2371296341Sdelphij        0xE1, 0x8D, 0xC3, 0x7D, 0x98, 0x27, 0x40, 0x08, 0xB8, 0x8C, 0x6A,
2372296341Sdelphij        0xE9,
2373296341Sdelphij        0xBB, 0x1A, 0x3A, 0xD6, 0x86, 0x83, 0x5E, 0x72, 0x41, 0xCE, 0x85,
2374296341Sdelphij        0x3C,
2375296341Sdelphij        0xD2, 0xB3, 0xFC, 0x13, 0xCE, 0x37, 0x81, 0x9E, 0x4C, 0x1C, 0x7B,
2376296341Sdelphij        0x65,
2377296341Sdelphij        0xD3, 0xE6, 0xA6, 0x00, 0xF5, 0x5A, 0x95, 0x43, 0x5E, 0x81, 0xCF,
2378296341Sdelphij        0x60,
2379296341Sdelphij        0xA2, 0x23, 0xFC, 0x36, 0xA7, 0x5D, 0x7A, 0x4C, 0x06, 0x91, 0x6E,
2380296341Sdelphij        0xF6,
2381296341Sdelphij        0x57, 0xEE, 0x36, 0xCB, 0x06, 0xEA, 0xF5, 0x3D, 0x95, 0x49, 0xCB,
2382296341Sdelphij        0xA7,
2383296341Sdelphij        0xDD, 0x81, 0xDF, 0x80, 0x09, 0x4A, 0x97, 0x4D, 0xA8, 0x22, 0x72,
2384296341Sdelphij        0xA1,
2385296341Sdelphij        0x7F, 0xC4, 0x70, 0x56, 0x70, 0xE8, 0x20, 0x10, 0x18, 0x8F, 0x2E,
2386296341Sdelphij        0x60,
2387296341Sdelphij        0x07, 0xE7, 0x68, 0x1A, 0x82, 0x5D, 0x32, 0xA2,
2388296341Sdelphij    };
2389296341Sdelphij    DH *dh;
239059191Skris
2391296341Sdelphij    if ((dh = DH_new()) == NULL)
2392296341Sdelphij        return (NULL);
2393296341Sdelphij    dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
2394296341Sdelphij    dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
2395296341Sdelphij    if ((dh->p == NULL) || (dh->g == NULL)) {
2396296341Sdelphij        DH_free(dh);
2397296341Sdelphij        return (NULL);
2398296341Sdelphij    }
2399296341Sdelphij    dh->length = 160;
2400296341Sdelphij    return (dh);
2401296341Sdelphij}
240259191Skris#endif
2403160814Ssimon
2404238405Sjkim#ifndef OPENSSL_NO_PSK
2405238405Sjkim/* convert the PSK key (psk_key) in ascii to binary (psk) */
2406238405Sjkimstatic int psk_key2bn(const char *pskkey, unsigned char *psk,
2407296341Sdelphij                      unsigned int max_psk_len)
2408296341Sdelphij{
2409296341Sdelphij    int ret;
2410296341Sdelphij    BIGNUM *bn = NULL;
2411238405Sjkim
2412296341Sdelphij    ret = BN_hex2bn(&bn, pskkey);
2413296341Sdelphij    if (!ret) {
2414296341Sdelphij        BIO_printf(bio_err, "Could not convert PSK key '%s' to BIGNUM\n",
2415296341Sdelphij                   pskkey);
2416296341Sdelphij        if (bn)
2417296341Sdelphij            BN_free(bn);
2418296341Sdelphij        return 0;
2419296341Sdelphij    }
2420296341Sdelphij    if (BN_num_bytes(bn) > (int)max_psk_len) {
2421296341Sdelphij        BIO_printf(bio_err,
2422296341Sdelphij                   "psk buffer of callback is too small (%d) for key (%d)\n",
2423296341Sdelphij                   max_psk_len, BN_num_bytes(bn));
2424296341Sdelphij        BN_free(bn);
2425296341Sdelphij        return 0;
2426296341Sdelphij    }
2427296341Sdelphij    ret = BN_bn2bin(bn, psk);
2428296341Sdelphij    BN_free(bn);
2429296341Sdelphij    return ret;
2430296341Sdelphij}
2431238405Sjkim
2432296341Sdelphijstatic unsigned int psk_client_callback(SSL *ssl, const char *hint,
2433296341Sdelphij                                        char *identity,
2434296341Sdelphij                                        unsigned int max_identity_len,
2435296341Sdelphij                                        unsigned char *psk,
2436296341Sdelphij                                        unsigned int max_psk_len)
2437296341Sdelphij{
2438296341Sdelphij    int ret;
2439296341Sdelphij    unsigned int psk_len = 0;
2440238405Sjkim
2441296341Sdelphij    ret = BIO_snprintf(identity, max_identity_len, "Client_identity");
2442296341Sdelphij    if (ret < 0)
2443296341Sdelphij        goto out_err;
2444296341Sdelphij    if (debug)
2445296341Sdelphij        fprintf(stderr, "client: created identity '%s' len=%d\n", identity,
2446296341Sdelphij                ret);
2447296341Sdelphij    ret = psk_key2bn(psk_key, psk, max_psk_len);
2448296341Sdelphij    if (ret < 0)
2449296341Sdelphij        goto out_err;
2450296341Sdelphij    psk_len = ret;
2451296341Sdelphij out_err:
2452296341Sdelphij    return psk_len;
2453296341Sdelphij}
2454238405Sjkim
2455238405Sjkimstatic unsigned int psk_server_callback(SSL *ssl, const char *identity,
2456296341Sdelphij                                        unsigned char *psk,
2457296341Sdelphij                                        unsigned int max_psk_len)
2458296341Sdelphij{
2459296341Sdelphij    unsigned int psk_len = 0;
2460238405Sjkim
2461296341Sdelphij    if (strcmp(identity, "Client_identity") != 0) {
2462296341Sdelphij        BIO_printf(bio_err, "server: PSK error: client identity not found\n");
2463296341Sdelphij        return 0;
2464296341Sdelphij    }
2465296341Sdelphij    psk_len = psk_key2bn(psk_key, psk, max_psk_len);
2466296341Sdelphij    return psk_len;
2467296341Sdelphij}
2468238405Sjkim#endif
2469238405Sjkim
2470160814Ssimonstatic int do_test_cipherlist(void)
2471296341Sdelphij{
2472296341Sdelphij    int i = 0;
2473296341Sdelphij    const SSL_METHOD *meth;
2474296341Sdelphij    const SSL_CIPHER *ci, *tci = NULL;
2475160814Ssimon
2476160814Ssimon#ifndef OPENSSL_NO_SSL2
2477296341Sdelphij    fprintf(stderr, "testing SSLv2 cipher list order: ");
2478296341Sdelphij    meth = SSLv2_method();
2479296341Sdelphij    while ((ci = meth->get_cipher(i++)) != NULL) {
2480296341Sdelphij        if (tci != NULL)
2481296341Sdelphij            if (ci->id >= tci->id) {
2482296341Sdelphij                fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
2483296341Sdelphij                return 0;
2484296341Sdelphij            }
2485296341Sdelphij        tci = ci;
2486296341Sdelphij    }
2487296341Sdelphij    fprintf(stderr, "ok\n");
2488160814Ssimon#endif
2489160814Ssimon#ifndef OPENSSL_NO_SSL3
2490296341Sdelphij    fprintf(stderr, "testing SSLv3 cipher list order: ");
2491296341Sdelphij    meth = SSLv3_method();
2492296341Sdelphij    tci = NULL;
2493296341Sdelphij    while ((ci = meth->get_cipher(i++)) != NULL) {
2494296341Sdelphij        if (tci != NULL)
2495296341Sdelphij            if (ci->id >= tci->id) {
2496296341Sdelphij                fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
2497296341Sdelphij                return 0;
2498296341Sdelphij            }
2499296341Sdelphij        tci = ci;
2500296341Sdelphij    }
2501296341Sdelphij    fprintf(stderr, "ok\n");
2502160814Ssimon#endif
2503160814Ssimon#ifndef OPENSSL_NO_TLS1
2504296341Sdelphij    fprintf(stderr, "testing TLSv1 cipher list order: ");
2505296341Sdelphij    meth = TLSv1_method();
2506296341Sdelphij    tci = NULL;
2507296341Sdelphij    while ((ci = meth->get_cipher(i++)) != NULL) {
2508296341Sdelphij        if (tci != NULL)
2509296341Sdelphij            if (ci->id >= tci->id) {
2510296341Sdelphij                fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
2511296341Sdelphij                return 0;
2512296341Sdelphij            }
2513296341Sdelphij        tci = ci;
2514296341Sdelphij    }
2515296341Sdelphij    fprintf(stderr, "ok\n");
2516160814Ssimon#endif
2517160814Ssimon
2518296341Sdelphij    return 1;
2519296341Sdelphij}
2520