x509_lu.c revision 109998
118334Speter/* crypto/x509/x509_lu.c */
252518Sobrien/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
318334Speter * All rights reserved.
418334Speter *
518334Speter * This package is an SSL implementation written
618334Speter * by Eric Young (eay@cryptsoft.com).
718334Speter * The implementation was written so as to conform with Netscapes SSL.
818334Speter *
918334Speter * This library is free for commercial and non-commercial use as long as
1018334Speter * the following conditions are aheared to.  The following conditions
1118334Speter * apply to all code found in this distribution, be it the RC4, RSA,
1218334Speter * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1318334Speter * included with this distribution is covered by the same copyright terms
1418334Speter * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1518334Speter *
1618334Speter * Copyright remains Eric Young's, and as such any Copyright notices in
1718334Speter * the code are not to be removed.
1818334Speter * If this package is used in a product, Eric Young should be given attribution
1918334Speter * as the author of the parts of the library used.
2018334Speter * This can be in the form of a textual message at program startup or
2152518Sobrien * in documentation (online or textual) provided with the package.
2218334Speter *
2352518Sobrien * Redistribution and use in source and binary forms, with or without
2418334Speter * modification, are permitted provided that the following conditions
2518334Speter * are met:
2618334Speter * 1. Redistributions of source code must retain the copyright
2718334Speter *    notice, this list of conditions and the following disclaimer.
2818334Speter * 2. Redistributions in binary form must reproduce the above copyright
2918334Speter *    notice, this list of conditions and the following disclaimer in the
3018334Speter *    documentation and/or other materials provided with the distribution.
3118334Speter * 3. All advertising materials mentioning features or use of this software
3218334Speter *    must display the following acknowledgement:
3318334Speter *    "This product includes cryptographic software written by
3418334Speter *     Eric Young (eay@cryptsoft.com)"
3518334Speter *    The word 'cryptographic' can be left out if the rouines from the library
3618334Speter *    being used are not cryptographic related :-).
3718334Speter * 4. If you include any Windows specific code (or a derivative thereof) from
3818334Speter *    the apps directory (application code) you must include an acknowledgement:
3918334Speter *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4018334Speter *
4118334Speter * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4218334Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4318334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4452268Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4518334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4618334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4718334Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4852268Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4918334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5018334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5118334Speter * SUCH DAMAGE.
5218334Speter *
5318334Speter * The licence and distribution terms for any publically available version or
5418334Speter * derivative of this code cannot be changed.  i.e. this code cannot simply be
5518334Speter * copied and put under another distribution licence
5618334Speter * [including the GNU Public Licence.]
5718334Speter */
5818334Speter
5918334Speter#include <stdio.h>
6052268Sobrien#include "cryptlib.h"
6152518Sobrien#include <openssl/lhash.h>
6218334Speter#include <openssl/x509.h>
6352268Sobrien#include <openssl/x509v3.h>
6452268Sobrien
6552268SobrienX509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
6652268Sobrien	{
6752518Sobrien	X509_LOOKUP *ret;
6852518Sobrien
6952518Sobrien	ret=(X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
7052518Sobrien	if (ret == NULL) return NULL;
7118334Speter
7218334Speter	ret->init=0;
7318334Speter	ret->skip=0;
7452268Sobrien	ret->method=method;
7518334Speter	ret->method_data=NULL;
7618334Speter	ret->store_ctx=NULL;
7718334Speter	if ((method->new_item != NULL) && !method->new_item(ret))
7818334Speter		{
7918334Speter		OPENSSL_free(ret);
8018334Speter		return NULL;
8118334Speter		}
8218334Speter	return ret;
8318334Speter	}
8418334Speter
8518334Spetervoid X509_LOOKUP_free(X509_LOOKUP *ctx)
8618334Speter	{
8718334Speter	if (ctx == NULL) return;
8818334Speter	if (	(ctx->method != NULL) &&
8918334Speter		(ctx->method->free != NULL))
9018334Speter		ctx->method->free(ctx);
9118334Speter	OPENSSL_free(ctx);
9218334Speter	}
9318334Speter
9418334Speterint X509_LOOKUP_init(X509_LOOKUP *ctx)
9518334Speter	{
9618334Speter	if (ctx->method == NULL) return 0;
9718334Speter	if (ctx->method->init != NULL)
9818334Speter		return ctx->method->init(ctx);
9918334Speter	else
10018334Speter		return 1;
10118334Speter	}
10218334Speter
10318334Speterint X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
10418334Speter	{
10518334Speter	if (ctx->method == NULL) return 0;
10618334Speter	if (ctx->method->shutdown != NULL)
10718334Speter		return ctx->method->shutdown(ctx);
10818334Speter	else
10918334Speter		return 1;
11018334Speter	}
11118334Speter
11218334Speterint X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
11318334Speter	     char **ret)
11418334Speter	{
11518334Speter	if (ctx->method == NULL) return -1;
11618334Speter	if (ctx->method->ctrl != NULL)
11718334Speter		return ctx->method->ctrl(ctx,cmd,argc,argl,ret);
11818334Speter	else
11918334Speter		return 1;
12018334Speter	}
12118334Speter
12218334Speterint X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
12318334Speter	     X509_OBJECT *ret)
12418334Speter	{
12518334Speter	if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
12618334Speter		return X509_LU_FAIL;
12718334Speter	if (ctx->skip) return 0;
12818334Speter	return ctx->method->get_by_subject(ctx,type,name,ret);
12918334Speter	}
13018334Speter
13118334Speterint X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
13218334Speter	     ASN1_INTEGER *serial, X509_OBJECT *ret)
13318334Speter	{
13418334Speter	if ((ctx->method == NULL) ||
13518334Speter		(ctx->method->get_by_issuer_serial == NULL))
13618334Speter		return X509_LU_FAIL;
13752518Sobrien	return ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret);
13852268Sobrien	}
13952518Sobrien
14052268Sobrienint X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
14152518Sobrien	     unsigned char *bytes, int len, X509_OBJECT *ret)
14252518Sobrien	{
14352518Sobrien	if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
14452518Sobrien		return X509_LU_FAIL;
14552268Sobrien	return ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret);
14652518Sobrien	}
14718334Speter
14852518Sobrienint X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
14952518Sobrien	     X509_OBJECT *ret)
15052518Sobrien	{
15118334Speter	if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
15252518Sobrien		return X509_LU_FAIL;
15352518Sobrien	return ctx->method->get_by_alias(ctx,type,str,len,ret);
15452518Sobrien	}
15552518Sobrien
15652518Sobrien
15752518Sobrienstatic int x509_object_cmp(const X509_OBJECT * const *a, const X509_OBJECT * const *b)
15852518Sobrien  	{
15952518Sobrien 	int ret;
16052518Sobrien
16152518Sobrien 	ret=((*a)->type - (*b)->type);
16252518Sobrien 	if (ret) return ret;
16352518Sobrien 	switch ((*a)->type)
16452268Sobrien 		{
16552268Sobrien 	case X509_LU_X509:
16652268Sobrien 		ret=X509_subject_name_cmp((*a)->data.x509,(*b)->data.x509);
16752268Sobrien 		break;
16852268Sobrien 	case X509_LU_CRL:
16918334Speter 		ret=X509_CRL_cmp((*a)->data.crl,(*b)->data.crl);
17018334Speter 		break;
17118334Speter	default:
17218334Speter		/* abort(); */
17318334Speter		return 0;
17418334Speter		}
17518334Speter	return ret;
17618334Speter	}
17718334Speter
17818334SpeterX509_STORE *X509_STORE_new(void)
17918334Speter	{
18018334Speter	X509_STORE *ret;
18118334Speter
18218334Speter	if ((ret=(X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
18318334Speter		return NULL;
18418334Speter	ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
18518334Speter	ret->cache=1;
18618334Speter	ret->get_cert_methods=sk_X509_LOOKUP_new_null();
18718334Speter	ret->verify=0;
18818334Speter	ret->verify_cb=0;
18918334Speter
19018334Speter	ret->purpose = 0;
19118334Speter	ret->trust = 0;
19218334Speter
19318334Speter	ret->flags = 0;
19418334Speter
19552268Sobrien	ret->get_issuer = 0;
19618334Speter	ret->check_issued = 0;
19718334Speter	ret->check_revocation = 0;
19818334Speter	ret->get_crl = 0;
19918334Speter	ret->check_crl = 0;
20018334Speter	ret->cert_crl = 0;
20118334Speter	ret->cleanup = 0;
20218334Speter
20318334Speter	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data);
20418334Speter	ret->references=1;
20518334Speter	ret->depth=0;
20618334Speter	return ret;
20718334Speter	}
20818334Speter
20918334Speterstatic void cleanup(X509_OBJECT *a)
21018334Speter	{
21118334Speter	if (a->type == X509_LU_X509)
21218334Speter		{
21318334Speter		X509_free(a->data.x509);
21418334Speter		}
21518334Speter	else if (a->type == X509_LU_CRL)
21618334Speter		{
21718334Speter		X509_CRL_free(a->data.crl);
21818334Speter		}
21918334Speter	else
22018334Speter		{
22118334Speter		/* abort(); */
22218334Speter		}
22352268Sobrien
22452268Sobrien	OPENSSL_free(a);
22552268Sobrien	}
22652268Sobrien
22718334Spetervoid X509_STORE_free(X509_STORE *vfy)
22818334Speter	{
22918334Speter	int i;
23018334Speter	STACK_OF(X509_LOOKUP) *sk;
23118334Speter	X509_LOOKUP *lu;
23218334Speter
23318334Speter	if (vfy == NULL)
23418334Speter	    return;
23518334Speter
23618334Speter	sk=vfy->get_cert_methods;
23718334Speter	for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
23818334Speter		{
23918334Speter		lu=sk_X509_LOOKUP_value(sk,i);
24052268Sobrien		X509_LOOKUP_shutdown(lu);
24152268Sobrien		X509_LOOKUP_free(lu);
24252268Sobrien		}
24352518Sobrien	sk_X509_LOOKUP_free(sk);
24452518Sobrien	sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
24552518Sobrien
24652518Sobrien	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
24752518Sobrien	OPENSSL_free(vfy);
24852518Sobrien	}
24952518Sobrien
25018334SpeterX509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
25118334Speter	{
25218334Speter	int i;
25318334Speter	STACK_OF(X509_LOOKUP) *sk;
25418334Speter	X509_LOOKUP *lu;
25518334Speter
25618334Speter	sk=v->get_cert_methods;
25718334Speter	for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
25818334Speter		{
25918334Speter		lu=sk_X509_LOOKUP_value(sk,i);
26018334Speter		if (m == lu->method)
26118334Speter			{
26218334Speter			return lu;
26352518Sobrien			}
26452518Sobrien		}
26552518Sobrien	/* a new one */
26618334Speter	lu=X509_LOOKUP_new(m);
26718334Speter	if (lu == NULL)
26852518Sobrien		return NULL;
26918334Speter	else
27052518Sobrien		{
27152518Sobrien		lu->store_ctx=v;
27252518Sobrien		if (sk_X509_LOOKUP_push(v->get_cert_methods,lu))
27352518Sobrien			return lu;
27452518Sobrien		else
27518334Speter			{
27618334Speter			X509_LOOKUP_free(lu);
27718334Speter			return NULL;
27818334Speter			}
27918334Speter		}
28018334Speter	}
28118334Speter
28218334Speterint X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
28318334Speter	     X509_OBJECT *ret)
28418334Speter	{
28518334Speter	X509_STORE *ctx=vs->ctx;
28618334Speter	X509_LOOKUP *lu;
28718334Speter	X509_OBJECT stmp,*tmp;
28818334Speter	int i,j;
28918334Speter
29018334Speter	tmp=X509_OBJECT_retrieve_by_subject(ctx->objs,type,name);
29118334Speter
29218334Speter	if (tmp == NULL)
29318334Speter		{
29418334Speter		for (i=vs->current_method; i<sk_X509_LOOKUP_num(ctx->get_cert_methods); i++)
29518334Speter			{
29618334Speter			lu=sk_X509_LOOKUP_value(ctx->get_cert_methods,i);
29718334Speter			j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
29818334Speter			if (j < 0)
29918334Speter				{
30018334Speter				vs->current_method=j;
30118334Speter				return j;
30218334Speter				}
30318334Speter			else if (j)
30418334Speter				{
30518334Speter				tmp= &stmp;
30618334Speter				break;
30718334Speter				}
30818334Speter			}
30918334Speter		vs->current_method=0;
31018334Speter		if (tmp == NULL)
31118334Speter			return 0;
31218334Speter		}
31318334Speter
31418334Speter/*	if (ret->data.ptr != NULL)
31518334Speter		X509_OBJECT_free_contents(ret); */
31618334Speter
31718334Speter	ret->type=tmp->type;
31818334Speter	ret->data.ptr=tmp->data.ptr;
31918334Speter
32018334Speter	X509_OBJECT_up_ref_count(ret);
32152268Sobrien
32218334Speter	return 1;
32318334Speter	}
32418334Speter
32518334Speterint X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
32618334Speter	{
32718334Speter	X509_OBJECT *obj;
32818334Speter	int ret=1;
32918334Speter
33018334Speter	if (x == NULL) return 0;
33118334Speter	obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
33218334Speter	if (obj == NULL)
33318334Speter		{
33418334Speter		X509err(X509_F_X509_STORE_ADD_CERT,ERR_R_MALLOC_FAILURE);
33518334Speter		return 0;
33618334Speter		}
33718334Speter	obj->type=X509_LU_X509;
33818334Speter	obj->data.x509=x;
33918334Speter
34018334Speter	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
34118334Speter
34218334Speter	X509_OBJECT_up_ref_count(obj);
34318334Speter
34418334Speter
34518334Speter	if (X509_OBJECT_retrieve_match(ctx->objs, obj))
34618334Speter		{
34718334Speter		X509_OBJECT_free_contents(obj);
34818334Speter		OPENSSL_free(obj);
34952268Sobrien		X509err(X509_F_X509_STORE_ADD_CERT,X509_R_CERT_ALREADY_IN_HASH_TABLE);
35052268Sobrien		ret=0;
35152268Sobrien		}
35218334Speter	else sk_X509_OBJECT_push(ctx->objs, obj);
35318334Speter
35418334Speter	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
35552268Sobrien
35652268Sobrien	return ret;
35752268Sobrien	}
35818334Speter
35918334Speterint X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
36018334Speter	{
36118334Speter	X509_OBJECT *obj;
36218334Speter	int ret=1;
36318334Speter
36418334Speter	if (x == NULL) return 0;
36518334Speter	obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
36652268Sobrien	if (obj == NULL)
36752268Sobrien		{
36818334Speter		X509err(X509_F_X509_STORE_ADD_CRL,ERR_R_MALLOC_FAILURE);
36918334Speter		return 0;
37018334Speter		}
37118334Speter	obj->type=X509_LU_CRL;
37218334Speter	obj->data.crl=x;
37318334Speter
37418334Speter	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
37518334Speter
37618334Speter	X509_OBJECT_up_ref_count(obj);
37718334Speter
37818334Speter	if (X509_OBJECT_retrieve_match(ctx->objs, obj))
37918334Speter		{
38018334Speter		X509_OBJECT_free_contents(obj);
38118334Speter		OPENSSL_free(obj);
38218334Speter		X509err(X509_F_X509_STORE_ADD_CRL,X509_R_CERT_ALREADY_IN_HASH_TABLE);
38318334Speter		ret=0;
38418334Speter		}
38518334Speter	else sk_X509_OBJECT_push(ctx->objs, obj);
38618334Speter
38718334Speter	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
38818334Speter
38918334Speter	return ret;
39018334Speter	}
39118334Speter
39218334Spetervoid X509_OBJECT_up_ref_count(X509_OBJECT *a)
39318334Speter	{
39418334Speter	switch (a->type)
39518334Speter		{
39618334Speter	case X509_LU_X509:
39718334Speter		CRYPTO_add(&a->data.x509->references,1,CRYPTO_LOCK_X509);
39852268Sobrien		break;
39918334Speter	case X509_LU_CRL:
40018334Speter		CRYPTO_add(&a->data.crl->references,1,CRYPTO_LOCK_X509_CRL);
40118334Speter		break;
40218334Speter		}
40352518Sobrien	}
40452518Sobrien
40518334Spetervoid X509_OBJECT_free_contents(X509_OBJECT *a)
40652268Sobrien	{
40752518Sobrien	switch (a->type)
40852518Sobrien		{
40952518Sobrien	case X509_LU_X509:
41052518Sobrien		X509_free(a->data.x509);
41152518Sobrien		break;
41252518Sobrien	case X509_LU_CRL:
41352518Sobrien		X509_CRL_free(a->data.crl);
41452518Sobrien		break;
41552518Sobrien		}
41652518Sobrien	}
41752518Sobrien
41818334Speterint X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
41918334Speter	     X509_NAME *name)
42018334Speter	{
42118334Speter	X509_OBJECT stmp;
42218334Speter	X509 x509_s;
42318334Speter	X509_CINF cinf_s;
42418334Speter	X509_CRL crl_s;
42518334Speter	X509_CRL_INFO crl_info_s;
42618334Speter
42718334Speter	stmp.type=type;
42818334Speter	switch (type)
42918334Speter		{
43052268Sobrien	case X509_LU_X509:
43118334Speter		stmp.data.x509= &x509_s;
43218334Speter		x509_s.cert_info= &cinf_s;
43352268Sobrien		cinf_s.subject=name;
43418334Speter		break;
43518334Speter	case X509_LU_CRL:
43618334Speter		stmp.data.crl= &crl_s;
43718334Speter		crl_s.crl= &crl_info_s;
43818334Speter		crl_info_s.issuer=name;
43918334Speter		break;
44018334Speter	default:
44118334Speter		/* abort(); */
44218334Speter		return -1;
44318334Speter		}
44452268Sobrien
44518334Speter	return sk_X509_OBJECT_find(h,&stmp);
44652268Sobrien	}
44718334Speter
44852268SobrienX509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type,
44952268Sobrien	     X509_NAME *name)
45052268Sobrien{
45152268Sobrien	int idx;
45252268Sobrien	idx = X509_OBJECT_idx_by_subject(h, type, name);
45352268Sobrien	if (idx==-1) return NULL;
45418334Speter	return sk_X509_OBJECT_value(h, idx);
45518334Speter}
45618334Speter
45718334SpeterX509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x)
45818334Speter{
45918334Speter	int idx, i;
46018334Speter	X509_OBJECT *obj;
46118334Speter	idx = sk_X509_OBJECT_find(h, x);
46218334Speter	if (idx == -1) return NULL;
46318334Speter	if (x->type != X509_LU_X509) return sk_X509_OBJECT_value(h, idx);
46418334Speter	for (i = idx; i < sk_X509_OBJECT_num(h); i++)
46518334Speter		{
46652518Sobrien		obj = sk_X509_OBJECT_value(h, i);
46752518Sobrien		if (x509_object_cmp((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
46852518Sobrien			return NULL;
46952518Sobrien		if ((x->type != X509_LU_X509) || !X509_cmp(obj->data.x509, x->data.x509))
47052518Sobrien			return obj;
47152518Sobrien		}
47252518Sobrien	return NULL;
47318334Speter}
47418334Speter
47552268Sobrien
47652268Sobrien/* Try to get issuer certificate from store. Due to limitations
47752518Sobrien * of the API this can only retrieve a single certificate matching
47852518Sobrien * a given subject name. However it will fill the cache with all
47918334Speter * matching certificates, so we can examine the cache for all
48018334Speter * matches.
48118334Speter *
48252518Sobrien * Return values are:
48352518Sobrien *  1 lookup successful.
48452518Sobrien *  0 certificate not found.
48552518Sobrien * -1 some other error.
48618334Speter */
48718334Speter
48818334Speter
48952518Sobrienint X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
49018334Speter{
49118334Speter	X509_NAME *xn;
49218334Speter	X509_OBJECT obj, *pobj;
49318334Speter	int i, ok, idx;
49418334Speter	xn=X509_get_issuer_name(x);
49518334Speter	ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
49618334Speter	if (ok != X509_LU_X509)
49718334Speter		{
49818334Speter		if (ok == X509_LU_RETRY)
49918334Speter			{
50018334Speter			X509_OBJECT_free_contents(&obj);
50118334Speter			X509err(X509_F_X509_VERIFY_CERT,X509_R_SHOULD_RETRY);
50252268Sobrien			return -1;
50318334Speter			}
50418334Speter		else if (ok != X509_LU_FAIL)
50552268Sobrien			{
50652268Sobrien			X509_OBJECT_free_contents(&obj);
50718334Speter			/* not good :-(, break anyway */
50852268Sobrien			return -1;
50918334Speter			}
51018334Speter		return 0;
51118334Speter		}
51252268Sobrien	/* If certificate matches all OK */
51318334Speter	if (ctx->check_issued(ctx, x, obj.data.x509))
51418334Speter		{
51552268Sobrien		*issuer = obj.data.x509;
51652518Sobrien		return 1;
51752518Sobrien		}
51852518Sobrien	X509_OBJECT_free_contents(&obj);
51952518Sobrien	/* Else find index of first matching cert */
52052518Sobrien	idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
52152518Sobrien	/* This shouldn't normally happen since we already have one match */
52252518Sobrien	if (idx == -1) return 0;
52352518Sobrien
52452518Sobrien	/* Look through all matching certificates for a suitable issuer */
52552518Sobrien	for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++)
52652518Sobrien		{
52718334Speter		pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
52818334Speter		/* See if we've ran out of matches */
52918334Speter		if (pobj->type != X509_LU_X509) return 0;
53018334Speter		if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509))) return 0;
53118334Speter		if (ctx->check_issued(ctx, x, pobj->data.x509))
53218334Speter			{
53318334Speter			*issuer = pobj->data.x509;
53418334Speter			X509_OBJECT_up_ref_count(pobj);
53518334Speter			return 1;
53618334Speter			}
53718334Speter		}
53818334Speter	return 0;
53952268Sobrien}
54018334Speter
54118334Spetervoid X509_STORE_set_flags(X509_STORE *ctx, long flags)
54218334Speter	{
54352268Sobrien	ctx->flags |= flags;
54418334Speter	}
54518334Speter
54618334Speterint X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
54718334Speter	{
54818334Speter	return X509_PURPOSE_set(&ctx->purpose, purpose);
54918334Speter	}
55018334Speter
55118334Speterint X509_STORE_set_trust(X509_STORE *ctx, int trust)
55218334Speter	{
55318334Speter	return X509_TRUST_set(&ctx->trust, trust);
55418334Speter	}
55518334Speter
55618334SpeterIMPLEMENT_STACK_OF(X509_LOOKUP)
55718334SpeterIMPLEMENT_STACK_OF(X509_OBJECT)
55818334Speter