/src/libressl/ssl/ssl_cert.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD: ssl_cert.c,v 1.103 2022/07/07 13:04:39 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 | | * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. |
60 | | * |
61 | | * Redistribution and use in source and binary forms, with or without |
62 | | * modification, are permitted provided that the following conditions |
63 | | * are met: |
64 | | * |
65 | | * 1. Redistributions of source code must retain the above copyright |
66 | | * notice, this list of conditions and the following disclaimer. |
67 | | * |
68 | | * 2. Redistributions in binary form must reproduce the above copyright |
69 | | * notice, this list of conditions and the following disclaimer in |
70 | | * the documentation and/or other materials provided with the |
71 | | * distribution. |
72 | | * |
73 | | * 3. All advertising materials mentioning features or use of this |
74 | | * software must display the following acknowledgment: |
75 | | * "This product includes software developed by the OpenSSL Project |
76 | | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" |
77 | | * |
78 | | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
79 | | * endorse or promote products derived from this software without |
80 | | * prior written permission. For written permission, please contact |
81 | | * openssl-core@openssl.org. |
82 | | * |
83 | | * 5. Products derived from this software may not be called "OpenSSL" |
84 | | * nor may "OpenSSL" appear in their names without prior written |
85 | | * permission of the OpenSSL Project. |
86 | | * |
87 | | * 6. Redistributions of any form whatsoever must retain the following |
88 | | * acknowledgment: |
89 | | * "This product includes software developed by the OpenSSL Project |
90 | | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" |
91 | | * |
92 | | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
93 | | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
94 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
95 | | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
96 | | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
97 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
98 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
99 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
100 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
101 | | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
102 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
103 | | * OF THE POSSIBILITY OF SUCH DAMAGE. |
104 | | * ==================================================================== |
105 | | * |
106 | | * This product includes cryptographic software written by Eric Young |
107 | | * (eay@cryptsoft.com). This product includes software written by Tim |
108 | | * Hudson (tjh@cryptsoft.com). |
109 | | * |
110 | | */ |
111 | | /* ==================================================================== |
112 | | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. |
113 | | * ECC cipher suite support in OpenSSL originally developed by |
114 | | * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. |
115 | | */ |
116 | | |
117 | | #include <sys/types.h> |
118 | | |
119 | | #include <dirent.h> |
120 | | #include <stdio.h> |
121 | | #include <unistd.h> |
122 | | |
123 | | #include <openssl/bio.h> |
124 | | #include <openssl/bn.h> |
125 | | #include <openssl/dh.h> |
126 | | #include <openssl/objects.h> |
127 | | #include <openssl/opensslconf.h> |
128 | | #include <openssl/pem.h> |
129 | | #include <openssl/x509v3.h> |
130 | | |
131 | | #include "ssl_locl.h" |
132 | | |
133 | | int |
134 | | SSL_get_ex_data_X509_STORE_CTX_idx(void) |
135 | 0 | { |
136 | 0 | static volatile int ssl_x509_store_ctx_idx = -1; |
137 | 0 | int got_write_lock = 0; |
138 | |
|
139 | 0 | CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); |
140 | |
|
141 | 0 | if (ssl_x509_store_ctx_idx < 0) { |
142 | 0 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); |
143 | 0 | CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); |
144 | 0 | got_write_lock = 1; |
145 | |
|
146 | 0 | if (ssl_x509_store_ctx_idx < 0) { |
147 | 0 | ssl_x509_store_ctx_idx = |
148 | 0 | X509_STORE_CTX_get_ex_new_index( |
149 | 0 | 0, "SSL for verify callback", NULL, NULL, NULL); |
150 | 0 | } |
151 | 0 | } |
152 | |
|
153 | 0 | if (got_write_lock) |
154 | 0 | CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); |
155 | 0 | else |
156 | 0 | CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); |
157 | |
|
158 | 0 | return ssl_x509_store_ctx_idx; |
159 | 0 | } |
160 | | |
161 | | SSL_CERT * |
162 | | ssl_cert_new(void) |
163 | 0 | { |
164 | 0 | SSL_CERT *ret; |
165 | |
|
166 | 0 | ret = calloc(1, sizeof(SSL_CERT)); |
167 | 0 | if (ret == NULL) { |
168 | 0 | SSLerrorx(ERR_R_MALLOC_FAILURE); |
169 | 0 | return (NULL); |
170 | 0 | } |
171 | 0 | ret->key = &(ret->pkeys[SSL_PKEY_RSA]); |
172 | 0 | ret->references = 1; |
173 | 0 | ret->security_cb = ssl_security_default_cb; |
174 | 0 | ret->security_level = OPENSSL_TLS_SECURITY_LEVEL; |
175 | 0 | ret->security_ex_data = NULL; |
176 | 0 | return (ret); |
177 | 0 | } |
178 | | |
179 | | SSL_CERT * |
180 | | ssl_cert_dup(SSL_CERT *cert) |
181 | 0 | { |
182 | 0 | SSL_CERT *ret; |
183 | 0 | int i; |
184 | |
|
185 | 0 | ret = calloc(1, sizeof(SSL_CERT)); |
186 | 0 | if (ret == NULL) { |
187 | 0 | SSLerrorx(ERR_R_MALLOC_FAILURE); |
188 | 0 | return (NULL); |
189 | 0 | } |
190 | | |
191 | | /* |
192 | | * same as ret->key = ret->pkeys + (cert->key - cert->pkeys), |
193 | | * if you find that more readable |
194 | | */ |
195 | 0 | ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; |
196 | |
|
197 | 0 | ret->valid = cert->valid; |
198 | 0 | ret->mask_k = cert->mask_k; |
199 | 0 | ret->mask_a = cert->mask_a; |
200 | |
|
201 | 0 | if (cert->dhe_params != NULL) { |
202 | 0 | ret->dhe_params = DHparams_dup(cert->dhe_params); |
203 | 0 | if (ret->dhe_params == NULL) { |
204 | 0 | SSLerrorx(ERR_R_DH_LIB); |
205 | 0 | goto err; |
206 | 0 | } |
207 | 0 | } |
208 | 0 | ret->dhe_params_cb = cert->dhe_params_cb; |
209 | 0 | ret->dhe_params_auto = cert->dhe_params_auto; |
210 | |
|
211 | 0 | for (i = 0; i < SSL_PKEY_NUM; i++) { |
212 | 0 | if (cert->pkeys[i].x509 != NULL) { |
213 | 0 | ret->pkeys[i].x509 = cert->pkeys[i].x509; |
214 | 0 | X509_up_ref(ret->pkeys[i].x509); |
215 | 0 | } |
216 | |
|
217 | 0 | if (cert->pkeys[i].privatekey != NULL) { |
218 | 0 | ret->pkeys[i].privatekey = cert->pkeys[i].privatekey; |
219 | 0 | EVP_PKEY_up_ref(ret->pkeys[i].privatekey); |
220 | 0 | switch (i) { |
221 | | /* |
222 | | * If there was anything special to do for |
223 | | * certain types of keys, we'd do it here. |
224 | | * (Nothing at the moment, I think.) |
225 | | */ |
226 | | |
227 | 0 | case SSL_PKEY_RSA: |
228 | | /* We have an RSA key. */ |
229 | 0 | break; |
230 | | |
231 | 0 | case SSL_PKEY_ECC: |
232 | | /* We have an ECC key */ |
233 | 0 | break; |
234 | | |
235 | 0 | case SSL_PKEY_GOST01: |
236 | | /* We have a GOST key */ |
237 | 0 | break; |
238 | | |
239 | 0 | default: |
240 | | /* Can't happen. */ |
241 | 0 | SSLerrorx(SSL_R_LIBRARY_BUG); |
242 | 0 | } |
243 | 0 | } |
244 | | |
245 | 0 | if (cert->pkeys[i].chain != NULL) { |
246 | 0 | if ((ret->pkeys[i].chain = |
247 | 0 | X509_chain_up_ref(cert->pkeys[i].chain)) == NULL) |
248 | 0 | goto err; |
249 | 0 | } |
250 | 0 | } |
251 | | |
252 | 0 | ret->security_cb = cert->security_cb; |
253 | 0 | ret->security_level = cert->security_level; |
254 | 0 | ret->security_ex_data = cert->security_ex_data; |
255 | | |
256 | | /* |
257 | | * ret->extra_certs *should* exist, but currently the own certificate |
258 | | * chain is held inside SSL_CTX |
259 | | */ |
260 | |
|
261 | 0 | ret->references = 1; |
262 | |
|
263 | 0 | return (ret); |
264 | | |
265 | 0 | err: |
266 | 0 | DH_free(ret->dhe_params); |
267 | |
|
268 | 0 | for (i = 0; i < SSL_PKEY_NUM; i++) { |
269 | 0 | X509_free(ret->pkeys[i].x509); |
270 | 0 | EVP_PKEY_free(ret->pkeys[i].privatekey); |
271 | 0 | sk_X509_pop_free(ret->pkeys[i].chain, X509_free); |
272 | 0 | } |
273 | 0 | free (ret); |
274 | 0 | return NULL; |
275 | 0 | } |
276 | | |
277 | | |
278 | | void |
279 | | ssl_cert_free(SSL_CERT *c) |
280 | 0 | { |
281 | 0 | int i; |
282 | |
|
283 | 0 | if (c == NULL) |
284 | 0 | return; |
285 | | |
286 | 0 | i = CRYPTO_add(&c->references, -1, CRYPTO_LOCK_SSL_CERT); |
287 | 0 | if (i > 0) |
288 | 0 | return; |
289 | | |
290 | 0 | DH_free(c->dhe_params); |
291 | |
|
292 | 0 | for (i = 0; i < SSL_PKEY_NUM; i++) { |
293 | 0 | X509_free(c->pkeys[i].x509); |
294 | 0 | EVP_PKEY_free(c->pkeys[i].privatekey); |
295 | 0 | sk_X509_pop_free(c->pkeys[i].chain, X509_free); |
296 | 0 | } |
297 | |
|
298 | 0 | free(c); |
299 | 0 | } |
300 | | |
301 | | SSL_CERT * |
302 | | ssl_get0_cert(SSL_CTX *ctx, SSL *ssl) |
303 | 0 | { |
304 | 0 | if (ssl != NULL) |
305 | 0 | return ssl->cert; |
306 | | |
307 | 0 | return ctx->internal->cert; |
308 | 0 | } |
309 | | |
310 | | int |
311 | | ssl_cert_set0_chain(SSL_CTX *ctx, SSL *ssl, STACK_OF(X509) *chain) |
312 | 0 | { |
313 | 0 | SSL_CERT *ssl_cert; |
314 | 0 | SSL_CERT_PKEY *cpk; |
315 | 0 | X509 *x509; |
316 | 0 | int ssl_err; |
317 | 0 | int i; |
318 | |
|
319 | 0 | if ((ssl_cert = ssl_get0_cert(ctx, ssl)) == NULL) |
320 | 0 | return 0; |
321 | | |
322 | 0 | if ((cpk = ssl_cert->key) == NULL) |
323 | 0 | return 0; |
324 | | |
325 | 0 | for (i = 0; i < sk_X509_num(chain); i++) { |
326 | 0 | x509 = sk_X509_value(chain, i); |
327 | 0 | if (!ssl_security_cert(ctx, ssl, x509, 0, &ssl_err)) { |
328 | 0 | SSLerrorx(ssl_err); |
329 | 0 | return 0; |
330 | 0 | } |
331 | 0 | } |
332 | | |
333 | 0 | sk_X509_pop_free(cpk->chain, X509_free); |
334 | 0 | cpk->chain = chain; |
335 | |
|
336 | 0 | return 1; |
337 | 0 | } |
338 | | |
339 | | int |
340 | | ssl_cert_set1_chain(SSL_CTX *ctx, SSL *ssl, STACK_OF(X509) *chain) |
341 | 0 | { |
342 | 0 | STACK_OF(X509) *new_chain = NULL; |
343 | |
|
344 | 0 | if (chain != NULL) { |
345 | 0 | if ((new_chain = X509_chain_up_ref(chain)) == NULL) |
346 | 0 | return 0; |
347 | 0 | } |
348 | 0 | if (!ssl_cert_set0_chain(ctx, ssl, new_chain)) { |
349 | 0 | sk_X509_pop_free(new_chain, X509_free); |
350 | 0 | return 0; |
351 | 0 | } |
352 | | |
353 | 0 | return 1; |
354 | 0 | } |
355 | | |
356 | | int |
357 | | ssl_cert_add0_chain_cert(SSL_CTX *ctx, SSL *ssl, X509 *cert) |
358 | 0 | { |
359 | 0 | SSL_CERT *ssl_cert; |
360 | 0 | SSL_CERT_PKEY *cpk; |
361 | 0 | int ssl_err; |
362 | |
|
363 | 0 | if ((ssl_cert = ssl_get0_cert(ctx, ssl)) == NULL) |
364 | 0 | return 0; |
365 | | |
366 | 0 | if ((cpk = ssl_cert->key) == NULL) |
367 | 0 | return 0; |
368 | | |
369 | 0 | if (!ssl_security_cert(ctx, ssl, cert, 0, &ssl_err)) { |
370 | 0 | SSLerrorx(ssl_err); |
371 | 0 | return 0; |
372 | 0 | } |
373 | | |
374 | 0 | if (cpk->chain == NULL) { |
375 | 0 | if ((cpk->chain = sk_X509_new_null()) == NULL) |
376 | 0 | return 0; |
377 | 0 | } |
378 | 0 | if (!sk_X509_push(cpk->chain, cert)) |
379 | 0 | return 0; |
380 | | |
381 | 0 | return 1; |
382 | 0 | } |
383 | | |
384 | | int |
385 | | ssl_cert_add1_chain_cert(SSL_CTX *ctx, SSL *ssl, X509 *cert) |
386 | 0 | { |
387 | 0 | if (!ssl_cert_add0_chain_cert(ctx, ssl, cert)) |
388 | 0 | return 0; |
389 | | |
390 | 0 | X509_up_ref(cert); |
391 | |
|
392 | 0 | return 1; |
393 | 0 | } |
394 | | |
395 | | int |
396 | | ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *certs) |
397 | 0 | { |
398 | 0 | X509_STORE_CTX *ctx = NULL; |
399 | 0 | X509_VERIFY_PARAM *param; |
400 | 0 | X509 *cert; |
401 | 0 | int ret = 0; |
402 | |
|
403 | 0 | if (sk_X509_num(certs) < 1) |
404 | 0 | goto err; |
405 | | |
406 | 0 | if ((ctx = X509_STORE_CTX_new()) == NULL) |
407 | 0 | goto err; |
408 | | |
409 | 0 | cert = sk_X509_value(certs, 0); |
410 | 0 | if (!X509_STORE_CTX_init(ctx, s->ctx->cert_store, cert, certs)) { |
411 | 0 | SSLerror(s, ERR_R_X509_LIB); |
412 | 0 | goto err; |
413 | 0 | } |
414 | 0 | X509_STORE_CTX_set_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s); |
415 | | |
416 | | /* |
417 | | * We need to inherit the verify parameters. These can be |
418 | | * determined by the context: if its a server it will verify |
419 | | * SSL client certificates or vice versa. |
420 | | */ |
421 | 0 | X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server"); |
422 | |
|
423 | 0 | param = X509_STORE_CTX_get0_param(ctx); |
424 | |
|
425 | 0 | X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s)); |
426 | | |
427 | | /* |
428 | | * Anything non-default in "param" should overwrite anything |
429 | | * in the ctx. |
430 | | */ |
431 | 0 | X509_VERIFY_PARAM_set1(param, s->param); |
432 | |
|
433 | 0 | if (s->internal->verify_callback) |
434 | 0 | X509_STORE_CTX_set_verify_cb(ctx, s->internal->verify_callback); |
435 | |
|
436 | 0 | if (s->ctx->internal->app_verify_callback != NULL) |
437 | 0 | ret = s->ctx->internal->app_verify_callback(ctx, |
438 | 0 | s->ctx->internal->app_verify_arg); |
439 | 0 | else |
440 | 0 | ret = X509_verify_cert(ctx); |
441 | |
|
442 | 0 | s->verify_result = X509_STORE_CTX_get_error(ctx); |
443 | 0 | sk_X509_pop_free(s->internal->verified_chain, X509_free); |
444 | 0 | s->internal->verified_chain = NULL; |
445 | 0 | if (X509_STORE_CTX_get0_chain(ctx) != NULL) { |
446 | 0 | s->internal->verified_chain = X509_STORE_CTX_get1_chain(ctx); |
447 | 0 | if (s->internal->verified_chain == NULL) { |
448 | 0 | SSLerrorx(ERR_R_MALLOC_FAILURE); |
449 | 0 | ret = 0; |
450 | 0 | } |
451 | 0 | } |
452 | |
|
453 | 0 | err: |
454 | 0 | X509_STORE_CTX_free(ctx); |
455 | |
|
456 | 0 | return (ret); |
457 | 0 | } |
458 | | |
459 | | static void |
460 | | set_client_CA_list(STACK_OF(X509_NAME) **ca_list, |
461 | | STACK_OF(X509_NAME) *name_list) |
462 | 0 | { |
463 | 0 | sk_X509_NAME_pop_free(*ca_list, X509_NAME_free); |
464 | 0 | *ca_list = name_list; |
465 | 0 | } |
466 | | |
467 | | STACK_OF(X509_NAME) * |
468 | | SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk) |
469 | 0 | { |
470 | 0 | int i; |
471 | 0 | STACK_OF(X509_NAME) *ret; |
472 | 0 | X509_NAME *name = NULL; |
473 | |
|
474 | 0 | if ((ret = sk_X509_NAME_new_null()) == NULL) |
475 | 0 | goto err; |
476 | | |
477 | 0 | for (i = 0; i < sk_X509_NAME_num(sk); i++) { |
478 | 0 | if ((name = X509_NAME_dup(sk_X509_NAME_value(sk, i))) == NULL) |
479 | 0 | goto err; |
480 | 0 | if (!sk_X509_NAME_push(ret, name)) |
481 | 0 | goto err; |
482 | 0 | } |
483 | 0 | return (ret); |
484 | | |
485 | 0 | err: |
486 | 0 | X509_NAME_free(name); |
487 | 0 | sk_X509_NAME_pop_free(ret, X509_NAME_free); |
488 | 0 | return NULL; |
489 | 0 | } |
490 | | |
491 | | void |
492 | | SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) |
493 | 0 | { |
494 | 0 | set_client_CA_list(&(s->internal->client_CA), name_list); |
495 | 0 | } |
496 | | |
497 | | void |
498 | | SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) |
499 | 0 | { |
500 | 0 | set_client_CA_list(&(ctx->internal->client_CA), name_list); |
501 | 0 | } |
502 | | |
503 | | STACK_OF(X509_NAME) * |
504 | | SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) |
505 | 0 | { |
506 | 0 | return (ctx->internal->client_CA); |
507 | 0 | } |
508 | | |
509 | | STACK_OF(X509_NAME) * |
510 | | SSL_get_client_CA_list(const SSL *s) |
511 | 0 | { |
512 | 0 | if (!s->server) { |
513 | | /* We are in the client. */ |
514 | 0 | if ((s->version >> 8) == SSL3_VERSION_MAJOR) |
515 | 0 | return (s->s3->hs.tls12.ca_names); |
516 | 0 | else |
517 | 0 | return (NULL); |
518 | 0 | } else { |
519 | 0 | if (s->internal->client_CA != NULL) |
520 | 0 | return (s->internal->client_CA); |
521 | 0 | else |
522 | 0 | return (s->ctx->internal->client_CA); |
523 | 0 | } |
524 | 0 | } |
525 | | |
526 | | static int |
527 | | add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x) |
528 | 0 | { |
529 | 0 | X509_NAME *name; |
530 | |
|
531 | 0 | if (x == NULL) |
532 | 0 | return (0); |
533 | 0 | if ((*sk == NULL) && ((*sk = sk_X509_NAME_new_null()) == NULL)) |
534 | 0 | return (0); |
535 | | |
536 | 0 | if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL) |
537 | 0 | return (0); |
538 | | |
539 | 0 | if (!sk_X509_NAME_push(*sk, name)) { |
540 | 0 | X509_NAME_free(name); |
541 | 0 | return (0); |
542 | 0 | } |
543 | 0 | return (1); |
544 | 0 | } |
545 | | |
546 | | int |
547 | | SSL_add_client_CA(SSL *ssl, X509 *x) |
548 | 0 | { |
549 | 0 | return (add_client_CA(&(ssl->internal->client_CA), x)); |
550 | 0 | } |
551 | | |
552 | | int |
553 | | SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) |
554 | 0 | { |
555 | 0 | return (add_client_CA(&(ctx->internal->client_CA), x)); |
556 | 0 | } |
557 | | |
558 | | static int |
559 | | xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b) |
560 | 0 | { |
561 | 0 | return (X509_NAME_cmp(*a, *b)); |
562 | 0 | } |
563 | | |
564 | | /*! |
565 | | * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; |
566 | | * it doesn't really have anything to do with clients (except that a common use |
567 | | * for a stack of CAs is to send it to the client). Actually, it doesn't have |
568 | | * much to do with CAs, either, since it will load any old cert. |
569 | | * \param file the file containing one or more certs. |
570 | | * \return a ::STACK containing the certs. |
571 | | */ |
572 | | STACK_OF(X509_NAME) * |
573 | | SSL_load_client_CA_file(const char *file) |
574 | 0 | { |
575 | 0 | BIO *in; |
576 | 0 | X509 *x = NULL; |
577 | 0 | X509_NAME *xn = NULL; |
578 | 0 | STACK_OF(X509_NAME) *ret = NULL, *sk; |
579 | |
|
580 | 0 | sk = sk_X509_NAME_new(xname_cmp); |
581 | |
|
582 | 0 | in = BIO_new(BIO_s_file()); |
583 | |
|
584 | 0 | if ((sk == NULL) || (in == NULL)) { |
585 | 0 | SSLerrorx(ERR_R_MALLOC_FAILURE); |
586 | 0 | goto err; |
587 | 0 | } |
588 | | |
589 | 0 | if (!BIO_read_filename(in, file)) |
590 | 0 | goto err; |
591 | | |
592 | 0 | for (;;) { |
593 | 0 | if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) |
594 | 0 | break; |
595 | 0 | if (ret == NULL) { |
596 | 0 | ret = sk_X509_NAME_new_null(); |
597 | 0 | if (ret == NULL) { |
598 | 0 | SSLerrorx(ERR_R_MALLOC_FAILURE); |
599 | 0 | goto err; |
600 | 0 | } |
601 | 0 | } |
602 | 0 | if ((xn = X509_get_subject_name(x)) == NULL) |
603 | 0 | goto err; |
604 | | /* check for duplicates */ |
605 | 0 | xn = X509_NAME_dup(xn); |
606 | 0 | if (xn == NULL) |
607 | 0 | goto err; |
608 | 0 | if (sk_X509_NAME_find(sk, xn) >= 0) |
609 | 0 | X509_NAME_free(xn); |
610 | 0 | else { |
611 | 0 | if (!sk_X509_NAME_push(sk, xn)) |
612 | 0 | goto err; |
613 | 0 | if (!sk_X509_NAME_push(ret, xn)) |
614 | 0 | goto err; |
615 | 0 | } |
616 | 0 | } |
617 | | |
618 | 0 | if (0) { |
619 | 0 | err: |
620 | 0 | sk_X509_NAME_pop_free(ret, X509_NAME_free); |
621 | 0 | ret = NULL; |
622 | 0 | } |
623 | 0 | sk_X509_NAME_free(sk); |
624 | 0 | BIO_free(in); |
625 | 0 | X509_free(x); |
626 | 0 | if (ret != NULL) |
627 | 0 | ERR_clear_error(); |
628 | |
|
629 | 0 | return (ret); |
630 | 0 | } |
631 | | |
632 | | /*! |
633 | | * Add a file of certs to a stack. |
634 | | * \param stack the stack to add to. |
635 | | * \param file the file to add from. All certs in this file that are not |
636 | | * already in the stack will be added. |
637 | | * \return 1 for success, 0 for failure. Note that in the case of failure some |
638 | | * certs may have been added to \c stack. |
639 | | */ |
640 | | |
641 | | int |
642 | | SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, |
643 | | const char *file) |
644 | 0 | { |
645 | 0 | BIO *in; |
646 | 0 | X509 *x = NULL; |
647 | 0 | X509_NAME *xn = NULL; |
648 | 0 | int ret = 1; |
649 | 0 | int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b); |
650 | |
|
651 | 0 | oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp); |
652 | |
|
653 | 0 | in = BIO_new(BIO_s_file()); |
654 | |
|
655 | 0 | if (in == NULL) { |
656 | 0 | SSLerrorx(ERR_R_MALLOC_FAILURE); |
657 | 0 | goto err; |
658 | 0 | } |
659 | | |
660 | 0 | if (!BIO_read_filename(in, file)) |
661 | 0 | goto err; |
662 | | |
663 | 0 | for (;;) { |
664 | 0 | if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) |
665 | 0 | break; |
666 | 0 | if ((xn = X509_get_subject_name(x)) == NULL) |
667 | 0 | goto err; |
668 | 0 | xn = X509_NAME_dup(xn); |
669 | 0 | if (xn == NULL) |
670 | 0 | goto err; |
671 | 0 | if (sk_X509_NAME_find(stack, xn) >= 0) |
672 | 0 | X509_NAME_free(xn); |
673 | 0 | else |
674 | 0 | if (!sk_X509_NAME_push(stack, xn)) |
675 | 0 | goto err; |
676 | 0 | } |
677 | | |
678 | 0 | ERR_clear_error(); |
679 | |
|
680 | 0 | if (0) { |
681 | 0 | err: |
682 | 0 | ret = 0; |
683 | 0 | } |
684 | 0 | BIO_free(in); |
685 | 0 | X509_free(x); |
686 | |
|
687 | 0 | (void)sk_X509_NAME_set_cmp_func(stack, oldcmp); |
688 | |
|
689 | 0 | return ret; |
690 | 0 | } |
691 | | |
692 | | /*! |
693 | | * Add a directory of certs to a stack. |
694 | | * \param stack the stack to append to. |
695 | | * \param dir the directory to append from. All files in this directory will be |
696 | | * examined as potential certs. Any that are acceptable to |
697 | | * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will |
698 | | * be included. |
699 | | * \return 1 for success, 0 for failure. Note that in the case of failure some |
700 | | * certs may have been added to \c stack. |
701 | | */ |
702 | | |
703 | | int |
704 | | SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, const char *dir) |
705 | 0 | { |
706 | 0 | DIR *dirp = NULL; |
707 | 0 | char *path = NULL; |
708 | 0 | int ret = 0; |
709 | |
|
710 | 0 | dirp = opendir(dir); |
711 | 0 | if (dirp) { |
712 | 0 | struct dirent *dp; |
713 | 0 | while ((dp = readdir(dirp)) != NULL) { |
714 | 0 | if (asprintf(&path, "%s/%s", dir, dp->d_name) != -1) { |
715 | 0 | ret = SSL_add_file_cert_subjects_to_stack( |
716 | 0 | stack, path); |
717 | 0 | free(path); |
718 | 0 | } |
719 | 0 | if (!ret) |
720 | 0 | break; |
721 | 0 | } |
722 | 0 | (void) closedir(dirp); |
723 | 0 | } |
724 | 0 | if (!ret) { |
725 | 0 | SYSerror(errno); |
726 | 0 | ERR_asprintf_error_data("opendir ('%s')", dir); |
727 | 0 | SSLerrorx(ERR_R_SYS_LIB); |
728 | 0 | } |
729 | 0 | return ret; |
730 | 0 | } |