Home | History | Annotate | Download | only in x509
      1 /* crypto/x509/x509_lu.c */
      2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      3  * All rights reserved.
      4  *
      5  * This package is an SSL implementation written
      6  * by Eric Young (eay (at) cryptsoft.com).
      7  * The implementation was written so as to conform with Netscapes SSL.
      8  *
      9  * This library is free for commercial and non-commercial use as long as
     10  * the following conditions are aheared to.  The following conditions
     11  * apply to all code found in this distribution, be it the RC4, RSA,
     12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
     13  * included with this distribution is covered by the same copyright terms
     14  * except that the holder is Tim Hudson (tjh (at) cryptsoft.com).
     15  *
     16  * Copyright remains Eric Young's, and as such any Copyright notices in
     17  * the code are not to be removed.
     18  * If this package is used in a product, Eric Young should be given attribution
     19  * as the author of the parts of the library used.
     20  * This can be in the form of a textual message at program startup or
     21  * in documentation (online or textual) provided with the package.
     22  *
     23  * Redistribution and use in source and binary forms, with or without
     24  * modification, are permitted provided that the following conditions
     25  * are met:
     26  * 1. Redistributions of source code must retain the copyright
     27  *    notice, this list of conditions and the following disclaimer.
     28  * 2. Redistributions in binary form must reproduce the above copyright
     29  *    notice, this list of conditions and the following disclaimer in the
     30  *    documentation and/or other materials provided with the distribution.
     31  * 3. All advertising materials mentioning features or use of this software
     32  *    must display the following acknowledgement:
     33  *    "This product includes cryptographic software written by
     34  *     Eric Young (eay (at) cryptsoft.com)"
     35  *    The word 'cryptographic' can be left out if the rouines from the library
     36  *    being used are not cryptographic related :-).
     37  * 4. If you include any Windows specific code (or a derivative thereof) from
     38  *    the apps directory (application code) you must include an acknowledgement:
     39  *    "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)"
     40  *
     41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
     42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     51  * SUCH DAMAGE.
     52  *
     53  * The licence and distribution terms for any publically available version or
     54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
     55  * copied and put under another distribution licence
     56  * [including the GNU Public Licence.] */
     57 
     58 #include <string.h>
     59 
     60 #include <openssl/err.h>
     61 #include <openssl/lhash.h>
     62 #include <openssl/mem.h>
     63 #include <openssl/thread.h>
     64 #include <openssl/x509.h>
     65 #include <openssl/x509v3.h>
     66 
     67 #include "../internal.h"
     68 
     69 
     70 X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
     71 	{
     72 	X509_LOOKUP *ret;
     73 
     74 	ret=(X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
     75 	if (ret == NULL) return NULL;
     76 
     77 	ret->init=0;
     78 	ret->skip=0;
     79 	ret->method=method;
     80 	ret->method_data=NULL;
     81 	ret->store_ctx=NULL;
     82 	if ((method->new_item != NULL) && !method->new_item(ret))
     83 		{
     84 		OPENSSL_free(ret);
     85 		return NULL;
     86 		}
     87 	return ret;
     88 	}
     89 
     90 void X509_LOOKUP_free(X509_LOOKUP *ctx)
     91 	{
     92 	if (ctx == NULL) return;
     93 	if (	(ctx->method != NULL) &&
     94 		(ctx->method->free != NULL))
     95 		(*ctx->method->free)(ctx);
     96 	OPENSSL_free(ctx);
     97 	}
     98 
     99 int X509_LOOKUP_init(X509_LOOKUP *ctx)
    100 	{
    101 	if (ctx->method == NULL) return 0;
    102 	if (ctx->method->init != NULL)
    103 		return ctx->method->init(ctx);
    104 	else
    105 		return 1;
    106 	}
    107 
    108 int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
    109 	{
    110 	if (ctx->method == NULL) return 0;
    111 	if (ctx->method->shutdown != NULL)
    112 		return ctx->method->shutdown(ctx);
    113 	else
    114 		return 1;
    115 	}
    116 
    117 int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
    118 	     char **ret)
    119 	{
    120 	if (ctx->method == NULL) return -1;
    121 	if (ctx->method->ctrl != NULL)
    122 		return ctx->method->ctrl(ctx,cmd,argc,argl,ret);
    123 	else
    124 		return 1;
    125 	}
    126 
    127 int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
    128 	     X509_OBJECT *ret)
    129 	{
    130 	if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
    131 		return X509_LU_FAIL;
    132 	if (ctx->skip) return 0;
    133 	return ctx->method->get_by_subject(ctx,type,name,ret);
    134 	}
    135 
    136 int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
    137 	     ASN1_INTEGER *serial, X509_OBJECT *ret)
    138 	{
    139 	if ((ctx->method == NULL) ||
    140 		(ctx->method->get_by_issuer_serial == NULL))
    141 		return X509_LU_FAIL;
    142 	return ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret);
    143 	}
    144 
    145 int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
    146 	     unsigned char *bytes, int len, X509_OBJECT *ret)
    147 	{
    148 	if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
    149 		return X509_LU_FAIL;
    150 	return ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret);
    151 	}
    152 
    153 int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
    154 	     X509_OBJECT *ret)
    155 	{
    156 	if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
    157 		return X509_LU_FAIL;
    158 	return ctx->method->get_by_alias(ctx,type,str,len,ret);
    159 	}
    160 
    161 
    162 static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b)
    163   	{
    164  	int ret;
    165 
    166  	ret=((*a)->type - (*b)->type);
    167  	if (ret) return ret;
    168  	switch ((*a)->type)
    169  		{
    170  	case X509_LU_X509:
    171  		ret=X509_subject_name_cmp((*a)->data.x509,(*b)->data.x509);
    172  		break;
    173  	case X509_LU_CRL:
    174  		ret=X509_CRL_cmp((*a)->data.crl,(*b)->data.crl);
    175  		break;
    176 	default:
    177 		/* abort(); */
    178 		return 0;
    179 		}
    180 	return ret;
    181 	}
    182 
    183 X509_STORE *X509_STORE_new(void)
    184 	{
    185 	X509_STORE *ret;
    186 
    187 	if ((ret=(X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
    188 		return NULL;
    189 	memset(ret, 0, sizeof(*ret));
    190 	CRYPTO_MUTEX_init(&ret->objs_lock);
    191 	ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
    192 	if (ret->objs == NULL)
    193 		goto err;
    194 	ret->cache = 1;
    195 	ret->get_cert_methods = sk_X509_LOOKUP_new_null();
    196 	if (ret->get_cert_methods == NULL)
    197 		goto err;
    198 	ret->param = X509_VERIFY_PARAM_new();
    199 	if (ret->param == NULL)
    200 		goto err;
    201 
    202 	ret->references = 1;
    203 	return ret;
    204 err:
    205 	if (ret)
    206 		{
    207 		CRYPTO_MUTEX_cleanup(&ret->objs_lock);
    208 		if (ret->param)
    209 			X509_VERIFY_PARAM_free(ret->param);
    210 		if (ret->get_cert_methods)
    211 			sk_X509_LOOKUP_free(ret->get_cert_methods);
    212 		if (ret->objs)
    213 			sk_X509_OBJECT_free(ret->objs);
    214 		OPENSSL_free(ret);
    215 		}
    216 	return NULL;
    217 	}
    218 
    219 static void cleanup(X509_OBJECT *a)
    220 	{
    221 	if (a->type == X509_LU_X509)
    222 		{
    223 		X509_free(a->data.x509);
    224 		}
    225 	else if (a->type == X509_LU_CRL)
    226 		{
    227 		X509_CRL_free(a->data.crl);
    228 		}
    229 	else
    230 		{
    231 		/* abort(); */
    232 		}
    233 
    234 	OPENSSL_free(a);
    235 	}
    236 
    237 void X509_STORE_free(X509_STORE *vfy)
    238 	{
    239 	size_t j;
    240 	STACK_OF(X509_LOOKUP) *sk;
    241 	X509_LOOKUP *lu;
    242 
    243 	if (vfy == NULL)
    244 	    return;
    245 
    246 	if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) {
    247 	  return;
    248 	}
    249 
    250 	CRYPTO_MUTEX_cleanup(&vfy->objs_lock);
    251 
    252 	sk=vfy->get_cert_methods;
    253 	for (j=0; j<sk_X509_LOOKUP_num(sk); j++)
    254 		{
    255 		lu=sk_X509_LOOKUP_value(sk,j);
    256 		X509_LOOKUP_shutdown(lu);
    257 		X509_LOOKUP_free(lu);
    258 		}
    259 	sk_X509_LOOKUP_free(sk);
    260 	sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
    261 
    262 	if (vfy->param)
    263 		X509_VERIFY_PARAM_free(vfy->param);
    264 	OPENSSL_free(vfy);
    265 	}
    266 
    267 X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
    268 	{
    269 	size_t i;
    270 	STACK_OF(X509_LOOKUP) *sk;
    271 	X509_LOOKUP *lu;
    272 
    273 	sk=v->get_cert_methods;
    274 	for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
    275 		{
    276 		lu=sk_X509_LOOKUP_value(sk,i);
    277 		if (m == lu->method)
    278 			{
    279 			return lu;
    280 			}
    281 		}
    282 	/* a new one */
    283 	lu=X509_LOOKUP_new(m);
    284 	if (lu == NULL)
    285 		return NULL;
    286 	else
    287 		{
    288 		lu->store_ctx=v;
    289 		if (sk_X509_LOOKUP_push(v->get_cert_methods,lu))
    290 			return lu;
    291 		else
    292 			{
    293 			X509_LOOKUP_free(lu);
    294 			return NULL;
    295 			}
    296 		}
    297 	}
    298 
    299 int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
    300 	     X509_OBJECT *ret)
    301 	{
    302 	X509_STORE *ctx=vs->ctx;
    303 	X509_LOOKUP *lu;
    304 	X509_OBJECT stmp,*tmp;
    305 	int i,j;
    306 
    307 	CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
    308 	tmp=X509_OBJECT_retrieve_by_subject(ctx->objs,type,name);
    309 	CRYPTO_MUTEX_unlock(&ctx->objs_lock);
    310 
    311 	if (tmp == NULL || type == X509_LU_CRL)
    312 		{
    313 		for (i=vs->current_method; i<(int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++)
    314 			{
    315 			lu=sk_X509_LOOKUP_value(ctx->get_cert_methods,i);
    316 			j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
    317 			if (j < 0)
    318 				{
    319 				vs->current_method=j;
    320 				return j;
    321 				}
    322 			else if (j)
    323 				{
    324 				tmp= &stmp;
    325 				break;
    326 				}
    327 			}
    328 		vs->current_method=0;
    329 		if (tmp == NULL)
    330 			return 0;
    331 		}
    332 
    333 /*	if (ret->data.ptr != NULL)
    334 		X509_OBJECT_free_contents(ret); */
    335 
    336 	ret->type=tmp->type;
    337 	ret->data.ptr=tmp->data.ptr;
    338 
    339 	X509_OBJECT_up_ref_count(ret);
    340 
    341 	return 1;
    342 	}
    343 
    344 int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
    345 	{
    346 	X509_OBJECT *obj;
    347 	int ret=1;
    348 
    349 	if (x == NULL) return 0;
    350 	obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
    351 	if (obj == NULL)
    352 		{
    353 		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
    354 		return 0;
    355 		}
    356 	obj->type=X509_LU_X509;
    357 	obj->data.x509=x;
    358 
    359 	CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
    360 
    361 	X509_OBJECT_up_ref_count(obj);
    362 
    363 	if (X509_OBJECT_retrieve_match(ctx->objs, obj))
    364 		{
    365 		X509_OBJECT_free_contents(obj);
    366 		OPENSSL_free(obj);
    367 		OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
    368 		ret=0;
    369 		}
    370 	else sk_X509_OBJECT_push(ctx->objs, obj);
    371 
    372 	CRYPTO_MUTEX_unlock(&ctx->objs_lock);
    373 
    374 	return ret;
    375 	}
    376 
    377 int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
    378 	{
    379 	X509_OBJECT *obj;
    380 	int ret=1;
    381 
    382 	if (x == NULL) return 0;
    383 	obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
    384 	if (obj == NULL)
    385 		{
    386 		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
    387 		return 0;
    388 		}
    389 	obj->type=X509_LU_CRL;
    390 	obj->data.crl=x;
    391 
    392 	CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
    393 
    394 	X509_OBJECT_up_ref_count(obj);
    395 
    396 	if (X509_OBJECT_retrieve_match(ctx->objs, obj))
    397 		{
    398 		X509_OBJECT_free_contents(obj);
    399 		OPENSSL_free(obj);
    400 		OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
    401 		ret=0;
    402 		}
    403 	else sk_X509_OBJECT_push(ctx->objs, obj);
    404 
    405 	CRYPTO_MUTEX_unlock(&ctx->objs_lock);
    406 
    407 	return ret;
    408 	}
    409 
    410 void X509_OBJECT_up_ref_count(X509_OBJECT *a)
    411 	{
    412 	switch (a->type)
    413 		{
    414 	case X509_LU_X509:
    415 		X509_up_ref(a->data.x509);
    416 		break;
    417 	case X509_LU_CRL:
    418 		X509_CRL_up_ref(a->data.crl);
    419 		break;
    420 		}
    421 	}
    422 
    423 void X509_OBJECT_free_contents(X509_OBJECT *a)
    424 	{
    425 	switch (a->type)
    426 		{
    427 	case X509_LU_X509:
    428 		X509_free(a->data.x509);
    429 		break;
    430 	case X509_LU_CRL:
    431 		X509_CRL_free(a->data.crl);
    432 		break;
    433 		}
    434 	}
    435 
    436 static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
    437 	     X509_NAME *name, int *pnmatch)
    438 	{
    439 	X509_OBJECT stmp;
    440 	X509 x509_s;
    441 	X509_CINF cinf_s;
    442 	X509_CRL crl_s;
    443 	X509_CRL_INFO crl_info_s;
    444 
    445 	stmp.type=type;
    446 	switch (type)
    447 		{
    448 	case X509_LU_X509:
    449 		stmp.data.x509= &x509_s;
    450 		x509_s.cert_info= &cinf_s;
    451 		cinf_s.subject=name;
    452 		break;
    453 	case X509_LU_CRL:
    454 		stmp.data.crl= &crl_s;
    455 		crl_s.crl= &crl_info_s;
    456 		crl_info_s.issuer=name;
    457 		break;
    458 	default:
    459 		/* abort(); */
    460 		return -1;
    461 		}
    462 
    463 	size_t idx;
    464 	if (!sk_X509_OBJECT_find(h, &idx, &stmp))
    465 		return -1;
    466 
    467 	if (pnmatch != NULL)
    468 		{
    469 		int tidx;
    470 		const X509_OBJECT *tobj, *pstmp;
    471 		*pnmatch = 1;
    472 		pstmp = &stmp;
    473 		for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++)
    474 			{
    475 			tobj = sk_X509_OBJECT_value(h, tidx);
    476 			if (x509_object_cmp(&tobj, &pstmp))
    477 				break;
    478 			(*pnmatch)++;
    479 			}
    480 		}
    481 
    482 	return idx;
    483 	}
    484 
    485 
    486 int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
    487 	     X509_NAME *name)
    488 	{
    489 	return x509_object_idx_cnt(h, type, name, NULL);
    490 	}
    491 
    492 X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type,
    493 	     X509_NAME *name)
    494 	{
    495 	int idx;
    496 	idx = X509_OBJECT_idx_by_subject(h, type, name);
    497 	if (idx==-1) return NULL;
    498 	return sk_X509_OBJECT_value(h, idx);
    499 	}
    500 
    501 STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
    502 	{
    503 	int i, idx, cnt;
    504 	STACK_OF(X509) *sk;
    505 	X509 *x;
    506 	X509_OBJECT *obj;
    507 	sk = sk_X509_new_null();
    508 	if (sk == NULL)
    509 		return NULL;
    510 	CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    511 	idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
    512 	if (idx < 0)
    513 		{
    514 		/* Nothing found in cache: do lookup to possibly add new
    515 		 * objects to cache
    516 		 */
    517 		X509_OBJECT xobj;
    518 		CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
    519 		if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj))
    520 			{
    521 			sk_X509_free(sk);
    522 			return NULL;
    523 			}
    524 		X509_OBJECT_free_contents(&xobj);
    525 		CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    526 		idx = x509_object_idx_cnt(ctx->ctx->objs,X509_LU_X509,nm, &cnt);
    527 		if (idx < 0)
    528 			{
    529 			CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
    530 			sk_X509_free(sk);
    531 			return NULL;
    532 			}
    533 		}
    534 	for (i = 0; i < cnt; i++, idx++)
    535 		{
    536 		obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
    537 		x = obj->data.x509;
    538 		if (!sk_X509_push(sk, X509_up_ref(x)))
    539 			{
    540 			CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
    541 			X509_free(x);
    542 			sk_X509_pop_free(sk, X509_free);
    543 			return NULL;
    544 			}
    545 		}
    546 	CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
    547 	return sk;
    548 
    549 	}
    550 
    551 STACK_OF(X509_CRL)* X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
    552 	{
    553 	int i, idx, cnt;
    554 	STACK_OF(X509_CRL) *sk;
    555 	X509_CRL *x;
    556 	X509_OBJECT *obj, xobj;
    557 	sk = sk_X509_CRL_new_null();
    558 	if (sk == NULL)
    559 		return NULL;
    560 
    561 	/* Always do lookup to possibly add new CRLs to cache. */
    562 	if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj))
    563 		{
    564 		sk_X509_CRL_free(sk);
    565 		return NULL;
    566 		}
    567 	X509_OBJECT_free_contents(&xobj);
    568 	CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    569 	idx = x509_object_idx_cnt(ctx->ctx->objs,X509_LU_CRL, nm, &cnt);
    570 	if (idx < 0)
    571 		{
    572 		CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
    573 		sk_X509_CRL_free(sk);
    574 		return NULL;
    575 		}
    576 
    577 	for (i = 0; i < cnt; i++, idx++)
    578 		{
    579 		obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
    580 		x = obj->data.crl;
    581 		X509_CRL_up_ref(x);
    582 		if (!sk_X509_CRL_push(sk, x))
    583 			{
    584 			CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
    585 			X509_CRL_free(x);
    586 			sk_X509_CRL_pop_free(sk, X509_CRL_free);
    587 			return NULL;
    588 			}
    589 		}
    590 	CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
    591 	return sk;
    592 	}
    593 
    594 X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x)
    595 	{
    596 	size_t idx, i;
    597 	X509_OBJECT *obj;
    598 
    599 	if (!sk_X509_OBJECT_find(h, &idx, x)) {
    600 		return NULL;
    601 	}
    602 	if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
    603 		return sk_X509_OBJECT_value(h, idx);
    604 	for (i = idx; i < sk_X509_OBJECT_num(h); i++)
    605 		{
    606 		obj = sk_X509_OBJECT_value(h, i);
    607 		if (x509_object_cmp((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
    608 			return NULL;
    609 		if (x->type == X509_LU_X509)
    610 			{
    611 			if (!X509_cmp(obj->data.x509, x->data.x509))
    612 				return obj;
    613 			}
    614 		else if (x->type == X509_LU_CRL)
    615 			{
    616 			if (!X509_CRL_match(obj->data.crl, x->data.crl))
    617 				return obj;
    618 			}
    619 		else
    620 			return obj;
    621 		}
    622 	return NULL;
    623 	}
    624 
    625 
    626 /* Try to get issuer certificate from store. Due to limitations
    627  * of the API this can only retrieve a single certificate matching
    628  * a given subject name. However it will fill the cache with all
    629  * matching certificates, so we can examine the cache for all
    630  * matches.
    631  *
    632  * Return values are:
    633  *  1 lookup successful.
    634  *  0 certificate not found.
    635  * -1 some other error.
    636  */
    637 int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
    638 	{
    639 	X509_NAME *xn;
    640 	X509_OBJECT obj, *pobj;
    641 	int ok, idx, ret;
    642 	size_t i;
    643 	xn=X509_get_issuer_name(x);
    644 	ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
    645 	if (ok != X509_LU_X509)
    646 		{
    647 		if (ok == X509_LU_RETRY)
    648 			{
    649 			X509_OBJECT_free_contents(&obj);
    650 			OPENSSL_PUT_ERROR(X509, X509_R_SHOULD_RETRY);
    651 			return -1;
    652 			}
    653 		else if (ok != X509_LU_FAIL)
    654 			{
    655 			X509_OBJECT_free_contents(&obj);
    656 			/* not good :-(, break anyway */
    657 			return -1;
    658 			}
    659 		return 0;
    660 		}
    661 	/* If certificate matches all OK */
    662 	if (ctx->check_issued(ctx, x, obj.data.x509))
    663 		{
    664 		*issuer = obj.data.x509;
    665 		return 1;
    666 		}
    667 	X509_OBJECT_free_contents(&obj);
    668 
    669 	/* Else find index of first cert accepted by 'check_issued' */
    670 	ret = 0;
    671 	CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    672 	idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
    673 	if (idx != -1) /* should be true as we've had at least one match */
    674 		{
    675 		/* Look through all matching certs for suitable issuer */
    676 		for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++)
    677 			{
    678 			pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
    679 			/* See if we've run past the matches */
    680 			if (pobj->type != X509_LU_X509)
    681 				break;
    682 			if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
    683 				break;
    684 			if (ctx->check_issued(ctx, x, pobj->data.x509))
    685 				{
    686 				*issuer = pobj->data.x509;
    687 				X509_OBJECT_up_ref_count(pobj);
    688 				ret = 1;
    689 				break;
    690 				}
    691 			}
    692 		}
    693 	CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
    694 	return ret;
    695 	}
    696 
    697 int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
    698 	{
    699 	return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
    700 	}
    701 
    702 int X509_STORE_set_depth(X509_STORE *ctx, int depth)
    703 	{
    704 	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
    705 	return 1;
    706 	}
    707 
    708 int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
    709 	{
    710 	return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
    711 	}
    712 
    713 int X509_STORE_set_trust(X509_STORE *ctx, int trust)
    714 	{
    715 	return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
    716 	}
    717 
    718 int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
    719 	{
    720 	return X509_VERIFY_PARAM_set1(ctx->param, param);
    721 	}
    722 
    723 void X509_STORE_set_verify_cb(X509_STORE *ctx,
    724 				  int (*verify_cb)(int, X509_STORE_CTX *))
    725 	{
    726 	ctx->verify_cb = verify_cb;
    727 	}
    728 
    729 void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx,
    730 		STACK_OF(X509_CRL)* (*cb)(X509_STORE_CTX *ctx, X509_NAME *nm))
    731 	{
    732 	ctx->lookup_crls = cb;
    733 	}
    734 
    735 X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
    736 	{
    737 	return ctx->ctx;
    738 	}
    739