Ejemplo n.º 1
0
Status checkAuthForCopydbCommand(ClientBasic* client,
                                 const std::string& dbname,
                                 const BSONObj& cmdObj) {
    bool fromSelf = StringData(cmdObj.getStringField("fromhost")).empty();
    StringData fromdb = cmdObj.getStringField("fromdb");
    StringData todb = cmdObj.getStringField("todb");

    // get system collections
    std::vector<std::string> legalClientSystemCollections;
    legalClientSystemCollections.push_back("system.js");
    if (fromdb == "admin") {
        legalClientSystemCollections.push_back("system.users");
        legalClientSystemCollections.push_back("system.roles");
        legalClientSystemCollections.push_back("system.version");
    } else if (fromdb == "local") {  // TODO(spencer): shouldn't be possible. See SERVER-11383
        legalClientSystemCollections.push_back("system.replset");
    }

    // Check authorization on destination db
    ActionSet actions;
    actions.addAction(ActionType::insert);
    actions.addAction(ActionType::createIndex);
    if (shouldBypassDocumentValidationForCommand(cmdObj)) {
        actions.addAction(ActionType::bypassDocumentValidation);
    }

    if (!AuthorizationSession::get(client)
             ->isAuthorizedForActionsOnResource(ResourcePattern::forDatabaseName(todb), actions)) {
        return Status(ErrorCodes::Unauthorized, "Unauthorized");
    }

    actions.removeAllActions();
    actions.addAction(ActionType::insert);
    for (size_t i = 0; i < legalClientSystemCollections.size(); ++i) {
        if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnNamespace(
                NamespaceString(todb, legalClientSystemCollections[i]), actions)) {
            return Status(ErrorCodes::Unauthorized, "Unauthorized");
        }
    }

    if (fromSelf) {
        // If copying from self, also require privileges on source db
        actions.removeAllActions();
        actions.addAction(ActionType::find);
        if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
                ResourcePattern::forDatabaseName(fromdb), actions)) {
            return Status(ErrorCodes::Unauthorized, "Unauthorized");
        }
        for (size_t i = 0; i < legalClientSystemCollections.size(); ++i) {
            if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnNamespace(
                    NamespaceString(fromdb, legalClientSystemCollections[i]), actions)) {
                return Status(ErrorCodes::Unauthorized, "Unauthorized");
            }
        }
    }
    return Status::OK();
}
Ejemplo n.º 2
0
    Status checkAuthForRenameCollectionCommand(ClientBasic* client,
                                               const std::string& dbname,
                                               const BSONObj& cmdObj) {
        NamespaceString sourceNS = NamespaceString(cmdObj.getStringField("renameCollection"));
        NamespaceString targetNS = NamespaceString(cmdObj.getStringField("to"));
        bool dropTarget = cmdObj["dropTarget"].trueValue();

        if (sourceNS.db() == targetNS.db() && !sourceNS.isSystem() && !targetNS.isSystem()) {
            // If renaming within the same database, then if you have renameCollectionSameDB and
            // either can read both of source and dest collections or *can't* read either of source
            // or dest collection, then you get can do the rename, even without insert on the
            // destination collection.
            bool canRename = AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
                    ResourcePattern::forDatabaseName(sourceNS.db()),
                    ActionType::renameCollectionSameDB);

            bool canDropTargetIfNeeded = true;
            if (dropTarget) {
                canDropTargetIfNeeded =
                        AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
                            ResourcePattern::forExactNamespace(targetNS),
                            ActionType::dropCollection);
            }

            bool canReadSrc = AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
                    ResourcePattern::forExactNamespace(sourceNS), ActionType::find);
            bool canReadDest = AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
                    ResourcePattern::forExactNamespace(targetNS), ActionType::find);

            if (canRename && canDropTargetIfNeeded && (canReadSrc || !canReadDest)) {
                return Status::OK();
            }
        }

        // Check privileges on source collection
        ActionSet actions;
        actions.addAction(ActionType::find);
        actions.addAction(ActionType::dropCollection);
        if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
                ResourcePattern::forExactNamespace(sourceNS), actions)) {
            return Status(ErrorCodes::Unauthorized, "Unauthorized");
        }

        // Check privileges on dest collection
        actions.removeAllActions();
        actions.addAction(ActionType::insert);
        actions.addAction(ActionType::createIndex);
        if (dropTarget) {
            actions.addAction(ActionType::dropCollection);
        }
        if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
                ResourcePattern::forExactNamespace(targetNS), actions)) {
            return Status(ErrorCodes::Unauthorized, "Unauthorized");
        }

        return Status::OK();
    }
    Status checkAuthForRenameCollectionCommand(ClientBasic* client,
                                               const std::string& dbname,
                                               const BSONObj& cmdObj) {
        NamespaceString sourceNS = NamespaceString(cmdObj.getStringField("renameCollection"));
        NamespaceString targetNS = NamespaceString(cmdObj.getStringField("to"));
        bool dropTarget = cmdObj["dropTarget"].trueValue();

        if (sourceNS.db() == targetNS.db() && !sourceNS.isSystem() && !targetNS.isSystem()) {
            bool authed1 = client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
                    ResourcePattern::forDatabaseName(sourceNS.db()),
                    ActionType::renameCollectionSameDB);

            bool authed2 = true;
            if (dropTarget) {
                authed2 = client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
                        ResourcePattern::forExactNamespace(targetNS), ActionType::dropCollection);
            }

            if (authed1 && authed2) {
                return Status::OK();
            }
        }

        // Check privileges on source collection
        ActionSet actions;
        actions.addAction(ActionType::find);
        actions.addAction(ActionType::dropCollection);
        if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
                ResourcePattern::forExactNamespace(sourceNS), actions)) {
            return Status(ErrorCodes::Unauthorized, "Unauthorized");
        }

        // Check privileges on dest collection
        actions.removeAllActions();
        actions.addAction(ActionType::insert);
        actions.addAction(ActionType::createIndex);
        if (dropTarget) {
            actions.addAction(ActionType::dropCollection);
        }
        if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
                ResourcePattern::forExactNamespace(targetNS), actions)) {
            return Status(ErrorCodes::Unauthorized, "Unauthorized");
        }

        return Status::OK();
    }