diff options
Diffstat (limited to 'src/mongo/db/auth')
-rw-r--r-- | src/mongo/db/auth/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_session.cpp | 76 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_session.h | 10 |
3 files changed, 72 insertions, 15 deletions
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript index 1cda5da1ee5..2f15a110423 100644 --- a/src/mongo/db/auth/SConscript +++ b/src/mongo/db/auth/SConscript @@ -34,6 +34,7 @@ env.Library('authcore', ['action_set.cpp', '$BUILD_DIR/mongo/db/common', '$BUILD_DIR/mongo/db/ops/update_driver', '$BUILD_DIR/mongo/md5', + '$BUILD_DIR/mongo/namespace_string', '$BUILD_DIR/mongo/signal_handlers_synchronous', '$BUILD_DIR/mongo/stringutils']) diff --git a/src/mongo/db/auth/authorization_session.cpp b/src/mongo/db/auth/authorization_session.cpp index 7173ca17a75..5b7a7c5e459 100644 --- a/src/mongo/db/auth/authorization_session.cpp +++ b/src/mongo/db/auth/authorization_session.cpp @@ -176,21 +176,46 @@ namespace { Status AuthorizationSession::checkAuthForQuery(const NamespaceString& ns, const BSONObj& query) { if (MONGO_unlikely(ns.isCommand())) { - return Status(ErrorCodes::InternalError, mongoutils::str::stream() << + return Status(ErrorCodes::InternalError, str::stream() << "Checking query auth on command namespace " << ns.ns()); } if (!isAuthorizedForActionsOnNamespace(ns, ActionType::find)) { return Status(ErrorCodes::Unauthorized, - mongoutils::str::stream() << "not authorized for query on " << ns.ns()); + str::stream() << "not authorized for query on " << ns.ns()); } return Status::OK(); } Status AuthorizationSession::checkAuthForGetMore(const NamespaceString& ns, long long cursorID) { - if (!isAuthorizedForActionsOnNamespace(ns, ActionType::find)) { - return Status(ErrorCodes::Unauthorized, - mongoutils::str::stream() << "not authorized for getmore on " << ns.ns()); + // "ns" can be in one of three formats: "listCollections" format, "listIndexes" format, and + // normal format. + if (ns.isListCollectionsGetMore()) { + // "ns" is of the form "<db>.$cmd.listCollections". Check if we can perform the + // listCollections action on the database resource for "<db>". + if (!isAuthorizedForActionsOnResource(ResourcePattern::forDatabaseName(ns.db()), + ActionType::listCollections)) { + return Status(ErrorCodes::Unauthorized, + str::stream() << "not authorized for listCollections getMore on " + << ns.ns()); + } + } + else if (ns.isListIndexesGetMore()) { + // "ns" is of the form "<db>.$cmd.listIndexes.<coll>". Check if we can perform the + // listIndexes action on the "<db>.<coll>" namespace. + NamespaceString targetNS = ns.getTargetNSForListIndexesGetMore(); + if (!isAuthorizedForActionsOnNamespace(targetNS, ActionType::listIndexes)) { + return Status(ErrorCodes::Unauthorized, + str::stream() << "not authorized for listIndexes getMore on " + << ns.ns()); + } + } + else { + // "ns" is a regular namespace string. Check if we can perform the find action on it. + if (!isAuthorizedForActionsOnNamespace(ns, ActionType::find)) { + return Status(ErrorCodes::Unauthorized, + str::stream() << "not authorized for getMore on " << ns.ns()); + } } return Status::OK(); } @@ -206,14 +231,13 @@ namespace { NamespaceString indexNS(nsElement.str()); if (!isAuthorizedForActionsOnNamespace(indexNS, ActionType::createIndex)) { return Status(ErrorCodes::Unauthorized, - mongoutils::str::stream() << "not authorized to create index on " << + str::stream() << "not authorized to create index on " << indexNS.ns()); } } else { if (!isAuthorizedForActionsOnNamespace(ns, ActionType::insert)) { return Status(ErrorCodes::Unauthorized, - mongoutils::str::stream() << "not authorized for insert on " << - ns.ns()); + str::stream() << "not authorized for insert on " << ns.ns()); } } @@ -227,8 +251,7 @@ namespace { if (!upsert) { if (!isAuthorizedForActionsOnNamespace(ns, ActionType::update)) { return Status(ErrorCodes::Unauthorized, - mongoutils::str::stream() << "not authorized for update on " << - ns.ns()); + str::stream() << "not authorized for update on " << ns.ns()); } } else { @@ -237,8 +260,7 @@ namespace { required.addAction(ActionType::insert); if (!isAuthorizedForActionsOnNamespace(ns, required)) { return Status(ErrorCodes::Unauthorized, - mongoutils::str::stream() << "not authorized for upsert on " << - ns.ns()); + str::stream() << "not authorized for upsert on " << ns.ns()); } } return Status::OK(); @@ -248,7 +270,35 @@ namespace { const BSONObj& query) { if (!isAuthorizedForActionsOnNamespace(ns, ActionType::remove)) { return Status(ErrorCodes::Unauthorized, - mongoutils::str::stream() << "not authorized to remove from " << ns.ns()); + str::stream() << "not authorized to remove from " << ns.ns()); + } + return Status::OK(); + } + + Status AuthorizationSession::checkAuthForKillCursors(const NamespaceString& ns, + long long cursorID) { + // See implementation comments in checkAuthForGetMore(). This method looks very similar. + if (ns.isListCollectionsGetMore()) { + if (!isAuthorizedForActionsOnResource(ResourcePattern::forDatabaseName(ns.db()), + ActionType::killCursors)) { + return Status(ErrorCodes::Unauthorized, + str::stream() << "not authorized to kill listCollections cursor on " + << ns.ns()); + } + } + else if (ns.isListIndexesGetMore()) { + NamespaceString targetNS = ns.getTargetNSForListIndexesGetMore(); + if (!isAuthorizedForActionsOnNamespace(targetNS, ActionType::killCursors)) { + return Status(ErrorCodes::Unauthorized, + str::stream() << "not authorized to kill listIndexes cursor on " + << ns.ns()); + } + } + else { + if (!isAuthorizedForActionsOnNamespace(ns, ActionType::killCursors)) { + return Status(ErrorCodes::Unauthorized, + str::stream() << "not authorized to kill cursor on " << ns.ns()); + } } return Status::OK(); } diff --git a/src/mongo/db/auth/authorization_session.h b/src/mongo/db/auth/authorization_session.h index 3a184e4be7d..190b854312d 100644 --- a/src/mongo/db/auth/authorization_session.h +++ b/src/mongo/db/auth/authorization_session.h @@ -115,8 +115,9 @@ namespace mongo { // given namespace. Status checkAuthForQuery(const NamespaceString& ns, const BSONObj& query); - // Checks if this connection has the privileges necessary to perform a getMore on the given - // cursor in the given namespace. + // Checks if this connection has the privileges necessary to perform a getMore operation on + // the identified cursor, supposing that cursor is associated with the supplied namespace + // identifier. Status checkAuthForGetMore(const NamespaceString& ns, long long cursorID); // Checks if this connection has the privileges necessary to perform the given update on the @@ -135,6 +136,11 @@ namespace mongo { // namespace. Status checkAuthForDelete(const NamespaceString& ns, const BSONObj& query); + // Checks if this connection has the privileges necessary to perform a killCursor on + // the identified cursor, supposing that cursor is associated with the supplied namespace + // identifier. + Status checkAuthForKillCursors(const NamespaceString& ns, long long cursorID); + // Checks if this connection has the privileges necessary to grant the given privilege // to a role. Status checkAuthorizedToGrantPrivilege(const Privilege& privilege); |