diff options
author | Amalia Hawkins <amalia.hawkins@10gen.com> | 2015-07-08 11:57:03 -0400 |
---|---|---|
committer | Amalia Hawkins <amalia.hawkins@10gen.com> | 2015-07-08 13:56:02 -0400 |
commit | b057c6a2a2b65de10ba1720ec2c9ccd4a6ba40dc (patch) | |
tree | 7874d53edff651a00b239006daec97ec79ec6024 | |
parent | deb117ad90c9f7d5360c4d249997ccb842d8c5ed (diff) | |
download | mongo-b057c6a2a2b65de10ba1720ec2c9ccd4a6ba40dc.tar.gz |
SERVER-17991 Refactor security key file reading / support base64 padding.
-rw-r--r-- | src/mongo/db/auth/security_key.cpp | 106 | ||||
-rw-r--r-- | src/mongo/db/auth/security_key.h | 9 |
2 files changed, 70 insertions, 45 deletions
diff --git a/src/mongo/db/auth/security_key.cpp b/src/mongo/db/auth/security_key.cpp index d7d7c96410e..e5a6b24a7ae 100644 --- a/src/mongo/db/auth/security_key.cpp +++ b/src/mongo/db/auth/security_key.cpp @@ -36,6 +36,7 @@ #include <string> #include <vector> +#include "mongo/base/status_with.h" #include "mongo/client/sasl_client_authenticate.h" #include "mongo/crypto/mechanism_scram.h" #include "mongo/db/auth/action_set.h" @@ -51,30 +52,76 @@ namespace mongo { -using std::endl; using std::string; bool setUpSecurityKey(const string& filename) { + StatusWith<std::string> keyString = readSecurityFile(filename); + if (!keyString.isOK()) { + log() << keyString.getStatus().reason(); + return false; + } + + std::string str = std::move(keyString.getValue()); + const unsigned long long keyLength = str.size(); + if (keyLength < 6 || keyLength > 1024) { + log() << " security key in " << filename << " has length " << keyLength + << ", must be between 6 and 1024 chars"; + 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, saslGlobalParams.scramIterationCount); + 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 + << "SCRAM-SHA-1" << saslCommandUserDBFieldName + << internalSecurity.user->getName().getDB() << saslCommandUserFieldName + << internalSecurity.user->getName().getUser() << saslCommandPasswordFieldName + << credentials.password << saslCommandDigestPasswordFieldName << false)); + } + + return true; +} + +StatusWith<std::string> readSecurityFile(const std::string& filename) { struct stat stats; // check obvious file errors if (stat(filename.c_str(), &stats) == -1) { - log() << "error getting file " << filename << ": " << strerror(errno) << endl; - return false; + return StatusWith<std::string>(ErrorCodes::InvalidPath, + str::stream() << "error getting file " << filename << ": " + << strerror(errno)); } #if !defined(_WIN32) // check permissions: must be X00, where X is >= 4 if ((stats.st_mode & (S_IRWXG | S_IRWXO)) != 0) { - log() << "permissions on " << filename << " are too open" << endl; - return false; + return StatusWith<std::string>(ErrorCodes::InvalidPath, + str::stream() << "permissions on " << filename + << " are too open"); } #endif FILE* file = fopen(filename.c_str(), "rb"); if (!file) { - log() << "error opening file: " << filename << ": " << strerror(errno) << endl; - return false; + return StatusWith<std::string>(ErrorCodes::InvalidPath, + str::stream() << "error opening file: " << filename << ": " + << strerror(errno)); } string str = ""; @@ -86,9 +133,9 @@ bool setUpSecurityKey(const string& filename) { char buf; int readLength = fread(&buf, 1, 1, file); if (readLength < 1) { - log() << "error reading file " << filename << endl; fclose(file); - return false; + return StatusWith<std::string>(ErrorCodes::UnsupportedFormat, + str::stream() << "error reading file: " << filename); } read++; @@ -99,49 +146,18 @@ bool setUpSecurityKey(const string& filename) { // check valid base64 if ((buf < 'A' || buf > 'Z') && (buf < 'a' || buf > 'z') && (buf < '0' || buf > '9') && - buf != '+' && buf != '/') { - log() << "invalid char in key file " << filename << ": " << buf << endl; + buf != '+' && buf != '/' && buf != '=') { fclose(file); - return false; + return StatusWith<std::string>(ErrorCodes::UnsupportedFormat, + str::stream() << "invalid char in key file " << filename + << ": " << buf); } str += buf; } fclose(file); - - const unsigned long long keyLength = str.size(); - if (keyLength < 6 || keyLength > 1024) { - log() << " security key in " << filename << " has length " << keyLength - << ", must be between 6 and 1024 chars" << endl; - 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, saslGlobalParams.scramIterationCount); - 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 - << "SCRAM-SHA-1" << saslCommandUserDBFieldName - << internalSecurity.user->getName().getDB() << saslCommandUserFieldName - << internalSecurity.user->getName().getUser() << saslCommandPasswordFieldName - << credentials.password << saslCommandDigestPasswordFieldName << false)); - } - return true; + return StatusWith<std::string>(str); } } // namespace mongo diff --git a/src/mongo/db/auth/security_key.h b/src/mongo/db/auth/security_key.h index 898efdf9e8a..8cd1b81a88f 100644 --- a/src/mongo/db/auth/security_key.h +++ b/src/mongo/db/auth/security_key.h @@ -31,6 +31,9 @@ #include <string> namespace mongo { +template <class T> +class StatusWith; + /** * This method checks the validity of filename as a security key, hashes its * contents, and stores it in the internalSecurity variable. Prints an @@ -40,4 +43,10 @@ namespace mongo { */ bool setUpSecurityKey(const std::string& filename); +/** + * This method takes in a filename and returns the contents as a string. + * It checks that the contents are valid base 64 characters. + */ +StatusWith<std::string> readSecurityFile(const std::string& filename); + } // namespace mongo |