diff options
author | Spencer Jackson <spencer.jackson@mongodb.com> | 2015-04-13 17:36:00 -0400 |
---|---|---|
committer | Spencer Jackson <spencer.jackson@mongodb.com> | 2015-04-21 17:05:12 -0400 |
commit | 2366756e21aa4ef2d8c05502a5fe934f779ae2ff (patch) | |
tree | a27ca469a4896b3cf957a362f6eacf868ae56c48 | |
parent | 4c1abad5a285071e55f1a88f619b13a290b3e794 (diff) | |
download | mongo-2366756e21aa4ef2d8c05502a5fe934f779ae2ff.tar.gz |
SERVER-17591: Allow TLS protocols to be disabled
-rw-r--r-- | src/mongo/util/net/ssl_manager.cpp | 33 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_options.cpp | 31 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_options.h | 8 |
3 files changed, 71 insertions, 1 deletions
diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp index af8bf305d91..30c76950b31 100644 --- a/src/mongo/util/net/ssl_manager.cpp +++ b/src/mongo/util/net/ssl_manager.cpp @@ -68,6 +68,18 @@ namespace mongo { return ""; } #else + +// Old copies of OpenSSL will not have constants to disable protocols they don't support. +// Define them to values we can OR together safely to generically disable these protocols across +// all versions of OpenSSL. +#ifndef SSL_OP_NO_TLSv1_1 +#define SSL_OP_NO_TLSv1_1 0 +#endif +#ifndef SSL_OP_NO_TLSv1_2 +#define SSL_OP_NO_TLSv1_2 0 +#endif + + const std::string getSSLVersion(const std::string &prefix, const std::string &suffix) { return prefix + SSLeay_version(SSLEAY_VERSION) + suffix; } @@ -158,6 +170,7 @@ namespace mongo { const std::string& pempwd, const std::string& clusterfile, const std::string& clusterpwd, + const std::vector<SSLGlobalParams::Protocols>& disabledProtocols, const std::string& cafile = "", const std::string& crlfile = "", const std::string& cipherConfig = "", @@ -172,6 +185,7 @@ namespace mongo { cafile(cafile), crlfile(crlfile), cipherConfig(cipherConfig), + disabledProtocols(disabledProtocols), weakCertificateValidation(weakCertificateValidation), allowInvalidCertificates(allowInvalidCertificates), allowInvalidHostnames(allowInvalidHostnames), @@ -184,6 +198,7 @@ namespace mongo { std::string cafile; std::string crlfile; std::string cipherConfig; + std::vector<SSLGlobalParams::Protocols> disabledProtocols; bool weakCertificateValidation; bool allowInvalidCertificates; bool allowInvalidHostnames; @@ -329,6 +344,7 @@ namespace mongo { sslGlobalParams.sslPEMKeyPassword, sslGlobalParams.sslClusterFile, sslGlobalParams.sslClusterPassword, + sslGlobalParams.sslDisabledProtocols, sslGlobalParams.sslCAFile, sslGlobalParams.sslCRLFile, sslGlobalParams.sslCipherConfig, @@ -587,7 +603,22 @@ namespace mongo { // SSL_OP_ALL - Activate all bug workaround options, to support buggy client SSL's. // SSL_OP_NO_SSLv2 - Disable SSL v2 support // SSL_OP_NO_SSLv3 - Disable SSL v3 support - SSL_CTX_set_options(*context, SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3); + long supportedProtocols = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3; + + // Set the supported TLS protocols. Allow --disabledProtocols to disable selected ciphers. + if (!params.disabledProtocols.empty()) { + for (std::vector<SSLGlobalParams::Protocols>::const_iterator it = + params.disabledProtocols.begin(); it != params.disabledProtocols.end(); ++it) { + if (*it == SSLGlobalParams::TLS1_0) { + supportedProtocols |= SSL_OP_NO_TLSv1; + } else if (*it == SSLGlobalParams::TLS1_1) { + supportedProtocols |= SSL_OP_NO_TLSv1_1; + } else if (*it == SSLGlobalParams::TLS1_2) { + supportedProtocols |= SSL_OP_NO_TLSv1_2; + } + } + } + SSL_CTX_set_options(*context, supportedProtocols); // HIGH - Enable strong ciphers // !EXPORT - Disable export ciphers (40/56 bit) diff --git a/src/mongo/util/net/ssl_options.cpp b/src/mongo/util/net/ssl_options.cpp index c4ff4f2c48c..8bb00c90570 100644 --- a/src/mongo/util/net/ssl_options.cpp +++ b/src/mongo/util/net/ssl_options.cpp @@ -36,6 +36,7 @@ #include "mongo/base/status.h" #include "mongo/db/server_options.h" #include "mongo/util/log.h" +#include "mongo/util/text.h" #include "mongo/util/options_parser/startup_options.h" namespace mongo { @@ -75,6 +76,10 @@ namespace mongo { "OpenSSL cipher configuration string") .hidden(); + options->addOptionChaining("net.ssl.disabledProtocols", "sslDisabledProtocols", moe::String, + "Comma separated list of disabled protocols") + .hidden(); + options->addOptionChaining("net.ssl.weakCertificateValidation", "sslWeakCertificateValidation", moe::Switch, "allow client to connect without " "presenting a certificate"); @@ -116,6 +121,11 @@ namespace mongo { .requires("ssl") .requires("ssl.CAFile"); + options->addOptionChaining("net.ssl.disabledProtocols", "sslDisabledProtocols", moe::String, + "Comma separated list of disabled protocols") + .requires("ssl") + .hidden(); + options->addOptionChaining("net.ssl.allowInvalidHostnames", "sslAllowInvalidHostnames", moe::Switch, "allow connections to servers with non-matching hostnames") .requires("ssl"); @@ -237,6 +247,26 @@ namespace mongo { sslGlobalParams.sslCipherConfig = params["net.ssl.sslCipherConfig"].as<string>(); } + if (params.count("net.ssl.disabledProtocols")) { + std::vector<std::string> tokens = StringSplitter::split( + params["net.ssl.disabledProtocols"].as<string>(), ","); + + std::map<std::string, SSLGlobalParams::Protocols> validConfigs; + validConfigs["noTLS1_0"] = SSLGlobalParams::TLS1_0; + validConfigs["noTLS1_1"] = SSLGlobalParams::TLS1_1; + validConfigs["noTLS1_2"] = SSLGlobalParams::TLS1_2; + for (std::vector<std::string>::iterator it = tokens.begin(); it != tokens.end(); ++it) { + std::map<std::string, SSLGlobalParams::Protocols>::iterator mappedToken = + validConfigs.find(*it); + if (mappedToken != validConfigs.end()) { + sslGlobalParams.sslDisabledProtocols.push_back(mappedToken->second); + } else { + return Status(ErrorCodes::BadValue, + "Unrecognized disabledProtocols '" + *it +"'"); + } + } + } + if (params.count("net.ssl.weakCertificateValidation")) { sslGlobalParams.sslWeakCertificateValidation = params["net.ssl.weakCertificateValidation"].as<bool>(); @@ -290,6 +320,7 @@ namespace mongo { sslGlobalParams.sslCAFile.size() || sslGlobalParams.sslCRLFile.size() || sslGlobalParams.sslCipherConfig.size() || + sslGlobalParams.sslDisabledProtocols.size() || sslGlobalParams.sslWeakCertificateValidation || sslGlobalParams.sslFIPSMode) { return Status(ErrorCodes::BadValue, diff --git a/src/mongo/util/net/ssl_options.h b/src/mongo/util/net/ssl_options.h index bc4f2dbbad4..09035b16c67 100644 --- a/src/mongo/util/net/ssl_options.h +++ b/src/mongo/util/net/ssl_options.h @@ -27,6 +27,8 @@ #pragma once +#include <vector> + #include "mongo/base/status.h" #include "mongo/client/export_macros.h" #include "mongo/util/net/ssl_manager.h" @@ -41,6 +43,11 @@ namespace mongo { namespace moe = mongo::optionenvironment; struct MONGO_CLIENT_API SSLGlobalParams { + enum Protocols { + TLS1_0, + TLS1_1, + TLS1_2 + }; AtomicInt32 sslMode; // --sslMode - the SSL operation mode, see enum SSLModes bool sslOnNormalPorts; // --sslOnNormalPorts (deprecated) std::string sslPEMKeyFile; // --sslPEMKeyFile @@ -50,6 +57,7 @@ namespace mongo { std::string sslCAFile; // --sslCAFile std::string sslCRLFile; // --sslCRLFile std::string sslCipherConfig; // --sslCipherConfig + std::vector<Protocols> sslDisabledProtocols; // --sslDisabledProtocols bool sslWeakCertificateValidation; // --sslWeakCertificateValidation bool sslFIPSMode; // --sslFIPSMode bool sslAllowInvalidCertificates; // --sslAllowInvalidCertificates |