1*cca6fc52SDaniel Fojt /* $OpenBSD: ssl_cert.c,v 1.76 2019/05/15 09:13:16 bcook Exp $ */ 2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3f5b1c8a1SJohn Marino * All rights reserved. 4f5b1c8a1SJohn Marino * 5f5b1c8a1SJohn Marino * This package is an SSL implementation written 6f5b1c8a1SJohn Marino * by Eric Young (eay@cryptsoft.com). 7f5b1c8a1SJohn Marino * The implementation was written so as to conform with Netscapes SSL. 8f5b1c8a1SJohn Marino * 9f5b1c8a1SJohn Marino * This library is free for commercial and non-commercial use as long as 10f5b1c8a1SJohn Marino * the following conditions are aheared to. The following conditions 11f5b1c8a1SJohn Marino * apply to all code found in this distribution, be it the RC4, RSA, 12f5b1c8a1SJohn Marino * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13f5b1c8a1SJohn Marino * included with this distribution is covered by the same copyright terms 14f5b1c8a1SJohn Marino * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15f5b1c8a1SJohn Marino * 16f5b1c8a1SJohn Marino * Copyright remains Eric Young's, and as such any Copyright notices in 17f5b1c8a1SJohn Marino * the code are not to be removed. 18f5b1c8a1SJohn Marino * If this package is used in a product, Eric Young should be given attribution 19f5b1c8a1SJohn Marino * as the author of the parts of the library used. 20f5b1c8a1SJohn Marino * This can be in the form of a textual message at program startup or 21f5b1c8a1SJohn Marino * in documentation (online or textual) provided with the package. 22f5b1c8a1SJohn Marino * 23f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without 24f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions 25f5b1c8a1SJohn Marino * are met: 26f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the copyright 27f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer. 28f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 29f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in the 30f5b1c8a1SJohn Marino * documentation and/or other materials provided with the distribution. 31f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this software 32f5b1c8a1SJohn Marino * must display the following acknowledgement: 33f5b1c8a1SJohn Marino * "This product includes cryptographic software written by 34f5b1c8a1SJohn Marino * Eric Young (eay@cryptsoft.com)" 35f5b1c8a1SJohn Marino * The word 'cryptographic' can be left out if the rouines from the library 36f5b1c8a1SJohn Marino * being used are not cryptographic related :-). 37f5b1c8a1SJohn Marino * 4. If you include any Windows specific code (or a derivative thereof) from 38f5b1c8a1SJohn Marino * the apps directory (application code) you must include an acknowledgement: 39f5b1c8a1SJohn Marino * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40f5b1c8a1SJohn Marino * 41f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42f5b1c8a1SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44f5b1c8a1SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45f5b1c8a1SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46f5b1c8a1SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47f5b1c8a1SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49f5b1c8a1SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50f5b1c8a1SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51f5b1c8a1SJohn Marino * SUCH DAMAGE. 52f5b1c8a1SJohn Marino * 53f5b1c8a1SJohn Marino * The licence and distribution terms for any publically available version or 54f5b1c8a1SJohn Marino * derivative of this code cannot be changed. i.e. this code cannot simply be 55f5b1c8a1SJohn Marino * copied and put under another distribution licence 56f5b1c8a1SJohn Marino * [including the GNU Public Licence.] 57f5b1c8a1SJohn Marino */ 58f5b1c8a1SJohn Marino /* ==================================================================== 59f5b1c8a1SJohn Marino * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. 60f5b1c8a1SJohn Marino * 61f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without 62f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions 63f5b1c8a1SJohn Marino * are met: 64f5b1c8a1SJohn Marino * 65f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the above copyright 66f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer. 67f5b1c8a1SJohn Marino * 68f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 69f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in 70f5b1c8a1SJohn Marino * the documentation and/or other materials provided with the 71f5b1c8a1SJohn Marino * distribution. 72f5b1c8a1SJohn Marino * 73f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this 74f5b1c8a1SJohn Marino * software must display the following acknowledgment: 75f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project 76f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77f5b1c8a1SJohn Marino * 78f5b1c8a1SJohn Marino * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79f5b1c8a1SJohn Marino * endorse or promote products derived from this software without 80f5b1c8a1SJohn Marino * prior written permission. For written permission, please contact 81f5b1c8a1SJohn Marino * openssl-core@openssl.org. 82f5b1c8a1SJohn Marino * 83f5b1c8a1SJohn Marino * 5. Products derived from this software may not be called "OpenSSL" 84f5b1c8a1SJohn Marino * nor may "OpenSSL" appear in their names without prior written 85f5b1c8a1SJohn Marino * permission of the OpenSSL Project. 86f5b1c8a1SJohn Marino * 87f5b1c8a1SJohn Marino * 6. Redistributions of any form whatsoever must retain the following 88f5b1c8a1SJohn Marino * acknowledgment: 89f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project 90f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 91f5b1c8a1SJohn Marino * 92f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 93f5b1c8a1SJohn Marino * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 95f5b1c8a1SJohn Marino * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 96f5b1c8a1SJohn Marino * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 97f5b1c8a1SJohn Marino * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 98f5b1c8a1SJohn Marino * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 99f5b1c8a1SJohn Marino * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 101f5b1c8a1SJohn Marino * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102f5b1c8a1SJohn Marino * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 103f5b1c8a1SJohn Marino * OF THE POSSIBILITY OF SUCH DAMAGE. 104f5b1c8a1SJohn Marino * ==================================================================== 105f5b1c8a1SJohn Marino * 106f5b1c8a1SJohn Marino * This product includes cryptographic software written by Eric Young 107f5b1c8a1SJohn Marino * (eay@cryptsoft.com). This product includes software written by Tim 108f5b1c8a1SJohn Marino * Hudson (tjh@cryptsoft.com). 109f5b1c8a1SJohn Marino * 110f5b1c8a1SJohn Marino */ 111f5b1c8a1SJohn Marino /* ==================================================================== 112f5b1c8a1SJohn Marino * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 113f5b1c8a1SJohn Marino * ECC cipher suite support in OpenSSL originally developed by 114f5b1c8a1SJohn Marino * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. 115f5b1c8a1SJohn Marino */ 116f5b1c8a1SJohn Marino 117f5b1c8a1SJohn Marino #include <sys/types.h> 118f5b1c8a1SJohn Marino 119f5b1c8a1SJohn Marino #include <dirent.h> 120f5b1c8a1SJohn Marino #include <stdio.h> 121f5b1c8a1SJohn Marino #include <unistd.h> 122f5b1c8a1SJohn Marino 123f5b1c8a1SJohn Marino #include <openssl/bio.h> 124f5b1c8a1SJohn Marino #include <openssl/bn.h> 125f5b1c8a1SJohn Marino #include <openssl/dh.h> 126f5b1c8a1SJohn Marino #include <openssl/objects.h> 127f5b1c8a1SJohn Marino #include <openssl/opensslconf.h> 128f5b1c8a1SJohn Marino #include <openssl/pem.h> 129f5b1c8a1SJohn Marino #include <openssl/x509v3.h> 130f5b1c8a1SJohn Marino 131f5b1c8a1SJohn Marino #include "ssl_locl.h" 132f5b1c8a1SJohn Marino 133f5b1c8a1SJohn Marino int 134f5b1c8a1SJohn Marino SSL_get_ex_data_X509_STORE_CTX_idx(void) 135f5b1c8a1SJohn Marino { 136f5b1c8a1SJohn Marino static volatile int ssl_x509_store_ctx_idx = -1; 137f5b1c8a1SJohn Marino int got_write_lock = 0; 138f5b1c8a1SJohn Marino 139f5b1c8a1SJohn Marino CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); 140f5b1c8a1SJohn Marino 141f5b1c8a1SJohn Marino if (ssl_x509_store_ctx_idx < 0) { 142f5b1c8a1SJohn Marino CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); 143f5b1c8a1SJohn Marino CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); 144f5b1c8a1SJohn Marino got_write_lock = 1; 145f5b1c8a1SJohn Marino 146f5b1c8a1SJohn Marino if (ssl_x509_store_ctx_idx < 0) { 147f5b1c8a1SJohn Marino ssl_x509_store_ctx_idx = 148f5b1c8a1SJohn Marino X509_STORE_CTX_get_ex_new_index( 149f5b1c8a1SJohn Marino 0, "SSL for verify callback", NULL, NULL, NULL); 150f5b1c8a1SJohn Marino } 151f5b1c8a1SJohn Marino } 152f5b1c8a1SJohn Marino 153f5b1c8a1SJohn Marino if (got_write_lock) 154f5b1c8a1SJohn Marino CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); 155f5b1c8a1SJohn Marino else 156f5b1c8a1SJohn Marino CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); 157f5b1c8a1SJohn Marino 158f5b1c8a1SJohn Marino return ssl_x509_store_ctx_idx; 159f5b1c8a1SJohn Marino } 160f5b1c8a1SJohn Marino 161f5b1c8a1SJohn Marino CERT * 162f5b1c8a1SJohn Marino ssl_cert_new(void) 163f5b1c8a1SJohn Marino { 164f5b1c8a1SJohn Marino CERT *ret; 165f5b1c8a1SJohn Marino 166f5b1c8a1SJohn Marino ret = calloc(1, sizeof(CERT)); 167f5b1c8a1SJohn Marino if (ret == NULL) { 16872c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE); 169f5b1c8a1SJohn Marino return (NULL); 170f5b1c8a1SJohn Marino } 171f5b1c8a1SJohn Marino ret->key = &(ret->pkeys[SSL_PKEY_RSA_ENC]); 172f5b1c8a1SJohn Marino ret->references = 1; 173f5b1c8a1SJohn Marino return (ret); 174f5b1c8a1SJohn Marino } 175f5b1c8a1SJohn Marino 176f5b1c8a1SJohn Marino CERT * 177f5b1c8a1SJohn Marino ssl_cert_dup(CERT *cert) 178f5b1c8a1SJohn Marino { 179f5b1c8a1SJohn Marino CERT *ret; 180f5b1c8a1SJohn Marino int i; 181f5b1c8a1SJohn Marino 182f5b1c8a1SJohn Marino ret = calloc(1, sizeof(CERT)); 183f5b1c8a1SJohn Marino if (ret == NULL) { 18472c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE); 185f5b1c8a1SJohn Marino return (NULL); 186f5b1c8a1SJohn Marino } 187f5b1c8a1SJohn Marino 188f5b1c8a1SJohn Marino /* 189f5b1c8a1SJohn Marino * same as ret->key = ret->pkeys + (cert->key - cert->pkeys), 190f5b1c8a1SJohn Marino * if you find that more readable 191f5b1c8a1SJohn Marino */ 192f5b1c8a1SJohn Marino ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; 193f5b1c8a1SJohn Marino 194f5b1c8a1SJohn Marino ret->valid = cert->valid; 195f5b1c8a1SJohn Marino ret->mask_k = cert->mask_k; 196f5b1c8a1SJohn Marino ret->mask_a = cert->mask_a; 197f5b1c8a1SJohn Marino 198f5b1c8a1SJohn Marino if (cert->dh_tmp != NULL) { 199f5b1c8a1SJohn Marino ret->dh_tmp = DHparams_dup(cert->dh_tmp); 200f5b1c8a1SJohn Marino if (ret->dh_tmp == NULL) { 20172c33676SMaxim Ag SSLerrorx(ERR_R_DH_LIB); 202f5b1c8a1SJohn Marino goto err; 203f5b1c8a1SJohn Marino } 204f5b1c8a1SJohn Marino if (cert->dh_tmp->priv_key) { 205f5b1c8a1SJohn Marino BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); 206f5b1c8a1SJohn Marino if (!b) { 20772c33676SMaxim Ag SSLerrorx(ERR_R_BN_LIB); 208f5b1c8a1SJohn Marino goto err; 209f5b1c8a1SJohn Marino } 210f5b1c8a1SJohn Marino ret->dh_tmp->priv_key = b; 211f5b1c8a1SJohn Marino } 212f5b1c8a1SJohn Marino if (cert->dh_tmp->pub_key) { 213f5b1c8a1SJohn Marino BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); 214f5b1c8a1SJohn Marino if (!b) { 21572c33676SMaxim Ag SSLerrorx(ERR_R_BN_LIB); 216f5b1c8a1SJohn Marino goto err; 217f5b1c8a1SJohn Marino } 218f5b1c8a1SJohn Marino ret->dh_tmp->pub_key = b; 219f5b1c8a1SJohn Marino } 220f5b1c8a1SJohn Marino } 221f5b1c8a1SJohn Marino ret->dh_tmp_cb = cert->dh_tmp_cb; 222f5b1c8a1SJohn Marino ret->dh_tmp_auto = cert->dh_tmp_auto; 223f5b1c8a1SJohn Marino 224f5b1c8a1SJohn Marino for (i = 0; i < SSL_PKEY_NUM; i++) { 225f5b1c8a1SJohn Marino if (cert->pkeys[i].x509 != NULL) { 226f5b1c8a1SJohn Marino ret->pkeys[i].x509 = cert->pkeys[i].x509; 227f5b1c8a1SJohn Marino CRYPTO_add(&ret->pkeys[i].x509->references, 1, 228f5b1c8a1SJohn Marino CRYPTO_LOCK_X509); 229f5b1c8a1SJohn Marino } 230f5b1c8a1SJohn Marino 231f5b1c8a1SJohn Marino if (cert->pkeys[i].privatekey != NULL) { 232f5b1c8a1SJohn Marino ret->pkeys[i].privatekey = cert->pkeys[i].privatekey; 233f5b1c8a1SJohn Marino CRYPTO_add(&ret->pkeys[i].privatekey->references, 1, 234f5b1c8a1SJohn Marino CRYPTO_LOCK_EVP_PKEY); 235f5b1c8a1SJohn Marino 236f5b1c8a1SJohn Marino switch (i) { 237f5b1c8a1SJohn Marino /* 238f5b1c8a1SJohn Marino * If there was anything special to do for 239f5b1c8a1SJohn Marino * certain types of keys, we'd do it here. 240f5b1c8a1SJohn Marino * (Nothing at the moment, I think.) 241f5b1c8a1SJohn Marino */ 242f5b1c8a1SJohn Marino 243f5b1c8a1SJohn Marino case SSL_PKEY_RSA_ENC: 244f5b1c8a1SJohn Marino case SSL_PKEY_RSA_SIGN: 245f5b1c8a1SJohn Marino /* We have an RSA key. */ 246f5b1c8a1SJohn Marino break; 247f5b1c8a1SJohn Marino 248f5b1c8a1SJohn Marino case SSL_PKEY_DH_RSA: 249f5b1c8a1SJohn Marino /* We have a DH key. */ 250f5b1c8a1SJohn Marino break; 251f5b1c8a1SJohn Marino 252f5b1c8a1SJohn Marino case SSL_PKEY_ECC: 253f5b1c8a1SJohn Marino /* We have an ECC key */ 254f5b1c8a1SJohn Marino break; 255f5b1c8a1SJohn Marino 256f5b1c8a1SJohn Marino default: 257f5b1c8a1SJohn Marino /* Can't happen. */ 25872c33676SMaxim Ag SSLerrorx(SSL_R_LIBRARY_BUG); 259f5b1c8a1SJohn Marino } 260f5b1c8a1SJohn Marino } 26172c33676SMaxim Ag 26272c33676SMaxim Ag if (cert->pkeys[i].chain != NULL) { 26372c33676SMaxim Ag if ((ret->pkeys[i].chain = 26472c33676SMaxim Ag X509_chain_up_ref(cert->pkeys[i].chain)) == NULL) 26572c33676SMaxim Ag goto err; 26672c33676SMaxim Ag } 267f5b1c8a1SJohn Marino } 268f5b1c8a1SJohn Marino 269f5b1c8a1SJohn Marino /* 270f5b1c8a1SJohn Marino * ret->extra_certs *should* exist, but currently the own certificate 271f5b1c8a1SJohn Marino * chain is held inside SSL_CTX 272f5b1c8a1SJohn Marino */ 273f5b1c8a1SJohn Marino 274f5b1c8a1SJohn Marino ret->references = 1; 275f5b1c8a1SJohn Marino 276f5b1c8a1SJohn Marino return (ret); 277f5b1c8a1SJohn Marino 278f5b1c8a1SJohn Marino err: 279f5b1c8a1SJohn Marino DH_free(ret->dh_tmp); 280f5b1c8a1SJohn Marino 281f5b1c8a1SJohn Marino for (i = 0; i < SSL_PKEY_NUM; i++) { 282f5b1c8a1SJohn Marino X509_free(ret->pkeys[i].x509); 283f5b1c8a1SJohn Marino EVP_PKEY_free(ret->pkeys[i].privatekey); 28472c33676SMaxim Ag sk_X509_pop_free(ret->pkeys[i].chain, X509_free); 285f5b1c8a1SJohn Marino } 286f5b1c8a1SJohn Marino free (ret); 287f5b1c8a1SJohn Marino return NULL; 288f5b1c8a1SJohn Marino } 289f5b1c8a1SJohn Marino 290f5b1c8a1SJohn Marino 291f5b1c8a1SJohn Marino void 292f5b1c8a1SJohn Marino ssl_cert_free(CERT *c) 293f5b1c8a1SJohn Marino { 294f5b1c8a1SJohn Marino int i; 295f5b1c8a1SJohn Marino 296f5b1c8a1SJohn Marino if (c == NULL) 297f5b1c8a1SJohn Marino return; 298f5b1c8a1SJohn Marino 299f5b1c8a1SJohn Marino i = CRYPTO_add(&c->references, -1, CRYPTO_LOCK_SSL_CERT); 300f5b1c8a1SJohn Marino if (i > 0) 301f5b1c8a1SJohn Marino return; 302f5b1c8a1SJohn Marino 303f5b1c8a1SJohn Marino DH_free(c->dh_tmp); 304f5b1c8a1SJohn Marino 305f5b1c8a1SJohn Marino for (i = 0; i < SSL_PKEY_NUM; i++) { 306f5b1c8a1SJohn Marino X509_free(c->pkeys[i].x509); 307f5b1c8a1SJohn Marino EVP_PKEY_free(c->pkeys[i].privatekey); 30872c33676SMaxim Ag sk_X509_pop_free(c->pkeys[i].chain, X509_free); 309f5b1c8a1SJohn Marino } 310f5b1c8a1SJohn Marino 311f5b1c8a1SJohn Marino free(c); 312f5b1c8a1SJohn Marino } 313f5b1c8a1SJohn Marino 314f5b1c8a1SJohn Marino int 31572c33676SMaxim Ag ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain) 316f5b1c8a1SJohn Marino { 31772c33676SMaxim Ag if (c->key == NULL) 31872c33676SMaxim Ag return 0; 319f5b1c8a1SJohn Marino 32072c33676SMaxim Ag sk_X509_pop_free(c->key->chain, X509_free); 32172c33676SMaxim Ag c->key->chain = chain; 32272c33676SMaxim Ag 32372c33676SMaxim Ag return 1; 324f5b1c8a1SJohn Marino } 325f5b1c8a1SJohn Marino 32672c33676SMaxim Ag int 32772c33676SMaxim Ag ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain) 32872c33676SMaxim Ag { 32972c33676SMaxim Ag STACK_OF(X509) *new_chain = NULL; 33072c33676SMaxim Ag 33172c33676SMaxim Ag if (chain != NULL) { 33272c33676SMaxim Ag if ((new_chain = X509_chain_up_ref(chain)) == NULL) 33372c33676SMaxim Ag return 0; 33472c33676SMaxim Ag } 33572c33676SMaxim Ag if (!ssl_cert_set0_chain(c, new_chain)) { 33672c33676SMaxim Ag sk_X509_pop_free(new_chain, X509_free); 33772c33676SMaxim Ag return 0; 33872c33676SMaxim Ag } 33972c33676SMaxim Ag 34072c33676SMaxim Ag return 1; 34172c33676SMaxim Ag } 34272c33676SMaxim Ag 34372c33676SMaxim Ag int 34472c33676SMaxim Ag ssl_cert_add0_chain_cert(CERT *c, X509 *cert) 34572c33676SMaxim Ag { 34672c33676SMaxim Ag if (c->key == NULL) 34772c33676SMaxim Ag return 0; 34872c33676SMaxim Ag 34972c33676SMaxim Ag if (c->key->chain == NULL) { 35072c33676SMaxim Ag if ((c->key->chain = sk_X509_new_null()) == NULL) 35172c33676SMaxim Ag return 0; 35272c33676SMaxim Ag } 35372c33676SMaxim Ag if (!sk_X509_push(c->key->chain, cert)) 35472c33676SMaxim Ag return 0; 35572c33676SMaxim Ag 35672c33676SMaxim Ag return 1; 35772c33676SMaxim Ag } 35872c33676SMaxim Ag 35972c33676SMaxim Ag int 36072c33676SMaxim Ag ssl_cert_add1_chain_cert(CERT *c, X509 *cert) 36172c33676SMaxim Ag { 36272c33676SMaxim Ag if (!ssl_cert_add0_chain_cert(c, cert)) 36372c33676SMaxim Ag return 0; 36472c33676SMaxim Ag 36572c33676SMaxim Ag X509_up_ref(cert); 36672c33676SMaxim Ag 36772c33676SMaxim Ag return 1; 36872c33676SMaxim Ag } 369f5b1c8a1SJohn Marino 370f5b1c8a1SJohn Marino SESS_CERT * 371f5b1c8a1SJohn Marino ssl_sess_cert_new(void) 372f5b1c8a1SJohn Marino { 373f5b1c8a1SJohn Marino SESS_CERT *ret; 374f5b1c8a1SJohn Marino 375f5b1c8a1SJohn Marino ret = calloc(1, sizeof *ret); 376f5b1c8a1SJohn Marino if (ret == NULL) { 37772c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE); 378f5b1c8a1SJohn Marino return NULL; 379f5b1c8a1SJohn Marino } 380f5b1c8a1SJohn Marino ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]); 381f5b1c8a1SJohn Marino ret->references = 1; 382f5b1c8a1SJohn Marino 383f5b1c8a1SJohn Marino return ret; 384f5b1c8a1SJohn Marino } 385f5b1c8a1SJohn Marino 386f5b1c8a1SJohn Marino void 387f5b1c8a1SJohn Marino ssl_sess_cert_free(SESS_CERT *sc) 388f5b1c8a1SJohn Marino { 389f5b1c8a1SJohn Marino int i; 390f5b1c8a1SJohn Marino 391f5b1c8a1SJohn Marino if (sc == NULL) 392f5b1c8a1SJohn Marino return; 393f5b1c8a1SJohn Marino 394f5b1c8a1SJohn Marino i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT); 395f5b1c8a1SJohn Marino if (i > 0) 396f5b1c8a1SJohn Marino return; 397f5b1c8a1SJohn Marino 398f5b1c8a1SJohn Marino sk_X509_pop_free(sc->cert_chain, X509_free); 399f5b1c8a1SJohn Marino for (i = 0; i < SSL_PKEY_NUM; i++) 400f5b1c8a1SJohn Marino X509_free(sc->peer_pkeys[i].x509); 401f5b1c8a1SJohn Marino 402f5b1c8a1SJohn Marino DH_free(sc->peer_dh_tmp); 403f5b1c8a1SJohn Marino EC_KEY_free(sc->peer_ecdh_tmp); 40472c33676SMaxim Ag free(sc->peer_x25519_tmp); 405f5b1c8a1SJohn Marino 406f5b1c8a1SJohn Marino free(sc); 407f5b1c8a1SJohn Marino } 408f5b1c8a1SJohn Marino 409f5b1c8a1SJohn Marino int 410f5b1c8a1SJohn Marino ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk) 411f5b1c8a1SJohn Marino { 412f5b1c8a1SJohn Marino X509_STORE_CTX ctx; 413f5b1c8a1SJohn Marino X509 *x; 414f5b1c8a1SJohn Marino int ret; 415f5b1c8a1SJohn Marino 416f5b1c8a1SJohn Marino if ((sk == NULL) || (sk_X509_num(sk) == 0)) 417f5b1c8a1SJohn Marino return (0); 418f5b1c8a1SJohn Marino 419f5b1c8a1SJohn Marino x = sk_X509_value(sk, 0); 420f5b1c8a1SJohn Marino if (!X509_STORE_CTX_init(&ctx, s->ctx->cert_store, x, sk)) { 42172c33676SMaxim Ag SSLerror(s, ERR_R_X509_LIB); 422f5b1c8a1SJohn Marino return (0); 423f5b1c8a1SJohn Marino } 424f5b1c8a1SJohn Marino X509_STORE_CTX_set_ex_data(&ctx, 425f5b1c8a1SJohn Marino SSL_get_ex_data_X509_STORE_CTX_idx(), s); 426f5b1c8a1SJohn Marino 427f5b1c8a1SJohn Marino /* 428f5b1c8a1SJohn Marino * We need to inherit the verify parameters. These can be 429f5b1c8a1SJohn Marino * determined by the context: if its a server it will verify 430f5b1c8a1SJohn Marino * SSL client certificates or vice versa. 431f5b1c8a1SJohn Marino */ 432f5b1c8a1SJohn Marino X509_STORE_CTX_set_default(&ctx, 433f5b1c8a1SJohn Marino s->server ? "ssl_client" : "ssl_server"); 434f5b1c8a1SJohn Marino 435f5b1c8a1SJohn Marino /* 436f5b1c8a1SJohn Marino * Anything non-default in "param" should overwrite anything 437f5b1c8a1SJohn Marino * in the ctx. 438f5b1c8a1SJohn Marino */ 439f5b1c8a1SJohn Marino X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param); 440f5b1c8a1SJohn Marino 44172c33676SMaxim Ag if (s->internal->verify_callback) 44272c33676SMaxim Ag X509_STORE_CTX_set_verify_cb(&ctx, s->internal->verify_callback); 443f5b1c8a1SJohn Marino 44472c33676SMaxim Ag if (s->ctx->internal->app_verify_callback != NULL) 44572c33676SMaxim Ag ret = s->ctx->internal->app_verify_callback(&ctx, 44672c33676SMaxim Ag s->ctx->internal->app_verify_arg); 447f5b1c8a1SJohn Marino else 448f5b1c8a1SJohn Marino ret = X509_verify_cert(&ctx); 449f5b1c8a1SJohn Marino 450f5b1c8a1SJohn Marino s->verify_result = ctx.error; 451f5b1c8a1SJohn Marino X509_STORE_CTX_cleanup(&ctx); 452f5b1c8a1SJohn Marino 453f5b1c8a1SJohn Marino return (ret); 454f5b1c8a1SJohn Marino } 455f5b1c8a1SJohn Marino 456f5b1c8a1SJohn Marino static void 457f5b1c8a1SJohn Marino set_client_CA_list(STACK_OF(X509_NAME) **ca_list, 458f5b1c8a1SJohn Marino STACK_OF(X509_NAME) *name_list) 459f5b1c8a1SJohn Marino { 460f5b1c8a1SJohn Marino sk_X509_NAME_pop_free(*ca_list, X509_NAME_free); 461f5b1c8a1SJohn Marino *ca_list = name_list; 462f5b1c8a1SJohn Marino } 463f5b1c8a1SJohn Marino 464f5b1c8a1SJohn Marino STACK_OF(X509_NAME) * 46572c33676SMaxim Ag SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk) 466f5b1c8a1SJohn Marino { 467f5b1c8a1SJohn Marino int i; 468f5b1c8a1SJohn Marino STACK_OF(X509_NAME) *ret; 469*cca6fc52SDaniel Fojt X509_NAME *name = NULL; 470f5b1c8a1SJohn Marino 471*cca6fc52SDaniel Fojt if ((ret = sk_X509_NAME_new_null()) == NULL) 472*cca6fc52SDaniel Fojt goto err; 473*cca6fc52SDaniel Fojt 474f5b1c8a1SJohn Marino for (i = 0; i < sk_X509_NAME_num(sk); i++) { 475*cca6fc52SDaniel Fojt if ((name = X509_NAME_dup(sk_X509_NAME_value(sk, i))) == NULL) 476*cca6fc52SDaniel Fojt goto err; 477*cca6fc52SDaniel Fojt if (!sk_X509_NAME_push(ret, name)) 478*cca6fc52SDaniel Fojt goto err; 479f5b1c8a1SJohn Marino } 480f5b1c8a1SJohn Marino return (ret); 481*cca6fc52SDaniel Fojt 482*cca6fc52SDaniel Fojt err: 483*cca6fc52SDaniel Fojt X509_NAME_free(name); 484*cca6fc52SDaniel Fojt sk_X509_NAME_pop_free(ret, X509_NAME_free); 485*cca6fc52SDaniel Fojt return NULL; 486f5b1c8a1SJohn Marino } 487f5b1c8a1SJohn Marino 488f5b1c8a1SJohn Marino void 489f5b1c8a1SJohn Marino SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) 490f5b1c8a1SJohn Marino { 49172c33676SMaxim Ag set_client_CA_list(&(s->internal->client_CA), name_list); 492f5b1c8a1SJohn Marino } 493f5b1c8a1SJohn Marino 494f5b1c8a1SJohn Marino void 495f5b1c8a1SJohn Marino SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) 496f5b1c8a1SJohn Marino { 49772c33676SMaxim Ag set_client_CA_list(&(ctx->internal->client_CA), name_list); 498f5b1c8a1SJohn Marino } 499f5b1c8a1SJohn Marino 500f5b1c8a1SJohn Marino STACK_OF(X509_NAME) * 501f5b1c8a1SJohn Marino SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) 502f5b1c8a1SJohn Marino { 50372c33676SMaxim Ag return (ctx->internal->client_CA); 504f5b1c8a1SJohn Marino } 505f5b1c8a1SJohn Marino 506f5b1c8a1SJohn Marino STACK_OF(X509_NAME) * 507f5b1c8a1SJohn Marino SSL_get_client_CA_list(const SSL *s) 508f5b1c8a1SJohn Marino { 50972c33676SMaxim Ag if (s->internal->type == SSL_ST_CONNECT) { 510f5b1c8a1SJohn Marino /* We are in the client. */ 511*cca6fc52SDaniel Fojt if ((s->version >> 8) == SSL3_VERSION_MAJOR) 51272c33676SMaxim Ag return (S3I(s)->tmp.ca_names); 513f5b1c8a1SJohn Marino else 514f5b1c8a1SJohn Marino return (NULL); 515f5b1c8a1SJohn Marino } else { 51672c33676SMaxim Ag if (s->internal->client_CA != NULL) 51772c33676SMaxim Ag return (s->internal->client_CA); 518f5b1c8a1SJohn Marino else 51972c33676SMaxim Ag return (s->ctx->internal->client_CA); 520f5b1c8a1SJohn Marino } 521f5b1c8a1SJohn Marino } 522f5b1c8a1SJohn Marino 523f5b1c8a1SJohn Marino static int 524f5b1c8a1SJohn Marino add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x) 525f5b1c8a1SJohn Marino { 526f5b1c8a1SJohn Marino X509_NAME *name; 527f5b1c8a1SJohn Marino 528f5b1c8a1SJohn Marino if (x == NULL) 529f5b1c8a1SJohn Marino return (0); 530f5b1c8a1SJohn Marino if ((*sk == NULL) && ((*sk = sk_X509_NAME_new_null()) == NULL)) 531f5b1c8a1SJohn Marino return (0); 532f5b1c8a1SJohn Marino 533f5b1c8a1SJohn Marino if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL) 534f5b1c8a1SJohn Marino return (0); 535f5b1c8a1SJohn Marino 536f5b1c8a1SJohn Marino if (!sk_X509_NAME_push(*sk, name)) { 537f5b1c8a1SJohn Marino X509_NAME_free(name); 538f5b1c8a1SJohn Marino return (0); 539f5b1c8a1SJohn Marino } 540f5b1c8a1SJohn Marino return (1); 541f5b1c8a1SJohn Marino } 542f5b1c8a1SJohn Marino 543f5b1c8a1SJohn Marino int 544f5b1c8a1SJohn Marino SSL_add_client_CA(SSL *ssl, X509 *x) 545f5b1c8a1SJohn Marino { 54672c33676SMaxim Ag return (add_client_CA(&(ssl->internal->client_CA), x)); 547f5b1c8a1SJohn Marino } 548f5b1c8a1SJohn Marino 549f5b1c8a1SJohn Marino int 550f5b1c8a1SJohn Marino SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) 551f5b1c8a1SJohn Marino { 55272c33676SMaxim Ag return (add_client_CA(&(ctx->internal->client_CA), x)); 553f5b1c8a1SJohn Marino } 554f5b1c8a1SJohn Marino 555f5b1c8a1SJohn Marino static int 556f5b1c8a1SJohn Marino xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b) 557f5b1c8a1SJohn Marino { 558f5b1c8a1SJohn Marino return (X509_NAME_cmp(*a, *b)); 559f5b1c8a1SJohn Marino } 560f5b1c8a1SJohn Marino 561f5b1c8a1SJohn Marino /*! 562f5b1c8a1SJohn Marino * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; 563f5b1c8a1SJohn Marino * it doesn't really have anything to do with clients (except that a common use 564f5b1c8a1SJohn Marino * for a stack of CAs is to send it to the client). Actually, it doesn't have 565f5b1c8a1SJohn Marino * much to do with CAs, either, since it will load any old cert. 566f5b1c8a1SJohn Marino * \param file the file containing one or more certs. 567f5b1c8a1SJohn Marino * \return a ::STACK containing the certs. 568f5b1c8a1SJohn Marino */ 569f5b1c8a1SJohn Marino STACK_OF(X509_NAME) * 570f5b1c8a1SJohn Marino SSL_load_client_CA_file(const char *file) 571f5b1c8a1SJohn Marino { 572f5b1c8a1SJohn Marino BIO *in; 573f5b1c8a1SJohn Marino X509 *x = NULL; 574f5b1c8a1SJohn Marino X509_NAME *xn = NULL; 575f5b1c8a1SJohn Marino STACK_OF(X509_NAME) *ret = NULL, *sk; 576f5b1c8a1SJohn Marino 577f5b1c8a1SJohn Marino sk = sk_X509_NAME_new(xname_cmp); 578f5b1c8a1SJohn Marino 579f5b1c8a1SJohn Marino in = BIO_new(BIO_s_file_internal()); 580f5b1c8a1SJohn Marino 581f5b1c8a1SJohn Marino if ((sk == NULL) || (in == NULL)) { 58272c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE); 583f5b1c8a1SJohn Marino goto err; 584f5b1c8a1SJohn Marino } 585f5b1c8a1SJohn Marino 586f5b1c8a1SJohn Marino if (!BIO_read_filename(in, file)) 587f5b1c8a1SJohn Marino goto err; 588f5b1c8a1SJohn Marino 589f5b1c8a1SJohn Marino for (;;) { 590f5b1c8a1SJohn Marino if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) 591f5b1c8a1SJohn Marino break; 592f5b1c8a1SJohn Marino if (ret == NULL) { 593f5b1c8a1SJohn Marino ret = sk_X509_NAME_new_null(); 594f5b1c8a1SJohn Marino if (ret == NULL) { 59572c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE); 596f5b1c8a1SJohn Marino goto err; 597f5b1c8a1SJohn Marino } 598f5b1c8a1SJohn Marino } 599f5b1c8a1SJohn Marino if ((xn = X509_get_subject_name(x)) == NULL) goto err; 600f5b1c8a1SJohn Marino /* check for duplicates */ 601f5b1c8a1SJohn Marino xn = X509_NAME_dup(xn); 602f5b1c8a1SJohn Marino if (xn == NULL) 603f5b1c8a1SJohn Marino goto err; 604f5b1c8a1SJohn Marino if (sk_X509_NAME_find(sk, xn) >= 0) 605f5b1c8a1SJohn Marino X509_NAME_free(xn); 606f5b1c8a1SJohn Marino else { 607f5b1c8a1SJohn Marino sk_X509_NAME_push(sk, xn); 608f5b1c8a1SJohn Marino sk_X509_NAME_push(ret, xn); 609f5b1c8a1SJohn Marino } 610f5b1c8a1SJohn Marino } 611f5b1c8a1SJohn Marino 612f5b1c8a1SJohn Marino if (0) { 613f5b1c8a1SJohn Marino err: 614f5b1c8a1SJohn Marino sk_X509_NAME_pop_free(ret, X509_NAME_free); 615f5b1c8a1SJohn Marino ret = NULL; 616f5b1c8a1SJohn Marino } 617f5b1c8a1SJohn Marino sk_X509_NAME_free(sk); 618f5b1c8a1SJohn Marino BIO_free(in); 619f5b1c8a1SJohn Marino X509_free(x); 620f5b1c8a1SJohn Marino if (ret != NULL) 621f5b1c8a1SJohn Marino ERR_clear_error(); 62272c33676SMaxim Ag 623f5b1c8a1SJohn Marino return (ret); 624f5b1c8a1SJohn Marino } 625f5b1c8a1SJohn Marino 626f5b1c8a1SJohn Marino /*! 627f5b1c8a1SJohn Marino * Add a file of certs to a stack. 628f5b1c8a1SJohn Marino * \param stack the stack to add to. 629f5b1c8a1SJohn Marino * \param file the file to add from. All certs in this file that are not 630f5b1c8a1SJohn Marino * already in the stack will be added. 631f5b1c8a1SJohn Marino * \return 1 for success, 0 for failure. Note that in the case of failure some 632f5b1c8a1SJohn Marino * certs may have been added to \c stack. 633f5b1c8a1SJohn Marino */ 634f5b1c8a1SJohn Marino 635f5b1c8a1SJohn Marino int 636f5b1c8a1SJohn Marino SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, 637f5b1c8a1SJohn Marino const char *file) 638f5b1c8a1SJohn Marino { 639f5b1c8a1SJohn Marino BIO *in; 640f5b1c8a1SJohn Marino X509 *x = NULL; 641f5b1c8a1SJohn Marino X509_NAME *xn = NULL; 642f5b1c8a1SJohn Marino int ret = 1; 643f5b1c8a1SJohn Marino int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b); 644f5b1c8a1SJohn Marino 645f5b1c8a1SJohn Marino oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp); 646f5b1c8a1SJohn Marino 647f5b1c8a1SJohn Marino in = BIO_new(BIO_s_file_internal()); 648f5b1c8a1SJohn Marino 649f5b1c8a1SJohn Marino if (in == NULL) { 65072c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE); 651f5b1c8a1SJohn Marino goto err; 652f5b1c8a1SJohn Marino } 653f5b1c8a1SJohn Marino 654f5b1c8a1SJohn Marino if (!BIO_read_filename(in, file)) 655f5b1c8a1SJohn Marino goto err; 656f5b1c8a1SJohn Marino 657f5b1c8a1SJohn Marino for (;;) { 658f5b1c8a1SJohn Marino if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) 659f5b1c8a1SJohn Marino break; 660f5b1c8a1SJohn Marino if ((xn = X509_get_subject_name(x)) == NULL) goto err; 661f5b1c8a1SJohn Marino xn = X509_NAME_dup(xn); 662f5b1c8a1SJohn Marino if (xn == NULL) 663f5b1c8a1SJohn Marino goto err; 664f5b1c8a1SJohn Marino if (sk_X509_NAME_find(stack, xn) >= 0) 665f5b1c8a1SJohn Marino X509_NAME_free(xn); 666f5b1c8a1SJohn Marino else 667f5b1c8a1SJohn Marino sk_X509_NAME_push(stack, xn); 668f5b1c8a1SJohn Marino } 669f5b1c8a1SJohn Marino 670f5b1c8a1SJohn Marino ERR_clear_error(); 671f5b1c8a1SJohn Marino 672f5b1c8a1SJohn Marino if (0) { 673f5b1c8a1SJohn Marino err: 674f5b1c8a1SJohn Marino ret = 0; 675f5b1c8a1SJohn Marino } 676f5b1c8a1SJohn Marino BIO_free(in); 677f5b1c8a1SJohn Marino X509_free(x); 678f5b1c8a1SJohn Marino 679f5b1c8a1SJohn Marino (void)sk_X509_NAME_set_cmp_func(stack, oldcmp); 680f5b1c8a1SJohn Marino 681f5b1c8a1SJohn Marino return ret; 682f5b1c8a1SJohn Marino } 683f5b1c8a1SJohn Marino 684f5b1c8a1SJohn Marino /*! 685f5b1c8a1SJohn Marino * Add a directory of certs to a stack. 686f5b1c8a1SJohn Marino * \param stack the stack to append to. 687f5b1c8a1SJohn Marino * \param dir the directory to append from. All files in this directory will be 688f5b1c8a1SJohn Marino * examined as potential certs. Any that are acceptable to 689f5b1c8a1SJohn Marino * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will 690f5b1c8a1SJohn Marino * be included. 691f5b1c8a1SJohn Marino * \return 1 for success, 0 for failure. Note that in the case of failure some 692f5b1c8a1SJohn Marino * certs may have been added to \c stack. 693f5b1c8a1SJohn Marino */ 694f5b1c8a1SJohn Marino 695f5b1c8a1SJohn Marino int 696f5b1c8a1SJohn Marino SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, const char *dir) 697f5b1c8a1SJohn Marino { 698f5b1c8a1SJohn Marino DIR *dirp = NULL; 699f5b1c8a1SJohn Marino char *path = NULL; 700f5b1c8a1SJohn Marino int ret = 0; 701f5b1c8a1SJohn Marino 702f5b1c8a1SJohn Marino dirp = opendir(dir); 703f5b1c8a1SJohn Marino if (dirp) { 704f5b1c8a1SJohn Marino struct dirent *dp; 705f5b1c8a1SJohn Marino while ((dp = readdir(dirp)) != NULL) { 706f5b1c8a1SJohn Marino if (asprintf(&path, "%s/%s", dir, dp->d_name) != -1) { 707f5b1c8a1SJohn Marino ret = SSL_add_file_cert_subjects_to_stack( 708f5b1c8a1SJohn Marino stack, path); 709f5b1c8a1SJohn Marino free(path); 710f5b1c8a1SJohn Marino } 711f5b1c8a1SJohn Marino if (!ret) 712f5b1c8a1SJohn Marino break; 713f5b1c8a1SJohn Marino } 714f5b1c8a1SJohn Marino (void) closedir(dirp); 715f5b1c8a1SJohn Marino } 716f5b1c8a1SJohn Marino if (!ret) { 71772c33676SMaxim Ag SYSerror(errno); 718f5b1c8a1SJohn Marino ERR_asprintf_error_data("opendir ('%s')", dir); 71972c33676SMaxim Ag SSLerrorx(ERR_R_SYS_LIB); 720f5b1c8a1SJohn Marino } 721f5b1c8a1SJohn Marino return ret; 722f5b1c8a1SJohn Marino } 723