summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2020-01-14 22:10:21 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-02-03 17:26:42 +0000
commiteee29e9ce82913f0713ec11a1246a2d9a9c8e713 (patch)
treea211549f773ec5b1b17061e8be3bd6e424a6e154
parent2a5433168a53044cb6b4fa8083e4cfd7ba142221 (diff)
downloadmongo-eee29e9ce82913f0713ec11a1246a2d9a9c8e713.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_openssl.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp
index 82c751bffa4..fae8072c630 100644
--- a/src/mongo/util/net/ssl_manager_openssl.cpp
+++ b/src/mongo/util/net/ssl_manager_openssl.cpp
@@ -79,6 +79,15 @@ namespace mongo {
namespace {
+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
// `mongo::SockAddr::Sockaddr(StringData, int, sa_family_t)`). A user explicitly specifying a Unix
@@ -186,8 +195,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.
*