bool CmdSaslStart::run(OperationContext* txn, const std::string& db, BSONObj& cmdObj, int options, std::string& ignored, BSONObjBuilder& result, bool fromRepl) { ClientBasic* client = ClientBasic::getCurrent(); client->resetAuthenticationSession(NULL); SaslAuthenticationSession* session = SaslAuthenticationSession::create(client->getAuthorizationSession()); boost::scoped_ptr<AuthenticationSession> sessionGuard(session); session->setOpCtxt(txn); Status status = doSaslStart(session, db, cmdObj, &result); addStatus(status, &result); if (session->isDone()) { audit::logAuthentication( client, session->getMechanism(), UserName(session->getPrincipalId(), db), status.code()); } else { client->swapAuthenticationSession(sessionGuard); } return status.isOK(); }
bool CmdSaslContinue::run(OperationContext* txn, const std::string& db, BSONObj& cmdObj, int options, std::string& ignored, BSONObjBuilder& result, bool fromRepl) { ClientBasic* client = ClientBasic::getCurrent(); boost::scoped_ptr<AuthenticationSession> sessionGuard(NULL); client->swapAuthenticationSession(sessionGuard); if (!sessionGuard || sessionGuard->getType() != AuthenticationSession::SESSION_TYPE_SASL) { addStatus(Status(ErrorCodes::ProtocolError, "No SASL session state found"), &result); return false; } SaslAuthenticationSession* session = static_cast<SaslAuthenticationSession*>(sessionGuard.get()); // Authenticating the __system@local user to the admin database on mongos is required // by the auth passthrough test suite. if (session->getAuthenticationDatabase() != db && !Command::testCommandsEnabled) { addStatus(Status(ErrorCodes::ProtocolError, "Attempt to switch database target during SASL authentication."), &result); return false; } session->setOpCtxt(txn); Status status = doSaslContinue(session, cmdObj, &result); addStatus(status, &result); if (session->isDone()) { audit::logAuthentication( client, session->getMechanism(), UserName(session->getPrincipalId(), db), status.code()); } else { client->swapAuthenticationSession(sessionGuard); } return status.isOK(); }
Status CmdAuthenticate::_authenticateCR(const UserName& user, const BSONObj& cmdObj) { if (user == internalSecurity.user->getName() && serverGlobalParams.clusterAuthMode == "x509") { return Status(ErrorCodes::AuthenticationFailed, "Mechanism x509 is required for internal cluster authentication"); } if (!_areNonceAuthenticateCommandsEnabled) { // SERVER-8461, MONGODB-CR must be enabled for authenticating the internal user, so that // cluster members may communicate with each other. if (user != internalSecurity.user->getName()) { return Status(ErrorCodes::BadValue, _nonceAuthenticateCommandsDisabledMessage); } } string key = cmdObj.getStringField("key"); string received_nonce = cmdObj.getStringField("nonce"); if( user.getUser().empty() || key.empty() || received_nonce.empty() ) { sleepmillis(10); return Status(ErrorCodes::ProtocolError, "field missing/wrong type in received authenticate command"); } stringstream digestBuilder; { ClientBasic *client = ClientBasic::getCurrent(); boost::scoped_ptr<AuthenticationSession> session; client->swapAuthenticationSession(session); if (!session || session->getType() != AuthenticationSession::SESSION_TYPE_MONGO) { sleepmillis(30); return Status(ErrorCodes::ProtocolError, "No pending nonce"); } else { nonce64 nonce = static_cast<MongoAuthenticationSession*>(session.get())->getNonce(); digestBuilder << hex << nonce; if (digestBuilder.str() != received_nonce) { sleepmillis(30); return Status(ErrorCodes::AuthenticationFailed, "Received wrong nonce."); } } } User* userObj; Status status = getGlobalAuthorizationManager()->acquireUser(user, &userObj); if (!status.isOK()) { // Failure to find the privilege document indicates no-such-user, a fact that we do not // wish to reveal to the client. So, we return AuthenticationFailed rather than passing // through the returned status. return Status(ErrorCodes::AuthenticationFailed, status.toString()); } string pwd = userObj->getCredentials().password; getGlobalAuthorizationManager()->releaseUser(userObj); md5digest d; { digestBuilder << user.getUser() << 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 ) { return Status(ErrorCodes::AuthenticationFailed, "key mismatch"); } AuthorizationSession* authorizationSession = ClientBasic::getCurrent()->getAuthorizationSession(); status = authorizationSession->addAndAuthorizeUser(user); if (!status.isOK()) { return status; } return Status::OK(); }