// 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), ); }), );