diff options
-rwxr-xr-x | buildscripts/smoke.py | 4 | ||||
-rw-r--r-- | jstests/ssl/initial_sync1_x509.js | 5 | ||||
-rw-r--r-- | jstests/ssl/replset1.js | 4 | ||||
-rw-r--r-- | jstests/ssl/sharding_with_x509.js | 2 | ||||
-rw-r--r-- | jstests/ssl/ssl_cert_password.js | 2 | ||||
-rw-r--r-- | jstests/ssl/ssl_crl.js | 6 | ||||
-rw-r--r-- | jstests/ssl/ssl_crl_revoked.js | 3 | ||||
-rw-r--r-- | jstests/ssl/ssl_weak.js | 6 | ||||
-rw-r--r-- | src/mongo/client/dbclient.cpp | 4 | ||||
-rw-r--r-- | src/mongo/client/examples/httpClientTest.cpp | 2 | ||||
-rwxr-xr-x | src/mongo/shell/servers.js | 6 | ||||
-rw-r--r-- | src/mongo/shell/servers_misc.js | 3 | ||||
-rw-r--r-- | src/mongo/tools/tool_options.cpp | 3 | ||||
-rw-r--r-- | src/mongo/util/net/message_port.cpp | 34 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager.cpp | 3 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_options.cpp | 48 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_options.h | 29 |
17 files changed, 119 insertions, 45 deletions
diff --git a/buildscripts/smoke.py b/buildscripts/smoke.py index 4c15119ebe8..d09f1cbde13 100755 --- a/buildscripts/smoke.py +++ b/buildscripts/smoke.py @@ -167,7 +167,7 @@ class mongod(object): def setup_admin_user(self, port=mongod_port): try: - Connection( "localhost" , int(port) ).admin.command("createUser", "admin", + Connection( "localhost" , int(port), ssl=use_ssl ).admin.command("createUser", "admin", pwd="password", roles=["__system"]) except OperationFailure, e: @@ -222,7 +222,7 @@ class mongod(object): argv += ['--setParameter', 'authenticationMechanisms=' + authMechanism] self.auth = True if self.kwargs.get('use_ssl') or self.kwargs.get('use_x509'): - argv += ['--sslOnNormalPorts', + argv += ['--sslMode', "sslOnly", '--sslPEMKeyFile', 'jstests/libs/server.pem', '--sslCAFile', 'jstests/libs/ca.pem', '--sslWeakCertificateValidation'] diff --git a/jstests/ssl/initial_sync1_x509.js b/jstests/ssl/initial_sync1_x509.js index 7206e98402c..e3a519346c2 100644 --- a/jstests/ssl/initial_sync1_x509.js +++ b/jstests/ssl/initial_sync1_x509.js @@ -2,10 +2,7 @@ // This test is launching replsets/initial_sync1.js with different // values for clusterAuthMode to emulate an upgrade process. -var common_options = {sslOnNormalPorts : "", - sslPEMKeyFile : "jstests/libs/server.pem", - sslCAFile: "jstests/libs/ca.pem", - keyFile : "jstests/libs/key1"}; +var common_options = {keyFile : "jstests/libs/key1"}; // Standard case, clusterAuthMode: x509 x509_options1 = Object.merge(common_options, diff --git a/jstests/ssl/replset1.js b/jstests/ssl/replset1.js index 6a1d2cba248..8462cc9fa2b 100644 --- a/jstests/ssl/replset1.js +++ b/jstests/ssl/replset1.js @@ -1,5 +1,5 @@ -ssl_options = {sslOnNormalPorts : "", +ssl_options = {sslMode : "sslOnly", sslPEMKeyFile : "jstests/libs/server.pem", sslCAFile: "jstests/libs/ca.pem"}; -load("jstests/replsets/replset1.js");
\ No newline at end of file +load("jstests/replsets/replset1.js"); diff --git a/jstests/ssl/sharding_with_x509.js b/jstests/ssl/sharding_with_x509.js index 6daf9e23675..37741513dbf 100644 --- a/jstests/ssl/sharding_with_x509.js +++ b/jstests/ssl/sharding_with_x509.js @@ -1,7 +1,7 @@ // Tests basic sharding with x509 cluster auth // The purpose is to verify the connectivity between mongos and the shards -var x509_options = {sslOnNormalPorts : "", +var x509_options = {sslMode : "sslOnly", sslPEMKeyFile : "jstests/libs/server.pem", sslCAFile: "jstests/libs/ca.pem", sslClusterFile: "jstests/libs/cluster-cert.pem", diff --git a/jstests/ssl/ssl_cert_password.js b/jstests/ssl/ssl_cert_password.js index d7734148aa8..1daccce7f74 100644 --- a/jstests/ssl/ssl_cert_password.js +++ b/jstests/ssl/ssl_cert_password.js @@ -11,7 +11,7 @@ resetDbpath(dbpath); md = startMongod("--nopreallocj", "--port", port, "--dbpath", dbpath, - "--sslOnNormalPorts", + "--sslMode","sslOnly", "--sslPEMKeyFile", "jstests/libs/password_protected.pem", "--sslPEMKeyPassword", "qwerty"); // startMongod connects a Mongo shell, so if we get here, the test is successful. diff --git a/jstests/ssl/ssl_crl.js b/jstests/ssl/ssl_crl.js index d2a96e31328..a536aba818f 100644 --- a/jstests/ssl/ssl_crl.js +++ b/jstests/ssl/ssl_crl.js @@ -11,7 +11,8 @@ var baseName = "jstests_ssl_ssl_crl"; var md = startMongod("--port", port1, "--dbpath", - "/data/db/" + baseName + "1", "--sslOnNormalPorts", + "/data/db/" + baseName + "1", + "--sslMode", "sslOnly", "--sslPEMKeyFile", "jstests/libs/server.pem", "--sslCAFile", "jstests/libs/ca.pem", "--sslCRLFile", "jstests/libs/crl.pem"); @@ -26,7 +27,8 @@ assert(mongo==0); port2 = ports[1]; // This test ensures clients cannot connect if the CRL is expired. -md = startMongod("--port", port2, "--dbpath", "/data/db/" + baseName + "2", "--sslOnNormalPorts", +md = startMongod("--port", port2, "--dbpath", "/data/db/" + baseName + "2", + "--sslMode", "sslOnly", "--sslPEMKeyFile", "jstests/libs/server.pem", "--sslCAFile", "jstests/libs/ca.pem", "--sslCRLFile", "jstests/libs/crl_expired.pem"); diff --git a/jstests/ssl/ssl_crl_revoked.js b/jstests/ssl/ssl_crl_revoked.js index 61c9e30dbe7..5c8c448c5a2 100644 --- a/jstests/ssl/ssl_crl_revoked.js +++ b/jstests/ssl/ssl_crl_revoked.js @@ -6,7 +6,8 @@ port = allocatePorts( 1 )[ 0 ]; var baseName = "jstests_ssl_ssl_crl_revoked"; -var md = startMongod( "--port", port, "--dbpath", "/data/db/" + baseName, "--sslOnNormalPorts", +var md = startMongod( "--port", port, "--dbpath", "/data/db/" + baseName, + "--sslMode","sslOnly", "--sslPEMKeyFile", "jstests/libs/server.pem", "--sslCAFile", "jstests/libs/ca.pem", "--sslCRLFile", "jstests/libs/crl_client_revoked.pem"); diff --git a/jstests/ssl/ssl_weak.js b/jstests/ssl/ssl_weak.js index 74dfb4e1031..26fb762958c 100644 --- a/jstests/ssl/ssl_weak.js +++ b/jstests/ssl/ssl_weak.js @@ -8,7 +8,8 @@ var baseName = "jstests_ssl_ssl_weak"; // Test that connecting with no client certificate and --sslWeakCertificateValidation connects // successfully. -var md = startMongod( "--port", ports[0], "--dbpath", "/data/db/" + baseName + "1", "--sslOnNormalPorts", +var md = startMongod( "--port", ports[0], "--dbpath", "/data/db/" + baseName + "1", + "--sslMode", "sslOnly", "--sslPEMKeyFile", "jstests/libs/server.pem", "--sslCAFile", "jstests/libs/ca.pem", "--sslWeakCertificateValidation"); @@ -31,7 +32,8 @@ assert(mongo==0); // Test that connecting with no client certificate and no --sslWeakCertificateValidation fails to // connect. -var md2 = startMongod( "--port", ports[1], "--dbpath", "/data/db/" + baseName + "2", "--sslOnNormalPorts", +var md2 = startMongod( "--port", ports[1], "--dbpath", "/data/db/" + baseName + "2", + "--sslMode", "sslOnly", "--sslPEMKeyFile", "jstests/libs/server.pem", "--sslCAFile", "jstests/libs/ca.pem"); diff --git a/src/mongo/client/dbclient.cpp b/src/mongo/client/dbclient.cpp index 18f1916bbed..b54f5aa9982 100644 --- a/src/mongo/client/dbclient.cpp +++ b/src/mongo/client/dbclient.cpp @@ -892,7 +892,9 @@ namespace mongo { } #ifdef MONGO_SSL - if (sslGlobalParams.sslOnNormalPorts) { + int sslModeVal = sslGlobalParams.sslMode.load(); + if (sslModeVal == SSLGlobalParams::SSLMode_sendAcceptSSL || + sslModeVal == SSLGlobalParams::SSLMode_sslOnly) { return p->secure( sslManager() ); } #endif diff --git a/src/mongo/client/examples/httpClientTest.cpp b/src/mongo/client/examples/httpClientTest.cpp index 554f84d7a20..fa6096438bb 100644 --- a/src/mongo/client/examples/httpClientTest.cpp +++ b/src/mongo/client/examples/httpClientTest.cpp @@ -47,7 +47,7 @@ void play( string url ) { int main( int argc, const char **argv, char **envp) { #ifdef MONGO_SSL - sslGlobalParams.sslOnNormalPorts = true; + sslGlobalParams.sslMode.store(SSLGlobalParams::SSLMode_sslOnly); runGlobalInitializersOrDie(argc, argv, envp); #endif diff --git a/src/mongo/shell/servers.js b/src/mongo/shell/servers.js index a8948dc1b26..8fc82448a41 100755 --- a/src/mongo/shell/servers.js +++ b/src/mongo/shell/servers.js @@ -414,7 +414,7 @@ MongoRunner.mongoOptions = function( opts ){ if (waitForConnect == undefined || waitForConnect == null) opts.waitForConnect = true; if( jsTestOptions().useSSL ) { - opts.sslOnNormalPorts = ""; + opts.sslMode = "sslOnly"; opts.sslPEMKeyFile = "jstests/libs/server.pem"; opts.sslCAFile = "jstests/libs/ca.pem"; opts.sslWeakCertificateValidation = ""; @@ -478,7 +478,7 @@ MongoRunner.mongodOptions = function( opts ){ } if( jsTestOptions().useSSL ) { - opts.sslOnNormalPorts = ""; + opts.sslMode = "sslOnly"; opts.sslPEMKeyFile = "jstests/libs/server.pem"; opts.sslCAFile = "jstests/libs/ca.pem"; opts.sslWeakCertificateValidation = ""; @@ -712,7 +712,7 @@ startMongodTest = function (port, dirname, restart, extraOptions ) { if( jsTestOptions().keyFile && (!extraOptions || !extraOptions['keyFile']) ) options['keyFile'] = jsTestOptions().keyFile if( jsTestOptions().useSSL ) { - options["sslOnNormalPorts"] = ""; + options["sslMode"] = "sslOnly"; options["sslPEMKeyFile"] = "jstests/libs/server.pem"; options["sslCAFile"] = "jstests/libs/ca.pem"; options["sslWeakCertificateValidation"] = ""; diff --git a/src/mongo/shell/servers_misc.js b/src/mongo/shell/servers_misc.js index cb4e953fd2c..d661228c766 100644 --- a/src/mongo/shell/servers_misc.js +++ b/src/mongo/shell/servers_misc.js @@ -164,7 +164,8 @@ ReplTest.prototype.getOptions = function( master , extra , putBinaryFirst, norep } if( jsTestOptions().useSSL ) { - a.push( "--sslOnNormalPorts" ) + a.push( "--sslMode" ) + a.push( "sslOnly" ) a.push( "--sslPEMKeyFile" ) a.push( "jstests/libs/server.pem" ) a.push( "--sslCAFile" ) diff --git a/src/mongo/tools/tool_options.cpp b/src/mongo/tools/tool_options.cpp index e0f30ccb0b9..4b6fb5dc3ee 100644 --- a/src/mongo/tools/tool_options.cpp +++ b/src/mongo/tools/tool_options.cpp @@ -24,6 +24,7 @@ #include "mongo/db/storage_options.h" #include "mongo/util/log.h" #include "mongo/util/net/sock.h" +#include "mongo/util/net/ssl_manager.h" #include "mongo/util/net/ssl_options.h" #include "mongo/util/options_parser/environment.h" #include "mongo/util/options_parser/option_description.h" @@ -280,7 +281,7 @@ namespace mongo { #ifdef MONGO_SSL if (toolsParsedOptions.count("ssl")) { - sslGlobalParams.sslOnNormalPorts = true; + sslGlobalParams.sslMode.store(SSLGlobalParams::SSLMode_sslOnly); } #endif diff --git a/src/mongo/util/net/message_port.cpp b/src/mongo/util/net/message_port.cpp index 772eeff77e9..b0b920116be 100644 --- a/src/mongo/util/net/message_port.cpp +++ b/src/mongo/util/net/message_port.cpp @@ -27,6 +27,7 @@ #include "mongo/util/net/listen.h" #include "mongo/util/net/message.h" #include "mongo/util/net/ssl_manager.h" +#include "mongo/util/net/ssl_options.h" #include "mongo/util/scopeguard.h" #include "mongo/util/time_support.h" @@ -162,7 +163,7 @@ again: int headerLen = sizeof(MSGHEADER); psock->recv( (char *)&header, headerLen ); int len = header.messageLength; - + if ( len == 542393671 ) { // an http GET string msg = "It looks like you are trying to access MongoDB over HTTP on the native driver port.\n"; @@ -181,17 +182,24 @@ again: goto again; } // If responseTo is not 0 or -1 for first packet assume SSL - else if (psock->isAwaitingHandshake() && - header.responseTo != 0 && header.responseTo != -1) { -#ifdef MONGO_SSL - uassert(17132, "SSL handshake received but server is started without SSL support", - NULL != getSSLManager()); - psock->setHandshakeReceived(); - setX509SubjectName(psock->doSSLHandshake( - reinterpret_cast<const char*>(&header), sizeof(header))); - goto again; -#else - uasserted(17133, "SSL handshake requested, SSL feature not available in this build"); + else if (psock->isAwaitingHandshake()) { +#ifndef MONGO_SSL + if (header.responseTo != 0 && header.responseTo != -1) { + uasserted(17133, + "SSL handshake requested, SSL feature not available in this build"); + } +#else + if (header.responseTo != 0 && header.responseTo != -1) { + uassert(17132, + "SSL handshake received but server is started without SSL support", + sslGlobalParams.sslMode.load() != SSLGlobalParams::SSLMode_noSSL); + setX509SubjectName(psock->doSSLHandshake( + reinterpret_cast<const char*>(&header), sizeof(header))); + psock->setHandshakeReceived(); + goto again; + } + uassert(17185, "The server is configured to only allow SSL connections", + sslGlobalParams.sslMode.load() != SSLGlobalParams::SSLMode_sslOnly); #endif // MONGO_SSL } else if ( len < static_cast<int>(sizeof(MSGHEADER)) || len > MaxMessageSizeBytes ) { @@ -199,7 +207,7 @@ again: << "Min " << sizeof(MSGHEADER) << " Max: " << MaxMessageSizeBytes << endl; return false; } - + psock->setHandshakeReceived(); int z = (len+1023)&0xfffffc00; verify(z>=len); diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp index 0fb645e988c..3457465a9b9 100644 --- a/src/mongo/util/net/ssl_manager.cpp +++ b/src/mongo/util/net/ssl_manager.cpp @@ -35,7 +35,6 @@ #endif namespace mongo { - SSLGlobalParams sslGlobalParams; #ifndef MONGO_SSL @@ -274,7 +273,7 @@ namespace mongo { MONGO_INITIALIZER(SSLManager)(InitializerContext* context) { SimpleMutex::scoped_lock lck(sslManagerMtx); - if (sslGlobalParams.sslOnNormalPorts) { + if (sslGlobalParams.sslMode.load() != SSLGlobalParams::SSLMode_noSSL) { const Params params( sslGlobalParams.sslPEMKeyFile, sslGlobalParams.sslPEMKeyPassword, diff --git a/src/mongo/util/net/ssl_options.cpp b/src/mongo/util/net/ssl_options.cpp index 3251b7fd3d5..935b3ee9bdd 100644 --- a/src/mongo/util/net/ssl_options.cpp +++ b/src/mongo/util/net/ssl_options.cpp @@ -34,6 +34,11 @@ namespace mongo { if (!ret.isOK()) { return ret; } + ret = options->addOption(OD("ssl.mode", "sslMode", moe::String, + "set the SSL operation mode (noSSL|acceptSSL|sendAcceptSSL|sslOnly)", true)); + if (!ret.isOK()) { + return ret; + } ret = options->addOption(OD("ssl.PEMKeyFile", "sslPEMKeyFile", moe::String, "PEM file for ssl", true)); if (!ret.isOK()) { @@ -116,6 +121,26 @@ namespace mongo { Status storeSSLServerOptions(const moe::Environment& params) { + if (params.count("ssl.mode")) { + std::string sslModeParam = params["ssl.mode"].as<string>(); + if (sslModeParam == "noSSL") { + sslGlobalParams.sslMode.store(SSLGlobalParams::SSLMode_noSSL); + } + else if (sslModeParam == "acceptSSL") { + sslGlobalParams.sslMode.store(SSLGlobalParams::SSLMode_acceptSSL); + } + else if (sslModeParam == "sendAcceptSSL") { + sslGlobalParams.sslMode.store(SSLGlobalParams::SSLMode_sendAcceptSSL); + } + else if (sslModeParam == "sslOnly") { + sslGlobalParams.sslMode.store(SSLGlobalParams::SSLMode_sslOnly); + } + else { + return Status(ErrorCodes::BadValue, + "unsupported value for sslMode " + sslModeParam ); + } + } + if (params.count("ssl.PEMKeyFile")) { sslGlobalParams.sslPEMKeyFile = boost::filesystem::absolute( params["ssl.PEMKeyFile"].as<string>()).generic_string(); @@ -148,10 +173,19 @@ namespace mongo { sslGlobalParams.sslWeakCertificateValidation = true; } if (params.count("ssl.sslOnNormalPorts")) { - sslGlobalParams.sslOnNormalPorts = true; + if (params.count("ssl.mode")) { + return Status(ErrorCodes::BadValue, + "can't have both sslMode and sslOnNormalPorts"); + } + else { + sslGlobalParams.sslMode.store(SSLGlobalParams::SSLMode_sslOnly); + } + } + + if (sslGlobalParams.sslMode.load() != SSLGlobalParams::SSLMode_noSSL) { if (sslGlobalParams.sslPEMKeyFile.size() == 0) { return Status(ErrorCodes::BadValue, - "need sslPEMKeyFile with sslOnNormalPorts"); + "need sslPEMKeyFile when SSL is enabled"); } if (sslGlobalParams.sslWeakCertificateValidation && sslGlobalParams.sslCAFile.empty()) { @@ -174,13 +208,15 @@ namespace mongo { sslGlobalParams.sslCRLFile.size() || sslGlobalParams.sslWeakCertificateValidation || sslGlobalParams.sslFIPSMode) { - return Status(ErrorCodes::BadValue, "need to enable sslOnNormalPorts"); + return Status(ErrorCodes::BadValue, + "need to enable SSL via the sslMode flag when" + "using SSL configuration parameters"); } if (serverGlobalParams.clusterAuthMode == "sendKeyfile" || serverGlobalParams.clusterAuthMode == "sendX509" || serverGlobalParams.clusterAuthMode == "x509") { - if (!sslGlobalParams.sslOnNormalPorts){ - return Status(ErrorCodes::BadValue, "need to enable sslOnNormalPorts"); + if (sslGlobalParams.sslMode.load() == SSLGlobalParams::SSLMode_noSSL){ + return Status(ErrorCodes::BadValue, "need to enable SSL via the sslMode flag"); } } else if (params.count("clusterAuthMode") && @@ -195,7 +231,7 @@ namespace mongo { Status storeSSLClientOptions(const moe::Environment& params) { if (params.count("ssl")) { - sslGlobalParams.sslOnNormalPorts = true; + sslGlobalParams.sslMode.store(SSLGlobalParams::SSLMode_sslOnly); } if (params.count("ssl.PEMKeyFile")) { sslGlobalParams.sslPEMKeyFile = params["ssl.PEMKeyFile"].as<std::string>(); diff --git a/src/mongo/util/net/ssl_options.h b/src/mongo/util/net/ssl_options.h index c21e166db81..dce6a9e8444 100644 --- a/src/mongo/util/net/ssl_options.h +++ b/src/mongo/util/net/ssl_options.h @@ -16,6 +16,7 @@ #pragma once #include "mongo/base/status.h" +#include "mongo/util/net/ssl_manager.h" namespace mongo { @@ -29,7 +30,8 @@ namespace mongo { extern moe::Environment sslParsedOptions; struct SSLGlobalParams { - bool sslOnNormalPorts; // --sslOnNormalPorts + AtomicInt32 sslMode; // --sslMode - the SSL operation mode, see enum SSLModes + bool sslOnNormalPorts; // --sslOnNormalPorts (deprecated) std::string sslPEMKeyFile; // --sslPEMKeyFile std::string sslPEMKeyPassword; // --sslPEMKeyPassword std::string sslClusterFile; // --sslInternalKeyFile @@ -40,12 +42,35 @@ namespace mongo { bool sslFIPSMode; // --sslFIPSMode SSLGlobalParams() { - sslOnNormalPorts = false; + sslMode.store(SSLMode_noSSL); } + + enum SSLModes { + /** + * Make unencrypted outgoing connections and do not accept incoming SSL-connections + */ + SSLMode_noSSL, + + /** + * Make unencrypted outgoing connections and accept both unencrypted and SSL-connections + */ + SSLMode_acceptSSL, + + /** + * Make outgoing SSL-connections and accept both unecrypted and SSL-connections + */ + SSLMode_sendAcceptSSL, + + /** + * Make outgoing SSL-connections and only accept incoming SSL-connections + */ + SSLMode_sslOnly + }; }; extern SSLGlobalParams sslGlobalParams; + Status addSSLServerOptions(moe::OptionSection* options); Status addSSLClientOptions(moe::OptionSection* options); |