xref: /onnv-gate/usr/src/common/openssl/ssl/ssltest.c (revision 8545:a1b3fd5884fd)
10Sstevel@tonic-gate /* ssl/ssltest.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate  * All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * This package is an SSL implementation written
60Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
110Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
130Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate  * the code are not to be removed.
180Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate  * as the author of the parts of the library used.
200Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate  * are met:
260Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate  *    must display the following acknowledgement:
330Sstevel@tonic-gate  *    "This product includes cryptographic software written by
340Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate  *    being used are not cryptographic related :-).
370Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate  *
410Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate  * SUCH DAMAGE.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
550Sstevel@tonic-gate  * copied and put under another distribution licence
560Sstevel@tonic-gate  * [including the GNU Public Licence.]
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate /* ====================================================================
590Sstevel@tonic-gate  * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
600Sstevel@tonic-gate  *
610Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
620Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
630Sstevel@tonic-gate  * are met:
640Sstevel@tonic-gate  *
650Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
660Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
690Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
700Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
710Sstevel@tonic-gate  *    distribution.
720Sstevel@tonic-gate  *
730Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
740Sstevel@tonic-gate  *    software must display the following acknowledgment:
750Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
760Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
770Sstevel@tonic-gate  *
780Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
790Sstevel@tonic-gate  *    endorse or promote products derived from this software without
800Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
810Sstevel@tonic-gate  *    openssl-core@openssl.org.
820Sstevel@tonic-gate  *
830Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
840Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
850Sstevel@tonic-gate  *    permission of the OpenSSL Project.
860Sstevel@tonic-gate  *
870Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
880Sstevel@tonic-gate  *    acknowledgment:
890Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
900Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
910Sstevel@tonic-gate  *
920Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
930Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
940Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
950Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
960Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
970Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
980Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
990Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1000Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1010Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1020Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
1030Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
1040Sstevel@tonic-gate  * ====================================================================
1050Sstevel@tonic-gate  *
1060Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
1070Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
1080Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
1090Sstevel@tonic-gate  *
1100Sstevel@tonic-gate  */
1112139Sjp161948 /* ====================================================================
1122139Sjp161948  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
1132139Sjp161948  * ECC cipher suite support in OpenSSL originally developed by
1142139Sjp161948  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
1152139Sjp161948  */
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate #define _BSD_SOURCE 1		/* Or gethostname won't be declared properly
1180Sstevel@tonic-gate 				   on Linux and GNU platforms. */
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate #include <assert.h>
1210Sstevel@tonic-gate #include <errno.h>
1220Sstevel@tonic-gate #include <limits.h>
1230Sstevel@tonic-gate #include <stdio.h>
1240Sstevel@tonic-gate #include <stdlib.h>
1250Sstevel@tonic-gate #include <string.h>
1260Sstevel@tonic-gate #include <time.h>
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate #define USE_SOCKETS
1290Sstevel@tonic-gate #include "e_os.h"
1300Sstevel@tonic-gate 
1312139Sjp161948 #define _XOPEN_SOURCE 500	/* Or isascii won't be declared properly on
1322139Sjp161948 				   VMS (at least with DECompHP C).  */
1332139Sjp161948 #include <ctype.h>
1342139Sjp161948 
1350Sstevel@tonic-gate #include <openssl/bio.h>
1360Sstevel@tonic-gate #include <openssl/crypto.h>
1370Sstevel@tonic-gate #include <openssl/evp.h>
1380Sstevel@tonic-gate #include <openssl/x509.h>
1392139Sjp161948 #include <openssl/x509v3.h>
1400Sstevel@tonic-gate #include <openssl/ssl.h>
1410Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
1420Sstevel@tonic-gate #include <openssl/engine.h>
1430Sstevel@tonic-gate #endif
1440Sstevel@tonic-gate #include <openssl/err.h>
1450Sstevel@tonic-gate #include <openssl/rand.h>
1462139Sjp161948 #ifndef OPENSSL_NO_RSA
1472139Sjp161948 #include <openssl/rsa.h>
1482139Sjp161948 #endif
1492139Sjp161948 #ifndef OPENSSL_NO_DSA
1502139Sjp161948 #include <openssl/dsa.h>
1512139Sjp161948 #endif
1522139Sjp161948 #ifndef OPENSSL_NO_DH
1532139Sjp161948 #include <openssl/dh.h>
1542139Sjp161948 #endif
1552139Sjp161948 #include <openssl/bn.h>
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate #define _XOPEN_SOURCE_EXTENDED	1 /* Or gethostname won't be declared properly
1580Sstevel@tonic-gate 				     on Compaq platforms (at least with DEC C).
1590Sstevel@tonic-gate 				     Do not try to put it earlier, or IPv6 includes
1600Sstevel@tonic-gate 				     get screwed...
1610Sstevel@tonic-gate 				  */
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS
1640Sstevel@tonic-gate #include <winsock.h>
1650Sstevel@tonic-gate #else
1660Sstevel@tonic-gate #include OPENSSL_UNISTD
1670Sstevel@tonic-gate #endif
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
1700Sstevel@tonic-gate #  define TEST_SERVER_CERT "SYS$DISK:[-.APPS]SERVER.PEM"
1710Sstevel@tonic-gate #  define TEST_CLIENT_CERT "SYS$DISK:[-.APPS]CLIENT.PEM"
1720Sstevel@tonic-gate #elif defined(OPENSSL_SYS_WINCE)
1730Sstevel@tonic-gate #  define TEST_SERVER_CERT "\\OpenSSL\\server.pem"
1740Sstevel@tonic-gate #  define TEST_CLIENT_CERT "\\OpenSSL\\client.pem"
1752139Sjp161948 #elif defined(OPENSSL_SYS_NETWARE)
1762139Sjp161948 #  define TEST_SERVER_CERT "\\openssl\\apps\\server.pem"
1772139Sjp161948 #  define TEST_CLIENT_CERT "\\openssl\\apps\\client.pem"
1780Sstevel@tonic-gate #else
1790Sstevel@tonic-gate #  define TEST_SERVER_CERT "../apps/server.pem"
1800Sstevel@tonic-gate #  define TEST_CLIENT_CERT "../apps/client.pem"
1810Sstevel@tonic-gate #endif
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate /* There is really no standard for this, so let's assign some tentative
1840Sstevel@tonic-gate    numbers.  In any case, these numbers are only for this test */
1852139Sjp161948 #define COMP_RLE	255
1862139Sjp161948 #define COMP_ZLIB	1
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
1890Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
1900Sstevel@tonic-gate static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export,int keylength);
1910Sstevel@tonic-gate static void free_tmp_rsa(void);
1920Sstevel@tonic-gate #endif
1930Sstevel@tonic-gate static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg);
1942139Sjp161948 #define APP_CALLBACK_STRING "Test Callback Argument"
1952139Sjp161948 struct app_verify_arg
1962139Sjp161948 	{
1972139Sjp161948 	char *string;
1982139Sjp161948 	int app_verify;
1992139Sjp161948 	int allow_proxy_certs;
2002139Sjp161948 	char *proxy_auth;
2012139Sjp161948 	char *proxy_cond;
2022139Sjp161948 	};
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
2050Sstevel@tonic-gate static DH *get_dh512(void);
2060Sstevel@tonic-gate static DH *get_dh1024(void);
2070Sstevel@tonic-gate static DH *get_dh1024dsa(void);
2080Sstevel@tonic-gate #endif
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate static BIO *bio_err=NULL;
2110Sstevel@tonic-gate static BIO *bio_stdout=NULL;
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate static char *cipher=NULL;
2140Sstevel@tonic-gate static int verbose=0;
2150Sstevel@tonic-gate static int debug=0;
2160Sstevel@tonic-gate #if 0
2170Sstevel@tonic-gate /* Not used yet. */
2180Sstevel@tonic-gate #ifdef FIONBIO
2190Sstevel@tonic-gate static int s_nbio=0;
2200Sstevel@tonic-gate #endif
2210Sstevel@tonic-gate #endif
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate static const char rnd_seed[] = "string to make the random number generator think it has entropy";
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate int doit_biopair(SSL *s_ssl,SSL *c_ssl,long bytes,clock_t *s_time,clock_t *c_time);
2260Sstevel@tonic-gate int doit(SSL *s_ssl,SSL *c_ssl,long bytes);
2272139Sjp161948 static int do_test_cipherlist(void);
sv_usage(void)2280Sstevel@tonic-gate static void sv_usage(void)
2290Sstevel@tonic-gate 	{
2300Sstevel@tonic-gate 	fprintf(stderr,"usage: ssltest [args ...]\n");
2310Sstevel@tonic-gate 	fprintf(stderr,"\n");
2320Sstevel@tonic-gate 	fprintf(stderr," -server_auth  - check server certificate\n");
2330Sstevel@tonic-gate 	fprintf(stderr," -client_auth  - do client authentication\n");
2342139Sjp161948 	fprintf(stderr," -proxy        - allow proxy certificates\n");
2352139Sjp161948 	fprintf(stderr," -proxy_auth <val> - set proxy policy rights\n");
2362139Sjp161948 	fprintf(stderr," -proxy_cond <val> - experssion to test proxy policy rights\n");
2370Sstevel@tonic-gate 	fprintf(stderr," -v            - more output\n");
2380Sstevel@tonic-gate 	fprintf(stderr," -d            - debug output\n");
2390Sstevel@tonic-gate 	fprintf(stderr," -reuse        - use session-id reuse\n");
2400Sstevel@tonic-gate 	fprintf(stderr," -num <val>    - number of connections to perform\n");
2410Sstevel@tonic-gate 	fprintf(stderr," -bytes <val>  - number of bytes to swap between client/server\n");
2420Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
2430Sstevel@tonic-gate 	fprintf(stderr," -dhe1024      - use 1024 bit key (safe prime) for DHE\n");
2440Sstevel@tonic-gate 	fprintf(stderr," -dhe1024dsa   - use 1024 bit key (with 160-bit subprime) for DHE\n");
2450Sstevel@tonic-gate 	fprintf(stderr," -no_dhe       - disable DHE\n");
2460Sstevel@tonic-gate #endif
2472139Sjp161948 #ifndef OPENSSL_NO_ECDH
2482139Sjp161948 	fprintf(stderr," -no_ecdhe     - disable ECDHE\n");
2492139Sjp161948 #endif
2500Sstevel@tonic-gate #ifndef OPENSSL_NO_SSL2
2510Sstevel@tonic-gate 	fprintf(stderr," -ssl2         - use SSLv2\n");
2520Sstevel@tonic-gate #endif
2530Sstevel@tonic-gate #ifndef OPENSSL_NO_SSL3
2540Sstevel@tonic-gate 	fprintf(stderr," -ssl3         - use SSLv3\n");
2550Sstevel@tonic-gate #endif
2560Sstevel@tonic-gate #ifndef OPENSSL_NO_TLS1
2570Sstevel@tonic-gate 	fprintf(stderr," -tls1         - use TLSv1\n");
2580Sstevel@tonic-gate #endif
2590Sstevel@tonic-gate 	fprintf(stderr," -CApath arg   - PEM format directory of CA's\n");
2600Sstevel@tonic-gate 	fprintf(stderr," -CAfile arg   - PEM format file of CA's\n");
2610Sstevel@tonic-gate 	fprintf(stderr," -cert arg     - Server certificate file\n");
2620Sstevel@tonic-gate 	fprintf(stderr," -key arg      - Server key file (default: same as -cert)\n");
2630Sstevel@tonic-gate 	fprintf(stderr," -c_cert arg   - Client certificate file\n");
2640Sstevel@tonic-gate 	fprintf(stderr," -c_key arg    - Client key file (default: same as -c_cert)\n");
2650Sstevel@tonic-gate 	fprintf(stderr," -cipher arg   - The cipher list\n");
2660Sstevel@tonic-gate 	fprintf(stderr," -bio_pair     - Use BIO pairs\n");
2670Sstevel@tonic-gate 	fprintf(stderr," -f            - Test even cases that can't work\n");
2680Sstevel@tonic-gate 	fprintf(stderr," -time         - measure processor time used by client and server\n");
2690Sstevel@tonic-gate 	fprintf(stderr," -zlib         - use zlib compression\n");
2702139Sjp161948 	fprintf(stderr," -rle          - use rle compression\n");
2712139Sjp161948 #ifndef OPENSSL_NO_ECDH
2722139Sjp161948 	fprintf(stderr," -named_curve arg  - Elliptic curve name to use for ephemeral ECDH keys.\n" \
2732139Sjp161948 	               "                 Use \"openssl ecparam -list_curves\" for all names\n"  \
2742139Sjp161948 	               "                 (default is sect163r2).\n");
2752139Sjp161948 #endif
2762139Sjp161948 	fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n");
2770Sstevel@tonic-gate 	}
2780Sstevel@tonic-gate 
print_details(SSL * c_ssl,const char * prefix)2790Sstevel@tonic-gate static void print_details(SSL *c_ssl, const char *prefix)
2800Sstevel@tonic-gate 	{
2810Sstevel@tonic-gate 	SSL_CIPHER *ciph;
2820Sstevel@tonic-gate 	X509 *cert;
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	ciph=SSL_get_current_cipher(c_ssl);
2850Sstevel@tonic-gate 	BIO_printf(bio_stdout,"%s%s, cipher %s %s",
2860Sstevel@tonic-gate 		prefix,
2870Sstevel@tonic-gate 		SSL_get_version(c_ssl),
2880Sstevel@tonic-gate 		SSL_CIPHER_get_version(ciph),
2890Sstevel@tonic-gate 		SSL_CIPHER_get_name(ciph));
2900Sstevel@tonic-gate 	cert=SSL_get_peer_certificate(c_ssl);
2910Sstevel@tonic-gate 	if (cert != NULL)
2920Sstevel@tonic-gate 		{
2930Sstevel@tonic-gate 		EVP_PKEY *pkey = X509_get_pubkey(cert);
2940Sstevel@tonic-gate 		if (pkey != NULL)
2950Sstevel@tonic-gate 			{
2960Sstevel@tonic-gate 			if (0)
2970Sstevel@tonic-gate 				;
2980Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
2990Sstevel@tonic-gate 			else if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL
3000Sstevel@tonic-gate 				&& pkey->pkey.rsa->n != NULL)
3010Sstevel@tonic-gate 				{
3020Sstevel@tonic-gate 				BIO_printf(bio_stdout, ", %d bit RSA",
3030Sstevel@tonic-gate 					BN_num_bits(pkey->pkey.rsa->n));
3040Sstevel@tonic-gate 				}
3050Sstevel@tonic-gate #endif
3060Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
3070Sstevel@tonic-gate 			else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL
3080Sstevel@tonic-gate 				&& pkey->pkey.dsa->p != NULL)
3090Sstevel@tonic-gate 				{
3100Sstevel@tonic-gate 				BIO_printf(bio_stdout, ", %d bit DSA",
3110Sstevel@tonic-gate 					BN_num_bits(pkey->pkey.dsa->p));
3120Sstevel@tonic-gate 				}
3130Sstevel@tonic-gate #endif
3140Sstevel@tonic-gate 			EVP_PKEY_free(pkey);
3150Sstevel@tonic-gate 			}
3160Sstevel@tonic-gate 		X509_free(cert);
3170Sstevel@tonic-gate 		}
3180Sstevel@tonic-gate 	/* The SSL API does not allow us to look at temporary RSA/DH keys,
3190Sstevel@tonic-gate 	 * otherwise we should print their lengths too */
3200Sstevel@tonic-gate 	BIO_printf(bio_stdout,"\n");
3210Sstevel@tonic-gate 	}
3220Sstevel@tonic-gate 
lock_dbg_cb(int mode,int type,const char * file,int line)3230Sstevel@tonic-gate static void lock_dbg_cb(int mode, int type, const char *file, int line)
3240Sstevel@tonic-gate 	{
3250Sstevel@tonic-gate 	static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
3260Sstevel@tonic-gate 	const char *errstr = NULL;
3270Sstevel@tonic-gate 	int rw;
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	rw = mode & (CRYPTO_READ|CRYPTO_WRITE);
3300Sstevel@tonic-gate 	if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE)))
3310Sstevel@tonic-gate 		{
3320Sstevel@tonic-gate 		errstr = "invalid mode";
3330Sstevel@tonic-gate 		goto err;
3340Sstevel@tonic-gate 		}
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	if (type < 0 || type >= CRYPTO_NUM_LOCKS)
3370Sstevel@tonic-gate 		{
3380Sstevel@tonic-gate 		errstr = "type out of bounds";
3390Sstevel@tonic-gate 		goto err;
3400Sstevel@tonic-gate 		}
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	if (mode & CRYPTO_LOCK)
3430Sstevel@tonic-gate 		{
3440Sstevel@tonic-gate 		if (modes[type])
3450Sstevel@tonic-gate 			{
3460Sstevel@tonic-gate 			errstr = "already locked";
3470Sstevel@tonic-gate 			/* must not happen in a single-threaded program
3480Sstevel@tonic-gate 			 * (would deadlock) */
3490Sstevel@tonic-gate 			goto err;
3500Sstevel@tonic-gate 			}
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 		modes[type] = rw;
3530Sstevel@tonic-gate 		}
3540Sstevel@tonic-gate 	else if (mode & CRYPTO_UNLOCK)
3550Sstevel@tonic-gate 		{
3560Sstevel@tonic-gate 		if (!modes[type])
3570Sstevel@tonic-gate 			{
3580Sstevel@tonic-gate 			errstr = "not locked";
3590Sstevel@tonic-gate 			goto err;
3600Sstevel@tonic-gate 			}
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 		if (modes[type] != rw)
3630Sstevel@tonic-gate 			{
3640Sstevel@tonic-gate 			errstr = (rw == CRYPTO_READ) ?
3650Sstevel@tonic-gate 				"CRYPTO_r_unlock on write lock" :
3660Sstevel@tonic-gate 				"CRYPTO_w_unlock on read lock";
3670Sstevel@tonic-gate 			}
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 		modes[type] = 0;
3700Sstevel@tonic-gate 		}
3710Sstevel@tonic-gate 	else
3720Sstevel@tonic-gate 		{
3730Sstevel@tonic-gate 		errstr = "invalid mode";
3740Sstevel@tonic-gate 		goto err;
3750Sstevel@tonic-gate 		}
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate  err:
3780Sstevel@tonic-gate 	if (errstr)
3790Sstevel@tonic-gate 		{
3800Sstevel@tonic-gate 		/* we cannot use bio_err here */
3810Sstevel@tonic-gate 		fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
3820Sstevel@tonic-gate 			errstr, mode, type, file, line);
3830Sstevel@tonic-gate 		}
3840Sstevel@tonic-gate 	}
3850Sstevel@tonic-gate 
3862139Sjp161948 
main(int argc,char * argv[])3870Sstevel@tonic-gate int main(int argc, char *argv[])
3880Sstevel@tonic-gate 	{
3890Sstevel@tonic-gate 	char *CApath=NULL,*CAfile=NULL;
3900Sstevel@tonic-gate 	int badop=0;
3910Sstevel@tonic-gate 	int bio_pair=0;
3920Sstevel@tonic-gate 	int force=0;
3930Sstevel@tonic-gate 	int tls1=0,ssl2=0,ssl3=0,ret=1;
3940Sstevel@tonic-gate 	int client_auth=0;
3950Sstevel@tonic-gate 	int server_auth=0,i;
3962139Sjp161948 	struct app_verify_arg app_verify_arg =
3972139Sjp161948 		{ APP_CALLBACK_STRING, 0, 0, NULL, NULL };
3980Sstevel@tonic-gate 	char *server_cert=TEST_SERVER_CERT;
3990Sstevel@tonic-gate 	char *server_key=NULL;
4000Sstevel@tonic-gate 	char *client_cert=TEST_CLIENT_CERT;
4010Sstevel@tonic-gate 	char *client_key=NULL;
4022139Sjp161948 #ifndef OPENSSL_NO_ECDH
4032139Sjp161948 	char *named_curve = NULL;
4042139Sjp161948 #endif
4050Sstevel@tonic-gate 	SSL_CTX *s_ctx=NULL;
4060Sstevel@tonic-gate 	SSL_CTX *c_ctx=NULL;
4070Sstevel@tonic-gate 	SSL_METHOD *meth=NULL;
4080Sstevel@tonic-gate 	SSL *c_ssl,*s_ssl;
4090Sstevel@tonic-gate 	int number=1,reuse=0;
4102139Sjp161948 	long bytes=256L;
4110Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
4120Sstevel@tonic-gate 	DH *dh;
4130Sstevel@tonic-gate 	int dhe1024 = 0, dhe1024dsa = 0;
4140Sstevel@tonic-gate #endif
4152139Sjp161948 #ifndef OPENSSL_NO_ECDH
4162139Sjp161948 	EC_KEY *ecdh = NULL;
4172139Sjp161948 #endif
4180Sstevel@tonic-gate 	int no_dhe = 0;
4192139Sjp161948 	int no_ecdhe = 0;
4200Sstevel@tonic-gate 	int print_time = 0;
4210Sstevel@tonic-gate 	clock_t s_time = 0, c_time = 0;
4220Sstevel@tonic-gate 	int comp = 0;
4232139Sjp161948 #ifndef OPENSSL_NO_COMP
4240Sstevel@tonic-gate 	COMP_METHOD *cm = NULL;
4252139Sjp161948 #endif
4262139Sjp161948 	STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
4272139Sjp161948 	int test_cipherlist = 0;
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	verbose = 0;
4300Sstevel@tonic-gate 	debug = 0;
4310Sstevel@tonic-gate 	cipher = 0;
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	CRYPTO_set_locking_callback(lock_dbg_cb);
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	/* enable memory leak checking unless explicitly disabled */
4380Sstevel@tonic-gate 	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
4390Sstevel@tonic-gate 		{
4400Sstevel@tonic-gate 		CRYPTO_malloc_debug_init();
4410Sstevel@tonic-gate 		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
4420Sstevel@tonic-gate 		}
4430Sstevel@tonic-gate 	else
4440Sstevel@tonic-gate 		{
4450Sstevel@tonic-gate 		/* OPENSSL_DEBUG_MEMORY=off */
4460Sstevel@tonic-gate 		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
4470Sstevel@tonic-gate 		}
4480Sstevel@tonic-gate 	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	RAND_seed(rnd_seed, sizeof rnd_seed);
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE);
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 	argc--;
4550Sstevel@tonic-gate 	argv++;
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	while (argc >= 1)
4580Sstevel@tonic-gate 		{
4590Sstevel@tonic-gate 		if	(strcmp(*argv,"-server_auth") == 0)
4600Sstevel@tonic-gate 			server_auth=1;
4610Sstevel@tonic-gate 		else if	(strcmp(*argv,"-client_auth") == 0)
4620Sstevel@tonic-gate 			client_auth=1;
4632139Sjp161948 		else if (strcmp(*argv,"-proxy_auth") == 0)
4642139Sjp161948 			{
4652139Sjp161948 			if (--argc < 1) goto bad;
4662139Sjp161948 			app_verify_arg.proxy_auth= *(++argv);
4672139Sjp161948 			}
4682139Sjp161948 		else if (strcmp(*argv,"-proxy_cond") == 0)
4692139Sjp161948 			{
4702139Sjp161948 			if (--argc < 1) goto bad;
4712139Sjp161948 			app_verify_arg.proxy_cond= *(++argv);
4722139Sjp161948 			}
4730Sstevel@tonic-gate 		else if	(strcmp(*argv,"-v") == 0)
4740Sstevel@tonic-gate 			verbose=1;
4750Sstevel@tonic-gate 		else if	(strcmp(*argv,"-d") == 0)
4760Sstevel@tonic-gate 			debug=1;
4770Sstevel@tonic-gate 		else if	(strcmp(*argv,"-reuse") == 0)
4780Sstevel@tonic-gate 			reuse=1;
4790Sstevel@tonic-gate 		else if	(strcmp(*argv,"-dhe1024") == 0)
4800Sstevel@tonic-gate 			{
4810Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
4820Sstevel@tonic-gate 			dhe1024=1;
4830Sstevel@tonic-gate #else
4840Sstevel@tonic-gate 			fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n");
4850Sstevel@tonic-gate #endif
4860Sstevel@tonic-gate 			}
4870Sstevel@tonic-gate 		else if	(strcmp(*argv,"-dhe1024dsa") == 0)
4880Sstevel@tonic-gate 			{
4890Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
4900Sstevel@tonic-gate 			dhe1024dsa=1;
4910Sstevel@tonic-gate #else
4920Sstevel@tonic-gate 			fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n");
4930Sstevel@tonic-gate #endif
4940Sstevel@tonic-gate 			}
4950Sstevel@tonic-gate 		else if	(strcmp(*argv,"-no_dhe") == 0)
4960Sstevel@tonic-gate 			no_dhe=1;
4972139Sjp161948 		else if	(strcmp(*argv,"-no_ecdhe") == 0)
4982139Sjp161948 			no_ecdhe=1;
4990Sstevel@tonic-gate 		else if	(strcmp(*argv,"-ssl2") == 0)
5000Sstevel@tonic-gate 			ssl2=1;
5010Sstevel@tonic-gate 		else if	(strcmp(*argv,"-tls1") == 0)
5020Sstevel@tonic-gate 			tls1=1;
5030Sstevel@tonic-gate 		else if	(strcmp(*argv,"-ssl3") == 0)
5040Sstevel@tonic-gate 			ssl3=1;
5050Sstevel@tonic-gate 		else if	(strncmp(*argv,"-num",4) == 0)
5060Sstevel@tonic-gate 			{
5070Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5080Sstevel@tonic-gate 			number= atoi(*(++argv));
5090Sstevel@tonic-gate 			if (number == 0) number=1;
5100Sstevel@tonic-gate 			}
5110Sstevel@tonic-gate 		else if	(strcmp(*argv,"-bytes") == 0)
5120Sstevel@tonic-gate 			{
5130Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5140Sstevel@tonic-gate 			bytes= atol(*(++argv));
5150Sstevel@tonic-gate 			if (bytes == 0L) bytes=1L;
5160Sstevel@tonic-gate 			i=strlen(argv[0]);
5170Sstevel@tonic-gate 			if (argv[0][i-1] == 'k') bytes*=1024L;
5180Sstevel@tonic-gate 			if (argv[0][i-1] == 'm') bytes*=1024L*1024L;
5190Sstevel@tonic-gate 			}
5200Sstevel@tonic-gate 		else if	(strcmp(*argv,"-cert") == 0)
5210Sstevel@tonic-gate 			{
5220Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5230Sstevel@tonic-gate 			server_cert= *(++argv);
5240Sstevel@tonic-gate 			}
5250Sstevel@tonic-gate 		else if	(strcmp(*argv,"-s_cert") == 0)
5260Sstevel@tonic-gate 			{
5270Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5280Sstevel@tonic-gate 			server_cert= *(++argv);
5290Sstevel@tonic-gate 			}
5300Sstevel@tonic-gate 		else if	(strcmp(*argv,"-key") == 0)
5310Sstevel@tonic-gate 			{
5320Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5330Sstevel@tonic-gate 			server_key= *(++argv);
5340Sstevel@tonic-gate 			}
5350Sstevel@tonic-gate 		else if	(strcmp(*argv,"-s_key") == 0)
5360Sstevel@tonic-gate 			{
5370Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5380Sstevel@tonic-gate 			server_key= *(++argv);
5390Sstevel@tonic-gate 			}
5400Sstevel@tonic-gate 		else if	(strcmp(*argv,"-c_cert") == 0)
5410Sstevel@tonic-gate 			{
5420Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5430Sstevel@tonic-gate 			client_cert= *(++argv);
5440Sstevel@tonic-gate 			}
5450Sstevel@tonic-gate 		else if	(strcmp(*argv,"-c_key") == 0)
5460Sstevel@tonic-gate 			{
5470Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5480Sstevel@tonic-gate 			client_key= *(++argv);
5490Sstevel@tonic-gate 			}
5500Sstevel@tonic-gate 		else if	(strcmp(*argv,"-cipher") == 0)
5510Sstevel@tonic-gate 			{
5520Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5530Sstevel@tonic-gate 			cipher= *(++argv);
5540Sstevel@tonic-gate 			}
5550Sstevel@tonic-gate 		else if	(strcmp(*argv,"-CApath") == 0)
5560Sstevel@tonic-gate 			{
5570Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5580Sstevel@tonic-gate 			CApath= *(++argv);
5590Sstevel@tonic-gate 			}
5600Sstevel@tonic-gate 		else if	(strcmp(*argv,"-CAfile") == 0)
5610Sstevel@tonic-gate 			{
5620Sstevel@tonic-gate 			if (--argc < 1) goto bad;
5630Sstevel@tonic-gate 			CAfile= *(++argv);
5640Sstevel@tonic-gate 			}
5650Sstevel@tonic-gate 		else if	(strcmp(*argv,"-bio_pair") == 0)
5660Sstevel@tonic-gate 			{
5670Sstevel@tonic-gate 			bio_pair = 1;
5680Sstevel@tonic-gate 			}
5690Sstevel@tonic-gate 		else if	(strcmp(*argv,"-f") == 0)
5700Sstevel@tonic-gate 			{
5710Sstevel@tonic-gate 			force = 1;
5720Sstevel@tonic-gate 			}
5730Sstevel@tonic-gate 		else if	(strcmp(*argv,"-time") == 0)
5740Sstevel@tonic-gate 			{
5750Sstevel@tonic-gate 			print_time = 1;
5760Sstevel@tonic-gate 			}
5770Sstevel@tonic-gate 		else if	(strcmp(*argv,"-zlib") == 0)
5780Sstevel@tonic-gate 			{
5790Sstevel@tonic-gate 			comp = COMP_ZLIB;
5800Sstevel@tonic-gate 			}
5810Sstevel@tonic-gate 		else if	(strcmp(*argv,"-rle") == 0)
5820Sstevel@tonic-gate 			{
5830Sstevel@tonic-gate 			comp = COMP_RLE;
5840Sstevel@tonic-gate 			}
5852139Sjp161948 		else if	(strcmp(*argv,"-named_curve") == 0)
5862139Sjp161948 			{
5872139Sjp161948 			if (--argc < 1) goto bad;
5882139Sjp161948 #ifndef OPENSSL_NO_ECDH
5892139Sjp161948 			named_curve = *(++argv);
5902139Sjp161948 #else
5912139Sjp161948 			fprintf(stderr,"ignoring -named_curve, since I'm compiled without ECDH\n");
5922139Sjp161948 			++argv;
5932139Sjp161948 #endif
5942139Sjp161948 			}
5950Sstevel@tonic-gate 		else if	(strcmp(*argv,"-app_verify") == 0)
5960Sstevel@tonic-gate 			{
5972139Sjp161948 			app_verify_arg.app_verify = 1;
5982139Sjp161948 			}
5992139Sjp161948 		else if	(strcmp(*argv,"-proxy") == 0)
6002139Sjp161948 			{
6012139Sjp161948 			app_verify_arg.allow_proxy_certs = 1;
6022139Sjp161948 			}
6032139Sjp161948 		else if (strcmp(*argv,"-test_cipherlist") == 0)
6042139Sjp161948 			{
6052139Sjp161948 			test_cipherlist = 1;
6060Sstevel@tonic-gate 			}
6070Sstevel@tonic-gate 		else
6080Sstevel@tonic-gate 			{
6090Sstevel@tonic-gate 			fprintf(stderr,"unknown option %s\n",*argv);
6100Sstevel@tonic-gate 			badop=1;
6110Sstevel@tonic-gate 			break;
6120Sstevel@tonic-gate 			}
6130Sstevel@tonic-gate 		argc--;
6140Sstevel@tonic-gate 		argv++;
6150Sstevel@tonic-gate 		}
6160Sstevel@tonic-gate 	if (badop)
6170Sstevel@tonic-gate 		{
6180Sstevel@tonic-gate bad:
6190Sstevel@tonic-gate 		sv_usage();
6200Sstevel@tonic-gate 		goto end;
6210Sstevel@tonic-gate 		}
6220Sstevel@tonic-gate 
6232139Sjp161948 	if (test_cipherlist == 1)
6242139Sjp161948 		{
6252139Sjp161948 		/* ensure that the cipher list are correctly sorted and exit */
6262139Sjp161948 		if (do_test_cipherlist() == 0)
6272139Sjp161948 			EXIT(1);
6282139Sjp161948 		ret = 0;
6292139Sjp161948 		goto end;
6302139Sjp161948 		}
6312139Sjp161948 
6320Sstevel@tonic-gate 	if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force)
6330Sstevel@tonic-gate 		{
6340Sstevel@tonic-gate 		fprintf(stderr, "This case cannot work.  Use -f to perform "
6350Sstevel@tonic-gate 			"the test anyway (and\n-d to see what happens), "
6360Sstevel@tonic-gate 			"or add one of -ssl2, -ssl3, -tls1, -reuse\n"
6370Sstevel@tonic-gate 			"to avoid protocol mismatch.\n");
6380Sstevel@tonic-gate 		EXIT(1);
6390Sstevel@tonic-gate 		}
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	if (print_time)
6420Sstevel@tonic-gate 		{
6430Sstevel@tonic-gate 		if (!bio_pair)
6440Sstevel@tonic-gate 			{
6450Sstevel@tonic-gate 			fprintf(stderr, "Using BIO pair (-bio_pair)\n");
6460Sstevel@tonic-gate 			bio_pair = 1;
6470Sstevel@tonic-gate 			}
6480Sstevel@tonic-gate 		if (number < 50 && !force)
6490Sstevel@tonic-gate 			fprintf(stderr, "Warning: For accurate timings, use more connections (e.g. -num 1000)\n");
6500Sstevel@tonic-gate 		}
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate /*	if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate 	SSL_library_init();
6550Sstevel@tonic-gate 	SSL_load_error_strings();
6560Sstevel@tonic-gate 
6572139Sjp161948 #ifndef OPENSSL_NO_COMP
6580Sstevel@tonic-gate 	if (comp == COMP_ZLIB) cm = COMP_zlib();
6590Sstevel@tonic-gate 	if (comp == COMP_RLE) cm = COMP_rle();
6600Sstevel@tonic-gate 	if (cm != NULL)
6610Sstevel@tonic-gate 		{
6620Sstevel@tonic-gate 		if (cm->type != NID_undef)
6630Sstevel@tonic-gate 			{
6640Sstevel@tonic-gate 			if (SSL_COMP_add_compression_method(comp, cm) != 0)
6650Sstevel@tonic-gate 				{
6660Sstevel@tonic-gate 				fprintf(stderr,
6670Sstevel@tonic-gate 					"Failed to add compression method\n");
6680Sstevel@tonic-gate 				ERR_print_errors_fp(stderr);
6690Sstevel@tonic-gate 				}
6700Sstevel@tonic-gate 			}
6710Sstevel@tonic-gate 		else
6720Sstevel@tonic-gate 			{
6730Sstevel@tonic-gate 			fprintf(stderr,
6740Sstevel@tonic-gate 				"Warning: %s compression not supported\n",
6750Sstevel@tonic-gate 				(comp == COMP_RLE ? "rle" :
6760Sstevel@tonic-gate 					(comp == COMP_ZLIB ? "zlib" :
6770Sstevel@tonic-gate 						"unknown")));
6780Sstevel@tonic-gate 			ERR_print_errors_fp(stderr);
6790Sstevel@tonic-gate 			}
6800Sstevel@tonic-gate 		}
6812139Sjp161948 	ssl_comp_methods = SSL_COMP_get_compression_methods();
6822139Sjp161948 	fprintf(stderr, "Available compression methods:\n");
6832139Sjp161948 	{
6842139Sjp161948 	int j, n = sk_SSL_COMP_num(ssl_comp_methods);
6852139Sjp161948 	if (n == 0)
6862139Sjp161948 		fprintf(stderr, "  NONE\n");
6872139Sjp161948 	else
6882139Sjp161948 		for (j = 0; j < n; j++)
6892139Sjp161948 			{
6902139Sjp161948 			SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j);
6912139Sjp161948 			fprintf(stderr, "  %d: %s\n", c->id, c->name);
6922139Sjp161948 			}
6932139Sjp161948 	}
6942139Sjp161948 #endif
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
6970Sstevel@tonic-gate 	if (ssl2)
6980Sstevel@tonic-gate 		meth=SSLv2_method();
6990Sstevel@tonic-gate 	else
7000Sstevel@tonic-gate 	if (tls1)
7010Sstevel@tonic-gate 		meth=TLSv1_method();
7020Sstevel@tonic-gate 	else
7030Sstevel@tonic-gate 	if (ssl3)
7040Sstevel@tonic-gate 		meth=SSLv3_method();
7050Sstevel@tonic-gate 	else
7060Sstevel@tonic-gate 		meth=SSLv23_method();
7070Sstevel@tonic-gate #else
7080Sstevel@tonic-gate #ifdef OPENSSL_NO_SSL2
7090Sstevel@tonic-gate 	meth=SSLv3_method();
7100Sstevel@tonic-gate #else
7110Sstevel@tonic-gate 	meth=SSLv2_method();
7120Sstevel@tonic-gate #endif
7130Sstevel@tonic-gate #endif
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 	c_ctx=SSL_CTX_new(meth);
7160Sstevel@tonic-gate 	s_ctx=SSL_CTX_new(meth);
7170Sstevel@tonic-gate 	if ((c_ctx == NULL) || (s_ctx == NULL))
7180Sstevel@tonic-gate 		{
7190Sstevel@tonic-gate 		ERR_print_errors(bio_err);
7200Sstevel@tonic-gate 		goto end;
7210Sstevel@tonic-gate 		}
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate 	if (cipher != NULL)
7240Sstevel@tonic-gate 		{
7250Sstevel@tonic-gate 		SSL_CTX_set_cipher_list(c_ctx,cipher);
7260Sstevel@tonic-gate 		SSL_CTX_set_cipher_list(s_ctx,cipher);
7270Sstevel@tonic-gate 		}
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
7300Sstevel@tonic-gate 	if (!no_dhe)
7310Sstevel@tonic-gate 		{
7320Sstevel@tonic-gate 		if (dhe1024dsa)
7330Sstevel@tonic-gate 			{
7340Sstevel@tonic-gate 			/* use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks */
7350Sstevel@tonic-gate 			SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
7360Sstevel@tonic-gate 			dh=get_dh1024dsa();
7370Sstevel@tonic-gate 			}
7380Sstevel@tonic-gate 		else if (dhe1024)
7390Sstevel@tonic-gate 			dh=get_dh1024();
7400Sstevel@tonic-gate 		else
7410Sstevel@tonic-gate 			dh=get_dh512();
7420Sstevel@tonic-gate 		SSL_CTX_set_tmp_dh(s_ctx,dh);
7430Sstevel@tonic-gate 		DH_free(dh);
7440Sstevel@tonic-gate 		}
7450Sstevel@tonic-gate #else
7460Sstevel@tonic-gate 	(void)no_dhe;
7470Sstevel@tonic-gate #endif
7480Sstevel@tonic-gate 
7492139Sjp161948 #ifndef OPENSSL_NO_ECDH
7502139Sjp161948 	if (!no_ecdhe)
7512139Sjp161948 		{
7522139Sjp161948 		int nid;
7532139Sjp161948 
7542139Sjp161948 		if (named_curve != NULL)
7552139Sjp161948 			{
7562139Sjp161948 			nid = OBJ_sn2nid(named_curve);
7572139Sjp161948 			if (nid == 0)
7582139Sjp161948 			{
7592139Sjp161948 				BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve);
7602139Sjp161948 				goto end;
7612139Sjp161948 				}
7622139Sjp161948 			}
7632139Sjp161948 		else
7642139Sjp161948 			nid = NID_sect163r2;
7652139Sjp161948 
7662139Sjp161948 		ecdh = EC_KEY_new_by_curve_name(nid);
7672139Sjp161948 		if (ecdh == NULL)
7682139Sjp161948 			{
7692139Sjp161948 			BIO_printf(bio_err, "unable to create curve\n");
7702139Sjp161948 			goto end;
7712139Sjp161948 			}
7722139Sjp161948 
7732139Sjp161948 		SSL_CTX_set_tmp_ecdh(s_ctx, ecdh);
7742139Sjp161948 		SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE);
7752139Sjp161948 		EC_KEY_free(ecdh);
7762139Sjp161948 		}
7772139Sjp161948 #else
7782139Sjp161948 	(void)no_ecdhe;
7792139Sjp161948 #endif
7802139Sjp161948 
7810Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
7820Sstevel@tonic-gate 	SSL_CTX_set_tmp_rsa_callback(s_ctx,tmp_rsa_cb);
7830Sstevel@tonic-gate #endif
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	if (!SSL_CTX_use_certificate_file(s_ctx,server_cert,SSL_FILETYPE_PEM))
7860Sstevel@tonic-gate 		{
7870Sstevel@tonic-gate 		ERR_print_errors(bio_err);
7880Sstevel@tonic-gate 		}
7890Sstevel@tonic-gate 	else if (!SSL_CTX_use_PrivateKey_file(s_ctx,
7900Sstevel@tonic-gate 		(server_key?server_key:server_cert), SSL_FILETYPE_PEM))
7910Sstevel@tonic-gate 		{
7920Sstevel@tonic-gate 		ERR_print_errors(bio_err);
7930Sstevel@tonic-gate 		goto end;
7940Sstevel@tonic-gate 		}
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 	if (client_auth)
7970Sstevel@tonic-gate 		{
7980Sstevel@tonic-gate 		SSL_CTX_use_certificate_file(c_ctx,client_cert,
7990Sstevel@tonic-gate 			SSL_FILETYPE_PEM);
8000Sstevel@tonic-gate 		SSL_CTX_use_PrivateKey_file(c_ctx,
8010Sstevel@tonic-gate 			(client_key?client_key:client_cert),
8020Sstevel@tonic-gate 			SSL_FILETYPE_PEM);
8030Sstevel@tonic-gate 		}
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 	if (	(!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) ||
8060Sstevel@tonic-gate 		(!SSL_CTX_set_default_verify_paths(s_ctx)) ||
8070Sstevel@tonic-gate 		(!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) ||
8080Sstevel@tonic-gate 		(!SSL_CTX_set_default_verify_paths(c_ctx)))
8090Sstevel@tonic-gate 		{
8100Sstevel@tonic-gate 		/* fprintf(stderr,"SSL_load_verify_locations\n"); */
8110Sstevel@tonic-gate 		ERR_print_errors(bio_err);
8120Sstevel@tonic-gate 		/* goto end; */
8130Sstevel@tonic-gate 		}
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 	if (client_auth)
8160Sstevel@tonic-gate 		{
8170Sstevel@tonic-gate 		BIO_printf(bio_err,"client authentication\n");
8180Sstevel@tonic-gate 		SSL_CTX_set_verify(s_ctx,
8190Sstevel@tonic-gate 			SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
8200Sstevel@tonic-gate 			verify_callback);
8212139Sjp161948 		SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, &app_verify_arg);
8220Sstevel@tonic-gate 		}
8230Sstevel@tonic-gate 	if (server_auth)
8240Sstevel@tonic-gate 		{
8250Sstevel@tonic-gate 		BIO_printf(bio_err,"server authentication\n");
8260Sstevel@tonic-gate 		SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER,
8270Sstevel@tonic-gate 			verify_callback);
8282139Sjp161948 		SSL_CTX_set_cert_verify_callback(c_ctx, app_verify_callback, &app_verify_arg);
8290Sstevel@tonic-gate 		}
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 	{
8320Sstevel@tonic-gate 		int session_id_context = 0;
8330Sstevel@tonic-gate 		SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, sizeof session_id_context);
8340Sstevel@tonic-gate 	}
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 	c_ssl=SSL_new(c_ctx);
8370Sstevel@tonic-gate 	s_ssl=SSL_new(s_ctx);
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate #ifndef OPENSSL_NO_KRB5
8400Sstevel@tonic-gate 	if (c_ssl  &&  c_ssl->kssl_ctx)
8410Sstevel@tonic-gate                 {
8420Sstevel@tonic-gate                 char	localhost[MAXHOSTNAMELEN+2];
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 		if (gethostname(localhost, sizeof localhost-1) == 0)
8450Sstevel@tonic-gate                         {
8460Sstevel@tonic-gate 			localhost[sizeof localhost-1]='\0';
8470Sstevel@tonic-gate 			if(strlen(localhost) == sizeof localhost-1)
8480Sstevel@tonic-gate 				{
8490Sstevel@tonic-gate 				BIO_printf(bio_err,"localhost name too long\n");
8500Sstevel@tonic-gate 				goto end;
8510Sstevel@tonic-gate 				}
8520Sstevel@tonic-gate 			kssl_ctx_setstring(c_ssl->kssl_ctx, KSSL_SERVER,
8530Sstevel@tonic-gate                                 localhost);
8540Sstevel@tonic-gate 			}
8550Sstevel@tonic-gate 		}
8560Sstevel@tonic-gate #endif    /* OPENSSL_NO_KRB5  */
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate 	for (i=0; i<number; i++)
8590Sstevel@tonic-gate 		{
8600Sstevel@tonic-gate 		if (!reuse) SSL_set_session(c_ssl,NULL);
8610Sstevel@tonic-gate 		if (bio_pair)
8620Sstevel@tonic-gate 			ret=doit_biopair(s_ssl,c_ssl,bytes,&s_time,&c_time);
8630Sstevel@tonic-gate 		else
8640Sstevel@tonic-gate 			ret=doit(s_ssl,c_ssl,bytes);
8650Sstevel@tonic-gate 		}
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate 	if (!verbose)
8680Sstevel@tonic-gate 		{
8690Sstevel@tonic-gate 		print_details(c_ssl, "");
8700Sstevel@tonic-gate 		}
8710Sstevel@tonic-gate 	if ((number > 1) || (bytes > 1L))
8720Sstevel@tonic-gate 		BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n",number,bytes);
8730Sstevel@tonic-gate 	if (print_time)
8740Sstevel@tonic-gate 		{
8750Sstevel@tonic-gate #ifdef CLOCKS_PER_SEC
8760Sstevel@tonic-gate 		/* "To determine the time in seconds, the value returned
8770Sstevel@tonic-gate 		 * by the clock function should be divided by the value
8780Sstevel@tonic-gate 		 * of the macro CLOCKS_PER_SEC."
8790Sstevel@tonic-gate 		 *                                       -- ISO/IEC 9899 */
8800Sstevel@tonic-gate 		BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n"
8810Sstevel@tonic-gate 			"Approximate total client time: %6.2f s\n",
8820Sstevel@tonic-gate 			(double)s_time/CLOCKS_PER_SEC,
8830Sstevel@tonic-gate 			(double)c_time/CLOCKS_PER_SEC);
8840Sstevel@tonic-gate #else
8850Sstevel@tonic-gate 		/* "`CLOCKS_PER_SEC' undeclared (first use this function)"
8860Sstevel@tonic-gate 		 *                            -- cc on NeXTstep/OpenStep */
8870Sstevel@tonic-gate 		BIO_printf(bio_stdout,
8880Sstevel@tonic-gate 			"Approximate total server time: %6.2f units\n"
8890Sstevel@tonic-gate 			"Approximate total client time: %6.2f units\n",
8900Sstevel@tonic-gate 			(double)s_time,
8910Sstevel@tonic-gate 			(double)c_time);
8920Sstevel@tonic-gate #endif
8930Sstevel@tonic-gate 		}
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 	SSL_free(s_ssl);
8960Sstevel@tonic-gate 	SSL_free(c_ssl);
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate end:
8990Sstevel@tonic-gate 	if (s_ctx != NULL) SSL_CTX_free(s_ctx);
9000Sstevel@tonic-gate 	if (c_ctx != NULL) SSL_CTX_free(c_ctx);
9010Sstevel@tonic-gate 
9020Sstevel@tonic-gate 	if (bio_stdout != NULL) BIO_free(bio_stdout);
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
9050Sstevel@tonic-gate 	free_tmp_rsa();
9060Sstevel@tonic-gate #endif
9070Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
9080Sstevel@tonic-gate 	ENGINE_cleanup();
9090Sstevel@tonic-gate #endif
9100Sstevel@tonic-gate 	CRYPTO_cleanup_all_ex_data();
9110Sstevel@tonic-gate 	ERR_free_strings();
9120Sstevel@tonic-gate 	ERR_remove_state(0);
9130Sstevel@tonic-gate 	EVP_cleanup();
9140Sstevel@tonic-gate 	CRYPTO_mem_leaks(bio_err);
9150Sstevel@tonic-gate 	if (bio_err != NULL) BIO_free(bio_err);
9160Sstevel@tonic-gate 	EXIT(ret);
9172139Sjp161948 	return ret;
9180Sstevel@tonic-gate 	}
9190Sstevel@tonic-gate 
doit_biopair(SSL * s_ssl,SSL * c_ssl,long count,clock_t * s_time,clock_t * c_time)9200Sstevel@tonic-gate int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
9210Sstevel@tonic-gate 	clock_t *s_time, clock_t *c_time)
9220Sstevel@tonic-gate 	{
9230Sstevel@tonic-gate 	long cw_num = count, cr_num = count, sw_num = count, sr_num = count;
9240Sstevel@tonic-gate 	BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL;
9250Sstevel@tonic-gate 	BIO *server = NULL, *server_io = NULL, *client = NULL, *client_io = NULL;
9260Sstevel@tonic-gate 	int ret = 1;
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	size_t bufsiz = 256; /* small buffer for testing */
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 	if (!BIO_new_bio_pair(&server, bufsiz, &server_io, bufsiz))
9310Sstevel@tonic-gate 		goto err;
9320Sstevel@tonic-gate 	if (!BIO_new_bio_pair(&client, bufsiz, &client_io, bufsiz))
9330Sstevel@tonic-gate 		goto err;
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	s_ssl_bio = BIO_new(BIO_f_ssl());
9360Sstevel@tonic-gate 	if (!s_ssl_bio)
9370Sstevel@tonic-gate 		goto err;
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 	c_ssl_bio = BIO_new(BIO_f_ssl());
9400Sstevel@tonic-gate 	if (!c_ssl_bio)
9410Sstevel@tonic-gate 		goto err;
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 	SSL_set_connect_state(c_ssl);
9440Sstevel@tonic-gate 	SSL_set_bio(c_ssl, client, client);
9450Sstevel@tonic-gate 	(void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE);
9460Sstevel@tonic-gate 
9470Sstevel@tonic-gate 	SSL_set_accept_state(s_ssl);
9480Sstevel@tonic-gate 	SSL_set_bio(s_ssl, server, server);
9490Sstevel@tonic-gate 	(void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE);
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 	do
9520Sstevel@tonic-gate 		{
9530Sstevel@tonic-gate 		/* c_ssl_bio:          SSL filter BIO
9540Sstevel@tonic-gate 		 *
9550Sstevel@tonic-gate 		 * client:             pseudo-I/O for SSL library
9560Sstevel@tonic-gate 		 *
9570Sstevel@tonic-gate 		 * client_io:          client's SSL communication; usually to be
9580Sstevel@tonic-gate 		 *                     relayed over some I/O facility, but in this
9590Sstevel@tonic-gate 		 *                     test program, we're the server, too:
9600Sstevel@tonic-gate 		 *
9610Sstevel@tonic-gate 		 * server_io:          server's SSL communication
9620Sstevel@tonic-gate 		 *
9630Sstevel@tonic-gate 		 * server:             pseudo-I/O for SSL library
9640Sstevel@tonic-gate 		 *
9650Sstevel@tonic-gate 		 * s_ssl_bio:          SSL filter BIO
9660Sstevel@tonic-gate 		 *
9670Sstevel@tonic-gate 		 * The client and the server each employ a "BIO pair":
9680Sstevel@tonic-gate 		 * client + client_io, server + server_io.
9690Sstevel@tonic-gate 		 * BIO pairs are symmetric.  A BIO pair behaves similar
9700Sstevel@tonic-gate 		 * to a non-blocking socketpair (but both endpoints must
9710Sstevel@tonic-gate 		 * be handled by the same thread).
9720Sstevel@tonic-gate 		 * [Here we could connect client and server to the ends
9730Sstevel@tonic-gate 		 * of a single BIO pair, but then this code would be less
9740Sstevel@tonic-gate 		 * suitable as an example for BIO pairs in general.]
9750Sstevel@tonic-gate 		 *
9760Sstevel@tonic-gate 		 * Useful functions for querying the state of BIO pair endpoints:
9770Sstevel@tonic-gate 		 *
9780Sstevel@tonic-gate 		 * BIO_ctrl_pending(bio)              number of bytes we can read now
9790Sstevel@tonic-gate 		 * BIO_ctrl_get_read_request(bio)     number of bytes needed to fulfil
9800Sstevel@tonic-gate 		 *                                      other side's read attempt
9810Sstevel@tonic-gate 		 * BIO_ctrl_get_write_guarantee(bio)   number of bytes we can write now
9820Sstevel@tonic-gate 		 *
9830Sstevel@tonic-gate 		 * ..._read_request is never more than ..._write_guarantee;
9840Sstevel@tonic-gate 		 * it depends on the application which one you should use.
9850Sstevel@tonic-gate 		 */
9860Sstevel@tonic-gate 
9870Sstevel@tonic-gate 		/* We have non-blocking behaviour throughout this test program, but
9880Sstevel@tonic-gate 		 * can be sure that there is *some* progress in each iteration; so
9890Sstevel@tonic-gate 		 * we don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE
9900Sstevel@tonic-gate 		 * -- we just try everything in each iteration
9910Sstevel@tonic-gate 		 */
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 			{
9940Sstevel@tonic-gate 			/* CLIENT */
9950Sstevel@tonic-gate 
9960Sstevel@tonic-gate 			MS_STATIC char cbuf[1024*8];
9970Sstevel@tonic-gate 			int i, r;
9980Sstevel@tonic-gate 			clock_t c_clock = clock();
9990Sstevel@tonic-gate 
10000Sstevel@tonic-gate 			memset(cbuf, 0, sizeof(cbuf));
10010Sstevel@tonic-gate 
10020Sstevel@tonic-gate 			if (debug)
10030Sstevel@tonic-gate 				if (SSL_in_init(c_ssl))
10040Sstevel@tonic-gate 					printf("client waiting in SSL_connect - %s\n",
10050Sstevel@tonic-gate 						SSL_state_string_long(c_ssl));
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 			if (cw_num > 0)
10080Sstevel@tonic-gate 				{
10090Sstevel@tonic-gate 				/* Write to server. */
10100Sstevel@tonic-gate 
10110Sstevel@tonic-gate 				if (cw_num > (long)sizeof cbuf)
10120Sstevel@tonic-gate 					i = sizeof cbuf;
10130Sstevel@tonic-gate 				else
10140Sstevel@tonic-gate 					i = (int)cw_num;
10150Sstevel@tonic-gate 				r = BIO_write(c_ssl_bio, cbuf, i);
10160Sstevel@tonic-gate 				if (r < 0)
10170Sstevel@tonic-gate 					{
10180Sstevel@tonic-gate 					if (!BIO_should_retry(c_ssl_bio))
10190Sstevel@tonic-gate 						{
10200Sstevel@tonic-gate 						fprintf(stderr,"ERROR in CLIENT\n");
10210Sstevel@tonic-gate 						goto err;
10220Sstevel@tonic-gate 						}
10230Sstevel@tonic-gate 					/* BIO_should_retry(...) can just be ignored here.
10240Sstevel@tonic-gate 					 * The library expects us to call BIO_write with
10250Sstevel@tonic-gate 					 * the same arguments again, and that's what we will
10260Sstevel@tonic-gate 					 * do in the next iteration. */
10270Sstevel@tonic-gate 					}
10280Sstevel@tonic-gate 				else if (r == 0)
10290Sstevel@tonic-gate 					{
10300Sstevel@tonic-gate 					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
10310Sstevel@tonic-gate 					goto err;
10320Sstevel@tonic-gate 					}
10330Sstevel@tonic-gate 				else
10340Sstevel@tonic-gate 					{
10350Sstevel@tonic-gate 					if (debug)
10360Sstevel@tonic-gate 						printf("client wrote %d\n", r);
10370Sstevel@tonic-gate 					cw_num -= r;
10380Sstevel@tonic-gate 					}
10390Sstevel@tonic-gate 				}
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate 			if (cr_num > 0)
10420Sstevel@tonic-gate 				{
10430Sstevel@tonic-gate 				/* Read from server. */
10440Sstevel@tonic-gate 
10450Sstevel@tonic-gate 				r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf));
10460Sstevel@tonic-gate 				if (r < 0)
10470Sstevel@tonic-gate 					{
10480Sstevel@tonic-gate 					if (!BIO_should_retry(c_ssl_bio))
10490Sstevel@tonic-gate 						{
10500Sstevel@tonic-gate 						fprintf(stderr,"ERROR in CLIENT\n");
10510Sstevel@tonic-gate 						goto err;
10520Sstevel@tonic-gate 						}
10530Sstevel@tonic-gate 					/* Again, "BIO_should_retry" can be ignored. */
10540Sstevel@tonic-gate 					}
10550Sstevel@tonic-gate 				else if (r == 0)
10560Sstevel@tonic-gate 					{
10570Sstevel@tonic-gate 					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
10580Sstevel@tonic-gate 					goto err;
10590Sstevel@tonic-gate 					}
10600Sstevel@tonic-gate 				else
10610Sstevel@tonic-gate 					{
10620Sstevel@tonic-gate 					if (debug)
10630Sstevel@tonic-gate 						printf("client read %d\n", r);
10640Sstevel@tonic-gate 					cr_num -= r;
10650Sstevel@tonic-gate 					}
10660Sstevel@tonic-gate 				}
10670Sstevel@tonic-gate 
10680Sstevel@tonic-gate 			/* c_time and s_time increments will typically be very small
10690Sstevel@tonic-gate 			 * (depending on machine speed and clock tick intervals),
10700Sstevel@tonic-gate 			 * but sampling over a large number of connections should
10710Sstevel@tonic-gate 			 * result in fairly accurate figures.  We cannot guarantee
10720Sstevel@tonic-gate 			 * a lot, however -- if each connection lasts for exactly
10730Sstevel@tonic-gate 			 * one clock tick, it will be counted only for the client
10740Sstevel@tonic-gate 			 * or only for the server or even not at all.
10750Sstevel@tonic-gate 			 */
10760Sstevel@tonic-gate 			*c_time += (clock() - c_clock);
10770Sstevel@tonic-gate 			}
10780Sstevel@tonic-gate 
10790Sstevel@tonic-gate 			{
10800Sstevel@tonic-gate 			/* SERVER */
10810Sstevel@tonic-gate 
10820Sstevel@tonic-gate 			MS_STATIC char sbuf[1024*8];
10830Sstevel@tonic-gate 			int i, r;
10840Sstevel@tonic-gate 			clock_t s_clock = clock();
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 			memset(sbuf, 0, sizeof(sbuf));
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate 			if (debug)
10890Sstevel@tonic-gate 				if (SSL_in_init(s_ssl))
10900Sstevel@tonic-gate 					printf("server waiting in SSL_accept - %s\n",
10910Sstevel@tonic-gate 						SSL_state_string_long(s_ssl));
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 			if (sw_num > 0)
10940Sstevel@tonic-gate 				{
10950Sstevel@tonic-gate 				/* Write to client. */
10960Sstevel@tonic-gate 
10970Sstevel@tonic-gate 				if (sw_num > (long)sizeof sbuf)
10980Sstevel@tonic-gate 					i = sizeof sbuf;
10990Sstevel@tonic-gate 				else
11000Sstevel@tonic-gate 					i = (int)sw_num;
11010Sstevel@tonic-gate 				r = BIO_write(s_ssl_bio, sbuf, i);
11020Sstevel@tonic-gate 				if (r < 0)
11030Sstevel@tonic-gate 					{
11040Sstevel@tonic-gate 					if (!BIO_should_retry(s_ssl_bio))
11050Sstevel@tonic-gate 						{
11060Sstevel@tonic-gate 						fprintf(stderr,"ERROR in SERVER\n");
11070Sstevel@tonic-gate 						goto err;
11080Sstevel@tonic-gate 						}
11090Sstevel@tonic-gate 					/* Ignore "BIO_should_retry". */
11100Sstevel@tonic-gate 					}
11110Sstevel@tonic-gate 				else if (r == 0)
11120Sstevel@tonic-gate 					{
11130Sstevel@tonic-gate 					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
11140Sstevel@tonic-gate 					goto err;
11150Sstevel@tonic-gate 					}
11160Sstevel@tonic-gate 				else
11170Sstevel@tonic-gate 					{
11180Sstevel@tonic-gate 					if (debug)
11190Sstevel@tonic-gate 						printf("server wrote %d\n", r);
11200Sstevel@tonic-gate 					sw_num -= r;
11210Sstevel@tonic-gate 					}
11220Sstevel@tonic-gate 				}
11230Sstevel@tonic-gate 
11240Sstevel@tonic-gate 			if (sr_num > 0)
11250Sstevel@tonic-gate 				{
11260Sstevel@tonic-gate 				/* Read from client. */
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate 				r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf));
11290Sstevel@tonic-gate 				if (r < 0)
11300Sstevel@tonic-gate 					{
11310Sstevel@tonic-gate 					if (!BIO_should_retry(s_ssl_bio))
11320Sstevel@tonic-gate 						{
11330Sstevel@tonic-gate 						fprintf(stderr,"ERROR in SERVER\n");
11340Sstevel@tonic-gate 						goto err;
11350Sstevel@tonic-gate 						}
11360Sstevel@tonic-gate 					/* blah, blah */
11370Sstevel@tonic-gate 					}
11380Sstevel@tonic-gate 				else if (r == 0)
11390Sstevel@tonic-gate 					{
11400Sstevel@tonic-gate 					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
11410Sstevel@tonic-gate 					goto err;
11420Sstevel@tonic-gate 					}
11430Sstevel@tonic-gate 				else
11440Sstevel@tonic-gate 					{
11450Sstevel@tonic-gate 					if (debug)
11460Sstevel@tonic-gate 						printf("server read %d\n", r);
11470Sstevel@tonic-gate 					sr_num -= r;
11480Sstevel@tonic-gate 					}
11490Sstevel@tonic-gate 				}
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate 			*s_time += (clock() - s_clock);
11520Sstevel@tonic-gate 			}
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 			{
11550Sstevel@tonic-gate 			/* "I/O" BETWEEN CLIENT AND SERVER. */
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 			size_t r1, r2;
11580Sstevel@tonic-gate 			BIO *io1 = server_io, *io2 = client_io;
11590Sstevel@tonic-gate 			/* we use the non-copying interface for io1
11600Sstevel@tonic-gate 			 * and the standard BIO_write/BIO_read interface for io2
11610Sstevel@tonic-gate 			 */
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate 			static int prev_progress = 1;
11640Sstevel@tonic-gate 			int progress = 0;
11650Sstevel@tonic-gate 
11660Sstevel@tonic-gate 			/* io1 to io2 */
11670Sstevel@tonic-gate 			do
11680Sstevel@tonic-gate 				{
11690Sstevel@tonic-gate 				size_t num;
11700Sstevel@tonic-gate 				int r;
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 				r1 = BIO_ctrl_pending(io1);
11730Sstevel@tonic-gate 				r2 = BIO_ctrl_get_write_guarantee(io2);
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 				num = r1;
11760Sstevel@tonic-gate 				if (r2 < num)
11770Sstevel@tonic-gate 					num = r2;
11780Sstevel@tonic-gate 				if (num)
11790Sstevel@tonic-gate 					{
11800Sstevel@tonic-gate 					char *dataptr;
11810Sstevel@tonic-gate 
11820Sstevel@tonic-gate 					if (INT_MAX < num) /* yeah, right */
11830Sstevel@tonic-gate 						num = INT_MAX;
11840Sstevel@tonic-gate 
11850Sstevel@tonic-gate 					r = BIO_nread(io1, &dataptr, (int)num);
11860Sstevel@tonic-gate 					assert(r > 0);
11870Sstevel@tonic-gate 					assert(r <= (int)num);
11880Sstevel@tonic-gate 					/* possibly r < num (non-contiguous data) */
11890Sstevel@tonic-gate 					num = r;
11900Sstevel@tonic-gate 					r = BIO_write(io2, dataptr, (int)num);
11910Sstevel@tonic-gate 					if (r != (int)num) /* can't happen */
11920Sstevel@tonic-gate 						{
11930Sstevel@tonic-gate 						fprintf(stderr, "ERROR: BIO_write could not write "
11940Sstevel@tonic-gate 							"BIO_ctrl_get_write_guarantee() bytes");
11950Sstevel@tonic-gate 						goto err;
11960Sstevel@tonic-gate 						}
11970Sstevel@tonic-gate 					progress = 1;
11980Sstevel@tonic-gate 
11990Sstevel@tonic-gate 					if (debug)
12000Sstevel@tonic-gate 						printf((io1 == client_io) ?
12010Sstevel@tonic-gate 							"C->S relaying: %d bytes\n" :
12020Sstevel@tonic-gate 							"S->C relaying: %d bytes\n",
12030Sstevel@tonic-gate 							(int)num);
12040Sstevel@tonic-gate 					}
12050Sstevel@tonic-gate 				}
12060Sstevel@tonic-gate 			while (r1 && r2);
12070Sstevel@tonic-gate 
12080Sstevel@tonic-gate 			/* io2 to io1 */
12090Sstevel@tonic-gate 			{
12100Sstevel@tonic-gate 				size_t num;
12110Sstevel@tonic-gate 				int r;
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate 				r1 = BIO_ctrl_pending(io2);
12140Sstevel@tonic-gate 				r2 = BIO_ctrl_get_read_request(io1);
12150Sstevel@tonic-gate 				/* here we could use ..._get_write_guarantee instead of
12160Sstevel@tonic-gate 				 * ..._get_read_request, but by using the latter
12170Sstevel@tonic-gate 				 * we test restartability of the SSL implementation
12180Sstevel@tonic-gate 				 * more thoroughly */
12190Sstevel@tonic-gate 				num = r1;
12200Sstevel@tonic-gate 				if (r2 < num)
12210Sstevel@tonic-gate 					num = r2;
12220Sstevel@tonic-gate 				if (num)
12230Sstevel@tonic-gate 					{
12240Sstevel@tonic-gate 					char *dataptr;
12250Sstevel@tonic-gate 
12260Sstevel@tonic-gate 					if (INT_MAX < num)
12270Sstevel@tonic-gate 						num = INT_MAX;
12280Sstevel@tonic-gate 
12290Sstevel@tonic-gate 					if (num > 1)
12300Sstevel@tonic-gate 						--num; /* test restartability even more thoroughly */
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate 					r = BIO_nwrite0(io1, &dataptr);
12330Sstevel@tonic-gate 					assert(r > 0);
12340Sstevel@tonic-gate 					if (r < (int)num)
12350Sstevel@tonic-gate 						num = r;
12360Sstevel@tonic-gate 					r = BIO_read(io2, dataptr, (int)num);
12370Sstevel@tonic-gate 					if (r != (int)num) /* can't happen */
12380Sstevel@tonic-gate 						{
12390Sstevel@tonic-gate 						fprintf(stderr, "ERROR: BIO_read could not read "
12400Sstevel@tonic-gate 							"BIO_ctrl_pending() bytes");
12410Sstevel@tonic-gate 						goto err;
12420Sstevel@tonic-gate 						}
12430Sstevel@tonic-gate 					progress = 1;
12440Sstevel@tonic-gate 					r = BIO_nwrite(io1, &dataptr, (int)num);
12450Sstevel@tonic-gate 					if (r != (int)num) /* can't happen */
12460Sstevel@tonic-gate 						{
12470Sstevel@tonic-gate 						fprintf(stderr, "ERROR: BIO_nwrite() did not accept "
12480Sstevel@tonic-gate 							"BIO_nwrite0() bytes");
12490Sstevel@tonic-gate 						goto err;
12500Sstevel@tonic-gate 						}
12510Sstevel@tonic-gate 
12520Sstevel@tonic-gate 					if (debug)
12530Sstevel@tonic-gate 						printf((io2 == client_io) ?
12540Sstevel@tonic-gate 							"C->S relaying: %d bytes\n" :
12550Sstevel@tonic-gate 							"S->C relaying: %d bytes\n",
12560Sstevel@tonic-gate 							(int)num);
12570Sstevel@tonic-gate 					}
12580Sstevel@tonic-gate 			} /* no loop, BIO_ctrl_get_read_request now returns 0 anyway */
12590Sstevel@tonic-gate 
12600Sstevel@tonic-gate 			if (!progress && !prev_progress)
12610Sstevel@tonic-gate 				if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0)
12620Sstevel@tonic-gate 					{
12630Sstevel@tonic-gate 					fprintf(stderr, "ERROR: got stuck\n");
12640Sstevel@tonic-gate 					if (strcmp("SSLv2", SSL_get_version(c_ssl)) == 0)
12650Sstevel@tonic-gate 						{
12660Sstevel@tonic-gate 						fprintf(stderr, "This can happen for SSL2 because "
12670Sstevel@tonic-gate 							"CLIENT-FINISHED and SERVER-VERIFY are written \n"
12680Sstevel@tonic-gate 							"concurrently ...");
12690Sstevel@tonic-gate 						if (strncmp("2SCF", SSL_state_string(c_ssl), 4) == 0
12700Sstevel@tonic-gate 							&& strncmp("2SSV", SSL_state_string(s_ssl), 4) == 0)
12710Sstevel@tonic-gate 							{
12720Sstevel@tonic-gate 							fprintf(stderr, " ok.\n");
12730Sstevel@tonic-gate 							goto end;
12740Sstevel@tonic-gate 							}
12750Sstevel@tonic-gate 						}
12760Sstevel@tonic-gate 					fprintf(stderr, " ERROR.\n");
12770Sstevel@tonic-gate 					goto err;
12780Sstevel@tonic-gate 					}
12790Sstevel@tonic-gate 			prev_progress = progress;
12800Sstevel@tonic-gate 			}
12810Sstevel@tonic-gate 		}
12820Sstevel@tonic-gate 	while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0);
12830Sstevel@tonic-gate 
12840Sstevel@tonic-gate 	if (verbose)
12850Sstevel@tonic-gate 		print_details(c_ssl, "DONE via BIO pair: ");
12860Sstevel@tonic-gate end:
12870Sstevel@tonic-gate 	ret = 0;
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate  err:
12900Sstevel@tonic-gate 	ERR_print_errors(bio_err);
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate 	if (server)
12930Sstevel@tonic-gate 		BIO_free(server);
12940Sstevel@tonic-gate 	if (server_io)
12950Sstevel@tonic-gate 		BIO_free(server_io);
12960Sstevel@tonic-gate 	if (client)
12970Sstevel@tonic-gate 		BIO_free(client);
12980Sstevel@tonic-gate 	if (client_io)
12990Sstevel@tonic-gate 		BIO_free(client_io);
13000Sstevel@tonic-gate 	if (s_ssl_bio)
13010Sstevel@tonic-gate 		BIO_free(s_ssl_bio);
13020Sstevel@tonic-gate 	if (c_ssl_bio)
13030Sstevel@tonic-gate 		BIO_free(c_ssl_bio);
13040Sstevel@tonic-gate 
13050Sstevel@tonic-gate 	return ret;
13060Sstevel@tonic-gate 	}
13070Sstevel@tonic-gate 
13080Sstevel@tonic-gate 
13090Sstevel@tonic-gate #define W_READ	1
13100Sstevel@tonic-gate #define W_WRITE	2
13110Sstevel@tonic-gate #define C_DONE	1
13120Sstevel@tonic-gate #define S_DONE	2
13130Sstevel@tonic-gate 
doit(SSL * s_ssl,SSL * c_ssl,long count)13140Sstevel@tonic-gate int doit(SSL *s_ssl, SSL *c_ssl, long count)
13150Sstevel@tonic-gate 	{
13160Sstevel@tonic-gate 	MS_STATIC char cbuf[1024*8],sbuf[1024*8];
13170Sstevel@tonic-gate 	long cw_num=count,cr_num=count;
13180Sstevel@tonic-gate 	long sw_num=count,sr_num=count;
13190Sstevel@tonic-gate 	int ret=1;
13200Sstevel@tonic-gate 	BIO *c_to_s=NULL;
13210Sstevel@tonic-gate 	BIO *s_to_c=NULL;
13220Sstevel@tonic-gate 	BIO *c_bio=NULL;
13230Sstevel@tonic-gate 	BIO *s_bio=NULL;
13240Sstevel@tonic-gate 	int c_r,c_w,s_r,s_w;
13250Sstevel@tonic-gate 	int c_want,s_want;
13260Sstevel@tonic-gate 	int i,j;
13270Sstevel@tonic-gate 	int done=0;
13280Sstevel@tonic-gate 	int c_write,s_write;
13290Sstevel@tonic-gate 	int do_server=0,do_client=0;
13300Sstevel@tonic-gate 
13310Sstevel@tonic-gate 	memset(cbuf,0,sizeof(cbuf));
13320Sstevel@tonic-gate 	memset(sbuf,0,sizeof(sbuf));
13330Sstevel@tonic-gate 
13340Sstevel@tonic-gate 	c_to_s=BIO_new(BIO_s_mem());
13350Sstevel@tonic-gate 	s_to_c=BIO_new(BIO_s_mem());
13360Sstevel@tonic-gate 	if ((s_to_c == NULL) || (c_to_s == NULL))
13370Sstevel@tonic-gate 		{
13380Sstevel@tonic-gate 		ERR_print_errors(bio_err);
13390Sstevel@tonic-gate 		goto err;
13400Sstevel@tonic-gate 		}
13410Sstevel@tonic-gate 
13420Sstevel@tonic-gate 	c_bio=BIO_new(BIO_f_ssl());
13430Sstevel@tonic-gate 	s_bio=BIO_new(BIO_f_ssl());
13440Sstevel@tonic-gate 	if ((c_bio == NULL) || (s_bio == NULL))
13450Sstevel@tonic-gate 		{
13460Sstevel@tonic-gate 		ERR_print_errors(bio_err);
13470Sstevel@tonic-gate 		goto err;
13480Sstevel@tonic-gate 		}
13490Sstevel@tonic-gate 
13500Sstevel@tonic-gate 	SSL_set_connect_state(c_ssl);
13510Sstevel@tonic-gate 	SSL_set_bio(c_ssl,s_to_c,c_to_s);
13520Sstevel@tonic-gate 	BIO_set_ssl(c_bio,c_ssl,BIO_NOCLOSE);
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 	SSL_set_accept_state(s_ssl);
13550Sstevel@tonic-gate 	SSL_set_bio(s_ssl,c_to_s,s_to_c);
13560Sstevel@tonic-gate 	BIO_set_ssl(s_bio,s_ssl,BIO_NOCLOSE);
13570Sstevel@tonic-gate 
13580Sstevel@tonic-gate 	c_r=0; s_r=1;
13590Sstevel@tonic-gate 	c_w=1; s_w=0;
13600Sstevel@tonic-gate 	c_want=W_WRITE;
13610Sstevel@tonic-gate 	s_want=0;
13620Sstevel@tonic-gate 	c_write=1,s_write=0;
13630Sstevel@tonic-gate 
13640Sstevel@tonic-gate 	/* We can always do writes */
13650Sstevel@tonic-gate 	for (;;)
13660Sstevel@tonic-gate 		{
13670Sstevel@tonic-gate 		do_server=0;
13680Sstevel@tonic-gate 		do_client=0;
13690Sstevel@tonic-gate 
13700Sstevel@tonic-gate 		i=(int)BIO_pending(s_bio);
13710Sstevel@tonic-gate 		if ((i && s_r) || s_w) do_server=1;
13720Sstevel@tonic-gate 
13730Sstevel@tonic-gate 		i=(int)BIO_pending(c_bio);
13740Sstevel@tonic-gate 		if ((i && c_r) || c_w) do_client=1;
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate 		if (do_server && debug)
13770Sstevel@tonic-gate 			{
13780Sstevel@tonic-gate 			if (SSL_in_init(s_ssl))
13790Sstevel@tonic-gate 				printf("server waiting in SSL_accept - %s\n",
13800Sstevel@tonic-gate 					SSL_state_string_long(s_ssl));
13810Sstevel@tonic-gate /*			else if (s_write)
13820Sstevel@tonic-gate 				printf("server:SSL_write()\n");
13830Sstevel@tonic-gate 			else
13840Sstevel@tonic-gate 				printf("server:SSL_read()\n"); */
13850Sstevel@tonic-gate 			}
13860Sstevel@tonic-gate 
13870Sstevel@tonic-gate 		if (do_client && debug)
13880Sstevel@tonic-gate 			{
13890Sstevel@tonic-gate 			if (SSL_in_init(c_ssl))
13900Sstevel@tonic-gate 				printf("client waiting in SSL_connect - %s\n",
13910Sstevel@tonic-gate 					SSL_state_string_long(c_ssl));
13920Sstevel@tonic-gate /*			else if (c_write)
13930Sstevel@tonic-gate 				printf("client:SSL_write()\n");
13940Sstevel@tonic-gate 			else
13950Sstevel@tonic-gate 				printf("client:SSL_read()\n"); */
13960Sstevel@tonic-gate 			}
13970Sstevel@tonic-gate 
13980Sstevel@tonic-gate 		if (!do_client && !do_server)
13990Sstevel@tonic-gate 			{
14000Sstevel@tonic-gate 			fprintf(stdout,"ERROR IN STARTUP\n");
14010Sstevel@tonic-gate 			ERR_print_errors(bio_err);
14020Sstevel@tonic-gate 			break;
14030Sstevel@tonic-gate 			}
14040Sstevel@tonic-gate 		if (do_client && !(done & C_DONE))
14050Sstevel@tonic-gate 			{
14060Sstevel@tonic-gate 			if (c_write)
14070Sstevel@tonic-gate 				{
14082139Sjp161948 				j = (cw_num > (long)sizeof(cbuf)) ?
14092139Sjp161948 					(int)sizeof(cbuf) : (int)cw_num;
14100Sstevel@tonic-gate 				i=BIO_write(c_bio,cbuf,j);
14110Sstevel@tonic-gate 				if (i < 0)
14120Sstevel@tonic-gate 					{
14130Sstevel@tonic-gate 					c_r=0;
14140Sstevel@tonic-gate 					c_w=0;
14150Sstevel@tonic-gate 					if (BIO_should_retry(c_bio))
14160Sstevel@tonic-gate 						{
14170Sstevel@tonic-gate 						if (BIO_should_read(c_bio))
14180Sstevel@tonic-gate 							c_r=1;
14190Sstevel@tonic-gate 						if (BIO_should_write(c_bio))
14200Sstevel@tonic-gate 							c_w=1;
14210Sstevel@tonic-gate 						}
14220Sstevel@tonic-gate 					else
14230Sstevel@tonic-gate 						{
14240Sstevel@tonic-gate 						fprintf(stderr,"ERROR in CLIENT\n");
14250Sstevel@tonic-gate 						ERR_print_errors(bio_err);
14260Sstevel@tonic-gate 						goto err;
14270Sstevel@tonic-gate 						}
14280Sstevel@tonic-gate 					}
14290Sstevel@tonic-gate 				else if (i == 0)
14300Sstevel@tonic-gate 					{
14310Sstevel@tonic-gate 					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
14320Sstevel@tonic-gate 					goto err;
14330Sstevel@tonic-gate 					}
14340Sstevel@tonic-gate 				else
14350Sstevel@tonic-gate 					{
14360Sstevel@tonic-gate 					if (debug)
14370Sstevel@tonic-gate 						printf("client wrote %d\n",i);
14380Sstevel@tonic-gate 					/* ok */
14390Sstevel@tonic-gate 					s_r=1;
14400Sstevel@tonic-gate 					c_write=0;
14410Sstevel@tonic-gate 					cw_num-=i;
14420Sstevel@tonic-gate 					}
14430Sstevel@tonic-gate 				}
14440Sstevel@tonic-gate 			else
14450Sstevel@tonic-gate 				{
14460Sstevel@tonic-gate 				i=BIO_read(c_bio,cbuf,sizeof(cbuf));
14470Sstevel@tonic-gate 				if (i < 0)
14480Sstevel@tonic-gate 					{
14490Sstevel@tonic-gate 					c_r=0;
14500Sstevel@tonic-gate 					c_w=0;
14510Sstevel@tonic-gate 					if (BIO_should_retry(c_bio))
14520Sstevel@tonic-gate 						{
14530Sstevel@tonic-gate 						if (BIO_should_read(c_bio))
14540Sstevel@tonic-gate 							c_r=1;
14550Sstevel@tonic-gate 						if (BIO_should_write(c_bio))
14560Sstevel@tonic-gate 							c_w=1;
14570Sstevel@tonic-gate 						}
14580Sstevel@tonic-gate 					else
14590Sstevel@tonic-gate 						{
14600Sstevel@tonic-gate 						fprintf(stderr,"ERROR in CLIENT\n");
14610Sstevel@tonic-gate 						ERR_print_errors(bio_err);
14620Sstevel@tonic-gate 						goto err;
14630Sstevel@tonic-gate 						}
14640Sstevel@tonic-gate 					}
14650Sstevel@tonic-gate 				else if (i == 0)
14660Sstevel@tonic-gate 					{
14670Sstevel@tonic-gate 					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
14680Sstevel@tonic-gate 					goto err;
14690Sstevel@tonic-gate 					}
14700Sstevel@tonic-gate 				else
14710Sstevel@tonic-gate 					{
14720Sstevel@tonic-gate 					if (debug)
14730Sstevel@tonic-gate 						printf("client read %d\n",i);
14740Sstevel@tonic-gate 					cr_num-=i;
14750Sstevel@tonic-gate 					if (sw_num > 0)
14760Sstevel@tonic-gate 						{
14770Sstevel@tonic-gate 						s_write=1;
14780Sstevel@tonic-gate 						s_w=1;
14790Sstevel@tonic-gate 						}
14800Sstevel@tonic-gate 					if (cr_num <= 0)
14810Sstevel@tonic-gate 						{
14820Sstevel@tonic-gate 						s_write=1;
14830Sstevel@tonic-gate 						s_w=1;
14840Sstevel@tonic-gate 						done=S_DONE|C_DONE;
14850Sstevel@tonic-gate 						}
14860Sstevel@tonic-gate 					}
14870Sstevel@tonic-gate 				}
14880Sstevel@tonic-gate 			}
14890Sstevel@tonic-gate 
14900Sstevel@tonic-gate 		if (do_server && !(done & S_DONE))
14910Sstevel@tonic-gate 			{
14920Sstevel@tonic-gate 			if (!s_write)
14930Sstevel@tonic-gate 				{
14940Sstevel@tonic-gate 				i=BIO_read(s_bio,sbuf,sizeof(cbuf));
14950Sstevel@tonic-gate 				if (i < 0)
14960Sstevel@tonic-gate 					{
14970Sstevel@tonic-gate 					s_r=0;
14980Sstevel@tonic-gate 					s_w=0;
14990Sstevel@tonic-gate 					if (BIO_should_retry(s_bio))
15000Sstevel@tonic-gate 						{
15010Sstevel@tonic-gate 						if (BIO_should_read(s_bio))
15020Sstevel@tonic-gate 							s_r=1;
15030Sstevel@tonic-gate 						if (BIO_should_write(s_bio))
15040Sstevel@tonic-gate 							s_w=1;
15050Sstevel@tonic-gate 						}
15060Sstevel@tonic-gate 					else
15070Sstevel@tonic-gate 						{
15080Sstevel@tonic-gate 						fprintf(stderr,"ERROR in SERVER\n");
15090Sstevel@tonic-gate 						ERR_print_errors(bio_err);
15100Sstevel@tonic-gate 						goto err;
15110Sstevel@tonic-gate 						}
15120Sstevel@tonic-gate 					}
15130Sstevel@tonic-gate 				else if (i == 0)
15140Sstevel@tonic-gate 					{
15150Sstevel@tonic-gate 					ERR_print_errors(bio_err);
15160Sstevel@tonic-gate 					fprintf(stderr,"SSL SERVER STARTUP FAILED in SSL_read\n");
15170Sstevel@tonic-gate 					goto err;
15180Sstevel@tonic-gate 					}
15190Sstevel@tonic-gate 				else
15200Sstevel@tonic-gate 					{
15210Sstevel@tonic-gate 					if (debug)
15220Sstevel@tonic-gate 						printf("server read %d\n",i);
15230Sstevel@tonic-gate 					sr_num-=i;
15240Sstevel@tonic-gate 					if (cw_num > 0)
15250Sstevel@tonic-gate 						{
15260Sstevel@tonic-gate 						c_write=1;
15270Sstevel@tonic-gate 						c_w=1;
15280Sstevel@tonic-gate 						}
15290Sstevel@tonic-gate 					if (sr_num <= 0)
15300Sstevel@tonic-gate 						{
15310Sstevel@tonic-gate 						s_write=1;
15320Sstevel@tonic-gate 						s_w=1;
15330Sstevel@tonic-gate 						c_write=0;
15340Sstevel@tonic-gate 						}
15350Sstevel@tonic-gate 					}
15360Sstevel@tonic-gate 				}
15370Sstevel@tonic-gate 			else
15380Sstevel@tonic-gate 				{
15392139Sjp161948 				j = (sw_num > (long)sizeof(sbuf)) ?
15402139Sjp161948 					(int)sizeof(sbuf) : (int)sw_num;
15410Sstevel@tonic-gate 				i=BIO_write(s_bio,sbuf,j);
15420Sstevel@tonic-gate 				if (i < 0)
15430Sstevel@tonic-gate 					{
15440Sstevel@tonic-gate 					s_r=0;
15450Sstevel@tonic-gate 					s_w=0;
15460Sstevel@tonic-gate 					if (BIO_should_retry(s_bio))
15470Sstevel@tonic-gate 						{
15480Sstevel@tonic-gate 						if (BIO_should_read(s_bio))
15490Sstevel@tonic-gate 							s_r=1;
15500Sstevel@tonic-gate 						if (BIO_should_write(s_bio))
15510Sstevel@tonic-gate 							s_w=1;
15520Sstevel@tonic-gate 						}
15530Sstevel@tonic-gate 					else
15540Sstevel@tonic-gate 						{
15550Sstevel@tonic-gate 						fprintf(stderr,"ERROR in SERVER\n");
15560Sstevel@tonic-gate 						ERR_print_errors(bio_err);
15570Sstevel@tonic-gate 						goto err;
15580Sstevel@tonic-gate 						}
15590Sstevel@tonic-gate 					}
15600Sstevel@tonic-gate 				else if (i == 0)
15610Sstevel@tonic-gate 					{
15620Sstevel@tonic-gate 					ERR_print_errors(bio_err);
15630Sstevel@tonic-gate 					fprintf(stderr,"SSL SERVER STARTUP FAILED in SSL_write\n");
15640Sstevel@tonic-gate 					goto err;
15650Sstevel@tonic-gate 					}
15660Sstevel@tonic-gate 				else
15670Sstevel@tonic-gate 					{
15680Sstevel@tonic-gate 					if (debug)
15690Sstevel@tonic-gate 						printf("server wrote %d\n",i);
15700Sstevel@tonic-gate 					sw_num-=i;
15710Sstevel@tonic-gate 					s_write=0;
15720Sstevel@tonic-gate 					c_r=1;
15730Sstevel@tonic-gate 					if (sw_num <= 0)
15740Sstevel@tonic-gate 						done|=S_DONE;
15750Sstevel@tonic-gate 					}
15760Sstevel@tonic-gate 				}
15770Sstevel@tonic-gate 			}
15780Sstevel@tonic-gate 
15790Sstevel@tonic-gate 		if ((done & S_DONE) && (done & C_DONE)) break;
15800Sstevel@tonic-gate 		}
15810Sstevel@tonic-gate 
15820Sstevel@tonic-gate 	if (verbose)
15830Sstevel@tonic-gate 		print_details(c_ssl, "DONE: ");
15840Sstevel@tonic-gate 	ret=0;
15850Sstevel@tonic-gate err:
15860Sstevel@tonic-gate 	/* We have to set the BIO's to NULL otherwise they will be
15870Sstevel@tonic-gate 	 * OPENSSL_free()ed twice.  Once when th s_ssl is SSL_free()ed and
15880Sstevel@tonic-gate 	 * again when c_ssl is SSL_free()ed.
15890Sstevel@tonic-gate 	 * This is a hack required because s_ssl and c_ssl are sharing the same
15900Sstevel@tonic-gate 	 * BIO structure and SSL_set_bio() and SSL_free() automatically
15910Sstevel@tonic-gate 	 * BIO_free non NULL entries.
15920Sstevel@tonic-gate 	 * You should not normally do this or be required to do this */
15930Sstevel@tonic-gate 	if (s_ssl != NULL)
15940Sstevel@tonic-gate 		{
15950Sstevel@tonic-gate 		s_ssl->rbio=NULL;
15960Sstevel@tonic-gate 		s_ssl->wbio=NULL;
15970Sstevel@tonic-gate 		}
15980Sstevel@tonic-gate 	if (c_ssl != NULL)
15990Sstevel@tonic-gate 		{
16000Sstevel@tonic-gate 		c_ssl->rbio=NULL;
16010Sstevel@tonic-gate 		c_ssl->wbio=NULL;
16020Sstevel@tonic-gate 		}
16030Sstevel@tonic-gate 
16040Sstevel@tonic-gate 	if (c_to_s != NULL) BIO_free(c_to_s);
16050Sstevel@tonic-gate 	if (s_to_c != NULL) BIO_free(s_to_c);
16060Sstevel@tonic-gate 	if (c_bio != NULL) BIO_free_all(c_bio);
16070Sstevel@tonic-gate 	if (s_bio != NULL) BIO_free_all(s_bio);
16080Sstevel@tonic-gate 	return(ret);
16090Sstevel@tonic-gate 	}
16100Sstevel@tonic-gate 
get_proxy_auth_ex_data_idx(void)16112139Sjp161948 static int get_proxy_auth_ex_data_idx(void)
16122139Sjp161948 	{
16132139Sjp161948 	static volatile int idx = -1;
16142139Sjp161948 	if (idx < 0)
16152139Sjp161948 		{
16162139Sjp161948 		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
16172139Sjp161948 		if (idx < 0)
16182139Sjp161948 			{
16192139Sjp161948 			idx = X509_STORE_CTX_get_ex_new_index(0,
16202139Sjp161948 				"SSLtest for verify callback", NULL,NULL,NULL);
16212139Sjp161948 			}
16222139Sjp161948 		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
16232139Sjp161948 		}
16242139Sjp161948 	return idx;
16252139Sjp161948 	}
16262139Sjp161948 
verify_callback(int ok,X509_STORE_CTX * ctx)16270Sstevel@tonic-gate static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
16280Sstevel@tonic-gate 	{
16290Sstevel@tonic-gate 	char *s,buf[256];
16300Sstevel@tonic-gate 
16310Sstevel@tonic-gate 	s=X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),buf,
16320Sstevel@tonic-gate 			    sizeof buf);
16330Sstevel@tonic-gate 	if (s != NULL)
16340Sstevel@tonic-gate 		{
16350Sstevel@tonic-gate 		if (ok)
16362139Sjp161948 			fprintf(stderr,"depth=%d %s\n",
16372139Sjp161948 				ctx->error_depth,buf);
16380Sstevel@tonic-gate 		else
16392139Sjp161948 			{
16400Sstevel@tonic-gate 			fprintf(stderr,"depth=%d error=%d %s\n",
16410Sstevel@tonic-gate 				ctx->error_depth,ctx->error,buf);
16422139Sjp161948 			}
16430Sstevel@tonic-gate 		}
16440Sstevel@tonic-gate 
16450Sstevel@tonic-gate 	if (ok == 0)
16460Sstevel@tonic-gate 		{
16472139Sjp161948 		fprintf(stderr,"Error string: %s\n",
16482139Sjp161948 			X509_verify_cert_error_string(ctx->error));
16490Sstevel@tonic-gate 		switch (ctx->error)
16500Sstevel@tonic-gate 			{
16510Sstevel@tonic-gate 		case X509_V_ERR_CERT_NOT_YET_VALID:
16520Sstevel@tonic-gate 		case X509_V_ERR_CERT_HAS_EXPIRED:
16530Sstevel@tonic-gate 		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
16542139Sjp161948 			fprintf(stderr,"  ... ignored.\n");
16550Sstevel@tonic-gate 			ok=1;
16560Sstevel@tonic-gate 			}
16570Sstevel@tonic-gate 		}
16580Sstevel@tonic-gate 
16592139Sjp161948 	if (ok == 1)
16602139Sjp161948 		{
16612139Sjp161948 		X509 *xs = ctx->current_cert;
16622139Sjp161948 #if 0
16632139Sjp161948 		X509 *xi = ctx->current_issuer;
16642139Sjp161948 #endif
16652139Sjp161948 
16662139Sjp161948 		if (xs->ex_flags & EXFLAG_PROXY)
16672139Sjp161948 			{
16682139Sjp161948 			unsigned int *letters =
16692139Sjp161948 				X509_STORE_CTX_get_ex_data(ctx,
16702139Sjp161948 					get_proxy_auth_ex_data_idx());
16712139Sjp161948 
16722139Sjp161948 			if (letters)
16732139Sjp161948 				{
16742139Sjp161948 				int found_any = 0;
16752139Sjp161948 				int i;
16762139Sjp161948 				PROXY_CERT_INFO_EXTENSION *pci =
16772139Sjp161948 					X509_get_ext_d2i(xs, NID_proxyCertInfo,
16782139Sjp161948 						NULL, NULL);
16792139Sjp161948 
16802139Sjp161948 				switch (OBJ_obj2nid(pci->proxyPolicy->policyLanguage))
16812139Sjp161948 					{
16822139Sjp161948 				case NID_Independent:
16832139Sjp161948 					/* Completely meaningless in this
16842139Sjp161948 					   program, as there's no way to
16852139Sjp161948 					   grant explicit rights to a
16862139Sjp161948 					   specific PrC.  Basically, using
16872139Sjp161948 					   id-ppl-Independent is the perfect
16882139Sjp161948 					   way to grant no rights at all. */
16892139Sjp161948 					fprintf(stderr, "  Independent proxy certificate");
16902139Sjp161948 					for (i = 0; i < 26; i++)
16912139Sjp161948 						letters[i] = 0;
16922139Sjp161948 					break;
16932139Sjp161948 				case NID_id_ppl_inheritAll:
16942139Sjp161948 					/* This is basically a NOP, we
16952139Sjp161948 					   simply let the current rights
16962139Sjp161948 					   stand as they are. */
16972139Sjp161948 					fprintf(stderr, "  Proxy certificate inherits all");
16982139Sjp161948 					break;
16992139Sjp161948 				default:
17002139Sjp161948 					s = (char *)
17012139Sjp161948 						pci->proxyPolicy->policy->data;
17022139Sjp161948 					i = pci->proxyPolicy->policy->length;
17032139Sjp161948 
17042139Sjp161948 					/* The algorithm works as follows:
17052139Sjp161948 					   it is assumed that previous
17062139Sjp161948 					   iterations or the initial granted
17072139Sjp161948 					   rights has already set some elements
17082139Sjp161948 					   of `letters'.  What we need to do is
17092139Sjp161948 					   to clear those that weren't granted
17102139Sjp161948 					   by the current PrC as well.  The
17112139Sjp161948 					   easiest way to do this is to add 1
17122139Sjp161948 					   to all the elements whose letters
17132139Sjp161948 					   are given with the current policy.
17142139Sjp161948 					   That way, all elements that are set
17152139Sjp161948 					   by the current policy and were
17162139Sjp161948 					   already set by earlier policies and
17172139Sjp161948 					   through the original grant of rights
17182139Sjp161948 					   will get the value 2 or higher.
17192139Sjp161948 					   The last thing to do is to sweep
17202139Sjp161948 					   through `letters' and keep the
17212139Sjp161948 					   elements having the value 2 as set,
17222139Sjp161948 					   and clear all the others. */
17232139Sjp161948 
17242139Sjp161948 					fprintf(stderr, "  Certificate proxy rights = %*.*s", i, i, s);
17252139Sjp161948 					while(i-- > 0)
17262139Sjp161948 						{
17272139Sjp161948 						int c = *s++;
17282139Sjp161948 						if (isascii(c) && isalpha(c))
17292139Sjp161948 							{
17302139Sjp161948 							if (islower(c))
17312139Sjp161948 								c = toupper(c);
17322139Sjp161948 							letters[c - 'A']++;
17332139Sjp161948 							}
17342139Sjp161948 						}
17352139Sjp161948 					for (i = 0; i < 26; i++)
17362139Sjp161948 						if (letters[i] < 2)
17372139Sjp161948 							letters[i] = 0;
17382139Sjp161948 						else
17392139Sjp161948 							letters[i] = 1;
17402139Sjp161948 					}
17412139Sjp161948 
17422139Sjp161948 				found_any = 0;
17432139Sjp161948 				fprintf(stderr,
17442139Sjp161948 					", resulting proxy rights = ");
17452139Sjp161948 				for(i = 0; i < 26; i++)
17462139Sjp161948 					if (letters[i])
17472139Sjp161948 						{
17482139Sjp161948 						fprintf(stderr, "%c", i + 'A');
17492139Sjp161948 						found_any = 1;
17502139Sjp161948 						}
17512139Sjp161948 				if (!found_any)
17522139Sjp161948 					fprintf(stderr, "none");
17532139Sjp161948 				fprintf(stderr, "\n");
17542139Sjp161948 
17552139Sjp161948 				PROXY_CERT_INFO_EXTENSION_free(pci);
17562139Sjp161948 				}
17572139Sjp161948 			}
17582139Sjp161948 		}
17592139Sjp161948 
17600Sstevel@tonic-gate 	return(ok);
17610Sstevel@tonic-gate 	}
17620Sstevel@tonic-gate 
process_proxy_debug(int indent,const char * format,...)17632139Sjp161948 static void process_proxy_debug(int indent, const char *format, ...)
17642139Sjp161948 	{
17652139Sjp161948 	static const char indentation[] =
17662139Sjp161948 		">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
17672139Sjp161948 		">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; /* That's 80 > */
17682139Sjp161948 	char my_format[256];
17692139Sjp161948 	va_list args;
17702139Sjp161948 
17712139Sjp161948 	BIO_snprintf(my_format, sizeof(my_format), "%*.*s %s",
17722139Sjp161948 		indent, indent, indentation, format);
17732139Sjp161948 
17742139Sjp161948 	va_start(args, format);
17752139Sjp161948 	vfprintf(stderr, my_format, args);
17762139Sjp161948 	va_end(args);
17772139Sjp161948 	}
17782139Sjp161948 /* Priority levels:
17792139Sjp161948    0	[!]var, ()
17802139Sjp161948    1	& ^
17812139Sjp161948    2	|
17822139Sjp161948 */
17832139Sjp161948 static int process_proxy_cond_adders(unsigned int letters[26],
17842139Sjp161948 	const char *cond, const char **cond_end, int *pos, int indent);
process_proxy_cond_val(unsigned int letters[26],const char * cond,const char ** cond_end,int * pos,int indent)17852139Sjp161948 static int process_proxy_cond_val(unsigned int letters[26],
17862139Sjp161948 	const char *cond, const char **cond_end, int *pos, int indent)
17872139Sjp161948 	{
17882139Sjp161948 	int c;
17892139Sjp161948 	int ok = 1;
17902139Sjp161948 	int negate = 0;
17912139Sjp161948 
17922139Sjp161948 	while(isspace((int)*cond))
17932139Sjp161948 		{
17942139Sjp161948 		cond++; (*pos)++;
17952139Sjp161948 		}
17962139Sjp161948 	c = *cond;
17972139Sjp161948 
17982139Sjp161948 	if (debug)
17992139Sjp161948 		process_proxy_debug(indent,
18002139Sjp161948 			"Start process_proxy_cond_val at position %d: %s\n",
18012139Sjp161948 			*pos, cond);
18022139Sjp161948 
18032139Sjp161948 	while(c == '!')
18042139Sjp161948 		{
18052139Sjp161948 		negate = !negate;
18062139Sjp161948 		cond++; (*pos)++;
18072139Sjp161948 		while(isspace((int)*cond))
18082139Sjp161948 			{
18092139Sjp161948 			cond++; (*pos)++;
18102139Sjp161948 			}
18112139Sjp161948 		c = *cond;
18122139Sjp161948 		}
18132139Sjp161948 
18142139Sjp161948 	if (c == '(')
18152139Sjp161948 		{
18162139Sjp161948 		cond++; (*pos)++;
18172139Sjp161948 		ok = process_proxy_cond_adders(letters, cond, cond_end, pos,
18182139Sjp161948 			indent + 1);
18192139Sjp161948 		cond = *cond_end;
18202139Sjp161948 		if (ok < 0)
18212139Sjp161948 			goto end;
18222139Sjp161948 		while(isspace((int)*cond))
18232139Sjp161948 			{
18242139Sjp161948 			cond++; (*pos)++;
18252139Sjp161948 			}
18262139Sjp161948 		c = *cond;
18272139Sjp161948 		if (c != ')')
18282139Sjp161948 			{
18292139Sjp161948 			fprintf(stderr,
18302139Sjp161948 				"Weird condition character in position %d: "
18312139Sjp161948 				"%c\n", *pos, c);
18322139Sjp161948 			ok = -1;
18332139Sjp161948 			goto end;
18342139Sjp161948 			}
18352139Sjp161948 		cond++; (*pos)++;
18362139Sjp161948 		}
18372139Sjp161948 	else if (isascii(c) && isalpha(c))
18382139Sjp161948 		{
18392139Sjp161948 		if (islower(c))
18402139Sjp161948 			c = toupper(c);
18412139Sjp161948 		ok = letters[c - 'A'];
18422139Sjp161948 		cond++; (*pos)++;
18432139Sjp161948 		}
18442139Sjp161948 	else
18452139Sjp161948 		{
18462139Sjp161948 		fprintf(stderr,
18472139Sjp161948 			"Weird condition character in position %d: "
18482139Sjp161948 			"%c\n", *pos, c);
18492139Sjp161948 		ok = -1;
18502139Sjp161948 		goto end;
18512139Sjp161948 		}
18522139Sjp161948  end:
18532139Sjp161948 	*cond_end = cond;
18542139Sjp161948 	if (ok >= 0 && negate)
18552139Sjp161948 		ok = !ok;
18562139Sjp161948 
18572139Sjp161948 	if (debug)
18582139Sjp161948 		process_proxy_debug(indent,
18592139Sjp161948 			"End process_proxy_cond_val at position %d: %s, returning %d\n",
18602139Sjp161948 			*pos, cond, ok);
18612139Sjp161948 
18622139Sjp161948 	return ok;
18632139Sjp161948 	}
process_proxy_cond_multipliers(unsigned int letters[26],const char * cond,const char ** cond_end,int * pos,int indent)18642139Sjp161948 static int process_proxy_cond_multipliers(unsigned int letters[26],
18652139Sjp161948 	const char *cond, const char **cond_end, int *pos, int indent)
18662139Sjp161948 	{
18672139Sjp161948 	int ok;
18682139Sjp161948 	char c;
18692139Sjp161948 
18702139Sjp161948 	if (debug)
18712139Sjp161948 		process_proxy_debug(indent,
18722139Sjp161948 			"Start process_proxy_cond_multipliers at position %d: %s\n",
18732139Sjp161948 			*pos, cond);
18742139Sjp161948 
18752139Sjp161948 	ok = process_proxy_cond_val(letters, cond, cond_end, pos, indent + 1);
18762139Sjp161948 	cond = *cond_end;
18772139Sjp161948 	if (ok < 0)
18782139Sjp161948 		goto end;
18792139Sjp161948 
18802139Sjp161948 	while(ok >= 0)
18812139Sjp161948 		{
18822139Sjp161948 		while(isspace((int)*cond))
18832139Sjp161948 			{
18842139Sjp161948 			cond++; (*pos)++;
18852139Sjp161948 			}
18862139Sjp161948 		c = *cond;
18872139Sjp161948 
18882139Sjp161948 		switch(c)
18892139Sjp161948 			{
18902139Sjp161948 		case '&':
18912139Sjp161948 		case '^':
18922139Sjp161948 			{
18932139Sjp161948 			int save_ok = ok;
18942139Sjp161948 
18952139Sjp161948 			cond++; (*pos)++;
18962139Sjp161948 			ok = process_proxy_cond_val(letters,
18972139Sjp161948 				cond, cond_end, pos, indent + 1);
18982139Sjp161948 			cond = *cond_end;
18992139Sjp161948 			if (ok < 0)
19002139Sjp161948 				break;
19012139Sjp161948 
19022139Sjp161948 			switch(c)
19032139Sjp161948 				{
19042139Sjp161948 			case '&':
19052139Sjp161948 				ok &= save_ok;
19062139Sjp161948 				break;
19072139Sjp161948 			case '^':
19082139Sjp161948 				ok ^= save_ok;
19092139Sjp161948 				break;
19102139Sjp161948 			default:
19112139Sjp161948 				fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!"
19122139Sjp161948 					" STOPPING\n");
19132139Sjp161948 				EXIT(1);
19142139Sjp161948 				}
19152139Sjp161948 			}
19162139Sjp161948 			break;
19172139Sjp161948 		default:
19182139Sjp161948 			goto end;
19192139Sjp161948 			}
19202139Sjp161948 		}
19212139Sjp161948  end:
19222139Sjp161948 	if (debug)
19232139Sjp161948 		process_proxy_debug(indent,
19242139Sjp161948 			"End process_proxy_cond_multipliers at position %d: %s, returning %d\n",
19252139Sjp161948 			*pos, cond, ok);
19262139Sjp161948 
19272139Sjp161948 	*cond_end = cond;
19282139Sjp161948 	return ok;
19292139Sjp161948 	}
process_proxy_cond_adders(unsigned int letters[26],const char * cond,const char ** cond_end,int * pos,int indent)19302139Sjp161948 static int process_proxy_cond_adders(unsigned int letters[26],
19312139Sjp161948 	const char *cond, const char **cond_end, int *pos, int indent)
19322139Sjp161948 	{
19332139Sjp161948 	int ok;
19342139Sjp161948 	char c;
19352139Sjp161948 
19362139Sjp161948 	if (debug)
19372139Sjp161948 		process_proxy_debug(indent,
19382139Sjp161948 			"Start process_proxy_cond_adders at position %d: %s\n",
19392139Sjp161948 			*pos, cond);
19402139Sjp161948 
19412139Sjp161948 	ok = process_proxy_cond_multipliers(letters, cond, cond_end, pos,
19422139Sjp161948 		indent + 1);
19432139Sjp161948 	cond = *cond_end;
19442139Sjp161948 	if (ok < 0)
19452139Sjp161948 		goto end;
19462139Sjp161948 
19472139Sjp161948 	while(ok >= 0)
19482139Sjp161948 		{
19492139Sjp161948 		while(isspace((int)*cond))
19502139Sjp161948 			{
19512139Sjp161948 			cond++; (*pos)++;
19522139Sjp161948 			}
19532139Sjp161948 		c = *cond;
19542139Sjp161948 
19552139Sjp161948 		switch(c)
19562139Sjp161948 			{
19572139Sjp161948 		case '|':
19582139Sjp161948 			{
19592139Sjp161948 			int save_ok = ok;
19602139Sjp161948 
19612139Sjp161948 			cond++; (*pos)++;
19622139Sjp161948 			ok = process_proxy_cond_multipliers(letters,
19632139Sjp161948 				cond, cond_end, pos, indent + 1);
19642139Sjp161948 			cond = *cond_end;
19652139Sjp161948 			if (ok < 0)
19662139Sjp161948 				break;
19672139Sjp161948 
19682139Sjp161948 			switch(c)
19692139Sjp161948 				{
19702139Sjp161948 			case '|':
19712139Sjp161948 				ok |= save_ok;
19722139Sjp161948 				break;
19732139Sjp161948 			default:
19742139Sjp161948 				fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!"
19752139Sjp161948 					" STOPPING\n");
19762139Sjp161948 				EXIT(1);
19772139Sjp161948 				}
19782139Sjp161948 			}
19792139Sjp161948 			break;
19802139Sjp161948 		default:
19812139Sjp161948 			goto end;
19822139Sjp161948 			}
19832139Sjp161948 		}
19842139Sjp161948  end:
19852139Sjp161948 	if (debug)
19862139Sjp161948 		process_proxy_debug(indent,
19872139Sjp161948 			"End process_proxy_cond_adders at position %d: %s, returning %d\n",
19882139Sjp161948 			*pos, cond, ok);
19892139Sjp161948 
19902139Sjp161948 	*cond_end = cond;
19912139Sjp161948 	return ok;
19922139Sjp161948 	}
19932139Sjp161948 
process_proxy_cond(unsigned int letters[26],const char * cond,const char ** cond_end)19942139Sjp161948 static int process_proxy_cond(unsigned int letters[26],
19952139Sjp161948 	const char *cond, const char **cond_end)
19962139Sjp161948 	{
19972139Sjp161948 	int pos = 1;
19982139Sjp161948 	return process_proxy_cond_adders(letters, cond, cond_end, &pos, 1);
19992139Sjp161948 	}
20002139Sjp161948 
app_verify_callback(X509_STORE_CTX * ctx,void * arg)20010Sstevel@tonic-gate static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg)
20020Sstevel@tonic-gate 	{
20030Sstevel@tonic-gate 	int ok=1;
20042139Sjp161948 	struct app_verify_arg *cb_arg = arg;
20052139Sjp161948 	unsigned int letters[26]; /* only used with proxy_auth */
20062139Sjp161948 
20072139Sjp161948 	if (cb_arg->app_verify)
20082139Sjp161948 		{
20092139Sjp161948 		char *s = NULL,buf[256];
20102139Sjp161948 
20112139Sjp161948 		fprintf(stderr, "In app_verify_callback, allowing cert. ");
20122139Sjp161948 		fprintf(stderr, "Arg is: %s\n", cb_arg->string);
20132139Sjp161948 		fprintf(stderr, "Finished printing do we have a context? 0x%p a cert? 0x%p\n",
20142139Sjp161948 			(void *)ctx, (void *)ctx->cert);
20152139Sjp161948 		if (ctx->cert)
20162139Sjp161948 			s=X509_NAME_oneline(X509_get_subject_name(ctx->cert),buf,256);
20172139Sjp161948 		if (s != NULL)
20182139Sjp161948 			{
20192139Sjp161948 			fprintf(stderr,"cert depth=%d %s\n",ctx->error_depth,buf);
20202139Sjp161948 			}
20212139Sjp161948 		return(1);
20222139Sjp161948 		}
20232139Sjp161948 	if (cb_arg->proxy_auth)
20242139Sjp161948 		{
20252139Sjp161948 		int found_any = 0, i;
20262139Sjp161948 		char *sp;
20270Sstevel@tonic-gate 
20282139Sjp161948 		for(i = 0; i < 26; i++)
20292139Sjp161948 			letters[i] = 0;
20302139Sjp161948 		for(sp = cb_arg->proxy_auth; *sp; sp++)
20312139Sjp161948 			{
20322139Sjp161948 			int c = *sp;
20332139Sjp161948 			if (isascii(c) && isalpha(c))
20342139Sjp161948 				{
20352139Sjp161948 				if (islower(c))
20362139Sjp161948 					c = toupper(c);
20372139Sjp161948 				letters[c - 'A'] = 1;
20382139Sjp161948 				}
20392139Sjp161948 			}
20402139Sjp161948 
20412139Sjp161948 		fprintf(stderr,
20422139Sjp161948 			"  Initial proxy rights = ");
20432139Sjp161948 		for(i = 0; i < 26; i++)
20442139Sjp161948 			if (letters[i])
20452139Sjp161948 				{
20462139Sjp161948 				fprintf(stderr, "%c", i + 'A');
20472139Sjp161948 				found_any = 1;
20482139Sjp161948 				}
20492139Sjp161948 		if (!found_any)
20502139Sjp161948 			fprintf(stderr, "none");
20512139Sjp161948 		fprintf(stderr, "\n");
20522139Sjp161948 
20532139Sjp161948 		X509_STORE_CTX_set_ex_data(ctx,
20542139Sjp161948 			get_proxy_auth_ex_data_idx(),letters);
20552139Sjp161948 		}
20562139Sjp161948 	if (cb_arg->allow_proxy_certs)
20570Sstevel@tonic-gate 		{
20582139Sjp161948 		X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
20590Sstevel@tonic-gate 		}
20600Sstevel@tonic-gate 
20612139Sjp161948 #ifndef OPENSSL_NO_X509_VERIFY
20622139Sjp161948 # ifdef OPENSSL_FIPS
20632139Sjp161948 	if(s->version == TLS1_VERSION)
20642139Sjp161948 		FIPS_allow_md5(1);
20652139Sjp161948 # endif
20662139Sjp161948 	ok = X509_verify_cert(ctx);
20672139Sjp161948 # ifdef OPENSSL_FIPS
20682139Sjp161948 	if(s->version == TLS1_VERSION)
20692139Sjp161948 		FIPS_allow_md5(0);
20702139Sjp161948 # endif
20712139Sjp161948 #endif
20722139Sjp161948 
20732139Sjp161948 	if (cb_arg->proxy_auth)
20742139Sjp161948 		{
2075*8545SJan.Pechanec@Sun.COM 		if (ok > 0)
20762139Sjp161948 			{
20772139Sjp161948 			const char *cond_end = NULL;
20782139Sjp161948 
20792139Sjp161948 			ok = process_proxy_cond(letters,
20802139Sjp161948 				cb_arg->proxy_cond, &cond_end);
20812139Sjp161948 
20822139Sjp161948 			if (ok < 0)
20832139Sjp161948 				EXIT(3);
20842139Sjp161948 			if (*cond_end)
20852139Sjp161948 				{
20862139Sjp161948 				fprintf(stderr, "Stopped processing condition before it's end.\n");
20872139Sjp161948 				ok = 0;
20882139Sjp161948 				}
20892139Sjp161948 			if (!ok)
20902139Sjp161948 				fprintf(stderr, "Proxy rights check with condition '%s' proved invalid\n",
20912139Sjp161948 					cb_arg->proxy_cond);
20922139Sjp161948 			else
20932139Sjp161948 				fprintf(stderr, "Proxy rights check with condition '%s' proved valid\n",
20942139Sjp161948 					cb_arg->proxy_cond);
20952139Sjp161948 			}
20962139Sjp161948 		}
20970Sstevel@tonic-gate 	return(ok);
20980Sstevel@tonic-gate 	}
20990Sstevel@tonic-gate 
21000Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
21010Sstevel@tonic-gate static RSA *rsa_tmp=NULL;
21020Sstevel@tonic-gate 
tmp_rsa_cb(SSL * s,int is_export,int keylength)21030Sstevel@tonic-gate static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength)
21040Sstevel@tonic-gate 	{
21052139Sjp161948 	BIGNUM *bn = NULL;
21060Sstevel@tonic-gate 	if (rsa_tmp == NULL)
21070Sstevel@tonic-gate 		{
21082139Sjp161948 		bn = BN_new();
21092139Sjp161948 		rsa_tmp = RSA_new();
21102139Sjp161948 		if(!bn || !rsa_tmp || !BN_set_word(bn, RSA_F4))
21112139Sjp161948 			{
21122139Sjp161948 			BIO_printf(bio_err, "Memory error...");
21132139Sjp161948 			goto end;
21142139Sjp161948 			}
21150Sstevel@tonic-gate 		BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength);
21160Sstevel@tonic-gate 		(void)BIO_flush(bio_err);
21172139Sjp161948 		if(!RSA_generate_key_ex(rsa_tmp,keylength,bn,NULL))
21182139Sjp161948 			{
21192139Sjp161948 			BIO_printf(bio_err, "Error generating key.");
21202139Sjp161948 			RSA_free(rsa_tmp);
21212139Sjp161948 			rsa_tmp = NULL;
21222139Sjp161948 			}
21232139Sjp161948 end:
21240Sstevel@tonic-gate 		BIO_printf(bio_err,"\n");
21250Sstevel@tonic-gate 		(void)BIO_flush(bio_err);
21260Sstevel@tonic-gate 		}
21272139Sjp161948 	if(bn) BN_free(bn);
21280Sstevel@tonic-gate 	return(rsa_tmp);
21290Sstevel@tonic-gate 	}
21300Sstevel@tonic-gate 
free_tmp_rsa(void)21310Sstevel@tonic-gate static void free_tmp_rsa(void)
21320Sstevel@tonic-gate 	{
21330Sstevel@tonic-gate 	if (rsa_tmp != NULL)
21340Sstevel@tonic-gate 		{
21350Sstevel@tonic-gate 		RSA_free(rsa_tmp);
21360Sstevel@tonic-gate 		rsa_tmp = NULL;
21370Sstevel@tonic-gate 		}
21380Sstevel@tonic-gate 	}
21390Sstevel@tonic-gate #endif
21400Sstevel@tonic-gate 
21410Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
21420Sstevel@tonic-gate /* These DH parameters have been generated as follows:
21430Sstevel@tonic-gate  *    $ openssl dhparam -C -noout 512
21440Sstevel@tonic-gate  *    $ openssl dhparam -C -noout 1024
21450Sstevel@tonic-gate  *    $ openssl dhparam -C -noout -dsaparam 1024
21460Sstevel@tonic-gate  * (The third function has been renamed to avoid name conflicts.)
21470Sstevel@tonic-gate  */
get_dh512()21480Sstevel@tonic-gate static DH *get_dh512()
21490Sstevel@tonic-gate 	{
21500Sstevel@tonic-gate 	static unsigned char dh512_p[]={
21510Sstevel@tonic-gate 		0xCB,0xC8,0xE1,0x86,0xD0,0x1F,0x94,0x17,0xA6,0x99,0xF0,0xC6,
21520Sstevel@tonic-gate 		0x1F,0x0D,0xAC,0xB6,0x25,0x3E,0x06,0x39,0xCA,0x72,0x04,0xB0,
21530Sstevel@tonic-gate 		0x6E,0xDA,0xC0,0x61,0xE6,0x7A,0x77,0x25,0xE8,0x3B,0xB9,0x5F,
21540Sstevel@tonic-gate 		0x9A,0xB6,0xB5,0xFE,0x99,0x0B,0xA1,0x93,0x4E,0x35,0x33,0xB8,
21550Sstevel@tonic-gate 		0xE1,0xF1,0x13,0x4F,0x59,0x1A,0xD2,0x57,0xC0,0x26,0x21,0x33,
21560Sstevel@tonic-gate 		0x02,0xC5,0xAE,0x23,
21570Sstevel@tonic-gate 		};
21580Sstevel@tonic-gate 	static unsigned char dh512_g[]={
21590Sstevel@tonic-gate 		0x02,
21600Sstevel@tonic-gate 		};
21610Sstevel@tonic-gate 	DH *dh;
21620Sstevel@tonic-gate 
21630Sstevel@tonic-gate 	if ((dh=DH_new()) == NULL) return(NULL);
21640Sstevel@tonic-gate 	dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
21650Sstevel@tonic-gate 	dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
21660Sstevel@tonic-gate 	if ((dh->p == NULL) || (dh->g == NULL))
21670Sstevel@tonic-gate 		{ DH_free(dh); return(NULL); }
21680Sstevel@tonic-gate 	return(dh);
21690Sstevel@tonic-gate 	}
21700Sstevel@tonic-gate 
get_dh1024()21710Sstevel@tonic-gate static DH *get_dh1024()
21720Sstevel@tonic-gate 	{
21730Sstevel@tonic-gate 	static unsigned char dh1024_p[]={
21740Sstevel@tonic-gate 		0xF8,0x81,0x89,0x7D,0x14,0x24,0xC5,0xD1,0xE6,0xF7,0xBF,0x3A,
21750Sstevel@tonic-gate 		0xE4,0x90,0xF4,0xFC,0x73,0xFB,0x34,0xB5,0xFA,0x4C,0x56,0xA2,
21760Sstevel@tonic-gate 		0xEA,0xA7,0xE9,0xC0,0xC0,0xCE,0x89,0xE1,0xFA,0x63,0x3F,0xB0,
21770Sstevel@tonic-gate 		0x6B,0x32,0x66,0xF1,0xD1,0x7B,0xB0,0x00,0x8F,0xCA,0x87,0xC2,
21780Sstevel@tonic-gate 		0xAE,0x98,0x89,0x26,0x17,0xC2,0x05,0xD2,0xEC,0x08,0xD0,0x8C,
21790Sstevel@tonic-gate 		0xFF,0x17,0x52,0x8C,0xC5,0x07,0x93,0x03,0xB1,0xF6,0x2F,0xB8,
21800Sstevel@tonic-gate 		0x1C,0x52,0x47,0x27,0x1B,0xDB,0xD1,0x8D,0x9D,0x69,0x1D,0x52,
21810Sstevel@tonic-gate 		0x4B,0x32,0x81,0xAA,0x7F,0x00,0xC8,0xDC,0xE6,0xD9,0xCC,0xC1,
21820Sstevel@tonic-gate 		0x11,0x2D,0x37,0x34,0x6C,0xEA,0x02,0x97,0x4B,0x0E,0xBB,0xB1,
21830Sstevel@tonic-gate 		0x71,0x33,0x09,0x15,0xFD,0xDD,0x23,0x87,0x07,0x5E,0x89,0xAB,
21840Sstevel@tonic-gate 		0x6B,0x7C,0x5F,0xEC,0xA6,0x24,0xDC,0x53,
21850Sstevel@tonic-gate 		};
21860Sstevel@tonic-gate 	static unsigned char dh1024_g[]={
21870Sstevel@tonic-gate 		0x02,
21880Sstevel@tonic-gate 		};
21890Sstevel@tonic-gate 	DH *dh;
21900Sstevel@tonic-gate 
21910Sstevel@tonic-gate 	if ((dh=DH_new()) == NULL) return(NULL);
21920Sstevel@tonic-gate 	dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
21930Sstevel@tonic-gate 	dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
21940Sstevel@tonic-gate 	if ((dh->p == NULL) || (dh->g == NULL))
21950Sstevel@tonic-gate 		{ DH_free(dh); return(NULL); }
21960Sstevel@tonic-gate 	return(dh);
21970Sstevel@tonic-gate 	}
21980Sstevel@tonic-gate 
get_dh1024dsa()21990Sstevel@tonic-gate static DH *get_dh1024dsa()
22000Sstevel@tonic-gate 	{
22010Sstevel@tonic-gate 	static unsigned char dh1024_p[]={
22020Sstevel@tonic-gate 		0xC8,0x00,0xF7,0x08,0x07,0x89,0x4D,0x90,0x53,0xF3,0xD5,0x00,
22030Sstevel@tonic-gate 		0x21,0x1B,0xF7,0x31,0xA6,0xA2,0xDA,0x23,0x9A,0xC7,0x87,0x19,
22040Sstevel@tonic-gate 		0x3B,0x47,0xB6,0x8C,0x04,0x6F,0xFF,0xC6,0x9B,0xB8,0x65,0xD2,
22050Sstevel@tonic-gate 		0xC2,0x5F,0x31,0x83,0x4A,0xA7,0x5F,0x2F,0x88,0x38,0xB6,0x55,
22060Sstevel@tonic-gate 		0xCF,0xD9,0x87,0x6D,0x6F,0x9F,0xDA,0xAC,0xA6,0x48,0xAF,0xFC,
22070Sstevel@tonic-gate 		0x33,0x84,0x37,0x5B,0x82,0x4A,0x31,0x5D,0xE7,0xBD,0x52,0x97,
22080Sstevel@tonic-gate 		0xA1,0x77,0xBF,0x10,0x9E,0x37,0xEA,0x64,0xFA,0xCA,0x28,0x8D,
22090Sstevel@tonic-gate 		0x9D,0x3B,0xD2,0x6E,0x09,0x5C,0x68,0xC7,0x45,0x90,0xFD,0xBB,
22100Sstevel@tonic-gate 		0x70,0xC9,0x3A,0xBB,0xDF,0xD4,0x21,0x0F,0xC4,0x6A,0x3C,0xF6,
22110Sstevel@tonic-gate 		0x61,0xCF,0x3F,0xD6,0x13,0xF1,0x5F,0xBC,0xCF,0xBC,0x26,0x9E,
22120Sstevel@tonic-gate 		0xBC,0x0B,0xBD,0xAB,0x5D,0xC9,0x54,0x39,
22130Sstevel@tonic-gate 		};
22140Sstevel@tonic-gate 	static unsigned char dh1024_g[]={
22150Sstevel@tonic-gate 		0x3B,0x40,0x86,0xE7,0xF3,0x6C,0xDE,0x67,0x1C,0xCC,0x80,0x05,
22160Sstevel@tonic-gate 		0x5A,0xDF,0xFE,0xBD,0x20,0x27,0x74,0x6C,0x24,0xC9,0x03,0xF3,
22170Sstevel@tonic-gate 		0xE1,0x8D,0xC3,0x7D,0x98,0x27,0x40,0x08,0xB8,0x8C,0x6A,0xE9,
22180Sstevel@tonic-gate 		0xBB,0x1A,0x3A,0xD6,0x86,0x83,0x5E,0x72,0x41,0xCE,0x85,0x3C,
22190Sstevel@tonic-gate 		0xD2,0xB3,0xFC,0x13,0xCE,0x37,0x81,0x9E,0x4C,0x1C,0x7B,0x65,
22200Sstevel@tonic-gate 		0xD3,0xE6,0xA6,0x00,0xF5,0x5A,0x95,0x43,0x5E,0x81,0xCF,0x60,
22210Sstevel@tonic-gate 		0xA2,0x23,0xFC,0x36,0xA7,0x5D,0x7A,0x4C,0x06,0x91,0x6E,0xF6,
22220Sstevel@tonic-gate 		0x57,0xEE,0x36,0xCB,0x06,0xEA,0xF5,0x3D,0x95,0x49,0xCB,0xA7,
22230Sstevel@tonic-gate 		0xDD,0x81,0xDF,0x80,0x09,0x4A,0x97,0x4D,0xA8,0x22,0x72,0xA1,
22240Sstevel@tonic-gate 		0x7F,0xC4,0x70,0x56,0x70,0xE8,0x20,0x10,0x18,0x8F,0x2E,0x60,
22250Sstevel@tonic-gate 		0x07,0xE7,0x68,0x1A,0x82,0x5D,0x32,0xA2,
22260Sstevel@tonic-gate 		};
22270Sstevel@tonic-gate 	DH *dh;
22280Sstevel@tonic-gate 
22290Sstevel@tonic-gate 	if ((dh=DH_new()) == NULL) return(NULL);
22300Sstevel@tonic-gate 	dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
22310Sstevel@tonic-gate 	dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
22320Sstevel@tonic-gate 	if ((dh->p == NULL) || (dh->g == NULL))
22330Sstevel@tonic-gate 		{ DH_free(dh); return(NULL); }
22340Sstevel@tonic-gate 	dh->length = 160;
22350Sstevel@tonic-gate 	return(dh);
22360Sstevel@tonic-gate 	}
22372139Sjp161948 
do_test_cipherlist(void)22382139Sjp161948 static int do_test_cipherlist(void)
22392139Sjp161948 	{
22402139Sjp161948 	int i = 0;
22412139Sjp161948 	const SSL_METHOD *meth;
22422139Sjp161948 	SSL_CIPHER *ci, *tci = NULL;
22432139Sjp161948 
22442139Sjp161948 	fprintf(stderr, "testing SSLv2 cipher list order: ");
22452139Sjp161948 	meth = SSLv2_method();
22462139Sjp161948 	while ((ci = meth->get_cipher(i++)) != NULL)
22472139Sjp161948 		{
22482139Sjp161948 		if (tci != NULL)
22492139Sjp161948 			if (ci->id >= tci->id)
22502139Sjp161948 				{
22512139Sjp161948 				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
22522139Sjp161948 				return 0;
22532139Sjp161948 				}
22542139Sjp161948 		tci = ci;
22552139Sjp161948 		}
22562139Sjp161948 	fprintf(stderr, "ok\n");
22572139Sjp161948 
22582139Sjp161948 	fprintf(stderr, "testing SSLv3 cipher list order: ");
22592139Sjp161948 	meth = SSLv3_method();
22602139Sjp161948 	tci = NULL;
22612139Sjp161948 	while ((ci = meth->get_cipher(i++)) != NULL)
22622139Sjp161948 		{
22632139Sjp161948 		if (tci != NULL)
22642139Sjp161948 			if (ci->id >= tci->id)
22652139Sjp161948 				{
22662139Sjp161948 				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
22672139Sjp161948 				return 0;
22682139Sjp161948 				}
22692139Sjp161948 		tci = ci;
22702139Sjp161948 		}
22712139Sjp161948 	fprintf(stderr, "ok\n");
22722139Sjp161948 
22732139Sjp161948 	fprintf(stderr, "testing TLSv1 cipher list order: ");
22742139Sjp161948 	meth = TLSv1_method();
22752139Sjp161948 	tci = NULL;
22762139Sjp161948 	while ((ci = meth->get_cipher(i++)) != NULL)
22772139Sjp161948 		{
22782139Sjp161948 		if (tci != NULL)
22792139Sjp161948 			if (ci->id >= tci->id)
22802139Sjp161948 				{
22812139Sjp161948 				fprintf(stderr, "failed %lx vs. %lx\n", ci->id, tci->id);
22822139Sjp161948 				return 0;
22832139Sjp161948 				}
22842139Sjp161948 		tci = ci;
22852139Sjp161948 		}
22862139Sjp161948 	fprintf(stderr, "ok\n");
22872139Sjp161948 
22882139Sjp161948 	return 1;
22892139Sjp161948 	}
22900Sstevel@tonic-gate #endif
2291