summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Nilsson <andreas.nilsson@10gen.com>2014-10-07 16:59:05 -0400
committerAndreas Nilsson <andreas.nilsson@10gen.com>2014-10-10 09:55:13 -0400
commiteb3435c25eabc90e2c4ff7c331c94c4c222d0b7e (patch)
tree63b73d91f489eacd599035e417cff62998ef8a0e
parentb179fa1eab1bc79be8562349ca6f43283f16ecc7 (diff)
downloadmongo-eb3435c25eabc90e2c4ff7c331c94c4c222d0b7e.tar.gz
SERVER-15236 Using SCRAM-SHA-1 for keyfile authentication
-rwxr-xr-xbuildscripts/smoke.py2
-rw-r--r--buildscripts/smoke_config/auth.yaml4
-rw-r--r--buildscripts/smoke_config/auth_shell.yaml4
-rw-r--r--jstests/auth/copyauth.js4
-rw-r--r--src/mongo/crypto/mechanism_scram.cpp8
-rw-r--r--src/mongo/crypto/mechanism_scram.h6
-rw-r--r--src/mongo/db/auth/sasl_commands.cpp12
-rw-r--r--src/mongo/db/auth/sasl_scramsha1_server_conversation.cpp8
-rw-r--r--src/mongo/db/auth/security_key.cpp65
-rw-r--r--src/mongo/shell/shardingtest.js2
-rw-r--r--src/mongo/shell/utils_auth.js2
11 files changed, 84 insertions, 33 deletions
diff --git a/buildscripts/smoke.py b/buildscripts/smoke.py
index d8884c6e3dc..fa00b907a12 100755
--- a/buildscripts/smoke.py
+++ b/buildscripts/smoke.py
@@ -1242,7 +1242,7 @@ def main():
parser.add_option('--use-x509', dest='use_x509', default=False,
action="store_true",
help='Use x509 auth for internal cluster authentication')
- parser.add_option('--authMechanism', dest='authMechanism', default='MONGODB-CR',
+ parser.add_option('--authMechanism', dest='authMechanism', default='SCRAM-SHA-1',
help='Use the given authentication mechanism, when --auth is used.')
parser.add_option('--keyFile', dest='keyFile', default=None,
help='Path to keyFile to use to run replSet and sharding tests with authentication enabled')
diff --git a/buildscripts/smoke_config/auth.yaml b/buildscripts/smoke_config/auth.yaml
index 102c8721b3f..9f4660fa831 100644
--- a/buildscripts/smoke_config/auth.yaml
+++ b/buildscripts/smoke_config/auth.yaml
@@ -14,14 +14,14 @@ executor:
shell_globals:
TestData:
auth: true
- authMechanism: MONGODB-CR
+ authMechanism: SCRAM-SHA-1
keyFile: ./jstests/lib/authTestsKey
keyFileData: Thiskeyisonlyforrunningthesuitewithauthenticationdontuseitinanytestsdirectly
testers:
js_test:
shell_options:
authenticationDatabase: local
- authenticationMechanism: MONGODB-CR
+ authenticationMechanism: SCRAM-SHA-1
password: Thiskeyisonlyforrunningthesuitewithauthenticationdontuseitinanytestsdirectly
username: __system
diff --git a/buildscripts/smoke_config/auth_shell.yaml b/buildscripts/smoke_config/auth_shell.yaml
index 56388ebb555..b89b776cfd8 100644
--- a/buildscripts/smoke_config/auth_shell.yaml
+++ b/buildscripts/smoke_config/auth_shell.yaml
@@ -8,14 +8,14 @@ executor:
shell_globals:
TestData:
auth: true
- authMechanism: MONGODB-CR
+ authMechanism: SCRAM-SHA-1
keyFile: ./jstests/lib/authTestsKey
keyFileData: Thiskeyisonlyforrunningthesuitewithauthenticationdontuseitinanytestsdirectly
testers:
js_test:
shell_options:
authenticationDatabase: local
- authenticationMechanism: MONGODB-CR
+ authenticationMechanism: SCRAM-SHA-1
password: Thiskeyisonlyforrunningthesuitewithauthenticationdontuseitinanytestsdirectly
username: __system
diff --git a/jstests/auth/copyauth.js b/jstests/auth/copyauth.js
index 1148b31104e..bf1742ea598 100644
--- a/jstests/auth/copyauth.js
+++ b/jstests/auth/copyauth.js
@@ -1,8 +1,8 @@
// Test copyDatabase command with various combinations of authed/unauthed and single node/replica
// set source and dest.
-TestData.authMechanism = "MONGODB-CR"; // SERVER-11428
-DB.prototype._defaultAuthenticationMechanism = "MONGODB-CR"; // SERVER-11428
+TestData.authMechanism = "SCRAM-SHA-1"; // SERVER-11428
+DB.prototype._defaultAuthenticationMechanism = "SCRAM-SHA-1"; // SERVER-11428
var baseName = "jstests_clone_copyauth";
diff --git a/src/mongo/crypto/mechanism_scram.cpp b/src/mongo/crypto/mechanism_scram.cpp
index 95629fcae86..1b6eaf88ea9 100644
--- a/src/mongo/crypto/mechanism_scram.cpp
+++ b/src/mongo/crypto/mechanism_scram.cpp
@@ -171,10 +171,10 @@ namespace scram {
std::string encodedServerKey =
base64::encode(reinterpret_cast<char*>(serverKey), hashSize);
- return BSON("iterationCount" << iterationCount <<
- "salt" << encodedUserSalt <<
- "storedKey" << encodedStoredKey <<
- "serverKey" << encodedServerKey);
+ return BSON(iterationCountFieldName << iterationCount <<
+ saltFieldName << encodedUserSalt <<
+ storedKeyFieldName << encodedStoredKey <<
+ serverKeyFieldName << encodedServerKey);
}
std::string generateClientProof(const unsigned char saltedPassword[hashSize],
diff --git a/src/mongo/crypto/mechanism_scram.h b/src/mongo/crypto/mechanism_scram.h
index 6f5b37b8d6b..fc6da4aea9c 100644
--- a/src/mongo/crypto/mechanism_scram.h
+++ b/src/mongo/crypto/mechanism_scram.h
@@ -36,9 +36,15 @@
namespace mongo {
namespace scram {
const unsigned int hashSize = 20;
+
const std::string serverKeyConst = "Server Key";
const std::string clientKeyConst = "Client Key";
+ const std::string iterationCountFieldName = "iterationCount";
+ const std::string saltFieldName = "salt";
+ const std::string storedKeyFieldName = "storedKey";
+ const std::string serverKeyFieldName = "serverKey";
+
/*
* Computes the SaltedPassword from password, salt and iterationCount.
*/
diff --git a/src/mongo/db/auth/sasl_commands.cpp b/src/mongo/db/auth/sasl_commands.cpp
index be9543a33da..14dfcc02e5d 100644
--- a/src/mongo/db/auth/sasl_commands.cpp
+++ b/src/mongo/db/auth/sasl_commands.cpp
@@ -323,7 +323,9 @@ namespace {
SaslAuthenticationSession* session =
static_cast<SaslAuthenticationSession*>(sessionGuard.get());
- if (session->getAuthenticationDatabase() != db) {
+ // Authenticating the __system@local user to the admin database on mongos is required
+ // by the auth passthrough test suite.
+ if (session->getAuthenticationDatabase() != db && !Command::testCommandsEnabled) {
addStatus(Status(ErrorCodes::ProtocolError,
"Attempt to switch database target during SASL authentication."),
&result);
@@ -348,18 +350,18 @@ namespace {
return status.isOK();
}
-
+
// The CyrusSaslCommands Enterprise initializer is dependent on PreSaslCommands
MONGO_INITIALIZER_WITH_PREREQUISITES(PreSaslCommands,
("NativeSaslServerCore"))
(InitializerContext*) {
-
+
if (!sequenceContains(saslGlobalParams.authenticationMechanisms, "MONGODB-CR"))
CmdAuthenticate::disableAuthMechanism("MONGODB-CR");
-
+
if (!sequenceContains(saslGlobalParams.authenticationMechanisms, "MONGODB-X509"))
CmdAuthenticate::disableAuthMechanism("MONGODB-X509");
-
+
return Status::OK();
}
diff --git a/src/mongo/db/auth/sasl_scramsha1_server_conversation.cpp b/src/mongo/db/auth/sasl_scramsha1_server_conversation.cpp
index 7631372bd17..791fe137b11 100644
--- a/src/mongo/db/auth/sasl_scramsha1_server_conversation.cpp
+++ b/src/mongo/db/auth/sasl_scramsha1_server_conversation.cpp
@@ -159,10 +159,10 @@ namespace mongo {
// Generate SCRAM credentials on the fly for mixed MONGODB-CR/SCRAM mode.
if (_creds.scram.salt.empty() && !_creds.password.empty()) {
BSONObj scramCreds = scram::generateCredentials(_creds.password);
- _creds.scram.iterationCount = scramCreds["iterationCount"].Int();
- _creds.scram.salt = scramCreds["salt"].String();
- _creds.scram.storedKey = scramCreds["storedKey"].String();
- _creds.scram.serverKey = scramCreds["serverKey"].String();
+ _creds.scram.iterationCount = scramCreds[scram::iterationCountFieldName].Int();
+ _creds.scram.salt = scramCreds[scram::saltFieldName].String();
+ _creds.scram.storedKey = scramCreds[scram::storedKeyFieldName].String();
+ _creds.scram.serverKey = scramCreds[scram::serverKeyFieldName].String();
}
// Generate server-first-message
diff --git a/src/mongo/db/auth/security_key.cpp b/src/mongo/db/auth/security_key.cpp
index 221a0c48cf5..dcc0f7866a3 100644
--- a/src/mongo/db/auth/security_key.cpp
+++ b/src/mongo/db/auth/security_key.cpp
@@ -36,7 +36,10 @@
#include <string>
#include <vector>
+#include "mongo/bson/mutable/document.h"
+#include "mongo/bson/mutable/element.h"
#include "mongo/client/sasl_client_authenticate.h"
+#include "mongo/crypto/mechanism_scram.h"
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_manager.h"
@@ -47,15 +50,22 @@
#include "mongo/util/password_digest.h"
namespace mongo {
+ namespace mmb = mongo::mutablebson;
+
// not guarded by the authParams mutex never changed in
// multi-threaded operation
static bool authParamsSet = false;
+
+ // Store default authentication parameters for internal authentication to cluster members,
// guarded by the authParams mutex
static BSONObj authParams;
- static boost::mutex authParamMutex;
+
+ // Store MONGODB-CR authentication parameters to use as fallback for mixed 2.6/28 clusters
+ static BSONObj authParamsCR;
+ static boost::mutex authParamMutex;
bool isInternalAuthSet() {
- return authParamsSet;
+ return authParamsSet;
}
void setInternalUserAuthParams(const BSONObj& authParamsIn) {
@@ -64,20 +74,45 @@ namespace mongo {
}
boost::mutex::scoped_lock lk(authParamMutex);
authParams = authParamsIn.copy();
+
+ // Create authParams for legacy MONGODB-CR authentication if applicable.
+ if (authParams["mechanism"].String() == "SCRAM-SHA-1") {
+ mmb::Document doc(authParams);
+ doc.root().findFirstChildNamed("mechanism").setValueString("MONGODB-CR");
+ authParamsCR = doc.getObject().copy();
+ }
}
-
+
bool authenticateInternalUser(DBClientWithCommands* conn){
if (!isInternalAuthSet()) {
log() << "ERROR: No authentication parameters set for internal user" << endl;
return false;
}
- try {
- BSONObj outgoingAuthParams;
- {
- boost::mutex::scoped_lock lk(authParamMutex);
- outgoingAuthParams = authParams.copy();
- }
- conn->auth(outgoingAuthParams);
+
+ BSONObj authParamsCopy;
+ BSONObj authParamsCRCopy;
+ {
+ boost::mutex::scoped_lock lk(authParamMutex);
+ authParamsCopy = authParams.copy();
+ authParamsCRCopy = authParamsCR.copy();
+ }
+
+ try {
+ conn->auth(authParamsCopy);
+ return true;
+ } catch(const UserException& ex) {
+ if (ex.getCode() != ErrorCodes::BadValue &&
+ ex.getCode() != ErrorCodes::CommandNotFound) {
+ log() << "can't authenticate to " << conn->toString() <<
+ " as internal user, error: "<< ex.what() << endl;
+ return false;
+ }
+ }
+
+ // BadValue indicates unsupported auth mechanism so fall back to
+ // MONGODB-CR for 2.6 compatibility.
+ try {
+ conn->auth(authParamsCRCopy);
return true;
} catch(const UserException& ex) {
log() << "can't authenticate to " << conn->toString() << " as internal user, error: "
@@ -148,16 +183,24 @@ namespace mongo {
return false;
}
+ // Generate MONGODB-CR and SCRAM credentials for the internal user based on the keyfile.
User::CredentialData credentials;
credentials.password = mongo::createPasswordDigest(
internalSecurity.user->getName().getUser().toString(), str);
+
+ BSONObj creds = scram::generateCredentials(credentials.password);
+ credentials.scram.iterationCount = creds[scram::iterationCountFieldName].Int();
+ credentials.scram.salt = creds[scram::saltFieldName].String();
+ credentials.scram.storedKey = creds[scram::storedKeyFieldName].String();
+ credentials.scram.serverKey = creds[scram::serverKeyFieldName].String();
+
internalSecurity.user->setCredentials(credentials);
int clusterAuthMode = serverGlobalParams.clusterAuthMode.load();
if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_keyFile ||
clusterAuthMode == ServerGlobalParams::ClusterAuthMode_sendKeyFile) {
setInternalUserAuthParams(
- BSON(saslCommandMechanismFieldName << "MONGODB-CR" <<
+ BSON(saslCommandMechanismFieldName << "SCRAM-SHA-1" <<
saslCommandUserDBFieldName <<
internalSecurity.user->getName().getDB() <<
saslCommandUserFieldName << internalSecurity.user->getName().getUser() <<
diff --git a/src/mongo/shell/shardingtest.js b/src/mongo/shell/shardingtest.js
index 1c8241ec392..3e333ab898d 100644
--- a/src/mongo/shell/shardingtest.js
+++ b/src/mongo/shell/shardingtest.js
@@ -386,7 +386,7 @@ ShardingTest = function( testName , numShards , verboseLevel , numMongos , other
if (keyFile) {
authutil.assertAuthenticate(this._mongos, 'admin', {
user: '__system',
- mechanism: 'MONGODB-CR',
+ mechanism: 'SCRAM-SHA-1',
pwd: cat(keyFile).replace(/[\011-\015\040]/g, '')
});
diff --git a/src/mongo/shell/utils_auth.js b/src/mongo/shell/utils_auth.js
index ff8f1543cac..f8534f616b1 100644
--- a/src/mongo/shell/utils_auth.js
+++ b/src/mongo/shell/utils_auth.js
@@ -71,7 +71,7 @@ var authutil;
var ex;
authutil.assertAuthenticate(conn, 'local', {
user: '__system',
- mechanism: 'MONGODB-CR',
+ mechanism: 'SCRAM-SHA-1',
pwd: cat(keyfile).replace(/[\011-\015\040]/g, '')
});