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