summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHai-Kinh Hoang <haikinh.hoang@mongodb.com>2016-08-10 10:57:32 -0400
committerHai-Kinh Hoang <haikinh.hoang@mongodb.com>2016-08-17 14:54:58 -0400
commitc267c7ad3573c82e9b463cc6f918e76bb921b292 (patch)
tree845209245734ed585b90a97735ca9e6f3301c403
parent7f05ff5fd7fab804d8d84397714b308adec6fe1a (diff)
downloadmongo-c267c7ad3573c82e9b463cc6f918e76bb921b292.tar.gz
SERVER-25082 Allow x509 authentication without user/subject field
-rw-r--r--jstests/ssl/x509_client.js8
-rw-r--r--src/mongo/client/authenticate.cpp16
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp18
-rw-r--r--src/mongo/shell/dbshell.cpp10
4 files changed, 35 insertions, 17 deletions
diff --git a/jstests/ssl/x509_client.js b/jstests/ssl/x509_client.js
index 7e38bd3a713..5bcc83edef9 100644
--- a/jstests/ssl/x509_client.js
+++ b/jstests/ssl/x509_client.js
@@ -70,9 +70,15 @@ function authAndTest(mongo) {
"read without login");
assert(!external.auth({user: INVALID_CLIENT_USER, mechanism: 'MONGODB-X509'}),
- "authentication with invalid user failed");
+ "authentication with invalid user should fail");
assert(external.auth({user: CLIENT_USER, mechanism: 'MONGODB-X509'}),
"authentication with valid user failed");
+ assert(external.auth({mechanism: 'MONGODB-X509'}),
+ "authentication with valid client cert and no user field failed");
+ assert(external.runCommand({authenticate: 1, mechanism: 'MONGODB-X509', user: CLIENT_USER}).ok,
+ "runCommand authentication with valid client cert and user field failed");
+ assert(external.runCommand({authenticate: 1, mechanism: 'MONGODB-X509'}).ok,
+ "runCommand authentication with valid client cert and no user field failed");
// Check that we can add a user and read data
test.createUser(
diff --git a/src/mongo/client/authenticate.cpp b/src/mongo/client/authenticate.cpp
index 7d45da9ef08..3f0320a2f4f 100644
--- a/src/mongo/client/authenticate.cpp
+++ b/src/mongo/client/authenticate.cpp
@@ -179,6 +179,11 @@ void authMongoCR(RunCommandHook runCommand, const BSONObj& params, AuthCompletio
//
AuthRequest createX509AuthCmd(const BSONObj& params, StringData clientName) {
+ if (clientName.empty()) {
+ return {ErrorCodes::AuthenticationFailed,
+ "Please enable SSL on the client-side to use the MONGODB-X509 authentication "
+ "mechanism."};
+ }
auto db = extractDBField(params);
if (!db.isOK())
return std::move(db.getStatus());
@@ -187,16 +192,11 @@ AuthRequest createX509AuthCmd(const BSONObj& params, StringData clientName) {
request.dbname = db.getValue();
std::string username;
- auto response = bsonExtractStringField(params, saslCommandUserFieldName, &username);
- if (!response.isOK())
+ auto response = bsonExtractStringFieldWithDefault(
+ params, saslCommandUserFieldName, clientName.toString(), &username);
+ if (!response.isOK()) {
return response;
-
- if (clientName.toString() == "") {
- return {ErrorCodes::AuthenticationFailed,
- "Please enable SSL on the client-side to use the MONGODB-X509 authentication "
- "mechanism."};
}
-
if (username != clientName.toString()) {
StringBuilder message;
message << "Username \"";
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index a6a9a6f4508..f6fcc301b05 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -53,6 +53,7 @@
#include "mongo/db/client.h"
#include "mongo/db/commands.h"
#include "mongo/db/jsobj.h"
+#include "mongo/db/operation_context.h"
#include "mongo/db/server_options.h"
#include "mongo/platform/random.h"
#include "mongo/stdx/memory.h"
@@ -161,8 +162,19 @@ bool CmdAuthenticate::run(OperationContext* txn,
redactForLogging(&cmdToLog);
log() << " authenticate db: " << dbname << " " << cmdToLog;
}
+ std::string mechanism = cmdObj.getStringField("mechanism");
+ if (mechanism.empty()) {
+ mechanism = "MONGODB-CR";
+ }
+ UserName user;
+ if (mechanism == "MONGODB-X509" && !cmdObj.hasField("user")) {
+ Client* client = txn->getClient();
+ auto clientName = client->session()->getX509PeerInfo().subjectName;
+ user = UserName(clientName, dbname);
+ } else {
+ user = UserName(cmdObj.getStringField("user"), dbname);
+ }
- 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
@@ -171,10 +183,6 @@ bool CmdAuthenticate::run(OperationContext* txn,
user = internalSecurity.user->getName();
}
- std::string mechanism = cmdObj.getStringField("mechanism");
- if (mechanism.empty()) {
- mechanism = "MONGODB-CR";
- }
Status status = _authenticate(txn, mechanism, user, cmdObj);
audit::logAuthentication(Client::getCurrent(), mechanism, user, status.code());
if (!status.isOK()) {
diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/dbshell.cpp
index 97f80abeb5e..243bdd187ef 100644
--- a/src/mongo/shell/dbshell.cpp
+++ b/src/mongo/shell/dbshell.cpp
@@ -647,7 +647,8 @@ int _main(int argc, char* argv[], char** envp) {
<< escape(shellGlobalParams.gssapiServiceName) << "\";" << endl;
}
- if (!shellGlobalParams.nodb && shellGlobalParams.username.size()) {
+ if (!shellGlobalParams.nodb && (!shellGlobalParams.username.empty() ||
+ shellGlobalParams.authenticationMechanism == "MONGODB-X509")) {
authStringStream << "var username = \"" << escape(shellGlobalParams.username) << "\";"
<< endl;
if (shellGlobalParams.usingPassword) {
@@ -660,11 +661,14 @@ int _main(int argc, char* argv[], char** envp) {
authStringStream << "var authDb = db.getSiblingDB(\""
<< escape(shellGlobalParams.authenticationDatabase) << "\");" << endl;
}
- authStringStream << "authDb._authOrThrow({ " << saslCommandUserFieldName << ": username ";
+
+ authStringStream << "authDb._authOrThrow({ ";
+ if (!shellGlobalParams.username.empty()) {
+ authStringStream << saslCommandUserFieldName << ": username ";
+ }
if (shellGlobalParams.usingPassword) {
authStringStream << ", " << saslCommandPasswordFieldName << ": password ";
}
-
if (!shellGlobalParams.gssapiHostName.empty()) {
authStringStream << ", " << saslCommandServiceHostnameFieldName << ": \""
<< escape(shellGlobalParams.gssapiHostName) << '"' << endl;