summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/authentication_commands.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/commands/authentication_commands.cpp')
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp604
1 files changed, 298 insertions, 306 deletions
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index 698eb2fd406..1b499f1d31d 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -64,370 +64,362 @@
namespace mongo {
- using std::hex;
- using std::string;
- using std::stringstream;
-
- static bool _isCRAuthDisabled;
- static bool _isX509AuthDisabled;
- static const char _nonceAuthenticationDisabledMessage[] =
- "Challenge-response authentication using getnonce and authenticate commands is disabled.";
- static const char _x509AuthenticationDisabledMessage[] =
- "x.509 authentication is disabled.";
-
- void CmdAuthenticate::disableAuthMechanism(std::string authMechanism) {
- if (authMechanism == "MONGODB-CR") {
- _isCRAuthDisabled = true;
- }
- if (authMechanism == "MONGODB-X509") {
- _isX509AuthDisabled = true;
- }
+using std::hex;
+using std::string;
+using std::stringstream;
+
+static bool _isCRAuthDisabled;
+static bool _isX509AuthDisabled;
+static const char _nonceAuthenticationDisabledMessage[] =
+ "Challenge-response authentication using getnonce and authenticate commands is disabled.";
+static const char _x509AuthenticationDisabledMessage[] = "x.509 authentication is disabled.";
+
+void CmdAuthenticate::disableAuthMechanism(std::string authMechanism) {
+ if (authMechanism == "MONGODB-CR") {
+ _isCRAuthDisabled = true;
}
+ if (authMechanism == "MONGODB-X509") {
+ _isX509AuthDisabled = true;
+ }
+}
- /* authentication
-
- system.users contains
- { user : <username>, pwd : <pwd_digest>, ... }
+/* authentication
- getnonce sends nonce to client
+ system.users contains
+ { user : <username>, pwd : <pwd_digest>, ... }
- client then sends { authenticate:1, nonce64:<nonce_str>, user:<username>, key:<key> }
+ getnonce sends nonce to client
- where <key> is md5(<nonce_str><username><pwd_digest_str>) as a string
- */
+ client then sends { authenticate:1, nonce64:<nonce_str>, user:<username>, key:<key> }
- class CmdGetNonce : public Command {
- public:
- CmdGetNonce() :
- Command("getnonce"),
- _random(SecureRandom::create()) {
- }
+ where <key> is md5(<nonce_str><username><pwd_digest_str>) as a string
+*/
- virtual bool slaveOk() const {
- return true;
- }
- void help(stringstream& h) const { h << "internal"; }
- virtual bool isWriteCommandForConfigServer() const { return false; }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {} // No auth required
- bool run(OperationContext* txn,
- const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
- nonce64 n = getNextNonce();
- stringstream ss;
- ss << hex << n;
- result.append("nonce", ss.str() );
- AuthenticationSession::set(
- ClientBasic::getCurrent(),
- stdx::make_unique<MongoAuthenticationSession>(n));
- return true;
- }
+class CmdGetNonce : public Command {
+public:
+ CmdGetNonce() : Command("getnonce"), _random(SecureRandom::create()) {}
- private:
- nonce64 getNextNonce() {
- stdx::lock_guard<SimpleMutex> lk(_randMutex);
- return _random->nextInt64();
- }
+ virtual bool slaveOk() const {
+ return true;
+ }
+ void help(stringstream& h) const {
+ h << "internal";
+ }
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {} // No auth required
+ bool run(OperationContext* txn,
+ const string&,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ nonce64 n = getNextNonce();
+ stringstream ss;
+ ss << hex << n;
+ result.append("nonce", ss.str());
+ AuthenticationSession::set(ClientBasic::getCurrent(),
+ stdx::make_unique<MongoAuthenticationSession>(n));
+ return true;
+ }
- SimpleMutex _randMutex; // Synchronizes accesses to _random.
- std::unique_ptr<SecureRandom> _random;
- } cmdGetNonce;
+private:
+ nonce64 getNextNonce() {
+ stdx::lock_guard<SimpleMutex> lk(_randMutex);
+ return _random->nextInt64();
+ }
- void CmdAuthenticate::redactForLogging(mutablebson::Document* cmdObj) {
- namespace mmb = mutablebson;
- static const int numRedactedFields = 2;
- static const char* redactedFields[numRedactedFields] = { "key", "nonce" };
- for (int i = 0; i < numRedactedFields; ++i) {
- for (mmb::Element element = mmb::findFirstChildNamed(cmdObj->root(), redactedFields[i]);
- element.ok();
- element = mmb::findElementNamed(element.rightSibling(), redactedFields[i])) {
+ SimpleMutex _randMutex; // Synchronizes accesses to _random.
+ std::unique_ptr<SecureRandom> _random;
+} cmdGetNonce;
- element.setValueString("xxx");
- }
+void CmdAuthenticate::redactForLogging(mutablebson::Document* cmdObj) {
+ namespace mmb = mutablebson;
+ static const int numRedactedFields = 2;
+ static const char* redactedFields[numRedactedFields] = {"key", "nonce"};
+ for (int i = 0; i < numRedactedFields; ++i) {
+ for (mmb::Element element = mmb::findFirstChildNamed(cmdObj->root(), redactedFields[i]);
+ element.ok();
+ element = mmb::findElementNamed(element.rightSibling(), redactedFields[i])) {
+ element.setValueString("xxx");
}
}
+}
- bool CmdAuthenticate::run(OperationContext* txn, const string& dbname,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
-
- if (!serverGlobalParams.quiet) {
- mutablebson::Document cmdToLog(cmdObj, mutablebson::Document::kInPlaceDisabled);
- redactForLogging(&cmdToLog);
- log() << " authenticate db: " << dbname << " " << cmdToLog;
- }
+bool CmdAuthenticate::run(OperationContext* txn,
+ const string& dbname,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ if (!serverGlobalParams.quiet) {
+ mutablebson::Document cmdToLog(cmdObj, mutablebson::Document::kInPlaceDisabled);
+ redactForLogging(&cmdToLog);
+ log() << " authenticate db: " << dbname << " " << cmdToLog;
+ }
- 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();
- }
+ 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";
+ std::string mechanism = cmdObj.getStringField("mechanism");
+ if (mechanism.empty()) {
+ mechanism = "MONGODB-CR";
+ }
+ Status status = _authenticate(txn, mechanism, user, cmdObj);
+ audit::logAuthentication(ClientBasic::getCurrent(), mechanism, user, status.code());
+ if (!status.isOK()) {
+ if (!serverGlobalParams.quiet) {
+ log() << "Failed to authenticate " << user << " with mechanism " << mechanism << ": "
+ << status;
}
- Status status = _authenticate(txn, mechanism, user, cmdObj);
- audit::logAuthentication(ClientBasic::getCurrent(),
- mechanism,
- user,
- status.code());
- if (!status.isOK()) {
- if (!serverGlobalParams.quiet) {
- 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;
+ 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);
}
- result.append("dbname", user.getDB());
- result.append("user", user.getUser());
- return true;
+ return false;
}
+ result.append("dbname", user.getDB());
+ result.append("user", user.getUser());
+ return true;
+}
- Status CmdAuthenticate::_authenticate(OperationContext* txn,
- const std::string& mechanism,
- const UserName& user,
- const BSONObj& cmdObj) {
-
- if (mechanism == "MONGODB-CR") {
- return _authenticateCR(txn, user, cmdObj);
- }
+Status CmdAuthenticate::_authenticate(OperationContext* txn,
+ const std::string& mechanism,
+ const UserName& user,
+ const BSONObj& cmdObj) {
+ if (mechanism == "MONGODB-CR") {
+ return _authenticateCR(txn, user, cmdObj);
+ }
#ifdef MONGO_CONFIG_SSL
- if (mechanism == "MONGODB-X509") {
- return _authenticateX509(txn, user, cmdObj);
- }
-#endif
- return Status(ErrorCodes::BadValue, "Unsupported mechanism: " + mechanism);
+ if (mechanism == "MONGODB-X509") {
+ return _authenticateX509(txn, user, cmdObj);
}
+#endif
+ return Status(ErrorCodes::BadValue, "Unsupported mechanism: " + mechanism);
+}
- Status CmdAuthenticate::_authenticateCR(
- OperationContext* txn, const UserName& user, const BSONObj& cmdObj) {
-
- if (user == internalSecurity.user->getName() &&
- serverGlobalParams.clusterAuthMode.load() ==
- ServerGlobalParams::ClusterAuthMode_x509) {
- return Status(ErrorCodes::AuthenticationFailed,
- "Mechanism x509 is required for internal cluster authentication");
- }
+Status CmdAuthenticate::_authenticateCR(OperationContext* txn,
+ const UserName& user,
+ const BSONObj& cmdObj) {
+ if (user == internalSecurity.user->getName() &&
+ serverGlobalParams.clusterAuthMode.load() == ServerGlobalParams::ClusterAuthMode_x509) {
+ return Status(ErrorCodes::AuthenticationFailed,
+ "Mechanism x509 is required for internal cluster authentication");
+ }
- if (_isCRAuthDisabled) {
- // 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, _nonceAuthenticationDisabledMessage);
- }
+ if (_isCRAuthDisabled) {
+ // 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, _nonceAuthenticationDisabledMessage);
}
+ }
- 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");
- }
+ string key = cmdObj.getStringField("key");
+ string received_nonce = cmdObj.getStringField("nonce");
- stringstream digestBuilder;
+ if (user.getUser().empty() || key.empty() || received_nonce.empty()) {
+ sleepmillis(10);
+ return Status(ErrorCodes::ProtocolError,
+ "field missing/wrong type in received authenticate command");
+ }
- {
- ClientBasic *client = ClientBasic::getCurrent();
- std::unique_ptr<AuthenticationSession> session;
- AuthenticationSession::swap(client, session);
- if (!session || session->getType() != AuthenticationSession::SESSION_TYPE_MONGO) {
+ stringstream digestBuilder;
+
+ {
+ ClientBasic* client = ClientBasic::getCurrent();
+ std::unique_ptr<AuthenticationSession> session;
+ AuthenticationSession::swap(client, 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::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.");
- }
+ return Status(ErrorCodes::AuthenticationFailed, "Received wrong nonce.");
}
}
+ }
- User* userObj;
- Status status = getGlobalAuthorizationManager()->acquireUser(txn, 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);
-
- if (pwd.empty()) {
- return Status(ErrorCodes::AuthenticationFailed,
- "MONGODB-CR credentials missing in the user document");
- }
+ User* userObj;
+ Status status = getGlobalAuthorizationManager()->acquireUser(txn, 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();
+ if (pwd.empty()) {
+ return Status(ErrorCodes::AuthenticationFailed,
+ "MONGODB-CR credentials missing in the user document");
+ }
- md5_state_t st;
- md5_init(&st);
- md5_append(&st, (const md5_byte_t *) done.c_str(), done.size());
- md5_finish(&st, d);
- }
+ md5digest d;
+ {
+ digestBuilder << user.getUser() << pwd;
+ string done = digestBuilder.str();
- string computed = digestToString( d );
+ md5_state_t st;
+ md5_init(&st);
+ md5_append(&st, (const md5_byte_t*)done.c_str(), done.size());
+ md5_finish(&st, d);
+ }
- if ( key != computed ) {
- return Status(ErrorCodes::AuthenticationFailed, "key mismatch");
- }
+ string computed = digestToString(d);
- AuthorizationSession* authorizationSession =
- AuthorizationSession::get(ClientBasic::getCurrent());
- status = authorizationSession->addAndAuthorizeUser(txn, user);
- if (!status.isOK()) {
- return status;
- }
+ if (key != computed) {
+ return Status(ErrorCodes::AuthenticationFailed, "key mismatch");
+ }
- return Status::OK();
+ AuthorizationSession* authorizationSession =
+ AuthorizationSession::get(ClientBasic::getCurrent());
+ status = authorizationSession->addAndAuthorizeUser(txn, user);
+ if (!status.isOK()) {
+ return status;
}
+ return Status::OK();
+}
+
#ifdef MONGO_CONFIG_SSL
- void canonicalizeClusterDN(std::vector<std::string>* dn) {
- // remove all RDNs we don't care about
- for (size_t i=0; i<dn->size(); i++) {
- std::string& comp = dn->at(i);
- boost::algorithm::trim(comp);
- if (!mongoutils::str::startsWith(comp.c_str(), "DC=") &&
- !mongoutils::str::startsWith(comp.c_str(), "O=") &&
- !mongoutils::str::startsWith(comp.c_str(), "OU=")) {
- dn->erase(dn->begin()+i);
- i--;
- }
+void canonicalizeClusterDN(std::vector<std::string>* dn) {
+ // remove all RDNs we don't care about
+ for (size_t i = 0; i < dn->size(); i++) {
+ std::string& comp = dn->at(i);
+ boost::algorithm::trim(comp);
+ if (!mongoutils::str::startsWith(comp.c_str(), "DC=") &&
+ !mongoutils::str::startsWith(comp.c_str(), "O=") &&
+ !mongoutils::str::startsWith(comp.c_str(), "OU=")) {
+ dn->erase(dn->begin() + i);
+ i--;
}
- std::stable_sort(dn->begin(), dn->end());
}
+ 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, ",");
+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);
+ canonicalizeClusterDN(&clientRDN);
+ canonicalizeClusterDN(&serverRDN);
- if (clientRDN.size() == 0 || clientRDN.size() != serverRDN.size()) {
- return false;
- }
+ 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;
- }
+ for (size_t i = 0; i < serverRDN.size(); i++) {
+ if (clientRDN[i] != serverRDN[i]) {
+ return false;
}
- return true;
}
-
- Status CmdAuthenticate::_authenticateX509(
- OperationContext* txn, const UserName& user, const BSONObj& cmdObj) {
- if (!getSSLManager()) {
- return Status(ErrorCodes::ProtocolError,
- "SSL support is required for the MONGODB-X509 mechanism.");
- }
- if(user.getDB() != "$external") {
- return Status(ErrorCodes::ProtocolError,
- "X.509 authentication must always use the $external database.");
- }
+ return true;
+}
- ClientBasic *client = ClientBasic::getCurrent();
- AuthorizationSession* authorizationSession = AuthorizationSession::get(client);
- std::string subjectName = client->port()->getX509SubjectName();
+Status CmdAuthenticate::_authenticateX509(OperationContext* txn,
+ const UserName& user,
+ const BSONObj& cmdObj) {
+ if (!getSSLManager()) {
+ return Status(ErrorCodes::ProtocolError,
+ "SSL support is required for the MONGODB-X509 mechanism.");
+ }
+ if (user.getDB() != "$external") {
+ return Status(ErrorCodes::ProtocolError,
+ "X.509 authentication must always use the $external database.");
+ }
- if (!getSSLManager()->getSSLConfiguration().hasCA) {
- return Status(ErrorCodes::AuthenticationFailed,
- "Unable to verify x.509 certificate, as no CA has been provided.");
- }
- else if (user.getUser() != subjectName) {
- return Status(ErrorCodes::AuthenticationFailed,
- "There is no x.509 client certificate matching the user.");
+ ClientBasic* client = ClientBasic::getCurrent();
+ AuthorizationSession* authorizationSession = AuthorizationSession::get(client);
+ std::string subjectName = client->port()->getX509SubjectName();
+
+ if (!getSSLManager()->getSSLConfiguration().hasCA) {
+ return Status(ErrorCodes::AuthenticationFailed,
+ "Unable to verify x.509 certificate, as no CA has been provided.");
+ } else if (user.getUser() != subjectName) {
+ return Status(ErrorCodes::AuthenticationFailed,
+ "There is no x.509 client certificate matching the user.");
+ } else {
+ std::string srvSubjectName = getSSLManager()->getSSLConfiguration().serverSubjectName;
+
+ // Handle internal cluster member auth, only applies to server-server connections
+ 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 "
+ "can only be used for cluster authentication, not client "
+ "authentication. The current configuration does not allow "
+ "x.509 cluster authentication, check the --clusterAuthMode flag");
+ }
+ authorizationSession->grantInternalAuthorization();
}
+ // Handle normal client authentication, only applies to client-server connections
else {
- std::string srvSubjectName = getSSLManager()->getSSLConfiguration().serverSubjectName;
-
- // Handle internal cluster member auth, only applies to server-server connections
- 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 "
- "can only be used for cluster authentication, not client "
- "authentication. The current configuration does not allow "
- "x.509 cluster authentication, check the --clusterAuthMode flag");
- }
- authorizationSession->grantInternalAuthorization();
+ if (_isX509AuthDisabled) {
+ return Status(ErrorCodes::BadValue, _x509AuthenticationDisabledMessage);
}
- // Handle normal client authentication, only applies to client-server connections
- else {
- if (_isX509AuthDisabled) {
- return Status(ErrorCodes::BadValue,
- _x509AuthenticationDisabledMessage);
- }
- Status status = authorizationSession->addAndAuthorizeUser(txn, user);
- if (!status.isOK()) {
- return status;
- }
+ Status status = authorizationSession->addAndAuthorizeUser(txn, user);
+ if (!status.isOK()) {
+ return status;
}
- return Status::OK();
}
+ return Status::OK();
}
+}
#endif
- CmdAuthenticate cmdAuthenticate;
+CmdAuthenticate cmdAuthenticate;
- class CmdLogout : public Command {
- public:
- virtual bool slaveOk() const {
- return true;
- }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {} // No auth required
- void help(stringstream& h) const { h << "de-authenticate"; }
- virtual bool isWriteCommandForConfigServer() const { return false; }
- CmdLogout() : Command("logout") {}
- bool run(OperationContext* txn, const string& dbname,
- BSONObj& cmdObj,
- int options,
- string& errmsg,
- BSONObjBuilder& result) {
- AuthorizationSession* authSession =
- AuthorizationSession::get(ClientBasic::getCurrent());
- authSession->logoutDatabase(dbname);
- if (Command::testCommandsEnabled && dbname == "admin") {
- // Allows logging out as the internal user against the admin database, however
- // this actually logs out of the local database as well. 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 logout as the internal user
- // without this).
- authSession->logoutDatabase("local");
- }
- return true;
+class CmdLogout : public Command {
+public:
+ virtual bool slaveOk() const {
+ return true;
+ }
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {} // No auth required
+ void help(stringstream& h) const {
+ h << "de-authenticate";
+ }
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+ CmdLogout() : Command("logout") {}
+ bool run(OperationContext* txn,
+ const string& dbname,
+ BSONObj& cmdObj,
+ int options,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ AuthorizationSession* authSession = AuthorizationSession::get(ClientBasic::getCurrent());
+ authSession->logoutDatabase(dbname);
+ if (Command::testCommandsEnabled && dbname == "admin") {
+ // Allows logging out as the internal user against the admin database, however
+ // this actually logs out of the local database as well. 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 logout as the internal user
+ // without this).
+ authSession->logoutDatabase("local");
}
- } cmdLogout;
+ return true;
+ }
+} cmdLogout;
}