STACK_OF(X509) *TS_CONF_load_certs(const char *file) { BIO *certs = NULL; STACK_OF(X509) *othercerts = NULL; STACK_OF(X509_INFO) *allcerts = NULL; int i; if ((certs = BIO_new_file(file, "r")) == NULL) goto end; if ((othercerts = sk_X509_new_null()) == NULL) goto end; allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL); for (i = 0; i < sk_X509_INFO_num(allcerts); i++) { X509_INFO *xi = sk_X509_INFO_value(allcerts, i); if (xi->x509) { sk_X509_push(othercerts, xi->x509); xi->x509 = NULL; } } end: if (othercerts == NULL) TSerr(TS_F_TS_CONF_LOAD_CERTS, TS_R_CANNOT_LOAD_CERT); sk_X509_INFO_pop_free(allcerts, X509_INFO_free); BIO_free(certs); return othercerts; }
STACK_OF(X509) *TS_CONF_load_certs(const char *file) { BIO *certs = NULL; STACK_OF(X509) *othercerts = NULL; STACK_OF(X509_INFO) *allcerts = NULL; int i; if (!(certs = BIO_new_file(file, "r"))) goto end; if (!(othercerts = sk_X509_new_null())) goto end; allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL); for(i = 0; i < sk_X509_INFO_num(allcerts); i++) { X509_INFO *xi = sk_X509_INFO_value(allcerts, i); if (xi->x509) { sk_X509_push(othercerts, xi->x509); xi->x509 = NULL; } } end: if (othercerts == NULL) fprintf(stderr, "unable to load certificates: %s\n", file); sk_X509_INFO_pop_free(allcerts, X509_INFO_free); BIO_free(certs); return othercerts; }
int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) { STACK_OF(X509_INFO) *inf; X509_INFO *itmp; BIO *in; int i, count = 0; if (type != X509_FILETYPE_PEM) return X509_load_cert_file(ctx, file, type); in = BIO_new_file(file, "r"); if (!in) { X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB); return 0; } inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); BIO_free(in); if (!inf) { X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB); return 0; } for (i = 0; i < sk_X509_INFO_num(inf); i++) { itmp = sk_X509_INFO_value(inf, i); if (itmp->x509) { X509_STORE_add_cert(ctx->store_ctx, itmp->x509); count++; } if (itmp->crl) { X509_STORE_add_crl(ctx->store_ctx, itmp->crl); count++; } } sk_X509_INFO_pop_free(inf, X509_INFO_free); return count; }
static int handle_certificate(const char *filename, const char *fullpath) { STACK_OF(X509_INFO) *inf; X509_INFO *x; BIO *b; const char *ext; unsigned char digest[EVP_MAX_MD_SIZE]; X509_NAME *name = NULL; int i, type, ret = -1; ext = strrchr(filename, '.'); if (ext == NULL) return 0; for (i = 0; i < countof(file_extensions); i++) { if (strcasecmp(file_extensions[i], ext+1) == 0) break; } if (i >= countof(file_extensions)) return -1; b = BIO_new_file(fullpath, "r"); if (!b) return -1; inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL); BIO_free(b); if (!inf) return -1; if (sk_X509_INFO_num(inf) == 1) { x = sk_X509_INFO_value(inf, 0); if (x->x509) { type = TYPE_CERT; name = X509_get_subject_name(x->x509); X509_digest(x->x509, evpmd, digest, NULL); } else if (x->crl) { type = TYPE_CRL; name = X509_CRL_get_issuer(x->crl); X509_CRL_digest(x->crl, evpmd, digest, NULL); } if (name && do_hash_new) add_entry(type, X509_NAME_hash(name), filename, digest, 1, ~0); if (name && do_hash_old) add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0); } else { fprintf(stderr, "WARNING: %s does not contain exactly one certificate or CRL: skipping\n", filename); } sk_X509_INFO_pop_free(inf, X509_INFO_free); return ret; }
/** * Parses X.509 PEM formatted certificates from file. The file can contain multiple * certificates. You can just use 'cat' command in linux to add multiple PEM formatted * X.509 certificates to one file (e.g. <code>cat cert1.pem cert2.pem > certs.pem</code>). * NB! This struct must be freed using sk_X509_free() function from OpenSSL or * with X509Stack_scope struct. * * @param path PEM formatted X.509 certificates file path. * @return returns stack of parsed X.509 certificates. * @throws IOException throws exception if the file does not contain X.509 * PEM formatted certificate(s). */ STACK_OF(X509)* digidoc::X509Cert::loadX509Stack(const std::string& path) throw(IOException) { // Create an empty X.509 stack. STACK_OF(X509)* stack = sk_X509_new_null(); if(stack == NULL) { THROW_IOEXCEPTION("Failed to create X.509 certificate stack."); } // Initialize OpenSSL file. BIO* file = BIO_new(BIO_s_file()); BIO_scope fileScope(&file); if(file == NULL) { THROW_IOEXCEPTION("Failed to open X.509 certificates file '%s': %s", path.c_str(), ERR_reason_error_string(ERR_get_error())); } // Open file, which can contain multiple X.509 certificates. if(BIO_read_filename(file, path.c_str()) <= 0) { THROW_IOEXCEPTION("Failed to open X.509 certificates file '%s': %s", path.c_str(), ERR_reason_error_string(ERR_get_error())); } // Read certificates info from the file. STACK_OF(X509_INFO)* certsInfo = PEM_X509_INFO_read_bio(file, NULL, NULL, NULL); if(certsInfo == NULL) { THROW_IOEXCEPTION("Failed to read X.509 certificates from file '%s': %s", path.c_str(), ERR_reason_error_string(ERR_get_error())); } // Put all found certificates to the stack. for(int i = 0; i < sk_X509_INFO_num(certsInfo); i++) { X509_INFO* xi = sk_X509_INFO_value(certsInfo, i); if(xi->x509 != NULL) { sk_X509_push(stack, xi->x509); xi->x509 = NULL; } } // Release resources. sk_X509_INFO_pop_free(certsInfo, X509_INFO_free); return stack; }
static STACK_OF(X509) * read_fullchain(const char *file, int *count) { int i; BIO *bio; STACK_OF(X509_INFO) *xis = NULL; X509_INFO *xi; STACK_OF(X509) *rv = NULL; *count = 0; if ((bio = BIO_new_file(file, "r")) == NULL) { warn("Unable to read a certificate from %s", file); return NULL; } if ((xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)) == NULL) { warnx("Unable to read PEM format from %s", file); return NULL; } BIO_free(bio); if (sk_X509_INFO_num(xis) <= 0) { warnx("No certificates in file %s", file); goto end; } if ((rv = sk_X509_new_null()) == NULL) { warnx("malloc failed"); goto end; } for (i = 0; i < sk_X509_INFO_num(xis); i++) { xi = sk_X509_INFO_value(xis, i); if (xi->x509 == NULL) continue; if (!sk_X509_push(rv, xi->x509)) { warnx("unable to build x509 chain"); sk_X509_pop_free(rv, X509_free); rv = NULL; goto end; } xi->x509 = NULL; (*count)++; } end: sk_X509_INFO_pop_free(xis, X509_INFO_free); return rv; }
/* * This function is used to load an X509_STORE using raw * data from a buffer. The data is expected to be PEM * encoded. * * Returns the number of certs added to the store */ static int ossl_init_cert_store_from_raw (X509_STORE *store, unsigned char *raw, int size) { STACK_OF(X509_INFO) * sk = NULL; X509_INFO *xi; BIO *in; int cert_cnt = 0; in = BIO_new_mem_buf(raw, size); if (in == NULL) { EST_LOG_ERR("Unable to open the raw CA cert buffer"); return 0; } /* This loads from a file, a stack of x509/crl/pkey sets */ sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); if (sk == NULL) { EST_LOG_ERR("Unable to read PEM encoded certs from BIO"); BIO_free(in); return 0; } BIO_free(in); /* scan over it and pull out the CRL's */ while (sk_X509_INFO_num(sk)) { xi = sk_X509_INFO_shift(sk); if (xi->x509 != NULL) { EST_LOG_INFO("Adding cert to store (%s)", xi->x509->name); X509_STORE_add_cert(store, xi->x509); cert_cnt++; } if (xi->crl != NULL) { EST_LOG_INFO("Adding CRL to store"); X509_STORE_add_crl(store, xi->crl); } X509_INFO_free(xi); } if (sk != NULL) { sk_X509_INFO_pop_free(sk, X509_INFO_free); } return (cert_cnt); }
static int hash_file(int dirfd, const char *filename) { STACK_OF(X509_INFO) *inf; X509_INFO *x; BIO *b; int i, count = 0; unsigned char digest[EVP_MAX_MD_SIZE]; b = BIO_openat(dirfd, filename); if (!b) return -1; inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL); BIO_free(b); if (!inf) return -1; for(i = 0; i < sk_X509_INFO_num(inf); i++) { x = sk_X509_INFO_value(inf, i); if (x->x509) { X509_digest(x->x509, evpmd, digest, NULL); link_file(dirfd, filename, TYPE_CERT, X509_subject_name_hash(x->x509), digest); count++; } if (x->crl) { X509_CRL_digest(x->crl, evpmd, digest, NULL); link_file(dirfd, filename, TYPE_CRL, X509_NAME_hash(X509_CRL_get_issuer(x->crl)), digest); count++; } } sk_X509_INFO_pop_free(inf, X509_INFO_free); if (count == 0) { fprintf(stderr, "WARNING: %s does not contain a certificate or CRL: skipping\n", filename); } return count; }
/* load a stack of x509 certificates */ STACK_OF(X509)* ocsp_load_certs(const char *file) { BIO *bio = NULL; STACK_OF(X509) *certs = NULL; STACK_OF(X509_INFO) *xis = NULL; X509_INFO *xi; int i; if ((bio = BIO_new_file(file, "r")) == NULL) { log_warn("%s: BIO_new_file failed for %s", __func__, file); return (NULL); } if ((xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)) == NULL) { ca_sslerror(__func__); goto done; } if ((certs = sk_X509_new_null()) == NULL) { log_debug("%s: sk_X509_new_null failed for %s", __func__, file); goto done; } for (i = 0; i < sk_X509_INFO_num(xis); i++) { xi = sk_X509_INFO_value(xis, i); if (xi->x509) { if (!sk_X509_push(certs, xi->x509)) goto done; xi->x509 = NULL; } } done: if (bio) BIO_free(bio); if (xis) sk_X509_INFO_pop_free(xis, X509_INFO_free); if (certs && sk_X509_num(certs) <= 0) { sk_X509_pop_free(certs, X509_free); certs = NULL; } return (certs); }
int ssl_by_mem_ctrl(X509_LOOKUP *lu, int cmd, const char *buf, long type, char **ret) { STACK_OF(X509_INFO) *inf; const struct iovec *iov; X509_INFO *itmp; BIO *in = NULL; int i, count = 0; iov = (const struct iovec *)buf; if (type != X509_FILETYPE_PEM) goto done; if ((in = BIO_new_mem_buf(iov->iov_base, iov->iov_len)) == NULL) goto done; if ((inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) goto done; for (i = 0; i < sk_X509_INFO_num(inf); i++) { itmp = sk_X509_INFO_value(inf, i); if (itmp->x509) { X509_STORE_add_cert(lu->store_ctx, itmp->x509); count++; } if (itmp->crl) { X509_STORE_add_crl(lu->store_ctx, itmp->crl); count++; } } sk_X509_INFO_pop_free(inf, X509_INFO_free); done: if (!count) X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_PEM_LIB); if (in != NULL) BIO_free(in); return (count); }
static int X509_load_cert_crl_mem(X509_LOOKUP *ctx, const char *mem) { STACK_OF(X509_INFO) *inf; X509_INFO *itmp; BIO *in; int i, count = 0; in = BIO_new(BIO_s_mem()); if (!in) { printk("X509_load_cert_crl_mem: cannot allocate BIO\n"); return 0; } BIO_write(in, mem, strlen(mem)); inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); BIO_free(in); if (!inf) { printk("X509_load_cert_crl_mem: cannot read X509_INFO\n"); return 0; } for (i = 0; i < sk_X509_INFO_num(inf); i++) { itmp = sk_X509_INFO_value(inf, i); if (itmp->x509) { X509_STORE_add_cert(ctx->store_ctx, itmp->x509); count++; } else if (itmp->crl) { X509_STORE_add_crl(ctx->store_ctx, itmp->crl); count++; } } sk_X509_INFO_pop_free(inf, X509_INFO_free); return count; }
int SSL_CTX_load_verify_mem(SSL_CTX *ctx, void *data, int data_len) { STACK_OF(X509_INFO) *stack = NULL; X509_INFO *info; int nstack, i, ret = 0, got = 0; BIO *bio; /* Read from memory */ bio = BIO_new_mem_buf(data, data_len); if (!bio) goto failed; /* Parse X509_INFO records */ stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); if (!stack) goto failed; /* Loop over stack, add certs and revocation records to store */ nstack = sk_X509_INFO_num(stack); for (i = 0; i < nstack; i++) { info = sk_X509_INFO_value(stack, i); if (info->x509 && !X509_STORE_add_cert(ctx->cert_store, info->x509)) goto failed; if (info->crl && !X509_STORE_add_crl(ctx->cert_store, info->crl)) goto failed; if (info->x509 || info->crl) got = 1; } ret = got; failed: if (bio) BIO_free(bio); if (stack) sk_X509_INFO_pop_free(stack, X509_INFO_free); if (!ret) X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB); return ret; }
STACK_OF(X509)* bdoc::X509Cert::loadX509Stack(const std::string& path) { STACK_OF(X509)* stack = sk_X509_new_null(); if (stack == NULL) { THROW_STACK_EXCEPTION("Failed to create X.509 certificate stack."); } BIO* file = BIO_new(BIO_s_file()); BIO_scope fileScope(&file); if (file == NULL) { THROW_STACK_EXCEPTION("Failed to open X.509 certificates file '%s': %s", path.c_str(), ERR_reason_error_string(ERR_get_error())); } if (BIO_read_filename(file, path.c_str()) <= 0) { THROW_STACK_EXCEPTION("Failed to open X.509 certificates file '%s': %s", path.c_str(), ERR_reason_error_string(ERR_get_error())); } STACK_OF(X509_INFO)* certsInfo = PEM_X509_INFO_read_bio(file, NULL, NULL, NULL); if (certsInfo == NULL) { THROW_STACK_EXCEPTION("Failed to read X.509 certificates from file '%s': %s", path.c_str(), ERR_reason_error_string(ERR_get_error())); } for (int i = 0; i < sk_X509_INFO_num(certsInfo); i++) { X509_INFO* xi = sk_X509_INFO_value(certsInfo, i); if (xi->x509 != NULL) { sk_X509_push(stack, xi->x509); xi->x509 = NULL; } } sk_X509_INFO_pop_free(certsInfo, X509_INFO_free); return stack; }
int openconnect_open_https(struct openconnect_info *vpninfo) { method_const SSL_METHOD *ssl3_method; SSL *https_ssl; BIO *https_bio; int ssl_sock; int err; if (vpninfo->https_ssl) return 0; if (vpninfo->peer_cert) { X509_free(vpninfo->peer_cert); vpninfo->peer_cert = NULL; } ssl_sock = connect_https_socket(vpninfo); if (ssl_sock < 0) return ssl_sock; ssl3_method = TLSv1_client_method(); if (!vpninfo->https_ctx) { vpninfo->https_ctx = SSL_CTX_new(ssl3_method); /* Some servers (or their firewalls) really don't like seeing extensions. */ #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(vpninfo->https_ctx, SSL_OP_NO_TICKET); #endif if (vpninfo->cert) { err = load_certificate(vpninfo); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Loading certificate failed. Aborting.\n")); SSL_CTX_free(vpninfo->https_ctx); vpninfo->https_ctx = NULL; close(ssl_sock); return err; } check_certificate_expiry(vpninfo); } /* We just want to do: SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY); ... but it doesn't work with OpenSSL < 0.9.8k because of problems with inheritance (fixed in v1.1.4.6 of crypto/x509/x509_vpm.c) so we have to play silly buggers instead. This trick doesn't work _either_ in < 0.9.7 but I don't know of _any_ workaround which will, and can't be bothered to find out either. */ #if OPENSSL_VERSION_NUMBER >= 0x00908000 SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx, ssl_app_verify_callback, NULL); #endif SSL_CTX_set_default_verify_paths(vpninfo->https_ctx); #ifdef ANDROID_KEYSTORE if (vpninfo->cafile && !strncmp(vpninfo->cafile, "keystore:", 9)) { STACK_OF(X509_INFO) *stack; X509_STORE *store; X509_INFO *info; BIO *b = BIO_from_keystore(vpninfo, vpninfo->cafile); if (!b) { SSL_CTX_free(vpninfo->https_ctx); vpninfo->https_ctx = NULL; close(ssl_sock); return -EINVAL; } stack = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL); BIO_free(b); if (!stack) { vpn_progress(vpninfo, PRG_ERR, _("Failed to read certs from CA file '%s'\n"), vpninfo->cafile); openconnect_report_ssl_errors(vpninfo); SSL_CTX_free(vpninfo->https_ctx); vpninfo->https_ctx = NULL; close(ssl_sock); return -ENOENT; } store = SSL_CTX_get_cert_store(vpninfo->https_ctx); while ((info = sk_X509_INFO_pop(stack))) { if (info->x509) X509_STORE_add_cert(store, info->x509); if (info->crl) X509_STORE_add_crl(store, info->crl); X509_INFO_free(info); } sk_X509_INFO_free(stack); } else #endif if (vpninfo->cafile) { if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) { vpn_progress(vpninfo, PRG_ERR, _("Failed to open CA file '%s'\n"), vpninfo->cafile); openconnect_report_ssl_errors(vpninfo); SSL_CTX_free(vpninfo->https_ctx); vpninfo->https_ctx = NULL; close(ssl_sock); return -EINVAL; } } } https_ssl = SSL_new(vpninfo->https_ctx); workaround_openssl_certchain_bug(vpninfo, https_ssl); https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE); BIO_set_nbio(https_bio, 1); SSL_set_bio(https_ssl, https_bio, https_bio); vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"), vpninfo->hostname); while ((err = SSL_connect(https_ssl)) <= 0) { fd_set wr_set, rd_set; int maxfd = ssl_sock; FD_ZERO(&wr_set); FD_ZERO(&rd_set); err = SSL_get_error(https_ssl, err); if (err == SSL_ERROR_WANT_READ) FD_SET(ssl_sock, &rd_set); else if (err == SSL_ERROR_WANT_WRITE) FD_SET(ssl_sock, &wr_set); else { vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n")); openconnect_report_ssl_errors(vpninfo); SSL_free(https_ssl); close(ssl_sock); return -EINVAL; } cmd_fd_set(vpninfo, &rd_set, &maxfd); select(maxfd + 1, &rd_set, &wr_set, NULL, NULL); if (is_cancel_pending(vpninfo, &rd_set)) { vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n")); SSL_free(https_ssl); close(ssl_sock); return -EINVAL; } } if (verify_peer(vpninfo, https_ssl)) { SSL_free(https_ssl); close(ssl_sock); return -EINVAL; } vpninfo->ssl_fd = ssl_sock; vpninfo->https_ssl = https_ssl; /* Stash this now, because it might not be available later if the server has disconnected. */ vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl); vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"), vpninfo->hostname); return 0; }
int tls_configure_ssl_verify(struct tls *ctx, SSL_CTX *ssl_ctx, int verify) { size_t ca_len = ctx->config->ca_len; char *ca_mem = ctx->config->ca_mem; char *crl_mem = ctx->config->crl_mem; size_t crl_len = ctx->config->crl_len; char *ca_free = NULL; STACK_OF(X509_INFO) *xis = NULL; X509_STORE *store; X509_INFO *xi; BIO *bio = NULL; int rv = -1; int i; SSL_CTX_set_verify(ssl_ctx, verify, NULL); SSL_CTX_set_cert_verify_callback(ssl_ctx, tls_ssl_cert_verify_cb, ctx); if (ctx->config->verify_depth >= 0) SSL_CTX_set_verify_depth(ssl_ctx, ctx->config->verify_depth); if (ctx->config->verify_cert == 0) goto done; /* If no CA has been specified, attempt to load the default. */ if (ctx->config->ca_mem == NULL && ctx->config->ca_path == NULL) { if (tls_config_load_file(&ctx->error, "CA", _PATH_SSL_CA_FILE, &ca_mem, &ca_len) != 0) goto err; ca_free = ca_mem; } if (ca_mem != NULL) { if (ca_len > INT_MAX) { tls_set_errorx(ctx, "ca too long"); goto err; } if (SSL_CTX_load_verify_mem(ssl_ctx, ca_mem, ca_len) != 1) { tls_set_errorx(ctx, "ssl verify memory setup failure"); goto err; } } else if (SSL_CTX_load_verify_locations(ssl_ctx, NULL, ctx->config->ca_path) != 1) { tls_set_errorx(ctx, "ssl verify locations failure"); goto err; } if (crl_mem != NULL) { if (crl_len > INT_MAX) { tls_set_errorx(ctx, "crl too long"); goto err; } if ((bio = BIO_new_mem_buf(crl_mem, crl_len)) == NULL) { tls_set_errorx(ctx, "failed to create buffer"); goto err; } if ((xis = PEM_X509_INFO_read_bio(bio, NULL, tls_password_cb, NULL)) == NULL) { tls_set_errorx(ctx, "failed to parse crl"); goto err; } store = SSL_CTX_get_cert_store(ssl_ctx); for (i = 0; i < sk_X509_INFO_num(xis); i++) { xi = sk_X509_INFO_value(xis, i); if (xi->crl == NULL) continue; if (!X509_STORE_add_crl(store, xi->crl)) { tls_set_error(ctx, "failed to add crl"); goto err; } xi->crl = NULL; } X509_VERIFY_PARAM_set_flags(store->param, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } done: rv = 0; err: sk_X509_INFO_pop_free(xis, X509_INFO_free); BIO_free(bio); free(ca_free); return (rv); }
void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, const char *ca_file_inline, const char *ca_path, bool tls_server ) { STACK_OF(X509_INFO) *info_stack = NULL; STACK_OF(X509_NAME) *cert_names = NULL; X509_LOOKUP *lookup = NULL; X509_STORE *store = NULL; X509_NAME *xn = NULL; BIO *in = NULL; int i, added = 0; ASSERT(NULL != ctx); store = SSL_CTX_get_cert_store(ctx->ctx); if (!store) msg(M_SSLERR, "Cannot get certificate store (SSL_CTX_get_cert_store)"); /* Try to add certificates and CRLs from ca_file */ if (ca_file) { if (!strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline) in = BIO_new_mem_buf ((char *)ca_file_inline, -1); else in = BIO_new_file (ca_file, "r"); if (in) info_stack = PEM_X509_INFO_read_bio (in, NULL, NULL, NULL); if (info_stack) { for (i = 0; i < sk_X509_INFO_num (info_stack); i++) { X509_INFO *info = sk_X509_INFO_value (info_stack, i); if (info->crl) X509_STORE_add_crl (store, info->crl); if (info->x509) { X509_STORE_add_cert (store, info->x509); added++; if (!tls_server) continue; /* Use names of CAs as a client CA list */ if (cert_names == NULL) { cert_names = sk_X509_NAME_new (sk_x509_name_cmp); if (!cert_names) continue; } xn = X509_get_subject_name (info->x509); if (!xn) continue; /* Don't add duplicate CA names */ if (sk_X509_NAME_find (cert_names, xn) == -1) { xn = X509_NAME_dup (xn); if (!xn) continue; sk_X509_NAME_push (cert_names, xn); } } } sk_X509_INFO_pop_free (info_stack, X509_INFO_free); } if (tls_server) SSL_CTX_set_client_CA_list (ctx->ctx, cert_names); if (!added || (tls_server && sk_X509_NAME_num (cert_names) != added)) msg (M_SSLERR, "Cannot load CA certificate file %s", np(ca_file)); if (in) BIO_free (in); } /* Set a store for certs (CA & CRL) with a lookup on the "capath" hash directory */ if (ca_path) { lookup = X509_STORE_add_lookup (store, X509_LOOKUP_hash_dir ()); if (lookup && X509_LOOKUP_add_dir (lookup, ca_path, X509_FILETYPE_PEM)) msg(M_WARN, "WARNING: experimental option --capath %s", ca_path); else msg(M_SSLERR, "Cannot add lookup at --capath %s", ca_path); #if OPENSSL_VERSION_NUMBER >= 0x00907000L X509_STORE_set_flags (store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); #else msg(M_WARN, "WARNING: this version of OpenSSL cannot handle CRL files in capath"); #endif } }