summaryrefslogtreecommitdiff
path: root/src/mongo/crypto
diff options
context:
space:
mode:
authorPatrick Freed <patrick.freed@mongodb.com>2018-11-30 16:40:02 -0500
committerPatrick Freed <patrick.freed@mongodb.com>2018-12-20 17:11:29 -0500
commit916a5553a2db8ae7553fea7c3703ef8fef75b055 (patch)
treed1cb1af190d93a2f010e2c8a11663366b4979bf7 /src/mongo/crypto
parentcf30414301d665e151b3d75eab7de59023514871 (diff)
downloadmongo-916a5553a2db8ae7553fea7c3703ef8fef75b055.tar.gz
SERVER-37565 Unlock memory held during SCRAM authentication
This fixes a bug where the server would crash if a large number of parallel connections occurred at once
Diffstat (limited to 'src/mongo/crypto')
-rw-r--r--src/mongo/crypto/mechanism_scram.h64
1 files changed, 49 insertions, 15 deletions
diff --git a/src/mongo/crypto/mechanism_scram.h b/src/mongo/crypto/mechanism_scram.h
index 37614357f73..2a8cd79e72f 100644
--- a/src/mongo/crypto/mechanism_scram.h
+++ b/src/mongo/crypto/mechanism_scram.h
@@ -139,6 +139,47 @@ template <typename T>
bool operator!=(const Presecrets<T>& lhs, const Presecrets<T>& rhs) {
return !(lhs == rhs);
}
+template <typename HashBlock>
+struct SecretsHolder {
+ HashBlock clientKey;
+ HashBlock storedKey;
+ HashBlock serverKey;
+};
+
+template <typename HashBlock>
+class LockedSecretsPolicy {
+public:
+ LockedSecretsPolicy() = default;
+
+ const SecretsHolder<HashBlock>* operator->() const {
+ return &(*_holder);
+ }
+ SecretsHolder<HashBlock>* operator->() {
+ return &(*_holder);
+ }
+
+private:
+ using SecureSecrets = SecureAllocatorAuthDomain::SecureHandle<SecretsHolder<HashBlock>>;
+
+ SecureSecrets _holder;
+};
+
+template <typename HashBlock>
+class UnlockedSecretsPolicy {
+public:
+ UnlockedSecretsPolicy() = default;
+
+ const SecretsHolder<HashBlock>* operator->() const {
+ return &_holder;
+ }
+
+ SecretsHolder<HashBlock>* operator->() {
+ return &_holder;
+ }
+
+private:
+ SecretsHolder<HashBlock> _holder;
+};
/* Stores all of the keys, generated from a password, needed for a client or server to perform a
* SCRAM handshake.
@@ -146,21 +187,13 @@ bool operator!=(const Presecrets<T>& lhs, const Presecrets<T>& rhs) {
* May be unpopulated. SCRAMSecrets created via the default constructor are unpopulated.
* The behavior is undefined if the accessors are called when unpopulated.
*/
-template <typename HashBlock>
+template <typename HashBlock, template <typename> class MemoryPolicy = LockedSecretsPolicy>
class Secrets {
-private:
- struct SecretsHolder {
- HashBlock clientKey;
- HashBlock storedKey;
- HashBlock serverKey;
- };
- using SecureSecrets = SecureAllocatorAuthDomain::SecureHandle<SecretsHolder>;
-
public:
Secrets() = default;
Secrets(StringData client, StringData stored, StringData server)
- : _ptr(std::make_shared<SecureSecrets>()) {
+ : _ptr(std::make_shared<MemoryPolicy<HashBlock>>()) {
if (!client.empty()) {
(*_ptr)->clientKey = uassertStatusOK(HashBlock::fromBuffer(
reinterpret_cast<const unsigned char*>(client.rawData()), client.size()));
@@ -171,13 +204,13 @@ public:
reinterpret_cast<const unsigned char*>(server.rawData()), stored.size()));
}
- Secrets(const HashBlock& saltedPassword) : _ptr(std::make_shared<SecureSecrets>()) {
+ Secrets(const HashBlock& saltedPassword) : _ptr(std::make_shared<MemoryPolicy<HashBlock>>()) {
// ClientKey := HMAC(saltedPassword, "Client Key")
- (*_ptr)->clientKey = HashBlock::computeHmac(
+ (*_ptr)->clientKey = (HashBlock::computeHmac(
saltedPassword.data(),
saltedPassword.size(),
reinterpret_cast<const unsigned char*>(kClientKeyConst.rawData()),
- kClientKeyConst.size());
+ kClientKeyConst.size()));
// StoredKey := H(clientKey)
(*_ptr)->storedKey = HashBlock::computeHash(clientKey().data(), clientKey().size());
@@ -255,7 +288,8 @@ public:
static BSONObj generateCredentials(const std::vector<uint8_t>& salt,
const std::string& password,
int iterationCount) {
- Secrets<HashBlock> secrets(Presecrets<HashBlock>(password, salt, iterationCount));
+ Secrets<HashBlock, MemoryPolicy> secrets(
+ Presecrets<HashBlock>(password, salt, iterationCount));
const auto encodedSalt =
base64::encode(reinterpret_cast<const char*>(salt.data()), salt.size());
return BSON(kIterationCountFieldName << iterationCount << kSaltFieldName << encodedSalt
@@ -289,7 +323,7 @@ public:
}
private:
- std::shared_ptr<SecureSecrets> _ptr;
+ std::shared_ptr<MemoryPolicy<HashBlock>> _ptr;
};
} // namespace scram