summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorsviatlana_zuiko <sviatlana.zuiko@mongodb.com>2020-11-13 10:20:02 +0300
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-11-13 10:39:59 +0000
commit796ee2ee8b8a7bb146bfa7a45eafb4b075a55372 (patch)
tree7b4337f39b4b8eb7186ef2bb2be645313fc9430b /src/mongo
parent6675536b77436eccddc54d6b3513ecb862cf381c (diff)
downloadmongo-796ee2ee8b8a7bb146bfa7a45eafb4b075a55372.tar.gz
Revert "SERVER-51599: Allow creating an SSLConnectionContext from in-memory certificates"
This reverts commit 8b195f11cbb144685baa20486b497528c8dde667.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/transport/transport_layer_asio.cpp2
-rw-r--r--src/mongo/transport/transport_layer_asio_test.cpp4
-rw-r--r--src/mongo/util/net/SConscript1
-rw-r--r--src/mongo/util/net/ssl_manager.cpp22
-rw-r--r--src/mongo/util/net/ssl_manager.h55
-rw-r--r--src/mongo/util/net/ssl_manager_apple.cpp10
-rw-r--r--src/mongo/util/net/ssl_manager_openssl.cpp313
-rw-r--r--src/mongo/util/net/ssl_manager_test.cpp186
-rw-r--r--src/mongo/util/net/ssl_manager_windows.cpp11
-rw-r--r--src/mongo/util/net/ssl_options.h1
10 files changed, 73 insertions, 532 deletions
diff --git a/src/mongo/transport/transport_layer_asio.cpp b/src/mongo/transport/transport_layer_asio.cpp
index 4fd4df156bc..0517f8d9af3 100644
--- a/src/mongo/transport/transport_layer_asio.cpp
+++ b/src/mongo/transport/transport_layer_asio.cpp
@@ -1199,7 +1199,6 @@ Status TransportLayerASIO::rotateCertificates(std::shared_ptr<SSLManagerInterfac
Status status = newSSLContext->manager->initSSLContext(
newSSLContext->ingress->native_handle(),
sslParams,
- TransientSSLParams(),
SSLManagerInterface::ConnectionDirection::kIncoming);
if (!status.isOK()) {
return status;
@@ -1220,7 +1219,6 @@ Status TransportLayerASIO::rotateCertificates(std::shared_ptr<SSLManagerInterfac
Status status = newSSLContext->manager->initSSLContext(
newSSLContext->egress->native_handle(),
sslParams,
- TransientSSLParams(),
SSLManagerInterface::ConnectionDirection::kOutgoing);
if (!status.isOK()) {
return status;
diff --git a/src/mongo/transport/transport_layer_asio_test.cpp b/src/mongo/transport/transport_layer_asio_test.cpp
index 9764e952b2e..a7938e031ba 100644
--- a/src/mongo/transport/transport_layer_asio_test.cpp
+++ b/src/mongo/transport/transport_layer_asio_test.cpp
@@ -50,12 +50,12 @@ public:
void startSession(transport::SessionHandle session) override {
stdx::unique_lock<Latch> lk(_mutex);
_sessions.push_back(std::move(session));
- LOGV2(2303201, "started session");
+ LOGV2(23032, "started session");
_cv.notify_one();
}
void endAllSessions(transport::Session::TagMask tags) override {
- LOGV2(2303301, "end all sessions");
+ LOGV2(23033, "end all sessions");
std::vector<transport::SessionHandle> old_sessions;
{
stdx::unique_lock<Latch> lock(_mutex);
diff --git a/src/mongo/util/net/SConscript b/src/mongo/util/net/SConscript
index adf8b0ec033..ea81c6d254c 100644
--- a/src/mongo/util/net/SConscript
+++ b/src/mongo/util/net/SConscript
@@ -231,7 +231,6 @@ if get_option('ssl') == 'on':
],
LIBDEPS=[
'$BUILD_DIR/mongo/db/server_options_servers',
- '$BUILD_DIR/mongo/transport/transport_layer',
'$BUILD_DIR/mongo/util/cmdline_utils/cmdline_utils',
'$BUILD_DIR/mongo/util/fail_point',
'network',
diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp
index 87772d303c8..73884cabae0 100644
--- a/src/mongo/util/net/ssl_manager.cpp
+++ b/src/mongo/util/net/ssl_manager.cpp
@@ -335,9 +335,14 @@ std::shared_ptr<SSLManagerInterface> SSLManagerCoordinator::getSSLManager() {
}
void logCert(const CertInformationToLog& cert, StringData certType, const int logNum) {
- auto attrs = cert.getDynamicAttributes();
- attrs.add("type", certType);
- LOGV2(logNum, "Certificate information", attrs);
+ LOGV2(logNum,
+ "Certificate information",
+ "type"_attr = certType,
+ "subject"_attr = cert.subject.toString(),
+ "issuer"_attr = cert.issuer.toString(),
+ "thumbprint"_attr = hexblob::encode(cert.thumbprint.data(), cert.thumbprint.size()),
+ "notValidBefore"_attr = cert.validityNotBefore.toString(),
+ "notValidAfter"_attr = cert.validityNotAfter.toString());
}
void logCRL(const CRLInformationToLog& crl, const int logNum) {
@@ -348,18 +353,15 @@ void logCRL(const CRLInformationToLog& crl, const int logNum) {
"notValidAfter"_attr = crl.validityNotAfter.toString());
}
-void logSSLInfo(const SSLInformationToLog& info,
- const int logNumPEM,
- const int logNumCluster,
- const int logNumCrl) {
+void logSSLInfo(const SSLInformationToLog& info) {
if (!(sslGlobalParams.sslPEMKeyFile.empty())) {
- logCert(info.server, "Server", logNumPEM);
+ logCert(info.server, "Server", 4913010);
}
if (info.cluster.has_value()) {
- logCert(info.cluster.get(), "Cluster", logNumCluster);
+ logCert(info.cluster.get(), "Cluster", 4913011);
}
if (info.crl.has_value()) {
- logCRL(info.crl.get(), logNumCrl);
+ logCRL(info.crl.get(), 4913012);
}
}
diff --git a/src/mongo/util/net/ssl_manager.h b/src/mongo/util/net/ssl_manager.h
index 7004ad4892c..ab8447c439f 100644
--- a/src/mongo/util/net/ssl_manager.h
+++ b/src/mongo/util/net/ssl_manager.h
@@ -40,7 +40,6 @@
#include "mongo/base/string_data.h"
#include "mongo/bson/bsonobj.h"
#include "mongo/db/service_context.h"
-#include "mongo/logv2/attribute_storage.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/util/decorable.h"
#include "mongo/util/net/sock.h"
@@ -78,7 +77,6 @@ Status validateDisableNonTLSConnectionLogging(const bool&);
#ifdef MONGO_CONFIG_SSL
namespace mongo {
struct SSLParams;
-struct TransientSSLParams;
#if MONGO_CONFIG_SSL_PROVIDER == MONGO_CONFIG_SSL_PROVIDER_OPENSSL
typedef SSL_CTX* SSLContextType;
@@ -166,28 +164,6 @@ struct CertInformationToLog {
std::vector<char> thumbprint;
Date_t validityNotBefore;
Date_t validityNotAfter;
- // If the certificate was loaded from file, this is the file name. If empty,
- // it means the certificate came from memory payload.
- std::optional<std::string> keyFile;
- // If the certificate targets a particular cluster, this is cluster URI. If empty,
- // it means the certificate is the default one for the local cluster.
- std::optional<std::string> targetClusterURI;
-
- logv2::DynamicAttributes getDynamicAttributes() const {
- logv2::DynamicAttributes attrs;
- attrs.add("subject", subject);
- attrs.add("issuer", issuer);
- attrs.add("thumbprint", StringData(hexblob::encode(thumbprint.data(), thumbprint.size())));
- attrs.add("notValidBefore", validityNotBefore);
- attrs.add("notValidAfter", validityNotAfter);
- if (keyFile) {
- attrs.add("keyFile", StringData(*keyFile));
- }
- if (targetClusterURI) {
- attrs.add("targetClusterURI", StringData(*targetClusterURI));
- }
- return attrs;
- }
};
struct CRLInformationToLog {
@@ -204,10 +180,6 @@ struct SSLInformationToLog {
class SSLManagerInterface : public Decorable<SSLManagerInterface> {
public:
- /**
- * Creates an instance of SSLManagerInterface.
- * Note: as we normally have one instance of the manager, it cannot take TransientSSLParams.
- */
static std::shared_ptr<SSLManagerInterface> create(const SSLParams& params, bool isServer);
virtual ~SSLManagerInterface();
@@ -260,17 +232,6 @@ public:
ERR_error_string_n(code, msg, msglen);
return msg;
}
-
- /**
- * Utility class to capture a temporary string with SSL error message in DynamicAttributes.
- */
- struct CaptureSSLErrorInAttrs {
- CaptureSSLErrorInAttrs(logv2::DynamicAttributes& attrs)
- : _captured(getSSLErrorMessage(ERR_get_error())) {
- attrs.add("error", _captured);
- }
- std::string _captured;
- };
#endif
/**
@@ -291,7 +252,6 @@ public:
*/
virtual Status initSSLContext(SSLContextType context,
const SSLParams& params,
- const TransientSSLParams& transientParams,
ConnectionDirection direction) = 0;
/**
@@ -430,20 +390,5 @@ void recordTLSVersion(TLSVersion version, const HostAndPort& hostForLogging);
void tlsEmitWarningExpiringClientCertificate(const SSLX509Name& peer);
void tlsEmitWarningExpiringClientCertificate(const SSLX509Name& peer, Days days);
-/**
- * Logs the SSL information by dispatching to either logCert() or logCRL().
- */
-void logSSLInfo(const SSLInformationToLog& info,
- const int logNumPEM = 4913010,
- const int logNumCluster = 4913011,
- const int logNumCrl = 4913012);
-
-/**
- * Logs the certificate.
- * @param certType human-readable description of the certificate type.
- */
-void logCert(const CertInformationToLog& cert, StringData certType, const int logNum);
-void logCRL(const CRLInformationToLog& crl, const int logNum);
-
} // namespace mongo
#endif // #ifdef MONGO_CONFIG_SSL
diff --git a/src/mongo/util/net/ssl_manager_apple.cpp b/src/mongo/util/net/ssl_manager_apple.cpp
index 32191e54b02..16af08cb0b9 100644
--- a/src/mongo/util/net/ssl_manager_apple.cpp
+++ b/src/mongo/util/net/ssl_manager_apple.cpp
@@ -1251,8 +1251,7 @@ public:
Status initSSLContext(asio::ssl::apple::Context* context,
const SSLParams& params,
- const TransientSSLParams& transientParams,
- ConnectionDirection direction) override final;
+ ConnectionDirection direction) final;
SSLConnectionInterface* connect(Socket* socket) final;
SSLConnectionInterface* accept(Socket* socket, const char* initialBytes, int len) final;
@@ -1311,16 +1310,14 @@ SSLManagerApple::SSLManagerApple(const SSLParams& params, bool isServer)
_allowInvalidHostnames(params.sslAllowInvalidHostnames),
_suppressNoCertificateWarning(params.suppressNoTLSPeerCertificateWarning) {
- uassertStatusOK(
- initSSLContext(&_clientCtx, params, TransientSSLParams(), ConnectionDirection::kOutgoing));
+ uassertStatusOK(initSSLContext(&_clientCtx, params, ConnectionDirection::kOutgoing));
if (_clientCtx.certs) {
_sslConfiguration.clientSubjectName =
uassertStatusOK(certificateGetSubject(_clientCtx.certs.get()));
}
if (isServer) {
- uassertStatusOK(initSSLContext(
- &_serverCtx, params, TransientSSLParams(), ConnectionDirection::kIncoming));
+ uassertStatusOK(initSSLContext(&_serverCtx, params, ConnectionDirection::kIncoming));
if (_serverCtx.certs) {
uassertStatusOK(
_sslConfiguration.setServerSubjectName(uassertStatusOK(certificateGetSubject(
@@ -1394,7 +1391,6 @@ StatusWith<std::pair<::SSLProtocol, ::SSLProtocol>> parseProtocolRange(const SSL
Status SSLManagerApple::initSSLContext(asio::ssl::apple::Context* context,
const SSLParams& params,
- const TransientSSLParams& transientParams,
ConnectionDirection direction) {
// Protocol Version.
const auto swProto = parseProtocolRange(params);
diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp
index a2f7bcc73e1..9fb60e83f6e 100644
--- a/src/mongo/util/net/ssl_manager_openssl.cpp
+++ b/src/mongo/util/net/ssl_manager_openssl.cpp
@@ -1128,7 +1128,7 @@ class SSLManagerOpenSSL : public SSLManagerInterface,
public std::enable_shared_from_this<SSLManagerOpenSSL> {
public:
explicit SSLManagerOpenSSL(const SSLParams& params, bool isServer);
- ~SSLManagerOpenSSL() final {
+ ~SSLManagerOpenSSL() {
stopJobs();
}
@@ -1138,7 +1138,6 @@ public:
*/
Status initSSLContext(SSL_CTX* context,
const SSLParams& params,
- const TransientSSLParams& transientParams,
ConnectionDirection direction) final;
SSLConnectionInterface* connect(Socket* socket) final;
@@ -1242,19 +1241,6 @@ private:
return StringData(_password->c_str());
}
- /**
- * This method can only return a cached password and never prompts.
- * @returns cached password if available, error if password is not cached.
- */
- StatusWith<StringData> fetchCachedPasswordNoPrompt() {
- stdx::lock_guard<Latch> lock(_mutex);
- if (_password->size()) {
- return StringData(_password->c_str());
- }
- return Status(ErrorCodes::UnknownError,
- "Failed to return a cached password, cannot prompt.");
- }
-
private:
Mutex _mutex = MONGO_MAKE_LATCH("PasswordFetcher::_mutex");
SecureString _password; // Protected by _mutex
@@ -1313,10 +1299,7 @@ private:
* @param info as a pointer to the CertInformationToLog struct to populate
* with the information.
*/
- static void _getX509CertInfo(UniqueX509& x509,
- CertInformationToLog* info,
- std::optional<StringData> keyFile,
- std::optional<StringData> targetClusterURI);
+ void _getX509CertInfo(UniqueX509& x509, CertInformationToLog* info) const;
/*
* Retrieve and store CRL information from the provided CRL filename.
@@ -1333,42 +1316,6 @@ private:
/** @return true if was successful, otherwise false */
bool _setupPEM(SSL_CTX* context, const std::string& keyFile, PasswordFetcher* password);
- /**
- * @param payload in-memory payload of a PEM file
- * @return true if was successful, otherwise false
- */
- bool _setupPEMFromMemoryPayload(SSL_CTX* context,
- const std::string& payload,
- PasswordFetcher* password,
- StringData targetClusterURI);
-
- /**
- * Setup PEM from BIO, which could be file or memory input abstraction.
- * @param inBio input BIO, where smart pointer is created with a custom deleter to call
- * 'BIO_free()'.
- * @param keyFile if the certificate was loaded from file, this is the file name. If empty,
- * it means the certificate came from memory payload.
- * @param targetClusterURI If the certificate targets a particular cluster, this is cluster URI.
- * If empty, it means the certificate is the default one for the local cluster.
- * @return true if was successful, otherwise false
- */
- bool _setupPEMFromBIO(SSL_CTX* context,
- UniqueBIO inBio,
- PasswordFetcher* password,
- std::optional<StringData> keyFile,
- std::optional<StringData> targetClusterURI);
-
- /**
- * Loads a certificate chain from memory into context.
- * This method is intended to be a repalcement of API call SSL_CTX_use_certificate_chain_file()
- * but using memory instead of file.
- * @return true if was successful, otherwise false
- */
- static bool _readCertificateChainFromMemory(SSL_CTX* context,
- const std::string& payload,
- PasswordFetcher* password,
- std::optional<StringData> targetClusterURI);
-
/*
* Set up an SSL context for certificate validation by loading a CA
*/
@@ -1395,25 +1342,10 @@ private:
*/
void _flushNetworkBIO(SSLConnectionOpenSSL* conn);
- /*
- * Utility method to process the result returned by password Fetcher.
- */
- static int _processPasswordFetcherOutput(StatusWith<StringData>* fetcherResult,
- char* buf,
- int num,
- int rwflag);
-
/**
* Callbacks for SSL functions.
*/
-
static int password_cb(char* buf, int num, int rwflag, void* userdata);
-
- /**
- * Special flawor of password callback, which always fails.
- * @return -1.
- */
- static int always_error_password_cb(char* buf, int num, int rwflag, void* userdata);
static int servername_cb(SSL* s, int* al, void* arg);
static int verify_cb(int ok, X509_STORE_CTX* ctx);
};
@@ -1582,28 +1514,20 @@ SSLManagerOpenSSL::SSLManagerOpenSSL(const SSLParams& params, bool isServer)
}
int SSLManagerOpenSSL::password_cb(char* buf, int num, int rwflag, void* userdata) {
- invariant(userdata);
- auto pwFetcher = static_cast<PasswordFetcher*>(userdata);
- auto swPassword = pwFetcher->fetchPassword();
- return _processPasswordFetcherOutput(&swPassword, buf, num, rwflag);
-}
-
-int SSLManagerOpenSSL::always_error_password_cb(char* buf, int num, int rwflag, void* userdata) {
- return -1;
-}
-
-int SSLManagerOpenSSL::_processPasswordFetcherOutput(StatusWith<StringData>* swPassword,
- char* buf,
- int num,
- int rwflag) {
// Unless OpenSSL misbehaves, num should always be positive
fassert(17314, num > 0);
+ invariant(userdata);
- if (!swPassword->isOK()) {
- LOGV2_ERROR(23239, "Unable to fetch password", "error"_attr = swPassword->getStatus());
+ auto pwFetcher = static_cast<PasswordFetcher*>(userdata);
+ auto swPassword = pwFetcher->fetchPassword();
+ if (!swPassword.isOK()) {
+ LOGV2_ERROR(23239,
+ "Unable to fetch password: {error}",
+ "Unable to fetch password",
+ "error"_attr = swPassword.getStatus());
return -1;
}
- StringData password = std::move(swPassword->getValue());
+ StringData password = std::move(swPassword.getValue());
const size_t copyCount = std::min(password.size(), static_cast<size_t>(num));
std::copy_n(password.begin(), copyCount, buf);
@@ -2112,7 +2036,6 @@ Milliseconds SSLManagerOpenSSL::updateOcspStaplingContextWithResponse(
Status SSLManagerOpenSSL::initSSLContext(SSL_CTX* context,
const SSLParams& params,
- const TransientSSLParams& transientParams,
ConnectionDirection direction) {
// SSL_OP_ALL - Activate all bug workaround options, to support buggy client SSL's.
// SSL_OP_NO_SSLv2 - Disable SSL v2 support
@@ -2174,21 +2097,7 @@ Status SSLManagerOpenSSL::initSSLContext(SSL_CTX* context,
<< getSSLErrorMessage(ERR_get_error()));
}
-
- if (direction == ConnectionDirection::kOutgoing &&
- !transientParams.sslClusterPEMPayload.empty()) {
-
- // Transient params for outgoing connection have priority over global params.
- if (!_setupPEMFromMemoryPayload(
- context,
- transientParams.sslClusterPEMPayload,
- &_clusterPEMPassword,
- transientParams.targetedClusterConnectionString.toString())) {
- return Status(ErrorCodes::InvalidSSLConfiguration,
- str::stream() << "Can not set up transient ssl cluster certificate for "
- << transientParams.targetedClusterConnectionString);
- }
- } else if (direction == ConnectionDirection::kOutgoing && params.tlsWithholdClientCertificate) {
+ if (direction == ConnectionDirection::kOutgoing && params.tlsWithholdClientCertificate) {
// Do not send a client certificate if they have been suppressed.
} else if (direction == ConnectionDirection::kOutgoing && !params.sslClusterFile.empty()) {
@@ -2286,7 +2195,7 @@ bool SSLManagerOpenSSL::_initSynchronousSSLContext(UniqueSSLContext* contextPtr,
ConnectionDirection direction) {
*contextPtr = UniqueSSLContext(SSL_CTX_new(SSLv23_method()));
- uassertStatusOK(initSSLContext(contextPtr->get(), params, TransientSSLParams(), direction));
+ uassertStatusOK(initSSLContext(contextPtr->get(), params, direction));
// If renegotiation is needed, don't return from recv() or send() until it's successful.
// Note: this is for blocking sockets only.
@@ -2302,6 +2211,7 @@ bool SSLManagerOpenSSL::_parseAndValidateCertificate(const std::string& keyFile,
BIO* inBIO = BIO_new(BIO_s_file());
if (inBIO == nullptr) {
LOGV2_ERROR(23243,
+ "failed to allocate BIO object: {error}",
"Failed to allocate BIO object",
"error"_attr = getSSLErrorMessage(ERR_get_error()));
return false;
@@ -2310,6 +2220,7 @@ bool SSLManagerOpenSSL::_parseAndValidateCertificate(const std::string& keyFile,
ON_BLOCK_EXIT([&] { BIO_free(inBIO); });
if (BIO_read_filename(inBIO, keyFile.c_str()) <= 0) {
LOGV2_ERROR(23244,
+ "cannot read key file when setting subject name: {keyFile} {error}",
"Cannot read key file when setting subject name",
"keyFile"_attr = keyFile,
"error"_attr = getSSLErrorMessage(ERR_get_error()));
@@ -2320,6 +2231,7 @@ bool SSLManagerOpenSSL::_parseAndValidateCertificate(const std::string& keyFile,
inBIO, nullptr, &SSLManagerOpenSSL::password_cb, static_cast<void*>(&keyPassword));
if (x509 == nullptr) {
LOGV2_ERROR(23245,
+ "cannot retrieve certificate from keyfile: {keyFile} {error}",
"Cannot retrieve certificate from keyfile",
"keyFile"_attr = keyFile,
"error"_attr = getSSLErrorMessage(ERR_get_error()));
@@ -2351,177 +2263,66 @@ bool SSLManagerOpenSSL::_parseAndValidateCertificate(const std::string& keyFile,
return true;
}
-// static
-bool SSLManagerOpenSSL::_readCertificateChainFromMemory(
- SSL_CTX* context,
- const std::string& payload,
- PasswordFetcher* password,
- std::optional<StringData> targetClusterURI) {
-
- logv2::DynamicAttributes errorAttrs;
- if (targetClusterURI) {
- errorAttrs.add("targetClusterURI", *targetClusterURI);
- }
-
- ERR_clear_error(); // Clear error stack for SSL_CTX_use_certificate().
-
- // Note: old versions of SSL take (void*) here but it's still R/O.
-#if OPENSSL_VERSION_NUMBER <= 0x1000114fL
- UniqueBIO inBio(BIO_new_mem_buf(const_cast<char*>(payload.c_str()), payload.length()));
-#else
- UniqueBIO inBio(BIO_new_mem_buf(payload.c_str(), payload.length()));
-#endif
-
- if (!inBio) {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(5159905, "Failed to allocate BIO from in memory payload", errorAttrs);
- return false;
- }
-
- auto password_cb =
- &SSLManagerOpenSSL::always_error_password_cb; // We don't expect a password to be required.
- void* userdata = static_cast<void*>(password);
- UniqueX509 x509cert(PEM_read_bio_X509_AUX(inBio.get(), NULL, password_cb, userdata));
-
- if (!x509cert) {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(5159906, "Failed to read the X509 certificate from memory", errorAttrs);
- return false;
- }
-
- CertInformationToLog debugInfo;
- _getX509CertInfo(x509cert, &debugInfo, std::nullopt, targetClusterURI);
- logCert(debugInfo, "", 5159903);
-
- // SSL_CTX_use_certificate increments the refcount on cert.
- if (1 != SSL_CTX_use_certificate(context, x509cert.get())) {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(5159907, "Failed to use the X509 certificate loaded from memory", errorAttrs);
- return false;
- }
-
- // If we could set up our certificate, now proceed to the CA certificates.
- UniqueX509 ca;
-#if OPENSSL_VERSION_NUMBER >= 0x100010fFL
- SSL_CTX_clear_chain_certs(context);
-#else
- SSL_CTX_clear_extra_chain_certs(context);
-#endif
- while ((ca = UniqueX509(PEM_read_bio_X509(inBio.get(), NULL, password_cb, userdata)))) {
-#if OPENSSL_VERSION_NUMBER >= 0x100010fFL
- if (1 != SSL_CTX_add1_chain_cert(context, ca.get())) {
-#else
- if (1 != SSL_CTX_add_extra_chain_cert(context, ca.release())) {
-#endif
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(
- 5159908, "Failed to use the CA X509 certificate loaded from memory", errorAttrs);
- return false;
- }
- _getX509CertInfo(ca, &debugInfo, std::nullopt, targetClusterURI);
- logCert(debugInfo, "", 5159902);
- }
- // When the while loop ends, it's usually just EOF.
- auto 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 {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(
- 5159909, "Error remained after scanning all X509 certificates from memory", errorAttrs);
- return false; // Some real error.
- }
-
- return true;
-}
-
bool SSLManagerOpenSSL::_setupPEM(SSL_CTX* context,
const std::string& keyFile,
PasswordFetcher* password) {
- logv2::DynamicAttributes errorAttrs;
- errorAttrs.add("keyFile", keyFile);
-
if (SSL_CTX_use_certificate_chain_file(context, keyFile.c_str()) != 1) {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(23248, "Cannot read certificate file", errorAttrs);
+ LOGV2_ERROR(23248,
+ "cannot read certificate file: {keyFile} {error}",
+ "Cannot read certificate file",
+ "keyFile"_attr = keyFile,
+ "error"_attr = getSSLErrorMessage(ERR_get_error()));
return false;
}
- UniqueBIO inBio(BIO_new(BIO_s_file()));
-
+ BIO* inBio = BIO_new(BIO_s_file());
if (!inBio) {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(23249, "Failed to allocate BIO object", errorAttrs);
- return false;
- }
-
- if (BIO_read_filename(inBio.get(), keyFile.c_str()) <= 0) {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(23250, "Cannot read PEM key file", errorAttrs);
- return false;
- }
- return _setupPEMFromBIO(context, std::move(inBio), password, keyFile, std::nullopt);
-}
-
-bool SSLManagerOpenSSL::_setupPEMFromMemoryPayload(SSL_CTX* context,
- const std::string& payload,
- PasswordFetcher* password,
- StringData targetClusterURI) {
- logv2::DynamicAttributes errorAttrs;
- errorAttrs.add("targetClusterURI", targetClusterURI);
-
- if (!_readCertificateChainFromMemory(context, payload, password, targetClusterURI)) {
+ LOGV2_ERROR(23249,
+ "failed to allocate BIO object: {error}",
+ "Failed to allocate BIO object",
+ "error"_attr = getSSLErrorMessage(ERR_get_error()));
return false;
}
-#if OPENSSL_VERSION_NUMBER <= 0x1000114fL
- UniqueBIO inBio(BIO_new_mem_buf(const_cast<char*>(payload.c_str()), payload.length()));
-#else
- UniqueBIO inBio(BIO_new_mem_buf(payload.c_str(), payload.length()));
-#endif
+ const auto bioGuard = makeGuard([&inBio]() { BIO_free(inBio); });
- if (!inBio) {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(5159901, "Failed to allocate BIO object from in-memory payload", errorAttrs);
+ if (BIO_read_filename(inBio, keyFile.c_str()) <= 0) {
+ LOGV2_ERROR(23250,
+ "cannot read PEM key file: {keyFile} {error}",
+ "Cannot read PEM key file",
+ "keyFile"_attr = keyFile,
+ "error"_attr = getSSLErrorMessage(ERR_get_error()));
return false;
}
- return _setupPEMFromBIO(context, std::move(inBio), password, std::nullopt, targetClusterURI);
-}
-
-bool SSLManagerOpenSSL::_setupPEMFromBIO(SSL_CTX* context,
- UniqueBIO inBio,
- PasswordFetcher* password,
- std::optional<StringData> keyFile,
- std::optional<StringData> targetClusterURI) {
- logv2::DynamicAttributes errorAttrs;
- if (keyFile) {
- errorAttrs.add("keyFile", *keyFile);
- }
- if (targetClusterURI) {
- errorAttrs.add("targetClusterURI", *targetClusterURI);
- }
-
// Obtain the private key, using our callback to acquire a decryption password if necessary.
- auto password_cb = &SSLManagerOpenSSL::password_cb;
+ decltype(&SSLManagerOpenSSL::password_cb) password_cb = &SSLManagerOpenSSL::password_cb;
void* userdata = static_cast<void*>(password);
- EVP_PKEY* privateKey = PEM_read_bio_PrivateKey(inBio.get(), nullptr, password_cb, userdata);
+ EVP_PKEY* privateKey = PEM_read_bio_PrivateKey(inBio, nullptr, password_cb, userdata);
if (!privateKey) {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(23251, "Cannot read PEM key", errorAttrs);
+ LOGV2_ERROR(23251,
+ "cannot read PEM key file: {keyFile} {error}",
+ "Cannot read PEM key file",
+ "keyFile"_attr = keyFile,
+ "error"_attr = getSSLErrorMessage(ERR_get_error()));
return false;
}
const auto privateKeyGuard = makeGuard([&privateKey]() { EVP_PKEY_free(privateKey); });
if (SSL_CTX_use_PrivateKey(context, privateKey) != 1) {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(23252, "Cannot use PEM key", errorAttrs);
+ LOGV2_ERROR(23252,
+ "cannot use PEM key file: {keyFile} {error}",
+ "Cannot use PEM key file",
+ "keyFile"_attr = keyFile,
+ "error"_attr = getSSLErrorMessage(ERR_get_error()));
return false;
}
// Verify that the certificate and the key go together.
if (SSL_CTX_check_private_key(context) != 1) {
- CaptureSSLErrorInAttrs capture(errorAttrs);
- LOGV2_ERROR(23253, "SSL certificate validation failed", errorAttrs);
+ LOGV2_ERROR(23253,
+ "SSL certificate validation failed: {error}",
+ "SSL certificate validation failed",
+ "error"_attr = getSSLErrorMessage(ERR_get_error()));
return false;
}
@@ -3182,11 +2983,7 @@ UniqueX509 SSLManagerOpenSSL::_getX509Object(StringData keyFile,
constexpr size_t kSHA1HashBytes = 20;
-// static
-void SSLManagerOpenSSL::_getX509CertInfo(UniqueX509& x509,
- CertInformationToLog* info,
- std::optional<StringData> keyFile,
- std::optional<StringData> targetClusterURI) {
+void SSLManagerOpenSSL::_getX509CertInfo(UniqueX509& x509, CertInformationToLog* info) const {
info->subject = getCertificateSubjectX509Name(x509.get());
info->issuer = convertX509ToSSLX509Name(X509_get_issuer_name(x509.get()));
@@ -3205,11 +3002,6 @@ void SSLManagerOpenSSL::_getX509CertInfo(UniqueX509& x509,
info->validityNotAfter = notAfterMillis;
uassert(4913004, "date conversion failed", notAfterMillis != Date_t());
-
- if (keyFile)
- info->keyFile = keyFile->toString();
- if (targetClusterURI)
- info->targetClusterURI = targetClusterURI->toString();
}
@@ -3260,15 +3052,14 @@ SSLInformationToLog SSLManagerOpenSSL::getSSLInformationToLog() const {
if (!(sslGlobalParams.sslPEMKeyFile.empty())) {
UniqueX509 serverX509Cert =
_getX509Object(sslGlobalParams.sslPEMKeyFile, &_serverPEMPassword);
- _getX509CertInfo(serverX509Cert, &info.server, sslGlobalParams.sslPEMKeyFile, std::nullopt);
+ _getX509CertInfo(serverX509Cert, &info.server);
}
if (!(sslGlobalParams.sslClusterFile.empty())) {
CertInformationToLog clusterInfo;
UniqueX509 clusterX509Cert =
_getX509Object(sslGlobalParams.sslClusterFile, &_clusterPEMPassword);
- _getX509CertInfo(
- clusterX509Cert, &clusterInfo, sslGlobalParams.sslClusterFile, std::nullopt);
+ _getX509CertInfo(clusterX509Cert, &clusterInfo);
info.cluster = clusterInfo;
} else {
info.cluster = boost::none;
diff --git a/src/mongo/util/net/ssl_manager_test.cpp b/src/mongo/util/net/ssl_manager_test.cpp
index b68713f4b1e..781707b14a9 100644
--- a/src/mongo/util/net/ssl_manager_test.cpp
+++ b/src/mongo/util/net/ssl_manager_test.cpp
@@ -29,15 +29,9 @@
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kTest
-#include <fstream>
-
#include "mongo/platform/basic.h"
-#include "mongo/transport/service_entry_point.h"
-#include "mongo/transport/transport_layer_asio.h"
-#include "mongo/util/net/ssl/context_base.hpp"
#include "mongo/util/net/ssl_manager.h"
-#include "mongo/util/net/ssl_options.h"
#include "mongo/config.h"
#include "mongo/logv2/log.h"
@@ -45,76 +39,11 @@
#if MONGO_CONFIG_SSL_PROVIDER == MONGO_CONFIG_SSL_PROVIDER_OPENSSL
#include "mongo/util/net/dh_openssl.h"
-#include "mongo/util/net/ssl/context_openssl.hpp"
#endif
namespace mongo {
namespace {
-
-
-// Test implementation needed by ASIO transport.
-class ServiceEntryPointUtil : public ServiceEntryPoint {
-public:
- void startSession(transport::SessionHandle session) override {
- stdx::unique_lock<Latch> lk(_mutex);
- _sessions.push_back(std::move(session));
- LOGV2(2303202, "started session");
- _cv.notify_one();
- }
-
- void endAllSessions(transport::Session::TagMask tags) override {
- LOGV2(2303302, "end all sessions");
- std::vector<transport::SessionHandle> old_sessions;
- {
- stdx::unique_lock<Latch> lock(_mutex);
- old_sessions.swap(_sessions);
- }
- old_sessions.clear();
- }
-
- Status start() override {
- return Status::OK();
- }
-
- bool shutdown(Milliseconds timeout) override {
- return true;
- }
-
- void appendStats(BSONObjBuilder*) const override {}
-
- size_t numOpenSessions() const override {
- stdx::unique_lock<Latch> lock(_mutex);
- return _sessions.size();
- }
-
- Future<DbResponse> handleRequest(OperationContext* opCtx,
- const Message& request) noexcept override {
- MONGO_UNREACHABLE;
- }
-
- void setTransportLayer(transport::TransportLayer* tl) {
- _transport = tl;
- }
-
- void waitForConnect() {
- stdx::unique_lock<Latch> lock(_mutex);
- _cv.wait(lock, [&] { return !_sessions.empty(); });
- }
-
-private:
- mutable Mutex _mutex = MONGO_MAKE_LATCH("::_mutex");
- stdx::condition_variable _cv;
- std::vector<transport::SessionHandle> _sessions;
- transport::TransportLayer* _transport = nullptr;
-};
-
-std::string LoadFile(const std::string& name) {
- std::ifstream input(name);
- std::string str((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
- return str;
-}
-
TEST(SSLManager, matchHostname) {
enum Expected : bool { match = true, mismatch = false };
const struct {
@@ -486,120 +415,5 @@ TEST(SSLManager, BadDNParsing) {
}
}
-TEST(SSLManager, RotateCertificatesFromFile) {
- SSLParams params;
- params.sslMode.store(::mongo::sslGlobalParams.SSLMode_requireSSL);
- // Server is required to have the sslPEMKeyFile.
- params.sslPEMKeyFile = "jstests/libs/server.pem";
- params.sslCAFile = "jstests/libs/ca.pem";
- params.sslClusterFile = "jstests/libs/client.pem";
-
- std::shared_ptr<SSLManagerInterface> manager =
- SSLManagerInterface::create(params, true /* isSSLServer */);
-
- ServiceEntryPointUtil sepu;
-
- auto options = [] {
- ServerGlobalParams params;
- params.noUnixSocket = true;
- transport::TransportLayerASIO::Options opts(&params);
- return opts;
- }();
- transport::TransportLayerASIO tla(options, &sepu);
- uassertStatusOK(tla.rotateCertificates(manager, false /* asyncOCSPStaple */));
-}
-
-TEST(SSLManager, InitContextFromFileShouldFail) {
- SSLParams params;
- params.sslMode.store(::mongo::sslGlobalParams.SSLMode_requireSSL);
- // Server is required to have the sslPEMKeyFile.
- // We force the initialization to fail by omitting this param.
- params.sslCAFile = "jstests/libs/ca.pem";
- params.sslClusterFile = "jstests/libs/client.pem";
-
- ASSERT_THROWS_CODE([&params] { SSLManagerInterface::create(params, true /* isSSLServer */); }(),
- DBException,
- 16942);
-}
-
-TEST(SSLManager, RotateClusterCertificatesFromFile) {
- SSLParams params;
- params.sslMode.store(::mongo::sslGlobalParams.SSLMode_requireSSL);
- // Client doesn't need params.sslPEMKeyFile.
- params.sslCAFile = "jstests/libs/ca.pem";
- params.sslClusterFile = "jstests/libs/client.pem";
-
- std::shared_ptr<SSLManagerInterface> manager =
- SSLManagerInterface::create(params, false /* isSSLServer */);
-
- ServiceEntryPointUtil sepu;
-
- auto options = [] {
- ServerGlobalParams params;
- params.noUnixSocket = true;
- transport::TransportLayerASIO::Options opts(&params);
- return opts;
- }();
- transport::TransportLayerASIO tla(options, &sepu);
- uassertStatusOK(tla.rotateCertificates(manager, false /* asyncOCSPStaple */));
-}
-
-#if MONGO_CONFIG_SSL_PROVIDER != MONGO_CONFIG_SSL_PROVIDER_APPLE
-
-TEST(SSLManager, InitContextFromFile) {
- SSLParams params;
- params.sslMode.store(::mongo::sslGlobalParams.SSLMode_requireSSL);
- // Client doesn't need params.sslPEMKeyFile.
- params.sslClusterFile = "jstests/libs/client.pem";
-
- std::shared_ptr<SSLManagerInterface> manager =
- SSLManagerInterface::create(params, false /* isSSLServer */);
-
- auto egress = std::make_unique<asio::ssl::context>(asio::ssl::context::sslv23);
- uassertStatusOK(manager->initSSLContext(egress->native_handle(),
- params,
- TransientSSLParams(),
- SSLManagerInterface::ConnectionDirection::kOutgoing));
-}
-
-TEST(SSLManager, InitContextFromMemory) {
- SSLParams params;
- params.sslMode.store(::mongo::sslGlobalParams.SSLMode_requireSSL);
- params.sslCAFile = "jstests/libs/ca.pem";
-
- TransientSSLParams transientParams;
- transientParams.sslClusterPEMPayload = LoadFile("jstests/libs/client.pem");
-
- std::shared_ptr<SSLManagerInterface> manager =
- SSLManagerInterface::create(params, false /* isSSLServer */);
-
- auto egress = std::make_unique<asio::ssl::context>(asio::ssl::context::sslv23);
- uassertStatusOK(manager->initSSLContext(egress->native_handle(),
- params,
- transientParams,
- SSLManagerInterface::ConnectionDirection::kOutgoing));
-}
-
-TEST(SSLManager, InitServerSideContextFromMemory) {
- SSLParams params;
- params.sslMode.store(::mongo::sslGlobalParams.SSLMode_requireSSL);
- params.sslPEMKeyFile = "jstests/libs/server.pem";
- params.sslCAFile = "jstests/libs/ca.pem";
-
- TransientSSLParams transientParams;
- transientParams.sslClusterPEMPayload = LoadFile("jstests/libs/client.pem");
-
- std::shared_ptr<SSLManagerInterface> manager =
- SSLManagerInterface::create(params, true /* isSSLServer */);
-
- auto egress = std::make_unique<asio::ssl::context>(asio::ssl::context::sslv23);
- uassertStatusOK(manager->initSSLContext(egress->native_handle(),
- params,
- transientParams,
- SSLManagerInterface::ConnectionDirection::kOutgoing));
-}
-
-#endif
-
} // namespace
} // namespace mongo
diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp
index edaf395f139..ad938405d62 100644
--- a/src/mongo/util/net/ssl_manager_windows.cpp
+++ b/src/mongo/util/net/ssl_manager_windows.cpp
@@ -269,8 +269,7 @@ public:
*/
Status initSSLContext(SCHANNEL_CRED* cred,
const SSLParams& params,
- const TransientSSLParams& transientParams,
- ConnectionDirection direction) override final;
+ ConnectionDirection direction) final;
SSLConnectionInterface* connect(Socket* socket) final;
@@ -416,8 +415,7 @@ SSLManagerWindows::SSLManagerWindows(const SSLParams& params, bool isServer)
uassertStatusOK(_loadCertificates(params));
- uassertStatusOK(
- initSSLContext(&_clientCred, params, TransientSSLParams(), ConnectionDirection::kOutgoing));
+ uassertStatusOK(initSSLContext(&_clientCred, params, ConnectionDirection::kOutgoing));
// Certificates may not have been loaded. This typically occurs in unit tests.
if (_clientCertificates[0] != nullptr) {
@@ -427,8 +425,7 @@ SSLManagerWindows::SSLManagerWindows(const SSLParams& params, bool isServer)
// SSL server specific initialization
if (isServer) {
- uassertStatusOK(initSSLContext(
- &_serverCred, params, TransientSSLParams(), ConnectionDirection::kIncoming));
+ uassertStatusOK(initSSLContext(&_serverCred, params, ConnectionDirection::kIncoming));
if (_serverCertificates[0] != nullptr) {
SSLX509Name subjectName;
@@ -1354,7 +1351,6 @@ Status SSLManagerWindows::_loadCertificates(const SSLParams& params) {
Status SSLManagerWindows::initSSLContext(SCHANNEL_CRED* cred,
const SSLParams& params,
- const TransientSSLParams& transientParams,
ConnectionDirection direction) {
memset(cred, 0, sizeof(*cred));
@@ -1447,7 +1443,6 @@ SSLConnectionInterface* SSLManagerWindows::accept(Socket* socket,
void SSLManagerWindows::_handshake(SSLConnectionWindows* conn, bool client) {
initSSLContext(conn->_cred,
getSSLGlobalParams(),
- TransientSSLParams(),
client ? SSLManagerInterface::ConnectionDirection::kOutgoing
: SSLManagerInterface::ConnectionDirection::kIncoming);
diff --git a/src/mongo/util/net/ssl_options.h b/src/mongo/util/net/ssl_options.h
index e58bedcd076..755cfb030c3 100644
--- a/src/mongo/util/net/ssl_options.h
+++ b/src/mongo/util/net/ssl_options.h
@@ -134,6 +134,7 @@ struct SSLParams {
extern SSLParams sslGlobalParams;
+
// Additional SSL Params that could be used to augment a particular connection
// or have limited lifetime. In all cases, the fields stored here are not appropriate
// to be part of sslGlobalParams.