diff --git a/src/impl/certificate.cpp b/src/impl/certificate.cpp index fed8cef1e..1194bed74 100644 --- a/src/impl/certificate.cpp +++ b/src/impl/certificate.cpp @@ -9,6 +9,7 @@ #include "certificate.hpp" #include "threadpool.hpp" +#include #include #include #include @@ -384,9 +385,16 @@ Certificate Certificate::FromString(string crt_pem, string key_pem) { BIO *bio = BIO_new(BIO_s_mem()); BIO_write(bio, crt_pem.data(), int(crt_pem.size())); auto x509 = shared_ptr(PEM_read_bio_X509(bio, nullptr, nullptr, nullptr), X509_free); - BIO_free(bio); - if (!x509) + if (!x509) { + BIO_free(bio); throw std::invalid_argument("Unable to import PEM certificate"); + } + std::vector> chain; + while (auto extra = + shared_ptr(PEM_read_bio_X509(bio, nullptr, nullptr, nullptr), X509_free)) { + chain.push_back(std::move(extra)); + } + BIO_free(bio); bio = BIO_new(BIO_s_mem()); BIO_write(bio, key_pem.data(), int(key_pem.size())); @@ -396,7 +404,7 @@ Certificate Certificate::FromString(string crt_pem, string key_pem) { if (!pkey) throw std::invalid_argument("Unable to import PEM key"); - return Certificate(x509, pkey); + return Certificate(x509, pkey, std::move(chain)); } Certificate Certificate::FromFile(const string &crt_pem_file, const string &key_pem_file, @@ -408,9 +416,16 @@ Certificate Certificate::FromFile(const string &crt_pem_file, const string &key_ throw std::invalid_argument("Unable to open PEM certificate file"); auto x509 = shared_ptr(PEM_read_bio_X509(bio, nullptr, nullptr, nullptr), X509_free); - BIO_free(bio); - if (!x509) + if (!x509) { + BIO_free(bio); throw std::invalid_argument("Unable to import PEM certificate from file"); + } + std::vector> chain; + while (auto extra = + shared_ptr(PEM_read_bio_X509(bio, nullptr, nullptr, nullptr), X509_free)) { + chain.push_back(std::move(extra)); + } + BIO_free(bio); bio = openssl::BIO_new_from_file(key_pem_file); if (!bio) @@ -423,7 +438,7 @@ Certificate Certificate::FromFile(const string &crt_pem_file, const string &key_ if (!pkey) throw std::invalid_argument("Unable to import PEM key from file"); - return Certificate(x509, pkey); + return Certificate(x509, pkey, std::move(chain)); } Certificate Certificate::Generate(CertificateType type, const string &commonName) { @@ -514,14 +529,23 @@ Certificate Certificate::Generate(CertificateType type, const string &commonName return Certificate(x509, pkey); } -Certificate::Certificate(shared_ptr x509, shared_ptr pkey) - : mX509(std::move(x509)), mPKey(std::move(pkey)), +Certificate::Certificate(shared_ptr x509, shared_ptr pkey, + std::vector> chain) + : mX509(std::move(x509)), mPKey(std::move(pkey)), mChain(std::move(chain)), mFingerprint(make_fingerprint(mX509.get(), CertificateFingerprint::Algorithm::Sha256)) {} std::tuple Certificate::credentials() const { return {mX509.get(), mPKey.get()}; } +std::vector Certificate::chain() const { + std::vector v; + v.reserve(mChain.size()); + std::transform(mChain.begin(), mChain.end(), std::back_inserter(v), + [](const auto &c) { return c.get(); }); + return v; +} + string make_fingerprint(X509 *x509, CertificateFingerprint::Algorithm fingerprintAlgorithm) { size_t size = CertificateFingerprint::AlgorithmSize(fingerprintAlgorithm); std::vector buffer(size); diff --git a/src/impl/certificate.hpp b/src/impl/certificate.hpp index 66111ccb4..0617ba173 100644 --- a/src/impl/certificate.hpp +++ b/src/impl/certificate.hpp @@ -34,8 +34,9 @@ class Certificate { Certificate(shared_ptr crt, shared_ptr pk); std::tuple, shared_ptr> credentials() const; #else // OPENSSL - Certificate(shared_ptr x509, shared_ptr pkey); + Certificate(shared_ptr x509, shared_ptr pkey, std::vector> chain = {}); std::tuple credentials() const; + std::vector chain() const; #endif CertificateFingerprint fingerprint() const; @@ -52,6 +53,7 @@ class Certificate { #else const shared_ptr mX509; const shared_ptr mPKey; + const std::vector> mChain; #endif const string mFingerprint; diff --git a/src/impl/tlstransport.cpp b/src/impl/tlstransport.cpp index 8f66d200f..0f5e9e967 100644 --- a/src/impl/tlstransport.cpp +++ b/src/impl/tlstransport.cpp @@ -603,6 +603,9 @@ TlsTransport::TlsTransport(variant, shared_ptrcredentials(); SSL_CTX_use_certificate(mCtx, x509); SSL_CTX_use_PrivateKey(mCtx, pkey); + + for (auto c : certificate->chain()) + SSL_CTX_add1_chain_cert(mCtx, c); // add1 increments reference count } SSL_CTX_set_options(mCtx, SSL_OP_NO_SSLv3 | SSL_OP_NO_RENEGOTIATION);