summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Shuvalov <andrew.shuvalov@mongodb.com>2021-08-06 21:34:26 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-08-06 22:03:25 +0000
commita3124693d95c37633cca3935d3d2515f63222d22 (patch)
tree60187d39af1834c72b9357643cee21f6358f4cd2
parent3f1695a90ae84726d560e02fb88b1521cde351d6 (diff)
downloadmongo-a3124693d95c37633cca3935d3d2515f63222d22.tar.gz
SERVER-59067: low level stress test for OpenSSL manager
-rw-r--r--src/mongo/util/net/ssl_manager_openssl.cpp10
-rw-r--r--src/mongo/util/net/ssl_manager_test.cpp109
2 files changed, 118 insertions, 1 deletions
diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp
index f847ce22706..563194e03c4 100644
--- a/src/mongo/util/net/ssl_manager_openssl.cpp
+++ b/src/mongo/util/net/ssl_manager_openssl.cpp
@@ -2686,7 +2686,7 @@ bool SSLManagerOpenSSL::_readCertificateChainFromMemory(
#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())) {
+ if (1 != SSL_CTX_add_extra_chain_cert(context, ca.get())) {
#endif
CaptureSSLErrorInAttrs capture(errorAttrs);
LOGV2_ERROR(
@@ -2695,6 +2695,10 @@ bool SSLManagerOpenSSL::_readCertificateChainFromMemory(
}
_getX509CertInfo(ca, &debugInfo, std::nullopt, targetClusterURI);
logCert(debugInfo, "", 5159902);
+#if OPENSSL_VERSION_NUMBER < 0x100010fFL
+ ca.release(); // Older version add_extra_chain_cert takes over the pointer without
+ // incrementing refcount. Avoid double free.
+#endif
}
// When the while loop ends, it's usually just EOF.
auto err = ERR_peek_last_error();
@@ -3462,6 +3466,10 @@ void SSLManagerOpenSSL::_getX509CertInfo(UniqueX509& x509,
CertInformationToLog* info,
std::optional<StringData> keyFile,
std::optional<StringData> targetClusterURI) {
+ if (!x509) {
+ return;
+ }
+
info->subject = getCertificateSubjectX509Name(x509.get());
info->issuer = convertX509ToSSLX509Name(X509_get_issuer_name(x509.get()));
diff --git a/src/mongo/util/net/ssl_manager_test.cpp b/src/mongo/util/net/ssl_manager_test.cpp
index 72902a32106..acebdca5fd8 100644
--- a/src/mongo/util/net/ssl_manager_test.cpp
+++ b/src/mongo/util/net/ssl_manager_test.cpp
@@ -627,6 +627,115 @@ TEST(SSLManager, TransientSSLParams) {
ASSERT_NOT_OK(tla.rotateCertificates(swContext.getValue()->manager, true));
}
+#if OPENSSL_VERSION_NUMBER >= 0x100010fFL
+
+TEST(SSLManager, TransientSSLParamsStressTestWithTransport) {
+ static constexpr int kMaxContexts = 100;
+ static constexpr int kThreads = 10;
+ SSLParams params;
+ params.sslMode.store(::mongo::sslGlobalParams.SSLMode_requireSSL);
+ params.sslCAFile = "jstests/libs/ca.pem";
+
+ ServiceEntryPointUtil sepu;
+
+ auto options = [] {
+ ServerGlobalParams params;
+ params.noUnixSocket = true;
+ transport::TransportLayerASIO::Options opts(&params);
+ return opts;
+ }();
+ transport::TransportLayerASIO tla(options, &sepu);
+
+ TransientSSLParams transientSSLParams;
+ transientSSLParams.sslClusterPEMPayload = loadFile("jstests/libs/client.pem");
+ transientSSLParams.targetedClusterConnectionString = ConnectionString::forLocal();
+
+ Mutex mutex = MONGO_MAKE_LATCH("::test_mutex");
+ std::deque<std::shared_ptr<const transport::SSLConnectionContext>> contexts;
+ std::vector<stdx::thread> threads;
+ Counter64 iterations;
+
+ for (int t = 0; t < kThreads; ++t) {
+ stdx::thread thread([&]() {
+ Timer timer;
+ while (timer.elapsed() < Seconds(2)) {
+ auto swContext = tla.createTransientSSLContext(transientSSLParams);
+ invariant(swContext.getStatus().isOK());
+ std::shared_ptr<const transport::SSLConnectionContext> ctxToDelete;
+ {
+ auto lk = stdx::lock_guard(mutex);
+ contexts.push_back(std::move(swContext.getValue()));
+ if (contexts.size() > kMaxContexts) {
+ ctxToDelete = contexts.front();
+ contexts.pop_front();
+ }
+ }
+ iterations.increment();
+ }
+ });
+ threads.push_back(std::move(thread));
+ }
+ for (auto& t : threads) {
+ t.join();
+ }
+
+ contexts.clear();
+ LOGV2(5906701, "Stress test completed", "iterations"_attr = iterations);
+}
+
+TEST(SSLManager, TransientSSLParamsStressTestWithManager) {
+ static constexpr int kMaxManagers = 100;
+ static constexpr int kThreads = 10;
+ 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");
+
+ Mutex mutex = MONGO_MAKE_LATCH("::test_mutex");
+ std::deque<std::shared_ptr<SSLManagerInterface>> managers;
+ std::vector<stdx::thread> threads;
+ int iterations = 0;
+
+ for (int t = 0; t < kThreads; ++t) {
+ stdx::thread thread([&]() {
+ Timer timer;
+ while (timer.elapsed() < Seconds(3)) {
+ std::shared_ptr<SSLManagerInterface> manager =
+ SSLManagerInterface::create(params, transientParams, true /* isSSLServer */);
+
+ auto egress = std::make_unique<asio::ssl::context>(asio::ssl::context::sslv23);
+ invariant(manager
+ ->initSSLContext(egress->native_handle(),
+ params,
+ SSLManagerInterface::ConnectionDirection::kOutgoing)
+ .isOK());
+ std::shared_ptr<SSLManagerInterface> managerToDelete;
+ {
+ auto lk = stdx::lock_guard(mutex);
+ managers.push_back(std::move(manager));
+ if (managers.size() > kMaxManagers) {
+ managerToDelete = managers.front();
+ managers.pop_front();
+ }
+ }
+ ++iterations;
+ }
+ });
+ threads.push_back(std::move(thread));
+ }
+ for (auto& t : threads) {
+ t.join();
+ }
+
+ managers.clear();
+ LOGV2(5906702, "Stress test completed", "iterations"_attr = iterations);
+}
+
+#endif // OPENSSL_VERSION_NUMBER >= 0x100010fFL
+
#endif // MONGO_CONFIG_SSL_PROVIDER == MONGO_CONFIG_SSL_PROVIDER_OPENSSL
static bool isSanWarningWritten(const std::vector<std::string>& logLines) {