xref: /openbsd/lib/libssl/ssl_cert.c (revision 4a18b5ba)
1 /* $OpenBSD: ssl_cert.c,v 1.86 2021/10/23 20:42:50 beck 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 {
136 	static volatile int ssl_x509_store_ctx_idx = -1;
137 	int got_write_lock = 0;
138 
139 	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
140 
141 	if (ssl_x509_store_ctx_idx < 0) {
142 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
143 		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
144 		got_write_lock = 1;
145 
146 		if (ssl_x509_store_ctx_idx < 0) {
147 			ssl_x509_store_ctx_idx =
148 			    X509_STORE_CTX_get_ex_new_index(
149 				0, "SSL for verify callback", NULL, NULL, NULL);
150 		}
151 	}
152 
153 	if (got_write_lock)
154 		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
155 	else
156 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
157 
158 	return ssl_x509_store_ctx_idx;
159 }
160 
161 CERT *
162 ssl_cert_new(void)
163 {
164 	CERT *ret;
165 
166 	ret = calloc(1, sizeof(CERT));
167 	if (ret == NULL) {
168 		SSLerrorx(ERR_R_MALLOC_FAILURE);
169 		return (NULL);
170 	}
171 	ret->key = &(ret->pkeys[SSL_PKEY_RSA]);
172 	ret->references = 1;
173 	return (ret);
174 }
175 
176 CERT *
177 ssl_cert_dup(CERT *cert)
178 {
179 	CERT *ret;
180 	int i;
181 
182 	ret = calloc(1, sizeof(CERT));
183 	if (ret == NULL) {
184 		SSLerrorx(ERR_R_MALLOC_FAILURE);
185 		return (NULL);
186 	}
187 
188 	/*
189 	 * same as ret->key = ret->pkeys + (cert->key - cert->pkeys),
190 	 * if you find that more readable
191 	 */
192 	ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
193 
194 	ret->valid = cert->valid;
195 	ret->mask_k = cert->mask_k;
196 	ret->mask_a = cert->mask_a;
197 
198 	if (cert->dh_tmp != NULL) {
199 		ret->dh_tmp = DHparams_dup(cert->dh_tmp);
200 		if (ret->dh_tmp == NULL) {
201 			SSLerrorx(ERR_R_DH_LIB);
202 			goto err;
203 		}
204 		if (cert->dh_tmp->priv_key) {
205 			BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
206 			if (!b) {
207 				SSLerrorx(ERR_R_BN_LIB);
208 				goto err;
209 			}
210 			ret->dh_tmp->priv_key = b;
211 		}
212 		if (cert->dh_tmp->pub_key) {
213 			BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
214 			if (!b) {
215 				SSLerrorx(ERR_R_BN_LIB);
216 				goto err;
217 			}
218 			ret->dh_tmp->pub_key = b;
219 		}
220 	}
221 	ret->dh_tmp_cb = cert->dh_tmp_cb;
222 	ret->dh_tmp_auto = cert->dh_tmp_auto;
223 
224 	for (i = 0; i < SSL_PKEY_NUM; i++) {
225 		if (cert->pkeys[i].x509 != NULL) {
226 			ret->pkeys[i].x509 = cert->pkeys[i].x509;
227 			X509_up_ref(ret->pkeys[i].x509);
228 		}
229 
230 		if (cert->pkeys[i].privatekey != NULL) {
231 			ret->pkeys[i].privatekey = cert->pkeys[i].privatekey;
232 			CRYPTO_add(&ret->pkeys[i].privatekey->references, 1,
233 			CRYPTO_LOCK_EVP_PKEY);
234 
235 			switch (i) {
236 				/*
237 				 * If there was anything special to do for
238 				 * certain types of keys, we'd do it here.
239 				 * (Nothing at the moment, I think.)
240 				 */
241 
242 			case SSL_PKEY_RSA:
243 				/* We have an RSA key. */
244 				break;
245 
246 			case SSL_PKEY_ECC:
247 				/* We have an ECC key */
248 				break;
249 
250 			case SSL_PKEY_GOST01:
251 				/* We have a GOST key */
252 				break;
253 
254 			default:
255 				/* Can't happen. */
256 				SSLerrorx(SSL_R_LIBRARY_BUG);
257 			}
258 		}
259 
260 		if (cert->pkeys[i].chain != NULL) {
261 			if ((ret->pkeys[i].chain =
262 			    X509_chain_up_ref(cert->pkeys[i].chain)) == NULL)
263 				goto err;
264 		}
265 	}
266 
267 	/*
268 	 * ret->extra_certs *should* exist, but currently the own certificate
269 	 * chain is held inside SSL_CTX
270 	 */
271 
272 	ret->references = 1;
273 
274 	return (ret);
275 
276  err:
277 	DH_free(ret->dh_tmp);
278 
279 	for (i = 0; i < SSL_PKEY_NUM; i++) {
280 		X509_free(ret->pkeys[i].x509);
281 		EVP_PKEY_free(ret->pkeys[i].privatekey);
282 		sk_X509_pop_free(ret->pkeys[i].chain, X509_free);
283 	}
284 	free (ret);
285 	return NULL;
286 }
287 
288 
289 void
290 ssl_cert_free(CERT *c)
291 {
292 	int i;
293 
294 	if (c == NULL)
295 		return;
296 
297 	i = CRYPTO_add(&c->references, -1, CRYPTO_LOCK_SSL_CERT);
298 	if (i > 0)
299 		return;
300 
301 	DH_free(c->dh_tmp);
302 
303 	for (i = 0; i < SSL_PKEY_NUM; i++) {
304 		X509_free(c->pkeys[i].x509);
305 		EVP_PKEY_free(c->pkeys[i].privatekey);
306 		sk_X509_pop_free(c->pkeys[i].chain, X509_free);
307 	}
308 
309 	free(c);
310 }
311 
312 int
313 ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain)
314 {
315 	if (c->key == NULL)
316 		return 0;
317 
318 	sk_X509_pop_free(c->key->chain, X509_free);
319 	c->key->chain = chain;
320 
321 	return 1;
322 }
323 
324 int
325 ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain)
326 {
327 	STACK_OF(X509) *new_chain = NULL;
328 
329 	if (chain != NULL) {
330 		if ((new_chain = X509_chain_up_ref(chain)) == NULL)
331 			return 0;
332 	}
333 	if (!ssl_cert_set0_chain(c, new_chain)) {
334 		sk_X509_pop_free(new_chain, X509_free);
335 		return 0;
336 	}
337 
338 	return 1;
339 }
340 
341 int
342 ssl_cert_add0_chain_cert(CERT *c, X509 *cert)
343 {
344 	if (c->key == NULL)
345 		return 0;
346 
347 	if (c->key->chain == NULL) {
348 		if ((c->key->chain = sk_X509_new_null()) == NULL)
349 			return 0;
350 	}
351 	if (!sk_X509_push(c->key->chain, cert))
352 		return 0;
353 
354 	return 1;
355 }
356 
357 int
358 ssl_cert_add1_chain_cert(CERT *c, X509 *cert)
359 {
360 	if (!ssl_cert_add0_chain_cert(c, cert))
361 		return 0;
362 
363 	X509_up_ref(cert);
364 
365 	return 1;
366 }
367 
368 SESS_CERT *
369 ssl_sess_cert_new(void)
370 {
371 	SESS_CERT *ret;
372 
373 	ret = calloc(1, sizeof *ret);
374 	if (ret == NULL) {
375 		SSLerrorx(ERR_R_MALLOC_FAILURE);
376 		return NULL;
377 	}
378 	ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA]);
379 	ret->references = 1;
380 
381 	return ret;
382 }
383 
384 void
385 ssl_sess_cert_free(SESS_CERT *sc)
386 {
387 	int i;
388 
389 	if (sc == NULL)
390 		return;
391 
392 	i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT);
393 	if (i > 0)
394 		return;
395 
396 	sk_X509_pop_free(sc->cert_chain, X509_free);
397 	for (i = 0; i < SSL_PKEY_NUM; i++)
398 		X509_free(sc->peer_pkeys[i].x509);
399 
400 	DH_free(sc->peer_dh_tmp);
401 	EC_KEY_free(sc->peer_ecdh_tmp);
402 	free(sc->peer_x25519_tmp);
403 
404 	free(sc);
405 }
406 
407 int
408 ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
409 {
410 	X509_STORE_CTX *ctx = NULL;
411 	X509 *x;
412 	int ret = 0;
413 
414 	if ((sk == NULL) || (sk_X509_num(sk) == 0))
415 		goto err;
416 
417 	if ((ctx = X509_STORE_CTX_new()) == NULL)
418 		goto err;
419 
420 	x = sk_X509_value(sk, 0);
421 	if (!X509_STORE_CTX_init(ctx, s->ctx->cert_store, x, sk)) {
422 		SSLerror(s, ERR_R_X509_LIB);
423 		goto err;
424 	}
425 	X509_STORE_CTX_set_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s);
426 
427 	/*
428 	 * We need to inherit the verify parameters. These can be
429 	 * determined by the context: if its a server it will verify
430 	 * SSL client certificates or vice versa.
431 	 */
432 	X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server");
433 
434 	/*
435 	 * Anything non-default in "param" should overwrite anything
436 	 * in the ctx.
437 	 */
438 	X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(ctx), s->param);
439 
440 	if (s->internal->verify_callback)
441 		X509_STORE_CTX_set_verify_cb(ctx, s->internal->verify_callback);
442 
443 	if (s->ctx->internal->app_verify_callback != NULL)
444 		ret = s->ctx->internal->app_verify_callback(ctx,
445 		    s->ctx->internal->app_verify_arg);
446 	else
447 		ret = X509_verify_cert(ctx);
448 
449 	s->verify_result = X509_STORE_CTX_get_error(ctx);
450 	sk_X509_pop_free(s->internal->verified_chain, X509_free);
451 	s->internal->verified_chain = NULL;
452 	if (X509_STORE_CTX_get0_chain(ctx) != NULL) {
453 		s->internal->verified_chain = X509_STORE_CTX_get1_chain(ctx);
454 		if (s->internal->verified_chain == NULL) {
455 			SSLerrorx(ERR_R_MALLOC_FAILURE);
456 			ret = 0;
457 		}
458 	}
459 
460  err:
461 	X509_STORE_CTX_free(ctx);
462 
463 	return (ret);
464 }
465 
466 static void
467 set_client_CA_list(STACK_OF(X509_NAME) **ca_list,
468     STACK_OF(X509_NAME) *name_list)
469 {
470 	sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
471 	*ca_list = name_list;
472 }
473 
474 STACK_OF(X509_NAME) *
475 SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk)
476 {
477 	int i;
478 	STACK_OF(X509_NAME) *ret;
479 	X509_NAME *name = NULL;
480 
481 	if ((ret = sk_X509_NAME_new_null()) == NULL)
482 		goto err;
483 
484 	for (i = 0; i < sk_X509_NAME_num(sk); i++) {
485 		if ((name = X509_NAME_dup(sk_X509_NAME_value(sk, i))) == NULL)
486 			goto err;
487 		if (!sk_X509_NAME_push(ret, name))
488 			goto err;
489 	}
490 	return (ret);
491 
492  err:
493 	X509_NAME_free(name);
494 	sk_X509_NAME_pop_free(ret, X509_NAME_free);
495 	return NULL;
496 }
497 
498 void
499 SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
500 {
501 	set_client_CA_list(&(s->internal->client_CA), name_list);
502 }
503 
504 void
505 SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
506 {
507 	set_client_CA_list(&(ctx->internal->client_CA), name_list);
508 }
509 
510 STACK_OF(X509_NAME) *
511 SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
512 {
513 	return (ctx->internal->client_CA);
514 }
515 
516 STACK_OF(X509_NAME) *
517 SSL_get_client_CA_list(const SSL *s)
518 {
519 	if (!s->server) {
520 		/* We are in the client. */
521 		if ((s->version >> 8) == SSL3_VERSION_MAJOR)
522 			return (S3I(s)->hs.tls12.ca_names);
523 		else
524 			return (NULL);
525 	} else {
526 		if (s->internal->client_CA != NULL)
527 			return (s->internal->client_CA);
528 		else
529 			return (s->ctx->internal->client_CA);
530 	}
531 }
532 
533 static int
534 add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x)
535 {
536 	X509_NAME *name;
537 
538 	if (x == NULL)
539 		return (0);
540 	if ((*sk == NULL) && ((*sk = sk_X509_NAME_new_null()) == NULL))
541 		return (0);
542 
543 	if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL)
544 		return (0);
545 
546 	if (!sk_X509_NAME_push(*sk, name)) {
547 		X509_NAME_free(name);
548 		return (0);
549 	}
550 	return (1);
551 }
552 
553 int
554 SSL_add_client_CA(SSL *ssl, X509 *x)
555 {
556 	return (add_client_CA(&(ssl->internal->client_CA), x));
557 }
558 
559 int
560 SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
561 {
562 	return (add_client_CA(&(ctx->internal->client_CA), x));
563 }
564 
565 static int
566 xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
567 {
568 	return (X509_NAME_cmp(*a, *b));
569 }
570 
571 /*!
572  * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
573  * it doesn't really have anything to do with clients (except that a common use
574  * for a stack of CAs is to send it to the client). Actually, it doesn't have
575  * much to do with CAs, either, since it will load any old cert.
576  * \param file the file containing one or more certs.
577  * \return a ::STACK containing the certs.
578  */
579 STACK_OF(X509_NAME) *
580 SSL_load_client_CA_file(const char *file)
581 {
582 	BIO *in;
583 	X509 *x = NULL;
584 	X509_NAME *xn = NULL;
585 	STACK_OF(X509_NAME) *ret = NULL, *sk;
586 
587 	sk = sk_X509_NAME_new(xname_cmp);
588 
589 	in = BIO_new(BIO_s_file_internal());
590 
591 	if ((sk == NULL) || (in == NULL)) {
592 		SSLerrorx(ERR_R_MALLOC_FAILURE);
593 		goto err;
594 	}
595 
596 	if (!BIO_read_filename(in, file))
597 		goto err;
598 
599 	for (;;) {
600 		if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
601 			break;
602 		if (ret == NULL) {
603 			ret = sk_X509_NAME_new_null();
604 			if (ret == NULL) {
605 				SSLerrorx(ERR_R_MALLOC_FAILURE);
606 				goto err;
607 			}
608 		}
609 		if ((xn = X509_get_subject_name(x)) == NULL)
610 			goto err;
611 		/* check for duplicates */
612 		xn = X509_NAME_dup(xn);
613 		if (xn == NULL)
614 			goto err;
615 		if (sk_X509_NAME_find(sk, xn) >= 0)
616 			X509_NAME_free(xn);
617 		else {
618 			sk_X509_NAME_push(sk, xn);
619 			sk_X509_NAME_push(ret, xn);
620 		}
621 	}
622 
623 	if (0) {
624  err:
625 		sk_X509_NAME_pop_free(ret, X509_NAME_free);
626 		ret = NULL;
627 	}
628 	sk_X509_NAME_free(sk);
629 	BIO_free(in);
630 	X509_free(x);
631 	if (ret != NULL)
632 		ERR_clear_error();
633 
634 	return (ret);
635 }
636 
637 /*!
638  * Add a file of certs to a stack.
639  * \param stack the stack to add to.
640  * \param file the file to add from. All certs in this file that are not
641  * already in the stack will be added.
642  * \return 1 for success, 0 for failure. Note that in the case of failure some
643  * certs may have been added to \c stack.
644  */
645 
646 int
647 SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
648     const char *file)
649 {
650 	BIO *in;
651 	X509 *x = NULL;
652 	X509_NAME *xn = NULL;
653 	int ret = 1;
654 	int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b);
655 
656 	oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp);
657 
658 	in = BIO_new(BIO_s_file_internal());
659 
660 	if (in == NULL) {
661 		SSLerrorx(ERR_R_MALLOC_FAILURE);
662 		goto err;
663 	}
664 
665 	if (!BIO_read_filename(in, file))
666 		goto err;
667 
668 	for (;;) {
669 		if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
670 			break;
671 		if ((xn = X509_get_subject_name(x)) == NULL)
672 			goto err;
673 		xn = X509_NAME_dup(xn);
674 		if (xn == NULL)
675 			goto err;
676 		if (sk_X509_NAME_find(stack, xn) >= 0)
677 			X509_NAME_free(xn);
678 		else
679 			sk_X509_NAME_push(stack, xn);
680 	}
681 
682 	ERR_clear_error();
683 
684 	if (0) {
685  err:
686 		ret = 0;
687 	}
688 	BIO_free(in);
689 	X509_free(x);
690 
691 	(void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
692 
693 	return ret;
694 }
695 
696 /*!
697  * Add a directory of certs to a stack.
698  * \param stack the stack to append to.
699  * \param dir the directory to append from. All files in this directory will be
700  * examined as potential certs. Any that are acceptable to
701  * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will
702  * be included.
703  * \return 1 for success, 0 for failure. Note that in the case of failure some
704  * certs may have been added to \c stack.
705  */
706 
707 int
708 SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, const char *dir)
709 {
710 	DIR *dirp = NULL;
711 	char *path = NULL;
712 	int ret = 0;
713 
714 	dirp = opendir(dir);
715 	if (dirp) {
716 		struct dirent *dp;
717 		while ((dp = readdir(dirp)) != NULL) {
718 			if (asprintf(&path, "%s/%s", dir, dp->d_name) != -1) {
719 				ret = SSL_add_file_cert_subjects_to_stack(
720 				    stack, path);
721 				free(path);
722 			}
723 			if (!ret)
724 				break;
725 		}
726 		(void) closedir(dirp);
727 	}
728 	if (!ret) {
729  		SYSerror(errno);
730 		ERR_asprintf_error_data("opendir ('%s')", dir);
731 		SSLerrorx(ERR_R_SYS_LIB);
732 	}
733 	return ret;
734 }
735