void tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file #if ENABLE_INLINE_FILES , const char *extra_certs_file_inline #endif ) { BIO *bio; X509 *cert; #if ENABLE_INLINE_FILES if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_file_inline) { bio = BIO_new_mem_buf ((char *)extra_certs_file_inline, -1); } else #endif { bio = BIO_new(BIO_s_file()); if (BIO_read_filename(bio, extra_certs_file) <= 0) msg (M_SSLERR, "Cannot load extra-certs file: %s", extra_certs_file); } for (;;) { cert = NULL; if (!PEM_read_bio_X509 (bio, &cert, 0, NULL)) /* takes ownership of cert */ break; if (!cert) msg (M_SSLERR, "Error reading extra-certs certificate"); if (SSL_CTX_add_extra_chain_cert(ctx->ctx, cert) != 1) msg (M_SSLERR, "Error adding extra-certs certificate"); } BIO_free (bio); }
int SSL_CTX_use_certificate_chain_mem(SSL_CTX *ctx, void *data, int data_len) { pem_password_cb *psw_fn = ctx->default_passwd_callback; void *psw_arg = ctx->default_passwd_callback_userdata; X509 *cert; BIO *bio = NULL; int ok; ERR_clear_error(); /* Read from memory */ bio = BIO_new_mem_buf(data, data_len); if (!bio) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); goto failed; } /* Load primary cert */ cert = PEM_read_bio_X509_AUX(bio, NULL, psw_fn, psw_arg); if (!cert) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); goto failed; } /* Increments refcount */ ok = SSL_CTX_use_certificate(ctx, cert); X509_free(cert); if (!ok || ERR_peek_error()) goto failed; /* Load extra certs */ ok = SSL_CTX_clear_extra_chain_certs(ctx); while (ok) { cert = PEM_read_bio_X509(bio, NULL, psw_fn, psw_arg); if (!cert) { /* Is it EOF? */ unsigned long err = ERR_peek_last_error(); if (ERR_GET_LIB(err) != ERR_LIB_PEM) break; if (ERR_GET_REASON(err) != PEM_R_NO_START_LINE) break; /* On EOF do successful exit */ BIO_free(bio); ERR_clear_error(); return 1; } /* Does not increment refcount */ ok = SSL_CTX_add_extra_chain_cert(ctx, cert); if (!ok) X509_free(cert); } failed: if (bio) BIO_free(bio); return 0; }
void Context::addChainCertificate(const Poco::Crypto::X509Certificate& certificate) { int errCode = SSL_CTX_add_extra_chain_cert(_pSSLContext, certificate.certificate()); if (errCode != 1) { std::string msg = Utility::getLastError(); throw SSLContextException("Cannot add chain certificate to Context", msg); } }
void SSLContext::addChainCertificate(const crypto::X509Certificate& certificate) { int errCode = SSL_CTX_add_extra_chain_cert(_sslContext, certificate.certificate()); if (errCode != 1) { std::string msg = getLastError(); throw std::runtime_error("SSL Error: Cannot add chain certificate to Context: " + msg); } }
static VALUE ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg) { X509 *x509; SSL_CTX *ctx; Data_Get_Struct(arg, SSL_CTX, ctx); x509 = DupX509CertPtr(i); if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){ ossl_raise(eSSLError, NULL); } return i; }
extern "C" int32_t CryptoNative_SslAddExtraChainCert(SSL* ssl, X509* x509) { if (!x509 || !ssl) { return 0; } SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl); if (SSL_CTX_add_extra_chain_cert(ssl_ctx, x509) == 1) { return 1; } return 0; }
static void tls_ctx_add_extra_certs (struct tls_root_ctx *ctx, BIO *bio) { X509 *cert; for (;;) { cert = NULL; if (!PEM_read_bio_X509 (bio, &cert, 0, NULL)) /* takes ownership of cert */ break; if (!cert) msg (M_SSLERR, "Error reading extra certificate"); if (SSL_CTX_add_extra_chain_cert(ctx->ctx, cert) != 1) msg (M_SSLERR, "Error adding extra certificate"); } }
int SSL_CTX_build_cert_chain(SSL_CTX* ssl_ctx, X509** certs, int count) { int i; for (i = count - 1; i >= 0; --i) if (!SSL_CTX_add_extra_chain_cert(ssl_ctx, certs[i])) { write_out(PRINT_ERROR, "Unable to build certificate chain."); write_raise_level(); print_ssl_error_stack(PRINT_ERROR); write_lower_level(); return 0; } return 1; }
void ContextImpl::addCertificate(const Certificate& certificate) { // NOTE: SSL_CTX_add_extra_chain_cert does not copy the X509 certificate, // or increase the refcount. We must copy it, because the SSL_CTX will // free it _extraCerts.reserve(_extraCerts.size() + 1); X509* extraX509 = copyX509( certificate.impl()->x509() ); X509AutoPtr x509Ptr(extraX509); if( ! SSL_CTX_add_extra_chain_cert(_ctx, extraX509) ) { throw InvalidCertificate("invalid extra certificate"); } _extraCerts.push_back(extraX509); x509Ptr.release(); }
static int openssl_ssl_ctx_add(lua_State*L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); X509* x = CHECK_OBJECT(2, X509, "openssl.x509"); int ret = SSL_CTX_add_client_CA(ctx, x); if (ret == 1 && !lua_isnoneornil(L, 3)) { size_t i; luaL_checktable(L, 3); for (i = 1; ret == 1 && i <= lua_rawlen(L, 3); i++ ) { lua_rawgeti(L, 3, i); x = CHECK_OBJECT(2, X509, "openssl.x509"); lua_pop(L, 1); CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); ret = SSL_CTX_add_extra_chain_cert(ctx, x); } } return openssl_pushresult(L, ret); }
/* Loads an in-memory PEM certificate chain into the SSL context. */ static tsi_result ssl_ctx_use_certificate_chain( SSL_CTX* context, const unsigned char* pem_cert_chain, size_t pem_cert_chain_size) { tsi_result result = TSI_OK; X509* certificate = NULL; BIO* pem = BIO_new_mem_buf((void*)pem_cert_chain, pem_cert_chain_size); if (pem == NULL) return TSI_OUT_OF_RESOURCES; do { certificate = PEM_read_bio_X509_AUX(pem, NULL, NULL, ""); if (certificate == NULL) { result = TSI_INVALID_ARGUMENT; break; } if (!SSL_CTX_use_certificate(context, certificate)) { result = TSI_INVALID_ARGUMENT; break; } while (1) { X509* certificate_authority = PEM_read_bio_X509(pem, NULL, NULL, ""); if (certificate_authority == NULL) { ERR_clear_error(); break; /* Done reading. */ } if (!SSL_CTX_add_extra_chain_cert(context, certificate_authority)) { X509_free(certificate_authority); result = TSI_INVALID_ARGUMENT; break; } /* We don't need to free certificate_authority as its ownership has been transfered to the context. That is not the case for certificate though. */ } } while (0); if (certificate != NULL) X509_free(certificate); BIO_free(pem); return result; }
bool OpenSSLContext::setClientCertificate(CertificateWithKey::ref certificate) { boost::shared_ptr<PKCS12Certificate> pkcs12Certificate = boost::dynamic_pointer_cast<PKCS12Certificate>(certificate); if (!pkcs12Certificate || pkcs12Certificate->isNull()) { return false; } // Create a PKCS12 structure BIO* bio = BIO_new(BIO_s_mem()); BIO_write(bio, vecptr(pkcs12Certificate->getData()), pkcs12Certificate->getData().size()); boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free); BIO_free(bio); if (!pkcs12) { return false; } // Parse PKCS12 X509 *certPtr = 0; EVP_PKEY* privateKeyPtr = 0; STACK_OF(X509)* caCertsPtr = 0; int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(pkcs12Certificate->getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr); if (result != 1) { return false; } boost::shared_ptr<X509> cert(certPtr, X509_free); boost::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free); boost::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack); // Use the key & certificates if (SSL_CTX_use_certificate(context_, cert.get()) != 1) { return false; } if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) { return false; } for (int i = 0; i < sk_X509_num(caCerts.get()); ++i) { SSL_CTX_add_extra_chain_cert(context_, sk_X509_value(caCerts.get(), i)); } return true; }
static void workaround_openssl_certchain_bug(struct openconnect_info *vpninfo, SSL *ssl) { /* OpenSSL has problems with certificate chains -- if there are multiple certs with the same name, it doesn't necessarily choose the _right_ one. (RT#1942) Pick the right ones for ourselves and add them manually. */ X509 *cert = SSL_get_certificate(ssl); X509 *cert2; X509_STORE *store = SSL_CTX_get_cert_store(vpninfo->https_ctx); X509_STORE_CTX ctx; if (!cert || !store) return; /* If we already have 'supporting' certs, don't add them again */ if (vpninfo->https_ctx->extra_certs) return; if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) return; while (ctx.get_issuer(&cert2, &ctx, cert) == 1) { char buf[200]; if (cert2 == cert) break; if (X509_check_issued(cert2, cert2) == X509_V_OK) break; cert = cert2; X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); vpn_progress(vpninfo, PRG_DEBUG, _("Extra cert from cafile: '%s'\n"), buf); SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert); } X509_STORE_CTX_cleanup(&ctx); }
/* Read a file that contains our certificate in "PEM" format, * possibly followed by a sequence of CA certificates that should be * sent to the peer in the Certificate message. */ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) { BIO *in; int ret=0; X509 *x=NULL; ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ in=BIO_new(BIO_s_file_internal()); if (in == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_BUF_LIB); goto end; } if (BIO_read_filename(in,file) <= 0) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_SYS_LIB); goto end; } x=PEM_read_bio_X509_AUX(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); if (x == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_PEM_LIB); goto end; } ret=SSL_CTX_use_certificate(ctx,x); if (ERR_peek_error() != 0) ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */ if (ret) { /* If we could set up our certificate, now proceed to * the CA certificates. */ X509 *ca; int r; unsigned long err; if (ctx->extra_certs != NULL) { sk_X509_pop_free(ctx->extra_certs, X509_free); ctx->extra_certs = NULL; } while ((ca = PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata)) != NULL) { r = SSL_CTX_add_extra_chain_cert(ctx, ca); if (!r) { X509_free(ca); ret = 0; goto end; } /* Note that we must not free r if it was successfully * added to the chain (while we must free the main * certificate, since its reference count is increased * by SSL_CTX_use_certificate). */ } /* When the while loop ends, it's usually just EOF. */ err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) ERR_clear_error(); else ret = 0; /* some real error */ } end: if (x != NULL) X509_free(x); if (in != NULL) BIO_free(in); return(ret); }
int tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, const char *pkcs12_file_inline, bool load_ca_file ) { FILE *fp; EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *ca = NULL; PKCS12 *p12; int i; char password[256]; ASSERT(NULL != ctx); if (!strcmp (pkcs12_file, INLINE_FILE_TAG) && pkcs12_file_inline) { BIO *b64 = BIO_new(BIO_f_base64()); BIO *bio = BIO_new_mem_buf((void *) pkcs12_file_inline, (int) strlen(pkcs12_file_inline)); ASSERT(b64 && bio); BIO_push(b64, bio); p12 = d2i_PKCS12_bio(b64, NULL); if (!p12) msg(M_SSLERR, "Error reading inline PKCS#12 file"); BIO_free(b64); BIO_free(bio); } else { /* Load the PKCS #12 file */ if (!(fp = platform_fopen(pkcs12_file, "rb"))) msg(M_SSLERR, "Error opening file %s", pkcs12_file); p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (!p12) msg(M_SSLERR, "Error reading PKCS#12 file %s", pkcs12_file); } /* Parse the PKCS #12 file */ if (!PKCS12_parse(p12, "", &pkey, &cert, &ca)) { pem_password_callback (password, sizeof(password) - 1, 0, NULL); /* Reparse the PKCS #12 file with password */ ca = NULL; if (!PKCS12_parse(p12, password, &pkey, &cert, &ca)) { #ifdef ENABLE_MANAGEMENT if (management && (ERR_GET_REASON (ERR_peek_error()) == PKCS12_R_MAC_VERIFY_FAILURE)) management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); #endif PKCS12_free(p12); return 1; } } PKCS12_free(p12); /* Load Certificate */ if (!SSL_CTX_use_certificate (ctx->ctx, cert)) msg (M_SSLERR, "Cannot use certificate"); /* Load Private Key */ if (!SSL_CTX_use_PrivateKey (ctx->ctx, pkey)) msg (M_SSLERR, "Cannot use private key"); warn_if_group_others_accessible (pkcs12_file); /* Check Private Key */ if (!SSL_CTX_check_private_key (ctx->ctx)) msg (M_SSLERR, "Private key does not match the certificate"); /* Set Certificate Verification chain */ if (load_ca_file) { /* Add CAs from PKCS12 to the cert store and mark them as trusted. * They're also used to fill in the chain of intermediate certs as * necessary. */ if (ca && sk_X509_num(ca)) { for (i = 0; i < sk_X509_num(ca); i++) { if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)"); if (!SSL_CTX_add_client_CA(ctx->ctx, sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)"); } } } else { /* If trusted CA certs were loaded from a PEM file, and we ignore the * ones in PKCS12, do load PKCS12-provided certs to the client extra * certs chain just in case they include intermediate CAs needed to * prove my identity to the other end. This does not make them trusted. */ if (ca && sk_X509_num(ca)) { for (i = 0; i < sk_X509_num(ca); i++) { if (!SSL_CTX_add_extra_chain_cert(ctx->ctx,sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add extra certificate to chain (SSL_CTX_add_extra_chain_cert)"); } } } return 0; }
/** * NOTE: From node.js * * Read a file that contains our certificate in "PEM" format, * possibly followed by a sequence of CA certificates that should be * sent to the peer in the Certificate message. * * Taken from OpenSSL - editted for style. */ int bud_context_use_certificate_chain(bud_context_t* ctx, BIO *in) { int ret; X509* x; X509* ca; X509_STORE* store; X509_STORE_CTX store_ctx; int r; unsigned long err; ERR_clear_error(); ret = 0; x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); if (x == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); goto end; } ret = SSL_CTX_use_certificate(ctx->ctx, x); ctx->cert = x; ctx->issuer = NULL; if (ERR_peek_error() != 0) { /* Key/certificate mismatch doesn't imply ret==0 ... */ ret = 0; } if (ret) { /** * If we could set up our certificate, now proceed to * the CA certificates. */ if (ctx->ctx->extra_certs != NULL) { sk_X509_pop_free(ctx->ctx->extra_certs, X509_free); ctx->ctx->extra_certs = NULL; } while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) { r = SSL_CTX_add_extra_chain_cert(ctx->ctx, ca); if (!r) { X509_free(ca); ret = 0; goto end; } /** * Note that we must not free r if it was successfully * added to the chain (while we must free the main * certificate, since its reference count is increased * by SSL_CTX_use_certificate). */ /* Find issuer */ if (ctx->issuer != NULL || X509_check_issued(ca, x) != X509_V_OK) continue; ctx->issuer = ca; } /* When the while loop ends, it's usually just EOF. */ err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { ERR_clear_error(); } else { /* some real error */ ret = 0; } } end: if (ret) { /* Try getting issuer from cert store */ if (ctx->issuer == NULL) { store = SSL_CTX_get_cert_store(ctx->ctx); ret = X509_STORE_CTX_init(&store_ctx, store, NULL, NULL); if (!ret) goto fatal; ret = X509_STORE_CTX_get1_issuer(&ctx->issuer, &store_ctx, ctx->cert); X509_STORE_CTX_cleanup(&store_ctx); ret = ret < 0 ? 0 : 1; /* NOTE: get_cert_store doesn't increment reference count */ } else { /* Increment issuer reference count */ CRYPTO_add(&ctx->issuer->references, 1, CRYPTO_LOCK_X509); } if (ctx->issuer != NULL) { /* Get ocsp_id */ ctx->ocsp_id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer); if (ctx->ocsp_id == NULL) { ctx->issuer = NULL; goto fatal; } } } else { if (ctx->issuer != NULL) X509_free(ctx->issuer); } fatal: if (ctx->cert != x && x != NULL) X509_free(x); return ret; }
long SSL_CTX_add_extra_chain_cert_shim(SSL_CTX *ctx, X509 *x509) { return SSL_CTX_add_extra_chain_cert(ctx, x509); }
bool TLS_SOCKET_CLASS::readCredentials(SSL_CTX* ctx_ptr) // DESCRIPTION : Reads the credentials file. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { bool ret = false; X509* certificate_ptr = NULL; X509* caCert_ptr = NULL; EVP_PKEY* rsaPrivateKey_ptr; STACK_OF(X509)* rsaCertChain_ptr; EVP_PKEY* dsaPrivateKey_ptr; STACK_OF(X509)* dsaCertChain_ptr; // clear the current certificate list if (ctx_ptr->extra_certs != NULL) { sk_X509_pop_free(ctx_ptr->extra_certs, X509_free); ctx_ptr->extra_certs = NULL; } // read the credentials file openSslM_ptr->readCredentialsFile(credentialsFilenameM.c_str(), &rsaPrivateKey_ptr, &rsaCertChain_ptr, &dsaPrivateKey_ptr, &dsaCertChain_ptr, ctx_ptr->default_passwd_callback, ctx_ptr->default_passwd_callback_userdata, loggerM_ptr); if (rsaPrivateKey_ptr != NULL) { // have a RSA private key if (SSL_CTX_use_PrivateKey(ctx_ptr, rsaPrivateKey_ptr) != 1) { goto end; } // get and save the certificate that goes with the RSA private key certificate_ptr = sk_X509_shift(rsaCertChain_ptr); if (SSL_CTX_use_certificate(ctx_ptr, certificate_ptr) != 1) { goto end; } if (ERR_peek_error() != 0) { ret = 0; // key/certificate mismatch doesn't imply ret==0 ... goto end; } X509_free(certificate_ptr); certificate_ptr = NULL; // save the rest of the certificate chain while ((caCert_ptr = sk_X509_shift(rsaCertChain_ptr)) != NULL) { if (SSL_CTX_add_extra_chain_cert(ctx_ptr, caCert_ptr) != 1) { X509_free(caCert_ptr); goto end; } // note that caCert_ptr must not be freed if it was successfully added to the chain } } if (dsaPrivateKey_ptr != NULL) { // have a DSA private key if (SSL_CTX_use_PrivateKey(ctx_ptr, dsaPrivateKey_ptr) != 1) { goto end; } // get and save the certificate that goes with the DSA private key certificate_ptr = sk_X509_shift(dsaCertChain_ptr); if (SSL_CTX_use_certificate(ctx_ptr, certificate_ptr) != 1) { goto end; } if (ERR_peek_error() != 0) { ret = 0; // key/certificate mismatch doesn't imply ret==0 ... goto end; } X509_free(certificate_ptr); certificate_ptr = NULL; // save the rest of the certificate chain while ((caCert_ptr = sk_X509_shift(dsaCertChain_ptr)) != NULL) { if (SSL_CTX_add_extra_chain_cert(ctx_ptr, caCert_ptr) != 1) { X509_free(caCert_ptr); goto end; } // note that caCert_ptr must not be freed if it was successfully added to the chain } } ret = true; end: if (certificate_ptr != NULL) X509_free(certificate_ptr); if (rsaPrivateKey_ptr != NULL) EVP_PKEY_free(rsaPrivateKey_ptr); if (dsaPrivateKey_ptr != NULL) EVP_PKEY_free(dsaPrivateKey_ptr); if (rsaCertChain_ptr != NULL) sk_X509_pop_free(rsaCertChain_ptr, X509_free); if (dsaCertChain_ptr != NULL) sk_X509_pop_free(dsaCertChain_ptr, X509_free); return ret; }
void initAuthenticated ( std::string key_file, std::string cert_file, std::string chain_file) { initCommon (); SSL_CTX* const ssl = m_context.native_handle (); bool cert_set = false; if (! cert_file.empty ()) { boost::system::error_code error; m_context.use_certificate_file ( cert_file, boost::asio::ssl::context::pem, error); if (error) { beast::FatalError ("Problem with SSL certificate file.", __FILE__, __LINE__); } cert_set = true; } if (! chain_file.empty ()) { // VFALCO Replace fopen() with RAII FILE* f = fopen (chain_file.c_str (), "r"); if (!f) { beast::FatalError ("Problem opening SSL chain file.", __FILE__, __LINE__); } try { for (;;) { X509* const x = PEM_read_X509 (f, NULL, NULL, NULL); if (x == nullptr) break; if (! cert_set) { if (SSL_CTX_use_certificate (ssl, x) != 1) beast::FatalError ("Problem retrieving SSL certificate from chain file.", __FILE__, __LINE__); cert_set = true; } else if (SSL_CTX_add_extra_chain_cert (ssl, x) != 1) { X509_free (x); beast::FatalError ("Problem adding SSL chain certificate.", __FILE__, __LINE__); } } fclose (f); } catch (...) { fclose (f); beast::FatalError ("Reading the SSL chain file generated an exception.", __FILE__, __LINE__); } } if (! key_file.empty ()) { boost::system::error_code error; m_context.use_private_key_file (key_file, boost::asio::ssl::context::pem, error); if (error) { beast::FatalError ("Problem using the SSL private key file.", __FILE__, __LINE__); } } if (SSL_CTX_check_private_key (ssl) != 1) { beast::FatalError ("Invalid key in SSL private key file.", __FILE__, __LINE__); } }
/** * Read a file that contains our certificate in "PEM" format, * possibly followed by a sequence of CA certificates that should be * sent to the peer in the Certificate message. * * Taken from OpenSSL & Node.js - editted for style. */ static int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, BIO *in) { int ret = 0; X509 *x = NULL; x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); if (x == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); goto end; } ret = SSL_CTX_use_certificate(ctx, x); if (ERR_peek_error() != 0) { /* Key/certificate mismatch doesn't imply ret==0 ... */ ret = 0; } if (ret) { /* If we could set up our certificate, now proceed to the CA certificates. */ X509 *ca; int r; unsigned long err; if (ctx->extra_certs != NULL) { sk_X509_pop_free(ctx->extra_certs, X509_free); ctx->extra_certs = NULL; } while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) { r = SSL_CTX_add_extra_chain_cert(ctx, ca); if (!r) { X509_free(ca); ret = 0; goto end; } /* Note that we must not free r if it was successfully * added to the chain (while we must free the main * certificate, since its reference count is increased * by SSL_CTX_use_certificate). */ } /* When the while loop ends, it's usually just EOF. */ err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { ERR_clear_error(); } else { /* some real error */ ret = 0; } } end: if (x != NULL) { X509_free(x); } return ret; }
int ssl_ctx_use_certificate_chain(SSL_CTX *ctx, char *buf, off_t len) { int ret; BIO *in; X509 *x; X509 *ca; unsigned long err; ret = 0; x = ca = NULL; if ((in = BIO_new_mem_buf(buf, len)) == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); goto end; } if ((x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata)) == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); goto end; } if (!SSL_CTX_use_certificate(ctx, x) || ERR_peek_error() != 0) goto end; /* If we could set up our certificate, now proceed to * the CA certificates. */ if (ctx->extra_certs != NULL) { sk_X509_pop_free(ctx->extra_certs, X509_free); ctx->extra_certs = NULL; } while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, ctx->default_passwd_callback_userdata)) != NULL) { if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) goto end; } err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) ERR_clear_error(); else goto end; ret = 1; end: if (ca != NULL) X509_free(ca); if (x != NULL) X509_free(x); if (in != NULL) BIO_free(in); return (ret); }
static int execute_test_large_message(const SSL_METHOD *smeth, const SSL_METHOD *cmeth, int read_ahead) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; int testresult = 0; int i; BIO *certbio = BIO_new_file(cert, "r"); X509 *chaincert = NULL; int certlen; if (certbio == NULL) { printf("Can't load the certificate file\n"); goto end; } chaincert = PEM_read_bio_X509(certbio, NULL, NULL, NULL); BIO_free(certbio); certbio = NULL; if (chaincert == NULL) { printf("Unable to load certificate for chain\n"); goto end; } if (!create_ssl_ctx_pair(smeth, cmeth, &sctx, &cctx, cert, privkey)) { printf("Unable to create SSL_CTX pair\n"); goto end; } if(read_ahead) { /* * Test that read_ahead works correctly when dealing with large * records */ SSL_CTX_set_read_ahead(cctx, 1); } /* * We assume the supplied certificate is big enough so that if we add * NUM_EXTRA_CERTS it will make the overall message large enough. The * default buffer size is requested to be 16k, but due to the way BUF_MEM * works, it ends up allocating a little over 21k (16 * 4/3). So, in this test * we need to have a message larger than that. */ certlen = i2d_X509(chaincert, NULL); OPENSSL_assert((certlen * NUM_EXTRA_CERTS) > ((SSL3_RT_MAX_PLAIN_LENGTH * 4) / 3)); for (i = 0; i < NUM_EXTRA_CERTS; i++) { if (!X509_up_ref(chaincert)) { printf("Unable to up ref cert\n"); goto end; } if (!SSL_CTX_add_extra_chain_cert(sctx, chaincert)) { printf("Unable to add extra chain cert %d\n", i); X509_free(chaincert); goto end; } } if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) { printf("Unable to create SSL objects\n"); goto end; } if (!create_ssl_connection(serverssl, clientssl)) { printf("Unable to create SSL connection\n"); goto end; } /* * Calling SSL_clear() first is not required but this tests that SSL_clear() * doesn't leak (when using enable-crypto-mdebug). */ if (!SSL_clear(serverssl)) { printf("Unexpected failure from SSL_clear()\n"); goto end; } testresult = 1; end: X509_free(chaincert); SSL_free(serverssl); SSL_free(clientssl); SSL_CTX_free(sctx); SSL_CTX_free(cctx); return testresult; }
static apr_status_t init_ssl_context(serv_ctx_t *serv_ctx, const char *keyfile, const char **certfiles, const char *client_cn) { ssl_context_t *ssl_ctx = apr_pcalloc(serv_ctx->pool, sizeof(*ssl_ctx)); serv_ctx->ssl_ctx = ssl_ctx; serv_ctx->client_cn = client_cn; serv_ctx->bio_read_status = APR_SUCCESS; /* Init OpenSSL globally */ if (!init_done) { CRYPTO_malloc_init(); ERR_load_crypto_strings(); SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); init_done = 1; } /* Init this connection */ if (!ssl_ctx->ctx) { X509_STORE *store; const char *certfile; int i; int rv; ssl_ctx->ctx = SSL_CTX_new(SSLv23_server_method()); SSL_CTX_set_default_passwd_cb(ssl_ctx->ctx, pem_passwd_cb); rv = SSL_CTX_use_PrivateKey_file(ssl_ctx->ctx, keyfile, SSL_FILETYPE_PEM); if (rv != 1) { fprintf(stderr, "Cannot load private key from file '%s'\n", keyfile); exit(1); } /* Set server certificate, add ca certificates if provided. */ certfile = certfiles[0]; rv = SSL_CTX_use_certificate_file(ssl_ctx->ctx, certfile, SSL_FILETYPE_PEM); if (rv != 1) { fprintf(stderr, "Cannot load certficate from file '%s'\n", keyfile); exit(1); } i = 1; certfile = certfiles[i++]; store = SSL_CTX_get_cert_store(ssl_ctx->ctx); while(certfile) { FILE *fp = fopen(certfile, "r"); if (fp) { X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL); fclose(fp); SSL_CTX_add_extra_chain_cert(ssl_ctx->ctx, ssl_cert); X509_STORE_add_cert(store, ssl_cert); } certfile = certfiles[i++]; } /* This makes the server send a client certificate request during handshake. The client certificate is optional (most tests don't send one) by default, but mandatory if client_cn was specified. */ SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER, validate_client_certificate); SSL_CTX_set_mode(ssl_ctx->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); ssl_ctx->bio = BIO_new(&bio_apr_socket_method); ssl_ctx->bio->ptr = serv_ctx; init_ssl(serv_ctx); } return APR_SUCCESS; }
static int load_pkcs12_certificate(struct openconnect_info *vpninfo, PKCS12 *p12) { EVP_PKEY *pkey = NULL; X509 *cert = NULL; STACK_OF(X509) *ca; int ret = 0; char *pass; pass = vpninfo->cert_password; vpninfo->cert_password = NULL; retrypass: /* We do this every time round the loop, to work around a bug in OpenSSL < 1.0.0-beta2 -- where the stack at *ca will be freed when PKCS12_parse() returns an error, but *ca is left pointing to the freed memory. */ ca = NULL; if (!pass && request_passphrase(vpninfo, "openconnect_pkcs12", &pass, _("Enter PKCS#12 pass phrase:")) < 0) { PKCS12_free(p12); return -EINVAL; } if (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) { unsigned long err = ERR_peek_error(); openconnect_report_ssl_errors(vpninfo); if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 && ERR_GET_FUNC(err) == PKCS12_F_PKCS12_PARSE && ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) { vpn_progress(vpninfo, PRG_ERR, _("Parse PKCS#12 failed (wrong passphrase?)\n")); free(pass); pass = NULL; goto retrypass; } vpn_progress(vpninfo, PRG_ERR, _("Parse PKCS#12 failed (see above errors)\n")); PKCS12_free(p12); free(pass); return -EINVAL; } free(pass); if (cert) { char buf[200]; vpninfo->cert_x509 = cert; SSL_CTX_use_certificate(vpninfo->https_ctx, cert); X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); vpn_progress(vpninfo, PRG_INFO, _("Using client certificate '%s'\n"), buf); } else { vpn_progress(vpninfo, PRG_ERR, _("PKCS#12 contained no certificate!")); ret = -EINVAL; } if (pkey) { SSL_CTX_use_PrivateKey(vpninfo->https_ctx, pkey); EVP_PKEY_free(pkey); } else { vpn_progress(vpninfo, PRG_ERR, _("PKCS#12 contained no private key!")); ret = -EINVAL; } /* Only include supporting certificates which are actually necessary */ if (ca) { int i; next: for (i = 0; i < sk_X509_num(ca); i++) { X509 *cert2 = sk_X509_value(ca, i); if (X509_check_issued(cert2, cert) == X509_V_OK) { char buf[200]; if (cert2 == cert) break; if (X509_check_issued(cert2, cert2) == X509_V_OK) break; X509_NAME_oneline(X509_get_subject_name(cert2), buf, sizeof(buf)); vpn_progress(vpninfo, PRG_DEBUG, _("Extra cert from PKCS#12: '%s'\n"), buf); CRYPTO_add(&cert2->references, 1, CRYPTO_LOCK_X509); SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert2); cert = cert2; goto next; } } sk_X509_pop_free(ca, X509_free); } PKCS12_free(p12); return ret; }
void ContextImpl::assign(const ContextImpl& ctx) { // TODO: consider to create a new SSL_CTX if required setProtocol(ctx._protocol); setVerifyMode(ctx._verify); setVerifyDepth(ctx._verifyDepth); // copy certificates presented to peer if(_pkey) EVP_PKEY_free(_pkey); _pkey = 0; if(_x509) X509_free(_x509); _x509 = 0; if( ctx._x509 ) { _pkey = copyPrivateKey( ctx._pkey ); _x509 = copyX509( ctx._x509 ); if( ! SSL_CTX_use_certificate(_ctx, _x509) ) { throw InvalidCertificate("invalid certificate"); } if( ! SSL_CTX_use_PrivateKey( _ctx, _pkey ) ) { throw InvalidCertificate("invalid certificate"); } } _extraCerts.clear(); _extraCerts.reserve( ctx._extraCerts.size() ); for(std::vector<X509*>::const_iterator it = ctx._extraCerts.begin(); it != ctx._extraCerts.end(); ++it) { // NOTE: SSL_CTX_add_extra_chain_cert does not copy the X509 certificate, // or increase the refcount. We must copy it, because the SSL_CTX will // free it X509* extraX509 = copyX509(*it); X509AutoPtr x509Ptr(extraX509); if( ! SSL_CTX_add_extra_chain_cert( _ctx, extraX509 ) ) throw InvalidCertificate("invalid extra certificate"); _extraCerts.push_back(extraX509); x509Ptr.release(); } // copy trusted CA certificates for(std::vector<X509*>::iterator it = _caCerts.begin(); it != _caCerts.end(); ++it) { X509_free(*it); } _caCerts.clear(); _caCerts.reserve( ctx._caCerts.size() ); X509_STORE* store = X509_STORE_new(); X509StoreAutoPtr storePtr(store); for(std::vector<X509*>::const_iterator it = ctx._caCerts.begin(); it != ctx._caCerts.end(); ++it) { X509* x509 = copyX509(*it); X509AutoPtr x509Ptr(x509); if( ! X509_STORE_add_cert(store, x509) ) throw InvalidCertificate("untrusted certificate"); _caCerts.push_back(x509); x509Ptr.release(); } SSL_CTX_set_cert_store( _ctx, store ); storePtr.release(); }