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