1*8edacedfSDaniel Fojt /* $OpenBSD: ssl_cert.c,v 1.78 2020/06/05 17:55:24 jsing 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 } 171*8edacedfSDaniel Fojt ret->key = &(ret->pkeys[SSL_PKEY_RSA]); 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 243*8edacedfSDaniel Fojt case SSL_PKEY_RSA: 244f5b1c8a1SJohn Marino /* We have an RSA key. */ 245f5b1c8a1SJohn Marino break; 246f5b1c8a1SJohn Marino 247f5b1c8a1SJohn Marino case SSL_PKEY_ECC: 248f5b1c8a1SJohn Marino /* We have an ECC key */ 249f5b1c8a1SJohn Marino break; 250f5b1c8a1SJohn Marino 251*8edacedfSDaniel Fojt case SSL_PKEY_GOST01: 252*8edacedfSDaniel Fojt /* We have a GOST key */ 253*8edacedfSDaniel Fojt break; 254*8edacedfSDaniel Fojt 255f5b1c8a1SJohn Marino default: 256f5b1c8a1SJohn Marino /* Can't happen. */ 25772c33676SMaxim Ag SSLerrorx(SSL_R_LIBRARY_BUG); 258f5b1c8a1SJohn Marino } 259f5b1c8a1SJohn Marino } 26072c33676SMaxim Ag 26172c33676SMaxim Ag if (cert->pkeys[i].chain != NULL) { 26272c33676SMaxim Ag if ((ret->pkeys[i].chain = 26372c33676SMaxim Ag X509_chain_up_ref(cert->pkeys[i].chain)) == NULL) 26472c33676SMaxim Ag goto err; 26572c33676SMaxim Ag } 266f5b1c8a1SJohn Marino } 267f5b1c8a1SJohn Marino 268f5b1c8a1SJohn Marino /* 269f5b1c8a1SJohn Marino * ret->extra_certs *should* exist, but currently the own certificate 270f5b1c8a1SJohn Marino * chain is held inside SSL_CTX 271f5b1c8a1SJohn Marino */ 272f5b1c8a1SJohn Marino 273f5b1c8a1SJohn Marino ret->references = 1; 274f5b1c8a1SJohn Marino 275f5b1c8a1SJohn Marino return (ret); 276f5b1c8a1SJohn Marino 277f5b1c8a1SJohn Marino err: 278f5b1c8a1SJohn Marino DH_free(ret->dh_tmp); 279f5b1c8a1SJohn Marino 280f5b1c8a1SJohn Marino for (i = 0; i < SSL_PKEY_NUM; i++) { 281f5b1c8a1SJohn Marino X509_free(ret->pkeys[i].x509); 282f5b1c8a1SJohn Marino EVP_PKEY_free(ret->pkeys[i].privatekey); 28372c33676SMaxim Ag sk_X509_pop_free(ret->pkeys[i].chain, X509_free); 284f5b1c8a1SJohn Marino } 285f5b1c8a1SJohn Marino free (ret); 286f5b1c8a1SJohn Marino return NULL; 287f5b1c8a1SJohn Marino } 288f5b1c8a1SJohn Marino 289f5b1c8a1SJohn Marino 290f5b1c8a1SJohn Marino void 291f5b1c8a1SJohn Marino ssl_cert_free(CERT *c) 292f5b1c8a1SJohn Marino { 293f5b1c8a1SJohn Marino int i; 294f5b1c8a1SJohn Marino 295f5b1c8a1SJohn Marino if (c == NULL) 296f5b1c8a1SJohn Marino return; 297f5b1c8a1SJohn Marino 298f5b1c8a1SJohn Marino i = CRYPTO_add(&c->references, -1, CRYPTO_LOCK_SSL_CERT); 299f5b1c8a1SJohn Marino if (i > 0) 300f5b1c8a1SJohn Marino return; 301f5b1c8a1SJohn Marino 302f5b1c8a1SJohn Marino DH_free(c->dh_tmp); 303f5b1c8a1SJohn Marino 304f5b1c8a1SJohn Marino for (i = 0; i < SSL_PKEY_NUM; i++) { 305f5b1c8a1SJohn Marino X509_free(c->pkeys[i].x509); 306f5b1c8a1SJohn Marino EVP_PKEY_free(c->pkeys[i].privatekey); 30772c33676SMaxim Ag sk_X509_pop_free(c->pkeys[i].chain, X509_free); 308f5b1c8a1SJohn Marino } 309f5b1c8a1SJohn Marino 310f5b1c8a1SJohn Marino free(c); 311f5b1c8a1SJohn Marino } 312f5b1c8a1SJohn Marino 313f5b1c8a1SJohn Marino int 31472c33676SMaxim Ag ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain) 315f5b1c8a1SJohn Marino { 31672c33676SMaxim Ag if (c->key == NULL) 31772c33676SMaxim Ag return 0; 318f5b1c8a1SJohn Marino 31972c33676SMaxim Ag sk_X509_pop_free(c->key->chain, X509_free); 32072c33676SMaxim Ag c->key->chain = chain; 32172c33676SMaxim Ag 32272c33676SMaxim Ag return 1; 323f5b1c8a1SJohn Marino } 324f5b1c8a1SJohn Marino 32572c33676SMaxim Ag int 32672c33676SMaxim Ag ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain) 32772c33676SMaxim Ag { 32872c33676SMaxim Ag STACK_OF(X509) *new_chain = NULL; 32972c33676SMaxim Ag 33072c33676SMaxim Ag if (chain != NULL) { 33172c33676SMaxim Ag if ((new_chain = X509_chain_up_ref(chain)) == NULL) 33272c33676SMaxim Ag return 0; 33372c33676SMaxim Ag } 33472c33676SMaxim Ag if (!ssl_cert_set0_chain(c, new_chain)) { 33572c33676SMaxim Ag sk_X509_pop_free(new_chain, X509_free); 33672c33676SMaxim Ag return 0; 33772c33676SMaxim Ag } 33872c33676SMaxim Ag 33972c33676SMaxim Ag return 1; 34072c33676SMaxim Ag } 34172c33676SMaxim Ag 34272c33676SMaxim Ag int 34372c33676SMaxim Ag ssl_cert_add0_chain_cert(CERT *c, X509 *cert) 34472c33676SMaxim Ag { 34572c33676SMaxim Ag if (c->key == NULL) 34672c33676SMaxim Ag return 0; 34772c33676SMaxim Ag 34872c33676SMaxim Ag if (c->key->chain == NULL) { 34972c33676SMaxim Ag if ((c->key->chain = sk_X509_new_null()) == NULL) 35072c33676SMaxim Ag return 0; 35172c33676SMaxim Ag } 35272c33676SMaxim Ag if (!sk_X509_push(c->key->chain, cert)) 35372c33676SMaxim Ag return 0; 35472c33676SMaxim Ag 35572c33676SMaxim Ag return 1; 35672c33676SMaxim Ag } 35772c33676SMaxim Ag 35872c33676SMaxim Ag int 35972c33676SMaxim Ag ssl_cert_add1_chain_cert(CERT *c, X509 *cert) 36072c33676SMaxim Ag { 36172c33676SMaxim Ag if (!ssl_cert_add0_chain_cert(c, cert)) 36272c33676SMaxim Ag return 0; 36372c33676SMaxim Ag 36472c33676SMaxim Ag X509_up_ref(cert); 36572c33676SMaxim Ag 36672c33676SMaxim Ag return 1; 36772c33676SMaxim Ag } 368f5b1c8a1SJohn Marino 369f5b1c8a1SJohn Marino SESS_CERT * 370f5b1c8a1SJohn Marino ssl_sess_cert_new(void) 371f5b1c8a1SJohn Marino { 372f5b1c8a1SJohn Marino SESS_CERT *ret; 373f5b1c8a1SJohn Marino 374f5b1c8a1SJohn Marino ret = calloc(1, sizeof *ret); 375f5b1c8a1SJohn Marino if (ret == NULL) { 37672c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE); 377f5b1c8a1SJohn Marino return NULL; 378f5b1c8a1SJohn Marino } 379*8edacedfSDaniel Fojt ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA]); 380f5b1c8a1SJohn Marino ret->references = 1; 381f5b1c8a1SJohn Marino 382f5b1c8a1SJohn Marino return ret; 383f5b1c8a1SJohn Marino } 384f5b1c8a1SJohn Marino 385f5b1c8a1SJohn Marino void 386f5b1c8a1SJohn Marino ssl_sess_cert_free(SESS_CERT *sc) 387f5b1c8a1SJohn Marino { 388f5b1c8a1SJohn Marino int i; 389f5b1c8a1SJohn Marino 390f5b1c8a1SJohn Marino if (sc == NULL) 391f5b1c8a1SJohn Marino return; 392f5b1c8a1SJohn Marino 393f5b1c8a1SJohn Marino i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT); 394f5b1c8a1SJohn Marino if (i > 0) 395f5b1c8a1SJohn Marino return; 396f5b1c8a1SJohn Marino 397f5b1c8a1SJohn Marino sk_X509_pop_free(sc->cert_chain, X509_free); 398f5b1c8a1SJohn Marino for (i = 0; i < SSL_PKEY_NUM; i++) 399f5b1c8a1SJohn Marino X509_free(sc->peer_pkeys[i].x509); 400f5b1c8a1SJohn Marino 401f5b1c8a1SJohn Marino DH_free(sc->peer_dh_tmp); 402f5b1c8a1SJohn Marino EC_KEY_free(sc->peer_ecdh_tmp); 40372c33676SMaxim Ag free(sc->peer_x25519_tmp); 404f5b1c8a1SJohn Marino 405f5b1c8a1SJohn Marino free(sc); 406f5b1c8a1SJohn Marino } 407f5b1c8a1SJohn Marino 408f5b1c8a1SJohn Marino int 409f5b1c8a1SJohn Marino ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk) 410f5b1c8a1SJohn Marino { 411f5b1c8a1SJohn Marino X509_STORE_CTX ctx; 412f5b1c8a1SJohn Marino X509 *x; 413f5b1c8a1SJohn Marino int ret; 414f5b1c8a1SJohn Marino 415f5b1c8a1SJohn Marino if ((sk == NULL) || (sk_X509_num(sk) == 0)) 416f5b1c8a1SJohn Marino return (0); 417f5b1c8a1SJohn Marino 418f5b1c8a1SJohn Marino x = sk_X509_value(sk, 0); 419f5b1c8a1SJohn Marino if (!X509_STORE_CTX_init(&ctx, s->ctx->cert_store, x, sk)) { 42072c33676SMaxim Ag SSLerror(s, ERR_R_X509_LIB); 421f5b1c8a1SJohn Marino return (0); 422f5b1c8a1SJohn Marino } 423f5b1c8a1SJohn Marino X509_STORE_CTX_set_ex_data(&ctx, 424f5b1c8a1SJohn Marino SSL_get_ex_data_X509_STORE_CTX_idx(), s); 425f5b1c8a1SJohn Marino 426f5b1c8a1SJohn Marino /* 427f5b1c8a1SJohn Marino * We need to inherit the verify parameters. These can be 428f5b1c8a1SJohn Marino * determined by the context: if its a server it will verify 429f5b1c8a1SJohn Marino * SSL client certificates or vice versa. 430f5b1c8a1SJohn Marino */ 431f5b1c8a1SJohn Marino X509_STORE_CTX_set_default(&ctx, 432f5b1c8a1SJohn Marino s->server ? "ssl_client" : "ssl_server"); 433f5b1c8a1SJohn Marino 434f5b1c8a1SJohn Marino /* 435f5b1c8a1SJohn Marino * Anything non-default in "param" should overwrite anything 436f5b1c8a1SJohn Marino * in the ctx. 437f5b1c8a1SJohn Marino */ 438f5b1c8a1SJohn Marino X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param); 439f5b1c8a1SJohn Marino 44072c33676SMaxim Ag if (s->internal->verify_callback) 44172c33676SMaxim Ag X509_STORE_CTX_set_verify_cb(&ctx, s->internal->verify_callback); 442f5b1c8a1SJohn Marino 44372c33676SMaxim Ag if (s->ctx->internal->app_verify_callback != NULL) 44472c33676SMaxim Ag ret = s->ctx->internal->app_verify_callback(&ctx, 44572c33676SMaxim Ag s->ctx->internal->app_verify_arg); 446f5b1c8a1SJohn Marino else 447f5b1c8a1SJohn Marino ret = X509_verify_cert(&ctx); 448f5b1c8a1SJohn Marino 449f5b1c8a1SJohn Marino s->verify_result = ctx.error; 450f5b1c8a1SJohn Marino X509_STORE_CTX_cleanup(&ctx); 451f5b1c8a1SJohn Marino 452f5b1c8a1SJohn Marino return (ret); 453f5b1c8a1SJohn Marino } 454f5b1c8a1SJohn Marino 455f5b1c8a1SJohn Marino static void 456f5b1c8a1SJohn Marino set_client_CA_list(STACK_OF(X509_NAME) **ca_list, 457f5b1c8a1SJohn Marino STACK_OF(X509_NAME) *name_list) 458f5b1c8a1SJohn Marino { 459f5b1c8a1SJohn Marino sk_X509_NAME_pop_free(*ca_list, X509_NAME_free); 460f5b1c8a1SJohn Marino *ca_list = name_list; 461f5b1c8a1SJohn Marino } 462f5b1c8a1SJohn Marino 463f5b1c8a1SJohn Marino STACK_OF(X509_NAME) * 46472c33676SMaxim Ag SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk) 465f5b1c8a1SJohn Marino { 466f5b1c8a1SJohn Marino int i; 467f5b1c8a1SJohn Marino STACK_OF(X509_NAME) *ret; 468cca6fc52SDaniel Fojt X509_NAME *name = NULL; 469f5b1c8a1SJohn Marino 470cca6fc52SDaniel Fojt if ((ret = sk_X509_NAME_new_null()) == NULL) 471cca6fc52SDaniel Fojt goto err; 472cca6fc52SDaniel Fojt 473f5b1c8a1SJohn Marino for (i = 0; i < sk_X509_NAME_num(sk); i++) { 474cca6fc52SDaniel Fojt if ((name = X509_NAME_dup(sk_X509_NAME_value(sk, i))) == NULL) 475cca6fc52SDaniel Fojt goto err; 476cca6fc52SDaniel Fojt if (!sk_X509_NAME_push(ret, name)) 477cca6fc52SDaniel Fojt goto err; 478f5b1c8a1SJohn Marino } 479f5b1c8a1SJohn Marino return (ret); 480cca6fc52SDaniel Fojt 481cca6fc52SDaniel Fojt err: 482cca6fc52SDaniel Fojt X509_NAME_free(name); 483cca6fc52SDaniel Fojt sk_X509_NAME_pop_free(ret, X509_NAME_free); 484cca6fc52SDaniel Fojt return NULL; 485f5b1c8a1SJohn Marino } 486f5b1c8a1SJohn Marino 487f5b1c8a1SJohn Marino void 488f5b1c8a1SJohn Marino SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) 489f5b1c8a1SJohn Marino { 49072c33676SMaxim Ag set_client_CA_list(&(s->internal->client_CA), name_list); 491f5b1c8a1SJohn Marino } 492f5b1c8a1SJohn Marino 493f5b1c8a1SJohn Marino void 494f5b1c8a1SJohn Marino SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) 495f5b1c8a1SJohn Marino { 49672c33676SMaxim Ag set_client_CA_list(&(ctx->internal->client_CA), name_list); 497f5b1c8a1SJohn Marino } 498f5b1c8a1SJohn Marino 499f5b1c8a1SJohn Marino STACK_OF(X509_NAME) * 500f5b1c8a1SJohn Marino SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) 501f5b1c8a1SJohn Marino { 50272c33676SMaxim Ag return (ctx->internal->client_CA); 503f5b1c8a1SJohn Marino } 504f5b1c8a1SJohn Marino 505f5b1c8a1SJohn Marino STACK_OF(X509_NAME) * 506f5b1c8a1SJohn Marino SSL_get_client_CA_list(const SSL *s) 507f5b1c8a1SJohn Marino { 50872c33676SMaxim Ag if (s->internal->type == SSL_ST_CONNECT) { 509f5b1c8a1SJohn Marino /* We are in the client. */ 510cca6fc52SDaniel Fojt if ((s->version >> 8) == SSL3_VERSION_MAJOR) 51172c33676SMaxim Ag return (S3I(s)->tmp.ca_names); 512f5b1c8a1SJohn Marino else 513f5b1c8a1SJohn Marino return (NULL); 514f5b1c8a1SJohn Marino } else { 51572c33676SMaxim Ag if (s->internal->client_CA != NULL) 51672c33676SMaxim Ag return (s->internal->client_CA); 517f5b1c8a1SJohn Marino else 51872c33676SMaxim Ag return (s->ctx->internal->client_CA); 519f5b1c8a1SJohn Marino } 520f5b1c8a1SJohn Marino } 521f5b1c8a1SJohn Marino 522f5b1c8a1SJohn Marino static int 523f5b1c8a1SJohn Marino add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x) 524f5b1c8a1SJohn Marino { 525f5b1c8a1SJohn Marino X509_NAME *name; 526f5b1c8a1SJohn Marino 527f5b1c8a1SJohn Marino if (x == NULL) 528f5b1c8a1SJohn Marino return (0); 529f5b1c8a1SJohn Marino if ((*sk == NULL) && ((*sk = sk_X509_NAME_new_null()) == NULL)) 530f5b1c8a1SJohn Marino return (0); 531f5b1c8a1SJohn Marino 532f5b1c8a1SJohn Marino if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL) 533f5b1c8a1SJohn Marino return (0); 534f5b1c8a1SJohn Marino 535f5b1c8a1SJohn Marino if (!sk_X509_NAME_push(*sk, name)) { 536f5b1c8a1SJohn Marino X509_NAME_free(name); 537f5b1c8a1SJohn Marino return (0); 538f5b1c8a1SJohn Marino } 539f5b1c8a1SJohn Marino return (1); 540f5b1c8a1SJohn Marino } 541f5b1c8a1SJohn Marino 542f5b1c8a1SJohn Marino int 543f5b1c8a1SJohn Marino SSL_add_client_CA(SSL *ssl, X509 *x) 544f5b1c8a1SJohn Marino { 54572c33676SMaxim Ag return (add_client_CA(&(ssl->internal->client_CA), x)); 546f5b1c8a1SJohn Marino } 547f5b1c8a1SJohn Marino 548f5b1c8a1SJohn Marino int 549f5b1c8a1SJohn Marino SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) 550f5b1c8a1SJohn Marino { 55172c33676SMaxim Ag return (add_client_CA(&(ctx->internal->client_CA), x)); 552f5b1c8a1SJohn Marino } 553f5b1c8a1SJohn Marino 554f5b1c8a1SJohn Marino static int 555f5b1c8a1SJohn Marino xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b) 556f5b1c8a1SJohn Marino { 557f5b1c8a1SJohn Marino return (X509_NAME_cmp(*a, *b)); 558f5b1c8a1SJohn Marino } 559f5b1c8a1SJohn Marino 560f5b1c8a1SJohn Marino /*! 561f5b1c8a1SJohn Marino * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; 562f5b1c8a1SJohn Marino * it doesn't really have anything to do with clients (except that a common use 563f5b1c8a1SJohn Marino * for a stack of CAs is to send it to the client). Actually, it doesn't have 564f5b1c8a1SJohn Marino * much to do with CAs, either, since it will load any old cert. 565f5b1c8a1SJohn Marino * \param file the file containing one or more certs. 566f5b1c8a1SJohn Marino * \return a ::STACK containing the certs. 567f5b1c8a1SJohn Marino */ 568f5b1c8a1SJohn Marino STACK_OF(X509_NAME) * 569f5b1c8a1SJohn Marino SSL_load_client_CA_file(const char *file) 570f5b1c8a1SJohn Marino { 571f5b1c8a1SJohn Marino BIO *in; 572f5b1c8a1SJohn Marino X509 *x = NULL; 573f5b1c8a1SJohn Marino X509_NAME *xn = NULL; 574f5b1c8a1SJohn Marino STACK_OF(X509_NAME) *ret = NULL, *sk; 575f5b1c8a1SJohn Marino 576f5b1c8a1SJohn Marino sk = sk_X509_NAME_new(xname_cmp); 577f5b1c8a1SJohn Marino 578f5b1c8a1SJohn Marino in = BIO_new(BIO_s_file_internal()); 579f5b1c8a1SJohn Marino 580f5b1c8a1SJohn Marino if ((sk == NULL) || (in == NULL)) { 58172c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE); 582f5b1c8a1SJohn Marino goto err; 583f5b1c8a1SJohn Marino } 584f5b1c8a1SJohn Marino 585f5b1c8a1SJohn Marino if (!BIO_read_filename(in, file)) 586f5b1c8a1SJohn Marino goto err; 587f5b1c8a1SJohn Marino 588f5b1c8a1SJohn Marino for (;;) { 589f5b1c8a1SJohn Marino if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) 590f5b1c8a1SJohn Marino break; 591f5b1c8a1SJohn Marino if (ret == NULL) { 592f5b1c8a1SJohn Marino ret = sk_X509_NAME_new_null(); 593f5b1c8a1SJohn Marino if (ret == NULL) { 59472c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE); 595f5b1c8a1SJohn Marino goto err; 596f5b1c8a1SJohn Marino } 597f5b1c8a1SJohn Marino } 598f5b1c8a1SJohn Marino if ((xn = X509_get_subject_name(x)) == NULL) goto err; 599f5b1c8a1SJohn Marino /* check for duplicates */ 600f5b1c8a1SJohn Marino xn = X509_NAME_dup(xn); 601f5b1c8a1SJohn Marino if (xn == NULL) 602f5b1c8a1SJohn Marino goto err; 603f5b1c8a1SJohn Marino if (sk_X509_NAME_find(sk, xn) >= 0) 604f5b1c8a1SJohn Marino X509_NAME_free(xn); 605f5b1c8a1SJohn Marino else { 606f5b1c8a1SJohn Marino sk_X509_NAME_push(sk, xn); 607f5b1c8a1SJohn Marino sk_X509_NAME_push(ret, xn); 608f5b1c8a1SJohn Marino } 609f5b1c8a1SJohn Marino } 610f5b1c8a1SJohn Marino 611f5b1c8a1SJohn Marino if (0) { 612f5b1c8a1SJohn Marino err: 613f5b1c8a1SJohn Marino sk_X509_NAME_pop_free(ret, X509_NAME_free); 614f5b1c8a1SJohn Marino ret = NULL; 615f5b1c8a1SJohn Marino } 616f5b1c8a1SJohn Marino sk_X509_NAME_free(sk); 617f5b1c8a1SJohn Marino BIO_free(in); 618f5b1c8a1SJohn Marino X509_free(x); 619f5b1c8a1SJohn Marino if (ret != NULL) 620f5b1c8a1SJohn Marino ERR_clear_error(); 62172c33676SMaxim Ag 622f5b1c8a1SJohn Marino return (ret); 623f5b1c8a1SJohn Marino } 624f5b1c8a1SJohn Marino 625f5b1c8a1SJohn Marino /*! 626f5b1c8a1SJohn Marino * Add a file of certs to a stack. 627f5b1c8a1SJohn Marino * \param stack the stack to add to. 628f5b1c8a1SJohn Marino * \param file the file to add from. All certs in this file that are not 629f5b1c8a1SJohn Marino * already in the stack will be added. 630f5b1c8a1SJohn Marino * \return 1 for success, 0 for failure. Note that in the case of failure some 631f5b1c8a1SJohn Marino * certs may have been added to \c stack. 632f5b1c8a1SJohn Marino */ 633f5b1c8a1SJohn Marino 634f5b1c8a1SJohn Marino int 635f5b1c8a1SJohn Marino SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, 636f5b1c8a1SJohn Marino const char *file) 637f5b1c8a1SJohn Marino { 638f5b1c8a1SJohn Marino BIO *in; 639f5b1c8a1SJohn Marino X509 *x = NULL; 640f5b1c8a1SJohn Marino X509_NAME *xn = NULL; 641f5b1c8a1SJohn Marino int ret = 1; 642f5b1c8a1SJohn Marino int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b); 643f5b1c8a1SJohn Marino 644f5b1c8a1SJohn Marino oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp); 645f5b1c8a1SJohn Marino 646f5b1c8a1SJohn Marino in = BIO_new(BIO_s_file_internal()); 647f5b1c8a1SJohn Marino 648f5b1c8a1SJohn Marino if (in == NULL) { 64972c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE); 650f5b1c8a1SJohn Marino goto err; 651f5b1c8a1SJohn Marino } 652f5b1c8a1SJohn Marino 653f5b1c8a1SJohn Marino if (!BIO_read_filename(in, file)) 654f5b1c8a1SJohn Marino goto err; 655f5b1c8a1SJohn Marino 656f5b1c8a1SJohn Marino for (;;) { 657f5b1c8a1SJohn Marino if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) 658f5b1c8a1SJohn Marino break; 659f5b1c8a1SJohn Marino if ((xn = X509_get_subject_name(x)) == NULL) goto err; 660f5b1c8a1SJohn Marino xn = X509_NAME_dup(xn); 661f5b1c8a1SJohn Marino if (xn == NULL) 662f5b1c8a1SJohn Marino goto err; 663f5b1c8a1SJohn Marino if (sk_X509_NAME_find(stack, xn) >= 0) 664f5b1c8a1SJohn Marino X509_NAME_free(xn); 665f5b1c8a1SJohn Marino else 666f5b1c8a1SJohn Marino sk_X509_NAME_push(stack, xn); 667f5b1c8a1SJohn Marino } 668f5b1c8a1SJohn Marino 669f5b1c8a1SJohn Marino ERR_clear_error(); 670f5b1c8a1SJohn Marino 671f5b1c8a1SJohn Marino if (0) { 672f5b1c8a1SJohn Marino err: 673f5b1c8a1SJohn Marino ret = 0; 674f5b1c8a1SJohn Marino } 675f5b1c8a1SJohn Marino BIO_free(in); 676f5b1c8a1SJohn Marino X509_free(x); 677f5b1c8a1SJohn Marino 678f5b1c8a1SJohn Marino (void)sk_X509_NAME_set_cmp_func(stack, oldcmp); 679f5b1c8a1SJohn Marino 680f5b1c8a1SJohn Marino return ret; 681f5b1c8a1SJohn Marino } 682f5b1c8a1SJohn Marino 683f5b1c8a1SJohn Marino /*! 684f5b1c8a1SJohn Marino * Add a directory of certs to a stack. 685f5b1c8a1SJohn Marino * \param stack the stack to append to. 686f5b1c8a1SJohn Marino * \param dir the directory to append from. All files in this directory will be 687f5b1c8a1SJohn Marino * examined as potential certs. Any that are acceptable to 688f5b1c8a1SJohn Marino * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will 689f5b1c8a1SJohn Marino * be included. 690f5b1c8a1SJohn Marino * \return 1 for success, 0 for failure. Note that in the case of failure some 691f5b1c8a1SJohn Marino * certs may have been added to \c stack. 692f5b1c8a1SJohn Marino */ 693f5b1c8a1SJohn Marino 694f5b1c8a1SJohn Marino int 695f5b1c8a1SJohn Marino SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, const char *dir) 696f5b1c8a1SJohn Marino { 697f5b1c8a1SJohn Marino DIR *dirp = NULL; 698f5b1c8a1SJohn Marino char *path = NULL; 699f5b1c8a1SJohn Marino int ret = 0; 700f5b1c8a1SJohn Marino 701f5b1c8a1SJohn Marino dirp = opendir(dir); 702f5b1c8a1SJohn Marino if (dirp) { 703f5b1c8a1SJohn Marino struct dirent *dp; 704f5b1c8a1SJohn Marino while ((dp = readdir(dirp)) != NULL) { 705f5b1c8a1SJohn Marino if (asprintf(&path, "%s/%s", dir, dp->d_name) != -1) { 706f5b1c8a1SJohn Marino ret = SSL_add_file_cert_subjects_to_stack( 707f5b1c8a1SJohn Marino stack, path); 708f5b1c8a1SJohn Marino free(path); 709f5b1c8a1SJohn Marino } 710f5b1c8a1SJohn Marino if (!ret) 711f5b1c8a1SJohn Marino break; 712f5b1c8a1SJohn Marino } 713f5b1c8a1SJohn Marino (void) closedir(dirp); 714f5b1c8a1SJohn Marino } 715f5b1c8a1SJohn Marino if (!ret) { 71672c33676SMaxim Ag SYSerror(errno); 717f5b1c8a1SJohn Marino ERR_asprintf_error_data("opendir ('%s')", dir); 71872c33676SMaxim Ag SSLerrorx(ERR_R_SYS_LIB); 719f5b1c8a1SJohn Marino } 720f5b1c8a1SJohn Marino return ret; 721f5b1c8a1SJohn Marino } 722