summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/ssl/tls1_0.js91
-rw-r--r--src/mongo/util/net/ssl_manager_windows.cpp4
-rw-r--r--src/mongo/util/net/ssl_options.cpp27
3 files changed, 120 insertions, 2 deletions
diff --git a/jstests/ssl/tls1_0.js b/jstests/ssl/tls1_0.js
new file mode 100644
index 00000000000..e634244af15
--- /dev/null
+++ b/jstests/ssl/tls1_0.js
@@ -0,0 +1,91 @@
+// Make sure MongoD starts with TLS 1.0 disabled (except w/ old OpenSSL).
+
+(function() {
+ 'use strict';
+
+ const supportsTLS1_1 = (function() {
+ const openssl = getBuildInfo().openssl || {};
+ if (openssl.compiled === undefined) {
+ // Native TLS build.
+ return true;
+ }
+ // OpenSSL 0.x.x => TLS 1.0 only.
+ if (/OpenSSL 0\./.test(openssl.compiled)) {
+ return false;
+ }
+ // OpenSSL 1.0.0-1.0.0k => TLS 1.0 only.
+ if (/OpenSSL 1\.0\.0[ a-k]/.test(openssl.compiled)) {
+ return false;
+ }
+
+ // OpenSSL 1.0.0l and later include TLS 1.1 and 1.2
+ return true;
+ })();
+
+ const defaultEnableTLS1_0 = (function() {
+ // If the build doesn't support TLS 1.1, then TLS 1.0 is left enabled.
+ if (!supportsTLS1_1) {
+ return true;
+ }
+ // If we're on Apple, then TLS 1.0 is left enabled regardless
+ // to support other tools on the system which may be TLS 1.0 only.
+ const buildEnv = getBuildInfo().buildEnvironment || {};
+ return (buildEnv.target_os === 'macOS');
+ })();
+
+ function test(disabledProtocols, shouldSucceed) {
+ const expectLogMessage = !defaultEnableTLS1_0 && (disabledProtocols === null);
+ let serverOpts = {
+ sslMode: 'allowSSL',
+ sslPEMKeyFile: 'jstests/libs/server.pem',
+ sslCAFile: 'jstests/libs/ca.pem',
+ waitForConnect: false
+ };
+ if (disabledProtocols !== null) {
+ serverOpts.sslDisabledProtocols = disabledProtocols;
+ }
+ clearRawMongoProgramOutput();
+ const mongod = MongoRunner.runMongod(serverOpts);
+ assert(mongod);
+
+ const didSucceed = (function() {
+ try {
+ assert.soon(function() {
+ return 0 == runMongoProgram('mongo',
+ '--ssl',
+ '--port',
+ mongod.port,
+ '--sslPEMKeyFile',
+ 'jstests/libs/client.pem',
+ '--sslCAFile',
+ 'jstests/libs/ca.pem',
+ '--eval',
+ ';');
+ }, "Connecting to mongod", 30 * 1000);
+ return true;
+ } catch (e) {
+ return false;
+ }
+ })();
+
+ // Exit code based success/failure.
+ assert.eq(didSucceed,
+ shouldSucceed,
+ "Running with disabledProtocols == " + tojson(disabledProtocols));
+
+ assert.eq(expectLogMessage,
+ rawMongoProgramOutput().search('Automatically disabling TLS 1.0') >= 0,
+ "TLS 1.0 was/wasn't automatically disabled");
+
+ const exitCode =
+ (didSucceed || !_isWindows()) ? MongoRunner.EXIT_CLEAN : MongoRunner.EXIT_SIGKILL;
+ MongoRunner.stopMongod(mongod, undefined, {allowedExitCode: exitCode});
+ }
+
+ test(null, true);
+ test('none', true);
+ test('TLS1_0', supportsTLS1_1);
+ test('TLS1_1,TLS1_2', true);
+ test('TLS1_0,TLS1_1', supportsTLS1_1);
+ test('TLS1_0,TLS1_1,TLS1_2', false);
+})();
diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp
index 3e91df52fe9..51e85111828 100644
--- a/src/mongo/util/net/ssl_manager_windows.cpp
+++ b/src/mongo/util/net/ssl_manager_windows.cpp
@@ -1267,6 +1267,10 @@ Status SSLManagerWindows::initSSLContext(SCHANNEL_CRED* cred,
}
cred->grbitEnabledProtocols = supportedProtocols;
+ if (supportedProtocols == 0) {
+ return {ErrorCodes::InvalidSSLConfiguration,
+ "All supported TLS protocols have been disabled."};
+ }
if (!params.sslCipherConfig.empty()) {
warning()
diff --git a/src/mongo/util/net/ssl_options.cpp b/src/mongo/util/net/ssl_options.cpp
index e6c0a8d21c9..ffca18fcc17 100644
--- a/src/mongo/util/net/ssl_options.cpp
+++ b/src/mongo/util/net/ssl_options.cpp
@@ -383,6 +383,15 @@ Status storeSSLServerOptions(const moe::Environment& params) {
// Map the tokens to their enum values, and push them onto the list of disabled protocols.
for (const std::string& token : tokens) {
+ if (token == "none") {
+ // Allow overriding the default behavior below of implicitly disabling TLS 1.0.
+ if (tokens.size() != 1) {
+ return {ErrorCodes::BadValue,
+ "'none' may not be specified with other values to disabledProtocols"};
+ }
+ break;
+ }
+
auto mappedToken = validConfigs.find(token);
if (mappedToken != validConfigs.end()) {
sslGlobalParams.sslDisabledProtocols.push_back(mappedToken->second);
@@ -391,6 +400,20 @@ Status storeSSLServerOptions(const moe::Environment& params) {
"Unrecognized disabledProtocols '" + token + "'");
}
}
+
+#if !defined(__APPLE__) && ((MONGO_CONFIG_SSL_PROVIDER != SSL_PROVIDER_OPENSSL) || \
+ (OPENSSL_VERSION_NUMBER >= 0x100000cf)) /* 1.0.0l */
+ } else {
+ /* Disable TLS 1.0 by default on non-Apple platforms
+ * except on mongod/mongos which were built with an
+ * old version of OpenSSL (pre 1.0.0l)
+ * which does not support TLS 1.1 or later.
+ * TL;DR - Pretty much any Linux/Windows build.
+ */
+ log() << "Automatically disabling TLS 1.0, to force-enable TLS 1.0 "
+ "specify --sslDisabledProtocols 'none'";
+ sslGlobalParams.sslDisabledProtocols.push_back(SSLParams::Protocols::TLS1_0);
+#endif
}
if (params.count("net.ssl.weakCertificateValidation")) {
@@ -438,7 +461,7 @@ Status storeSSLServerOptions(const moe::Environment& params) {
bool usingCertifiateSelectors = params.count("net.ssl.certificateSelector");
if (sslGlobalParams.sslPEMKeyFile.size() == 0 && !usingCertifiateSelectors) {
return Status(ErrorCodes::BadValue,
- "need sslPEMKeyFileor certificateSelector when SSL is enabled");
+ "need sslPEMKeyFile or certificateSelector when SSL is enabled");
}
if (!sslGlobalParams.sslCRLFile.empty() && sslGlobalParams.sslCAFile.empty()) {
return Status(ErrorCodes::BadValue, "need sslCAFile with sslCRLFile");
@@ -459,7 +482,7 @@ Status storeSSLServerOptions(const moe::Environment& params) {
sslGlobalParams.sslClusterFile.size() || sslGlobalParams.sslClusterPassword.size() ||
sslGlobalParams.sslCAFile.size() || sslGlobalParams.sslCRLFile.size() ||
sslGlobalParams.sslCipherConfig.size() ||
- sslGlobalParams.sslDisabledProtocols.size() ||
+ params.count("net.ssl.disabledProtocols") ||
#ifdef MONGO_CONFIG_SSL_CERTIFICATE_SELECTORS
params.count("net.ssl.certificateSelector") ||
params.count("net.ssl.clusterCertificateSelector") ||