summaryrefslogtreecommitdiff
path: root/src/mongo/util/net
diff options
context:
space:
mode:
authorLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
committerLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
commit4cb8841196d0625dfa3825aa326f071cd27c7b8b (patch)
tree1682a647d4463397c119183369ae6f750d5fdcff /src/mongo/util/net
parentaa03c6362cbaa767638e6eed9b031d86dd2643d1 (diff)
parent8f0827553e09872941945a093b647a4211a9db7f (diff)
Update upstream source from tag 'upstream/6.0.0'master
Update to upstream version '6.0.0' with Debian dir 5604a80ec1c96ca76f25f40d78e6ef855abec322
Diffstat (limited to 'src/mongo/util/net')
-rw-r--r--src/mongo/util/net/SConscript8
-rw-r--r--src/mongo/util/net/hostandport.cpp7
-rw-r--r--src/mongo/util/net/hostandport.h6
-rw-r--r--src/mongo/util/net/hostname_canonicalization.cpp6
-rw-r--r--src/mongo/util/net/http_client_curl.cpp100
-rw-r--r--src/mongo/util/net/http_client_options.cpp36
-rw-r--r--src/mongo/util/net/http_client_options.h46
-rw-r--r--src/mongo/util/net/http_client_options.idl38
-rw-r--r--src/mongo/util/net/ocsp/ocsp_manager.cpp1
-rw-r--r--src/mongo/util/net/openssl_init.cpp59
-rw-r--r--src/mongo/util/net/ssl_manager.cpp4
-rw-r--r--src/mongo/util/net/ssl_manager_apple.cpp57
-rw-r--r--src/mongo/util/net/ssl_manager_openssl.cpp65
-rw-r--r--src/mongo/util/net/ssl_manager_test.cpp1
-rw-r--r--src/mongo/util/net/ssl_manager_windows.cpp30
-rw-r--r--src/mongo/util/net/ssl_options.h1
-rw-r--r--src/mongo/util/net/ssl_options_server.cpp20
-rw-r--r--src/mongo/util/net/ssl_options_server.idl7
-rw-r--r--src/mongo/util/net/ssl_parameters.idl2
-rw-r--r--src/mongo/util/net/ssl_types.h1
20 files changed, 120 insertions, 375 deletions
diff --git a/src/mongo/util/net/SConscript b/src/mongo/util/net/SConscript
index 272cd9740a1..9aec6ba3150 100644
--- a/src/mongo/util/net/SConscript
+++ b/src/mongo/util/net/SConscript
@@ -33,9 +33,11 @@ env.Library(
source=[
"ssl_options.cpp",
],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
+ ],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/server_options_core',
- '$BUILD_DIR/mongo/idl/server_parameter',
'$BUILD_DIR/mongo/util/options_parser/options_parser',
]
)
@@ -62,13 +64,13 @@ env.Library(
'ssl_options_server.idl',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
'ssl_options',
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/auth/auth_options',
'$BUILD_DIR/mongo/db/auth/cluster_auth_mode',
'$BUILD_DIR/mongo/db/server_options_core',
- '$BUILD_DIR/mongo/idl/server_parameter',
'$BUILD_DIR/mongo/util/options_parser/options_parser',
]
)
@@ -207,8 +209,6 @@ else:
env.Library(
target='http_client_impl',
source=[
- 'http_client_options.idl',
- 'http_client_options.cpp',
'http_client_winhttp.cpp' if env.TargetOSIs('windows') else 'http_client_curl.cpp',
],
LIBDEPS=[
diff --git a/src/mongo/util/net/hostandport.cpp b/src/mongo/util/net/hostandport.cpp
index f351b51b9b9..eb22852a926 100644
--- a/src/mongo/util/net/hostandport.cpp
+++ b/src/mongo/util/net/hostandport.cpp
@@ -52,13 +52,6 @@ StatusWith<HostAndPort> HostAndPort::parse(StringData text) {
return StatusWith<HostAndPort>(result);
}
-Status validateHostAndPort(const std::string& hostAndPortStr) {
- if (hostAndPortStr.empty()) {
- return Status::OK();
- }
- return HostAndPort::parse(hostAndPortStr).getStatus();
-}
-
HostAndPort::HostAndPort() : _port(-1) {}
HostAndPort::HostAndPort(StringData text) {
diff --git a/src/mongo/util/net/hostandport.h b/src/mongo/util/net/hostandport.h
index 3c05c5d0c53..369437fb621 100644
--- a/src/mongo/util/net/hostandport.h
+++ b/src/mongo/util/net/hostandport.h
@@ -45,12 +45,6 @@ class StatusWith;
class StringData;
/**
- * Validate that a string is either empty or is parseable to a HostAndPort. This is intended for use
- * as an IDL validator callback.
- */
-Status validateHostAndPort(const std::string& hostAndPortStr);
-
-/**
* Name of a process on the network.
*
* Composed of some name component, followed optionally by a colon and a numeric port. The name
diff --git a/src/mongo/util/net/hostname_canonicalization.cpp b/src/mongo/util/net/hostname_canonicalization.cpp
index dd31e4b7015..f11ee345480 100644
--- a/src/mongo/util/net/hostname_canonicalization.cpp
+++ b/src/mongo/util/net/hostname_canonicalization.cpp
@@ -111,6 +111,7 @@ StatusWith<std::vector<std::string>> getHostFQDNs(std::string hostName,
std::vector<std::string> getNameInfoErrors;
for (shim_addrinfo* p = info; p; p = p->ai_next) {
+ std::stringstream getNameInfoError;
shim_char host[NI_MAXHOST] = {};
if ((err = shim_getnameinfo(
p->ai_addr, p->ai_addrlen, host, sizeof(host), nullptr, 0, NI_NAMEREQD)) == 0) {
@@ -129,7 +130,6 @@ StatusWith<std::vector<std::string>> getHostFQDNs(std::string hostName,
sin_addr = reinterpret_cast<void*>(&addr_in6->sin6_addr);
}
- std::stringstream getNameInfoError;
if (sin_addr) {
invariant(inet_ntop(p->ai_family, sin_addr, ip_str, sizeof(ip_str)) != nullptr);
getNameInfoError << ip_str;
@@ -138,8 +138,8 @@ StatusWith<std::vector<std::string>> getHostFQDNs(std::string hostName,
}
getNameInfoError << ": \"" << getAddrInfoStrError(err);
- getNameInfoErrors.push_back(getNameInfoError.str());
}
+ getNameInfoErrors.push_back(getNameInfoError.str());
}
if (!getNameInfoErrors.empty()) {
@@ -150,8 +150,6 @@ StatusWith<std::vector<std::string>> getHostFQDNs(std::string hostName,
"errors"_attr = getNameInfoErrors);
}
- LOGV2_DEBUG(7317600, 4, "Name info: {results}", "Name info", "results"_attr = results);
-
// Deduplicate the results list
std::sort(results.begin(), results.end());
results.erase(std::unique(results.begin(), results.end()), results.end());
diff --git a/src/mongo/util/net/http_client_curl.cpp b/src/mongo/util/net/http_client_curl.cpp
index 9db3c06f73f..fa1834c8bde 100644
--- a/src/mongo/util/net/http_client_curl.cpp
+++ b/src/mongo/util/net/http_client_curl.cpp
@@ -27,8 +27,6 @@
* it in the license file.
*/
-#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kNetwork
-
#include "mongo/platform/basic.h"
#include <cstddef>
@@ -49,24 +47,22 @@
#include "mongo/db/commands/server_status.h"
#include "mongo/executor/connection_pool.h"
#include "mongo/executor/connection_pool_stats.h"
-#include "mongo/logv2/log.h"
#include "mongo/platform/mutex.h"
#include "mongo/stdx/unordered_map.h"
#include "mongo/transport/transport_layer.h"
#include "mongo/util/alarm.h"
#include "mongo/util/alarm_runner_background_thread.h"
#include "mongo/util/assert_util.h"
-#include "mongo/util/bufreader.h"
#include "mongo/util/concurrency/thread_pool.h"
#include "mongo/util/functional.h"
#include "mongo/util/net/hostandport.h"
#include "mongo/util/net/http_client.h"
-#include "mongo/util/net/http_client_options.h"
#include "mongo/util/processinfo.h"
#include "mongo/util/strong_weak_finish_line.h"
#include "mongo/util/system_clock_source.h"
#include "mongo/util/timer.h"
+
namespace mongo {
namespace {
@@ -163,40 +159,20 @@ size_t WriteMemoryCallback(void* ptr, size_t size, size_t nmemb, void* data) {
*/
size_t ReadMemoryCallback(char* buffer, size_t size, size_t nitems, void* instream) {
- auto* bufReader = reinterpret_cast<BufReader*>(instream);
+ auto* cdrc = reinterpret_cast<ConstDataRangeCursor*>(instream);
size_t ret = 0;
- if (bufReader->remaining() > 0) {
- size_t readSize =
- std::min(size * nitems, static_cast<unsigned long>(bufReader->remaining()));
- auto buf = bufReader->readBytes(readSize);
- memcpy(buffer, buf.rawData(), readSize);
+ if (cdrc->length() > 0) {
+ size_t readSize = std::min(size * nitems, cdrc->length());
+ memcpy(buffer, cdrc->data(), readSize);
+ invariant(cdrc->advanceNoThrow(readSize).isOK());
ret = readSize;
}
return ret;
}
-/**
- * Seek into for data to the remote side
- */
-size_t SeekMemoryCallback(void* clientp, curl_off_t offset, int origin) {
-
- // Curl will call this in readrewind but only to reset the stream to the beginning
- // In other protocols (like FTP, SSH) or HTTP resumption they may ask for partial buffers which
- // we do not support.
- if (offset != 0 || origin != SEEK_SET) {
- return CURL_SEEKFUNC_CANTSEEK;
- }
-
- auto* bufReader = reinterpret_cast<BufReader*>(clientp);
-
- bufReader->rewindToStart();
-
- return CURL_SEEKFUNC_OK;
-}
-
struct CurlEasyCleanup {
void operator()(CURL* handle) {
if (handle) {
@@ -220,47 +196,6 @@ long longSeconds(Seconds tm) {
return static_cast<long>(durationCount<Seconds>(tm));
}
-
-StringData enumToString(curl_infotype type) {
- switch (type) {
- case CURLINFO_TEXT:
- return "TEXT"_sd;
- case CURLINFO_HEADER_IN:
- return "HEADER_IN"_sd;
- case CURLINFO_HEADER_OUT:
- return "HEADER_OUT"_sd;
- case CURLINFO_DATA_IN:
- return "DATA_IN"_sd;
- case CURLINFO_DATA_OUT:
- return "DATA_OUT"_sd;
- case CURLINFO_SSL_DATA_IN:
- return "SSL_DATA_IN"_sd;
- case CURLINFO_SSL_DATA_OUT:
- return "SSL_DATA_OUT"_sd;
- default:
- return "unknown"_sd;
- }
-}
-
-int curlDebugCallback(CURL* handle, curl_infotype type, char* data, size_t size, void* clientp) {
- switch (type) {
- case CURLINFO_TEXT:
- case CURLINFO_HEADER_IN:
- case CURLINFO_HEADER_OUT:
- case CURLINFO_DATA_IN:
- case CURLINFO_DATA_OUT:
- LOGV2_DEBUG(7661901,
- 1,
- "Curl",
- "type"_attr = enumToString(type),
- "message"_attr = StringData(data, size));
- [[fallthrough]];
-
- default:
- return 0;
- }
-}
-
CurlEasyHandle createCurlEasyHandle(Protocols protocol) {
CurlEasyHandle handle(curl_easy_init());
uassert(ErrorCodes::InternalError, "Curl initialization failed", handle);
@@ -291,10 +226,9 @@ CurlEasyHandle createCurlEasyHandle(Protocols protocol) {
}
// TODO: CURLOPT_EXPECT_100_TIMEOUT_MS?
- if (httpClientOptions.verboseLogging.loadRelaxed()) {
- curl_easy_setopt(handle.get(), CURLOPT_VERBOSE, 1);
- curl_easy_setopt(handle.get(), CURLOPT_DEBUGFUNCTION, curlDebugCallback);
- }
+ // TODO: consider making this configurable, defaults to stderr
+ // curl_easy_setopt(handle.get(), CURLOPT_VERBOSE, 1);
+ // curl_easy_setopt(_handle.get(), CURLOPT_DEBUGFUNCTION , ???);
return handle;
}
@@ -696,7 +630,7 @@ private:
curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, longSeconds(_connectTimeout));
- BufReader bufReader(cdr.data(), cdr.length());
+ ConstDataRangeCursor cdrc(cdr);
switch (method) {
case HttpMethod::kGET:
uassert(ErrorCodes::BadValue,
@@ -711,22 +645,16 @@ private:
curl_easy_setopt(handle, CURLOPT_POST, 1);
curl_easy_setopt(handle, CURLOPT_READFUNCTION, ReadMemoryCallback);
- curl_easy_setopt(handle, CURLOPT_READDATA, &bufReader);
- curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, (long)bufReader.remaining());
-
- curl_easy_setopt(handle, CURLOPT_SEEKFUNCTION, SeekMemoryCallback);
- curl_easy_setopt(handle, CURLOPT_SEEKDATA, &bufReader);
+ curl_easy_setopt(handle, CURLOPT_READDATA, &cdrc);
+ curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, (long)cdrc.length());
break;
case HttpMethod::kPUT:
curl_easy_setopt(handle, CURLOPT_POST, 0);
curl_easy_setopt(handle, CURLOPT_PUT, 1);
curl_easy_setopt(handle, CURLOPT_READFUNCTION, ReadMemoryCallback);
- curl_easy_setopt(handle, CURLOPT_READDATA, &bufReader);
- curl_easy_setopt(handle, CURLOPT_INFILESIZE_LARGE, (long)bufReader.remaining());
-
- curl_easy_setopt(handle, CURLOPT_SEEKFUNCTION, SeekMemoryCallback);
- curl_easy_setopt(handle, CURLOPT_SEEKDATA, &bufReader);
+ curl_easy_setopt(handle, CURLOPT_READDATA, &cdrc);
+ curl_easy_setopt(handle, CURLOPT_INFILESIZE_LARGE, (long)cdrc.length());
break;
default:
MONGO_UNREACHABLE;
diff --git a/src/mongo/util/net/http_client_options.cpp b/src/mongo/util/net/http_client_options.cpp
deleted file mode 100644
index 7e96be222ac..00000000000
--- a/src/mongo/util/net/http_client_options.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Copyright (C) 2023-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/util/net/http_client_options.h"
-
-namespace mongo {
-
-HttpClientOptions httpClientOptions;
-
-}
diff --git a/src/mongo/util/net/http_client_options.h b/src/mongo/util/net/http_client_options.h
deleted file mode 100644
index ebf4611677a..00000000000
--- a/src/mongo/util/net/http_client_options.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * Copyright (C) 2023-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#pragma once
-
-#include "mongo/platform/atomic_word.h"
-
-namespace mongo {
-struct HttpClientOptions {
- /**
- * Boolean flag that indicates whether verbose logging for http clients should be enabled.
- *
- * Note: only affects new handles. This means that if connection pooling is in use, this will
- * not take affect on existing connections.
- */
- AtomicWord<bool> verboseLogging;
-};
-
-extern HttpClientOptions httpClientOptions;
-} // namespace mongo
diff --git a/src/mongo/util/net/http_client_options.idl b/src/mongo/util/net/http_client_options.idl
deleted file mode 100644
index b53b5e5541b..00000000000
--- a/src/mongo/util/net/http_client_options.idl
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2023-present MongoDB, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the Server Side Public License, version 1,
-# as published by MongoDB, Inc.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# Server Side Public License for more details.
-#
-# You should have received a copy of the Server Side Public License
-# along with this program. If not, see
-# <http://www.mongodb.com/licensing/server-side-public-license>.
-#
-# As a special exception, the copyright holders give permission to link the
-# code of portions of this program with the OpenSSL library under certain
-# conditions as described in each individual source file and distribute
-# linked combinations including the program with the OpenSSL library. You
-# must comply with the Server Side Public License in all respects for
-# all of the code used other than as permitted herein. If you modify file(s)
-# with this exception, you may extend this exception to your version of the
-# file(s), but you are not obligated to do so. If you do not wish to do so,
-# delete this exception statement from your version. If you delete this
-# exception statement from all source files in the program, then also delete
-# it in the license file.
-
-global:
- cpp_namespace: "mongo"
- cpp_includes:
- - "mongo/util/net/http_client_options.h"
-
-server_parameters:
- httpVerboseLogging:
- description: Boolean flag that indicates whether verbose logging for http clients should be enabled.
- set_at: [ startup, runtime ]
- default: false
- cpp_varname: "httpClientOptions.verboseLogging"
diff --git a/src/mongo/util/net/ocsp/ocsp_manager.cpp b/src/mongo/util/net/ocsp/ocsp_manager.cpp
index b8d0b2683dd..1524d1da560 100644
--- a/src/mongo/util/net/ocsp/ocsp_manager.cpp
+++ b/src/mongo/util/net/ocsp/ocsp_manager.cpp
@@ -68,6 +68,7 @@ void OCSPManager::start(ServiceContext* service) {
void OCSPManager::shutdown(ServiceContext* service) {
get(service)->_pool->shutdown();
+ getOCSPManager(service).reset();
}
OCSPManager::OCSPManager() {
diff --git a/src/mongo/util/net/openssl_init.cpp b/src/mongo/util/net/openssl_init.cpp
index 5ef31f1212b..89e5a1c4498 100644
--- a/src/mongo/util/net/openssl_init.cpp
+++ b/src/mongo/util/net/openssl_init.cpp
@@ -46,12 +46,6 @@
#include <stack>
#include <vector>
-#if OPENSSL_VERSION_NUMBER > 0x30000000L
-#include <openssl/provider.h>
-#endif
-
-#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kNetwork
-
namespace mongo {
namespace {
@@ -150,54 +144,21 @@ private:
}
};
-#if OPENSSL_VERSION_NUMBER > 0x30000000L
-#define _SUPPORT_FIPS 1
-
-OSSL_PROVIDER* fipsProvider;
-OSSL_PROVIDER* baseProvider;
-
-void initFIPS() {
- // OpenSSL 3 has a different FIPS design then previous OpenSSL. To load FIPS, we use the FIPS
- // algorithm provider which we load into the "default" library context.
- fipsProvider = OSSL_PROVIDER_load(NULL, "fips");
- if (fipsProvider == NULL) {
- LOGV2_FATAL_NOTRACE(
- 7585801,
- "Failed to load OpenSSL 3 FIPS provider. OpenSSL was not compiled with FIPS support.",
- "error"_attr = SSLManagerInterface::getSSLErrorMessage(ERR_get_error()));
- }
-
- // Base provide has non-cryptographic algorihms (like encoding/decoding keys)
- baseProvider = OSSL_PROVIDER_load(NULL, "base");
- if (baseProvider == NULL) {
- LOGV2_FATAL_NOTRACE(7585802,
- "Failed to load OpenSSL 3 Base provider",
- "error"_attr =
- SSLManagerInterface::getSSLErrorMessage(ERR_get_error()));
- }
-}
-#elif defined(MONGO_CONFIG_HAVE_FIPS_MODE_SET)
-
-#define _SUPPORT_FIPS 1
-
-void initFIPS() {
+void setupFIPS() {
+// Turn on FIPS mode if requested, OPENSSL_FIPS must be defined by the OpenSSL headers
+#if defined(MONGO_CONFIG_HAVE_FIPS_MODE_SET)
int status = FIPS_mode_set(1);
if (!status) {
- LOGV2_FATAL_NOTRACE(23173,
- "Can't activate FIPS mode",
- "error"_attr =
- SSLManagerInterface::getSSLErrorMessage(ERR_get_error()));
+ LOGV2_FATAL(23173,
+ "can't activate FIPS mode: {error}",
+ "Can't activate FIPS mode",
+ "error"_attr = SSLManagerInterface::getSSLErrorMessage(ERR_get_error()));
+ fassertFailedNoTrace(16703);
}
-}
-#endif
-
-void setupFIPS() {
-// Turn on FIPS mode if requested, OPENSSL_FIPS must be defined by the OpenSSL headers
-#if defined(_SUPPORT_FIPS)
- initFIPS();
LOGV2(23172, "FIPS 140-2 mode activated");
#else
- LOGV2_FATAL_NOTRACE(23174, "this version of mongodb was not compiled with FIPS support");
+ LOGV2_FATAL(23174, "this version of mongodb was not compiled with FIPS support");
+ fassertFailedNoTrace(17089);
#endif
}
diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp
index c784c3792d6..2f4a6fb713f 100644
--- a/src/mongo/util/net/ssl_manager.cpp
+++ b/src/mongo/util/net/ssl_manager.cpp
@@ -38,7 +38,6 @@
#include <string>
#include <vector>
-#include "mongo/base/data_view.h"
#include "mongo/base/init.h"
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/client/internal_auth.h"
@@ -780,6 +779,7 @@ bool SSLConfiguration::isClusterMember(StringData subjectName) const {
void SSLConfiguration::getServerStatusBSON(BSONObjBuilder* security) const {
security->append("SSLServerSubjectName", _serverSubjectName.toString());
+ security->appendBool("SSLServerHasCertificateAuthority", hasCA);
security->appendDate("SSLServerCertificateExpirationDate", serverCertificateExpirationDate);
}
@@ -1048,7 +1048,7 @@ StatusWith<DERToken> DERToken::parse(ConstDataRange cdr, size_t* outLength) {
derLength = ConstDataView(lengthBuffer.data()).read<BigEndian<uint64_t>>();
} else {
// Length is <= 127 bytes, i.e. short form of length
- derLength = ConstDataView(&initialLengthByte).read<uint8_t>();
+ derLength = initialLengthByte;
}
// This is the total length of the TLV and all data
diff --git a/src/mongo/util/net/ssl_manager_apple.cpp b/src/mongo/util/net/ssl_manager_apple.cpp
index f3e0f4d6652..ec77dc17722 100644
--- a/src/mongo/util/net/ssl_manager_apple.cpp
+++ b/src/mongo/util/net/ssl_manager_apple.cpp
@@ -1369,15 +1369,20 @@ SSLManagerApple::SSLManagerApple(const SSLParams& params, bool isServer)
}
}
- // If the user has specified --setParameter tlsUseSystemCA=true, then no params.sslCAFile nor
- // params.sslClusterCAFile will be defined, and the SSL Manager will fall back to the System CA.
if (!params.sslCAFile.empty()) {
auto ca = uassertStatusOK(loadPEM(params.sslCAFile, "", kLoadPEMStripKeys));
_clientCA = std::move(ca);
+ _sslConfiguration.hasCA = _clientCA && ::CFArrayGetCount(_clientCA.get());
+ }
+
+ if (!params.sslCertificateSelector.empty() || !params.sslClusterCertificateSelector.empty()) {
+ // By using the system keychain, we acknowledge it exists.
+ _sslConfiguration.hasCA = true;
}
if (!_clientCA) {
- // No explicit CA was specified, use the Keychain CA explicitly
+ // No explicit CA was specified, use the Keychain CA explicitly on client connects,
+ // even though we're going to pretend it doesn't exist on server.
::CFArrayRef certs = nullptr;
uassertOSStatusOK(SecTrustCopyAnchorCertificates(&certs));
_clientCA.reset(certs);
@@ -1552,6 +1557,17 @@ Future<SSLPeerInfo> SSLManagerApple::parseAndValidatePeerCertificate(
recordTLSVersion(tlsVersionStatus.getValue(), hostForLogging);
+ /* While we always have a system CA via the Keychain,
+ * we'll pretend not to in terms of validation if the server
+ * was started using a PEM file (legacy mode).
+ *
+ * When a certificate selector is used, we'll override hasCA to true
+ * so that the validation path runs anyway.
+ */
+ if (!_sslConfiguration.hasCA && isSSLServer) {
+ return Future<SSLPeerInfo>::makeReady(SSLPeerInfo(sniName));
+ }
+
const auto badCert = [&](StringData msg, bool warn = false) -> Future<SSLPeerInfo> {
if (warn) {
LOGV2_WARNING(23209,
@@ -1576,7 +1592,7 @@ Future<SSLPeerInfo> SSLManagerApple::parseAndValidatePeerCertificate(
return SSLPeerInfo(sniName);
} else {
if (status == ::errSecSuccess) {
- return badCert(str::stream() << "No SSL certificate provided by peer: "
+ return badCert(str::stream() << "no SSL certificate provided by peer: "
<< stringFromOSStatus(status),
_weakValidation);
} else {
@@ -1654,14 +1670,11 @@ Future<SSLPeerInfo> SSLManagerApple::parseAndValidatePeerCertificate(
return swPeerSubjectName.getStatus();
}
const auto peerSubjectName = std::move(swPeerSubjectName.getValue());
- // The cipher will be presented as a number.
- ::SSLCipherSuite cipher;
- uassertOSStatusOK(::SSLGetNegotiatedCipher(ssl, &cipher));
-
- LOGV2_INFO(6723803,
- "Accepted TLS connection from peer",
- "peerSubjectName"_attr = peerSubjectName,
- "cipher"_attr = cipher);
+ LOGV2_DEBUG(23207,
+ 2,
+ "Accepted TLS connection from peer: {peerSubjectName}",
+ "Accepted TLS connection from peer",
+ "peerSubjectName"_attr = peerSubjectName);
// Server side.
if (remoteHost.empty()) {
@@ -1874,26 +1887,8 @@ MONGO_INITIALIZER_WITH_PREREQUISITES(SSLManager, ("EndStartupOptionHandling"))
kMongoDBRolesOID = ::CFStringCreateWithCString(
nullptr, mongodbRolesOID.identifier.c_str(), ::kCFStringEncodingUTF8);
- // TODO SERVER-67419 This retry logic is a workaround; reconsider this approach after
- // investigation.
- constexpr int kMaxRetries = 10;
if (!isSSLServer || (sslGlobalParams.sslMode.load() != SSLParams::SSLMode_disabled)) {
- for (int i = 0; i < kMaxRetries; i++) {
- try {
- theSSLManagerCoordinator = new SSLManagerCoordinator();
- return;
- } catch (const ExceptionFor<ErrorCodes::InvalidSSLConfiguration>& e) {
- bool isRetriableError = nullptr != strstr(e.what(), "No keychain is available.");
- if (!isRetriableError || i == kMaxRetries - 1) {
- // Rethrow if a different error or we fail on final iteration
- throw;
- }
- LOGV2_INFO(6741800,
- "Caught exception during apple SSLManagerCoordinator creation, retrying",
- "try"_attr = i,
- "error"_attr = e.what());
- }
- }
+ theSSLManagerCoordinator = new SSLManagerCoordinator();
}
}
diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp
index 48461e4120d..f2ddee148c7 100644
--- a/src/mongo/util/net/ssl_manager_openssl.cpp
+++ b/src/mongo/util/net/ssl_manager_openssl.cpp
@@ -123,7 +123,12 @@ struct X509StackDeleter {
}
}
};
-using UniqueStackOfX509 = std::unique_ptr<STACK_OF(X509), X509StackDeleter>;
+
+// If we have an X509 Stack that is owned by an internal SSL Object, we need to use this
+// deleter.
+struct X509StackDeleterNoOp {
+ void operator()(STACK_OF(X509) * chain) {}
+};
// Modulus for Diffie-Hellman parameter 'ffdhe3072' defined in RFC 7919
constexpr std::array<std::uint8_t, 384> ffdhe3072_p = {
@@ -319,6 +324,25 @@ X509* X509_OBJECT_get0_X509(const X509_OBJECT* a) {
return a->data.x509;
}
+using UniqueVerifiedChainPolyfill = std::unique_ptr<STACK_OF(X509), X509StackDeleter>;
+
+STACK_OF(X509) * SSL_get0_verified_chain(SSL* s) {
+ auto* store = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s));
+ UniqueX509 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.get(), peerChain)) {
+ return nullptr;
+ }
+
+ if (X509_verify_cert(ctx.get()) <= 0) {
+ return nullptr;
+ }
+
+ return X509_STORE_CTX_get1_chain(ctx.get());
+}
+
const OCSP_CERTID* OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP* single) {
return single->certId;
}
@@ -351,23 +375,14 @@ static ASN1OID tlsFeatureOID("1.3.6.1.5.5.7.1.24", "tlsfeature", "TLS Feature");
static int const NID_tlsfeature = OBJ_create(tlsFeatureOID.identifier.c_str(),
tlsFeatureOID.shortDescription.c_str(),
tlsFeatureOID.longDescription.c_str());
-#endif
-
-UniqueStackOfX509 SSLgetVerifiedChain(SSL* s) {
- auto* store = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s));
- auto* peerChain = SSL_get_peer_cert_chain(s);
- UniqueX509 peer(SSL_get_peer_certificate(s));
- UniqueX509StoreCtx ctx(X509_STORE_CTX_new());
- if (!X509_STORE_CTX_init(ctx.get(), store, peer.get(), peerChain)) {
- return nullptr;
- }
+#else
+using UniqueVerifiedChainPolyfill = std::unique_ptr<STACK_OF(X509), X509StackDeleterNoOp>;
- if (X509_verify_cert(ctx.get()) <= 0) {
- return nullptr;
- }
+#endif
- return UniqueStackOfX509(X509_STORE_CTX_get1_chain(ctx.get()));
+UniqueVerifiedChainPolyfill SSLgetVerifiedChain(SSL* s) {
+ return UniqueVerifiedChainPolyfill(SSL_get0_verified_chain(s));
}
SSLX509Name convertX509ToSSLX509Name(X509_NAME* x509Name) {
@@ -641,7 +656,7 @@ std::vector<std::vector<unsigned char>> convertStackOfX509ToDERVec(STACK_OF(X509
}
struct OCSPCacheKey {
- OCSPCacheKey(UniqueX509 cert, SSL_CTX* context, UniqueStackOfX509 intermediateCerts)
+ OCSPCacheKey(UniqueX509 cert, SSL_CTX* context, UniqueVerifiedChainPolyfill intermediateCerts)
: peerCert(std::move(cert)),
context(context),
intermediateCerts(std::move(intermediateCerts)),
@@ -2539,8 +2554,6 @@ Status SSLManagerOpenSSL::initSSLContext(SSL_CTX* context,
}
}
- // If the user has specified --setParameter tlsUseSystemCA=true, then no params.sslCAFile nor
- // params.sslClusterCAFile will be defined, and the SSL Manager will fall back to the System CA.
std::string cafile = params.sslCAFile;
if (direction == ConnectionDirection::kIncoming && !params.sslClusterCAFile.empty()) {
cafile = params.sslClusterCAFile;
@@ -2955,6 +2968,7 @@ Status SSLManagerOpenSSL::_setupCA(SSL_CTX* context, const std::string& caFile)
// Set SSL to require peer (client) certificate verification
// if a certificate is presented
SSL_CTX_set_verify(context, SSL_VERIFY_PEER, &SSLManagerOpenSSL::verify_cb);
+ _sslConfiguration.hasCA = true;
return Status::OK();
}
@@ -2979,7 +2993,7 @@ Status SSLManagerOpenSSL::_setupSystemCA(SSL_CTX* context) {
<< "(default certificate file: " << X509_get_default_cert_file() << ", "
<< "default certificate path: " << X509_get_default_cert_dir() << ")"};
}
- SSL_CTX_set_verify(context, SSL_VERIFY_PEER, &SSLManagerOpenSSL::verify_cb);
+
return Status::OK();
}
@@ -3219,6 +3233,9 @@ Future<SSLPeerInfo> SSLManagerOpenSSL::parseAndValidatePeerCertificate(
recordTLSVersion(tlsVersionStatus.getValue(), hostForLogging);
+ if (!_sslConfiguration.hasCA && isSSLServer)
+ return SSLPeerInfo(sni);
+
UniqueX509 peerCert(SSL_get_peer_certificate(conn));
if (nullptr == peerCert) { // no certificate presented by peer
@@ -3271,11 +3288,11 @@ Future<SSLPeerInfo> SSLManagerOpenSSL::parseAndValidatePeerCertificate(
// TODO: check optional cipher restriction, using cert.
auto peerSubject = getCertificateSubjectX509Name(peerCert.get());
- const auto cipher = SSL_get_current_cipher(conn);
- LOGV2_INFO(6723801,
- "Accepted TLS connection from peer",
- "peerSubject"_attr = peerSubject,
- "cipher"_attr = SSL_CIPHER_get_name(cipher));
+ LOGV2_DEBUG(23229,
+ 2,
+ "Accepted TLS connection from peer: {peerSubject}",
+ "Accepted TLS connection from peer",
+ "peerSubject"_attr = peerSubject);
StatusWith<stdx::unordered_set<RoleName>> swPeerCertificateRoles =
_parsePeerRoles(peerCert.get());
diff --git a/src/mongo/util/net/ssl_manager_test.cpp b/src/mongo/util/net/ssl_manager_test.cpp
index 913c8ba983b..1dd6585f7c1 100644
--- a/src/mongo/util/net/ssl_manager_test.cpp
+++ b/src/mongo/util/net/ssl_manager_test.cpp
@@ -780,5 +780,6 @@ TEST(SSLManager, InitContextNoSanWarning) {
ASSERT_FALSE(isSanWarningWritten(getCapturedTextFormatLogMessages()));
}
+
} // namespace
} // namespace mongo
diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp
index 7169e1eef1f..adf86ae847f 100644
--- a/src/mongo/util/net/ssl_manager_windows.cpp
+++ b/src/mongo/util/net/ssl_manager_windows.cpp
@@ -1284,9 +1284,11 @@ Status SSLManagerWindows::_loadCertificates(const SSLParams& params) {
_clientCertificates[0] = std::get<0>(_clusterPEMCertificate).get();
}
- // If the user has specified --setParameter tlsUseSystemCA=true, then no params.sslCAFile nor
- // params.sslClusterCAFile will be defined, and the SSL Manager will fall back to the System CA.
if (!params.sslCAFile.empty()) {
+ // SChannel always has a CA even when the user does not specify one
+ // The openssl implementations uses this to decide if it wants to do certificate validation
+ // on the server side.
+ _sslConfiguration.hasCA = true;
auto swChain = readCertChains(params.sslCAFile, params.sslCRLFile);
if (!swChain.isOK()) {
@@ -1349,8 +1351,10 @@ Status SSLManagerWindows::_loadCertificates(const SSLParams& params) {
if (!params.sslCAFile.empty()) {
LOGV2_WARNING(23271,
"Mixing certs from the system certificate store and PEM files. This may "
- "produce unexpected results.");
+ "produced unexpected results.");
}
+
+ _sslConfiguration.hasCA = true;
}
if (_sslCertificate) {
@@ -2003,6 +2007,9 @@ Future<SSLPeerInfo> SSLManagerWindows::parseAndValidatePeerCertificate(
recordTLSVersion(tlsVersionStatus.getValue(), hostForLogging);
+ if (!_sslConfiguration.hasCA && isSSLServer)
+ return Future<SSLPeerInfo>::makeReady(SSLPeerInfo(sni));
+
SECURITY_STATUS ss = QueryContextAttributes(ssl, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &cert);
if (ss == SEC_E_NO_CREDENTIALS) { // no certificate presented by peer
@@ -2062,19 +2069,10 @@ Future<SSLPeerInfo> SSLManagerWindows::parseAndValidatePeerCertificate(
return Future<SSLPeerInfo>::makeReady(SSLPeerInfo(sni));
}
- SecPkgContext_CipherInfo cipherInfo;
- SECURITY_STATUS ssCipher = QueryContextAttributes(ssl, SECPKG_ATTR_CIPHER_INFO, &cipherInfo);
- if (ssCipher != SEC_E_OK) {
- return Status(ErrorCodes::SSLHandshakeFailed,
- str::stream()
- << "QueryContextAttributes for connection info failed with" << ssCipher);
- }
- const auto cipher = std::wstring(cipherInfo.szCipherSuite);
-
- LOGV2_INFO(6723802,
- "Accepted TLS connection from peer",
- "peerSubjectName"_attr = peerSubjectName,
- "cipher"_attr = toUtf8String(cipher));
+ LOGV2_DEBUG(23270,
+ 2,
+ "Accepted TLS connection from peer: {peerSubjectName}",
+ "peerSubjectName"_attr = peerSubjectName);
// If this is a server and client and server certificate are the same, log a warning.
if (remoteHost.empty() && _sslConfiguration.serverSubjectName() == peerSubjectName) {
diff --git a/src/mongo/util/net/ssl_options.h b/src/mongo/util/net/ssl_options.h
index 13f7303704e..e58bedcd076 100644
--- a/src/mongo/util/net/ssl_options.h
+++ b/src/mongo/util/net/ssl_options.h
@@ -93,7 +93,6 @@ struct SSLParams {
bool sslFIPSMode = false; // --sslFIPSMode
bool sslAllowInvalidCertificates = false; // --sslAllowInvalidCertificates
bool sslAllowInvalidHostnames = false; // --sslAllowInvalidHostnames
- bool sslUseSystemCA = false; // --setParameter tlsUseSystemCA
bool disableNonSSLConnectionLogging =
false; // --setParameter disableNonSSLConnectionLogging=true
bool disableNonSSLConnectionLoggingSet = false;
diff --git a/src/mongo/util/net/ssl_options_server.cpp b/src/mongo/util/net/ssl_options_server.cpp
index eb67d49e2c3..4612993df07 100644
--- a/src/mongo/util/net/ssl_options_server.cpp
+++ b/src/mongo/util/net/ssl_options_server.cpp
@@ -29,7 +29,6 @@
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kControl
-#include "mongo/base/error_codes.h"
#include "mongo/platform/basic.h"
#include "mongo/util/net/ssl_options.h"
@@ -193,27 +192,14 @@ MONGO_STARTUP_OPTIONS_POST(SSLServerOptions)(InitializerContext*) {
const auto clusterAuthMode = serverGlobalParams.startupClusterAuthMode;
if (sslGlobalParams.sslMode.load() != SSLParams::SSLMode_disabled) {
- uassert(ErrorCodes::InvalidOptions,
- "Specifying a tlsClusterCAFile requires a tlsCAFile also be specified. See "
- "https://dochub.mongodb.org/core/mongod"
- "#std-option-mongod.--tlsClusterCAFile for details.",
- sslGlobalParams.sslClusterCAFile.empty() || !sslGlobalParams.sslCAFile.empty());
- uassert(ErrorCodes::InvalidOptions,
- "The use of both a CA File and the System Certificate store is not supported.",
- !sslGlobalParams.sslUseSystemCA || sslGlobalParams.sslCAFile.empty());
- uassert(ErrorCodes::InvalidOptions,
- "The use of TLS without specifying a chain of trust is no longer supported. See "
- "https://jira.mongodb.org/browse/SERVER-72839 for details.",
- sslGlobalParams.sslUseSystemCA || !sslGlobalParams.sslCAFile.empty());
- if (!sslGlobalParams.sslCRLFile.empty() && sslGlobalParams.sslCAFile.empty()) {
- uasserted(ErrorCodes::BadValue,
- "Specifying a tlsCRLFile requires a tlsCAFile also be specified.");
- }
bool usingCertifiateSelectors = params.count("net.tls.certificateSelector");
if (sslGlobalParams.sslPEMKeyFile.size() == 0 && !usingCertifiateSelectors) {
uasserted(ErrorCodes::BadValue,
"need tlsCertificateKeyFile or certificateSelector when TLS is enabled");
}
+ if (!sslGlobalParams.sslCRLFile.empty() && sslGlobalParams.sslCAFile.empty()) {
+ uasserted(ErrorCodes::BadValue, "need tlsCAFile with tlsCRLFile");
+ }
std::string sslCANotFoundError(
"No TLS certificate validation can be performed since"
diff --git a/src/mongo/util/net/ssl_options_server.idl b/src/mongo/util/net/ssl_options_server.idl
index d69af991a11..58b05893a36 100644
--- a/src/mongo/util/net/ssl_options_server.idl
+++ b/src/mongo/util/net/ssl_options_server.idl
@@ -40,13 +40,6 @@ global:
imports:
- "mongo/idl/basic_types.idl"
-server_parameters:
- tlsUseSystemCA:
- description: "Use System CA for certificate verification"
- set_at: startup
- cpp_varname: "sslGlobalParams.sslUseSystemCA"
- default: false
-
configs:
"net.tls.tlsOnNormalPorts":
description: "Use TLS on configured ports"
diff --git a/src/mongo/util/net/ssl_parameters.idl b/src/mongo/util/net/ssl_parameters.idl
index 9b3222159bb..c0cc5ca2c63 100644
--- a/src/mongo/util/net/ssl_parameters.idl
+++ b/src/mongo/util/net/ssl_parameters.idl
@@ -87,7 +87,7 @@ server_parameters:
when fetching OCSP Responses for peer certificate
set_at: startup
cpp_vartype: int
- default: 4
+ default: 5
cpp_varname: "gTLSOCSPVerifyTimeoutSecs"
validator:
gte: 1
diff --git a/src/mongo/util/net/ssl_types.h b/src/mongo/util/net/ssl_types.h
index e129b549056..6f859ee01aa 100644
--- a/src/mongo/util/net/ssl_types.h
+++ b/src/mongo/util/net/ssl_types.h
@@ -122,6 +122,7 @@ public:
SSLX509Name clientSubjectName;
Date_t serverCertificateExpirationDate;
+ bool hasCA = false;
private:
SSLX509Name _serverSubjectName;