diff options
Diffstat (limited to 'src/mongo/db/auth')
-rw-r--r-- | src/mongo/db/auth/action_types.txt | 1 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_session.cpp | 30 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_session.h | 22 | ||||
-rw-r--r-- | src/mongo/db/auth/user_management_commands_parser.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/auth/user_management_commands_parser.h | 11 | ||||
-rw-r--r-- | src/mongo/db/auth/user_name.h | 76 | ||||
-rw-r--r-- | src/mongo/db/auth/user_set.cpp | 24 | ||||
-rw-r--r-- | src/mongo/db/auth/user_set.h | 33 | ||||
-rw-r--r-- | src/mongo/db/auth/user_set_test.cpp | 4 |
9 files changed, 166 insertions, 43 deletions
diff --git a/src/mongo/db/auth/action_types.txt b/src/mongo/db/auth/action_types.txt index 9c06abbc2fb..ecf7bf9ad87 100644 --- a/src/mongo/db/auth/action_types.txt +++ b/src/mongo/db/auth/action_types.txt @@ -59,6 +59,7 @@ "grantRolesToUser", # Not used for permissions checks, but to id the event in logs. "handshake", "hostInfo", +"impersonate", "indexStats", "inprog", "insert", diff --git a/src/mongo/db/auth/authorization_session.cpp b/src/mongo/db/auth/authorization_session.cpp index bbab218f0b1..a9f0887253e 100644 --- a/src/mongo/db/auth/authorization_session.cpp +++ b/src/mongo/db/auth/authorization_session.cpp @@ -51,7 +51,8 @@ namespace { const std::string ADMIN_DBNAME = "admin"; } // namespace - AuthorizationSession::AuthorizationSession(AuthzSessionExternalState* externalState) { + AuthorizationSession::AuthorizationSession(AuthzSessionExternalState* externalState) + : _impersonationFlag(false) { _externalState.reset(externalState); } @@ -78,6 +79,9 @@ namespace { return status; } + // If there are any users in the impersonate list, clear them. + clearImpersonatedUserNames(); + // Calling add() on the UserSet may return a user that was replaced because it was from the // same database. User* replacedUser = _authenticatedUsers.add(user); @@ -97,19 +101,20 @@ namespace { } void AuthorizationSession::logoutDatabase(const std::string& dbname) { + clearImpersonatedUserNames(); User* removedUser = _authenticatedUsers.removeByDBName(dbname); if (removedUser) { getAuthorizationManager().releaseUser(removedUser); } } - UserSet::NameIterator AuthorizationSession::getAuthenticatedUserNames() { + UserNameIterator AuthorizationSession::getAuthenticatedUserNames() { return _authenticatedUsers.getNames(); } std::string AuthorizationSession::getAuthenticatedUserNamesToken() { std::string ret; - for (UserSet::NameIterator nameIter = getAuthenticatedUserNames(); + for (UserNameIterator nameIter = getAuthenticatedUserNames(); nameIter.more(); nameIter.next()) { ret += '\0'; // Using a NUL byte which isn't valid in usernames to separate them. @@ -475,4 +480,23 @@ namespace { return false; } + void AuthorizationSession::setImpersonatedUserNames(const std::vector<UserName>& names) { + _impersonatedUserNames = names; + _impersonationFlag = true; + } + + // Clear the vector of impersonated UserNames. + void AuthorizationSession::clearImpersonatedUserNames() { + _impersonatedUserNames.clear(); + _impersonationFlag = false; + } + + UserNameIterator AuthorizationSession::getImpersonatedUserNames() const { + return makeUserNameIteratorForContainer(_impersonatedUserNames); + } + + bool AuthorizationSession::isImpersonating() const { + return _impersonationFlag; + } + } // namespace mongo diff --git a/src/mongo/db/auth/authorization_session.h b/src/mongo/db/auth/authorization_session.h index c9c9178791a..3a64792b611 100644 --- a/src/mongo/db/auth/authorization_session.h +++ b/src/mongo/db/auth/authorization_session.h @@ -89,7 +89,7 @@ namespace mongo { size_t getNumAuthenticatedUsers(); // Gets an iterator over the names of all authenticated users stored in this manager. - UserSet::NameIterator getAuthenticatedUserNames(); + UserNameIterator getAuthenticatedUserNames(); // Returns a string representing all logged-in users on the current session. // WARNING: this string will contain NUL bytes so don't call c_str()! @@ -180,6 +180,21 @@ namespace mongo { // isAuthorizedForActionsOnResource(ResourcePattern::forExactNamespace(ns), actions). bool isAuthorizedForActionsOnNamespace(const NamespaceString& ns, const ActionSet& actions); + // Replaces the vector of UserNames that a system user is impersonating with a new vector. + // The auditing system adds these to each audit record in the log. + void setImpersonatedUserNames(const std::vector<UserName>& names); + + // Returns an iterator to a vector of impersonated usernames. + UserNameIterator getImpersonatedUserNames() const; + + // Clears the vector of impersonated UserNames. + void clearImpersonatedUserNames(); + + // Tells whether impersonation is active or not. This state is set when + // setImpersonatedUserNames is called and cleared when clearImpersonatedUserNames is + // called. + bool isImpersonating() const; + private: // If any users authenticated on this session are marked as invalid this updates them with @@ -195,6 +210,11 @@ namespace mongo { // All Users who have been authenticated on this connection UserSet _authenticatedUsers; + + // A vector of impersonated UserNames. These are used in the auditing system. + // They are not used for authz checks. + std::vector<UserName> _impersonatedUserNames; + bool _impersonationFlag; }; } // namespace mongo diff --git a/src/mongo/db/auth/user_management_commands_parser.cpp b/src/mongo/db/auth/user_management_commands_parser.cpp index 002880c2050..61023fe6a25 100644 --- a/src/mongo/db/auth/user_management_commands_parser.cpp +++ b/src/mongo/db/auth/user_management_commands_parser.cpp @@ -137,7 +137,7 @@ namespace auth { return Status::OK(); } - Status _parseUserNamesFromBSONArray(const BSONArray& usersArray, + Status parseUserNamesFromBSONArray(const BSONArray& usersArray, const StringData& dbname, std::vector<UserName>* parsedUserNames) { return _parseNamesFromBSONArray(usersArray, @@ -359,9 +359,9 @@ namespace auth { if (cmdObj["usersInfo"].numberInt() == 1) { parsedArgs->allForDB = true; } else if (cmdObj["usersInfo"].type() == Array) { - status = _parseUserNamesFromBSONArray(BSONArray(cmdObj["usersInfo"].Obj()), - dbname, - &parsedArgs->userNames); + status = parseUserNamesFromBSONArray(BSONArray(cmdObj["usersInfo"].Obj()), + dbname, + &parsedArgs->userNames); if (!status.isOK()) { return status; } diff --git a/src/mongo/db/auth/user_management_commands_parser.h b/src/mongo/db/auth/user_management_commands_parser.h index d5e10f7574d..befeb2731ba 100644 --- a/src/mongo/db/auth/user_management_commands_parser.h +++ b/src/mongo/db/auth/user_management_commands_parser.h @@ -194,7 +194,7 @@ namespace auth { PrivilegeVector* parsedPrivileges); /** - * Takes a BSONArray of name,source pair documents, parses that array and returns (via the + * Takes a BSONArray of name,db pair documents, parses that array and returns (via the * output param parsedRoleNames) a list of the role names in the input array. * Performs syntactic validation of "rolesArray", only. */ @@ -202,5 +202,14 @@ namespace auth { const StringData& dbname, std::vector<RoleName>* parsedRoleNames); + /** + * Takes a BSONArray of name,db pair documents, parses that array and returns (via the + * output param parsedUserNames) a list of the usernames in the input array. + * Performs syntactic validation of "usersArray", only. + */ + Status parseUserNamesFromBSONArray(const BSONArray& usersArray, + const StringData& dbname, + std::vector<UserName>* parsedUserNames); + } // namespace auth } // namespace mongo diff --git a/src/mongo/db/auth/user_name.h b/src/mongo/db/auth/user_name.h index acee87f8ada..9104fded846 100644 --- a/src/mongo/db/auth/user_name.h +++ b/src/mongo/db/auth/user_name.h @@ -18,6 +18,9 @@ #include <iosfwd> #include <string> +#include <boost/scoped_ptr.hpp> + +#include "mongo/base/disallow_copying.h" #include "mongo/base/string_data.h" namespace mongo { @@ -71,4 +74,77 @@ namespace mongo { std::ostream& operator<<(std::ostream& os, const UserName& name); + /** + * Iterator over an unspecified container of UserName objects. + */ + class UserNameIterator { + public: + class Impl { + MONGO_DISALLOW_COPYING(Impl); + public: + Impl() {}; + virtual ~Impl() {}; + static Impl* clone(Impl* orig) { return orig ? orig->doClone(): NULL; } + virtual bool more() const = 0; + virtual const UserName& get() const = 0; + + virtual const UserName& next() = 0; + + private: + virtual Impl* doClone() const = 0; + }; + + UserNameIterator() : _impl(NULL) {} + UserNameIterator(const UserNameIterator& other) : _impl(Impl::clone(other._impl.get())) {} + explicit UserNameIterator(Impl* impl) : _impl(impl) {} + + UserNameIterator& operator=(const UserNameIterator& other) { + _impl.reset(Impl::clone(other._impl.get())); + return *this; + } + + bool more() const { return _impl.get() && _impl->more(); } + const UserName& get() const { return _impl->get(); } + + const UserName& next() { return _impl->next(); } + + const UserName& operator*() const { return get(); } + const UserName* operator->() const { return &get(); } + + private: + boost::scoped_ptr<Impl> _impl; + }; + + + template <typename ContainerIterator> + class UserNameContainerIteratorImpl : public UserNameIterator::Impl { + MONGO_DISALLOW_COPYING(UserNameContainerIteratorImpl); + public: + UserNameContainerIteratorImpl(const ContainerIterator& begin, + const ContainerIterator& end) : + _curr(begin), _end(end) {} + virtual ~UserNameContainerIteratorImpl() {} + virtual bool more() const { return _curr != _end; } + virtual const UserName& next() { return *(_curr++); } + virtual const UserName& get() const { return *_curr; } + virtual UserNameIterator::Impl* doClone() const { + return new UserNameContainerIteratorImpl(_curr, _end); + } + + private: + ContainerIterator _curr; + ContainerIterator _end; + }; + + template <typename ContainerIterator> + UserNameIterator makeUserNameIterator(const ContainerIterator& begin, + const ContainerIterator& end) { + return UserNameIterator( new UserNameContainerIteratorImpl<ContainerIterator>(begin, end)); + } + + template <typename Container> + UserNameIterator makeUserNameIteratorForContainer(const Container& container) { + return makeUserNameIterator(container.begin(), container.end()); + } + } // namespace mongo diff --git a/src/mongo/db/auth/user_set.cpp b/src/mongo/db/auth/user_set.cpp index c36a1c093f7..34c1318ab9d 100644 --- a/src/mongo/db/auth/user_set.cpp +++ b/src/mongo/db/auth/user_set.cpp @@ -23,6 +23,27 @@ namespace mongo { +namespace { + class UserSetNameIteratorImpl : public UserNameIterator::Impl { + MONGO_DISALLOW_COPYING(UserSetNameIteratorImpl); + public: + UserSetNameIteratorImpl(const UserSet::iterator& begin, + const UserSet::iterator& end) : + _curr(begin), _end(end) {} + virtual ~UserSetNameIteratorImpl() {} + virtual bool more() const { return _curr != _end; } + virtual const UserName& next() { return (*(_curr++))->getName(); } + virtual const UserName& get() const { return (*_curr)->getName(); } + virtual UserNameIterator::Impl* doClone() const { + return new UserSetNameIteratorImpl(_curr, _end); + } + + private: + UserSet::iterator _curr; + UserSet::iterator _end; + }; +} // namespace + UserSet::UserSet() : _users(), _usersEnd(_users.end()) {} UserSet::~UserSet() {} @@ -90,4 +111,7 @@ namespace mongo { return NULL; } + UserNameIterator UserSet::getNames() const { + return UserNameIterator(new UserSetNameIteratorImpl(begin(), end())); + } } // namespace mongo diff --git a/src/mongo/db/auth/user_set.h b/src/mongo/db/auth/user_set.h index ad193654e52..591a9bdb9fa 100644 --- a/src/mongo/db/auth/user_set.h +++ b/src/mongo/db/auth/user_set.h @@ -37,37 +37,6 @@ namespace mongo { public: typedef std::vector<User*>::const_iterator iterator; - /** - * Forward iterator over the names of the users stored in a UserSet. - * - * Instances are valid until the underlying vector<User*> is modified. - * - * more() must be the first method called after construction, and must be checked - * after each call to next() before calling any other methods. - */ - class NameIterator { - public: - explicit NameIterator(iterator begin, iterator end) : _curr(begin), _end(end) {} - - NameIterator() {} - - bool more() { return _curr != _end; } - const UserName& next() { - const UserName& ret = get(); - ++_curr; - return ret; - } - - const UserName& get() const { return (*_curr)->getName(); } - - const UserName& operator*() const { return get(); } - const UserName* operator->() const { return &get(); } - - private: - std::vector<User*>::const_iterator _curr; - std::vector<User*>::const_iterator _end; - }; - UserSet(); ~UserSet(); @@ -121,7 +90,7 @@ namespace mongo { // Gets an iterator over the names of the users stored in the set. The iterator is // valid until the next non-const method is called on the UserSet. - NameIterator getNames() const { return NameIterator(begin(), end()); } + UserNameIterator getNames() const; iterator begin() const { return _users.begin(); } iterator end() const { return _usersEnd; } diff --git a/src/mongo/db/auth/user_set_test.cpp b/src/mongo/db/auth/user_set_test.cpp index fb30d00bee7..5063f727412 100644 --- a/src/mongo/db/auth/user_set_test.cpp +++ b/src/mongo/db/auth/user_set_test.cpp @@ -75,7 +75,7 @@ namespace { ASSERT_EQUALS(p3, set.lookup(UserName("Bob", "test2"))); ASSERT_EQUALS(p3, set.lookupByDBName("test2")); - UserSet::NameIterator iter = set.getNames(); + UserNameIterator iter = set.getNames(); ASSERT_TRUE(iter.more()); ASSERT_EQUALS(iter.next(), UserName("Bob", "test2")); ASSERT_FALSE(iter.more()); @@ -83,7 +83,7 @@ namespace { TEST(UserSetTest, IterateNames) { UserSet pset; - UserSet::NameIterator iter = pset.getNames(); + UserNameIterator iter = pset.getNames(); ASSERT(!iter.more()); ASSERT_NULL(pset.add(new User(UserName("bob", "test")))); |