static Status _checkAuthorizationImpl(Command* c, ClientBasic* client, const std::string& dbname, const BSONObj& cmdObj, bool fromRepl) { namespace mmb = mutablebson; if ( c->adminOnly() && ! fromRepl && dbname != "admin" ) { return Status(ErrorCodes::Unauthorized, str::stream() << c->name << " may only be run against the admin database."); } if (client->getAuthorizationSession()->getAuthorizationManager().isAuthEnabled()) { Status status = c->checkAuthForCommand(client, dbname, cmdObj); if (status == ErrorCodes::Unauthorized) { mmb::Document cmdToLog(cmdObj, mmb::Document::kInPlaceDisabled); c->redactForLogging(&cmdToLog); return Status(ErrorCodes::Unauthorized, str::stream() << "not authorized on " << dbname << " to execute command " << cmdToLog.toString()); } if (!status.isOK()) { return status; } } else if (c->adminOnly() && c->localHostOnlyIfNoAuth(cmdObj) && !client->getIsLocalHostConnection()) { return Status(ErrorCodes::Unauthorized, str::stream() << c->name << " must run from localhost when running db without auth"); } return Status::OK(); }
BSONObj Command::getRedactedCopyForLogging(const BSONObj& cmdObj) { namespace mmb = mutablebson; mmb::Document cmdToLog(cmdObj, mmb::Document::kInPlaceDisabled); redactForLogging(&cmdToLog); BSONObjBuilder bob; cmdToLog.writeTo(&bob); return bob.obj(); }
bool CmdAuthenticate::run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { mutablebson::Document cmdToLog(cmdObj, mutablebson::Document::kInPlaceDisabled); redactForLogging(&cmdToLog); log() << " authenticate db: " << dbname << " " << cmdToLog << endl; UserName user(cmdObj.getStringField("user"), dbname); if (Command::testCommandsEnabled && user.getDB() == "admin" && user.getUser() == internalSecurity.user->getName().getUser()) { // Allows authenticating as the internal user against the admin database. This is to // support the auth passthrough test framework on mongos (since you can't use the local // database on a mongos, so you can't auth as the internal user without this). user = internalSecurity.user->getName(); } std::string mechanism = cmdObj.getStringField("mechanism"); if (mechanism.empty()) { mechanism = "MONGODB-CR"; } Status status = _authenticate(mechanism, user, cmdObj); audit::logAuthentication(ClientBasic::getCurrent(), mechanism, user, status.code()); if (!status.isOK()) { log() << "Failed to authenticate " << user << " with mechanism " << mechanism << ": " << status; if (status.code() == ErrorCodes::AuthenticationFailed) { // Statuses with code AuthenticationFailed may contain messages we do not wish to // reveal to the user, so we return a status with the message "auth failed". appendCommandStatus(result, Status(ErrorCodes::AuthenticationFailed, "auth failed")); } else { appendCommandStatus(result, status); } return false; } result.append("dbname", user.getDB()); result.append("user", user.getUser()); return true; }
Status Command::_checkAuthorization(Command* c, ClientBasic* client, const std::string& dbname, const BSONObj& cmdObj, bool fromRepl) { namespace mmb = mutablebson; Status status = _checkAuthorizationImpl(c, client, dbname, cmdObj, fromRepl); if (!status.isOK()) { log() << status << std::endl; } mmb::Document cmdToLog(cmdObj, mmb::Document::kInPlaceDisabled); c->redactForLogging(&cmdToLog); audit::logCommandAuthzCheck(client, NamespaceString(c->parseNs(dbname, cmdObj)), cmdToLog, status.code()); return status; }
bool CmdAuthenticate::run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { mutablebson::Document cmdToLog(cmdObj, mutablebson::Document::kInPlaceDisabled); redactForLogging(&cmdToLog); log() << " authenticate db: " << dbname << " " << cmdToLog << endl; UserName user(cmdObj.getStringField("user"), dbname); std::string mechanism = cmdObj.getStringField("mechanism"); if (mechanism.empty()) { mechanism = "MONGODB-CR"; } Status status = _authenticate(mechanism, user, cmdObj); audit::logAuthentication(ClientBasic::getCurrent(), mechanism, user, status.code()); if (!status.isOK()) { log() << "Failed to authenticate " << user << " with mechanism " << mechanism << ": " << status; if (status.code() == ErrorCodes::AuthenticationFailed) { // Statuses with code AuthenticationFailed may contain messages we do not wish to // reveal to the user, so we return a status with the message "auth failed". appendCommandStatus(result, Status(ErrorCodes::AuthenticationFailed, "auth failed")); } else { appendCommandStatus(result, status); } return false; } result.append("dbname", user.getDB()); result.append("user", user.getUser()); return true; }
string OpDebug::report( const CurOp& curop ) const { StringBuilder s; if ( iscommand ) s << "command "; else s << opToString( op ) << ' '; s << ns.toString(); if ( ! query.isEmpty() ) { if ( iscommand ) { s << " command: "; Command* curCommand = curop.getCommand(); if (curCommand) { mutablebson::Document cmdToLog(curop.query(), mutablebson::Document::kInPlaceDisabled); curCommand->redactForLogging(&cmdToLog); s << cmdToLog.toString(); } else { // Should not happen but we need to handle curCommand == NULL gracefully s << query.toString(); } } else { s << " query: "; s << query.toString(); } } if (!planSummary.empty()) { s << " planSummary: " << planSummary.toString(); } if ( ! updateobj.isEmpty() ) { s << " update: "; updateobj.toString( s ); } OPDEBUG_TOSTRING_HELP( cursorid ); OPDEBUG_TOSTRING_HELP( ntoreturn ); OPDEBUG_TOSTRING_HELP( ntoskip ); OPDEBUG_TOSTRING_HELP_BOOL( exhaust ); OPDEBUG_TOSTRING_HELP( nscanned ); OPDEBUG_TOSTRING_HELP_BOOL( idhack ); OPDEBUG_TOSTRING_HELP_BOOL( scanAndOrder ); OPDEBUG_TOSTRING_HELP( nmoved ); OPDEBUG_TOSTRING_HELP( nMatched ); OPDEBUG_TOSTRING_HELP( nModified ); OPDEBUG_TOSTRING_HELP( ninserted ); OPDEBUG_TOSTRING_HELP( ndeleted ); OPDEBUG_TOSTRING_HELP_BOOL( fastmod ); OPDEBUG_TOSTRING_HELP_BOOL( fastmodinsert ); OPDEBUG_TOSTRING_HELP_BOOL( upsert ); OPDEBUG_TOSTRING_HELP( keyUpdates ); if ( extra.len() ) s << " " << extra.str(); if ( ! exceptionInfo.empty() ) { s << " exception: " << exceptionInfo.msg; if ( exceptionInfo.code ) s << " code:" << exceptionInfo.code; } s << " numYields:" << curop.numYields(); s << " "; curop.lockStat().report( s ); OPDEBUG_TOSTRING_HELP( nreturned ); if ( responseLength > 0 ) s << " reslen:" << responseLength; s << " " << executionTime << "ms"; return s.str(); }