void AclReader::loadDecisionData()

in src/qpid/acl/AclReader.cpp [84:281]


    void AclReader::loadDecisionData(boost::shared_ptr<AclData> d) {
        d->clear();
        QPID_LOG(debug, "ACL: Load Rules");
        bool foundmode = false;
        bool foundConnectionMode = false;

        rlCitr i = rules.end();
        for (int cnt = rules.size(); cnt; cnt--) {
            i--;
            QPID_LOG(debug, "ACL: Processing " << std::setfill(' ') << std::setw(2)
                << cnt << " " << (*i)->toString());

            if (!(*i)->actionAll && (*i)->objStatus == aclRule::VALUE &&
                !validator.validateAllowedProperties(
                    (*i)->action, (*i)->object, (*i)->props, false)) {
                    // specific object/action has bad property
                    // this rule gets ignored
                    continue;
            } else {
                // action=all or object=none/all means the rule gets propagated
                // possibly to many places.
                // Invalid rule combinations are not propagated.
            }

            if (!foundmode && (*i)->actionAll && (*i)->names.size() == 1
                && (*((*i)->names.begin())).compare(AclData::ACL_KEYWORD_WILDCARD) == 0) {
                    d->decisionMode = (*i)->res;
                    QPID_LOG(debug, "ACL: FoundMode "
                        << AclHelper::getAclResultStr(d->decisionMode));
                    foundmode = true;
            } else if ((*i)->action == acl::ACT_CREATE && (*i)->object == acl::OBJ_CONNECTION) {
                // Intercept CREATE CONNECTION rules process them into separate lists to
                // be consumed in the connection approval code path.
                propMap::const_iterator pName = (*i)->props.find(SPECPROP_NAME);
                if (pName != (*i)->props.end()) {
                    throw Exception(QPID_MSG("ACL: CREATE CONNECTION rule " << cnt << " must not have a 'name' property"));
                }
                propMap::const_iterator pHost = (*i)->props.find(SPECPROP_HOST);
                if (pHost == (*i)->props.end()) {
                    throw Exception(QPID_MSG("ACL: CREATE CONNECTION rule " << cnt << " has no 'host' property"));
                }
                // create the connection rule
                bool allUsers = (*(*i)->names.begin()).compare(AclData::ACL_KEYWORD_WILDCARD) == 0;
                bool allHosts = pHost->second.compare(AclData::ACL_KEYWORD_ALL) == 0;
                AclBWHostRule bwRule((*i)->res, (allHosts ? "" : pHost->second));

                // apply the rule globally or to user list
                if (allUsers) {
                    if (allHosts) {
                        // allow one specification of allUsers,allHosts
                        if (foundConnectionMode) {
                            throw Exception(QPID_MSG("ACL: only one CREATE CONNECTION rule for user=all and host=all allowed"));
                        }
                        foundConnectionMode = true;
                        d->connectionDecisionMode = (*i)->res;
                        QPID_LOG(trace, "ACL: Found connection mode: " << AclHelper::getAclResultStr( (*i)->res ));
                    } else {
                        // Rules for allUsers but not allHosts go into the global list
                        globalHostRules->insert( globalHostRules->begin(), bwRule );
                    }
                } else {
                    // other rules go into binned rule sets for each user
                    for (nsCitr itr  = (*i)->names.begin();
                                itr != (*i)->names.end();
                                itr++) {
                        (*userHostRules)[(*itr)].insert( (*userHostRules)[(*itr)].begin(), bwRule);
                    }
                }
            } else {
                AclData::Rule rule(cnt, (*i)->res, (*i)->props);
                // Record which properties have the user substitution string
                for (pmCitr pItr=rule.props.begin(); pItr!=rule.props.end(); pItr++) {
                    if ((pItr->second.find(AclData::ACL_KEYWORD_USER_SUBST, 0)       != std::string::npos) ||
                        (pItr->second.find(AclData::ACL_KEYWORD_DOMAIN_SUBST, 0)     != std::string::npos) ||
                        (pItr->second.find(AclData::ACL_KEYWORD_USERDOMAIN_SUBST, 0) != std::string::npos)) {
                        rule.ruleHasUserSub[pItr->first] = true;
                    }
                }

                // Find possible routingkey property and cache its pattern
                for (pmCitr pItr=rule.props.begin(); pItr!=rule.props.end(); pItr++) {
                    if (acl::SPECPROP_ROUTINGKEY == pItr->first)
                    {
                        rule.pubRoutingKeyInRule = true;
                        rule.pubRoutingKey = (std::string)pItr->second;
                        rule.addTopicTest(rule.pubRoutingKey);
                    }
                }

                // Action -> Object -> map<user -> set<Rule> >
                std::ostringstream actionstr;
                for (int acnt = ((*i)->actionAll ? 0 : (*i)->action);
                    acnt < acl::ACTIONSIZE;
                    (*i)->actionAll ? acnt++ : acnt = acl::ACTIONSIZE) {

                    if (acnt == acl::ACT_PUBLISH)
                    {
                        d->transferAcl = true; // we have transfer ACL
                        // For Publish the only object should be Exchange
                        // and the only property should be routingkey.
                        // Go through the rule properties and find the name and the key.
                        // If found then place them specially for the lookup engine.
                        for (pmCitr pItr=(*i)->props.begin(); pItr!=(*i)->props.end(); pItr++) {
                            if (acl::SPECPROP_NAME == pItr->first)
                            {
                                rule.pubExchNameInRule = true;
                                rule.pubExchName = pItr->second;
                                rule.pubExchNameMatchesBlank = rule.pubExchName.compare(AclData::ACL_KEYWORD_DEFAULT_EXCHANGE) == 0;
                            }
                        }
                    }
                    actionstr << AclHelper::getActionStr((Action) acnt) << ",";

                    //find the Action, create if not exist
                    if (d->actionList[acnt] == NULL) {
                        d->actionList[acnt] =
                            new AclData::aclAction[qpid::acl::OBJECTSIZE];
                        for (int j = 0; j < qpid::acl::OBJECTSIZE; j++)
                            d->actionList[acnt][j] = NULL;
                    }

                    for (int ocnt = ((*i)->objStatus != aclRule::VALUE ? 0
                        : (*i)->object);
                        ocnt < acl::OBJECTSIZE;
                    (*i)->objStatus != aclRule::VALUE ? ocnt++ : ocnt = acl::OBJECTSIZE) {

                        //find the Object, create if not exist
                        if (d->actionList[acnt][ocnt] == NULL)
                            d->actionList[acnt][ocnt] =
                                new AclData::actionObject;

                        // add users and Rule to object set
                        bool allNames = false;
                        // check to see if names.begin is '*'
                        if ((*(*i)->names.begin()).compare(AclData::ACL_KEYWORD_WILDCARD) == 0)
                            allNames = true;

                        for (nsCitr itr  = (allNames ? names.begin() : (*i)->names.begin());
                                    itr != (allNames ? names.end()   : (*i)->names.end());
                                    itr++) {
                            if (validator.validateAllowedProperties(acl::Action(acnt),
                                                                    acl::ObjectType(ocnt),
                                                                    (*i)->props,
                                                                    false)) {
                                AclData::actObjItr itrRule =
                                    d->actionList[acnt][ocnt]->find(*itr);

                                if (itrRule == d->actionList[acnt][ocnt]->end()) {
                                    AclData::ruleSet rSet;
                                    rSet.push_back(rule);
                                    d->actionList[acnt][ocnt]->insert
                                        (make_pair(std::string(*itr), rSet));
                                } else {
                                        itrRule->second.push_back(rule);
                                }
                            } else {
                                // Skip propagating this rule as it will never match.
                            }
                        }
                    }
                }

                std::ostringstream objstr;
                for (int ocnt = ((*i)->objStatus != aclRule::VALUE ? 0 : (*i)->object);
                         ocnt < acl::OBJECTSIZE;
                                 (*i)->objStatus != aclRule::VALUE ? ocnt++ : ocnt = acl::OBJECTSIZE) {
                        objstr << AclHelper::getObjectTypeStr((ObjectType) ocnt) << ",";
                }

                bool allNames = ((*(*i)->names.begin()).compare(AclData::ACL_KEYWORD_WILDCARD) == 0);
                std::ostringstream userstr;
                for (nsCitr itr  = (allNames ? names.begin() : (*i)->names.begin());
                            itr != (allNames ? names.end()   : (*i)->names.end());
                            itr++) {
                    userstr << *itr << ",";
                }

                QPID_LOG(debug, "ACL: Adding actions {" <<
                    actionstr.str().substr(0,actionstr.str().length()-1)
                    << "} to objects {" <<
                    objstr.str().substr(0,objstr.str().length()-1)
                    << "} with props " <<
                    AclHelper::propertyMapToString(&rule.props)
                    << " for users {" <<
                    userstr.str().substr(0,userstr.str().length()-1)
                    << "}");
            }
        }

        // connection quota
        d->setConnQuotaRuleSettings(connQuota);
        // queue quota
        d->setQueueQuotaRuleSettings(queueQuota);
        // global B/W connection rules
        d->setConnGlobalRules(globalHostRules);
        // user B/W connection rules
        d->setConnUserRules(userHostRules);
    }