ssl_cert.c revision 162911
133965Sjdp/*! \file ssl/ssl_cert.c */
289857Sobrien/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3130561Sobrien * All rights reserved.
460484Sobrien *
533965Sjdp * This package is an SSL implementation written
6104834Sobrien * by Eric Young (eay@cryptsoft.com).
733965Sjdp * The implementation was written so as to conform with Netscapes SSL.
8104834Sobrien *
9104834Sobrien * This library is free for commercial and non-commercial use as long as
10104834Sobrien * the following conditions are aheared to.  The following conditions
11104834Sobrien * apply to all code found in this distribution, be it the RC4, RSA,
1233965Sjdp * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13104834Sobrien * included with this distribution is covered by the same copyright terms
14104834Sobrien * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15104834Sobrien *
16104834Sobrien * Copyright remains Eric Young's, and as such any Copyright notices in
1733965Sjdp * the code are not to be removed.
18104834Sobrien * If this package is used in a product, Eric Young should be given attribution
19104834Sobrien * as the author of the parts of the library used.
20104834Sobrien * This can be in the form of a textual message at program startup or
2133965Sjdp * in documentation (online or textual) provided with the package.
2233965Sjdp *
2333965Sjdp * Redistribution and use in source and binary forms, with or without
2433965Sjdp * modification, are permitted provided that the following conditions
2533965Sjdp * are met:
2633965Sjdp * 1. Redistributions of source code must retain the copyright
27130561Sobrien *    notice, this list of conditions and the following disclaimer.
28104834Sobrien * 2. Redistributions in binary form must reproduce the above copyright
2933965Sjdp *    notice, this list of conditions and the following disclaimer in the
3033965Sjdp *    documentation and/or other materials provided with the distribution.
3133965Sjdp * 3. All advertising materials mentioning features or use of this software
3233965Sjdp *    must display the following acknowledgement:
3333965Sjdp *    "This product includes cryptographic software written by
3433965Sjdp *     Eric Young (eay@cryptsoft.com)"
3533965Sjdp *    The word 'cryptographic' can be left out if the rouines from the library
3661843Sobrien *    being used are not cryptographic related :-).
37104834Sobrien * 4. If you include any Windows specific code (or a derivative thereof) from
3833965Sjdp *    the apps directory (application code) you must include an acknowledgement:
3933965Sjdp *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4033965Sjdp *
4133965Sjdp * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4233965Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4333965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4433965Sjdp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4533965Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4660484Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4760484Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4860484Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4960484Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5060484Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5160484Sobrien * SUCH DAMAGE.
5233965Sjdp *
5333965Sjdp * The licence and distribution terms for any publically available version or
5433965Sjdp * derivative of this code cannot be changed.  i.e. this code cannot simply be
5533965Sjdp * copied and put under another distribution licence
5633965Sjdp * [including the GNU Public Licence.]
57130561Sobrien */
5833965Sjdp/* ====================================================================
5933965Sjdp * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
6033965Sjdp *
61130561Sobrien * Redistribution and use in source and binary forms, with or without
62130561Sobrien * modification, are permitted provided that the following conditions
63130561Sobrien * are met:
64130561Sobrien *
65130561Sobrien * 1. Redistributions of source code must retain the above copyright
66130561Sobrien *    notice, this list of conditions and the following disclaimer.
6733965Sjdp *
6833965Sjdp * 2. Redistributions in binary form must reproduce the above copyright
69130561Sobrien *    notice, this list of conditions and the following disclaimer in
70130561Sobrien *    the documentation and/or other materials provided with the
7133965Sjdp *    distribution.
7233965Sjdp *
73130561Sobrien * 3. All advertising materials mentioning features or use of this
74130561Sobrien *    software must display the following acknowledgment:
75130561Sobrien *    "This product includes software developed by the OpenSSL Project
76130561Sobrien *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77130561Sobrien *
78130561Sobrien * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79130561Sobrien *    endorse or promote products derived from this software without
80130561Sobrien *    prior written permission. For written permission, please contact
8133965Sjdp *    openssl-core@openssl.org.
8233965Sjdp *
8333965Sjdp * 5. Products derived from this software may not be called "OpenSSL"
8433965Sjdp *    nor may "OpenSSL" appear in their names without prior written
8533965Sjdp *    permission of the OpenSSL Project.
8633965Sjdp *
8733965Sjdp * 6. Redistributions of any form whatsoever must retain the following
8833965Sjdp *    acknowledgment:
8933965Sjdp *    "This product includes software developed by the OpenSSL Project
9033965Sjdp *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
9133965Sjdp *
9233965Sjdp * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
9333965Sjdp * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9433965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
9533965Sjdp * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
9633965Sjdp * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9733965Sjdp * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
9833965Sjdp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
9933965Sjdp * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10033965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
10133965Sjdp * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10233965Sjdp * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10333965Sjdp * OF THE POSSIBILITY OF SUCH DAMAGE.
10433965Sjdp * ====================================================================
10533965Sjdp *
106130561Sobrien * This product includes cryptographic software written by Eric Young
10733965Sjdp * (eay@cryptsoft.com).  This product includes software written by Tim
10833965Sjdp * Hudson (tjh@cryptsoft.com).
10933965Sjdp *
11033965Sjdp */
11133965Sjdp/* ====================================================================
11233965Sjdp * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
11333965Sjdp * ECC cipher suite support in OpenSSL originally developed by
11433965Sjdp * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
11533965Sjdp */
11633965Sjdp
11733965Sjdp#include <stdio.h>
11833965Sjdp
11933965Sjdp#include "e_os.h"
12033965Sjdp#ifndef NO_SYS_TYPES_H
12133965Sjdp# include <sys/types.h>
12233965Sjdp#endif
12333965Sjdp
12433965Sjdp#include "o_dir.h"
12533965Sjdp#include <openssl/objects.h>
12633965Sjdp#include <openssl/bio.h>
127130561Sobrien#include <openssl/pem.h>
12833965Sjdp#include <openssl/x509v3.h>
129130561Sobrien#ifndef OPENSSL_NO_DH
13060484Sobrien#include <openssl/dh.h>
131130561Sobrien#endif
13260484Sobrien#include <openssl/bn.h>
13360484Sobrien#include "ssl_locl.h"
13433965Sjdp
135130561Sobrienint SSL_get_ex_data_X509_STORE_CTX_idx(void)
13633965Sjdp	{
13760484Sobrien	static volatile int ssl_x509_store_ctx_idx= -1;
13860484Sobrien	int got_write_lock = 0;
13960484Sobrien
140130561Sobrien	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
14160484Sobrien
14233965Sjdp	if (ssl_x509_store_ctx_idx < 0)
14333965Sjdp		{
14433965Sjdp		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
145130561Sobrien		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
14633965Sjdp		got_write_lock = 1;
14733965Sjdp
14833965Sjdp		if (ssl_x509_store_ctx_idx < 0)
14933965Sjdp			{
15033965Sjdp			ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index(
15133965Sjdp				0,"SSL for verify callback",NULL,NULL,NULL);
15233965Sjdp			}
15333965Sjdp		}
15433965Sjdp
15533965Sjdp	if (got_write_lock)
156130561Sobrien		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
15733965Sjdp	else
15833965Sjdp		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
15960484Sobrien
16033965Sjdp	return ssl_x509_store_ctx_idx;
16133965Sjdp	}
16233965Sjdp
16333965SjdpCERT *ssl_cert_new(void)
16433965Sjdp	{
16533965Sjdp	CERT *ret;
16633965Sjdp
16733965Sjdp	ret=(CERT *)OPENSSL_malloc(sizeof(CERT));
16833965Sjdp	if (ret == NULL)
16933965Sjdp		{
17060484Sobrien		SSLerr(SSL_F_SSL_CERT_NEW,ERR_R_MALLOC_FAILURE);
17133965Sjdp		return(NULL);
17233965Sjdp		}
17333965Sjdp	memset(ret,0,sizeof(CERT));
17433965Sjdp
17533965Sjdp	ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
17633965Sjdp	ret->references=1;
17733965Sjdp
17833965Sjdp	return(ret);
179130561Sobrien	}
18033965Sjdp
18160484SobrienCERT *ssl_cert_dup(CERT *cert)
18233965Sjdp	{
18333965Sjdp	CERT *ret;
18433965Sjdp	int i;
18533965Sjdp
18633965Sjdp	ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
18733965Sjdp	if (ret == NULL)
18833965Sjdp		{
18933965Sjdp		SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
19033965Sjdp		return(NULL);
19133965Sjdp		}
19233965Sjdp
19361843Sobrien	memset(ret, 0, sizeof(CERT));
19433965Sjdp
19560484Sobrien	ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
19660484Sobrien	/* or ret->key = ret->pkeys + (cert->key - cert->pkeys),
197104834Sobrien	 * if you find that more readable */
19860484Sobrien
19960484Sobrien	ret->valid = cert->valid;
20060484Sobrien	ret->mask = cert->mask;
20160484Sobrien	ret->export_mask = cert->export_mask;
20260484Sobrien
20360484Sobrien#ifndef OPENSSL_NO_RSA
204130561Sobrien	if (cert->rsa_tmp != NULL)
20533965Sjdp		{
20633965Sjdp		RSA_up_ref(cert->rsa_tmp);
20733965Sjdp		ret->rsa_tmp = cert->rsa_tmp;
20833965Sjdp		}
20960484Sobrien	ret->rsa_tmp_cb = cert->rsa_tmp_cb;
21060484Sobrien#endif
21133965Sjdp
21233965Sjdp#ifndef OPENSSL_NO_DH
21333965Sjdp	if (cert->dh_tmp != NULL)
214130561Sobrien		{
21533965Sjdp		ret->dh_tmp = DHparams_dup(cert->dh_tmp);
21633965Sjdp		if (ret->dh_tmp == NULL)
217130561Sobrien			{
21833965Sjdp			SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB);
21933965Sjdp			goto err;
22033965Sjdp			}
22133965Sjdp		if (cert->dh_tmp->priv_key)
222104834Sobrien			{
22333965Sjdp			BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
22460484Sobrien			if (!b)
22560484Sobrien				{
226104834Sobrien				SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
22760484Sobrien				goto err;
22860484Sobrien				}
22960484Sobrien			ret->dh_tmp->priv_key = b;
23060484Sobrien			}
23160484Sobrien		if (cert->dh_tmp->pub_key)
23260484Sobrien			{
23360484Sobrien			BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
23460484Sobrien			if (!b)
23560484Sobrien				{
23660484Sobrien				SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
23760484Sobrien				goto err;
23860484Sobrien				}
23960484Sobrien			ret->dh_tmp->pub_key = b;
24060484Sobrien			}
24160484Sobrien		}
24260484Sobrien	ret->dh_tmp_cb = cert->dh_tmp_cb;
24360484Sobrien#endif
24460484Sobrien
24560484Sobrien#ifndef OPENSSL_NO_ECDH
24660484Sobrien	if (cert->ecdh_tmp)
24760484Sobrien		{
24860484Sobrien		ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
24960484Sobrien		if (ret->ecdh_tmp == NULL)
25060484Sobrien			{
25160484Sobrien			SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB);
252104834Sobrien			goto err;
253104834Sobrien			}
25460484Sobrien		}
25533965Sjdp	ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
25689857Sobrien#endif
257104834Sobrien
25889857Sobrien	for (i = 0; i < SSL_PKEY_NUM; i++)
25989857Sobrien		{
26089857Sobrien		if (cert->pkeys[i].x509 != NULL)
26189857Sobrien			{
26289857Sobrien			ret->pkeys[i].x509 = cert->pkeys[i].x509;
26389857Sobrien			CRYPTO_add(&ret->pkeys[i].x509->references, 1,
26433965Sjdp				CRYPTO_LOCK_X509);
26533965Sjdp			}
26633965Sjdp
26733965Sjdp		if (cert->pkeys[i].privatekey != NULL)
26860484Sobrien			{
26933965Sjdp			ret->pkeys[i].privatekey = cert->pkeys[i].privatekey;
27033965Sjdp			CRYPTO_add(&ret->pkeys[i].privatekey->references, 1,
27133965Sjdp				CRYPTO_LOCK_EVP_PKEY);
27233965Sjdp
27333965Sjdp			switch(i)
27433965Sjdp				{
27533965Sjdp				/* If there was anything special to do for
27633965Sjdp				 * certain types of keys, we'd do it here.
277130561Sobrien				 * (Nothing at the moment, I think.) */
27833965Sjdp
27933965Sjdp			case SSL_PKEY_RSA_ENC:
28033965Sjdp			case SSL_PKEY_RSA_SIGN:
28160484Sobrien				/* We have an RSA key. */
28260484Sobrien				break;
28360484Sobrien
28433965Sjdp			case SSL_PKEY_DSA_SIGN:
28561843Sobrien				/* We have a DSA key. */
28661843Sobrien				break;
28761843Sobrien
28861843Sobrien			case SSL_PKEY_DH_RSA:
28977298Sobrien			case SSL_PKEY_DH_DSA:
29061843Sobrien				/* We have a DH key. */
29161843Sobrien				break;
29277298Sobrien
29361843Sobrien			case SSL_PKEY_ECC:
29461843Sobrien				/* We have an ECC key */
29533965Sjdp				break;
29633965Sjdp
29733965Sjdp			default:
29833965Sjdp				/* Can't happen. */
29933965Sjdp				SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG);
30033965Sjdp				}
30133965Sjdp			}
30233965Sjdp		}
30333965Sjdp
30433965Sjdp	/* ret->extra_certs *should* exist, but currently the own certificate
30533965Sjdp	 * chain is held inside SSL_CTX */
30633965Sjdp
30733965Sjdp	ret->references=1;
30833965Sjdp
30933965Sjdp	return(ret);
31033965Sjdp
31133965Sjdp#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
31233965Sjdperr:
31333965Sjdp#endif
31433965Sjdp#ifndef OPENSSL_NO_RSA
31533965Sjdp	if (ret->rsa_tmp != NULL)
31633965Sjdp		RSA_free(ret->rsa_tmp);
31733965Sjdp#endif
31860484Sobrien#ifndef OPENSSL_NO_DH
31933965Sjdp	if (ret->dh_tmp != NULL)
32033965Sjdp		DH_free(ret->dh_tmp);
32133965Sjdp#endif
32233965Sjdp#ifndef OPENSSL_NO_ECDH
323130561Sobrien	if (ret->ecdh_tmp != NULL)
32433965Sjdp		EC_KEY_free(ret->ecdh_tmp);
32533965Sjdp#endif
32633965Sjdp
327130561Sobrien	for (i = 0; i < SSL_PKEY_NUM; i++)
328130561Sobrien		{
32933965Sjdp		if (ret->pkeys[i].x509 != NULL)
33033965Sjdp			X509_free(ret->pkeys[i].x509);
33133965Sjdp		if (ret->pkeys[i].privatekey != NULL)
33233965Sjdp			EVP_PKEY_free(ret->pkeys[i].privatekey);
33333965Sjdp		}
33433965Sjdp
33533965Sjdp	return NULL;
33633965Sjdp	}
33733965Sjdp
338130561Sobrien
33989857Sobrienvoid ssl_cert_free(CERT *c)
34033965Sjdp	{
341130561Sobrien	int i;
34233965Sjdp
34333965Sjdp	if(c == NULL)
34433965Sjdp	    return;
34533965Sjdp
34633965Sjdp	i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT);
34733965Sjdp#ifdef REF_PRINT
34833965Sjdp	REF_PRINT("CERT",c);
34933965Sjdp#endif
35033965Sjdp	if (i > 0) return;
35133965Sjdp#ifdef REF_CHECK
35260484Sobrien	if (i < 0)
35333965Sjdp		{
35433965Sjdp		fprintf(stderr,"ssl_cert_free, bad reference count\n");
355104834Sobrien		abort(); /* ok */
356130561Sobrien		}
35733965Sjdp#endif
35860484Sobrien
35960484Sobrien#ifndef OPENSSL_NO_RSA
36060484Sobrien	if (c->rsa_tmp) RSA_free(c->rsa_tmp);
36189857Sobrien#endif
36289857Sobrien#ifndef OPENSSL_NO_DH
36389857Sobrien	if (c->dh_tmp) DH_free(c->dh_tmp);
36460484Sobrien#endif
36560484Sobrien#ifndef OPENSSL_NO_ECDH
36660484Sobrien	if (c->ecdh_tmp) EC_KEY_free(c->ecdh_tmp);
36733965Sjdp#endif
36833965Sjdp
36933965Sjdp	for (i=0; i<SSL_PKEY_NUM; i++)
37033965Sjdp		{
37133965Sjdp		if (c->pkeys[i].x509 != NULL)
37233965Sjdp			X509_free(c->pkeys[i].x509);
37333965Sjdp		if (c->pkeys[i].privatekey != NULL)
37433965Sjdp			EVP_PKEY_free(c->pkeys[i].privatekey);
37561843Sobrien#if 0
376104834Sobrien		if (c->pkeys[i].publickey != NULL)
377104834Sobrien			EVP_PKEY_free(c->pkeys[i].publickey);
378104834Sobrien#endif
379104834Sobrien		}
380104834Sobrien	OPENSSL_free(c);
381104834Sobrien	}
382104834Sobrien
383104834Sobrienint ssl_cert_inst(CERT **o)
38461843Sobrien	{
38533965Sjdp	/* Create a CERT if there isn't already one
38633965Sjdp	 * (which cannot really happen, as it is initially created in
38733965Sjdp	 * SSL_CTX_new; but the earlier code usually allows for that one
38833965Sjdp	 * being non-existant, so we follow that behaviour, as it might
38933965Sjdp	 * turn out that there actually is a reason for it -- but I'm
39061843Sobrien	 * not sure that *all* of the existing code could cope with
39133965Sjdp	 * s->cert being NULL, otherwise we could do without the
39233965Sjdp	 * initialization in SSL_CTX_new).
39333965Sjdp	 */
39433965Sjdp
39533965Sjdp	if (o == NULL)
39633965Sjdp		{
39733965Sjdp		SSLerr(SSL_F_SSL_CERT_INST, ERR_R_PASSED_NULL_PARAMETER);
39833965Sjdp		return(0);
39933965Sjdp		}
40033965Sjdp	if (*o == NULL)
40133965Sjdp		{
40233965Sjdp		if ((*o = ssl_cert_new()) == NULL)
40333965Sjdp			{
40433965Sjdp			SSLerr(SSL_F_SSL_CERT_INST, ERR_R_MALLOC_FAILURE);
40533965Sjdp			return(0);
40633965Sjdp			}
40733965Sjdp		}
40833965Sjdp	return(1);
40933965Sjdp	}
41033965Sjdp
41133965Sjdp
41233965SjdpSESS_CERT *ssl_sess_cert_new(void)
41333965Sjdp	{
41433965Sjdp	SESS_CERT *ret;
41533965Sjdp
41633965Sjdp	ret = OPENSSL_malloc(sizeof *ret);
41733965Sjdp	if (ret == NULL)
418104834Sobrien		{
419104834Sobrien		SSLerr(SSL_F_SSL_SESS_CERT_NEW, ERR_R_MALLOC_FAILURE);
420104834Sobrien		return NULL;
421104834Sobrien		}
422104834Sobrien
42377298Sobrien	memset(ret, 0 ,sizeof *ret);
42433965Sjdp	ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]);
42533965Sjdp	ret->references = 1;
426130561Sobrien
42733965Sjdp	return ret;
42889857Sobrien	}
42989857Sobrien
43089857Sobrienvoid ssl_sess_cert_free(SESS_CERT *sc)
43189857Sobrien	{
43233965Sjdp	int i;
43333965Sjdp
43433965Sjdp	if (sc == NULL)
43533965Sjdp		return;
43633965Sjdp
43733965Sjdp	i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT);
43833965Sjdp#ifdef REF_PRINT
43933965Sjdp	REF_PRINT("SESS_CERT", sc);
44033965Sjdp#endif
441130561Sobrien	if (i > 0)
44233965Sjdp		return;
44333965Sjdp#ifdef REF_CHECK
44433965Sjdp	if (i < 0)
44533965Sjdp		{
44633965Sjdp		fprintf(stderr,"ssl_sess_cert_free, bad reference count\n");
44733965Sjdp		abort(); /* ok */
44833965Sjdp		}
44933965Sjdp#endif
45033965Sjdp
45133965Sjdp	/* i == 0 */
45233965Sjdp	if (sc->cert_chain != NULL)
45333965Sjdp		sk_X509_pop_free(sc->cert_chain, X509_free);
45433965Sjdp	for (i = 0; i < SSL_PKEY_NUM; i++)
45533965Sjdp		{
45633965Sjdp		if (sc->peer_pkeys[i].x509 != NULL)
45733965Sjdp			X509_free(sc->peer_pkeys[i].x509);
45833965Sjdp#if 0 /* We don't have the peer's private key.  These lines are just
45933965Sjdp	   * here as a reminder that we're still using a not-quite-appropriate
46033965Sjdp	   * data structure. */
46133965Sjdp		if (sc->peer_pkeys[i].privatekey != NULL)
46233965Sjdp			EVP_PKEY_free(sc->peer_pkeys[i].privatekey);
463130561Sobrien#endif
464130561Sobrien		}
46533965Sjdp
46633965Sjdp#ifndef OPENSSL_NO_RSA
467130561Sobrien	if (sc->peer_rsa_tmp != NULL)
468130561Sobrien		RSA_free(sc->peer_rsa_tmp);
469130561Sobrien#endif
470130561Sobrien#ifndef OPENSSL_NO_DH
471130561Sobrien	if (sc->peer_dh_tmp != NULL)
472130561Sobrien		DH_free(sc->peer_dh_tmp);
47333965Sjdp#endif
474130561Sobrien#ifndef OPENSSL_NO_ECDH
47533965Sjdp	if (sc->peer_ecdh_tmp != NULL)
476130561Sobrien		EC_KEY_free(sc->peer_ecdh_tmp);
47733965Sjdp#endif
47833965Sjdp
47933965Sjdp	OPENSSL_free(sc);
48033965Sjdp	}
48133965Sjdp
48233965Sjdpint ssl_set_peer_cert_type(SESS_CERT *sc,int type)
48333965Sjdp	{
48433965Sjdp	sc->peer_cert_type = type;
48533965Sjdp	return(1);
48633965Sjdp	}
487130561Sobrien
488130561Sobrienint ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk)
489130561Sobrien	{
490130561Sobrien	X509 *x;
491130561Sobrien	int i;
492130561Sobrien	X509_STORE_CTX ctx;
493130561Sobrien
494130561Sobrien	if ((sk == NULL) || (sk_X509_num(sk) == 0))
495130561Sobrien		return(0);
496130561Sobrien
497130561Sobrien	x=sk_X509_value(sk,0);
498130561Sobrien	if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk))
499130561Sobrien		{
500130561Sobrien		SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB);
501130561Sobrien		return(0);
502130561Sobrien		}
503130561Sobrien	if (s->param)
504130561Sobrien		X509_VERIFY_PARAM_inherit(X509_STORE_CTX_get0_param(&ctx),
505130561Sobrien						s->param);
506130561Sobrien#if 0
507130561Sobrien	if (SSL_get_verify_depth(s) >= 0)
508130561Sobrien		X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s));
509130561Sobrien#endif
510130561Sobrien	X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s);
511130561Sobrien
512130561Sobrien	/* We need to inherit the verify parameters. These can be determined by
513130561Sobrien	 * the context: if its a server it will verify SSL client certificates
514130561Sobrien	 * or vice versa.
515130561Sobrien	 */
516130561Sobrien
517130561Sobrien	X509_STORE_CTX_set_default(&ctx,
51833965Sjdp				s->server ? "ssl_client" : "ssl_server");
519130561Sobrien
520130561Sobrien	if (s->verify_callback)
521130561Sobrien		X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
522130561Sobrien
523130561Sobrien	if (s->ctx->app_verify_callback != NULL)
524130561Sobrien#if 1 /* new with OpenSSL 0.9.7 */
525130561Sobrien		i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg);
526130561Sobrien#else
527130561Sobrien		i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */
528130561Sobrien#endif
529130561Sobrien	else
530130561Sobrien		{
531130561Sobrien#ifndef OPENSSL_NO_X509_VERIFY
532130561Sobrien		i=X509_verify_cert(&ctx);
533130561Sobrien#else
534130561Sobrien		i=0;
535130561Sobrien		ctx.error=X509_V_ERR_APPLICATION_VERIFICATION;
536130561Sobrien		SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,SSL_R_NO_VERIFY_CALLBACK);
537130561Sobrien#endif
538130561Sobrien		}
539130561Sobrien
540130561Sobrien	s->verify_result=ctx.error;
541130561Sobrien	X509_STORE_CTX_cleanup(&ctx);
542130561Sobrien
543130561Sobrien	return(i);
544130561Sobrien	}
545130561Sobrien
546130561Sobrienstatic void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,STACK_OF(X509_NAME) *name_list)
547130561Sobrien	{
548130561Sobrien	if (*ca_list != NULL)
549130561Sobrien		sk_X509_NAME_pop_free(*ca_list,X509_NAME_free);
550130561Sobrien
551130561Sobrien	*ca_list=name_list;
552130561Sobrien	}
553130561Sobrien
554130561SobrienSTACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk)
555130561Sobrien	{
556130561Sobrien	int i;
557130561Sobrien	STACK_OF(X509_NAME) *ret;
558130561Sobrien	X509_NAME *name;
559130561Sobrien
560130561Sobrien	ret=sk_X509_NAME_new_null();
561130561Sobrien	for (i=0; i<sk_X509_NAME_num(sk); i++)
562130561Sobrien		{
563130561Sobrien		name=X509_NAME_dup(sk_X509_NAME_value(sk,i));
564130561Sobrien		if ((name == NULL) || !sk_X509_NAME_push(ret,name))
56533965Sjdp			{
56633965Sjdp			sk_X509_NAME_pop_free(ret,X509_NAME_free);
567130561Sobrien			return(NULL);
568130561Sobrien			}
569130561Sobrien		}
570130561Sobrien	return(ret);
571130561Sobrien	}
572130561Sobrien
573130561Sobrienvoid SSL_set_client_CA_list(SSL *s,STACK_OF(X509_NAME) *name_list)
57433965Sjdp	{
575130561Sobrien	set_client_CA_list(&(s->client_CA),name_list);
57633965Sjdp	}
57733965Sjdp
57833965Sjdpvoid SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK_OF(X509_NAME) *name_list)
57933965Sjdp	{
580130561Sobrien	set_client_CA_list(&(ctx->client_CA),name_list);
581130561Sobrien	}
58233965Sjdp
58333965SjdpSTACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
58433965Sjdp	{
58533965Sjdp	return(ctx->client_CA);
58633965Sjdp	}
58733965Sjdp
58833965SjdpSTACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
58933965Sjdp	{
59033965Sjdp	if (s->type == SSL_ST_CONNECT)
59133965Sjdp		{ /* we are in the client */
59233965Sjdp		if (((s->version>>8) == SSL3_VERSION_MAJOR) &&
59333965Sjdp			(s->s3 != NULL))
59433965Sjdp			return(s->s3->tmp.ca_names);
59533965Sjdp		else
59633965Sjdp			return(NULL);
59733965Sjdp		}
59833965Sjdp	else
59933965Sjdp		{
600130561Sobrien		if (s->client_CA != NULL)
60133965Sjdp			return(s->client_CA);
60233965Sjdp		else
60333965Sjdp			return(s->ctx->client_CA);
60433965Sjdp		}
60560484Sobrien	}
60633965Sjdp
60733965Sjdpstatic int add_client_CA(STACK_OF(X509_NAME) **sk,X509 *x)
60860484Sobrien	{
60933965Sjdp	X509_NAME *name;
61033965Sjdp
61133965Sjdp	if (x == NULL) return(0);
61233965Sjdp	if ((*sk == NULL) && ((*sk=sk_X509_NAME_new_null()) == NULL))
613104834Sobrien		return(0);
61460484Sobrien
615104834Sobrien	if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL)
61660484Sobrien		return(0);
61760484Sobrien
618104834Sobrien	if (!sk_X509_NAME_push(*sk,name))
61960484Sobrien		{
62060484Sobrien		X509_NAME_free(name);
62160484Sobrien		return(0);
62233965Sjdp		}
62333965Sjdp	return(1);
62433965Sjdp	}
62560484Sobrien
62633965Sjdpint SSL_add_client_CA(SSL *ssl,X509 *x)
62733965Sjdp	{
62833965Sjdp	return(add_client_CA(&(ssl->client_CA),x));
62933965Sjdp	}
63033965Sjdp
63133965Sjdpint SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x)
63233965Sjdp	{
63333965Sjdp	return(add_client_CA(&(ctx->client_CA),x));
63433965Sjdp	}
63533965Sjdp
63633965Sjdpstatic int xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
63733965Sjdp	{
63833965Sjdp	return(X509_NAME_cmp(*a,*b));
63933965Sjdp	}
64033965Sjdp
64133965Sjdp#ifndef OPENSSL_NO_STDIO
64233965Sjdp/*!
64333965Sjdp * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
64433965Sjdp * it doesn't really have anything to do with clients (except that a common use
64533965Sjdp * for a stack of CAs is to send it to the client). Actually, it doesn't have
64633965Sjdp * much to do with CAs, either, since it will load any old cert.
64733965Sjdp * \param file the file containing one or more certs.
64833965Sjdp * \return a ::STACK containing the certs.
64933965Sjdp */
65033965SjdpSTACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
65133965Sjdp	{
65233965Sjdp	BIO *in;
65333965Sjdp	X509 *x=NULL;
654104834Sobrien	X509_NAME *xn=NULL;
65533965Sjdp	STACK_OF(X509_NAME) *ret = NULL,*sk;
65633965Sjdp
65733965Sjdp	sk=sk_X509_NAME_new(xname_cmp);
65833965Sjdp
65933965Sjdp	in=BIO_new(BIO_s_file_internal());
66033965Sjdp
66133965Sjdp	if ((sk == NULL) || (in == NULL))
66233965Sjdp		{
66333965Sjdp		SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE);
66433965Sjdp		goto err;
66533965Sjdp		}
66660484Sobrien
66733965Sjdp	if (!BIO_read_filename(in,file))
66833965Sjdp		goto err;
66933965Sjdp
67060484Sobrien	for (;;)
67133965Sjdp		{
67233965Sjdp		if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
67333965Sjdp			break;
67460484Sobrien		if (ret == NULL)
67533965Sjdp			{
67633965Sjdp			ret = sk_X509_NAME_new_null();
67733965Sjdp			if (ret == NULL)
67833965Sjdp				{
67933965Sjdp				SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE);
68060484Sobrien				goto err;
68160484Sobrien				}
68233965Sjdp			}
68333965Sjdp		if ((xn=X509_get_subject_name(x)) == NULL) goto err;
68433965Sjdp		/* check for duplicates */
68533965Sjdp		xn=X509_NAME_dup(xn);
68633965Sjdp		if (xn == NULL) goto err;
68760484Sobrien		if (sk_X509_NAME_find(sk,xn) >= 0)
68860484Sobrien			X509_NAME_free(xn);
68933965Sjdp		else
69033965Sjdp			{
69133965Sjdp			sk_X509_NAME_push(sk,xn);
69233965Sjdp			sk_X509_NAME_push(ret,xn);
69333965Sjdp			}
69433965Sjdp		}
69560484Sobrien
69660484Sobrien	if (0)
69733965Sjdp		{
69833965Sjdperr:
69933965Sjdp		if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free);
70033965Sjdp		ret=NULL;
70160484Sobrien		}
70260484Sobrien	if (sk != NULL) sk_X509_NAME_free(sk);
70333965Sjdp	if (in != NULL) BIO_free(in);
70433965Sjdp	if (x != NULL) X509_free(x);
70533965Sjdp	if (ret != NULL)
70633965Sjdp		ERR_clear_error();
70733965Sjdp	return(ret);
70833965Sjdp	}
70933965Sjdp#endif
71033965Sjdp
71133965Sjdp/*!
71233965Sjdp * Add a file of certs to a stack.
713130561Sobrien * \param stack the stack to add to.
71433965Sjdp * \param file the file to add from. All certs in this file that are not
71533965Sjdp * already in the stack will be added.
71633965Sjdp * \return 1 for success, 0 for failure. Note that in the case of failure some
71733965Sjdp * certs may have been added to \c stack.
71833965Sjdp */
71933965Sjdp
72033965Sjdpint SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
72133965Sjdp					const char *file)
72233965Sjdp	{
72333965Sjdp	BIO *in;
72433965Sjdp	X509 *x=NULL;
72533965Sjdp	X509_NAME *xn=NULL;
72633965Sjdp	int ret=1;
72733965Sjdp	int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b);
72861843Sobrien
72933965Sjdp	oldcmp=sk_X509_NAME_set_cmp_func(stack,xname_cmp);
73061843Sobrien
73161843Sobrien	in=BIO_new(BIO_s_file_internal());
73261843Sobrien
73361843Sobrien	if (in == NULL)
73461843Sobrien		{
73533965Sjdp		SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,ERR_R_MALLOC_FAILURE);
73661843Sobrien		goto err;
73733965Sjdp		}
73833965Sjdp
73933965Sjdp	if (!BIO_read_filename(in,file))
74033965Sjdp		goto err;
74133965Sjdp
74233965Sjdp	for (;;)
74333965Sjdp		{
74433965Sjdp		if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
74533965Sjdp			break;
74633965Sjdp		if ((xn=X509_get_subject_name(x)) == NULL) goto err;
74733965Sjdp		xn=X509_NAME_dup(xn);
74833965Sjdp		if (xn == NULL) goto err;
74933965Sjdp		if (sk_X509_NAME_find(stack,xn) >= 0)
75033965Sjdp			X509_NAME_free(xn);
75133965Sjdp		else
75233965Sjdp			sk_X509_NAME_push(stack,xn);
75333965Sjdp		}
75433965Sjdp
75533965Sjdp	if (0)
75633965Sjdp		{
75733965Sjdperr:
75833965Sjdp		ret=0;
75933965Sjdp		}
76033965Sjdp	if(in != NULL)
76133965Sjdp		BIO_free(in);
76233965Sjdp	if(x != NULL)
76333965Sjdp		X509_free(x);
76433965Sjdp
76533965Sjdp	sk_X509_NAME_set_cmp_func(stack,oldcmp);
76633965Sjdp
76733965Sjdp	return ret;
76833965Sjdp	}
76933965Sjdp
770130561Sobrien/*!
771130561Sobrien * Add a directory of certs to a stack.
77260484Sobrien * \param stack the stack to append to.
77360484Sobrien * \param dir the directory to append from. All files in this directory will be
77460484Sobrien * examined as potential certs. Any that are acceptable to
77533965Sjdp * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be
77633965Sjdp * included.
77733965Sjdp * \return 1 for success, 0 for failure. Note that in the case of failure some
77833965Sjdp * certs may have been added to \c stack.
77933965Sjdp */
78033965Sjdp
78133965Sjdpint SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
78233965Sjdp				       const char *dir)
78333965Sjdp	{
78433965Sjdp	OPENSSL_DIR_CTX *d = NULL;
78533965Sjdp	const char *filename;
78633965Sjdp	int ret = 0;
78733965Sjdp
78833965Sjdp	CRYPTO_w_lock(CRYPTO_LOCK_READDIR);
78933965Sjdp
79033965Sjdp	/* Note that a side effect is that the CAs will be sorted by name */
79133965Sjdp
79233965Sjdp	while((filename = OPENSSL_DIR_read(&d, dir)))
79333965Sjdp		{
79433965Sjdp		char buf[1024];
79533965Sjdp		int r;
79633965Sjdp
79733965Sjdp		if(strlen(dir)+strlen(filename)+2 > sizeof buf)
79833965Sjdp			{
79933965Sjdp			SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG);
80033965Sjdp			goto err;
80133965Sjdp			}
80233965Sjdp
80333965Sjdp#ifdef OPENSSL_SYS_VMS
80433965Sjdp		r = BIO_snprintf(buf,sizeof buf,"%s%s",dir,filename);
80533965Sjdp#else
80633965Sjdp		r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,filename);
80733965Sjdp#endif
80833965Sjdp		if (r <= 0 || r >= (int)sizeof(buf))
80933965Sjdp			goto err;
81033965Sjdp		if(!SSL_add_file_cert_subjects_to_stack(stack,buf))
81133965Sjdp			goto err;
812130561Sobrien		}
81333965Sjdp
81433965Sjdp	if (errno)
81533965Sjdp		{
81633965Sjdp		SYSerr(SYS_F_OPENDIR, get_last_sys_error());
81733965Sjdp		ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
81833965Sjdp		SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB);
81960484Sobrien		goto err;
82060484Sobrien		}
82133965Sjdp
82233965Sjdp	ret = 1;
82377298Sobrien
824130561Sobrienerr:
82533965Sjdp	if (d) OPENSSL_DIR_end(&d);
82689857Sobrien	CRYPTO_w_unlock(CRYPTO_LOCK_READDIR);
82733965Sjdp	return ret;
82833965Sjdp	}
82933965Sjdp
83033965Sjdp