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; }
bool CERTIFICATE_FILE_CLASS::removeCertificate(int index) // DESCRIPTION : Remove the certificate at the given index. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { int numberOfCerts; if ((openSslM_ptr == NULL) || (x509InfoListM_ptr == NULL)) { return NULL; } numberOfCerts = sk_X509_INFO_num(x509InfoListM_ptr); if ( (index < 0) || (index >= numberOfCerts)) { // index out of range if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Index out of bounds in CERTIFICATE_FILE_CLASS::removeCertificate()"); } return false; } // delete the certificate sk_X509_INFO_delete(x509InfoListM_ptr, index); changedM = true; return true; ; }
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; }
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; }
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; }
CERTIFICATE_CLASS* CERTIFICATE_FILE_CLASS::getCertificate(int index) // DESCRIPTION : Return the certificate at the given index. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : The caller needs to delete the certificate //<<=========================================================================== { int numberOfCerts; X509_INFO* x509Info_ptr; CERTIFICATE_CLASS* cert_ptr; if ((openSslM_ptr == NULL) || (x509InfoListM_ptr == NULL)) { return NULL; } numberOfCerts = sk_X509_INFO_num(x509InfoListM_ptr); if ( (index < 0) || (index >= numberOfCerts)) { // index out of range if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Index out of bounds in CERTIFICATE_FILE_CLASS::getCertificate()"); } return NULL; } // get the certificate x509Info_ptr = sk_X509_INFO_value(x509InfoListM_ptr, index); if (x509Info_ptr == NULL) { openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "getting certificate"); return NULL; } if (x509Info_ptr->x509 != NULL) { cert_ptr = new CERTIFICATE_CLASS(x509Info_ptr->x509); } else if (x509Info_ptr->x_pkey != NULL) { cert_ptr = new CERTIFICATE_CLASS(x509Info_ptr->x_pkey->dec_pkey); } else { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "No data in information structure while getting certificate"); } return NULL; } return cert_ptr; }
bool CERTIFICATE_FILE_CLASS::moveCertificate(int oldIndex, int newIndex) // DESCRIPTION : Moves the certificate at the given index to the new index. // : The newIndex will be the index the certificate will be at // : after the move is complete. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { int numberOfCerts; X509_INFO* x509Info_ptr; if ((openSslM_ptr == NULL) || (x509InfoListM_ptr == NULL)) { return NULL; } numberOfCerts = sk_X509_INFO_num(x509InfoListM_ptr); if ((oldIndex < 0) || (oldIndex >= numberOfCerts) || (newIndex < 0) || (newIndex >= numberOfCerts)) { // index out of range if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Index out of bounds in CERTIFICATE_FILE_CLASS::moveCertificate()"); } return false; } // get the certificate x509Info_ptr = sk_X509_INFO_value(x509InfoListM_ptr, oldIndex); if (x509Info_ptr == NULL) { openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "getting certificate"); return NULL; } // delete the certificate sk_X509_INFO_delete(x509InfoListM_ptr, oldIndex); // add the certificate back in if (newIndex > oldIndex) { newIndex--; // adjust the index value for the deleted certificate } sk_X509_INFO_insert(x509InfoListM_ptr, x509Info_ptr, newIndex); changedM = true; return true; ; }
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; }
int CERTIFICATE_FILE_CLASS::getNumberOfCertificates() // DESCRIPTION : Return the number of certificates available. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { if ((openSslM_ptr == NULL) || (x509InfoListM_ptr == NULL)) { return 0; } return sk_X509_INFO_num(x509InfoListM_ptr); }
/* * 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 STACK_OF(X509_INFO) * load_decryption_certs_keys(const char *dirname) { AUTO_STACK(X509_INFO, infos); AUTO(DIR, dir); if (dirname == NULL) return NULL; infos = sk_X509_INFO_new_null(); if (infos == NULL) return NULL; dir = opendir(dirname); if (dir == NULL) return NULL; for (struct dirent *de = readdir(dir); de != NULL; de = readdir(dir)) { char path[strlen(dirname) + strlen(de->d_name) + 2]; AUTO(FILE, file); if (!deo_isreg(dirname, de)) continue; strcpy(path, dirname); strcat(path, "/"); strcat(path, de->d_name); file = fopen(path, "r"); if (file == NULL) return NULL; if (PEM_X509_INFO_read(file, infos, NULL, NULL) == NULL) return NULL; } if (sk_X509_INFO_num(infos) == 0) return NULL; return STEAL(infos); }
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; }
ctx * ctx_init(const char *tls, const char *enc, const char *dec) { const int ops = SSL_OP_NO_COMPRESSION | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; AUTO(EVP_PKEY, prv); AUTO(FILE, file); AUTO(ctx, ctx); if (tls == NULL || enc == NULL || dec == NULL) return NULL; ctx = OPENSSL_malloc(sizeof(*ctx)); if (ctx == NULL) return NULL; memset(ctx, 0, sizeof(*ctx)); ctx->ctx = SSL_CTX_new(SSLv23_server_method()); if (ctx->ctx == NULL) return NULL; if (SSL_CTX_set_options(ctx->ctx, ops) <= 0) return NULL; if (SSL_CTX_use_certificate_chain_file(ctx->ctx, tls) <= 0) return NULL; prv = load_prv(tls); if (prv == NULL) return NULL; if (SSL_CTX_use_PrivateKey(ctx->ctx, prv) <= 0) return NULL; file = fopen(enc, "r"); if (file == NULL) return NULL; ctx->crt = sk_X509_new_null(); if (ctx->crt == NULL) return NULL; if (!deo_load(file, ctx->crt)) return NULL; ctx->dec = load_decryption_certs_keys(dec); if (ctx->dec == NULL) return NULL; /* Check to ensure that the TLS connection key is not also listed * in the decryption keys. This prevents an attack where, upon * misconfiguration, this service could be used to decrypt its own * traffic. */ for (int i = 0; i < sk_X509_INFO_num(ctx->dec); i++) { X509_INFO *info = sk_X509_INFO_value(ctx->dec, i); if (info->x_pkey == NULL) continue; if (EVP_PKEY_cmp(prv, info->x_pkey->dec_pkey) == 1) { fprintf(stderr, "TLS private key is exposed!\n"); return NULL; } } return STEAL(ctx); }
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); }
bool CERTIFICATE_FILE_CLASS::verify(bool isCredentials, char **msg_ptrptr) // DESCRIPTION : verifies the contents of the file to make sure it is of the correct format // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { int numberOfCerts; int i; X509_INFO* x509Info_ptr; if ((openSslM_ptr == NULL) || (x509InfoListM_ptr == NULL)) { *msg_ptrptr = "Secure Socket Library not present"; return false; } if (isCredentials) { // credentials file bool waitingForCertificate = false; // indicates that the next PEM read must be a certificate bool rsaKeyRead = false; bool dsaKeyRead = false; bool lastKeyReadRsa = false; // indicates that we are working on the RSA key and certificates, // otherwise, we are working on the DSA key and certificate. numberOfCerts = sk_X509_INFO_num(x509InfoListM_ptr); for (i = 0; i < numberOfCerts; i++) { // get the PEM info x509Info_ptr = sk_X509_INFO_value(x509InfoListM_ptr, i); if (x509Info_ptr == NULL) { *msg_ptrptr = "internal error"; return false; } if (x509Info_ptr->x_pkey != NULL) { // private key if (waitingForCertificate) { *msg_ptrptr = "Private key does not have a corresponding certificate"; return false; } if (x509Info_ptr->x_pkey->dec_pkey->type == EVP_PKEY_RSA) { // rsa key if (rsaKeyRead) { *msg_ptrptr = "More than one RSA Private Key in credentials file"; return false; } rsaKeyRead = true; lastKeyReadRsa = true; // we are reading rsa keys now } else if (x509Info_ptr->x_pkey->dec_pkey->type == EVP_PKEY_DSA) { // dsa key if (dsaKeyRead) { *msg_ptrptr = "More than one DSA Private Key in credentials file"; return false; } dsaKeyRead = true; lastKeyReadRsa = false; // we are reading dsa keys now } else { *msg_ptrptr = "Unsupported private key type"; return false; } waitingForCertificate = true; // the next thing in the file needs to be the public key certificate } if (x509Info_ptr->x509 != NULL) { // certificate if (!rsaKeyRead && !dsaKeyRead) { // no private key read yet *msg_ptrptr = "Credentials file starts with a certificate. Must start with a private key."; return false; } waitingForCertificate = false; // check certificate chain } } // check to make sure all is well if (waitingForCertificate) { // file didn't have required certificate *msg_ptrptr = "Private key does not have a corresponding certificate at end of credentials file"; return false; } if (!rsaKeyRead && !dsaKeyRead && (numberOfCerts > 0)) { // no private key read *msg_ptrptr = "Credentials file has no private keys"; return false; } } else { // trusted certificate file numberOfCerts = sk_X509_INFO_num(x509InfoListM_ptr); for (i = 0; i < numberOfCerts; i++) { // get the PEM info x509Info_ptr = sk_X509_INFO_value(x509InfoListM_ptr, i); if (x509Info_ptr == NULL) { *msg_ptrptr = "internal error"; return false; } if (x509Info_ptr->x_pkey != NULL) { // private key, not expected in certificate file *msg_ptrptr = "Private Key not expected in a trusted certificate file"; return false; } if (x509Info_ptr->x509 != NULL) { // certificate, check certificate chain } } } // if we got here there were no errors return true; }
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 } }