summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Nilsson <andreas.nilsson@10gen.com>2014-05-20 16:34:25 -0400
committerDan Pasette <dan@mongodb.com>2014-05-23 14:57:13 -0400
commit81b9d6df4f2476f46a5896bafc1639c5899e3130 (patch)
treebd48a993bdb0f0e0eec68dad576e3d7cafb4c25e
parent7c75cf1da8fe396eb0fff8dc9c7365e539ece611 (diff)
downloadmongo-81b9d6df4f2476f46a5896bafc1639c5899e3130.tar.gz
SERVER-13945 Match x.509 cluster certs per attribute
(cherry picked from commit 81967a2dce1898d1f03938f0b5c27b8a37873877)
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp49
-rw-r--r--src/mongo/db/commands/authentication_commands.h1
2 files changed, 39 insertions, 11 deletions
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index 1c6a63bf4f9..0b462cab95d 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -28,6 +28,7 @@
#include "mongo/db/commands/authentication_commands.h"
+#include <boost/algorithm/string.hpp>
#include <boost/scoped_ptr.hpp>
#include <string>
#include <vector>
@@ -52,6 +53,7 @@
#include "mongo/util/concurrency/mutex.h"
#include "mongo/util/md5.hpp"
#include "mongo/util/net/ssl_manager.h"
+#include "mongo/util/text.h"
namespace mongo {
@@ -283,6 +285,39 @@ namespace mongo {
}
#ifdef MONGO_SSL
+ void canonicalizeClusterDN(std::vector<std::string>* dn) {
+ // remove all RDNs we don't care about
+ for (std::vector<string>::iterator it=dn->begin(); it != dn->end(); it++) {
+ boost::algorithm::trim(*it);
+ if (!mongoutils::str::startsWith(it->c_str(), "DC=") &&
+ !mongoutils::str::startsWith(it->c_str(), "O=") &&
+ !mongoutils::str::startsWith(it->c_str(), "OU=")) {
+ dn->erase(it--);
+ }
+ }
+ std::stable_sort(dn->begin(), dn->end());
+ }
+
+ bool CmdAuthenticate::_clusterIdMatch(const std::string& subjectName,
+ const std::string& srvSubjectName) {
+ std::vector<string> clientRDN = StringSplitter::split(subjectName, ",");
+ std::vector<string> serverRDN = StringSplitter::split(srvSubjectName, ",");
+
+ canonicalizeClusterDN(&clientRDN);
+ canonicalizeClusterDN(&serverRDN);
+
+ if (clientRDN.size() == 0 || clientRDN.size() != serverRDN.size()) {
+ return false;
+ }
+
+ for (size_t i=0; i < serverRDN.size(); i++) {
+ if(clientRDN[i] != serverRDN[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
Status CmdAuthenticate::_authenticateX509(const UserName& user, const BSONObj& cmdObj) {
if (!getSSLManager()) {
return Status(ErrorCodes::ProtocolError,
@@ -303,18 +338,10 @@ namespace mongo {
}
else {
std::string srvSubjectName = getSSLManager()->getServerSubjectName();
-
- size_t srvClusterIdPos = srvSubjectName.find(",OU=");
- size_t peerClusterIdPos = subjectName.find(",OU=");
-
- std::string srvClusterId = srvClusterIdPos != std::string::npos ?
- srvSubjectName.substr(srvClusterIdPos) : "";
- std::string peerClusterId = peerClusterIdPos != std::string::npos ?
- subjectName.substr(peerClusterIdPos) : "";
-
+
// Handle internal cluster member auth, only applies to server-server connections
- int clusterAuthMode = serverGlobalParams.clusterAuthMode.load();
- if (srvClusterId == peerClusterId && !srvClusterId.empty()) {
+ if (_clusterIdMatch(subjectName, srvSubjectName)) {
+ int clusterAuthMode = serverGlobalParams.clusterAuthMode.load();
if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_undefined ||
clusterAuthMode == ServerGlobalParams::ClusterAuthMode_keyFile) {
return Status(ErrorCodes::AuthenticationFailed, "The provided certificate "
diff --git a/src/mongo/db/commands/authentication_commands.h b/src/mongo/db/commands/authentication_commands.h
index 44db5b1b910..e7891329946 100644
--- a/src/mongo/db/commands/authentication_commands.h
+++ b/src/mongo/db/commands/authentication_commands.h
@@ -79,6 +79,7 @@ namespace mongo {
const BSONObj& cmdObj);
Status _authenticateCR(const UserName& user, const BSONObj& cmdObj);
Status _authenticateX509(const UserName& user, const BSONObj& cmdObj);
+ bool _clusterIdMatch(const std::string& subjectName, const std::string& srvSubjectName);
};
extern CmdAuthenticate cmdAuthenticate;