xref: /onnv-gate/usr/src/common/openssl/ssl/ssl_cert.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /*! \file ssl/ssl_cert.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) 1999 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  */
106*2139Sjp161948 /* ====================================================================
107*2139Sjp161948  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
108*2139Sjp161948  * ECC cipher suite support in OpenSSL originally developed by
109*2139Sjp161948  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
110*2139Sjp161948  */
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate #include <stdio.h>
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate #include "e_os.h"
1150Sstevel@tonic-gate #ifndef NO_SYS_TYPES_H
1160Sstevel@tonic-gate # include <sys/types.h>
1170Sstevel@tonic-gate #endif
1180Sstevel@tonic-gate 
119*2139Sjp161948 #include "o_dir.h"
1200Sstevel@tonic-gate #include <openssl/objects.h>
1210Sstevel@tonic-gate #include <openssl/bio.h>
1220Sstevel@tonic-gate #include <openssl/pem.h>
1230Sstevel@tonic-gate #include <openssl/x509v3.h>
124*2139Sjp161948 #ifndef OPENSSL_NO_DH
125*2139Sjp161948 #include <openssl/dh.h>
126*2139Sjp161948 #endif
127*2139Sjp161948 #include <openssl/bn.h>
1280Sstevel@tonic-gate #include "ssl_locl.h"
1290Sstevel@tonic-gate 
SSL_get_ex_data_X509_STORE_CTX_idx(void)1300Sstevel@tonic-gate int SSL_get_ex_data_X509_STORE_CTX_idx(void)
1310Sstevel@tonic-gate 	{
1320Sstevel@tonic-gate 	static volatile int ssl_x509_store_ctx_idx= -1;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	if (ssl_x509_store_ctx_idx < 0)
1350Sstevel@tonic-gate 		{
1360Sstevel@tonic-gate 		/* any write lock will do; usually this branch
1370Sstevel@tonic-gate 		 * will only be taken once anyway */
1380Sstevel@tonic-gate 		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 		if (ssl_x509_store_ctx_idx < 0)
1410Sstevel@tonic-gate 			{
1420Sstevel@tonic-gate 			ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index(
1430Sstevel@tonic-gate 				0,"SSL for verify callback",NULL,NULL,NULL);
1440Sstevel@tonic-gate 			}
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
1470Sstevel@tonic-gate 		}
1480Sstevel@tonic-gate 	return ssl_x509_store_ctx_idx;
1490Sstevel@tonic-gate 	}
1500Sstevel@tonic-gate 
ssl_cert_new(void)1510Sstevel@tonic-gate CERT *ssl_cert_new(void)
1520Sstevel@tonic-gate 	{
1530Sstevel@tonic-gate 	CERT *ret;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	ret=(CERT *)OPENSSL_malloc(sizeof(CERT));
1560Sstevel@tonic-gate 	if (ret == NULL)
1570Sstevel@tonic-gate 		{
1580Sstevel@tonic-gate 		SSLerr(SSL_F_SSL_CERT_NEW,ERR_R_MALLOC_FAILURE);
1590Sstevel@tonic-gate 		return(NULL);
1600Sstevel@tonic-gate 		}
1610Sstevel@tonic-gate 	memset(ret,0,sizeof(CERT));
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
1640Sstevel@tonic-gate 	ret->references=1;
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	return(ret);
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 
ssl_cert_dup(CERT * cert)1690Sstevel@tonic-gate CERT *ssl_cert_dup(CERT *cert)
1700Sstevel@tonic-gate 	{
1710Sstevel@tonic-gate 	CERT *ret;
1720Sstevel@tonic-gate 	int i;
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 	ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
1750Sstevel@tonic-gate 	if (ret == NULL)
1760Sstevel@tonic-gate 		{
1770Sstevel@tonic-gate 		SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
1780Sstevel@tonic-gate 		return(NULL);
1790Sstevel@tonic-gate 		}
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	memset(ret, 0, sizeof(CERT));
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 	ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
1840Sstevel@tonic-gate 	/* or ret->key = ret->pkeys + (cert->key - cert->pkeys),
1850Sstevel@tonic-gate 	 * if you find that more readable */
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	ret->valid = cert->valid;
1880Sstevel@tonic-gate 	ret->mask = cert->mask;
1890Sstevel@tonic-gate 	ret->export_mask = cert->export_mask;
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
1920Sstevel@tonic-gate 	if (cert->rsa_tmp != NULL)
1930Sstevel@tonic-gate 		{
1940Sstevel@tonic-gate 		RSA_up_ref(cert->rsa_tmp);
1950Sstevel@tonic-gate 		ret->rsa_tmp = cert->rsa_tmp;
1960Sstevel@tonic-gate 		}
1970Sstevel@tonic-gate 	ret->rsa_tmp_cb = cert->rsa_tmp_cb;
1980Sstevel@tonic-gate #endif
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
2010Sstevel@tonic-gate 	if (cert->dh_tmp != NULL)
2020Sstevel@tonic-gate 		{
2030Sstevel@tonic-gate 		ret->dh_tmp = DHparams_dup(cert->dh_tmp);
2040Sstevel@tonic-gate 		if (ret->dh_tmp == NULL)
2050Sstevel@tonic-gate 			{
2060Sstevel@tonic-gate 			SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB);
2070Sstevel@tonic-gate 			goto err;
2080Sstevel@tonic-gate 			}
2090Sstevel@tonic-gate 		if (cert->dh_tmp->priv_key)
2100Sstevel@tonic-gate 			{
2110Sstevel@tonic-gate 			BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
2120Sstevel@tonic-gate 			if (!b)
2130Sstevel@tonic-gate 				{
2140Sstevel@tonic-gate 				SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
2150Sstevel@tonic-gate 				goto err;
2160Sstevel@tonic-gate 				}
2170Sstevel@tonic-gate 			ret->dh_tmp->priv_key = b;
2180Sstevel@tonic-gate 			}
2190Sstevel@tonic-gate 		if (cert->dh_tmp->pub_key)
2200Sstevel@tonic-gate 			{
2210Sstevel@tonic-gate 			BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
2220Sstevel@tonic-gate 			if (!b)
2230Sstevel@tonic-gate 				{
2240Sstevel@tonic-gate 				SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
2250Sstevel@tonic-gate 				goto err;
2260Sstevel@tonic-gate 				}
2270Sstevel@tonic-gate 			ret->dh_tmp->pub_key = b;
2280Sstevel@tonic-gate 			}
2290Sstevel@tonic-gate 		}
2300Sstevel@tonic-gate 	ret->dh_tmp_cb = cert->dh_tmp_cb;
2310Sstevel@tonic-gate #endif
2320Sstevel@tonic-gate 
233*2139Sjp161948 #ifndef OPENSSL_NO_ECDH
234*2139Sjp161948 	if (cert->ecdh_tmp)
235*2139Sjp161948 		{
236*2139Sjp161948 		ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
237*2139Sjp161948 		if (ret->ecdh_tmp == NULL)
238*2139Sjp161948 			{
239*2139Sjp161948 			SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB);
240*2139Sjp161948 			goto err;
241*2139Sjp161948 			}
242*2139Sjp161948 		}
243*2139Sjp161948 	ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
244*2139Sjp161948 #endif
245*2139Sjp161948 
2460Sstevel@tonic-gate 	for (i = 0; i < SSL_PKEY_NUM; i++)
2470Sstevel@tonic-gate 		{
2480Sstevel@tonic-gate 		if (cert->pkeys[i].x509 != NULL)
2490Sstevel@tonic-gate 			{
2500Sstevel@tonic-gate 			ret->pkeys[i].x509 = cert->pkeys[i].x509;
2510Sstevel@tonic-gate 			CRYPTO_add(&ret->pkeys[i].x509->references, 1,
2520Sstevel@tonic-gate 				CRYPTO_LOCK_X509);
2530Sstevel@tonic-gate 			}
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 		if (cert->pkeys[i].privatekey != NULL)
2560Sstevel@tonic-gate 			{
2570Sstevel@tonic-gate 			ret->pkeys[i].privatekey = cert->pkeys[i].privatekey;
2580Sstevel@tonic-gate 			CRYPTO_add(&ret->pkeys[i].privatekey->references, 1,
2590Sstevel@tonic-gate 				CRYPTO_LOCK_EVP_PKEY);
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 			switch(i)
2620Sstevel@tonic-gate 				{
2630Sstevel@tonic-gate 				/* If there was anything special to do for
2640Sstevel@tonic-gate 				 * certain types of keys, we'd do it here.
2650Sstevel@tonic-gate 				 * (Nothing at the moment, I think.) */
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 			case SSL_PKEY_RSA_ENC:
2680Sstevel@tonic-gate 			case SSL_PKEY_RSA_SIGN:
2690Sstevel@tonic-gate 				/* We have an RSA key. */
2700Sstevel@tonic-gate 				break;
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 			case SSL_PKEY_DSA_SIGN:
2730Sstevel@tonic-gate 				/* We have a DSA key. */
2740Sstevel@tonic-gate 				break;
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 			case SSL_PKEY_DH_RSA:
2770Sstevel@tonic-gate 			case SSL_PKEY_DH_DSA:
2780Sstevel@tonic-gate 				/* We have a DH key. */
2790Sstevel@tonic-gate 				break;
280*2139Sjp161948 
281*2139Sjp161948 			case SSL_PKEY_ECC:
282*2139Sjp161948 				/* We have an ECC key */
283*2139Sjp161948 				break;
284*2139Sjp161948 
2850Sstevel@tonic-gate 			default:
2860Sstevel@tonic-gate 				/* Can't happen. */
2870Sstevel@tonic-gate 				SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG);
2880Sstevel@tonic-gate 				}
2890Sstevel@tonic-gate 			}
2900Sstevel@tonic-gate 		}
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	/* ret->extra_certs *should* exist, but currently the own certificate
2930Sstevel@tonic-gate 	 * chain is held inside SSL_CTX */
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	ret->references=1;
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 	return(ret);
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate #ifndef OPENSSL_NO_DH /* avoid 'unreferenced label' warning if OPENSSL_NO_DH is defined */
3000Sstevel@tonic-gate err:
3010Sstevel@tonic-gate #endif
3020Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
3030Sstevel@tonic-gate 	if (ret->rsa_tmp != NULL)
3040Sstevel@tonic-gate 		RSA_free(ret->rsa_tmp);
3050Sstevel@tonic-gate #endif
3060Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
3070Sstevel@tonic-gate 	if (ret->dh_tmp != NULL)
3080Sstevel@tonic-gate 		DH_free(ret->dh_tmp);
3090Sstevel@tonic-gate #endif
310*2139Sjp161948 #ifndef OPENSSL_NO_ECDH
311*2139Sjp161948 	if (ret->ecdh_tmp != NULL)
312*2139Sjp161948 		EC_KEY_free(ret->ecdh_tmp);
313*2139Sjp161948 #endif
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	for (i = 0; i < SSL_PKEY_NUM; i++)
3160Sstevel@tonic-gate 		{
3170Sstevel@tonic-gate 		if (ret->pkeys[i].x509 != NULL)
3180Sstevel@tonic-gate 			X509_free(ret->pkeys[i].x509);
3190Sstevel@tonic-gate 		if (ret->pkeys[i].privatekey != NULL)
3200Sstevel@tonic-gate 			EVP_PKEY_free(ret->pkeys[i].privatekey);
3210Sstevel@tonic-gate 		}
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	return NULL;
3240Sstevel@tonic-gate 	}
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 
ssl_cert_free(CERT * c)3270Sstevel@tonic-gate void ssl_cert_free(CERT *c)
3280Sstevel@tonic-gate 	{
3290Sstevel@tonic-gate 	int i;
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 	if(c == NULL)
3320Sstevel@tonic-gate 	    return;
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT);
3350Sstevel@tonic-gate #ifdef REF_PRINT
3360Sstevel@tonic-gate 	REF_PRINT("CERT",c);
3370Sstevel@tonic-gate #endif
3380Sstevel@tonic-gate 	if (i > 0) return;
3390Sstevel@tonic-gate #ifdef REF_CHECK
3400Sstevel@tonic-gate 	if (i < 0)
3410Sstevel@tonic-gate 		{
3420Sstevel@tonic-gate 		fprintf(stderr,"ssl_cert_free, bad reference count\n");
3430Sstevel@tonic-gate 		abort(); /* ok */
3440Sstevel@tonic-gate 		}
3450Sstevel@tonic-gate #endif
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
3480Sstevel@tonic-gate 	if (c->rsa_tmp) RSA_free(c->rsa_tmp);
3490Sstevel@tonic-gate #endif
3500Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
3510Sstevel@tonic-gate 	if (c->dh_tmp) DH_free(c->dh_tmp);
3520Sstevel@tonic-gate #endif
353*2139Sjp161948 #ifndef OPENSSL_NO_ECDH
354*2139Sjp161948 	if (c->ecdh_tmp) EC_KEY_free(c->ecdh_tmp);
355*2139Sjp161948 #endif
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	for (i=0; i<SSL_PKEY_NUM; i++)
3580Sstevel@tonic-gate 		{
3590Sstevel@tonic-gate 		if (c->pkeys[i].x509 != NULL)
3600Sstevel@tonic-gate 			X509_free(c->pkeys[i].x509);
3610Sstevel@tonic-gate 		if (c->pkeys[i].privatekey != NULL)
3620Sstevel@tonic-gate 			EVP_PKEY_free(c->pkeys[i].privatekey);
3630Sstevel@tonic-gate #if 0
3640Sstevel@tonic-gate 		if (c->pkeys[i].publickey != NULL)
3650Sstevel@tonic-gate 			EVP_PKEY_free(c->pkeys[i].publickey);
3660Sstevel@tonic-gate #endif
3670Sstevel@tonic-gate 		}
3680Sstevel@tonic-gate 	OPENSSL_free(c);
3690Sstevel@tonic-gate 	}
3700Sstevel@tonic-gate 
ssl_cert_inst(CERT ** o)3710Sstevel@tonic-gate int ssl_cert_inst(CERT **o)
3720Sstevel@tonic-gate 	{
3730Sstevel@tonic-gate 	/* Create a CERT if there isn't already one
3740Sstevel@tonic-gate 	 * (which cannot really happen, as it is initially created in
3750Sstevel@tonic-gate 	 * SSL_CTX_new; but the earlier code usually allows for that one
3760Sstevel@tonic-gate 	 * being non-existant, so we follow that behaviour, as it might
3770Sstevel@tonic-gate 	 * turn out that there actually is a reason for it -- but I'm
3780Sstevel@tonic-gate 	 * not sure that *all* of the existing code could cope with
3790Sstevel@tonic-gate 	 * s->cert being NULL, otherwise we could do without the
3800Sstevel@tonic-gate 	 * initialization in SSL_CTX_new).
3810Sstevel@tonic-gate 	 */
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	if (o == NULL)
3840Sstevel@tonic-gate 		{
3850Sstevel@tonic-gate 		SSLerr(SSL_F_SSL_CERT_INST, ERR_R_PASSED_NULL_PARAMETER);
3860Sstevel@tonic-gate 		return(0);
3870Sstevel@tonic-gate 		}
3880Sstevel@tonic-gate 	if (*o == NULL)
3890Sstevel@tonic-gate 		{
3900Sstevel@tonic-gate 		if ((*o = ssl_cert_new()) == NULL)
3910Sstevel@tonic-gate 			{
3920Sstevel@tonic-gate 			SSLerr(SSL_F_SSL_CERT_INST, ERR_R_MALLOC_FAILURE);
3930Sstevel@tonic-gate 			return(0);
3940Sstevel@tonic-gate 			}
3950Sstevel@tonic-gate 		}
3960Sstevel@tonic-gate 	return(1);
3970Sstevel@tonic-gate 	}
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 
ssl_sess_cert_new(void)4000Sstevel@tonic-gate SESS_CERT *ssl_sess_cert_new(void)
4010Sstevel@tonic-gate 	{
4020Sstevel@tonic-gate 	SESS_CERT *ret;
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	ret = OPENSSL_malloc(sizeof *ret);
4050Sstevel@tonic-gate 	if (ret == NULL)
4060Sstevel@tonic-gate 		{
4070Sstevel@tonic-gate 		SSLerr(SSL_F_SSL_SESS_CERT_NEW, ERR_R_MALLOC_FAILURE);
4080Sstevel@tonic-gate 		return NULL;
4090Sstevel@tonic-gate 		}
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	memset(ret, 0 ,sizeof *ret);
4120Sstevel@tonic-gate 	ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]);
4130Sstevel@tonic-gate 	ret->references = 1;
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	return ret;
4160Sstevel@tonic-gate 	}
4170Sstevel@tonic-gate 
ssl_sess_cert_free(SESS_CERT * sc)4180Sstevel@tonic-gate void ssl_sess_cert_free(SESS_CERT *sc)
4190Sstevel@tonic-gate 	{
4200Sstevel@tonic-gate 	int i;
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	if (sc == NULL)
4230Sstevel@tonic-gate 		return;
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT);
4260Sstevel@tonic-gate #ifdef REF_PRINT
4270Sstevel@tonic-gate 	REF_PRINT("SESS_CERT", sc);
4280Sstevel@tonic-gate #endif
4290Sstevel@tonic-gate 	if (i > 0)
4300Sstevel@tonic-gate 		return;
4310Sstevel@tonic-gate #ifdef REF_CHECK
4320Sstevel@tonic-gate 	if (i < 0)
4330Sstevel@tonic-gate 		{
4340Sstevel@tonic-gate 		fprintf(stderr,"ssl_sess_cert_free, bad reference count\n");
4350Sstevel@tonic-gate 		abort(); /* ok */
4360Sstevel@tonic-gate 		}
4370Sstevel@tonic-gate #endif
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	/* i == 0 */
4400Sstevel@tonic-gate 	if (sc->cert_chain != NULL)
4410Sstevel@tonic-gate 		sk_X509_pop_free(sc->cert_chain, X509_free);
4420Sstevel@tonic-gate 	for (i = 0; i < SSL_PKEY_NUM; i++)
4430Sstevel@tonic-gate 		{
4440Sstevel@tonic-gate 		if (sc->peer_pkeys[i].x509 != NULL)
4450Sstevel@tonic-gate 			X509_free(sc->peer_pkeys[i].x509);
4460Sstevel@tonic-gate #if 0 /* We don't have the peer's private key.  These lines are just
4470Sstevel@tonic-gate 	   * here as a reminder that we're still using a not-quite-appropriate
4480Sstevel@tonic-gate 	   * data structure. */
4490Sstevel@tonic-gate 		if (sc->peer_pkeys[i].privatekey != NULL)
4500Sstevel@tonic-gate 			EVP_PKEY_free(sc->peer_pkeys[i].privatekey);
4510Sstevel@tonic-gate #endif
4520Sstevel@tonic-gate 		}
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
4550Sstevel@tonic-gate 	if (sc->peer_rsa_tmp != NULL)
4560Sstevel@tonic-gate 		RSA_free(sc->peer_rsa_tmp);
4570Sstevel@tonic-gate #endif
4580Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
4590Sstevel@tonic-gate 	if (sc->peer_dh_tmp != NULL)
4600Sstevel@tonic-gate 		DH_free(sc->peer_dh_tmp);
4610Sstevel@tonic-gate #endif
462*2139Sjp161948 #ifndef OPENSSL_NO_ECDH
463*2139Sjp161948 	if (sc->peer_ecdh_tmp != NULL)
464*2139Sjp161948 		EC_KEY_free(sc->peer_ecdh_tmp);
465*2139Sjp161948 #endif
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	OPENSSL_free(sc);
4680Sstevel@tonic-gate 	}
4690Sstevel@tonic-gate 
ssl_set_peer_cert_type(SESS_CERT * sc,int type)4700Sstevel@tonic-gate int ssl_set_peer_cert_type(SESS_CERT *sc,int type)
4710Sstevel@tonic-gate 	{
4720Sstevel@tonic-gate 	sc->peer_cert_type = type;
4730Sstevel@tonic-gate 	return(1);
4740Sstevel@tonic-gate 	}
4750Sstevel@tonic-gate 
ssl_verify_cert_chain(SSL * s,STACK_OF (X509)* sk)4760Sstevel@tonic-gate int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk)
4770Sstevel@tonic-gate 	{
4780Sstevel@tonic-gate 	X509 *x;
4790Sstevel@tonic-gate 	int i;
4800Sstevel@tonic-gate 	X509_STORE_CTX ctx;
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	if ((sk == NULL) || (sk_X509_num(sk) == 0))
4830Sstevel@tonic-gate 		return(0);
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 	x=sk_X509_value(sk,0);
4860Sstevel@tonic-gate 	if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk))
4870Sstevel@tonic-gate 		{
4880Sstevel@tonic-gate 		SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB);
4890Sstevel@tonic-gate 		return(0);
4900Sstevel@tonic-gate 		}
491*2139Sjp161948 	if (s->param)
492*2139Sjp161948 		X509_VERIFY_PARAM_inherit(X509_STORE_CTX_get0_param(&ctx),
493*2139Sjp161948 						s->param);
494*2139Sjp161948 #if 0
4950Sstevel@tonic-gate 	if (SSL_get_verify_depth(s) >= 0)
4960Sstevel@tonic-gate 		X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s));
497*2139Sjp161948 #endif
4980Sstevel@tonic-gate 	X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s);
4990Sstevel@tonic-gate 
500*2139Sjp161948 	/* We need to inherit the verify parameters. These can be determined by
5010Sstevel@tonic-gate 	 * the context: if its a server it will verify SSL client certificates
5020Sstevel@tonic-gate 	 * or vice versa.
5030Sstevel@tonic-gate 	 */
5040Sstevel@tonic-gate 
505*2139Sjp161948 	X509_STORE_CTX_set_default(&ctx,
506*2139Sjp161948 				s->server ? "ssl_client" : "ssl_server");
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	if (s->verify_callback)
5090Sstevel@tonic-gate 		X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 	if (s->ctx->app_verify_callback != NULL)
5120Sstevel@tonic-gate #if 1 /* new with OpenSSL 0.9.7 */
5130Sstevel@tonic-gate 		i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg);
5140Sstevel@tonic-gate #else
5150Sstevel@tonic-gate 		i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */
5160Sstevel@tonic-gate #endif
5170Sstevel@tonic-gate 	else
5180Sstevel@tonic-gate 		{
5190Sstevel@tonic-gate #ifndef OPENSSL_NO_X509_VERIFY
5200Sstevel@tonic-gate 		i=X509_verify_cert(&ctx);
5210Sstevel@tonic-gate #else
5220Sstevel@tonic-gate 		i=0;
5230Sstevel@tonic-gate 		ctx.error=X509_V_ERR_APPLICATION_VERIFICATION;
5240Sstevel@tonic-gate 		SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,SSL_R_NO_VERIFY_CALLBACK);
5250Sstevel@tonic-gate #endif
5260Sstevel@tonic-gate 		}
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 	s->verify_result=ctx.error;
5290Sstevel@tonic-gate 	X509_STORE_CTX_cleanup(&ctx);
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	return(i);
5320Sstevel@tonic-gate 	}
5330Sstevel@tonic-gate 
set_client_CA_list(STACK_OF (X509_NAME)** ca_list,STACK_OF (X509_NAME)* name_list)5340Sstevel@tonic-gate static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,STACK_OF(X509_NAME) *name_list)
5350Sstevel@tonic-gate 	{
5360Sstevel@tonic-gate 	if (*ca_list != NULL)
5370Sstevel@tonic-gate 		sk_X509_NAME_pop_free(*ca_list,X509_NAME_free);
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	*ca_list=name_list;
5400Sstevel@tonic-gate 	}
5410Sstevel@tonic-gate 
STACK_OF(X509_NAME)5420Sstevel@tonic-gate STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk)
5430Sstevel@tonic-gate 	{
5440Sstevel@tonic-gate 	int i;
5450Sstevel@tonic-gate 	STACK_OF(X509_NAME) *ret;
5460Sstevel@tonic-gate 	X509_NAME *name;
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	ret=sk_X509_NAME_new_null();
5490Sstevel@tonic-gate 	for (i=0; i<sk_X509_NAME_num(sk); i++)
5500Sstevel@tonic-gate 		{
5510Sstevel@tonic-gate 		name=X509_NAME_dup(sk_X509_NAME_value(sk,i));
5520Sstevel@tonic-gate 		if ((name == NULL) || !sk_X509_NAME_push(ret,name))
5530Sstevel@tonic-gate 			{
5540Sstevel@tonic-gate 			sk_X509_NAME_pop_free(ret,X509_NAME_free);
5550Sstevel@tonic-gate 			return(NULL);
5560Sstevel@tonic-gate 			}
5570Sstevel@tonic-gate 		}
5580Sstevel@tonic-gate 	return(ret);
5590Sstevel@tonic-gate 	}
5600Sstevel@tonic-gate 
SSL_set_client_CA_list(SSL * s,STACK_OF (X509_NAME)* name_list)5610Sstevel@tonic-gate void SSL_set_client_CA_list(SSL *s,STACK_OF(X509_NAME) *name_list)
5620Sstevel@tonic-gate 	{
5630Sstevel@tonic-gate 	set_client_CA_list(&(s->client_CA),name_list);
5640Sstevel@tonic-gate 	}
5650Sstevel@tonic-gate 
SSL_CTX_set_client_CA_list(SSL_CTX * ctx,STACK_OF (X509_NAME)* name_list)5660Sstevel@tonic-gate void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK_OF(X509_NAME) *name_list)
5670Sstevel@tonic-gate 	{
5680Sstevel@tonic-gate 	set_client_CA_list(&(ctx->client_CA),name_list);
5690Sstevel@tonic-gate 	}
5700Sstevel@tonic-gate 
STACK_OF(X509_NAME)571*2139Sjp161948 STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
5720Sstevel@tonic-gate 	{
5730Sstevel@tonic-gate 	return(ctx->client_CA);
5740Sstevel@tonic-gate 	}
5750Sstevel@tonic-gate 
STACK_OF(X509_NAME)576*2139Sjp161948 STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
5770Sstevel@tonic-gate 	{
5780Sstevel@tonic-gate 	if (s->type == SSL_ST_CONNECT)
5790Sstevel@tonic-gate 		{ /* we are in the client */
5800Sstevel@tonic-gate 		if (((s->version>>8) == SSL3_VERSION_MAJOR) &&
5810Sstevel@tonic-gate 			(s->s3 != NULL))
5820Sstevel@tonic-gate 			return(s->s3->tmp.ca_names);
5830Sstevel@tonic-gate 		else
5840Sstevel@tonic-gate 			return(NULL);
5850Sstevel@tonic-gate 		}
5860Sstevel@tonic-gate 	else
5870Sstevel@tonic-gate 		{
5880Sstevel@tonic-gate 		if (s->client_CA != NULL)
5890Sstevel@tonic-gate 			return(s->client_CA);
5900Sstevel@tonic-gate 		else
5910Sstevel@tonic-gate 			return(s->ctx->client_CA);
5920Sstevel@tonic-gate 		}
5930Sstevel@tonic-gate 	}
5940Sstevel@tonic-gate 
add_client_CA(STACK_OF (X509_NAME)** sk,X509 * x)5950Sstevel@tonic-gate static int add_client_CA(STACK_OF(X509_NAME) **sk,X509 *x)
5960Sstevel@tonic-gate 	{
5970Sstevel@tonic-gate 	X509_NAME *name;
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	if (x == NULL) return(0);
6000Sstevel@tonic-gate 	if ((*sk == NULL) && ((*sk=sk_X509_NAME_new_null()) == NULL))
6010Sstevel@tonic-gate 		return(0);
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 	if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL)
6040Sstevel@tonic-gate 		return(0);
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate 	if (!sk_X509_NAME_push(*sk,name))
6070Sstevel@tonic-gate 		{
6080Sstevel@tonic-gate 		X509_NAME_free(name);
6090Sstevel@tonic-gate 		return(0);
6100Sstevel@tonic-gate 		}
6110Sstevel@tonic-gate 	return(1);
6120Sstevel@tonic-gate 	}
6130Sstevel@tonic-gate 
SSL_add_client_CA(SSL * ssl,X509 * x)6140Sstevel@tonic-gate int SSL_add_client_CA(SSL *ssl,X509 *x)
6150Sstevel@tonic-gate 	{
6160Sstevel@tonic-gate 	return(add_client_CA(&(ssl->client_CA),x));
6170Sstevel@tonic-gate 	}
6180Sstevel@tonic-gate 
SSL_CTX_add_client_CA(SSL_CTX * ctx,X509 * x)6190Sstevel@tonic-gate int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x)
6200Sstevel@tonic-gate 	{
6210Sstevel@tonic-gate 	return(add_client_CA(&(ctx->client_CA),x));
6220Sstevel@tonic-gate 	}
6230Sstevel@tonic-gate 
xname_cmp(const X509_NAME * const * a,const X509_NAME * const * b)6240Sstevel@tonic-gate static int xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
6250Sstevel@tonic-gate 	{
6260Sstevel@tonic-gate 	return(X509_NAME_cmp(*a,*b));
6270Sstevel@tonic-gate 	}
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate #ifndef OPENSSL_NO_STDIO
6300Sstevel@tonic-gate /*!
6310Sstevel@tonic-gate  * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
6320Sstevel@tonic-gate  * it doesn't really have anything to do with clients (except that a common use
6330Sstevel@tonic-gate  * for a stack of CAs is to send it to the client). Actually, it doesn't have
6340Sstevel@tonic-gate  * much to do with CAs, either, since it will load any old cert.
6350Sstevel@tonic-gate  * \param file the file containing one or more certs.
6360Sstevel@tonic-gate  * \return a ::STACK containing the certs.
6370Sstevel@tonic-gate  */
STACK_OF(X509_NAME)6380Sstevel@tonic-gate STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
6390Sstevel@tonic-gate 	{
6400Sstevel@tonic-gate 	BIO *in;
6410Sstevel@tonic-gate 	X509 *x=NULL;
6420Sstevel@tonic-gate 	X509_NAME *xn=NULL;
643*2139Sjp161948 	STACK_OF(X509_NAME) *ret = NULL,*sk;
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	sk=sk_X509_NAME_new(xname_cmp);
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 	in=BIO_new(BIO_s_file_internal());
6480Sstevel@tonic-gate 
649*2139Sjp161948 	if ((sk == NULL) || (in == NULL))
6500Sstevel@tonic-gate 		{
6510Sstevel@tonic-gate 		SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE);
6520Sstevel@tonic-gate 		goto err;
6530Sstevel@tonic-gate 		}
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 	if (!BIO_read_filename(in,file))
6560Sstevel@tonic-gate 		goto err;
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 	for (;;)
6590Sstevel@tonic-gate 		{
6600Sstevel@tonic-gate 		if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
6610Sstevel@tonic-gate 			break;
662*2139Sjp161948 		if (ret == NULL)
663*2139Sjp161948 			{
664*2139Sjp161948 			ret = sk_X509_NAME_new_null();
665*2139Sjp161948 			if (ret == NULL)
666*2139Sjp161948 				{
667*2139Sjp161948 				SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE);
668*2139Sjp161948 				goto err;
669*2139Sjp161948 				}
670*2139Sjp161948 			}
6710Sstevel@tonic-gate 		if ((xn=X509_get_subject_name(x)) == NULL) goto err;
6720Sstevel@tonic-gate 		/* check for duplicates */
6730Sstevel@tonic-gate 		xn=X509_NAME_dup(xn);
6740Sstevel@tonic-gate 		if (xn == NULL) goto err;
6750Sstevel@tonic-gate 		if (sk_X509_NAME_find(sk,xn) >= 0)
6760Sstevel@tonic-gate 			X509_NAME_free(xn);
6770Sstevel@tonic-gate 		else
6780Sstevel@tonic-gate 			{
6790Sstevel@tonic-gate 			sk_X509_NAME_push(sk,xn);
6800Sstevel@tonic-gate 			sk_X509_NAME_push(ret,xn);
6810Sstevel@tonic-gate 			}
6820Sstevel@tonic-gate 		}
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate 	if (0)
6850Sstevel@tonic-gate 		{
6860Sstevel@tonic-gate err:
6870Sstevel@tonic-gate 		if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free);
6880Sstevel@tonic-gate 		ret=NULL;
6890Sstevel@tonic-gate 		}
6900Sstevel@tonic-gate 	if (sk != NULL) sk_X509_NAME_free(sk);
6910Sstevel@tonic-gate 	if (in != NULL) BIO_free(in);
6920Sstevel@tonic-gate 	if (x != NULL) X509_free(x);
693*2139Sjp161948 	if (ret != NULL)
694*2139Sjp161948 		ERR_clear_error();
6950Sstevel@tonic-gate 	return(ret);
6960Sstevel@tonic-gate 	}
6970Sstevel@tonic-gate #endif
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate /*!
7000Sstevel@tonic-gate  * Add a file of certs to a stack.
7010Sstevel@tonic-gate  * \param stack the stack to add to.
7020Sstevel@tonic-gate  * \param file the file to add from. All certs in this file that are not
7030Sstevel@tonic-gate  * already in the stack will be added.
7040Sstevel@tonic-gate  * \return 1 for success, 0 for failure. Note that in the case of failure some
7050Sstevel@tonic-gate  * certs may have been added to \c stack.
7060Sstevel@tonic-gate  */
7070Sstevel@tonic-gate 
SSL_add_file_cert_subjects_to_stack(STACK_OF (X509_NAME)* stack,const char * file)7080Sstevel@tonic-gate int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
7090Sstevel@tonic-gate 					const char *file)
7100Sstevel@tonic-gate 	{
7110Sstevel@tonic-gate 	BIO *in;
7120Sstevel@tonic-gate 	X509 *x=NULL;
7130Sstevel@tonic-gate 	X509_NAME *xn=NULL;
7140Sstevel@tonic-gate 	int ret=1;
7150Sstevel@tonic-gate 	int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b);
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	oldcmp=sk_X509_NAME_set_cmp_func(stack,xname_cmp);
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 	in=BIO_new(BIO_s_file_internal());
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	if (in == NULL)
7220Sstevel@tonic-gate 		{
7230Sstevel@tonic-gate 		SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,ERR_R_MALLOC_FAILURE);
7240Sstevel@tonic-gate 		goto err;
7250Sstevel@tonic-gate 		}
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	if (!BIO_read_filename(in,file))
7280Sstevel@tonic-gate 		goto err;
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	for (;;)
7310Sstevel@tonic-gate 		{
7320Sstevel@tonic-gate 		if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
7330Sstevel@tonic-gate 			break;
7340Sstevel@tonic-gate 		if ((xn=X509_get_subject_name(x)) == NULL) goto err;
7350Sstevel@tonic-gate 		xn=X509_NAME_dup(xn);
7360Sstevel@tonic-gate 		if (xn == NULL) goto err;
7370Sstevel@tonic-gate 		if (sk_X509_NAME_find(stack,xn) >= 0)
7380Sstevel@tonic-gate 			X509_NAME_free(xn);
7390Sstevel@tonic-gate 		else
7400Sstevel@tonic-gate 			sk_X509_NAME_push(stack,xn);
7410Sstevel@tonic-gate 		}
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	if (0)
7440Sstevel@tonic-gate 		{
7450Sstevel@tonic-gate err:
7460Sstevel@tonic-gate 		ret=0;
7470Sstevel@tonic-gate 		}
7480Sstevel@tonic-gate 	if(in != NULL)
7490Sstevel@tonic-gate 		BIO_free(in);
7500Sstevel@tonic-gate 	if(x != NULL)
7510Sstevel@tonic-gate 		X509_free(x);
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 	sk_X509_NAME_set_cmp_func(stack,oldcmp);
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 	return ret;
7560Sstevel@tonic-gate 	}
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate /*!
7590Sstevel@tonic-gate  * Add a directory of certs to a stack.
7600Sstevel@tonic-gate  * \param stack the stack to append to.
7610Sstevel@tonic-gate  * \param dir the directory to append from. All files in this directory will be
7620Sstevel@tonic-gate  * examined as potential certs. Any that are acceptable to
7630Sstevel@tonic-gate  * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be
7640Sstevel@tonic-gate  * included.
7650Sstevel@tonic-gate  * \return 1 for success, 0 for failure. Note that in the case of failure some
7660Sstevel@tonic-gate  * certs may have been added to \c stack.
7670Sstevel@tonic-gate  */
7680Sstevel@tonic-gate 
SSL_add_dir_cert_subjects_to_stack(STACK_OF (X509_NAME)* stack,const char * dir)7690Sstevel@tonic-gate int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
7700Sstevel@tonic-gate 				       const char *dir)
7710Sstevel@tonic-gate 	{
772*2139Sjp161948 	OPENSSL_DIR_CTX *d = NULL;
773*2139Sjp161948 	const char *filename;
7740Sstevel@tonic-gate 	int ret = 0;
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 	CRYPTO_w_lock(CRYPTO_LOCK_READDIR);
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 	/* Note that a side effect is that the CAs will be sorted by name */
779*2139Sjp161948 
780*2139Sjp161948 	while((filename = OPENSSL_DIR_read(&d, dir)))
7810Sstevel@tonic-gate 		{
7820Sstevel@tonic-gate 		char buf[1024];
7830Sstevel@tonic-gate 		int r;
784*2139Sjp161948 
785*2139Sjp161948 		if(strlen(dir)+strlen(filename)+2 > sizeof buf)
7860Sstevel@tonic-gate 			{
7870Sstevel@tonic-gate 			SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG);
7880Sstevel@tonic-gate 			goto err;
7890Sstevel@tonic-gate 			}
790*2139Sjp161948 
791*2139Sjp161948 #ifdef OPENSSL_SYS_VMS
792*2139Sjp161948 		r = BIO_snprintf(buf,sizeof buf,"%s%s",dir,filename);
793*2139Sjp161948 #else
794*2139Sjp161948 		r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,filename);
795*2139Sjp161948 #endif
796*2139Sjp161948 		if (r <= 0 || r >= (int)sizeof(buf))
7970Sstevel@tonic-gate 			goto err;
7980Sstevel@tonic-gate 		if(!SSL_add_file_cert_subjects_to_stack(stack,buf))
7990Sstevel@tonic-gate 			goto err;
8000Sstevel@tonic-gate 		}
801*2139Sjp161948 
802*2139Sjp161948 	if (errno)
803*2139Sjp161948 		{
804*2139Sjp161948 		SYSerr(SYS_F_OPENDIR, get_last_sys_error());
805*2139Sjp161948 		ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
806*2139Sjp161948 		SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB);
807*2139Sjp161948 		goto err;
808*2139Sjp161948 		}
809*2139Sjp161948 
8100Sstevel@tonic-gate 	ret = 1;
8110Sstevel@tonic-gate 
812*2139Sjp161948 err:
813*2139Sjp161948 	if (d) OPENSSL_DIR_end(&d);
8140Sstevel@tonic-gate 	CRYPTO_w_unlock(CRYPTO_LOCK_READDIR);
8150Sstevel@tonic-gate 	return ret;
8160Sstevel@tonic-gate 	}
8170Sstevel@tonic-gate 
818