summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer T Brody <spencer@10gen.com>2012-11-16 20:44:21 -0500
committerSpencer T Brody <spencer@10gen.com>2012-11-20 13:20:42 -0500
commit85abee65027409182c318d22aa79fd224e6b311c (patch)
treeabd60bfe2ceb5968eabc6d7212ff288108f5564b
parent2f433ece1bb9408f949527e0d95ad6db0d5ef7c5 (diff)
downloadmongo-85abee65027409182c318d22aa79fd224e6b311c.tar.gz
SERVER-6591 Fix localhost auth exception in sharded systems
-rw-r--r--src/SConscript.client3
-rw-r--r--src/mongo/SConscript10
-rw-r--r--src/mongo/client/authentication_table.h3
-rw-r--r--src/mongo/client/authentication_table_client.cpp27
-rw-r--r--src/mongo/client/authentication_table_common.cpp (renamed from src/mongo/client/authentication_table.cpp)7
-rw-r--r--src/mongo/client/authentication_table_server.cpp30
-rw-r--r--src/mongo/client/clientAndShell.cpp4
-rw-r--r--src/mongo/db/client.cpp4
-rw-r--r--src/mongo/db/client_common.h1
-rw-r--r--src/mongo/db/security.cpp4
-rwxr-xr-xsrc/mongo/db/security.h1
-rw-r--r--src/mongo/s/client_info.cpp9
-rw-r--r--src/mongo/s/client_info.h3
-rw-r--r--src/mongo/s/security.cpp38
14 files changed, 132 insertions, 12 deletions
diff --git a/src/SConscript.client b/src/SConscript.client
index 81055293af1..aded23f5b9b 100644
--- a/src/SConscript.client
+++ b/src/SConscript.client
@@ -27,7 +27,8 @@ clientSource = [
'mongo/base/status.cpp',
'mongo/bson/oid.cpp',
'mongo/buildinfo.cpp',
- "mongo/client/authentication_table.cpp",
+ "mongo/client/authentication_table_common.cpp",
+ "mongo/client/authentication_table_client.cpp",
'mongo/client/clientAndShell.cpp',
'mongo/client/clientOnly.cpp',
'mongo/client/connection_factory.cpp',
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index ecfe672e74a..f5d9a803f70 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -126,7 +126,7 @@ commonFiles = [ "pch.cpp",
"util/net/listen.cpp",
"util/startup_test.cpp",
"util/version.cpp",
- "client/authentication_table.cpp",
+ "client/authentication_table_common.cpp",
"client/connpool.cpp",
"client/dbclient.cpp",
"client/dbclient_rs.cpp",
@@ -182,6 +182,7 @@ env.StaticLibrary('mongocommon', commonFiles,
SYSLIBDEPS=commonSysLibdeps)
env.StaticLibrary("coredb", [
+ "client/authentication_table_server.cpp",
"client/parallel.cpp",
"db/commands.cpp",
"db/commands/fail_point_cmd.cpp",
@@ -564,7 +565,12 @@ mongos = env.Program(
"mongodandmongos"] + env['MODULE_LIBDEPS_MONGOS'])
env.Install( '#/', mongos )
-env.Library("clientandshell", ["client/clientAndShell.cpp"], LIBDEPS=["mongocommon", "defaultversion", "gridfs", "notmongodormongos"])
+env.Library("clientandshell", ["client/authentication_table_client.cpp",
+ "client/clientAndShell.cpp"],
+ LIBDEPS=["mongocommon",
+ "defaultversion",
+ "gridfs",
+ "notmongodormongos"])
env.Library("allclient", "client/clientOnly.cpp", LIBDEPS=["clientandshell"])
if has_option( "sharedclient" ):
diff --git a/src/mongo/client/authentication_table.h b/src/mongo/client/authentication_table.h
index ddab123922d..75e7b3140b7 100644
--- a/src/mongo/client/authentication_table.h
+++ b/src/mongo/client/authentication_table.h
@@ -59,6 +59,9 @@ namespace mongo {
static const string fieldName;
private:
+
+ bool _shouldSendInternalSecurityTable() const;
+
typedef map<std::string,Auth> DBAuthMap;
DBAuthMap _dbs; // dbname -> auth
};
diff --git a/src/mongo/client/authentication_table_client.cpp b/src/mongo/client/authentication_table_client.cpp
new file mode 100644
index 00000000000..593d44616e6
--- /dev/null
+++ b/src/mongo/client/authentication_table_client.cpp
@@ -0,0 +1,27 @@
+/* Copyright 2012 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "mongo/client/authentication_table.h"
+#include "mongo/db/client_common.h"
+#include "mongo/db/security.h"
+
+namespace mongo {
+
+ bool AuthenticationTable::_shouldSendInternalSecurityTable() const {
+ return false;
+ }
+
+}
diff --git a/src/mongo/client/authentication_table.cpp b/src/mongo/client/authentication_table_common.cpp
index 9af6de4f5c7..ca6eda1a26f 100644
--- a/src/mongo/client/authentication_table.cpp
+++ b/src/mongo/client/authentication_table_common.cpp
@@ -93,7 +93,12 @@ namespace mongo {
cmdWithAuth.append(e);
}
- cmdWithAuth.append( fieldName, toBSON() );
+ if (_shouldSendInternalSecurityTable()) {
+ cmdWithAuth.append(fieldName, internalSecurityAuthenticationTable.toBSON());
+ }
+ else {
+ cmdWithAuth.append(fieldName, toBSON());
+ }
return cmdWithAuth.obj();
}
diff --git a/src/mongo/client/authentication_table_server.cpp b/src/mongo/client/authentication_table_server.cpp
new file mode 100644
index 00000000000..dc69a5629ea
--- /dev/null
+++ b/src/mongo/client/authentication_table_server.cpp
@@ -0,0 +1,30 @@
+/* Copyright 2012 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "mongo/client/authentication_table.h"
+#include "mongo/db/client_common.h"
+#include "mongo/db/security.h"
+
+namespace mongo {
+
+ bool AuthenticationTable::_shouldSendInternalSecurityTable() const {
+ if (!ClientBasic::hasCurrent() || !ClientBasic::getCurrent()->getAuthenticationInfo()) {
+ return false;
+ }
+ return ClientBasic::getCurrent()->getAuthenticationInfo()->isSpecialLocalhostAdmin();
+ }
+
+}
diff --git a/src/mongo/client/clientAndShell.cpp b/src/mongo/client/clientAndShell.cpp
index 2fff7e4652b..dd5474aa9a2 100644
--- a/src/mongo/client/clientAndShell.cpp
+++ b/src/mongo/client/clientAndShell.cpp
@@ -82,4 +82,8 @@ namespace mongo {
ClientBasic* ClientBasic::getCurrent() {
return 0;
}
+
+ bool ClientBasic::hasCurrent() {
+ return false;
+ }
}
diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp
index db9bd0b6665..a30370e7585 100644
--- a/src/mongo/db/client.cpp
+++ b/src/mongo/db/client.cpp
@@ -416,6 +416,10 @@ namespace mongo {
}
}
+ bool ClientBasic::hasCurrent() {
+ return currentClient.get();
+ }
+
ClientBasic* ClientBasic::getCurrent() {
return currentClient.get();
}
diff --git a/src/mongo/db/client_common.h b/src/mongo/db/client_common.h
index dd719ccb1b9..86c8039103b 100644
--- a/src/mongo/db/client_common.h
+++ b/src/mongo/db/client_common.h
@@ -72,6 +72,7 @@ namespace mongo {
AbstractMessagingPort * port() const { return _messagingPort; }
static ClientBasic* getCurrent();
+ static bool hasCurrent();
protected:
ClientBasic(AbstractMessagingPort* messagingPort) : _messagingPort(messagingPort) {}
diff --git a/src/mongo/db/security.cpp b/src/mongo/db/security.cpp
index 0913bff6186..25a3d877a25 100644
--- a/src/mongo/db/security.cpp
+++ b/src/mongo/db/security.cpp
@@ -73,6 +73,10 @@ namespace mongo {
_checkLocalHostSpecialAdmin();
}
+ bool AuthenticationInfo::isSpecialLocalhostAdmin() const {
+ return _isLocalHostAndLocalHostIsAuthorizedForAll;
+ }
+
void AuthenticationInfo::_checkLocalHostSpecialAdmin() {
if ( ! _isLocalHost )
return;
diff --git a/src/mongo/db/security.h b/src/mongo/db/security.h
index cab945d55d1..a7f01a98c5b 100755
--- a/src/mongo/db/security.h
+++ b/src/mongo/db/security.h
@@ -43,6 +43,7 @@ namespace mongo {
}
~AuthenticationInfo() {}
bool isLocalHost() const { return _isLocalHost; } // why are you calling this? makes no sense to be externalized
+ bool isSpecialLocalhostAdmin() const;
// -- modifiers ----
diff --git a/src/mongo/s/client_info.cpp b/src/mongo/s/client_info.cpp
index 59b5a89f602..9b1f96ceb7a 100644
--- a/src/mongo/s/client_info.cpp
+++ b/src/mongo/s/client_info.cpp
@@ -74,6 +74,7 @@ namespace mongo {
_cur = _prev;
_prev = temp;
_cur->clear();
+ _ai.startRequest();
}
void ClientInfo::_setupAuth() {
@@ -124,6 +125,14 @@ namespace mongo {
return info;
}
+ bool ClientInfo::exists() {
+ return _tlInfo.get();
+ }
+
+ bool ClientBasic::hasCurrent() {
+ return ClientInfo::exists();
+ }
+
ClientBasic* ClientBasic::getCurrent() {
return ClientInfo::get();
}
diff --git a/src/mongo/s/client_info.h b/src/mongo/s/client_info.h
index 8e0ed86f4f7..e71bc53e139 100644
--- a/src/mongo/s/client_info.h
+++ b/src/mongo/s/client_info.h
@@ -101,6 +101,9 @@ namespace mongo {
void noAutoSplit() { _autoSplitOk = false; }
+ // Returns whether or not a ClientInfo for this thread has already been created and stored
+ // in _tlInfo.
+ static bool exists();
// Gets the ClientInfo object for this thread from _tlInfo. If no ClientInfo object exists
// yet for this thread, it creates one.
static ClientInfo * get(AbstractMessagingPort* messagingPort = NULL);
diff --git a/src/mongo/s/security.cpp b/src/mongo/s/security.cpp
index c1089867b76..e7ccbdee554 100644
--- a/src/mongo/s/security.cpp
+++ b/src/mongo/s/security.cpp
@@ -65,14 +65,28 @@ namespace mongo {
return true;
}
+ void AuthenticationInfo::startRequest() {
+ _checkLocalHostSpecialAdmin();
+ }
+
void AuthenticationInfo::setIsALocalHostConnectionWithSpecialAuthPowers() {
verify(!_isLocalHost);
_isLocalHost = true;
+ _isLocalHostAndLocalHostIsAuthorizedForAll = true;
+ _checkLocalHostSpecialAdmin();
}
bool AuthenticationInfo::_isAuthorizedSpecialChecks( const string& dbname ) const {
- if ( !_isLocalHost ) {
- return false;
+ return isSpecialLocalhostAdmin();
+ }
+
+ bool AuthenticationInfo::isSpecialLocalhostAdmin() const {
+ return _isLocalHostAndLocalHostIsAuthorizedForAll;
+ }
+
+ void AuthenticationInfo::_checkLocalHostSpecialAdmin() {
+ if (!_isLocalHost || !_isLocalHostAndLocalHostIsAuthorizedForAll) {
+ return;
}
string adminNs = "admin.system.users";
@@ -80,8 +94,15 @@ namespace mongo {
DBConfigPtr config = grid.getDBConfig( adminNs );
Shard s = config->getShard( adminNs );
- ShardConnection conn( s, adminNs );
- BSONObj result = conn->findOne("admin.system.users", Query());
+ //
+ // Note: The connection mechanism here is *not* ideal, and should not be used elsewhere.
+ // It is safe in this particular case because the admin database is always on the config
+ // server and does not move.
+ //
+ scoped_ptr<ScopedDbConnection> conn(
+ ScopedDbConnection::getInternalScopedDbConnection(s.getConnString(), 30.0));
+
+ BSONObj result = (*conn)->findOne("admin.system.users", Query());
if( result.isEmpty() ) {
if( ! _warned ) {
// you could get a few of these in a race, but that's ok
@@ -91,13 +112,14 @@ namespace mongo {
// Must return conn to pool
// TODO: Check for errors during findOne(), or just let the conn die?
- conn.done();
- return true;
+ conn->done();
+ _isLocalHostAndLocalHostIsAuthorizedForAll = true;
+ return;
}
// Must return conn to pool
- conn.done();
- return false;
+ conn->done();
+ _isLocalHostAndLocalHostIsAuthorizedForAll = false;
}
bool CmdLogout::run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {