diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2020-01-14 22:10:21 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-02-04 19:03:40 +0000 |
commit | d3262e58c914fd0b5689069c7e8950c508cf1b4a (patch) | |
tree | 57adba8ec78610193c92aa5304dc43b7f007eeaf | |
parent | 21899f6bd537399e00dd86833d185b1ebd1fffe9 (diff) | |
download | mongo-d3262e58c914fd0b5689069c7e8950c508cf1b4a.tar.gz |
SERVER-44325 Provide SSL_get0_verified_chain() polyfill for OpenSSL < 1.1.0
(cherry picked from commit d4a93cea2eee5d2823d7a4d0224db06b4cd15b50)
-rw-r--r-- | src/mongo/util/net/ssl_manager.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp index 1951264ce88..70854fd0a50 100644 --- a/src/mongo/util/net/ssl_manager.cpp +++ b/src/mongo/util/net/ssl_manager.cpp @@ -88,6 +88,14 @@ std::string removeFQDNRoot(std::string name) { return name; }; +struct UniqueX509StoreCtxDeleter { + void operator()(X509_STORE_CTX* ctx) { + if (ctx) { + ::X509_STORE_CTX_free(ctx); + } + } +}; +using UniqueX509StoreCtx = std::unique_ptr<X509_STORE_CTX, UniqueX509StoreCtxDeleter>; // Because the hostname having a slash is used by `mongo::SockAddr` to determine if a hostname is a // Unix Domain Socket endpoint, this function uses the same logic. (See @@ -270,8 +278,46 @@ const STACK_OF(X509_EXTENSION) * X509_get0_extensions(const X509* peerCert) { inline int X509_NAME_ENTRY_set(const X509_NAME_ENTRY* ne) { return ne->set; } + +// On OpenSSL < 1.1.0, this chain isn't attached to +// the SSL session, so we need it to dispose of itself. +struct VerifiedChainDeleter { + void operator()(STACK_OF(X509) * chain) { + if (chain) { + sk_X509_pop_free(chain, X509_free); + } + } +}; + +STACK_OF(X509) * SSL_get0_verified_chain(SSL* s) { + auto* store = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)); + auto* peer = SSL_get_peer_certificate(s); + auto* peerChain = SSL_get_peer_cert_chain(s); + + UniqueX509StoreCtx ctx(X509_STORE_CTX_new()); + if (!X509_STORE_CTX_init(ctx.get(), store, peer, peerChain)) { + return nullptr; + } + + if (X509_verify_cert(ctx.get()) <= 0) { + return nullptr; + } + + return X509_STORE_CTX_get1_chain(ctx.get()); +} + +#else +// No-op deleter for OpenSSL >= 1.1.0 +struct VerifiedChainDeleter { + void operator()(STACK_OF(X509) * chain) {} +}; #endif +using UniqueVerifiedChainPolyfill = std::unique_ptr<STACK_OF(X509), VerifiedChainDeleter>; +UniqueVerifiedChainPolyfill SSLgetVerifiedChain(SSL* s) { + return UniqueVerifiedChainPolyfill(SSL_get0_verified_chain(s)); +} + /** * Multithreaded Support for SSL. * |