bool CmdAuthenticate::authenticateX509(const string& dbname,
                                           BSONObj& cmdObj, 
                                           string& errmsg, 
                                           BSONObjBuilder& result) {
        if(dbname != "$external") {
            errmsg = "X.509 authentication must always use the $external database.";
            result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
            return false;
        }

        std::string user = cmdObj.getStringField("user");
        ClientBasic *client = ClientBasic::getCurrent();
        AuthorizationSession* authorizationSession = client->getAuthorizationSession();
        StringData subjectName = client->port()->getX509SubjectName();
        
        if (user != subjectName) {
            errmsg = "There is no x.509 client certificate matching the user.";
            result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
            return false;
        }
        else {
            StringData srvSubjectName = getSSLManager()->getSubjectName();
            StringData srvClusterId = srvSubjectName.substr(0, srvSubjectName.find("/CN")+1);
            StringData peerClusterId = subjectName.substr(0, subjectName.find("/CN")+1);

            // Handle internal cluster member 
            if (srvClusterId == peerClusterId) {
                authorizationSession->grantInternalAuthorization(UserName(user, "$external"));
            }
            // Handle normal client authentication
            else {
                Principal* principal = new Principal(UserName(user, "$external"));
                principal->setImplicitPrivilegeAcquisition(true);
                authorizationSession->addAuthorizedPrincipal(principal);
            }
            result.append( "dbname" , dbname );
            result.append( "user" , user );
            return true;
        }
    }
    bool CmdAuthenticate::authenticateCR(const string& dbname, 
                                         BSONObj& cmdObj, 
                                         string& errmsg, 
                                         BSONObjBuilder& result) {
        
        string user = cmdObj.getStringField("user");

        if (!_areNonceAuthenticateCommandsEnabled) {
            // SERVER-8461, MONGODB-CR must be enabled for authenticating the internal user, so that
            // cluster members may communicate with each other.
            if (dbname != StringData("local", StringData::LiteralTag()) ||
                user != internalSecurity.user) {
                errmsg = _nonceAuthenticateCommandsDisabledMessage;
                result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
                return false;
            }
        }

        string key = cmdObj.getStringField("key");
        string received_nonce = cmdObj.getStringField("nonce");

        if( user.empty() || key.empty() || received_nonce.empty() ) {
            log() << "field missing/wrong type in received authenticate command "
                  << dbname
                  << endl;
            errmsg = "auth fails";
            sleepmillis(10);
            result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
            return false;
        }

        stringstream digestBuilder;

        {
            bool reject = false;
            ClientBasic *client = ClientBasic::getCurrent();
            AuthenticationSession *session = client->getAuthenticationSession();
            if (!session || session->getType() != AuthenticationSession::SESSION_TYPE_MONGO) {
                reject = true;
                LOG(1) << "auth: No pending nonce" << endl;
            }
            else {
                nonce64 nonce = static_cast<MongoAuthenticationSession*>(session)->getNonce();
                digestBuilder << hex << nonce;
                reject = digestBuilder.str() != received_nonce;
                if ( reject ) {
                    LOG(1) << "auth: Authentication failed for " << dbname << '$' << user << endl;
                }
            }
            client->resetAuthenticationSession(NULL);

            if ( reject ) {
                log() << "auth: bad nonce received or getnonce not called. could be a driver bug or a security attack. db:" << dbname << endl;
                errmsg = "auth fails";
                sleepmillis(30);
                result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
                return false;
            }
        }

        BSONObj userObj;
        string pwd;
        Status status = getGlobalAuthorizationManager()->getPrivilegeDocument(
                dbname, UserName(user, dbname), &userObj);
        if (!status.isOK()) {
            log() << status.reason() << std::endl;
            errmsg = "auth fails";
            result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
            return false;
        }
        pwd = userObj["pwd"].String();

        md5digest d;
        {
            digestBuilder << user << pwd;
            string done = digestBuilder.str();

            md5_state_t st;
            md5_init(&st);
            md5_append(&st, (const md5_byte_t *) done.c_str(), done.size());
            md5_finish(&st, d);
        }

        string computed = digestToString( d );

        if ( key != computed ) {
            log() << "auth: key mismatch " << user << ", ns:" << dbname << endl;
            errmsg = "auth fails";
            result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
            return false;
        }

        AuthorizationSession* authorizationSession =
            ClientBasic::getCurrent()->getAuthorizationSession();
        Principal* principal = new Principal(UserName(user, dbname));
        principal->setImplicitPrivilegeAcquisition(true);
        authorizationSession->addAuthorizedPrincipal(principal);

        result.append( "dbname" , dbname );
        result.append( "user" , user );
        return true;
    }