diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2018-02-13 15:39:46 -0500 |
---|---|---|
committer | Sara Golemon <sara.golemon@mongodb.com> | 2018-02-24 16:13:04 -0500 |
commit | 10c09477dd67543a417423254b1e7c4dd4f9d05c (patch) | |
tree | 3228ffd4ee8694a282bd724932f62df6d5969946 | |
parent | d9453ada059e2e6315d55ab92781b64f0076db97 (diff) | |
download | mongo-10c09477dd67543a417423254b1e7c4dd4f9d05c.tar.gz |
SERVER-33305 Expand scramsha1 tests to include SHA256
-rw-r--r-- | src/mongo/client/scram_client_cache.h | 2 | ||||
-rw-r--r-- | src/mongo/crypto/mechanism_scram.h | 3 | ||||
-rw-r--r-- | src/mongo/crypto/mechanism_scram_test.cpp | 78 | ||||
-rw-r--r-- | src/mongo/db/auth/SConscript | 4 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_manager_test.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_session_test.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/auth/sasl_scram_test.cpp (renamed from src/mongo/db/auth/sasl_scramsha1_test.cpp) | 268 | ||||
-rw-r--r-- | src/mongo/db/auth/security_key.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/logical_session_id_test.cpp | 8 |
9 files changed, 234 insertions, 153 deletions
diff --git a/src/mongo/client/scram_client_cache.h b/src/mongo/client/scram_client_cache.h index 0f8d6f8a55a..6b8b7b20d7b 100644 --- a/src/mongo/client/scram_client_cache.h +++ b/src/mongo/client/scram_client_cache.h @@ -120,6 +120,4 @@ private: HostToSecretsMap _hostToSecrets; }; -using SCRAMSHA1ClientCache = SCRAMClientCache<SHA1Block>; - } // namespace mongo diff --git a/src/mongo/crypto/mechanism_scram.h b/src/mongo/crypto/mechanism_scram.h index 741566252ab..8ff6d488c06 100644 --- a/src/mongo/crypto/mechanism_scram.h +++ b/src/mongo/crypto/mechanism_scram.h @@ -284,8 +284,5 @@ private: std::shared_ptr<SecureSecrets> _ptr; }; -using SHA1Presecrets = Presecrets<SHA1Block>; -using SHA1Secrets = Secrets<SHA1Block>; - } // namespace scram } // namespace mongo diff --git a/src/mongo/crypto/mechanism_scram_test.cpp b/src/mongo/crypto/mechanism_scram_test.cpp index 5e67a1dfaa9..88a10bc3569 100644 --- a/src/mongo/crypto/mechanism_scram_test.cpp +++ b/src/mongo/crypto/mechanism_scram_test.cpp @@ -31,6 +31,8 @@ #include "mongo/platform/basic.h" #include "mongo/crypto/mechanism_scram.h" +#include "mongo/crypto/sha1_block.h" +#include "mongo/crypto/sha256_block.h" #include "mongo/unittest/unittest.h" #include "mongo/util/log.h" @@ -38,47 +40,77 @@ namespace mongo { namespace scram { namespace { -TEST(MechanismScram, BasicVectors) { - const std::vector<uint8_t> kBadSha1Salt{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - - ASSERT_EQ(kBadSha1Salt.size(), SHA1Block::kHashLength - 4); - - SHA1Presecrets presecrets("password", kBadSha1Salt, 4096); - ASSERT_EQ(presecrets.generateSaltedPassword().toString(), "531aYHrF581Skow4E0gCWLw/Ibo="); - - SHA1Secrets secrets(presecrets); - ASSERT_EQ(secrets.clientKey().toString(), "wiHbIsPcvJo230S6Qf5xYCDrhb0="); - ASSERT_EQ(secrets.storedKey().toString(), "SjXiaB2hLRr8aMUyXMVEw7H1jSI="); - ASSERT_EQ(secrets.serverKey().toString(), "FilAoFIclBukd3xZxBvYMXTU3HM="); +template <typename HashBlock> +void testBasicVectors(StringData saltedPw, + StringData clientKey, + StringData storedKey, + StringData serverKey, + StringData proof, + StringData signature) { + // Predictable salts yield predictable secrets. + // salt = {0, 1, 2, 3, ..., n-1} + std::vector<uint8_t> salt; + salt.resize(HashBlock::kHashLength - 4); + int i = 0; + std::generate(salt.begin(), salt.end(), [&i] { return i++; }); + + Presecrets<HashBlock> presecrets("password", salt, 4096); + ASSERT_EQ(presecrets.generateSaltedPassword().toString(), saltedPw); + + Secrets<HashBlock> secrets(presecrets); + ASSERT_EQ(secrets.clientKey().toString(), clientKey); + ASSERT_EQ(secrets.storedKey().toString(), storedKey); + ASSERT_EQ(secrets.serverKey().toString(), serverKey); const StringData authMessage("secret"); - auto proof = secrets.generateClientProof(authMessage); - ASSERT_EQ(proof, "y+cpoAm0YlN30GuNgN4B9xghi4E="); - ASSERT_TRUE(secrets.verifyClientProof(authMessage, base64::decode(proof))); + const auto generatedProof = secrets.generateClientProof(authMessage); + ASSERT_EQ(generatedProof, proof); + ASSERT_TRUE(secrets.verifyClientProof(authMessage, base64::decode(generatedProof))); - auto sig = secrets.generateServerSignature(authMessage); - ASSERT_EQ(sig, "kiZS90Kz4/yaYZn9JieHtcRzXR0="); - ASSERT_TRUE(secrets.verifyServerSignature(authMessage, base64::decode(sig))); + const auto generatedSig = secrets.generateServerSignature(authMessage); + ASSERT_EQ(generatedSig, signature); + ASSERT_TRUE(secrets.verifyServerSignature(authMessage, base64::decode(generatedSig))); } -TEST(MechanismScram, generateCredentials) { - const auto bson = SHA1Secrets::generateCredentials("password", 4096); +TEST(MechanismScram, BasicVectors) { + testBasicVectors<SHA1Block>("531aYHrF581Skow4E0gCWLw/Ibo=", + "wiHbIsPcvJo230S6Qf5xYCDrhb0=", + "SjXiaB2hLRr8aMUyXMVEw7H1jSI=", + "FilAoFIclBukd3xZxBvYMXTU3HM=", + "y+cpoAm0YlN30GuNgN4B9xghi4E=", + "kiZS90Kz4/yaYZn9JieHtcRzXR0="); + testBasicVectors<SHA256Block>("UA7rgIQG0u7EQJuOrJ99qaWVlcWnY0e/ijWBuyzSN0M=", + "xdYqTeBpV5U7m/j9EdpKT1Ls+5ublIEeYGND2RUB18k=", + "w4nwnR0Mck11lMY3EeF4pCcpJMgaToIguPbEk/ipNGY=", + "oKgZqeFO8FDpB14Y8QDLbiX1TurT6XZTdlexUt/Ny5g=", + "D6x37wuGhm1HegzIrJhedSb26XOdg5IRyR47oFqzKIo=", + "ybHsTJuRLmeT0/1YvQZKrlsgDE40RobAX7o8fu9sbdk="); +} + +template <typename HashBlock> +void testGenerateCredentials() { + const auto bson = Secrets<HashBlock>::generateCredentials("password", 4096); ASSERT_EQ(bson.nFields(), 4); ASSERT_TRUE(bson.hasField("salt")); - ASSERT_EQ(base64::decode(bson.getStringField("salt")).size(), SHA1Block::kHashLength - 4); + ASSERT_EQ(base64::decode(bson.getStringField("salt")).size(), HashBlock::kHashLength - 4); ASSERT_TRUE(bson.hasField("storedKey")); - ASSERT_EQ(base64::decode(bson.getStringField("storedKey")).size(), SHA1Block::kHashLength); + ASSERT_EQ(base64::decode(bson.getStringField("storedKey")).size(), HashBlock::kHashLength); ASSERT_TRUE(bson.hasField("serverKey")); - ASSERT_EQ(base64::decode(bson.getStringField("serverKey")).size(), SHA1Block::kHashLength); + ASSERT_EQ(base64::decode(bson.getStringField("serverKey")).size(), HashBlock::kHashLength); ASSERT_TRUE(bson.hasField("iterationCount")); ASSERT_EQ(bson.getIntField("iterationCount"), 4096); } +TEST(MechanismScram, generateCredentials) { + testGenerateCredentials<SHA1Block>(); + testGenerateCredentials<SHA256Block>(); +} + } // namespace } // namespace scram } // namespace mongo diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript index 42873a49826..db4f9cfce13 100644 --- a/src/mongo/db/auth/SConscript +++ b/src/mongo/db/auth/SConscript @@ -295,10 +295,10 @@ env.CppUnitTest( ) env.CppUnitTest( - target='sasl_scramsha1_test', + target='sasl_scram_test', source=[ 'sasl_authentication_session_test.cpp', - 'sasl_scramsha1_test.cpp', + 'sasl_scram_test.cpp', ], LIBDEPS_PRIVATE=[ 'saslauth', diff --git a/src/mongo/db/auth/authorization_manager_test.cpp b/src/mongo/db/auth/authorization_manager_test.cpp index 603cc770bb3..a2c14d71be9 100644 --- a/src/mongo/db/auth/authorization_manager_test.cpp +++ b/src/mongo/db/auth/authorization_manager_test.cpp @@ -33,6 +33,8 @@ #include "mongo/base/status.h" #include "mongo/bson/mutable/document.h" #include "mongo/crypto/mechanism_scram.h" +#include "mongo/crypto/sha1_block.h" +#include "mongo/crypto/sha256_block.h" #include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authorization_manager.h" @@ -173,13 +175,16 @@ public: void setUp() override { auto localExternalState = stdx::make_unique<AuthzManagerExternalStateMock>(); externalState = localExternalState.get(); - externalState->setAuthzVersion(AuthorizationManager::schemaVersion26Final); authzManager = stdx::make_unique<AuthorizationManager>(std::move(localExternalState)); externalState->setAuthorizationManager(authzManager.get()); authzManager->setAuthEnabled(true); - credentials = BSON("SCRAM-SHA-1" << scram::SHA1Secrets::generateCredentials( - "password", saslGlobalParams.scramSHA1IterationCount.load())); + credentials = BSON("SCRAM-SHA-1" + << scram::Secrets<SHA1Block>::generateCredentials( + "password", saslGlobalParams.scramSHA1IterationCount.load()) + << "SCRAM-SHA-256" + << scram::Secrets<SHA256Block>::generateCredentials( + "password", saslGlobalParams.scramSHA256IterationCount.load())); } std::unique_ptr<AuthorizationManager> authzManager; diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp index 4bbca4e2e17..7933bb8f46b 100644 --- a/src/mongo/db/auth/authorization_session_test.cpp +++ b/src/mongo/db/auth/authorization_session_test.cpp @@ -33,6 +33,8 @@ #include "mongo/base/status.h" #include "mongo/bson/bson_depth.h" #include "mongo/crypto/mechanism_scram.h" +#include "mongo/crypto/sha1_block.h" +#include "mongo/crypto/sha256_block.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authorization_session_for_test.h" @@ -112,8 +114,12 @@ public: authzSession = stdx::make_unique<AuthorizationSessionForTest>(std::move(localSessionState)); authzManager->setAuthEnabled(true); - credentials = BSON("SCRAM-SHA-1" << scram::SHA1Secrets::generateCredentials( - "a", saslGlobalParams.scramSHA1IterationCount.load())); + credentials = + BSON("SCRAM-SHA-1" << scram::Secrets<SHA1Block>::generateCredentials( + "a", saslGlobalParams.scramSHA1IterationCount.load()) + << "SCRAM-SHA-256" + << scram::Secrets<SHA256Block>::generateCredentials( + "a", saslGlobalParams.scramSHA256IterationCount.load())); } }; diff --git a/src/mongo/db/auth/sasl_scramsha1_test.cpp b/src/mongo/db/auth/sasl_scram_test.cpp index d0c326ea570..c75cae5f260 100644 --- a/src/mongo/db/auth/sasl_scramsha1_test.cpp +++ b/src/mongo/db/auth/sasl_scram_test.cpp @@ -26,11 +26,15 @@ * it in the license file. */ +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault + #include "mongo/platform/basic.h" #include "mongo/client/native_sasl_client_session.h" #include "mongo/client/scram_client_cache.h" #include "mongo/crypto/mechanism_scram.h" +#include "mongo/crypto/sha1_block.h" +#include "mongo/crypto/sha256_block.h" #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authz_manager_external_state_mock.h" #include "mongo/db/auth/authz_session_external_state_mock.h" @@ -40,23 +44,26 @@ #include "mongo/stdx/memory.h" #include "mongo/unittest/unittest.h" #include "mongo/util/base64.h" +#include "mongo/util/log.h" #include "mongo/util/password_digest.h" namespace mongo { +namespace { BSONObj generateSCRAMUserDocument(StringData username, StringData password) { - const size_t scramIterationCount = 10000; - auto database = "test"_sd; + const auto database = "test"_sd; - std::string digested = createPasswordDigest(username, password); - auto scramCred = scram::SHA1Secrets::generateCredentials(digested, scramIterationCount); + const auto digested = createPasswordDigest(username, password); + const auto sha1Cred = scram::Secrets<SHA1Block>::generateCredentials(digested, 10000); + const auto sha256Cred = + scram::Secrets<SHA256Block>::generateCredentials(password.toString(), 15000); return BSON("_id" << (str::stream() << database << "." << username).operator StringData() << AuthorizationManager::USER_NAME_FIELD_NAME << username << AuthorizationManager::USER_DB_FIELD_NAME << database << "credentials" - << BSON("SCRAM-SHA-1" << scramCred) + << BSON("SCRAM-SHA-1" << sha1Cred << "SCRAM-SHA-256" << sha256Cred) << "roles" << BSONArray() << "privileges" @@ -194,7 +201,7 @@ SCRAMStepsResult runSteps(NativeSaslAuthenticationSession* saslServerSession, return result; } -class SCRAMSHA1Fixture : public mongo::unittest::Test { +class SCRAMFixture : public mongo::unittest::Test { protected: const SCRAMStepsResult goalState = SCRAMStepsResult(SaslTestState(SaslTestState::kClient, 4), Status::OK()); @@ -210,7 +217,7 @@ protected: std::unique_ptr<NativeSaslAuthenticationSession> saslServerSession; std::unique_ptr<NativeSaslClientSession> saslClientSession; - void setUp() { + void setUp() final { client = serviceContext.makeClient("test"); opCtx = serviceContext.makeOperationContext(client.get()); @@ -224,23 +231,55 @@ protected: saslServerSession = stdx::make_unique<NativeSaslAuthenticationSession>(authzSession.get()); saslServerSession->setOpCtxt(opCtx.get()); - saslServerSession->start("test", "SCRAM-SHA-1", "mongodb", "MockServer.test", 1, false) - .transitional_ignore(); + ASSERT_OK( + saslServerSession->start("test", _mechanism, "mongodb", "MockServer.test", 1, false)); saslClientSession = stdx::make_unique<NativeSaslClientSession>(); - saslClientSession->setParameter(NativeSaslClientSession::parameterMechanism, "SCRAM-SHA-1"); + saslClientSession->setParameter(NativeSaslClientSession::parameterMechanism, _mechanism); saslClientSession->setParameter(NativeSaslClientSession::parameterServiceName, "mongodb"); saslClientSession->setParameter(NativeSaslClientSession::parameterServiceHostname, "MockServer.test"); saslClientSession->setParameter(NativeSaslClientSession::parameterServiceHostAndPort, "MockServer.test:27017"); } + + void tearDown() final { + saslClientSession.reset(); + saslServerSession.reset(); + authzSession.reset(); + authzManager.reset(); + authzManagerExternalState = nullptr; + opCtx.reset(); + client.reset(); + } + + std::string createPasswordDigest(StringData username, StringData password) { + if (_digestPassword) { + return mongo::createPasswordDigest(username, password); + } else { + return password.toString(); + } + } + + std::string _mechanism; + bool _digestPassword; + +public: + void run() { + log() << "SCRAM-SHA-1 variant"; + _mechanism = "SCRAM-SHA-1"; + _digestPassword = true; + Test::run(); + + log() << "SCRAM-SHA-256 variant"; + _mechanism = "SCRAM-SHA-256"; + _digestPassword = false; + Test::run(); + } }; -TEST_F(SCRAMSHA1Fixture, testServerStep1DoesNotIncludeNonceFromClientStep1) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testServerStep1DoesNotIncludeNonceFromClientStep1) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -261,11 +300,9 @@ TEST_F(SCRAMSHA1Fixture, testServerStep1DoesNotIncludeNonceFromClientStep1) { runSteps(saslServerSession.get(), saslClientSession.get(), mutator)); } -TEST_F(SCRAMSHA1Fixture, testClientStep2DoesNotIncludeNonceFromServerStep1) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testClientStep2DoesNotIncludeNonceFromServerStep1) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -285,11 +322,9 @@ TEST_F(SCRAMSHA1Fixture, testClientStep2DoesNotIncludeNonceFromServerStep1) { runSteps(saslServerSession.get(), saslClientSession.get(), mutator)); } -TEST_F(SCRAMSHA1Fixture, testClientStep2GivesBadProof) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testClientStep2GivesBadProof) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -313,11 +348,9 @@ TEST_F(SCRAMSHA1Fixture, testClientStep2GivesBadProof) { runSteps(saslServerSession.get(), saslClientSession.get(), mutator)); } -TEST_F(SCRAMSHA1Fixture, testServerStep2GivesBadVerifier) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testServerStep2GivesBadVerifier) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -349,11 +382,9 @@ TEST_F(SCRAMSHA1Fixture, testServerStep2GivesBadVerifier) { } -TEST_F(SCRAMSHA1Fixture, testSCRAM) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testSCRAM) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -364,11 +395,9 @@ TEST_F(SCRAMSHA1Fixture, testSCRAM) { ASSERT_EQ(goalState, runSteps(saslServerSession.get(), saslClientSession.get())); } -TEST_F(SCRAMSHA1Fixture, testSCRAMWithChannelBindingSupportedByClient) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testSCRAMWithChannelBindingSupportedByClient) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -384,11 +413,9 @@ TEST_F(SCRAMSHA1Fixture, testSCRAMWithChannelBindingSupportedByClient) { ASSERT_EQ(goalState, runSteps(saslServerSession.get(), saslClientSession.get(), mutator)); } -TEST_F(SCRAMSHA1Fixture, testSCRAMWithChannelBindingRequiredByClient) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testSCRAMWithChannelBindingRequiredByClient) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -407,11 +434,9 @@ TEST_F(SCRAMSHA1Fixture, testSCRAMWithChannelBindingRequiredByClient) { runSteps(saslServerSession.get(), saslClientSession.get(), mutator)); } -TEST_F(SCRAMSHA1Fixture, testSCRAMWithInvalidChannelBinding) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testSCRAMWithInvalidChannelBinding) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -430,11 +455,9 @@ TEST_F(SCRAMSHA1Fixture, testSCRAMWithInvalidChannelBinding) { runSteps(saslServerSession.get(), saslClientSession.get(), mutator)); } -TEST_F(SCRAMSHA1Fixture, testNULLInPassword) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("sajack", "saj\0ack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testNULLInPassword) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("sajack", "saj\0ack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -446,11 +469,9 @@ TEST_F(SCRAMSHA1Fixture, testNULLInPassword) { } -TEST_F(SCRAMSHA1Fixture, testCommasInUsernameAndPassword) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("s,a,jack", "s,a,jack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testCommasInUsernameAndPassword) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("s,a,jack", "s,a,jack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "s,a,jack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -461,7 +482,7 @@ TEST_F(SCRAMSHA1Fixture, testCommasInUsernameAndPassword) { ASSERT_EQ(goalState, runSteps(saslServerSession.get(), saslClientSession.get())); } -TEST_F(SCRAMSHA1Fixture, testIncorrectUser) { +TEST_F(SCRAMFixture, testIncorrectUser) { saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, createPasswordDigest("sajack", "sajack")); @@ -473,11 +494,9 @@ TEST_F(SCRAMSHA1Fixture, testIncorrectUser) { runSteps(saslServerSession.get(), saslClientSession.get())); } -TEST_F(SCRAMSHA1Fixture, testIncorrectPassword) { - authzManagerExternalState - ->insertPrivilegeDocument( - opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj()) - .transitional_ignore(); +TEST_F(SCRAMFixture, testIncorrectPassword) { + ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( + opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); saslClientSession->setParameter(NativeSaslClientSession::parameterUser, "sajack"); saslClientSession->setParameter(NativeSaslClientSession::parameterPassword, @@ -491,7 +510,7 @@ TEST_F(SCRAMSHA1Fixture, testIncorrectPassword) { runSteps(saslServerSession.get(), saslClientSession.get())); } -TEST_F(SCRAMSHA1Fixture, testOptionalClientExtensions) { +TEST_F(SCRAMFixture, testOptionalClientExtensions) { // Verify server ignores unknown/optional extensions sent by client. ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); @@ -515,7 +534,7 @@ TEST_F(SCRAMSHA1Fixture, testOptionalClientExtensions) { runSteps(saslServerSession.get(), saslClientSession.get(), mutator)); } -TEST_F(SCRAMSHA1Fixture, testOptionalServerExtensions) { +TEST_F(SCRAMFixture, testOptionalServerExtensions) { // Verify client errors on unknown/optional extensions sent by server. ASSERT_OK(authzManagerExternalState->insertPrivilegeDocument( opCtx.get(), generateSCRAMUserDocument("sajack", "sajack"), BSONObj())); @@ -540,70 +559,91 @@ TEST_F(SCRAMSHA1Fixture, testOptionalServerExtensions) { runSteps(saslServerSession.get(), saslClientSession.get(), mutator)); } -TEST(SCRAMSHA1Cache, testGetFromEmptyCache) { - SCRAMSHA1ClientCache cache; - std::string saltStr("saltsaltsaltsalt"); - std::vector<std::uint8_t> salt(saltStr.begin(), saltStr.end()); +template <typename HashBlock> +void testGetFromEmptyCache() { + SCRAMClientCache<HashBlock> cache; + const auto salt = scram::Presecrets<HashBlock>::generateSecureRandomSalt(); HostAndPort host("localhost:27017"); - - ASSERT_FALSE(cache.getCachedSecrets(host, scram::SHA1Presecrets("aaa", salt, 10000))); + ASSERT_FALSE(cache.getCachedSecrets(host, scram::Presecrets<HashBlock>("aaa", salt, 10000))); } +TEST(SCRAMCache, testGetFromEmptyCache) { + testGetFromEmptyCache<SHA1Block>(); + testGetFromEmptyCache<SHA256Block>(); +} -TEST(SCRAMSHA1Cache, testSetAndGet) { - SCRAMSHA1ClientCache cache; - std::string saltStr("saltsaltsaltsalt"); - std::string badSaltStr("s@lts@lts@lts@lt"); - std::vector<std::uint8_t> salt(saltStr.begin(), saltStr.end()); - std::vector<std::uint8_t> badSalt(badSaltStr.begin(), badSaltStr.end()); +template <typename HashBlock> +void testSetAndGet() { + SCRAMClientCache<HashBlock> cache; + const auto salt = scram::Presecrets<HashBlock>::generateSecureRandomSalt(); HostAndPort host("localhost:27017"); - auto secret = scram::SHA1Secrets(scram::SHA1Presecrets("aaa", salt, 10000)); - cache.setCachedSecrets(host, scram::SHA1Presecrets("aaa", salt, 10000), secret); - auto cachedSecret = cache.getCachedSecrets(host, scram::SHA1Presecrets("aaa", salt, 10000)); - ASSERT_TRUE(cachedSecret); - ASSERT_TRUE(secret.clientKey() == cachedSecret.clientKey()); - ASSERT_TRUE(secret.serverKey() == cachedSecret.serverKey()); - ASSERT_TRUE(secret.storedKey() == cachedSecret.storedKey()); + const auto presecrets = scram::Presecrets<HashBlock>("aaa", salt, 10000); + const auto secrets = scram::Secrets<HashBlock>(presecrets); + cache.setCachedSecrets(host, presecrets, secrets); + const auto cachedSecrets = cache.getCachedSecrets(host, presecrets); + + ASSERT_TRUE(cachedSecrets); + ASSERT_TRUE(secrets.clientKey() == cachedSecrets.clientKey()); + ASSERT_TRUE(secrets.serverKey() == cachedSecrets.serverKey()); + ASSERT_TRUE(secrets.storedKey() == cachedSecrets.storedKey()); } +TEST(SCRAMCache, testSetAndGet) { + testSetAndGet<SHA1Block>(); + testSetAndGet<SHA256Block>(); +} -TEST(SCRAMSHA1Cache, testSetAndGetWithDifferentParameters) { - SCRAMSHA1ClientCache cache; - std::string saltStr("saltsaltsaltsalt"); - std::string badSaltStr("s@lts@lts@lts@lt"); - std::vector<std::uint8_t> salt(saltStr.begin(), saltStr.end()); - std::vector<std::uint8_t> badSalt(badSaltStr.begin(), badSaltStr.end()); +template <typename HashBlock> +void testSetAndGetWithDifferentParameters() { + SCRAMClientCache<HashBlock> cache; + const auto salt = scram::Presecrets<HashBlock>::generateSecureRandomSalt(); HostAndPort host("localhost:27017"); - auto secret = scram::SHA1Secrets(scram::SHA1Presecrets("aaa", salt, 10000)); - cache.setCachedSecrets(host, scram::SHA1Presecrets("aaa", salt, 10000), secret); - - ASSERT_FALSE(cache.getCachedSecrets(HostAndPort("localhost:27018"), - scram::SHA1Presecrets("aaa", salt, 10000))); - ASSERT_FALSE(cache.getCachedSecrets(host, scram::SHA1Presecrets("aab", salt, 10000))); - ASSERT_FALSE(cache.getCachedSecrets(host, scram::SHA1Presecrets("aaa", badSalt, 10000))); - ASSERT_FALSE(cache.getCachedSecrets(host, scram::SHA1Presecrets("aaa", salt, 10001))); + const auto presecrets = scram::Presecrets<HashBlock>("aaa", salt, 10000); + const auto secrets = scram::Secrets<HashBlock>(presecrets); + cache.setCachedSecrets(host, presecrets, secrets); + ASSERT_TRUE(cache.getCachedSecrets(host, presecrets)); + + // Alter each of: host, password, salt, iterationCount. + // Any one of which should fail to retreive from cache. + ASSERT_FALSE(cache.getCachedSecrets(HostAndPort("localhost:27018"), presecrets)); + ASSERT_FALSE(cache.getCachedSecrets(host, scram::Presecrets<HashBlock>("aab", salt, 10000))); + const auto badSalt = scram::Presecrets<HashBlock>::generateSecureRandomSalt(); + ASSERT_FALSE(cache.getCachedSecrets(host, scram::Presecrets<HashBlock>("aaa", badSalt, 10000))); + ASSERT_FALSE(cache.getCachedSecrets(host, scram::Presecrets<HashBlock>("aaa", salt, 10001))); } +TEST(SCRAMCache, testSetAndGetWithDifferentParameters) { + testSetAndGetWithDifferentParameters<SHA1Block>(); + testSetAndGetWithDifferentParameters<SHA256Block>(); +} -TEST(SCRAMSHA1Cache, testSetAndReset) { - SCRAMSHA1ClientCache cache; - StringData saltStr("saltsaltsaltsalt"); - std::vector<std::uint8_t> salt(saltStr.begin(), saltStr.end()); +template <typename HashBlock> +void testSetAndReset() { + SCRAMClientCache<HashBlock> cache; + const auto salt = scram::Presecrets<HashBlock>::generateSecureRandomSalt(); HostAndPort host("localhost:27017"); - scram::SHA1Secrets secret(scram::SHA1Presecrets("aaa", salt, 10000)); - cache.setCachedSecrets(host, scram::SHA1Presecrets("aaa", salt, 10000), secret); - scram::SHA1Secrets newSecret(scram::SHA1Presecrets("aab", salt, 10000)); - cache.setCachedSecrets(host, scram::SHA1Presecrets("aab", salt, 10000), newSecret); + const auto presecretsA = scram::Presecrets<HashBlock>("aaa", salt, 10000); + const auto secretsA = scram::Secrets<HashBlock>(presecretsA); + cache.setCachedSecrets(host, presecretsA, secretsA); + const auto presecretsB = scram::Presecrets<HashBlock>("aab", salt, 10000); + const auto secretsB = scram::Secrets<HashBlock>(presecretsB); + cache.setCachedSecrets(host, presecretsB, secretsB); - ASSERT_FALSE(cache.getCachedSecrets(host, scram::SHA1Presecrets("aaa", salt, 10000))); - auto cachedSecret = cache.getCachedSecrets(host, scram::SHA1Presecrets("aab", salt, 10000)); + ASSERT_FALSE(cache.getCachedSecrets(host, presecretsA)); + const auto cachedSecret = cache.getCachedSecrets(host, presecretsB); ASSERT_TRUE(cachedSecret); - ASSERT_TRUE(newSecret.clientKey() == cachedSecret.clientKey()); - ASSERT_TRUE(newSecret.serverKey() == cachedSecret.serverKey()); - ASSERT_TRUE(newSecret.storedKey() == cachedSecret.storedKey()); + ASSERT_TRUE(secretsB.clientKey() == cachedSecret.clientKey()); + ASSERT_TRUE(secretsB.serverKey() == cachedSecret.serverKey()); + ASSERT_TRUE(secretsB.storedKey() == cachedSecret.storedKey()); +} + +TEST(SCRAMCache, testSetAndReset) { + testSetAndReset<SHA1Block>(); + testSetAndReset<SHA256Block>(); } +} // namespace } // namespace mongo diff --git a/src/mongo/db/auth/security_key.cpp b/src/mongo/db/auth/security_key.cpp index 04c46e3e4dd..3e14d65c00e 100644 --- a/src/mongo/db/auth/security_key.cpp +++ b/src/mongo/db/auth/security_key.cpp @@ -39,6 +39,7 @@ #include "mongo/base/status_with.h" #include "mongo/client/sasl_client_authenticate.h" #include "mongo/crypto/mechanism_scram.h" +#include "mongo/crypto/sha1_block.h" #include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authorization_manager.h" @@ -76,7 +77,7 @@ bool setUpSecurityKey(const string& filename) { const auto password = mongo::createPasswordDigest(internalSecurity.user->getName().getUser().toString(), str); - auto creds = scram::SHA1Secrets::generateCredentials( + auto creds = scram::Secrets<SHA1Block>::generateCredentials( password, saslGlobalParams.scramSHA1IterationCount.load()); credentials.scram_sha1.iterationCount = creds[scram::kIterationCountFieldName].Int(); credentials.scram_sha1.salt = creds[scram::kSaltFieldName].String(); diff --git a/src/mongo/db/logical_session_id_test.cpp b/src/mongo/db/logical_session_id_test.cpp index c2e0bf17105..f80d4eca0f4 100644 --- a/src/mongo/db/logical_session_id_test.cpp +++ b/src/mongo/db/logical_session_id_test.cpp @@ -33,6 +33,8 @@ #include "mongo/db/logical_session_id.h" #include "mongo/crypto/mechanism_scram.h" +#include "mongo/crypto/sha1_block.h" +#include "mongo/crypto/sha256_block.h" #include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authorization_manager.h" @@ -105,7 +107,7 @@ public: } User* addSimpleUser(UserName un) { - const auto creds = BSON("SCRAM-SHA-1" << scram::SHA1Secrets::generateCredentials( + const auto creds = BSON("SCRAM-SHA-1" << scram::Secrets<SHA1Block>::generateCredentials( "a", saslGlobalParams.scramSHA1IterationCount.load())); ASSERT_OK(managerState->insertPrivilegeDocument( _opCtx.get(), @@ -120,8 +122,8 @@ public: } User* addClusterUser(UserName un) { - const auto creds = BSON("SCRAM-SHA-1" << scram::SHA1Secrets::generateCredentials( - "a", saslGlobalParams.scramSHA1IterationCount.load())); + const auto creds = BSON("SCRAM-SHA-256" << scram::Secrets<SHA256Block>::generateCredentials( + "a", saslGlobalParams.scramSHA256IterationCount.load())); ASSERT_OK(managerState->insertPrivilegeDocument( _opCtx.get(), BSON("user" << un.getUser() << "db" << un.getDB() << "credentials" << creds << "roles" |