mongo/jstests/sslSpecial/tls_protocols.js

212 lines
7.0 KiB
JavaScript

// Make sure MongoD starts with TLS 1.0 and 1.1 disabled (except w/ old OpenSSL).
import {
CA_CERT,
CLIENT_CERT,
clientSupportsTLS1_1,
clientSupportsTLS1_2,
clientSupportsTLS1_3,
determineSSLProvider,
SERVER_CERT,
sslProviderSupportsTLS1_0,
} from "jstests/ssl/libs/ssl_helpers.js";
const supportsTLS1_0 = sslProviderSupportsTLS1_0();
const supportsTLS1_1 = clientSupportsTLS1_1();
const supportsTLS1_2 = clientSupportsTLS1_2();
const supportsTLS1_3 = clientSupportsTLS1_3();
// There will be cases where a connect is impossible,
// let the test runner clean those up.
TestData.ignoreUnterminatedProcesses = true;
function test(serverDisabledProtocols, clientDisabledProtocols, shouldStart, shouldSucceed) {
let buildInfo = getBuildInfo().openssl.compiled;
if (!buildInfo) {
buildInfo = determineSSLProvider() + " native TLS";
}
const configStr =
tojson(serverDisabledProtocols) +
"/" +
tojson(clientDisabledProtocols) +
" at " +
buildInfo +
"; shouldStart: " +
shouldStart +
"; shouldSucceed: " +
shouldSucceed;
let serverOpts = {
tlsMode: "allowTLS",
tlsCertificateKeyFile: SERVER_CERT,
tlsCAFile: CA_CERT,
waitForConnect: true,
};
if (serverDisabledProtocols !== null) {
serverOpts.tlsDisabledProtocols = serverDisabledProtocols;
}
clearRawMongoProgramOutput();
let mongod;
try {
mongod = MongoRunner.runMongod(serverOpts);
} catch (e) {
let mongoOutput = rawMongoProgramOutput(".*");
if (
mongoOutput.match(/All valid TLS modes disabled/) ||
mongoOutput.match(/All supported TLS protocols have been disabled/)
) {
jsTest.log.info("All valid TLS modes disabled, returning");
} else {
assert(!shouldStart, "Failed to start mongod with " + configStr);
}
return;
}
assert(mongod);
assert(shouldStart, "Expected mongod to fail with " + configStr);
const host = "localhost:" + mongod.port;
let connection;
try {
connection = new Mongo(host, undefined /* encryptedDBClientCallback */, {
tls: {
certificateKeyFile: CLIENT_CERT,
CAFile: CA_CERT,
disabledProtocols: clientDisabledProtocols,
allowInvalidCertificates: true,
},
});
assert.commandWorked(connection.adminCommand({connectionStatus: 1}), "Running with " + configStr);
} catch (e) {
assert(!shouldSucceed, "Running with " + configStr);
}
const expectLogMessage_disable_1_0_1_1 = supportsTLS1_2 && serverDisabledProtocols === null;
const expectLogMessage_disable_1_0 =
!expectLogMessage_disable_1_0_1_1 && supportsTLS1_1 && serverDisabledProtocols === null;
assert.eq(
expectLogMessage_disable_1_0,
checkLog.checkContainsOnce(mongod, "Automatically disabling TLS 1.0,"),
"TLS 1.0 was/wasn't automatically disabled with " + configStr,
);
assert.eq(
expectLogMessage_disable_1_0_1_1,
checkLog.checkContainsOnce(mongod, "Automatically disabling TLS 1.0 and TLS 1.1,"),
"TLS 1.0 and TLS 1.1 was/wasn't automatically disabled with " + configStr,
);
MongoRunner.stopMongod(mongod);
}
const TLS_1_0 = 1;
const TLS_1_1 = 2;
const TLS_1_2 = 4;
const TLS_1_3 = 8;
const tlsSupport =
determineSSLProvider() === "openssl"
? (supportsTLS1_0 ? TLS_1_0 : 0) |
(supportsTLS1_1 ? TLS_1_1 : 0) |
(supportsTLS1_2 ? TLS_1_2 : 0) |
(supportsTLS1_3 ? TLS_1_3 : 0)
: TLS_1_0 | TLS_1_1 | TLS_1_2;
const defaultServerDisable = determineSSLProvider() === "openssl" ? TLS_1_0 | TLS_1_1 : 0;
const defaultClientDisable = (supportsTLS1_2 ? TLS_1_1 : 0) | (supportsTLS1_2 || supportsTLS1_1 ? TLS_1_0 : 0);
function shouldStart(serverDisable) {
const serverDisabledProtocols = serverDisable === null ? defaultServerDisable : serverDisable;
if (determineSSLProvider() === "openssl") {
if (
(serverDisabledProtocols & (TLS_1_0 | TLS_1_1 | TLS_1_2 | TLS_1_3)) ===
(TLS_1_0 | TLS_1_1 | TLS_1_2 | TLS_1_3)
) {
return false;
}
}
// All valid TLS modes are disabled for Apple or Windows
if (determineSSLProvider() === "apple" || determineSSLProvider() === "windows") {
if ((serverDisabledProtocols & (TLS_1_0 | TLS_1_1 | TLS_1_2)) === (TLS_1_0 | TLS_1_1 | TLS_1_2)) {
// apple & windows only check for 1.0, 1.1, 1.2 and ignores 1.3
// SERVER-98279: support tls 1.3 for windows & apple
return false;
}
}
// (Apple only) If the available protocols is not a continuous range
if (determineSSLProvider() === "apple") {
// ssl_manager_apple.cpp: 'Can not disable TLS 1.1 while leaving 1.0 and 1.2 enabled'
if ((serverDisabledProtocols & (TLS_1_0 | TLS_1_1 | TLS_1_2)) === TLS_1_1) {
return false;
}
}
return true;
}
function shouldSucceed(serverDisable, clientDisable) {
serverDisable = serverDisable === null ? defaultServerDisable : serverDisable;
clientDisable = clientDisable === null ? defaultClientDisable : clientDisable;
return ~serverDisable & tlsSupport & ~clientDisable;
}
function tlsFlagsToString(tlsFlags) {
if (tlsFlags === null) {
return null;
} else if (tlsFlags === 0) {
return "none";
} else {
let tlsStrings = [];
if (tlsFlags & TLS_1_0) {
tlsStrings.push("TLS1_0");
}
if (tlsFlags & TLS_1_1) {
tlsStrings.push("TLS1_1");
}
if (tlsFlags & TLS_1_2) {
tlsStrings.push("TLS1_2");
}
if (tlsFlags & TLS_1_3) {
tlsStrings.push("TLS1_3");
}
return tlsStrings.join(",");
}
}
const serverScenarios = [
null,
0,
TLS_1_0,
TLS_1_0 | TLS_1_1,
TLS_1_0 | TLS_1_2,
TLS_1_0 | TLS_1_1 | TLS_1_2,
TLS_1_0 | TLS_1_2 | TLS_1_3,
TLS_1_0 | TLS_1_1 | TLS_1_3,
TLS_1_0 | TLS_1_1 | TLS_1_2 | TLS_1_3,
TLS_1_1,
TLS_1_1 | TLS_1_2,
TLS_1_1 | TLS_1_3,
TLS_1_1 | TLS_1_2 | TLS_1_3,
];
const clientScenarios = [null, 0, TLS_1_0, TLS_1_0 | TLS_1_1];
// TODO
// SERVER-98278: bad input for --sslDisabledProtocols are not checked for windows / openssl
if (determineSSLProvider() === "apple") {
test("TLS_INVALID", null, false, null);
}
serverScenarios.forEach((serverDisable) =>
clientScenarios.forEach((clientDisable) => {
// SERVER-98279: support tls 1.3 for windows & apple
// skip any tests disabling TLS 1.3 since it's not supported for those platforms yet
if (determineSSLProvider() === "apple" || determineSSLProvider() === "windows") {
if (serverDisable & TLS_1_3) return;
}
test(
tlsFlagsToString(serverDisable),
tlsFlagsToString(clientDisable),
shouldStart(serverDisable),
shouldSucceed(serverDisable, clientDisable),
);
}),
);