summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer Jackson <spencer.jackson@mongodb.com>2018-10-03 23:17:42 -0400
committerSpencer Jackson <spencer.jackson@mongodb.com>2018-10-29 16:53:50 -0400
commitcbb76539c47068f8836ed05283763e687cf126a7 (patch)
tree24a225884afa83d28928c52781e8b69575dfca69
parentc377f378176e34987babf95db8ed70a12ce44b4f (diff)
downloadmongo-cbb76539c47068f8836ed05283763e687cf126a7.tar.gz
SERVER-37135: Track and report TLS 1.3
(cherry picked from commit 670963110d9d226824842d22540a79154fce59a1)
-rw-r--r--jstests/ssl/libs/ssl_helpers.js27
-rw-r--r--jstests/ssl/ssl_count_protocols.js32
-rw-r--r--jstests/ssl/tls1_0.js13
-rw-r--r--src/mongo/util/net/ssl_manager.cpp13
-rw-r--r--src/mongo/util/net/ssl_manager.h3
-rw-r--r--src/mongo/util/net/ssl_manager_apple.cpp3
-rw-r--r--src/mongo/util/net/ssl_manager_openssl.cpp5
-rw-r--r--src/mongo/util/net/ssl_options.cpp3
-rw-r--r--src/mongo/util/net/ssl_options.h4
9 files changed, 94 insertions, 9 deletions
diff --git a/jstests/ssl/libs/ssl_helpers.js b/jstests/ssl/libs/ssl_helpers.js
index 05d0a5b9333..79bd2721819 100644
--- a/jstests/ssl/libs/ssl_helpers.js
+++ b/jstests/ssl/libs/ssl_helpers.js
@@ -207,3 +207,30 @@ function requireSSLProvider(required, fn) {
}
fn();
}
+
+function detectDefaultTLSProtocol() {
+ const conn = MongoRunner.runMongod({
+ sslMode: 'allowSSL',
+ sslPEMKeyFile: SERVER_CERT,
+ sslDisabledProtocols: 'none',
+ useLogFiles: true,
+ tlsLogVersions: "TLS1_0,TLS1_1,TLS1_2,TLS1_3",
+ });
+
+ const res = conn.getDB("admin").serverStatus().transportSecurity;
+
+ MongoRunner.stopMongod(conn);
+
+ // Verify that the default protocol is either TLS1.2 or TLS1.3.
+ // No supported platform should default to an older protocol version.
+ assert.eq(0, res["1.0"]);
+ assert.eq(0, res["1.1"]);
+ assert.eq(0, res["unknown"]);
+ assert.neq(res["1.2"], res["1.3"]);
+
+ if (res["1.2"].tojson() != NumberLong(0).tojson()) {
+ return "TLS1_2";
+ } else {
+ return "TLS1_3";
+ }
+}
diff --git a/jstests/ssl/ssl_count_protocols.js b/jstests/ssl/ssl_count_protocols.js
index ae21894eee0..a9e3202c30f 100644
--- a/jstests/ssl/ssl_count_protocols.js
+++ b/jstests/ssl/ssl_count_protocols.js
@@ -2,23 +2,35 @@
(function() {
'use strict';
+ load("jstests/ssl/libs/ssl_helpers.js");
+
var SERVER_CERT = "jstests/libs/server.pem";
var CLIENT_CERT = "jstests/libs/client.pem";
var CA_CERT = "jstests/libs/ca.pem";
+ const protocols = ["TLS1_0", "TLS1_1", "TLS1_2", "TLS1_3"];
+
+ // First, figure out what protocol our local TLS stack wants to speak.
+ // We're going to observe a connection of this type from the testrunner.
+ const expectedDefaultProtocol = detectDefaultTLSProtocol();
+ print("Expected default protocol: " + expectedDefaultProtocol);
+
function runTestWithoutSubset(client) {
- let disabledProtocols = ["TLS1_0", "TLS1_1", "TLS1_2"];
- let expectedCounts = [0, 0, 1];
+ print("Running test: " + client);
+ let disabledProtocols = protocols.slice();
+ let expectedCounts = [0, 0, 0, 0, 0];
+ expectedCounts[protocols.indexOf(expectedDefaultProtocol)] = 1;
var index = disabledProtocols.indexOf(client);
disabledProtocols.splice(index, 1);
expectedCounts[index] += 1;
+ print(tojson(expectedCounts));
const conn = MongoRunner.runMongod({
sslMode: 'allowSSL',
sslPEMKeyFile: SERVER_CERT,
sslDisabledProtocols: 'none',
useLogFiles: true,
- tlsLogVersions: "TLS1_0,TLS1_1,TLS1_2",
+ tlsLogVersions: "TLS1_0,TLS1_1,TLS1_2,TLS1_3",
});
print(disabledProtocols);
@@ -43,8 +55,21 @@
'a[one] = NumberLong(' + expectedCounts[0] + ');' +
'a["1.1"] = NumberLong(' + expectedCounts[1] + ');' +
'a["1.2"] = NumberLong(' + expectedCounts[2] + ');' +
+ 'a["1.3"] = NumberLong(' + expectedCounts[3] + ');' +
+ 'a["unknown"] = NumberLong(' + expectedCounts[4] + ');' +
'assert.eq(db.serverStatus().transportSecurity, a);');
+ if (expectedDefaultProtocol === "TLS1_2" && client === "TLS1_3") {
+ // If the runtime environment does not support TLS 1.3, a client cannot connect to a
+ // server if TLS 1.3 is its only usable protocol version.
+ assert.neq(
+ 0,
+ exitStatus,
+ "A client which does not support TLS 1.3 should not be able to connect with it");
+ MongoRunner.stopMongod(conn);
+ return;
+ }
+
assert.eq(0, exitStatus, "");
print(`Checking ${conn.fullOptions.logFile} for TLS version message`);
@@ -73,5 +98,6 @@
runTestWithoutSubset("TLS1_0");
runTestWithoutSubset("TLS1_1");
runTestWithoutSubset("TLS1_2");
+ runTestWithoutSubset("TLS1_3");
})();
diff --git a/jstests/ssl/tls1_0.js b/jstests/ssl/tls1_0.js
index dc2b706ae80..5c751d73f0f 100644
--- a/jstests/ssl/tls1_0.js
+++ b/jstests/ssl/tls1_0.js
@@ -3,6 +3,8 @@
(function() {
'use strict';
+ load("jstests/ssl/libs/ssl_helpers.js");
+
// There will be cases where a connect is impossible,
// let the test runner clean those up.
TestData.failIfUnterminatedProcesses = false;
@@ -31,6 +33,8 @@
return !supportsTLS1_1;
})();
+ const supportsTLS1_3 = detectDefaultTLSProtocol() !== "TLS1_2";
+
function test(serverDP, clientDP, shouldSucceed) {
const expectLogMessage = !defaultEnableTLS1_0 && (serverDP === null);
let serverOpts = {
@@ -84,9 +88,11 @@
test(null, null, true);
test('none', null, true);
test('TLS1_0', null, supportsTLS1_1);
- test('TLS1_1,TLS1_2', null, !supportsTLS1_1);
+ test('TLS1_1,TLS1_2', null, !supportsTLS1_1 || supportsTLS1_3);
+ test('TLS1_1,TLS1_2,TLS1_3', null, !supportsTLS1_1);
test('TLS1_0,TLS1_1', null, supportsTLS1_1);
- test('TLS1_0,TLS1_1,TLS1_2', null, false);
+ test('TLS1_0,TLS1_1,TLS1_2', null, supportsTLS1_3);
+ test('TLS1_0,TLS1_1,TLS1_2,TLS1_3', null, false);
// Tests with TLS 1.0 always enabled on client.
test(null, 'none', true);
@@ -99,6 +105,7 @@
test(null, 'TLS1_0', supportsTLS1_1);
test('none', 'TLS1_0', supportsTLS1_1);
test('TLS1_0', 'TLS1_0', supportsTLS1_1);
- test('TLS1_1,TLS1_2', 'TLS1_0', false);
+ test('TLS1_1,TLS1_2', 'TLS1_0', supportsTLS1_3);
+ test('TLS1_1,TLS1_2,TLS1_3', 'TLS1_0', false);
test('TLS1_0,TLS1_1', 'TLS1_0', supportsTLS1_1);
})();
diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp
index e4e189e23bc..2667f13be4b 100644
--- a/src/mongo/util/net/ssl_manager.cpp
+++ b/src/mongo/util/net/ssl_manager.cpp
@@ -723,6 +723,8 @@ public:
builder.append("1.0", counts.tls10.load());
builder.append("1.1", counts.tls11.load());
builder.append("1.2", counts.tls12.load());
+ builder.append("1.3", counts.tls13.load());
+ builder.append("unknown", counts.tlsUnknown.load());
return builder.obj();
}
} tlsVersionStatus;
@@ -755,9 +757,18 @@ void recordTLSVersion(TLSVersion version, const HostAndPort& hostForLogging) {
versionString = "1.2"_sd;
}
break;
+ case TLSVersion::kTLS13:
+ counts.tls13.addAndFetch(1);
+ if (std::find(sslGlobalParams.tlsLogVersions.cbegin(),
+ sslGlobalParams.tlsLogVersions.cend(),
+ SSLParams::Protocols::TLS1_3) != sslGlobalParams.tlsLogVersions.cend()) {
+ versionString = "1.3"_sd;
+ }
+ break;
default:
+ counts.tlsUnknown.addAndFetch(1);
if (!sslGlobalParams.tlsLogVersions.empty()) {
- versionString = "unkown"_sd;
+ versionString = "unknown"_sd;
}
break;
}
diff --git a/src/mongo/util/net/ssl_manager.h b/src/mongo/util/net/ssl_manager.h
index 0a83de2b88b..8c6df1d31ca 100644
--- a/src/mongo/util/net/ssl_manager.h
+++ b/src/mongo/util/net/ssl_manager.h
@@ -123,9 +123,11 @@ const ASN1OID mongodbRolesOID("1.3.6.1.4.1.34601.2.1.1",
* Counts of negogtiated version used by TLS connections.
*/
struct TLSVersionCounts {
+ AtomicInt64 tlsUnknown;
AtomicInt64 tls10;
AtomicInt64 tls11;
AtomicInt64 tls12;
+ AtomicInt64 tls13;
static TLSVersionCounts& get(ServiceContext* serviceContext);
};
@@ -246,6 +248,7 @@ enum class TLSVersion {
kTLS10,
kTLS11,
kTLS12,
+ kTLS13,
};
/**
diff --git a/src/mongo/util/net/ssl_manager_apple.cpp b/src/mongo/util/net/ssl_manager_apple.cpp
index f292c14bd6c..952bbfe9d19 100644
--- a/src/mongo/util/net/ssl_manager_apple.cpp
+++ b/src/mongo/util/net/ssl_manager_apple.cpp
@@ -1164,6 +1164,9 @@ StatusWith<std::pair<::SSLProtocol, ::SSLProtocol>> parseProtocolRange(const SSL
tls11 = false;
} else if (protocol == SSLParams::Protocols::TLS1_2) {
tls12 = false;
+ } else if (protocol == SSLParams::Protocols::TLS1_3) {
+ // By ignoring this value, we are disabling support until we have access to the
+ // modern library.
} else {
return {ErrorCodes::InvalidSSLConfiguration, "Unknown disabled TLS protocol version"};
}
diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp
index 5f08a469b6a..170aeec1641 100644
--- a/src/mongo/util/net/ssl_manager_openssl.cpp
+++ b/src/mongo/util/net/ssl_manager_openssl.cpp
@@ -149,6 +149,9 @@ UniqueBIO makeUniqueMemBio(std::vector<std::uint8_t>& v) {
#ifndef SSL_OP_NO_TLSv1_2
#define SSL_OP_NO_TLSv1_2 0
#endif
+#ifndef SSL_OP_NO_TLSv1_3
+#define SSL_OP_NO_TLSv1_3 0
+#endif
// clang-format off
#ifndef MONGO_CONFIG_HAVE_ASN1_ANY_DEFINITIONS
@@ -720,6 +723,8 @@ Status SSLManagerOpenSSL::initSSLContext(SSL_CTX* context,
supportedProtocols |= SSL_OP_NO_TLSv1_1;
} else if (protocol == SSLParams::Protocols::TLS1_2) {
supportedProtocols |= SSL_OP_NO_TLSv1_2;
+ } else if (protocol == SSLParams::Protocols::TLS1_3) {
+ supportedProtocols |= SSL_OP_NO_TLSv1_3;
}
}
::SSL_CTX_set_options(context, supportedProtocols);
diff --git a/src/mongo/util/net/ssl_options.cpp b/src/mongo/util/net/ssl_options.cpp
index aebab2d48a9..240eeb137dc 100644
--- a/src/mongo/util/net/ssl_options.cpp
+++ b/src/mongo/util/net/ssl_options.cpp
@@ -99,6 +99,7 @@ Status storeDisabledProtocols(const std::string& disabledProtocols,
{"TLS1_0", SSLParams::Protocols::TLS1_0},
{"TLS1_1", SSLParams::Protocols::TLS1_1},
{"TLS1_2", SSLParams::Protocols::TLS1_2},
+ {"TLS1_3", SSLParams::Protocols::TLS1_3},
};
// These noTLS* tokens exist for backwards compatibility.
@@ -106,6 +107,7 @@ Status storeDisabledProtocols(const std::string& disabledProtocols,
{"noTLS1_0", SSLParams::Protocols::TLS1_0},
{"noTLS1_1", SSLParams::Protocols::TLS1_1},
{"noTLS1_2", SSLParams::Protocols::TLS1_2},
+ {"noTLS1_3", SSLParams::Protocols::TLS1_3},
};
// Map the tokens to their enum values, and push them onto the list of disabled protocols.
@@ -295,6 +297,7 @@ Status storeTLSLogVersion(const std::string& loggedProtocols) {
{"TLS1_0", SSLParams::Protocols::TLS1_0},
{"TLS1_1", SSLParams::Protocols::TLS1_1},
{"TLS1_2", SSLParams::Protocols::TLS1_2},
+ {"TLS1_3", SSLParams::Protocols::TLS1_3},
};
// Map the tokens to their enum values, and push them onto the list of logged protocols.
diff --git a/src/mongo/util/net/ssl_options.h b/src/mongo/util/net/ssl_options.h
index ec756d94266..63e898b213c 100644
--- a/src/mongo/util/net/ssl_options.h
+++ b/src/mongo/util/net/ssl_options.h
@@ -49,8 +49,8 @@ class Environment;
} // namespace optionenvironment
struct SSLParams {
- enum class Protocols { TLS1_0, TLS1_1, TLS1_2 };
- AtomicInt32 sslMode; // --sslMode - the SSL operation mode, see enum SSLModes
+ enum class Protocols { TLS1_0, TLS1_1, TLS1_2, TLS1_3 };
+ AtomicInt32 sslMode; // --sslMode - the TLS operation mode, see enum SSLModes
std::string sslPEMTempDHParam; // --setParameter OpenSSLDiffieHellmanParameters=file : PEM file
// with DH parameters.
std::string sslPEMKeyFile; // --sslPEMKeyFile