c4ca619d8c46c2378b68ca7e74405c86ca5eae28
[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 int X509_OBJECT_get_type(X509_OBJECT *a)
440 {
441     return a->type;
442 }
443
444 void X509_OBJECT_free(X509_OBJECT *a)
445 {
446     if (a == NULL)
447         return;
448     X509_OBJECT_free_contents(a);
449     OPENSSL_free(a);
450 }
451
452 void X509_OBJECT_free_contents(X509_OBJECT *a)
453 {
454     if (a == NULL)
455         return;
456     switch (a->type) {
457     default:
458         break;
459     case X509_LU_X509:
460         X509_free(a->data.x509);
461         break;
462     case X509_LU_CRL:
463         X509_CRL_free(a->data.crl);
464         break;
465     }
466 }
467
468 static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
469                                X509_NAME *name, int *pnmatch)
470 {
471     X509_OBJECT stmp;
472     X509 x509_s;
473     X509_CRL crl_s;
474     int idx;
475
476     stmp.type = type;
477     switch (type) {
478     case X509_LU_X509:
479         stmp.data.x509 = &x509_s;
480         x509_s.cert_info.subject = name;
481         break;
482     case X509_LU_CRL:
483         stmp.data.crl = &crl_s;
484         crl_s.crl.issuer = name;
485         break;
486     default:
487         /* abort(); */
488         return -1;
489     }
490
491     idx = sk_X509_OBJECT_find(h, &stmp);
492     if (idx >= 0 && pnmatch) {
493         int tidx;
494         const X509_OBJECT *tobj, *pstmp;
495         *pnmatch = 1;
496         pstmp = &stmp;
497         for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) {
498             tobj = sk_X509_OBJECT_value(h, tidx);
499             if (x509_object_cmp(&tobj, &pstmp))
500                 break;
501             (*pnmatch)++;
502         }
503     }
504     return idx;
505 }
506
507 int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
508                                X509_NAME *name)
509 {
510     return x509_object_idx_cnt(h, type, name, NULL);
511 }
512
513 X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
514                                              int type, X509_NAME *name)
515 {
516     int idx;
517     idx = X509_OBJECT_idx_by_subject(h, type, name);
518     if (idx == -1)
519         return NULL;
520     return sk_X509_OBJECT_value(h, idx);
521 }
522
523 STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v)
524 {
525     return v->objs;
526 }
527
528 STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
529 {
530     int i, idx, cnt;
531     STACK_OF(X509) *sk;
532     X509 *x;
533     X509_OBJECT *obj;
534     sk = sk_X509_new_null();
535     CRYPTO_THREAD_write_lock(ctx->ctx->lock);
536     idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
537     if (idx < 0) {
538         /*
539          * Nothing found in cache: do lookup to possibly add new objects to
540          * cache
541          */
542         X509_OBJECT xobj;
543         CRYPTO_THREAD_unlock(ctx->ctx->lock);
544         if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
545             sk_X509_free(sk);
546             return NULL;
547         }
548         X509_OBJECT_free_contents(&xobj);
549         CRYPTO_THREAD_write_lock(ctx->ctx->lock);
550         idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
551         if (idx < 0) {
552             CRYPTO_THREAD_unlock(ctx->ctx->lock);
553             sk_X509_free(sk);
554             return NULL;
555         }
556     }
557     for (i = 0; i < cnt; i++, idx++) {
558         obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
559         x = obj->data.x509;
560         X509_up_ref(x);
561         if (!sk_X509_push(sk, x)) {
562             CRYPTO_THREAD_unlock(ctx->ctx->lock);
563             X509_free(x);
564             sk_X509_pop_free(sk, X509_free);
565             return NULL;
566         }
567     }
568     CRYPTO_THREAD_unlock(ctx->ctx->lock);
569     return sk;
570
571 }
572
573 STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
574 {
575     int i, idx, cnt;
576     STACK_OF(X509_CRL) *sk;
577     X509_CRL *x;
578     X509_OBJECT *obj, xobj;
579     sk = sk_X509_CRL_new_null();
580
581     /*
582      * Always do lookup to possibly add new CRLs to cache
583      */
584     if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) {
585         sk_X509_CRL_free(sk);
586         return NULL;
587     }
588     X509_OBJECT_free_contents(&xobj);
589     CRYPTO_THREAD_write_lock(ctx->ctx->lock);
590     idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
591     if (idx < 0) {
592         CRYPTO_THREAD_unlock(ctx->ctx->lock);
593         sk_X509_CRL_free(sk);
594         return NULL;
595     }
596
597     for (i = 0; i < cnt; i++, idx++) {
598         obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
599         x = obj->data.crl;
600         X509_CRL_up_ref(x);
601         if (!sk_X509_CRL_push(sk, x)) {
602             CRYPTO_THREAD_unlock(ctx->ctx->lock);
603             X509_CRL_free(x);
604             sk_X509_CRL_pop_free(sk, X509_CRL_free);
605             return NULL;
606         }
607     }
608     CRYPTO_THREAD_unlock(ctx->ctx->lock);
609     return sk;
610 }
611
612 X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
613                                         X509_OBJECT *x)
614 {
615     int idx, i;
616     X509_OBJECT *obj;
617     idx = sk_X509_OBJECT_find(h, x);
618     if (idx == -1)
619         return NULL;
620     if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
621         return sk_X509_OBJECT_value(h, idx);
622     for (i = idx; i < sk_X509_OBJECT_num(h); i++) {
623         obj = sk_X509_OBJECT_value(h, i);
624         if (x509_object_cmp
625             ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
626             return NULL;
627         if (x->type == X509_LU_X509) {
628             if (!X509_cmp(obj->data.x509, x->data.x509))
629                 return obj;
630         } else if (x->type == X509_LU_CRL) {
631             if (!X509_CRL_match(obj->data.crl, x->data.crl))
632                 return obj;
633         } else
634             return obj;
635     }
636     return NULL;
637 }
638
639 /*-
640  * Try to get issuer certificate from store. Due to limitations
641  * of the API this can only retrieve a single certificate matching
642  * a given subject name. However it will fill the cache with all
643  * matching certificates, so we can examine the cache for all
644  * matches.
645  *
646  * Return values are:
647  *  1 lookup successful.
648  *  0 certificate not found.
649  * -1 some other error.
650  */
651 int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
652 {
653     X509_NAME *xn;
654     X509_OBJECT obj, *pobj;
655     int i, ok, idx, ret;
656
657     *issuer = NULL;
658     xn = X509_get_issuer_name(x);
659     ok = X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj);
660     if (ok != X509_LU_X509) {
661         if (ok == X509_LU_RETRY) {
662             X509_OBJECT_free_contents(&obj);
663             X509err(X509_F_X509_STORE_CTX_GET1_ISSUER, X509_R_SHOULD_RETRY);
664             return -1;
665         } else if (ok != X509_LU_FAIL) {
666             X509_OBJECT_free_contents(&obj);
667             /* not good :-(, break anyway */
668             return -1;
669         }
670         return 0;
671     }
672     /* If certificate matches all OK */
673     if (ctx->check_issued(ctx, x, obj.data.x509)) {
674         if (x509_check_cert_time(ctx, obj.data.x509, -1)) {
675             *issuer = obj.data.x509;
676             return 1;
677         }
678     }
679     X509_OBJECT_free_contents(&obj);
680
681     /* Else find index of first cert accepted by 'check_issued' */
682     ret = 0;
683     CRYPTO_THREAD_write_lock(ctx->ctx->lock);
684     idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
685     if (idx != -1) {            /* should be true as we've had at least one
686                                  * match */
687         /* Look through all matching certs for suitable issuer */
688         for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) {
689             pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
690             /* See if we've run past the matches */
691             if (pobj->type != X509_LU_X509)
692                 break;
693             if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
694                 break;
695             if (ctx->check_issued(ctx, x, pobj->data.x509)) {
696                 *issuer = pobj->data.x509;
697                 ret = 1;
698                 /*
699                  * If times check, exit with match,
700                  * otherwise keep looking. Leave last
701                  * match in issuer so we return nearest
702                  * match if no certificate time is OK.
703                  */
704
705                 if (x509_check_cert_time(ctx, *issuer, -1))
706                     break;
707             }
708         }
709     }
710     CRYPTO_THREAD_unlock(ctx->ctx->lock);
711     if (*issuer)
712         X509_up_ref(*issuer);
713     return ret;
714 }
715
716 int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
717 {
718     return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
719 }
720
721 int X509_STORE_set_depth(X509_STORE *ctx, int depth)
722 {
723     X509_VERIFY_PARAM_set_depth(ctx->param, depth);
724     return 1;
725 }
726
727 int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
728 {
729     return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
730 }
731
732 int X509_STORE_set_trust(X509_STORE *ctx, int trust)
733 {
734     return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
735 }
736
737 int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
738 {
739     return X509_VERIFY_PARAM_set1(ctx->param, param);
740 }
741
742 X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx)
743 {
744     return ctx->param;
745 }
746
747 void X509_STORE_set_verify_cb(X509_STORE *ctx,
748                               int (*verify_cb) (int, X509_STORE_CTX *))
749 {
750     ctx->verify_cb = verify_cb;
751 }
752
753 void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify verify)
754 {
755     ctx->verify = verify;
756 }
757
758 void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx,
759                                    STACK_OF(X509_CRL) *(*cb) (X509_STORE_CTX
760                                                               *ctx,
761                                                               X509_NAME *nm))
762 {
763     ctx->lookup_crls = cb;
764 }
765
766 int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data)
767 {
768     return CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
769 }
770
771 void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx)
772 {
773     return CRYPTO_get_ex_data(&ctx->ex_data, idx);
774 }
775
776 X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
777 {
778     return ctx->ctx;
779 }