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 
     59 #include <stdio.h>
     60 #include "cryptlib.h"
     61 #include <openssl/lhash.h>
     62 #include <openssl/x509.h>
     63 #include <openssl/x509v3.h>
     64 
     65 X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
     66 	{
     67 	X509_LOOKUP *ret;
     68 
     69 	ret=(X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
     70 	if (ret == NULL) return NULL;
     71 
     72 	ret->init=0;
     73 	ret->skip=0;
     74 	ret->method=method;
     75 	ret->method_data=NULL;
     76 	ret->store_ctx=NULL;
     77 	if ((method->new_item != NULL) && !method->new_item(ret))
     78 		{
     79 		OPENSSL_free(ret);
     80 		return NULL;
     81 		}
     82 	return ret;
     83 	}
     84 
     85 void X509_LOOKUP_free(X509_LOOKUP *ctx)
     86 	{
     87 	if (ctx == NULL) return;
     88 	if (	(ctx->method != NULL) &&
     89 		(ctx->method->free != NULL))
     90 		ctx->method->free(ctx);
     91 	OPENSSL_free(ctx);
     92 	}
     93 
     94 int X509_LOOKUP_init(X509_LOOKUP *ctx)
     95 	{
     96 	if (ctx->method == NULL) return 0;
     97 	if (ctx->method->init != NULL)
     98 		return ctx->method->init(ctx);
     99 	else
    100 		return 1;
    101 	}
    102 
    103 int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
    104 	{
    105 	if (ctx->method == NULL) return 0;
    106 	if (ctx->method->shutdown != NULL)
    107 		return ctx->method->shutdown(ctx);
    108 	else
    109 		return 1;
    110 	}
    111 
    112 int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
    113 	     char **ret)
    114 	{
    115 	if (ctx->method == NULL) return -1;
    116 	if (ctx->method->ctrl != NULL)
    117 		return ctx->method->ctrl(ctx,cmd,argc,argl,ret);
    118 	else
    119 		return 1;
    120 	}
    121 
    122 int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
    123 	     X509_OBJECT *ret)
    124 	{
    125 	if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
    126 		return X509_LU_FAIL;
    127 	if (ctx->skip) return 0;
    128 	return ctx->method->get_by_subject(ctx,type,name,ret);
    129 	}
    130 
    131 int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
    132 	     ASN1_INTEGER *serial, X509_OBJECT *ret)
    133 	{
    134 	if ((ctx->method == NULL) ||
    135 		(ctx->method->get_by_issuer_serial == NULL))
    136 		return X509_LU_FAIL;
    137 	return ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret);
    138 	}
    139 
    140 int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
    141 	     unsigned char *bytes, int len, X509_OBJECT *ret)
    142 	{
    143 	if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
    144 		return X509_LU_FAIL;
    145 	return ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret);
    146 	}
    147 
    148 int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
    149 	     X509_OBJECT *ret)
    150 	{
    151 	if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
    152 		return X509_LU_FAIL;
    153 	return ctx->method->get_by_alias(ctx,type,str,len,ret);
    154 	}
    155 
    156 
    157 static int x509_object_cmp(const X509_OBJECT * const *a, const X509_OBJECT * const *b)
    158   	{
    159  	int ret;
    160 
    161  	ret=((*a)->type - (*b)->type);
    162  	if (ret) return ret;
    163  	switch ((*a)->type)
    164  		{
    165  	case X509_LU_X509:
    166  		ret=X509_subject_name_cmp((*a)->data.x509,(*b)->data.x509);
    167  		break;
    168  	case X509_LU_CRL:
    169  		ret=X509_CRL_cmp((*a)->data.crl,(*b)->data.crl);
    170  		break;
    171 	default:
    172 		/* abort(); */
    173 		return 0;
    174 		}
    175 	return ret;
    176 	}
    177 
    178 X509_STORE *X509_STORE_new(void)
    179 	{
    180 	X509_STORE *ret;
    181 
    182 	if ((ret=(X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
    183 		return NULL;
    184 	ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
    185 	ret->cache=1;
    186 	ret->get_cert_methods=sk_X509_LOOKUP_new_null();
    187 	ret->verify=0;
    188 	ret->verify_cb=0;
    189 
    190 	if ((ret->param = X509_VERIFY_PARAM_new()) == NULL)
    191 		return NULL;
    192 
    193 	ret->get_issuer = 0;
    194 	ret->check_issued = 0;
    195 	ret->check_revocation = 0;
    196 	ret->get_crl = 0;
    197 	ret->check_crl = 0;
    198 	ret->cert_crl = 0;
    199 	ret->cleanup = 0;
    200 
    201 	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data))
    202 		{
    203 		sk_X509_OBJECT_free(ret->objs);
    204 		OPENSSL_free(ret);
    205 		return NULL;
    206 		}
    207 
    208 	ret->references=1;
    209 	return ret;
    210 	}
    211 
    212 static void cleanup(X509_OBJECT *a)
    213 	{
    214 	if (a->type == X509_LU_X509)
    215 		{
    216 		X509_free(a->data.x509);
    217 		}
    218 	else if (a->type == X509_LU_CRL)
    219 		{
    220 		X509_CRL_free(a->data.crl);
    221 		}
    222 	else
    223 		{
    224 		/* abort(); */
    225 		}
    226 
    227 	OPENSSL_free(a);
    228 	}
    229 
    230 void X509_STORE_free(X509_STORE *vfy)
    231 	{
    232 	int i;
    233 	STACK_OF(X509_LOOKUP) *sk;
    234 	X509_LOOKUP *lu;
    235 
    236 	if (vfy == NULL)
    237 	    return;
    238 
    239 	sk=vfy->get_cert_methods;
    240 	for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
    241 		{
    242 		lu=sk_X509_LOOKUP_value(sk,i);
    243 		X509_LOOKUP_shutdown(lu);
    244 		X509_LOOKUP_free(lu);
    245 		}
    246 	sk_X509_LOOKUP_free(sk);
    247 	sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
    248 
    249 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
    250 	if (vfy->param)
    251 		X509_VERIFY_PARAM_free(vfy->param);
    252 	OPENSSL_free(vfy);
    253 	}
    254 
    255 X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
    256 	{
    257 	int i;
    258 	STACK_OF(X509_LOOKUP) *sk;
    259 	X509_LOOKUP *lu;
    260 
    261 	sk=v->get_cert_methods;
    262 	for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
    263 		{
    264 		lu=sk_X509_LOOKUP_value(sk,i);
    265 		if (m == lu->method)
    266 			{
    267 			return lu;
    268 			}
    269 		}
    270 	/* a new one */
    271 	lu=X509_LOOKUP_new(m);
    272 	if (lu == NULL)
    273 		return NULL;
    274 	else
    275 		{
    276 		lu->store_ctx=v;
    277 		if (sk_X509_LOOKUP_push(v->get_cert_methods,lu))
    278 			return lu;
    279 		else
    280 			{
    281 			X509_LOOKUP_free(lu);
    282 			return NULL;
    283 			}
    284 		}
    285 	}
    286 
    287 int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
    288 	     X509_OBJECT *ret)
    289 	{
    290 	X509_STORE *ctx=vs->ctx;
    291 	X509_LOOKUP *lu;
    292 	X509_OBJECT stmp,*tmp;
    293 	int i,j;
    294 
    295 	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
    296 	tmp=X509_OBJECT_retrieve_by_subject(ctx->objs,type,name);
    297 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
    298 
    299 	if (tmp == NULL)
    300 		{
    301 		for (i=vs->current_method; i<sk_X509_LOOKUP_num(ctx->get_cert_methods); i++)
    302 			{
    303 			lu=sk_X509_LOOKUP_value(ctx->get_cert_methods,i);
    304 			j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
    305 			if (j < 0)
    306 				{
    307 				vs->current_method=j;
    308 				return j;
    309 				}
    310 			else if (j)
    311 				{
    312 				tmp= &stmp;
    313 				break;
    314 				}
    315 			}
    316 		vs->current_method=0;
    317 		if (tmp == NULL)
    318 			return 0;
    319 		}
    320 
    321 /*	if (ret->data.ptr != NULL)
    322 		X509_OBJECT_free_contents(ret); */
    323 
    324 	ret->type=tmp->type;
    325 	ret->data.ptr=tmp->data.ptr;
    326 
    327 	X509_OBJECT_up_ref_count(ret);
    328 
    329 	return 1;
    330 	}
    331 
    332 int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
    333 	{
    334 	X509_OBJECT *obj;
    335 	int ret=1;
    336 
    337 	if (x == NULL) return 0;
    338 	obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
    339 	if (obj == NULL)
    340 		{
    341 		X509err(X509_F_X509_STORE_ADD_CERT,ERR_R_MALLOC_FAILURE);
    342 		return 0;
    343 		}
    344 	obj->type=X509_LU_X509;
    345 	obj->data.x509=x;
    346 
    347 	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
    348 
    349 	X509_OBJECT_up_ref_count(obj);
    350 
    351 	if (X509_OBJECT_retrieve_match(ctx->objs, obj))
    352 		{
    353 		X509_OBJECT_free_contents(obj);
    354 		OPENSSL_free(obj);
    355 		X509err(X509_F_X509_STORE_ADD_CERT,X509_R_CERT_ALREADY_IN_HASH_TABLE);
    356 		ret=0;
    357 		}
    358 	else sk_X509_OBJECT_push(ctx->objs, obj);
    359 
    360 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
    361 
    362 	return ret;
    363 	}
    364 
    365 int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
    366 	{
    367 	X509_OBJECT *obj;
    368 	int ret=1;
    369 
    370 	if (x == NULL) return 0;
    371 	obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
    372 	if (obj == NULL)
    373 		{
    374 		X509err(X509_F_X509_STORE_ADD_CRL,ERR_R_MALLOC_FAILURE);
    375 		return 0;
    376 		}
    377 	obj->type=X509_LU_CRL;
    378 	obj->data.crl=x;
    379 
    380 	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
    381 
    382 	X509_OBJECT_up_ref_count(obj);
    383 
    384 	if (X509_OBJECT_retrieve_match(ctx->objs, obj))
    385 		{
    386 		X509_OBJECT_free_contents(obj);
    387 		OPENSSL_free(obj);
    388 		X509err(X509_F_X509_STORE_ADD_CRL,X509_R_CERT_ALREADY_IN_HASH_TABLE);
    389 		ret=0;
    390 		}
    391 	else sk_X509_OBJECT_push(ctx->objs, obj);
    392 
    393 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
    394 
    395 	return ret;
    396 	}
    397 
    398 void X509_OBJECT_up_ref_count(X509_OBJECT *a)
    399 	{
    400 	switch (a->type)
    401 		{
    402 	case X509_LU_X509:
    403 		CRYPTO_add(&a->data.x509->references,1,CRYPTO_LOCK_X509);
    404 		break;
    405 	case X509_LU_CRL:
    406 		CRYPTO_add(&a->data.crl->references,1,CRYPTO_LOCK_X509_CRL);
    407 		break;
    408 		}
    409 	}
    410 
    411 void X509_OBJECT_free_contents(X509_OBJECT *a)
    412 	{
    413 	switch (a->type)
    414 		{
    415 	case X509_LU_X509:
    416 		X509_free(a->data.x509);
    417 		break;
    418 	case X509_LU_CRL:
    419 		X509_CRL_free(a->data.crl);
    420 		break;
    421 		}
    422 	}
    423 
    424 int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
    425 	     X509_NAME *name)
    426 	{
    427 	X509_OBJECT stmp;
    428 	X509 x509_s;
    429 	X509_CINF cinf_s;
    430 	X509_CRL crl_s;
    431 	X509_CRL_INFO crl_info_s;
    432 
    433 	stmp.type=type;
    434 	switch (type)
    435 		{
    436 	case X509_LU_X509:
    437 		stmp.data.x509= &x509_s;
    438 		x509_s.cert_info= &cinf_s;
    439 		cinf_s.subject=name;
    440 		break;
    441 	case X509_LU_CRL:
    442 		stmp.data.crl= &crl_s;
    443 		crl_s.crl= &crl_info_s;
    444 		crl_info_s.issuer=name;
    445 		break;
    446 	default:
    447 		/* abort(); */
    448 		return -1;
    449 		}
    450 
    451 	return sk_X509_OBJECT_find(h,&stmp);
    452 	}
    453 
    454 X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type,
    455 	     X509_NAME *name)
    456 	{
    457 	int idx;
    458 	idx = X509_OBJECT_idx_by_subject(h, type, name);
    459 	if (idx==-1) return NULL;
    460 	return sk_X509_OBJECT_value(h, idx);
    461 	}
    462 
    463 X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x)
    464 	{
    465 	int idx, i;
    466 	X509_OBJECT *obj;
    467 	idx = sk_X509_OBJECT_find(h, x);
    468 	if (idx == -1) return NULL;
    469 	if (x->type != X509_LU_X509) return sk_X509_OBJECT_value(h, idx);
    470 	for (i = idx; i < sk_X509_OBJECT_num(h); i++)
    471 		{
    472 		obj = sk_X509_OBJECT_value(h, i);
    473 		if (x509_object_cmp((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
    474 			return NULL;
    475 		if ((x->type != X509_LU_X509) || !X509_cmp(obj->data.x509, x->data.x509))
    476 			return obj;
    477 		}
    478 	return NULL;
    479 	}
    480 
    481 
    482 /* Try to get issuer certificate from store. Due to limitations
    483  * of the API this can only retrieve a single certificate matching
    484  * a given subject name. However it will fill the cache with all
    485  * matching certificates, so we can examine the cache for all
    486  * matches.
    487  *
    488  * Return values are:
    489  *  1 lookup successful.
    490  *  0 certificate not found.
    491  * -1 some other error.
    492  */
    493 int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
    494 	{
    495 	X509_NAME *xn;
    496 	X509_OBJECT obj, *pobj;
    497 	int i, ok, idx, ret;
    498 	xn=X509_get_issuer_name(x);
    499 	ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
    500 	if (ok != X509_LU_X509)
    501 		{
    502 		if (ok == X509_LU_RETRY)
    503 			{
    504 			X509_OBJECT_free_contents(&obj);
    505 			X509err(X509_F_X509_STORE_CTX_GET1_ISSUER,X509_R_SHOULD_RETRY);
    506 			return -1;
    507 			}
    508 		else if (ok != X509_LU_FAIL)
    509 			{
    510 			X509_OBJECT_free_contents(&obj);
    511 			/* not good :-(, break anyway */
    512 			return -1;
    513 			}
    514 		return 0;
    515 		}
    516 	/* If certificate matches all OK */
    517 	if (ctx->check_issued(ctx, x, obj.data.x509))
    518 		{
    519 		*issuer = obj.data.x509;
    520 		return 1;
    521 		}
    522 	X509_OBJECT_free_contents(&obj);
    523 
    524 	/* Else find index of first cert accepted by 'check_issued' */
    525 	ret = 0;
    526 	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
    527 	idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
    528 	if (idx != -1) /* should be true as we've had at least one match */
    529 		{
    530 		/* Look through all matching certs for suitable issuer */
    531 		for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++)
    532 			{
    533 			pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
    534 			/* See if we've run past the matches */
    535 			if (pobj->type != X509_LU_X509)
    536 				break;
    537 			if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
    538 				break;
    539 			if (ctx->check_issued(ctx, x, pobj->data.x509))
    540 				{
    541 				*issuer = pobj->data.x509;
    542 				X509_OBJECT_up_ref_count(pobj);
    543 				ret = 1;
    544 				break;
    545 				}
    546 			}
    547 		}
    548 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
    549 	return ret;
    550 	}
    551 
    552 int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
    553 	{
    554 	return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
    555 	}
    556 
    557 int X509_STORE_set_depth(X509_STORE *ctx, int depth)
    558 	{
    559 	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
    560 	return 1;
    561 	}
    562 
    563 int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
    564 	{
    565 	return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
    566 	}
    567 
    568 int X509_STORE_set_trust(X509_STORE *ctx, int trust)
    569 	{
    570 	return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
    571 	}
    572 
    573 int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
    574 	{
    575 	return X509_VERIFY_PARAM_set1(ctx->param, param);
    576 	}
    577 
    578 IMPLEMENT_STACK_OF(X509_LOOKUP)
    579 IMPLEMENT_STACK_OF(X509_OBJECT)
    580