0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 17:10:48 +01:00

SERVER-17991 Refactor security key file reading / support base64 padding.

This commit is contained in:
Amalia Hawkins 2015-07-08 11:57:03 -04:00
parent deb117ad90
commit b057c6a2a2
2 changed files with 80 additions and 55 deletions

View File

@ -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,73 +52,25 @@
namespace mongo {
using std::endl;
using std::string;
bool setUpSecurityKey(const string& filename) {
struct stat stats;
// check obvious file errors
if (stat(filename.c_str(), &stats) == -1) {
log() << "error getting file " << filename << ": " << strerror(errno) << endl;
StatusWith<std::string> keyString = readSecurityFile(filename);
if (!keyString.isOK()) {
log() << keyString.getStatus().reason();
return false;
}
#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;
}
#endif
FILE* file = fopen(filename.c_str(), "rb");
if (!file) {
log() << "error opening file: " << filename << ": " << strerror(errno) << endl;
return false;
}
string str = "";
// strip key file
const unsigned long long fileLength = stats.st_size;
unsigned long long read = 0;
while (read < fileLength) {
char buf;
int readLength = fread(&buf, 1, 1, file);
if (readLength < 1) {
log() << "error reading file " << filename << endl;
fclose(file);
return false;
}
read++;
// check for whitespace
if ((buf >= '\x09' && buf <= '\x0D') || buf == ' ') {
continue;
}
// 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;
fclose(file);
return false;
}
str += buf;
}
fclose(file);
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" << endl;
<< ", must be between 6 and 1024 chars";
return false;
}
// Generate MONGODB-CR and SCRAM credentials for the internal user based on the keyfile.
// 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);
@ -141,7 +94,70 @@ bool setUpSecurityKey(const string& filename) {
<< 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) {
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) {
return StatusWith<std::string>(ErrorCodes::InvalidPath,
str::stream() << "permissions on " << filename
<< " are too open");
}
#endif
FILE* file = fopen(filename.c_str(), "rb");
if (!file) {
return StatusWith<std::string>(ErrorCodes::InvalidPath,
str::stream() << "error opening file: " << filename << ": "
<< strerror(errno));
}
string str = "";
// strip key file
const unsigned long long fileLength = stats.st_size;
unsigned long long read = 0;
while (read < fileLength) {
char buf;
int readLength = fread(&buf, 1, 1, file);
if (readLength < 1) {
fclose(file);
return StatusWith<std::string>(ErrorCodes::UnsupportedFormat,
str::stream() << "error reading file: " << filename);
}
read++;
// check for whitespace
if ((buf >= '\x09' && buf <= '\x0D') || buf == ' ') {
continue;
}
// check valid base64
if ((buf < 'A' || buf > 'Z') && (buf < 'a' || buf > 'z') && (buf < '0' || buf > '9') &&
buf != '+' && buf != '/' && buf != '=') {
fclose(file);
return StatusWith<std::string>(ErrorCodes::UnsupportedFormat,
str::stream() << "invalid char in key file " << filename
<< ": " << buf);
}
str += buf;
}
fclose(file);
return StatusWith<std::string>(str);
}
} // namespace mongo

View File

@ -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