void PartialPolicyExecutor::executeActionStep() { if (isGoalReached || hasFailed) return; if (active != NULL && !active->hasFinished()) { if (newAction) { for_each(executionObservers.begin(),executionObservers.end(),NotifyActionStart(active->toFluent(actionCounter))); newAction = false; } active->run(); } else { if (active != NULL) { for_each(executionObservers.begin(),executionObservers.end(),NotifyActionTermination(active->toFluent(actionCounter++))); } isGoalReached = kr->currentStateQuery(goalRules).isSatisfied(); if (isGoalReached) //well done! return; //choose the next action AnswerSet currentState = kr->currentStateQuery(vector<AspRule>()); set<AspFluent> state(currentState.getFluents().begin(), currentState.getFluents().end()); ActionSet options = policy->actions(state); if (options.empty() || (active != NULL && active->hasFailed())) { //there's no action for this state, computing more plans //if the last action failed, we may want to have some more option PartialPolicy *otherPolicy = planner->computePolicy(goalRules,suboptimality); policy->merge(otherPolicy); delete otherPolicy; for_each(executionObservers.begin(),executionObservers.end(),bind2nd(mem_fun(&ExecutionObserver::policyChanged),policy)); options = policy->actions(state); if (options.empty()) { //no actions available from here! hasFailed = true; return; } } set<AspFluent>::const_iterator chosen = selector->choose(options); delete active; active = instantiateAction(actionMap,*chosen); actionCounter++; newAction = true; } }
bool AuthorizationSession::_isAuthorizedForPrivilege(const Privilege& privilege) { AuthorizationManager& authMan = getAuthorizationManager(); const ResourcePattern& target(privilege.getResourcePattern()); ResourcePattern resourceSearchList[resourceSearchListCapacity]; const int resourceSearchListLength = buildResourceSearchList(target, resourceSearchList); ActionSet unmetRequirements = privilege.getActions(); UserSet::iterator it = _authenticatedUsers.begin(); while (it != _authenticatedUsers.end()) { User* user = *it; if (!user->isValid()) { // Make a good faith effort to acquire an up-to-date user object, since the one // we've cached is marked "out-of-date." UserName name = user->getName(); User* updatedUser; Status status = authMan.acquireUser(name, &updatedUser); switch (status.code()) { case ErrorCodes::OK: { // Success! Replace the old User object with the updated one. fassert(17067, _authenticatedUsers.replaceAt(it, updatedUser) == user); authMan.releaseUser(user); user = updatedUser; LOG(1) << "Updated session cache of user information for " << name; break; } case ErrorCodes::UserNotFound: { // User does not exist anymore; remove it from _authenticatedUsers. fassert(17068, _authenticatedUsers.removeAt(it) == user); authMan.releaseUser(user); LOG(1) << "Removed deleted user " << name << " from session cache of user information."; continue; // No need to advance "it" in this case. } default: // Unrecognized error; assume that it's transient, and continue working with the // out-of-date privilege data. warning() << "Could not fetch updated user privilege information for " << name << "; continuing to use old information. Reason is " << status; break; } } for (int i = 0; i < resourceSearchListLength; ++i) { ActionSet userActions = user->getActionsForResource(resourceSearchList[i]); unmetRequirements.removeAllActionsFromSet(userActions); if (unmetRequirements.empty()) return true; } ++it; } return false; }
Status checkAuthForWriteCommand(AuthorizationSession* authzSession, BatchedCommandRequest::BatchType cmdType, const OpMsgRequest& request) { std::vector<Privilege> privileges; ActionSet actionsOnCommandNSS; if (shouldBypassDocumentValidationForCommand(request.body)) { actionsOnCommandNSS.addAction(ActionType::bypassDocumentValidation); } NamespaceString cmdNSS; if (cmdType == BatchedCommandRequest::BatchType_Insert) { auto op = Insert::parse(IDLParserErrorContext("insert"), request); cmdNSS = op.getNamespace(); if (!op.getNamespace().isSystemDotIndexes()) { actionsOnCommandNSS.addAction(ActionType::insert); } else { // Special-case indexes until we have a command const auto swNssToIndex = getIndexedNss(op.getDocuments()); if (!swNssToIndex.isOK()) { return swNssToIndex.getStatus(); } const auto& nssToIndex = swNssToIndex.getValue(); privileges.push_back( Privilege(ResourcePattern::forExactNamespace(nssToIndex), ActionType::createIndex)); } } else if (cmdType == BatchedCommandRequest::BatchType_Update) { auto op = Update::parse(IDLParserErrorContext("update"), request); cmdNSS = op.getNamespace(); actionsOnCommandNSS.addAction(ActionType::update); // Upsert also requires insert privs if (containsUpserts(op.getUpdates())) { actionsOnCommandNSS.addAction(ActionType::insert); } } else { fassert(17251, cmdType == BatchedCommandRequest::BatchType_Delete); auto op = Delete::parse(IDLParserErrorContext("delete"), request); cmdNSS = op.getNamespace(); actionsOnCommandNSS.addAction(ActionType::remove); } if (!actionsOnCommandNSS.empty()) { privileges.emplace_back(ResourcePattern::forExactNamespace(cmdNSS), actionsOnCommandNSS); } if (authzSession->isAuthorizedForPrivileges(privileges)) return Status::OK(); return Status(ErrorCodes::Unauthorized, "unauthorized"); }
bool AuthorizationSession::_isAuthorizedForPrivilege(const Privilege& privilege) { const ResourcePattern& target(privilege.getResourcePattern()); ResourcePattern resourceSearchList[resourceSearchListCapacity]; const int resourceSearchListLength = buildResourceSearchList(target, resourceSearchList); ActionSet unmetRequirements = privilege.getActions(); PrivilegeVector defaultPrivileges = getDefaultPrivileges(); for (PrivilegeVector::iterator it = defaultPrivileges.begin(); it != defaultPrivileges.end(); ++it) { for (int i = 0; i < resourceSearchListLength; ++i) { if (!(it->getResourcePattern() == resourceSearchList[i])) continue; ActionSet userActions = it->getActions(); unmetRequirements.removeAllActionsFromSet(userActions); if (unmetRequirements.empty()) return true; } } for (UserSet::iterator it = _authenticatedUsers.begin(); it != _authenticatedUsers.end(); ++it) { User* user = *it; for (int i = 0; i < resourceSearchListLength; ++i) { ActionSet userActions = user->getActionsForResource(resourceSearchList[i]); unmetRequirements.removeAllActionsFromSet(userActions); if (unmetRequirements.empty()) return true; } } return false; }
bool AuthorizationSession::_isAuthorizedForPrivilege(const Privilege& privilege) { const ResourcePattern& target(privilege.getResourcePattern()); ResourcePattern resourceSearchList[resourceSearchListCapacity]; const int resourceSearchListLength = buildResourceSearchList(target, resourceSearchList); ActionSet unmetRequirements = privilege.getActions(); for (UserSet::iterator it = _authenticatedUsers.begin(); it != _authenticatedUsers.end(); ++it) { User* user = *it; if (user->getSchemaVersion() == AuthorizationManager::schemaVersion24 && (target.isDatabasePattern() || target.isExactNamespacePattern()) && !user->hasProbedV1(target.databaseToMatch())) { UserName name = user->getName(); User* updatedUser; Status status = getAuthorizationManager().acquireV1UserProbedForDb( name, target.databaseToMatch(), &updatedUser); if (status.isOK()) { if (user != updatedUser) { LOG(1) << "Updated session cache with privileges on the " << target.databaseToMatch() << " database for V1 user " << name; fassert(17226, _authenticatedUsers.replaceAt(it, updatedUser) == user); } getAuthorizationManager().releaseUser(user); user = updatedUser; } else if (status != ErrorCodes::UserNotFound) { warning() << "Could not fetch updated user privilege information for V1-style " "user " << name << "; continuing to use old information. Reason is " << status; } } for (int i = 0; i < resourceSearchListLength; ++i) { ActionSet userActions = user->getActionsForResource(resourceSearchList[i]); unmetRequirements.removeAllActionsFromSet(userActions); if (unmetRequirements.empty()) return true; } } return false; }
Status checkAuthForWriteCommand(AuthorizationSession* authzSession, BatchedCommandRequest::BatchType cmdType, const NamespaceString& cmdNSS, const BSONObj& cmdObj) { vector<Privilege> privileges; ActionSet actionsOnCommandNSS; if (shouldBypassDocumentValidationForCommand(cmdObj)) { actionsOnCommandNSS.addAction(ActionType::bypassDocumentValidation); } if (cmdType == BatchedCommandRequest::BatchType_Insert) { if (!cmdNSS.isSystemDotIndexes()) { actionsOnCommandNSS.addAction(ActionType::insert); } else { // Special-case indexes until we have a command string nsToIndex, errMsg; if (!BatchedCommandRequest::getIndexedNS(cmdObj, &nsToIndex, &errMsg)) { return Status(ErrorCodes::FailedToParse, errMsg); } NamespaceString nssToIndex(nsToIndex); privileges.push_back( Privilege(ResourcePattern::forExactNamespace(nssToIndex), ActionType::createIndex)); } } else if (cmdType == BatchedCommandRequest::BatchType_Update) { actionsOnCommandNSS.addAction(ActionType::update); // Upsert also requires insert privs if (BatchedCommandRequest::containsUpserts(cmdObj)) { actionsOnCommandNSS.addAction(ActionType::insert); } } else { fassert(17251, cmdType == BatchedCommandRequest::BatchType_Delete); actionsOnCommandNSS.addAction(ActionType::remove); } if (!actionsOnCommandNSS.empty()) { privileges.emplace_back(ResourcePattern::forExactNamespace(cmdNSS), actionsOnCommandNSS); } if (authzSession->isAuthorizedForPrivileges(privileges)) return Status::OK(); return Status(ErrorCodes::Unauthorized, "unauthorized"); }
bool PrivilegeSet::hasPrivilege(const Privilege& desiredPrivilege) { if (desiredPrivilege.getActions().empty()) return true; StringData resourceSearchList[2]; resourceSearchList[0] = WILDCARD_RESOURCE; resourceSearchList[1] = desiredPrivilege.getResource(); ActionSet unmetRequirements = desiredPrivilege.getActions(); for (int i = 0; i < boost::size(resourceSearchList); ++i) { ResourcePrivilegeCacheEntry* entry = _lookupEntry(resourceSearchList[i]); if (NULL == entry) continue; if (entry->dirty) _rebuildEntry(resourceSearchList[i], entry); unmetRequirements.removeAllActionsFromSet(entry->actions); if (unmetRequirements.empty()) return true; } return false; }
Status AuthorizationSession::_checkAuthForPrivilegeHelper(const Privilege& privilege) { AuthorizationManager& authMan = getAuthorizationManager(); Privilege modifiedPrivilege = _modifyPrivilegeForSpecialCases(privilege); // Need to check not just the resource of the privilege, but also just the database // component and the "*" resource. std::string resourceSearchList[3]; resourceSearchList[0] = AuthorizationManager::WILDCARD_RESOURCE_NAME; resourceSearchList[1] = nsToDatabase(modifiedPrivilege.getResource()); resourceSearchList[2] = modifiedPrivilege.getResource(); ActionSet unmetRequirements = modifiedPrivilege.getActions(); UserSet::iterator it = _authenticatedUsers.begin(); while (it != _authenticatedUsers.end()) { User* user = *it; if (!user->isValid()) { // Make a good faith effort to acquire an up-to-date user object, since the one // we've cached is marked "out-of-date." UserName name = user->getName(); User* updatedUser; Status status = authMan.acquireUser(name, &updatedUser); switch (status.code()) { case ErrorCodes::OK: { // Success! Replace the old User object with the updated one. fassert(17067, _authenticatedUsers.replaceAt(it, updatedUser) == user); authMan.releaseUser(user); user = updatedUser; LOG(1) << "Updated session cache of user information for " << name; break; } case ErrorCodes::UserNotFound: { // User does not exist anymore; remove it from _authenticatedUsers. fassert(17068, _authenticatedUsers.removeAt(it) == user); authMan.releaseUser(user); LOG(1) << "Removed deleted user " << name << " from session cache of user information."; continue; // No need to advance "it" in this case. } default: // Unrecognized error; assume that it's transient, and continue working with the // out-of-date privilege data. warning() << "Could not fetch updated user privilege information for " << name << "; continuing to use old information. Reason is " << status; break; } } for (int i = 0; i < static_cast<int>(boost::size(resourceSearchList)); ++i) { ActionSet userActions = user->getActionsForResource(resourceSearchList[i]); unmetRequirements.removeAllActionsFromSet(userActions); if (unmetRequirements.empty()) return Status::OK(); } ++it; } return Status(ErrorCodes::Unauthorized, "unauthorized"); }
void ActionSet::removeAllActionsFromSet(const ActionSet& other) { _actions &= ~other._actions; if (!other.empty()) { _actions.set(ActionType::anyAction.getIdentifier(), false); } }