diff options
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/auth/sasl_plain_server_conversation.cpp | 19 | ||||
-rw-r--r-- | src/mongo/db/auth/sasl_scramsha1_server_conversation.cpp | 53 | ||||
-rw-r--r-- | src/mongo/db/auth/sasl_scramsha1_test.cpp | 78 |
3 files changed, 94 insertions, 56 deletions
diff --git a/src/mongo/db/auth/sasl_plain_server_conversation.cpp b/src/mongo/db/auth/sasl_plain_server_conversation.cpp index 31945f6e9a6..cf7f2cdeaa5 100644 --- a/src/mongo/db/auth/sasl_plain_server_conversation.cpp +++ b/src/mongo/db/auth/sasl_plain_server_conversation.cpp @@ -28,7 +28,6 @@ #include "mongo/db/auth/sasl_plain_server_conversation.h" -#include "mongo/base/secure_allocator.h" #include "mongo/crypto/mechanism_scram.h" #include "mongo/db/auth/sasl_authentication_session.h" #include "mongo/util/base64.h" @@ -115,18 +114,16 @@ StatusWith<bool> SaslPLAINServerConversation::step(StringData inputData, std::st } } else { // Handle schemaVersion28SCRAM (SCRAM only mode) - unsigned char storedKey[scram::hashSize]; - unsigned char serverKey[scram::hashSize]; - - scram::generateSecrets( + std::string decodedSalt = base64::decode(creds.scram.salt); + scram::SCRAMSecrets secrets = scram::generateSecrets(scram::SCRAMPresecrets( authDigest, - reinterpret_cast<const unsigned char*>(base64::decode(creds.scram.salt).c_str()), - 16, - creds.scram.iterationCount, - storedKey, - serverKey); + std::vector<std::uint8_t>(reinterpret_cast<const std::uint8_t*>(decodedSalt.c_str()), + reinterpret_cast<const std::uint8_t*>(decodedSalt.c_str()) + + 16), + creds.scram.iterationCount)); if (creds.scram.storedKey != - base64::encode(reinterpret_cast<const char*>(storedKey), scram::hashSize)) { + base64::encode(reinterpret_cast<const char*>(secrets.storedKey->data()), + secrets.storedKey->size())) { return StatusWith<bool>(ErrorCodes::AuthenticationFailed, mongoutils::str::stream() << "Incorrect user name or password"); } diff --git a/src/mongo/db/auth/sasl_scramsha1_server_conversation.cpp b/src/mongo/db/auth/sasl_scramsha1_server_conversation.cpp index ed812ddb27f..a98dc6d7dcc 100644 --- a/src/mongo/db/auth/sasl_scramsha1_server_conversation.cpp +++ b/src/mongo/db/auth/sasl_scramsha1_server_conversation.cpp @@ -281,60 +281,23 @@ StatusWith<bool> SaslSCRAMSHA1ServerConversation::_secondStep(const std::vector< // ClientKey := ClientSignature XOR ClientProof // ServerSignature := HMAC(ServerKey, AuthMessage) - unsigned int hashLen = 0; - unsigned char clientSignature[scram::hashSize]; - - std::string decodedStoredKey = base64::decode(_creds.scram.storedKey); - // ClientSignature := HMAC(StoredKey, AuthMessage) - fassert(18662, - crypto::hmacSha1(reinterpret_cast<const unsigned char*>(decodedStoredKey.c_str()), - scram::hashSize, - reinterpret_cast<const unsigned char*>(_authMessage.c_str()), - _authMessage.size(), - clientSignature, - &hashLen)); - - fassert(18658, hashLen == scram::hashSize); - - try { - clientProof = base64::decode(clientProof); - } catch (const DBException& ex) { - return StatusWith<bool>(ex.toStatus()); - } - const unsigned char* decodedClientProof = - reinterpret_cast<const unsigned char*>(clientProof.c_str()); - - // ClientKey := ClientSignature XOR ClientProof - unsigned char clientKey[scram::hashSize]; - for (size_t i = 0; i < scram::hashSize; i++) { - clientKey[i] = clientSignature[i] ^ decodedClientProof[i]; - } - - // StoredKey := H(ClientKey) - unsigned char computedStoredKey[scram::hashSize]; - fassert(18659, crypto::sha1(clientKey, scram::hashSize, computedStoredKey)); - - if (memcmp(decodedStoredKey.c_str(), computedStoredKey, scram::hashSize) != 0) { + if (!scram::verifyClientProof( + base64::decode(clientProof), base64::decode(_creds.scram.storedKey), _authMessage)) { return StatusWith<bool>(ErrorCodes::AuthenticationFailed, mongoutils::str::stream() << "SCRAM-SHA-1 authentication failed, storedKey mismatch"); } // ServerSignature := HMAC(ServerKey, AuthMessage) - unsigned char serverSignature[scram::hashSize]; std::string decodedServerKey = base64::decode(_creds.scram.serverKey); - fassert(18660, - crypto::hmacSha1(reinterpret_cast<const unsigned char*>(decodedServerKey.c_str()), - scram::hashSize, - reinterpret_cast<const unsigned char*>(_authMessage.c_str()), - _authMessage.size(), - serverSignature, - &hashLen)); - - fassert(18661, hashLen == scram::hashSize); + SHA1Hash serverSignature = + crypto::hmacSha1(reinterpret_cast<const unsigned char*>(decodedServerKey.c_str()), + decodedServerKey.size(), + reinterpret_cast<const unsigned char*>(_authMessage.c_str()), + _authMessage.size()); StringBuilder sb; - sb << "v=" << base64::encode(reinterpret_cast<char*>(serverSignature), scram::hashSize); + sb << "v=" << scram::hashToBase64(serverSignature); *outputData = sb.str(); return StatusWith<bool>(false); diff --git a/src/mongo/db/auth/sasl_scramsha1_test.cpp b/src/mongo/db/auth/sasl_scramsha1_test.cpp index 72b817bc95d..b7a214af68e 100644 --- a/src/mongo/db/auth/sasl_scramsha1_test.cpp +++ b/src/mongo/db/auth/sasl_scramsha1_test.cpp @@ -29,6 +29,7 @@ #include "mongo/platform/basic.h" #include "mongo/client/native_sasl_client_session.h" +#include "mongo/client/scram_sha1_client_cache.h" #include "mongo/crypto/mechanism_scram.h" #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authz_manager_external_state_mock.h" @@ -246,6 +247,8 @@ protected: saslClientSession->setParameter(NativeSaslClientSession::parameterServiceName, "mongodb"); saslClientSession->setParameter(NativeSaslClientSession::parameterServiceHostname, "MockServer.test"); + saslClientSession->setParameter(NativeSaslClientSession::parameterServiceHostAndPort, + "MockServer.test:27017"); } }; @@ -435,4 +438,79 @@ TEST_F(SCRAMSHA1Fixture, testMONGODBCR) { ASSERT_EQ(goalState, runSteps(saslServerSession.get(), saslClientSession.get())); } +TEST(SCRAMSHA1Cache, testGetFromEmptyCache) { + SCRAMSHA1ClientCache cache; + std::string saltStr("saltsaltsaltsalt"); + std::vector<std::uint8_t> salt(saltStr.begin(), saltStr.end()); + HostAndPort host("localhost:27017"); + + ASSERT_FALSE(cache.getCachedSecrets(host, scram::SCRAMPresecrets("aaa", salt, 10000))); +} + + +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()); + HostAndPort host("localhost:27017"); + + auto secret = scram::generateSecrets(scram::SCRAMPresecrets("aaa", salt, 10000)); + cache.setCachedSecrets(host, scram::SCRAMPresecrets("aaa", salt, 10000), secret); + auto cachedSecret = cache.getCachedSecrets(host, scram::SCRAMPresecrets("aaa", salt, 10000)); + ASSERT_TRUE(cachedSecret); + ASSERT_TRUE(std::equal( + secret.clientKey->begin(), secret.clientKey->end(), cachedSecret->clientKey->begin())); + ASSERT_TRUE(std::equal( + secret.serverKey->begin(), secret.serverKey->end(), cachedSecret->serverKey->begin())); + ASSERT_TRUE(std::equal( + secret.storedKey->begin(), secret.storedKey->end(), cachedSecret->storedKey->begin())); +} + + +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()); + HostAndPort host("localhost:27017"); + + auto secret = scram::generateSecrets(scram::SCRAMPresecrets("aaa", salt, 10000)); + cache.setCachedSecrets(host, scram::SCRAMPresecrets("aaa", salt, 10000), secret); + + ASSERT_FALSE(cache.getCachedSecrets(HostAndPort("localhost:27018"), + scram::SCRAMPresecrets("aaa", salt, 10000))); + ASSERT_FALSE(cache.getCachedSecrets(host, scram::SCRAMPresecrets("aab", salt, 10000))); + ASSERT_FALSE(cache.getCachedSecrets(host, scram::SCRAMPresecrets("aaa", badSalt, 10000))); + ASSERT_FALSE(cache.getCachedSecrets(host, scram::SCRAMPresecrets("aaa", salt, 10001))); +} + + +TEST(SCRAMSHA1Cache, testSetAndReset) { + SCRAMSHA1ClientCache cache; + StringData saltStr("saltsaltsaltsalt"); + std::vector<std::uint8_t> salt(saltStr.begin(), saltStr.end()); + HostAndPort host("localhost:27017"); + + auto secret = scram::generateSecrets(scram::SCRAMPresecrets("aaa", salt, 10000)); + cache.setCachedSecrets(host, scram::SCRAMPresecrets("aaa", salt, 10000), secret); + auto newSecret = scram::generateSecrets(scram::SCRAMPresecrets("aab", salt, 10000)); + cache.setCachedSecrets(host, scram::SCRAMPresecrets("aab", salt, 10000), newSecret); + + ASSERT_FALSE(cache.getCachedSecrets(host, scram::SCRAMPresecrets("aaa", salt, 10000))); + auto cachedSecret = cache.getCachedSecrets(host, scram::SCRAMPresecrets("aab", salt, 10000)); + ASSERT_TRUE(cachedSecret); + ASSERT_TRUE(std::equal(newSecret.clientKey->begin(), + newSecret.clientKey->end(), + cachedSecret->clientKey->begin())); + ASSERT_TRUE(std::equal(newSecret.serverKey->begin(), + newSecret.serverKey->end(), + cachedSecret->serverKey->begin())); + ASSERT_TRUE(std::equal(newSecret.storedKey->begin(), + newSecret.storedKey->end(), + cachedSecret->storedKey->begin())); +} + } // namespace mongo |