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);
}