]>
Commit | Line | Data |
---|---|---|
b1322259 RS |
1 | /* |
2 | * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. | |
d02b48c6 | 3 | * |
b1322259 RS |
4 | * Licensed under the OpenSSL license (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
d02b48c6 RE |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
b39fc560 | 11 | #include "internal/cryptlib.h" |
ec577822 BM |
12 | #include <openssl/lhash.h> |
13 | #include <openssl/x509.h> | |
e3e57192 | 14 | #include "internal/x509_int.h" |
926a56bf | 15 | #include <openssl/x509v3.h> |
0930251d | 16 | #include "x509_lcl.h" |
d02b48c6 | 17 | |
6b691a5c | 18 | X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method) |
0f113f3e MC |
19 | { |
20 | X509_LOOKUP *ret; | |
21 | ||
64b25758 | 22 | ret = OPENSSL_zalloc(sizeof(*ret)); |
0f113f3e MC |
23 | if (ret == NULL) |
24 | return NULL; | |
25 | ||
0f113f3e | 26 | ret->method = method; |
0f113f3e MC |
27 | if ((method->new_item != NULL) && !method->new_item(ret)) { |
28 | OPENSSL_free(ret); | |
29 | return NULL; | |
30 | } | |
31 | return ret; | |
32 | } | |
d02b48c6 | 33 | |
6b691a5c | 34 | void X509_LOOKUP_free(X509_LOOKUP *ctx) |
0f113f3e MC |
35 | { |
36 | if (ctx == NULL) | |
37 | return; | |
38 | if ((ctx->method != NULL) && (ctx->method->free != NULL)) | |
39 | (*ctx->method->free) (ctx); | |
40 | OPENSSL_free(ctx); | |
41 | } | |
d02b48c6 | 42 | |
3067095e RL |
43 | int X509_STORE_lock(X509_STORE *s) |
44 | { | |
45 | return CRYPTO_THREAD_write_lock(s->lock); | |
46 | } | |
47 | ||
48 | int X509_STORE_unlock(X509_STORE *s) | |
49 | { | |
50 | return CRYPTO_THREAD_unlock(s->lock); | |
51 | } | |
52 | ||
6b691a5c | 53 | int X509_LOOKUP_init(X509_LOOKUP *ctx) |
0f113f3e MC |
54 | { |
55 | if (ctx->method == NULL) | |
56 | return 0; | |
57 | if (ctx->method->init != NULL) | |
58 | return ctx->method->init(ctx); | |
59 | else | |
60 | return 1; | |
61 | } | |
d02b48c6 | 62 | |
6b691a5c | 63 | int X509_LOOKUP_shutdown(X509_LOOKUP *ctx) |
0f113f3e MC |
64 | { |
65 | if (ctx->method == NULL) | |
66 | return 0; | |
67 | if (ctx->method->shutdown != NULL) | |
68 | return ctx->method->shutdown(ctx); | |
69 | else | |
70 | return 1; | |
71 | } | |
d02b48c6 | 72 | |
303c0028 | 73 | int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, |
0f113f3e MC |
74 | char **ret) |
75 | { | |
76 | if (ctx->method == NULL) | |
77 | return -1; | |
78 | if (ctx->method->ctrl != NULL) | |
79 | return ctx->method->ctrl(ctx, cmd, argc, argl, ret); | |
80 | else | |
81 | return 1; | |
82 | } | |
d02b48c6 | 83 | |
0946a198 DSH |
84 | int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, |
85 | X509_NAME *name, X509_OBJECT *ret) | |
0f113f3e MC |
86 | { |
87 | if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL)) | |
ba1a1c37 | 88 | return 0; |
0f113f3e MC |
89 | if (ctx->skip) |
90 | return 0; | |
91 | return ctx->method->get_by_subject(ctx, type, name, ret); | |
92 | } | |
d02b48c6 | 93 | |
0946a198 DSH |
94 | int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, |
95 | X509_NAME *name, ASN1_INTEGER *serial, | |
96 | X509_OBJECT *ret) | |
0f113f3e MC |
97 | { |
98 | if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL)) | |
ba1a1c37 | 99 | return 0; |
0f113f3e MC |
100 | return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret); |
101 | } | |
d02b48c6 | 102 | |
0946a198 | 103 | int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, |
0f113f3e MC |
104 | unsigned char *bytes, int len, |
105 | X509_OBJECT *ret) | |
106 | { | |
107 | if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL)) | |
ba1a1c37 | 108 | return 0; |
0f113f3e MC |
109 | return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret); |
110 | } | |
d02b48c6 | 111 | |
0946a198 DSH |
112 | int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, |
113 | char *str, int len, X509_OBJECT *ret) | |
0f113f3e MC |
114 | { |
115 | if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL)) | |
ba1a1c37 | 116 | return 0; |
0f113f3e MC |
117 | return ctx->method->get_by_alias(ctx, type, str, len, ret); |
118 | } | |
119 | ||
120 | static int x509_object_cmp(const X509_OBJECT *const *a, | |
121 | const X509_OBJECT *const *b) | |
122 | { | |
123 | int ret; | |
124 | ||
125 | ret = ((*a)->type - (*b)->type); | |
126 | if (ret) | |
127 | return ret; | |
128 | switch ((*a)->type) { | |
129 | case X509_LU_X509: | |
130 | ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509); | |
131 | break; | |
132 | case X509_LU_CRL: | |
133 | ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl); | |
134 | break; | |
135 | default: | |
136 | /* abort(); */ | |
137 | return 0; | |
138 | } | |
139 | return ret; | |
140 | } | |
d02b48c6 | 141 | |
6b691a5c | 142 | X509_STORE *X509_STORE_new(void) |
0f113f3e MC |
143 | { |
144 | X509_STORE *ret; | |
145 | ||
64b25758 | 146 | if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) |
0f113f3e | 147 | return NULL; |
90945fa3 MC |
148 | if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) |
149 | goto err; | |
0f113f3e | 150 | ret->cache = 1; |
90945fa3 MC |
151 | if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) |
152 | goto err; | |
0f113f3e MC |
153 | |
154 | if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) | |
90945fa3 | 155 | goto err; |
0f113f3e | 156 | |
90945fa3 MC |
157 | if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) |
158 | goto err; | |
0f113f3e | 159 | |
c001ce33 AG |
160 | ret->lock = CRYPTO_THREAD_lock_new(); |
161 | if (ret->lock == NULL) | |
162 | goto err; | |
163 | ||
0f113f3e MC |
164 | ret->references = 1; |
165 | return ret; | |
c001ce33 | 166 | |
90945fa3 MC |
167 | err: |
168 | X509_VERIFY_PARAM_free(ret->param); | |
169 | sk_X509_OBJECT_free(ret->objs); | |
170 | sk_X509_LOOKUP_free(ret->get_cert_methods); | |
171 | OPENSSL_free(ret); | |
172 | return NULL; | |
0f113f3e | 173 | } |
d02b48c6 | 174 | |
6b691a5c | 175 | static void cleanup(X509_OBJECT *a) |
0f113f3e | 176 | { |
222561fe RS |
177 | if (!a) |
178 | return; | |
0f113f3e MC |
179 | if (a->type == X509_LU_X509) { |
180 | X509_free(a->data.x509); | |
181 | } else if (a->type == X509_LU_CRL) { | |
182 | X509_CRL_free(a->data.crl); | |
183 | } else { | |
184 | /* abort(); */ | |
185 | } | |
186 | ||
187 | OPENSSL_free(a); | |
188 | } | |
d02b48c6 | 189 | |
6b691a5c | 190 | void X509_STORE_free(X509_STORE *vfy) |
0f113f3e MC |
191 | { |
192 | int i; | |
193 | STACK_OF(X509_LOOKUP) *sk; | |
194 | X509_LOOKUP *lu; | |
d02b48c6 | 195 | |
0f113f3e MC |
196 | if (vfy == NULL) |
197 | return; | |
e03ddfae | 198 | |
c001ce33 | 199 | CRYPTO_atomic_add(&vfy->references, -1, &i, vfy->lock); |
f3f1cf84 | 200 | REF_PRINT_COUNT("X509_STORE", vfy); |
0f113f3e MC |
201 | if (i > 0) |
202 | return; | |
f3f1cf84 | 203 | REF_ASSERT_ISNT(i < 0); |
bff9ce4d | 204 | |
0f113f3e MC |
205 | sk = vfy->get_cert_methods; |
206 | for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { | |
207 | lu = sk_X509_LOOKUP_value(sk, i); | |
208 | X509_LOOKUP_shutdown(lu); | |
209 | X509_LOOKUP_free(lu); | |
210 | } | |
211 | sk_X509_LOOKUP_free(sk); | |
212 | sk_X509_OBJECT_pop_free(vfy->objs, cleanup); | |
213 | ||
214 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data); | |
222561fe | 215 | X509_VERIFY_PARAM_free(vfy->param); |
c001ce33 | 216 | CRYPTO_THREAD_lock_free(vfy->lock); |
0f113f3e MC |
217 | OPENSSL_free(vfy); |
218 | } | |
d02b48c6 | 219 | |
c001ce33 AG |
220 | int X509_STORE_up_ref(X509_STORE *vfy) |
221 | { | |
222 | int i; | |
223 | ||
224 | if (CRYPTO_atomic_add(&vfy->references, 1, &i, vfy->lock) <= 0) | |
225 | return 0; | |
226 | ||
227 | REF_PRINT_COUNT("X509_STORE", a); | |
228 | REF_ASSERT_ISNT(i < 2); | |
229 | return ((i > 1) ? 1 : 0); | |
230 | } | |
231 | ||
6b691a5c | 232 | X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) |
0f113f3e MC |
233 | { |
234 | int i; | |
235 | STACK_OF(X509_LOOKUP) *sk; | |
236 | X509_LOOKUP *lu; | |
237 | ||
238 | sk = v->get_cert_methods; | |
239 | for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { | |
240 | lu = sk_X509_LOOKUP_value(sk, i); | |
241 | if (m == lu->method) { | |
242 | return lu; | |
243 | } | |
244 | } | |
245 | /* a new one */ | |
246 | lu = X509_LOOKUP_new(m); | |
247 | if (lu == NULL) | |
248 | return NULL; | |
249 | else { | |
250 | lu->store_ctx = v; | |
251 | if (sk_X509_LOOKUP_push(v->get_cert_methods, lu)) | |
252 | return lu; | |
253 | else { | |
254 | X509_LOOKUP_free(lu); | |
255 | return NULL; | |
256 | } | |
257 | } | |
258 | } | |
d02b48c6 | 259 | |
0946a198 DSH |
260 | X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, |
261 | X509_LOOKUP_TYPE type, | |
6ddbb4cd | 262 | X509_NAME *name) |
f0e0fd51 | 263 | { |
6ddbb4cd | 264 | X509_OBJECT *ret = X509_OBJECT_new(); |
f0e0fd51 | 265 | |
6ddbb4cd | 266 | if (ret == NULL) |
f0e0fd51 | 267 | return NULL; |
6ddbb4cd RS |
268 | if (!X509_STORE_CTX_get_by_subject(vs, type, name, ret)) { |
269 | X509_OBJECT_free(ret); | |
f0e0fd51 RS |
270 | return NULL; |
271 | } | |
272 | return ret; | |
273 | } | |
274 | ||
6ddbb4cd RS |
275 | int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, |
276 | X509_NAME *name, X509_OBJECT *ret) | |
0f113f3e MC |
277 | { |
278 | X509_STORE *ctx = vs->ctx; | |
279 | X509_LOOKUP *lu; | |
280 | X509_OBJECT stmp, *tmp; | |
281 | int i, j; | |
282 | ||
c001ce33 | 283 | CRYPTO_THREAD_write_lock(ctx->lock); |
0f113f3e | 284 | tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name); |
c001ce33 | 285 | CRYPTO_THREAD_unlock(ctx->lock); |
0f113f3e MC |
286 | |
287 | if (tmp == NULL || type == X509_LU_CRL) { | |
fc9d1ef3 | 288 | for (i = 0; i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { |
0f113f3e MC |
289 | lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i); |
290 | j = X509_LOOKUP_by_subject(lu, type, name, &stmp); | |
fc9d1ef3 | 291 | if (j) { |
0f113f3e MC |
292 | tmp = &stmp; |
293 | break; | |
294 | } | |
295 | } | |
0f113f3e MC |
296 | if (tmp == NULL) |
297 | return 0; | |
298 | } | |
299 | ||
0f113f3e MC |
300 | ret->type = tmp->type; |
301 | ret->data.ptr = tmp->data.ptr; | |
302 | ||
303 | X509_OBJECT_up_ref_count(ret); | |
304 | ||
305 | return 1; | |
306 | } | |
d02b48c6 | 307 | |
2f043896 | 308 | int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) |
0f113f3e MC |
309 | { |
310 | X509_OBJECT *obj; | |
68efafc5 | 311 | int ret = 1, added = 1; |
0f113f3e MC |
312 | |
313 | if (x == NULL) | |
314 | return 0; | |
6ddbb4cd RS |
315 | obj = X509_OBJECT_new(); |
316 | if (obj == NULL) | |
0f113f3e | 317 | return 0; |
0f113f3e MC |
318 | obj->type = X509_LU_X509; |
319 | obj->data.x509 = x; | |
68efafc5 | 320 | X509_OBJECT_up_ref_count(obj); |
0f113f3e | 321 | |
c001ce33 | 322 | CRYPTO_THREAD_write_lock(ctx->lock); |
0f113f3e | 323 | |
0f113f3e | 324 | if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { |
0f113f3e MC |
325 | X509err(X509_F_X509_STORE_ADD_CERT, |
326 | X509_R_CERT_ALREADY_IN_HASH_TABLE); | |
327 | ret = 0; | |
68efafc5 F |
328 | } else { |
329 | added = sk_X509_OBJECT_push(ctx->objs, obj); | |
330 | ret = added != 0; | |
331 | } | |
0f113f3e | 332 | |
c001ce33 | 333 | CRYPTO_THREAD_unlock(ctx->lock); |
0f113f3e | 334 | |
68efafc5 F |
335 | if (!ret) /* obj not pushed */ |
336 | X509_OBJECT_free(obj); | |
337 | if (!added) /* on push failure */ | |
338 | X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE); | |
339 | ||
0f113f3e MC |
340 | return ret; |
341 | } | |
2f043896 DSH |
342 | |
343 | int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) | |
0f113f3e MC |
344 | { |
345 | X509_OBJECT *obj; | |
68efafc5 | 346 | int ret = 1, added = 1; |
0f113f3e MC |
347 | |
348 | if (x == NULL) | |
349 | return 0; | |
6ddbb4cd RS |
350 | obj = X509_OBJECT_new(); |
351 | if (obj == NULL) | |
0f113f3e | 352 | return 0; |
0f113f3e MC |
353 | obj->type = X509_LU_CRL; |
354 | obj->data.crl = x; | |
68efafc5 | 355 | X509_OBJECT_up_ref_count(obj); |
0f113f3e | 356 | |
c001ce33 | 357 | CRYPTO_THREAD_write_lock(ctx->lock); |
0f113f3e | 358 | |
0f113f3e | 359 | if (X509_OBJECT_retrieve_match(ctx->objs, obj)) { |
0f113f3e MC |
360 | X509err(X509_F_X509_STORE_ADD_CRL, X509_R_CERT_ALREADY_IN_HASH_TABLE); |
361 | ret = 0; | |
68efafc5 F |
362 | } else { |
363 | added = sk_X509_OBJECT_push(ctx->objs, obj); | |
364 | ret = added != 0; | |
365 | } | |
0f113f3e | 366 | |
c001ce33 | 367 | CRYPTO_THREAD_unlock(ctx->lock); |
0f113f3e | 368 | |
68efafc5 F |
369 | if (!ret) /* obj not pushed */ |
370 | X509_OBJECT_free(obj); | |
371 | if (!added) /* on push failure */ | |
372 | X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE); | |
373 | ||
0f113f3e MC |
374 | return ret; |
375 | } | |
2f043896 | 376 | |
c5ebfcab | 377 | int X509_OBJECT_up_ref_count(X509_OBJECT *a) |
0f113f3e MC |
378 | { |
379 | switch (a->type) { | |
bca3f06b RS |
380 | default: |
381 | break; | |
0f113f3e | 382 | case X509_LU_X509: |
c5ebfcab | 383 | return X509_up_ref(a->data.x509); |
0f113f3e | 384 | case X509_LU_CRL: |
c5ebfcab | 385 | return X509_CRL_up_ref(a->data.crl); |
0f113f3e | 386 | } |
c5ebfcab | 387 | return 1; |
0f113f3e | 388 | } |
d02b48c6 | 389 | |
7d7da288 | 390 | X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a) |
f0e0fd51 | 391 | { |
6ddbb4cd RS |
392 | if (a == NULL || a->type != X509_LU_X509) |
393 | return NULL; | |
f0e0fd51 RS |
394 | return a->data.x509; |
395 | } | |
396 | ||
6ddbb4cd RS |
397 | X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a) |
398 | { | |
399 | if (a == NULL || a->type != X509_LU_CRL) | |
400 | return NULL; | |
401 | return a->data.crl; | |
402 | } | |
403 | ||
0946a198 | 404 | X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a) |
f0c58c32 CH |
405 | { |
406 | return a->type; | |
407 | } | |
408 | ||
6ddbb4cd | 409 | X509_OBJECT *X509_OBJECT_new() |
f0e0fd51 | 410 | { |
6ddbb4cd RS |
411 | X509_OBJECT *ret = OPENSSL_zalloc(sizeof(*ret)); |
412 | ||
413 | if (ret == NULL) { | |
414 | X509err(X509_F_X509_OBJECT_NEW, ERR_R_MALLOC_FAILURE); | |
415 | return NULL; | |
416 | } | |
ba1a1c37 | 417 | ret->type = X509_LU_NONE; |
6ddbb4cd | 418 | return ret; |
f0e0fd51 RS |
419 | } |
420 | ||
6ddbb4cd RS |
421 | |
422 | void X509_OBJECT_free(X509_OBJECT *a) | |
0f113f3e | 423 | { |
f0e0fd51 | 424 | if (a == NULL) |
222561fe | 425 | return; |
0f113f3e | 426 | switch (a->type) { |
bca3f06b RS |
427 | default: |
428 | break; | |
0f113f3e MC |
429 | case X509_LU_X509: |
430 | X509_free(a->data.x509); | |
431 | break; | |
432 | case X509_LU_CRL: | |
433 | X509_CRL_free(a->data.crl); | |
434 | break; | |
435 | } | |
6ddbb4cd | 436 | OPENSSL_free(a); |
0f113f3e | 437 | } |
d02b48c6 | 438 | |
0946a198 | 439 | static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, |
0f113f3e MC |
440 | X509_NAME *name, int *pnmatch) |
441 | { | |
442 | X509_OBJECT stmp; | |
443 | X509 x509_s; | |
0f113f3e | 444 | X509_CRL crl_s; |
0f113f3e MC |
445 | int idx; |
446 | ||
447 | stmp.type = type; | |
448 | switch (type) { | |
449 | case X509_LU_X509: | |
450 | stmp.data.x509 = &x509_s; | |
5cf6abd8 | 451 | x509_s.cert_info.subject = name; |
0f113f3e MC |
452 | break; |
453 | case X509_LU_CRL: | |
454 | stmp.data.crl = &crl_s; | |
7aef39a7 | 455 | crl_s.crl.issuer = name; |
0f113f3e MC |
456 | break; |
457 | default: | |
458 | /* abort(); */ | |
459 | return -1; | |
460 | } | |
461 | ||
462 | idx = sk_X509_OBJECT_find(h, &stmp); | |
463 | if (idx >= 0 && pnmatch) { | |
464 | int tidx; | |
465 | const X509_OBJECT *tobj, *pstmp; | |
466 | *pnmatch = 1; | |
467 | pstmp = &stmp; | |
468 | for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) { | |
469 | tobj = sk_X509_OBJECT_value(h, tidx); | |
470 | if (x509_object_cmp(&tobj, &pstmp)) | |
471 | break; | |
472 | (*pnmatch)++; | |
473 | } | |
474 | } | |
475 | return idx; | |
476 | } | |
4d50a2b4 | 477 | |
0946a198 | 478 | int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, |
0f113f3e MC |
479 | X509_NAME *name) |
480 | { | |
481 | return x509_object_idx_cnt(h, type, name, NULL); | |
482 | } | |
483 | ||
484 | X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, | |
0946a198 DSH |
485 | X509_LOOKUP_TYPE type, |
486 | X509_NAME *name) | |
0f113f3e MC |
487 | { |
488 | int idx; | |
489 | idx = X509_OBJECT_idx_by_subject(h, type, name); | |
490 | if (idx == -1) | |
491 | return NULL; | |
492 | return sk_X509_OBJECT_value(h, idx); | |
493 | } | |
11262391 | 494 | |
f0c58c32 CH |
495 | STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v) |
496 | { | |
497 | return v->objs; | |
498 | } | |
499 | ||
6ddbb4cd | 500 | STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm) |
0f113f3e MC |
501 | { |
502 | int i, idx, cnt; | |
6ddbb4cd | 503 | STACK_OF(X509) *sk = NULL; |
0f113f3e MC |
504 | X509 *x; |
505 | X509_OBJECT *obj; | |
6ddbb4cd | 506 | |
c001ce33 | 507 | CRYPTO_THREAD_write_lock(ctx->ctx->lock); |
0f113f3e MC |
508 | idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); |
509 | if (idx < 0) { | |
510 | /* | |
511 | * Nothing found in cache: do lookup to possibly add new objects to | |
512 | * cache | |
513 | */ | |
6ddbb4cd RS |
514 | X509_OBJECT *xobj = X509_OBJECT_new(); |
515 | ||
c001ce33 | 516 | CRYPTO_THREAD_unlock(ctx->ctx->lock); |
6ddbb4cd RS |
517 | if (xobj == NULL) |
518 | return NULL; | |
519 | if (!X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, nm, xobj)) { | |
520 | X509_OBJECT_free(xobj); | |
0f113f3e MC |
521 | return NULL; |
522 | } | |
6ddbb4cd | 523 | X509_OBJECT_free(xobj); |
c001ce33 | 524 | CRYPTO_THREAD_write_lock(ctx->ctx->lock); |
0f113f3e MC |
525 | idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt); |
526 | if (idx < 0) { | |
c001ce33 | 527 | CRYPTO_THREAD_unlock(ctx->ctx->lock); |
0f113f3e MC |
528 | return NULL; |
529 | } | |
530 | } | |
6ddbb4cd RS |
531 | |
532 | sk = sk_X509_new_null(); | |
0f113f3e MC |
533 | for (i = 0; i < cnt; i++, idx++) { |
534 | obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); | |
535 | x = obj->data.x509; | |
05f0fb9f | 536 | X509_up_ref(x); |
0f113f3e | 537 | if (!sk_X509_push(sk, x)) { |
c001ce33 | 538 | CRYPTO_THREAD_unlock(ctx->ctx->lock); |
0f113f3e MC |
539 | X509_free(x); |
540 | sk_X509_pop_free(sk, X509_free); | |
541 | return NULL; | |
542 | } | |
543 | } | |
c001ce33 | 544 | CRYPTO_THREAD_unlock(ctx->ctx->lock); |
0f113f3e | 545 | return sk; |
0f113f3e | 546 | } |
4d50a2b4 | 547 | |
6ddbb4cd | 548 | STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm) |
0f113f3e MC |
549 | { |
550 | int i, idx, cnt; | |
6ddbb4cd | 551 | STACK_OF(X509_CRL) *sk = sk_X509_CRL_new_null(); |
0f113f3e | 552 | X509_CRL *x; |
6ddbb4cd | 553 | X509_OBJECT *obj, *xobj = X509_OBJECT_new(); |
0f113f3e | 554 | |
6ddbb4cd RS |
555 | /* Always do lookup to possibly add new CRLs to cache */ |
556 | if (sk == NULL || xobj == NULL || | |
557 | !X509_STORE_CTX_get_by_subject(ctx, X509_LU_CRL, nm, xobj)) { | |
558 | X509_OBJECT_free(xobj); | |
0f113f3e MC |
559 | sk_X509_CRL_free(sk); |
560 | return NULL; | |
561 | } | |
6ddbb4cd | 562 | X509_OBJECT_free(xobj); |
c001ce33 | 563 | CRYPTO_THREAD_write_lock(ctx->ctx->lock); |
0f113f3e MC |
564 | idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt); |
565 | if (idx < 0) { | |
c001ce33 | 566 | CRYPTO_THREAD_unlock(ctx->ctx->lock); |
0f113f3e MC |
567 | sk_X509_CRL_free(sk); |
568 | return NULL; | |
569 | } | |
570 | ||
571 | for (i = 0; i < cnt; i++, idx++) { | |
572 | obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx); | |
573 | x = obj->data.crl; | |
65cbf983 | 574 | X509_CRL_up_ref(x); |
0f113f3e | 575 | if (!sk_X509_CRL_push(sk, x)) { |
c001ce33 | 576 | CRYPTO_THREAD_unlock(ctx->ctx->lock); |
0f113f3e MC |
577 | X509_CRL_free(x); |
578 | sk_X509_CRL_pop_free(sk, X509_CRL_free); | |
579 | return NULL; | |
580 | } | |
581 | } | |
c001ce33 | 582 | CRYPTO_THREAD_unlock(ctx->ctx->lock); |
0f113f3e MC |
583 | return sk; |
584 | } | |
585 | ||
586 | X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, | |
587 | X509_OBJECT *x) | |
588 | { | |
589 | int idx, i; | |
590 | X509_OBJECT *obj; | |
591 | idx = sk_X509_OBJECT_find(h, x); | |
592 | if (idx == -1) | |
593 | return NULL; | |
594 | if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL)) | |
595 | return sk_X509_OBJECT_value(h, idx); | |
596 | for (i = idx; i < sk_X509_OBJECT_num(h); i++) { | |
597 | obj = sk_X509_OBJECT_value(h, i); | |
598 | if (x509_object_cmp | |
599 | ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x)) | |
600 | return NULL; | |
601 | if (x->type == X509_LU_X509) { | |
602 | if (!X509_cmp(obj->data.x509, x->data.x509)) | |
603 | return obj; | |
604 | } else if (x->type == X509_LU_CRL) { | |
605 | if (!X509_CRL_match(obj->data.crl, x->data.crl)) | |
606 | return obj; | |
607 | } else | |
608 | return obj; | |
609 | } | |
610 | return NULL; | |
611 | } | |
d02b48c6 | 612 | |
1d97c843 TH |
613 | /*- |
614 | * Try to get issuer certificate from store. Due to limitations | |
2f043896 DSH |
615 | * of the API this can only retrieve a single certificate matching |
616 | * a given subject name. However it will fill the cache with all | |
a8397553 | 617 | * matching certificates, so we can examine the cache for all |
2f043896 DSH |
618 | * matches. |
619 | * | |
620 | * Return values are: | |
621 | * 1 lookup successful. | |
622 | * 0 certificate not found. | |
623 | * -1 some other error. | |
624 | */ | |
2f043896 | 625 | int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) |
0f113f3e MC |
626 | { |
627 | X509_NAME *xn; | |
6ddbb4cd | 628 | X509_OBJECT *obj = X509_OBJECT_new(), *pobj = NULL; |
0f113f3e | 629 | int i, ok, idx, ret; |
f0e0fd51 | 630 | |
6ddbb4cd RS |
631 | if (obj == NULL) |
632 | return -1; | |
0f113f3e MC |
633 | *issuer = NULL; |
634 | xn = X509_get_issuer_name(x); | |
6ddbb4cd | 635 | ok = X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, xn, obj); |
ba1a1c37 | 636 | if (ok != 1) { |
6ddbb4cd | 637 | X509_OBJECT_free(obj); |
0f113f3e MC |
638 | return 0; |
639 | } | |
640 | /* If certificate matches all OK */ | |
6ddbb4cd RS |
641 | if (ctx->check_issued(ctx, x, obj->data.x509)) { |
642 | if (x509_check_cert_time(ctx, obj->data.x509, -1)) { | |
643 | *issuer = obj->data.x509; | |
644 | X509_up_ref(*issuer); | |
645 | X509_OBJECT_free(obj); | |
0f113f3e MC |
646 | return 1; |
647 | } | |
648 | } | |
6ddbb4cd | 649 | X509_OBJECT_free(obj); |
0f113f3e MC |
650 | |
651 | /* Else find index of first cert accepted by 'check_issued' */ | |
652 | ret = 0; | |
c001ce33 | 653 | CRYPTO_THREAD_write_lock(ctx->ctx->lock); |
0f113f3e MC |
654 | idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn); |
655 | if (idx != -1) { /* should be true as we've had at least one | |
656 | * match */ | |
657 | /* Look through all matching certs for suitable issuer */ | |
658 | for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) { | |
659 | pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i); | |
660 | /* See if we've run past the matches */ | |
661 | if (pobj->type != X509_LU_X509) | |
662 | break; | |
663 | if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509))) | |
664 | break; | |
665 | if (ctx->check_issued(ctx, x, pobj->data.x509)) { | |
666 | *issuer = pobj->data.x509; | |
667 | ret = 1; | |
668 | /* | |
669 | * If times check, exit with match, | |
670 | * otherwise keep looking. Leave last | |
671 | * match in issuer so we return nearest | |
672 | * match if no certificate time is OK. | |
673 | */ | |
674 | ||
70dd3c65 | 675 | if (x509_check_cert_time(ctx, *issuer, -1)) |
0f113f3e MC |
676 | break; |
677 | } | |
678 | } | |
679 | } | |
c001ce33 | 680 | CRYPTO_THREAD_unlock(ctx->ctx->lock); |
0f113f3e | 681 | if (*issuer) |
05f0fb9f | 682 | X509_up_ref(*issuer); |
0f113f3e MC |
683 | return ret; |
684 | } | |
d02b48c6 | 685 | |
5d7c222d | 686 | int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) |
0f113f3e MC |
687 | { |
688 | return X509_VERIFY_PARAM_set_flags(ctx->param, flags); | |
689 | } | |
5d7c222d DSH |
690 | |
691 | int X509_STORE_set_depth(X509_STORE *ctx, int depth) | |
0f113f3e MC |
692 | { |
693 | X509_VERIFY_PARAM_set_depth(ctx->param, depth); | |
694 | return 1; | |
695 | } | |
bdee69f7 | 696 | |
926a56bf | 697 | int X509_STORE_set_purpose(X509_STORE *ctx, int purpose) |
0f113f3e MC |
698 | { |
699 | return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose); | |
700 | } | |
926a56bf DSH |
701 | |
702 | int X509_STORE_set_trust(X509_STORE *ctx, int trust) | |
0f113f3e MC |
703 | { |
704 | return X509_VERIFY_PARAM_set_trust(ctx->param, trust); | |
705 | } | |
5d7c222d DSH |
706 | |
707 | int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param) | |
0f113f3e MC |
708 | { |
709 | return X509_VERIFY_PARAM_set1(ctx->param, param); | |
710 | } | |
926a56bf | 711 | |
f0c58c32 CH |
712 | X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx) |
713 | { | |
714 | return ctx->param; | |
715 | } | |
716 | ||
1060a50b RL |
717 | void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify) |
718 | { | |
719 | ctx->verify = verify; | |
720 | } | |
721 | ||
722 | X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx) | |
723 | { | |
724 | return ctx->verify; | |
725 | } | |
726 | ||
a5b37fca | 727 | void X509_STORE_set_verify_cb(X509_STORE *ctx, |
1060a50b | 728 | X509_STORE_CTX_verify_cb verify_cb) |
0f113f3e MC |
729 | { |
730 | ctx->verify_cb = verify_cb; | |
731 | } | |
a5b37fca | 732 | |
1060a50b | 733 | X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx) |
7cafbb4b | 734 | { |
1060a50b RL |
735 | return ctx->verify_cb; |
736 | } | |
737 | ||
738 | void X509_STORE_set_get_issuer(X509_STORE *ctx, | |
739 | X509_STORE_CTX_get_issuer_fn get_issuer) | |
740 | { | |
741 | ctx->get_issuer = get_issuer; | |
742 | } | |
743 | ||
744 | X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx) | |
745 | { | |
746 | return ctx->get_issuer; | |
747 | } | |
748 | ||
749 | void X509_STORE_set_check_issued(X509_STORE *ctx, | |
750 | X509_STORE_CTX_check_issued_fn check_issued) | |
751 | { | |
752 | ctx->check_issued = check_issued; | |
753 | } | |
754 | ||
755 | X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx) | |
756 | { | |
757 | return ctx->check_issued; | |
758 | } | |
759 | ||
760 | void X509_STORE_set_check_revocation(X509_STORE *ctx, | |
761 | X509_STORE_CTX_check_revocation_fn check_revocation) | |
762 | { | |
763 | ctx->check_revocation = check_revocation; | |
764 | } | |
765 | ||
766 | X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx) | |
767 | { | |
768 | return ctx->check_revocation; | |
769 | } | |
770 | ||
771 | void X509_STORE_set_get_crl(X509_STORE *ctx, | |
772 | X509_STORE_CTX_get_crl_fn get_crl) | |
773 | { | |
774 | ctx->get_crl = get_crl; | |
775 | } | |
776 | ||
777 | X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx) | |
778 | { | |
779 | return ctx->get_crl; | |
780 | } | |
781 | ||
782 | void X509_STORE_set_check_crl(X509_STORE *ctx, | |
783 | X509_STORE_CTX_check_crl_fn check_crl) | |
784 | { | |
785 | ctx->check_crl = check_crl; | |
786 | } | |
787 | ||
788 | X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx) | |
789 | { | |
790 | return ctx->check_crl; | |
791 | } | |
792 | ||
793 | void X509_STORE_set_cert_crl(X509_STORE *ctx, | |
794 | X509_STORE_CTX_cert_crl_fn cert_crl) | |
795 | { | |
796 | ctx->cert_crl = cert_crl; | |
797 | } | |
798 | ||
799 | X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx) | |
800 | { | |
801 | return ctx->cert_crl; | |
802 | } | |
803 | ||
0a5fe2eb RL |
804 | void X509_STORE_set_check_policy(X509_STORE *ctx, |
805 | X509_STORE_CTX_check_policy_fn check_policy) | |
806 | { | |
807 | ctx->check_policy = check_policy; | |
808 | } | |
809 | ||
810 | X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE *ctx) | |
811 | { | |
812 | return ctx->check_policy; | |
813 | } | |
814 | ||
1060a50b RL |
815 | void X509_STORE_set_lookup_certs(X509_STORE *ctx, |
816 | X509_STORE_CTX_lookup_certs_fn lookup_certs) | |
817 | { | |
818 | ctx->lookup_certs = lookup_certs; | |
819 | } | |
820 | ||
821 | X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx) | |
822 | { | |
823 | return ctx->lookup_certs; | |
824 | } | |
825 | ||
826 | void X509_STORE_set_lookup_crls(X509_STORE *ctx, | |
827 | X509_STORE_CTX_lookup_crls_fn lookup_crls) | |
828 | { | |
829 | ctx->lookup_crls = lookup_crls; | |
830 | } | |
831 | ||
832 | X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx) | |
833 | { | |
834 | return ctx->lookup_crls; | |
835 | } | |
836 | ||
837 | void X509_STORE_set_cleanup(X509_STORE *ctx, | |
838 | X509_STORE_CTX_cleanup_fn ctx_cleanup) | |
839 | { | |
840 | ctx->cleanup = ctx_cleanup; | |
7cafbb4b MC |
841 | } |
842 | ||
1060a50b | 843 | X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx) |
0f113f3e | 844 | { |
1060a50b | 845 | return ctx->cleanup; |
0f113f3e | 846 | } |
2c340864 | 847 | |
3aec886e KY |
848 | int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data) |
849 | { | |
850 | return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); | |
851 | } | |
852 | ||
853 | void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx) | |
854 | { | |
855 | return CRYPTO_get_ex_data(&ctx->ex_data, idx); | |
856 | } | |
857 | ||
2c340864 | 858 | X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx) |
0f113f3e MC |
859 | { |
860 | return ctx->ctx; | |
861 | } |