CVE-2014-3971: Improper Input Validation (CWE-20)
value: The CmdAuthenticate::_authenticateX509 function in db/commands/authentication_commands.cpp in mongod in MongoDB 2.6.x before 2.6.2 allows remote attackers to cause a denial of service (daemon crash) by attempting authentication with an invalid X.509 client certificate.
CWE description: The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
Published: 2014-12-25T11:59Z
Repository: https://github.com/mongodb/mongo
Language: C++
Files changed: src/mongo/db/commands/authentication_commands.cpp
Commit date: 2014-04-29 13:05:43 -0400
Commit message: SERVER-13573 Fix x.509 auth exception

Diff: diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index be1ddf2ec..2bfbe96cb 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -301,18 +301,22 @@ namespace mongo {
             return Status(ErrorCodes::AuthenticationFailed,
                           "There is no x.509 client certificate matching the user.");
         }
         else {
             std::string srvSubjectName = getSSLManager()->getServerSubjectName();
-            std::string srvClusterId = srvSubjectName.substr(srvSubjectName.find(",OU="));
-            std::string peerClusterId = subjectName.substr(subjectName.find(",OU="));
+            
+            size_t srvClusterIdPos = srvSubjectName.find(",OU=");
+            size_t peerClusterIdPos = subjectName.find(",OU=");
 
-            fassert(17002, !srvClusterId.empty() && srvClusterId != srvSubjectName);
+            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) {
+            if (srvClusterId == peerClusterId && !srvClusterId.empty()) {
                 if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_undefined ||
                     clusterAuthMode == ServerGlobalParams::ClusterAuthMode_keyFile) {
                     return Status(ErrorCodes::AuthenticationFailed, "The provided certificate " 
                                   "can only be used for cluster authentication, not client " 
                                   "authentication. The current configuration does not allow " 

Vulnerable code:             std::string srvClusterId = srvSubjectName.substr(srvSubjectName.find(",OU="));
            std::string peerClusterId = subjectName.substr(subjectName.find(",OU="));
            fassert(17002, !srvClusterId.empty() && srvClusterId != srvSubjectName);
            if (srvClusterId == peerClusterId) {
Fixed code:             
            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) : "";
            if (srvClusterId == peerClusterId && !srvClusterId.empty()) {