x509_lu.c revision 59191
1/* crypto/x509/x509_lu.c */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@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@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@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@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 64static STACK_OF(CRYPTO_EX_DATA_FUNCS) *x509_store_meth=NULL; 65static STACK_OF(CRYPTO_EX_DATA_FUNCS) *x509_store_ctx_meth=NULL; 66 67X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method) 68 { 69 X509_LOOKUP *ret; 70 71 ret=(X509_LOOKUP *)Malloc(sizeof(X509_LOOKUP)); 72 if (ret == NULL) return(NULL); 73 74 ret->init=0; 75 ret->skip=0; 76 ret->method=method; 77 ret->method_data=NULL; 78 ret->store_ctx=NULL; 79 if ((method->new_item != NULL) && !method->new_item(ret)) 80 { 81 Free(ret); 82 return(NULL); 83 } 84 return(ret); 85 } 86 87void X509_LOOKUP_free(X509_LOOKUP *ctx) 88 { 89 if (ctx == NULL) return; 90 if ( (ctx->method != NULL) && 91 (ctx->method->free != NULL)) 92 ctx->method->free(ctx); 93 Free(ctx); 94 } 95 96int X509_LOOKUP_init(X509_LOOKUP *ctx) 97 { 98 if (ctx->method == NULL) return(0); 99 if (ctx->method->init != NULL) 100 return(ctx->method->init(ctx)); 101 else 102 return(1); 103 } 104 105int X509_LOOKUP_shutdown(X509_LOOKUP *ctx) 106 { 107 if (ctx->method == NULL) return(0); 108 if (ctx->method->shutdown != NULL) 109 return(ctx->method->shutdown(ctx)); 110 else 111 return(1); 112 } 113 114int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, 115 char **ret) 116 { 117 if (ctx->method == NULL) return(-1); 118 if (ctx->method->ctrl != NULL) 119 return(ctx->method->ctrl(ctx,cmd,argc,argl,ret)); 120 else 121 return(1); 122 } 123 124int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, 125 X509_OBJECT *ret) 126 { 127 if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL)) 128 return(X509_LU_FAIL); 129 if (ctx->skip) return(0); 130 return(ctx->method->get_by_subject(ctx,type,name,ret)); 131 } 132 133int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, 134 ASN1_INTEGER *serial, X509_OBJECT *ret) 135 { 136 if ((ctx->method == NULL) || 137 (ctx->method->get_by_issuer_serial == NULL)) 138 return(X509_LU_FAIL); 139 return(ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret)); 140 } 141 142int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, 143 unsigned char *bytes, int len, X509_OBJECT *ret) 144 { 145 if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL)) 146 return(X509_LU_FAIL); 147 return(ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret)); 148 } 149 150int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len, 151 X509_OBJECT *ret) 152 { 153 if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL)) 154 return(X509_LU_FAIL); 155 return(ctx->method->get_by_alias(ctx,type,str,len,ret)); 156 } 157 158static unsigned long x509_object_hash(X509_OBJECT *a) 159 { 160 unsigned long h; 161 162 switch (a->type) 163 { 164 case X509_LU_X509: 165 h=X509_NAME_hash(a->data.x509->cert_info->subject); 166 break; 167 case X509_LU_CRL: 168 h=X509_NAME_hash(a->data.crl->crl->issuer); 169 break; 170 default: 171 abort(); 172 } 173 return(h); 174 } 175 176static int x509_object_cmp(X509_OBJECT *a, X509_OBJECT *b) 177 { 178 int ret; 179 180 ret=(a->type - b->type); 181 if (ret) return(ret); 182 switch (a->type) 183 { 184 case X509_LU_X509: 185 ret=X509_subject_name_cmp(a->data.x509,b->data.x509); 186 break; 187 case X509_LU_CRL: 188 ret=X509_CRL_cmp(a->data.crl,b->data.crl); 189 break; 190 default: 191 abort(); 192 } 193 return(ret); 194 } 195 196X509_STORE *X509_STORE_new(void) 197 { 198 X509_STORE *ret; 199 200 if ((ret=(X509_STORE *)Malloc(sizeof(X509_STORE))) == NULL) 201 return(NULL); 202 ret->certs=lh_new(x509_object_hash,x509_object_cmp); 203 ret->cache=1; 204 ret->get_cert_methods=sk_X509_LOOKUP_new_null(); 205 ret->verify=NULL; 206 ret->verify_cb=NULL; 207 memset(&ret->ex_data,0,sizeof(CRYPTO_EX_DATA)); 208 ret->references=1; 209 ret->depth=0; 210 return(ret); 211 } 212 213static void cleanup(X509_OBJECT *a) 214 { 215 if (a->type == X509_LU_X509) 216 { 217 X509_free(a->data.x509); 218 } 219 else if (a->type == X509_LU_CRL) 220 { 221 X509_CRL_free(a->data.crl); 222 } 223 else 224 abort(); 225 226 Free(a); 227 } 228 229void X509_STORE_free(X509_STORE *vfy) 230 { 231 int i; 232 STACK_OF(X509_LOOKUP) *sk; 233 X509_LOOKUP *lu; 234 235 if(vfy == NULL) 236 return; 237 238 sk=vfy->get_cert_methods; 239 for (i=0; i<sk_X509_LOOKUP_num(sk); i++) 240 { 241 lu=sk_X509_LOOKUP_value(sk,i); 242 X509_LOOKUP_shutdown(lu); 243 X509_LOOKUP_free(lu); 244 } 245 sk_X509_LOOKUP_free(sk); 246 247 CRYPTO_free_ex_data(x509_store_meth,vfy,&vfy->ex_data); 248 lh_doall(vfy->certs,cleanup); 249 lh_free(vfy->certs); 250 Free(vfy); 251 } 252 253X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) 254 { 255 int i; 256 STACK_OF(X509_LOOKUP) *sk; 257 X509_LOOKUP *lu; 258 259 sk=v->get_cert_methods; 260 for (i=0; i<sk_X509_LOOKUP_num(sk); i++) 261 { 262 lu=sk_X509_LOOKUP_value(sk,i); 263 if (m == lu->method) 264 { 265 return(lu); 266 } 267 } 268 /* a new one */ 269 lu=X509_LOOKUP_new(m); 270 if (lu == NULL) 271 return(NULL); 272 else 273 { 274 lu->store_ctx=v; 275 if (sk_X509_LOOKUP_push(v->get_cert_methods,lu)) 276 return(lu); 277 else 278 { 279 X509_LOOKUP_free(lu); 280 return(NULL); 281 } 282 } 283 } 284 285int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name, 286 X509_OBJECT *ret) 287 { 288 X509_STORE *ctx=vs->ctx; 289 X509_LOOKUP *lu; 290 X509_OBJECT stmp,*tmp; 291 int i,j; 292 293 tmp=X509_OBJECT_retrieve_by_subject(ctx->certs,type,name); 294 295 if (tmp == NULL) 296 { 297 for (i=vs->current_method; i<sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) 298 { 299 lu=sk_X509_LOOKUP_value(ctx->get_cert_methods,i); 300 j=X509_LOOKUP_by_subject(lu,type,name,&stmp); 301 if (j < 0) 302 { 303 vs->current_method=j; 304 return(j); 305 } 306 else if (j) 307 { 308 tmp= &stmp; 309 break; 310 } 311 } 312 vs->current_method=0; 313 if (tmp == NULL) 314 return(0); 315 } 316 317/* if (ret->data.ptr != NULL) 318 X509_OBJECT_free_contents(ret); */ 319 320 ret->type=tmp->type; 321 ret->data.ptr=tmp->data.ptr; 322 323 X509_OBJECT_up_ref_count(ret); 324 325 return(1); 326 } 327 328void X509_OBJECT_up_ref_count(X509_OBJECT *a) 329 { 330 switch (a->type) 331 { 332 case X509_LU_X509: 333 CRYPTO_add(&a->data.x509->references,1,CRYPTO_LOCK_X509); 334 break; 335 case X509_LU_CRL: 336 CRYPTO_add(&a->data.crl->references,1,CRYPTO_LOCK_X509_CRL); 337 break; 338 } 339 } 340 341void X509_OBJECT_free_contents(X509_OBJECT *a) 342 { 343 switch (a->type) 344 { 345 case X509_LU_X509: 346 X509_free(a->data.x509); 347 break; 348 case X509_LU_CRL: 349 X509_CRL_free(a->data.crl); 350 break; 351 } 352 } 353 354X509_OBJECT *X509_OBJECT_retrieve_by_subject(LHASH *h, int type, 355 X509_NAME *name) 356 { 357 X509_OBJECT stmp,*tmp; 358 X509 x509_s; 359 X509_CINF cinf_s; 360 X509_CRL crl_s; 361 X509_CRL_INFO crl_info_s; 362 363 stmp.type=type; 364 switch (type) 365 { 366 case X509_LU_X509: 367 stmp.data.x509= &x509_s; 368 x509_s.cert_info= &cinf_s; 369 cinf_s.subject=name; 370 break; 371 case X509_LU_CRL: 372 stmp.data.crl= &crl_s; 373 crl_s.crl= &crl_info_s; 374 crl_info_s.issuer=name; 375 break; 376 default: 377 abort(); 378 } 379 380 tmp=(X509_OBJECT *)lh_retrieve(h,&stmp); 381 return(tmp); 382 } 383 384X509_STORE_CTX *X509_STORE_CTX_new(void) 385{ 386 X509_STORE_CTX *ctx; 387 ctx = (X509_STORE_CTX *)Malloc(sizeof(X509_STORE_CTX)); 388 if(ctx) memset(ctx, 0, sizeof(X509_STORE_CTX)); 389 return ctx; 390} 391 392void X509_STORE_CTX_free(X509_STORE_CTX *ctx) 393{ 394 X509_STORE_CTX_cleanup(ctx); 395 Free(ctx); 396} 397 398void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, 399 STACK_OF(X509) *chain) 400 { 401 ctx->ctx=store; 402 ctx->current_method=0; 403 ctx->cert=x509; 404 ctx->untrusted=chain; 405 ctx->last_untrusted=0; 406 ctx->purpose=0; 407 ctx->trust=0; 408 ctx->valid=0; 409 ctx->chain=NULL; 410 ctx->depth=9; 411 ctx->error=0; 412 ctx->current_cert=NULL; 413 memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); 414 } 415 416void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) 417 { 418 if (ctx->chain != NULL) 419 { 420 sk_X509_pop_free(ctx->chain,X509_free); 421 ctx->chain=NULL; 422 } 423 CRYPTO_free_ex_data(x509_store_ctx_meth,ctx,&(ctx->ex_data)); 424 memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA)); 425 } 426 427IMPLEMENT_STACK_OF(X509_LOOKUP) 428