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