1 /* $OpenBSD: x509_lu.c,v 1.55 2022/01/14 07:53:45 tb Exp $ */
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 <string.h>
61
62 #include <openssl/err.h>
63 #include <openssl/lhash.h>
64 #include <openssl/x509.h>
65 #include <openssl/x509v3.h>
66 #include "x509_lcl.h"
67
68 X509_LOOKUP *
X509_LOOKUP_new(X509_LOOKUP_METHOD * method)69 X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
70 {
71 X509_LOOKUP *lu;
72
73 if ((lu = calloc(1, sizeof(*lu))) == NULL) {
74 X509error(ERR_R_MALLOC_FAILURE);
75 return NULL;
76 }
77
78 lu->method = method;
79
80 if (method->new_item != NULL && !method->new_item(lu)) {
81 free(lu);
82 return NULL;
83 }
84
85 return lu;
86 }
87
88 void
X509_LOOKUP_free(X509_LOOKUP * ctx)89 X509_LOOKUP_free(X509_LOOKUP *ctx)
90 {
91 if (ctx == NULL)
92 return;
93 if (ctx->method != NULL && ctx->method->free != NULL)
94 ctx->method->free(ctx);
95 free(ctx);
96 }
97
98 int
X509_LOOKUP_init(X509_LOOKUP * ctx)99 X509_LOOKUP_init(X509_LOOKUP *ctx)
100 {
101 if (ctx->method == NULL)
102 return 0;
103 if (ctx->method->init == NULL)
104 return 1;
105 return ctx->method->init(ctx);
106 }
107
108 int
X509_LOOKUP_shutdown(X509_LOOKUP * ctx)109 X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
110 {
111 if (ctx->method == NULL)
112 return 0;
113 if (ctx->method->shutdown == NULL)
114 return 1;
115 return ctx->method->shutdown(ctx);
116 }
117
118 int
X509_LOOKUP_ctrl(X509_LOOKUP * ctx,int cmd,const char * argc,long argl,char ** ret)119 X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
120 char **ret)
121 {
122 if (ctx->method == NULL)
123 return -1;
124 if (ctx->method->ctrl == NULL)
125 return 1;
126 return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
127 }
128
129 int
X509_LOOKUP_by_subject(X509_LOOKUP * ctx,X509_LOOKUP_TYPE type,X509_NAME * name,X509_OBJECT * ret)130 X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, X509_NAME *name,
131 X509_OBJECT *ret)
132 {
133 if (ctx->method == NULL || ctx->method->get_by_subject == NULL)
134 return 0;
135 return ctx->method->get_by_subject(ctx, type, name, ret);
136 }
137
138 int
X509_LOOKUP_by_issuer_serial(X509_LOOKUP * ctx,X509_LOOKUP_TYPE type,X509_NAME * name,ASN1_INTEGER * serial,X509_OBJECT * ret)139 X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
140 X509_NAME *name, ASN1_INTEGER *serial, X509_OBJECT *ret)
141 {
142 if (ctx->method == NULL || ctx->method->get_by_issuer_serial == NULL)
143 return 0;
144 return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret);
145 }
146
147 int
X509_LOOKUP_by_fingerprint(X509_LOOKUP * ctx,X509_LOOKUP_TYPE type,const unsigned char * bytes,int len,X509_OBJECT * ret)148 X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
149 const unsigned char *bytes, int len, X509_OBJECT *ret)
150 {
151 if (ctx->method == NULL || ctx->method->get_by_fingerprint == NULL)
152 return 0;
153 return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret);
154 }
155
156 int
X509_LOOKUP_by_alias(X509_LOOKUP * ctx,X509_LOOKUP_TYPE type,const char * str,int len,X509_OBJECT * ret)157 X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, const char *str,
158 int len, X509_OBJECT *ret)
159 {
160 if (ctx->method == NULL || ctx->method->get_by_alias == NULL)
161 return 0;
162 return ctx->method->get_by_alias(ctx, type, str, len, ret);
163 }
164
165 static int
x509_object_cmp(const X509_OBJECT * const * a,const X509_OBJECT * const * b)166 x509_object_cmp(const X509_OBJECT * const *a, const X509_OBJECT * const *b)
167 {
168 int ret;
169
170 if ((ret = (*a)->type - (*b)->type) != 0)
171 return ret;
172
173 switch ((*a)->type) {
174 case X509_LU_X509:
175 return X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
176 case X509_LU_CRL:
177 return X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
178 }
179 return 0;
180 }
181
182 X509_STORE *
X509_STORE_new(void)183 X509_STORE_new(void)
184 {
185 X509_STORE *store;
186
187 if ((store = calloc(1, sizeof(*store))) == NULL)
188 goto err;
189
190 if ((store->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL)
191 goto err;
192 if ((store->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL)
193 goto err;
194 if ((store->param = X509_VERIFY_PARAM_new()) == NULL)
195 goto err;
196
197 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, store,
198 &store->ex_data))
199 goto err;
200
201 store->references = 1;
202
203 return store;
204
205 err:
206 X509error(ERR_R_MALLOC_FAILURE);
207 X509_STORE_free(store);
208
209 return NULL;
210 }
211
212 X509_OBJECT *
X509_OBJECT_new(void)213 X509_OBJECT_new(void)
214 {
215 X509_OBJECT *obj;
216
217 if ((obj = calloc(1, sizeof(*obj))) == NULL) {
218 X509error(ERR_R_MALLOC_FAILURE);
219 return NULL;
220 }
221
222 obj->type = X509_LU_NONE;
223
224 return obj;
225 }
226
227 void
X509_OBJECT_free(X509_OBJECT * a)228 X509_OBJECT_free(X509_OBJECT *a)
229 {
230 if (a == NULL)
231 return;
232
233 switch (a->type) {
234 case X509_LU_X509:
235 X509_free(a->data.x509);
236 break;
237 case X509_LU_CRL:
238 X509_CRL_free(a->data.crl);
239 break;
240 }
241
242 free(a);
243 }
244
245 void
X509_STORE_free(X509_STORE * store)246 X509_STORE_free(X509_STORE *store)
247 {
248 STACK_OF(X509_LOOKUP) *sk;
249 X509_LOOKUP *lu;
250 int i;
251
252 if (store == NULL)
253 return;
254
255 if (CRYPTO_add(&store->references, -1, CRYPTO_LOCK_X509_STORE) > 0)
256 return;
257
258 sk = store->get_cert_methods;
259 for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
260 lu = sk_X509_LOOKUP_value(sk, i);
261 X509_LOOKUP_shutdown(lu);
262 X509_LOOKUP_free(lu);
263 }
264 sk_X509_LOOKUP_free(sk);
265 sk_X509_OBJECT_pop_free(store->objs, X509_OBJECT_free);
266
267 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, store, &store->ex_data);
268 X509_VERIFY_PARAM_free(store->param);
269 free(store);
270 }
271
272 int
X509_STORE_up_ref(X509_STORE * store)273 X509_STORE_up_ref(X509_STORE *store)
274 {
275 return CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE) > 1;
276 }
277
278 X509_LOOKUP *
X509_STORE_add_lookup(X509_STORE * store,X509_LOOKUP_METHOD * method)279 X509_STORE_add_lookup(X509_STORE *store, X509_LOOKUP_METHOD *method)
280 {
281 STACK_OF(X509_LOOKUP) *sk;
282 X509_LOOKUP *lu;
283 int i;
284
285 sk = store->get_cert_methods;
286 for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
287 lu = sk_X509_LOOKUP_value(sk, i);
288 if (method == lu->method) {
289 return lu;
290 }
291 }
292
293 if ((lu = X509_LOOKUP_new(method)) == NULL)
294 return NULL;
295
296 lu->store_ctx = store;
297 if (sk_X509_LOOKUP_push(store->get_cert_methods, lu) <= 0) {
298 X509error(ERR_R_MALLOC_FAILURE);
299 X509_LOOKUP_free(lu);
300 return NULL;
301 }
302
303 return lu;
304 }
305
306 X509_OBJECT *
X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX * vs,X509_LOOKUP_TYPE type,X509_NAME * name)307 X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
308 X509_NAME *name)
309 {
310 X509_OBJECT *obj;
311
312 if ((obj = X509_OBJECT_new()) == NULL)
313 return NULL;
314 if (!X509_STORE_CTX_get_by_subject(vs, type, name, obj)) {
315 X509_OBJECT_free(obj);
316 return NULL;
317 }
318
319 return obj;
320 }
321
322 int
X509_STORE_CTX_get_by_subject(X509_STORE_CTX * vs,X509_LOOKUP_TYPE type,X509_NAME * name,X509_OBJECT * ret)323 X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
324 X509_NAME *name, X509_OBJECT *ret)
325 {
326 X509_STORE *ctx = vs->store;
327 X509_LOOKUP *lu;
328 X509_OBJECT stmp, *tmp;
329 int i;
330
331 if (ctx == NULL)
332 return 0;
333
334 memset(&stmp, 0, sizeof(stmp));
335
336 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
337 tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
338 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
339
340 if (tmp == NULL || type == X509_LU_CRL) {
341 for (i = 0; i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
342 lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
343 if (X509_LOOKUP_by_subject(lu, type, name, &stmp) != 0) {
344 tmp = &stmp;
345 break;
346 }
347 }
348 if (tmp == NULL)
349 return 0;
350 }
351
352 if (!X509_OBJECT_up_ref_count(tmp))
353 return 0;
354
355 *ret = *tmp;
356
357 return 1;
358 }
359
360 /* Add obj to the store. Takes ownership of obj. */
361 static int
X509_STORE_add_object(X509_STORE * store,X509_OBJECT * obj)362 X509_STORE_add_object(X509_STORE *store, X509_OBJECT *obj)
363 {
364 int ret = 0;
365
366 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
367
368 if (X509_OBJECT_retrieve_match(store->objs, obj) != NULL) {
369 /* Object is already present in the store. That's fine. */
370 ret = 1;
371 goto out;
372 }
373
374 if (sk_X509_OBJECT_push(store->objs, obj) <= 0) {
375 X509error(ERR_R_MALLOC_FAILURE);
376 goto out;
377 }
378
379 obj = NULL;
380 ret = 1;
381
382 out:
383 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
384 X509_OBJECT_free(obj);
385
386 return ret;
387 }
388
389 int
X509_STORE_add_cert(X509_STORE * store,X509 * x)390 X509_STORE_add_cert(X509_STORE *store, X509 *x)
391 {
392 X509_OBJECT *obj;
393
394 if (x == NULL)
395 return 0;
396
397 if ((obj = X509_OBJECT_new()) == NULL)
398 return 0;
399
400 if (!X509_up_ref(x)) {
401 X509_OBJECT_free(obj);
402 return 0;
403 }
404
405 obj->type = X509_LU_X509;
406 obj->data.x509 = x;
407
408 return X509_STORE_add_object(store, obj);
409 }
410
411 int
X509_STORE_add_crl(X509_STORE * store,X509_CRL * x)412 X509_STORE_add_crl(X509_STORE *store, X509_CRL *x)
413 {
414 X509_OBJECT *obj;
415
416 if (x == NULL)
417 return 0;
418
419 if ((obj = X509_OBJECT_new()) == NULL)
420 return 0;
421
422 if (!X509_CRL_up_ref(x)) {
423 X509_OBJECT_free(obj);
424 return 0;
425 }
426
427 obj->type = X509_LU_CRL;
428 obj->data.crl = x;
429
430 return X509_STORE_add_object(store, obj);
431 }
432
433 int
X509_OBJECT_up_ref_count(X509_OBJECT * a)434 X509_OBJECT_up_ref_count(X509_OBJECT *a)
435 {
436 switch (a->type) {
437 case X509_LU_X509:
438 return X509_up_ref(a->data.x509);
439 case X509_LU_CRL:
440 return X509_CRL_up_ref(a->data.crl);
441 }
442 return 1;
443 }
444
445 X509_LOOKUP_TYPE
X509_OBJECT_get_type(const X509_OBJECT * a)446 X509_OBJECT_get_type(const X509_OBJECT *a)
447 {
448 return a->type;
449 }
450
451 static int
x509_object_idx_cnt(STACK_OF (X509_OBJECT)* h,X509_LOOKUP_TYPE type,X509_NAME * name,int * pnmatch)452 x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
453 X509_NAME *name, int *pnmatch)
454 {
455 X509_OBJECT stmp;
456 X509 x509_s;
457 X509_CINF cinf_s;
458 X509_CRL crl_s;
459 X509_CRL_INFO crl_info_s;
460 int idx;
461
462 stmp.type = type;
463 switch (type) {
464 case X509_LU_X509:
465 stmp.data.x509 = &x509_s;
466 x509_s.cert_info = &cinf_s;
467 cinf_s.subject = name;
468 break;
469 case X509_LU_CRL:
470 stmp.data.crl = &crl_s;
471 crl_s.crl = &crl_info_s;
472 crl_info_s.issuer = name;
473 break;
474 default:
475 return -1;
476 }
477
478 idx = sk_X509_OBJECT_find(h, &stmp);
479 if (idx >= 0 && pnmatch) {
480 int tidx;
481 const X509_OBJECT *tobj, *pstmp;
482
483 *pnmatch = 1;
484 pstmp = &stmp;
485 for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) {
486 tobj = sk_X509_OBJECT_value(h, tidx);
487 if (x509_object_cmp(&tobj, &pstmp))
488 break;
489 (*pnmatch)++;
490 }
491 }
492 return idx;
493 }
494
495 int
X509_OBJECT_idx_by_subject(STACK_OF (X509_OBJECT)* h,X509_LOOKUP_TYPE type,X509_NAME * name)496 X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
497 X509_NAME *name)
498 {
499 return x509_object_idx_cnt(h, type, name, NULL);
500 }
501
502 X509_OBJECT *
X509_OBJECT_retrieve_by_subject(STACK_OF (X509_OBJECT)* h,X509_LOOKUP_TYPE type,X509_NAME * name)503 X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
504 X509_NAME *name)
505 {
506 int idx;
507
508 idx = X509_OBJECT_idx_by_subject(h, type, name);
509 if (idx == -1)
510 return NULL;
511 return sk_X509_OBJECT_value(h, idx);
512 }
513
514 X509 *
X509_OBJECT_get0_X509(const X509_OBJECT * xo)515 X509_OBJECT_get0_X509(const X509_OBJECT *xo)
516 {
517 if (xo != NULL && xo->type == X509_LU_X509)
518 return xo->data.x509;
519 return NULL;
520 }
521
522 X509_CRL *
X509_OBJECT_get0_X509_CRL(X509_OBJECT * xo)523 X509_OBJECT_get0_X509_CRL(X509_OBJECT *xo)
524 {
525 if (xo != NULL && xo->type == X509_LU_CRL)
526 return xo->data.crl;
527 return NULL;
528 }
529
STACK_OF(X509)530 static STACK_OF(X509) *
531 X509_get1_certs_from_cache(X509_STORE *store, X509_NAME *name)
532 {
533 STACK_OF(X509) *sk = NULL;
534 X509 *x = NULL;
535 X509_OBJECT *obj;
536 int i, idx, cnt;
537
538 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
539
540 idx = x509_object_idx_cnt(store->objs, X509_LU_X509, name, &cnt);
541 if (idx < 0)
542 goto err;
543
544 if ((sk = sk_X509_new_null()) == NULL)
545 goto err;
546
547 for (i = 0; i < cnt; i++, idx++) {
548 obj = sk_X509_OBJECT_value(store->objs, idx);
549
550 x = obj->data.x509;
551 if (!X509_up_ref(x)) {
552 x = NULL;
553 goto err;
554 }
555 if (!sk_X509_push(sk, x))
556 goto err;
557 }
558
559 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
560
561 return sk;
562
563 err:
564 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
565 sk_X509_pop_free(sk, X509_free);
566 X509_free(x);
567
568 return NULL;
569 }
570
STACK_OF(X509)571 STACK_OF(X509) *
572 X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *name)
573 {
574 X509_STORE *store = ctx->store;
575 STACK_OF(X509) *sk;
576 X509_OBJECT *obj;
577
578 if (store == NULL)
579 return NULL;
580
581 if ((sk = X509_get1_certs_from_cache(store, name)) != NULL)
582 return sk;
583
584 /* Nothing found: do lookup to possibly add new objects to cache. */
585 obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, name);
586 if (obj == NULL)
587 return NULL;
588 X509_OBJECT_free(obj);
589
590 return X509_get1_certs_from_cache(store, name);
591 }
592
STACK_OF(X509_CRL)593 STACK_OF(X509_CRL) *
594 X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *name)
595 {
596 X509_STORE *store = ctx->store;
597 STACK_OF(X509_CRL) *sk = NULL;
598 X509_CRL *x = NULL;
599 X509_OBJECT *obj = NULL;
600 int i, idx, cnt;
601
602 if (store == NULL)
603 return NULL;
604
605 /* Always do lookup to possibly add new CRLs to cache */
606 obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_CRL, name);
607 if (obj == NULL)
608 return NULL;
609
610 X509_OBJECT_free(obj);
611 obj = NULL;
612
613 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
614 idx = x509_object_idx_cnt(store->objs, X509_LU_CRL, name, &cnt);
615 if (idx < 0)
616 goto err;
617
618 if ((sk = sk_X509_CRL_new_null()) == NULL)
619 goto err;
620
621 for (i = 0; i < cnt; i++, idx++) {
622 obj = sk_X509_OBJECT_value(store->objs, idx);
623
624 x = obj->data.crl;
625 if (!X509_CRL_up_ref(x)) {
626 x = NULL;
627 goto err;
628 }
629 if (!sk_X509_CRL_push(sk, x))
630 goto err;
631 }
632
633 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
634 return sk;
635
636 err:
637 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
638 X509_CRL_free(x);
639 sk_X509_CRL_pop_free(sk, X509_CRL_free);
640 return NULL;
641 }
642
643 X509_OBJECT *
X509_OBJECT_retrieve_match(STACK_OF (X509_OBJECT)* h,X509_OBJECT * x)644 X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x)
645 {
646 int idx, i;
647 X509_OBJECT *obj;
648
649 idx = sk_X509_OBJECT_find(h, x);
650 if (idx == -1)
651 return NULL;
652 if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
653 return sk_X509_OBJECT_value(h, idx);
654 for (i = idx; i < sk_X509_OBJECT_num(h); i++) {
655 obj = sk_X509_OBJECT_value(h, i);
656 if (x509_object_cmp((const X509_OBJECT **)&obj,
657 (const X509_OBJECT **)&x))
658 return NULL;
659 if (x->type == X509_LU_X509) {
660 if (!X509_cmp(obj->data.x509, x->data.x509))
661 return obj;
662 } else if (x->type == X509_LU_CRL) {
663 if (!X509_CRL_match(obj->data.crl, x->data.crl))
664 return obj;
665 } else
666 return obj;
667 }
668 return NULL;
669 }
670
671 /* Try to get issuer certificate from store. Due to limitations
672 * of the API this can only retrieve a single certificate matching
673 * a given subject name. However it will fill the cache with all
674 * matching certificates, so we can examine the cache for all
675 * matches.
676 *
677 * Return values are:
678 * 1 lookup successful.
679 * 0 certificate not found.
680 * -1 some other error.
681 */
682 int
X509_STORE_CTX_get1_issuer(X509 ** out_issuer,X509_STORE_CTX * ctx,X509 * x)683 X509_STORE_CTX_get1_issuer(X509 **out_issuer, X509_STORE_CTX *ctx, X509 *x)
684 {
685 X509_NAME *xn;
686 X509_OBJECT *obj, *pobj;
687 X509 *issuer = NULL;
688 int i, idx, ret;
689
690 *out_issuer = NULL;
691
692 xn = X509_get_issuer_name(x);
693 obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, xn);
694 if (obj == NULL)
695 return 0;
696
697 if ((issuer = X509_OBJECT_get0_X509(obj)) == NULL) {
698 X509_OBJECT_free(obj);
699 return 0;
700 }
701 if (!X509_up_ref(issuer)) {
702 X509_OBJECT_free(obj);
703 return -1;
704 }
705
706 /* If certificate matches all OK */
707 if (ctx->check_issued(ctx, x, issuer)) {
708 if (x509_check_cert_time(ctx, issuer, -1)) {
709 *out_issuer = issuer;
710 X509_OBJECT_free(obj);
711 return 1;
712 }
713 }
714 X509_free(issuer);
715 issuer = NULL;
716 X509_OBJECT_free(obj);
717 obj = NULL;
718
719 if (ctx->store == NULL)
720 return 0;
721
722 /* Else find index of first cert accepted by 'check_issued' */
723 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
724 idx = X509_OBJECT_idx_by_subject(ctx->store->objs, X509_LU_X509, xn);
725 if (idx != -1) /* should be true as we've had at least one match */ {
726 /* Look through all matching certs for suitable issuer */
727 for (i = idx; i < sk_X509_OBJECT_num(ctx->store->objs); i++) {
728 pobj = sk_X509_OBJECT_value(ctx->store->objs, i);
729 /* See if we've run past the matches */
730 if (pobj->type != X509_LU_X509)
731 break;
732 if (X509_NAME_cmp(xn,
733 X509_get_subject_name(pobj->data.x509)))
734 break;
735 if (ctx->check_issued(ctx, x, pobj->data.x509)) {
736 issuer = pobj->data.x509;
737 /*
738 * If times check, exit with match,
739 * otherwise keep looking. Leave last
740 * match in issuer so we return nearest
741 * match if no certificate time is OK.
742 */
743 if (x509_check_cert_time(ctx, issuer, -1))
744 break;
745 }
746 }
747 }
748 ret = 0;
749 if (issuer != NULL) {
750 if (!X509_up_ref(issuer)) {
751 ret = -1;
752 } else {
753 *out_issuer = issuer;
754 ret = 1;
755 }
756 }
757 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
758 return ret;
759 }
760
STACK_OF(X509_OBJECT)761 STACK_OF(X509_OBJECT) *
762 X509_STORE_get0_objects(X509_STORE *xs)
763 {
764 return xs->objs;
765 }
766
767 void *
X509_STORE_get_ex_data(X509_STORE * xs,int idx)768 X509_STORE_get_ex_data(X509_STORE *xs, int idx)
769 {
770 return CRYPTO_get_ex_data(&xs->ex_data, idx);
771 }
772
773 int
X509_STORE_set_ex_data(X509_STORE * xs,int idx,void * data)774 X509_STORE_set_ex_data(X509_STORE *xs, int idx, void *data)
775 {
776 return CRYPTO_set_ex_data(&xs->ex_data, idx, data);
777 }
778
779 int
X509_STORE_set_flags(X509_STORE * ctx,unsigned long flags)780 X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
781 {
782 return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
783 }
784
785 int
X509_STORE_set_depth(X509_STORE * ctx,int depth)786 X509_STORE_set_depth(X509_STORE *ctx, int depth)
787 {
788 X509_VERIFY_PARAM_set_depth(ctx->param, depth);
789 return 1;
790 }
791
792 int
X509_STORE_set_purpose(X509_STORE * ctx,int purpose)793 X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
794 {
795 return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
796 }
797
798 int
X509_STORE_set_trust(X509_STORE * ctx,int trust)799 X509_STORE_set_trust(X509_STORE *ctx, int trust)
800 {
801 return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
802 }
803
804 int
X509_STORE_set1_param(X509_STORE * ctx,X509_VERIFY_PARAM * param)805 X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
806 {
807 return X509_VERIFY_PARAM_set1(ctx->param, param);
808 }
809
810 X509_VERIFY_PARAM *
X509_STORE_get0_param(X509_STORE * ctx)811 X509_STORE_get0_param(X509_STORE *ctx)
812 {
813 return ctx->param;
814 }
815
816 void
X509_STORE_set_verify(X509_STORE * store,X509_STORE_CTX_verify_fn verify)817 X509_STORE_set_verify(X509_STORE *store, X509_STORE_CTX_verify_fn verify)
818 {
819 store->verify = verify;
820 }
821
822 X509_STORE_CTX_verify_fn
X509_STORE_get_verify(X509_STORE * store)823 X509_STORE_get_verify(X509_STORE *store)
824 {
825 return store->verify;
826 }
827
828 void
X509_STORE_set_verify_cb(X509_STORE * store,X509_STORE_CTX_verify_cb verify_cb)829 X509_STORE_set_verify_cb(X509_STORE *store, X509_STORE_CTX_verify_cb verify_cb)
830 {
831 store->verify_cb = verify_cb;
832 }
833
834 X509_STORE_CTX_verify_cb
X509_STORE_get_verify_cb(X509_STORE * store)835 X509_STORE_get_verify_cb(X509_STORE *store)
836 {
837 return store->verify_cb;
838 }
839