/* * * Copyright (c) 2006 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "qpid/acl/AclData.h" #include "qpid/acl/AclValidator.h" #include "qpid/log/Statement.h" #include "qpid/sys/IntegerTypes.h" #include #include #include #include namespace qpid { namespace acl { // // Instantiate the keyword strings // const std::string AclData::ACL_KEYWORD_USER_SUBST = "${user}"; const std::string AclData::ACL_KEYWORD_DOMAIN_SUBST = "${domain}"; const std::string AclData::ACL_KEYWORD_USERDOMAIN_SUBST = "${userdomain}"; const std::string AclData::ACL_KEYWORD_ALL = "all"; const std::string AclData::ACL_KEYWORD_ACL = "acl"; const std::string AclData::ACL_KEYWORD_GROUP = "group"; const std::string AclData::ACL_KEYWORD_QUOTA = "quota"; const std::string AclData::ACL_KEYWORD_QUOTA_CONNECTIONS = "connections"; const std::string AclData::ACL_KEYWORD_QUOTA_QUEUES = "queues"; const char AclData::ACL_SYMBOL_WILDCARD = '*'; const std::string AclData::ACL_KEYWORD_WILDCARD = "*"; const char AclData::ACL_SYMBOL_LINE_CONTINUATION = '\\'; const std::string AclData::ACL_KEYWORD_DEFAULT_EXCHANGE = "amq.default"; // // constructor // AclData::AclData(): decisionMode(qpid::acl::DENY), transferAcl(false), aclSource("UNKNOWN"), connectionDecisionMode(qpid::acl::ALLOW), connQuotaRuleSettings(new quotaRuleSet), queueQuotaRuleSettings(new quotaRuleSet), connBWHostsGlobalRules(new bwHostRuleSet), connBWHostsUserRules(new bwHostUserRuleMap) { for (unsigned int cnt=0; cnt< qpid::acl::ACTIONSIZE; cnt++) { actionList[cnt]=0; } } // // clear // void AclData::clear () { for (unsigned int cnt=0; cnt< qpid::acl::ACTIONSIZE; cnt++) { if (actionList[cnt]) { for (unsigned int cnt1=0; cnt1< qpid::acl::OBJECTSIZE; cnt1++) { delete actionList[cnt][cnt1]; } } delete[] actionList[cnt]; } transferAcl = false; connectionDecisionMode = qpid::acl::ALLOW; connQuotaRuleSettings->clear(); queueQuotaRuleSettings->clear(); connBWHostsGlobalRules->clear(); connBWHostsUserRules->clear(); } void AclData::printDecisionRules(int userFieldWidth) { AclValidator validator; QPID_LOG(trace, "ACL: Decision rule cross reference"); for (int act=0; actbegin(); aoitr != actionList[act][obj]->end(); aoitr++) { std::string user = (*aoitr).first; ruleSetItr rsitr = (*aoitr).second.end(); for (size_t rCnt=0; rCnt < (*aoitr).second.size(); rCnt++) { rsitr--; std::vector candidates; validator.findPossibleLookupMatch( action, object, rsitr->props, candidates); std::stringstream ss; std::string sep(""); for (std::vector::const_iterator itr = candidates.begin(); itr != candidates.end(); itr++) { ss << sep << *itr; sep = ","; } QPID_LOG(trace, "ACL: User: " << std::setfill(' ') << std::setw(userFieldWidth +1) << std::left << user << " " << std::setfill(' ') << std::setw(acl::ACTION_STR_WIDTH +1) << std::left << AclHelper::getActionStr(action) << std::setfill(' ') << std::setw(acl::OBJECTTYPE_STR_WIDTH) << std::left << AclHelper::getObjectTypeStr(object) << " Rule: " << rsitr->toString() << " may match Lookups : (" << ss.str() << ")"); } } } else { // no rules for action/object } } } } // // matchProp // // Compare a rule's property name with a lookup name, // The rule's name may contain a trailing '*' to specify a wildcard match. // bool AclData::matchProp(const std::string& ruleStr, const std::string& lookupStr) { // allow wildcard on the end of rule strings... if (ruleStr.data()[ruleStr.size()-1]==ACL_SYMBOL_WILDCARD) { return ruleStr.compare(0, ruleStr.size()-1, lookupStr, 0, ruleStr.size()-1 ) == 0; } else { return ruleStr.compare(lookupStr) == 0; } } // // lookupMatchRule // // Check a single rule and if it's a match return the decision // bool AclData::lookupMatchRule( const ruleSetItr& rsItr, const std::string& id, const std::string& name, const std::map* params, AclResult& aclresult) { QPID_LOG(debug, "ACL: checking rule " << rsItr->toString()); bool match = true; bool limitChecked = true; // Iterate this rule's properties. A 'match' is true when // all of the rule's properties are found to be satisfied // in the lookup param list. The lookup may specify things // (they usually do) that are not in the rule properties but // these things don't interfere with the rule match. for (specPropertyMapItr rulePropMapItr = rsItr->props.begin(); (rulePropMapItr != rsItr->props.end()) && match; rulePropMapItr++) { // The rule property map's NAME property is given in // the calling args and not in the param map. if (rulePropMapItr->first == acl::SPECPROP_NAME) { // substitute user name into object name bool result; if (rsItr->ruleHasUserSub[PROP_NAME]) { std::string sName(rulePropMapItr->second); substituteUserId(sName, id); result = matchProp(sName, name); } else { result = matchProp(rulePropMapItr->second, name); } if (result) { QPID_LOG(debug, "ACL: lookup name '" << name << "' matched with rule name '" << rulePropMapItr->second << "'"); } else { match = false; QPID_LOG(debug, "ACL: lookup name '" << name << "' didn't match with rule name '" << rulePropMapItr->second << "'"); } } else { if (params) { // The rule's property map non-NAME properties // found in the lookup's params list. // In some cases the param's index is not the same // as rule's index. propertyMapItr lookupParamItr; switch (rulePropMapItr->first) { case acl::SPECPROP_MAXPAGESLOWERLIMIT: case acl::SPECPROP_MAXPAGESUPPERLIMIT: lookupParamItr = params->find(PROP_MAXPAGES); break; case acl::SPECPROP_MAXPAGEFACTORLOWERLIMIT: case acl::SPECPROP_MAXPAGEFACTORUPPERLIMIT: lookupParamItr = params->find(PROP_MAXPAGEFACTOR); break; case acl::SPECPROP_MAXQUEUECOUNTUPPERLIMIT: case acl::SPECPROP_MAXQUEUECOUNTLOWERLIMIT: lookupParamItr = params->find(PROP_MAXQUEUECOUNT); break; case acl::SPECPROP_MAXQUEUESIZEUPPERLIMIT: case acl::SPECPROP_MAXQUEUESIZELOWERLIMIT: lookupParamItr = params->find(PROP_MAXQUEUESIZE); break; case acl::SPECPROP_MAXFILECOUNTUPPERLIMIT: case acl::SPECPROP_MAXFILECOUNTLOWERLIMIT: lookupParamItr = params->find(PROP_MAXFILECOUNT); break; case acl::SPECPROP_MAXFILESIZEUPPERLIMIT: case acl::SPECPROP_MAXFILESIZELOWERLIMIT: lookupParamItr = params->find(PROP_MAXFILESIZE); break; default: lookupParamItr = params->find((Property)rulePropMapItr->first); break; }; if (lookupParamItr == params->end()) { // Now the rule has a specified property // that does not exist in the caller's // lookup params list. // This rule does not match. match = false; QPID_LOG(debug, "ACL: lookup parameter map doesn't contain the rule property '" << AclHelper::getPropertyStr(rulePropMapItr->first) << "'"); } else { // Now account for the business of rules // whose property indexes are mismatched. switch (rulePropMapItr->first) { case acl::SPECPROP_MAXQUEUECOUNTUPPERLIMIT: case acl::SPECPROP_MAXQUEUESIZEUPPERLIMIT: case acl::SPECPROP_MAXFILECOUNTUPPERLIMIT: case acl::SPECPROP_MAXFILESIZEUPPERLIMIT: case acl::SPECPROP_MAXPAGESUPPERLIMIT: case acl::SPECPROP_MAXPAGEFACTORUPPERLIMIT: limitChecked &= compareInt( rulePropMapItr->first, boost::lexical_cast(rulePropMapItr->second), boost::lexical_cast(lookupParamItr->second), true); break; case acl::SPECPROP_MAXQUEUECOUNTLOWERLIMIT: case acl::SPECPROP_MAXQUEUESIZELOWERLIMIT: case acl::SPECPROP_MAXFILECOUNTLOWERLIMIT: case acl::SPECPROP_MAXFILESIZELOWERLIMIT: case acl::SPECPROP_MAXPAGESLOWERLIMIT: case acl::SPECPROP_MAXPAGEFACTORLOWERLIMIT: limitChecked &= compareInt( rulePropMapItr->first, boost::lexical_cast(rulePropMapItr->second), boost::lexical_cast(lookupParamItr->second), false); break; default: bool result; if ((SPECPROP_ALTERNATE == rulePropMapItr->first && rsItr->ruleHasUserSub[PROP_ALTERNATE]) || (SPECPROP_QUEUENAME == rulePropMapItr->first && rsItr->ruleHasUserSub[PROP_QUEUENAME])) { // These properties are allowed to have username substitution std::string sName(rulePropMapItr->second); substituteUserId(sName, id); result = matchProp(sName, lookupParamItr->second); } else if (SPECPROP_ROUTINGKEY == rulePropMapItr->first) { // Routing key is allowed to have username substitution // and it gets topic exchange matching if (rsItr->ruleHasUserSub[PROP_ROUTINGKEY]) { std::string sKey(lookupParamItr->second); substituteKeywords(sKey, id); result = rsItr->matchRoutingKey(sKey); } else { result = rsItr->matchRoutingKey(lookupParamItr->second); } } else { // Rules without substitution result = matchProp(rulePropMapItr->second, lookupParamItr->second); } if (result) { QPID_LOG(debug, "ACL: the pair(" << AclHelper::getPropertyStr(lookupParamItr->first) << "," << lookupParamItr->second << ") given in lookup matched the pair(" << AclHelper::getPropertyStr(rulePropMapItr->first) << "," << rulePropMapItr->second << ") given in the rule"); } else { match = false; QPID_LOG(debug, "ACL: the pair(" << AclHelper::getPropertyStr(lookupParamItr->first) << "," << lookupParamItr->second << ") given in lookup doesn't match the pair(" << AclHelper::getPropertyStr(rulePropMapItr->first) << "," << rulePropMapItr->second << ") given in the rule"); } break; }; } } else { // params don't exist. } } } if (match) { aclresult = rsItr->ruleMode; if (!limitChecked) { // Now a lookup matched all rule properties but one // of the numeric limit checks has failed. // Demote allow rules to corresponding deny rules. switch (aclresult) { case acl::ALLOW: aclresult = acl::DENY; break; case acl::ALLOWLOG: aclresult = acl::DENYLOG; break; default: break; }; } QPID_LOG(debug,"ACL: Successful match, the decision is:" << AclHelper::getAclResultStr(aclresult)); } else { // This rule did not match the requested lookup and // does not contribute to an ACL decision. } return match; } // // lookup - general ACL lookup // // The ACL main business logic function of matching rules and declaring // an allow or deny result. // AclResult AclData::lookup( const std::string& id, const Action& action, const ObjectType& objType, const std::string& name, std::map* params) { QPID_LOG(debug, "ACL: Lookup for id:" << id << " action:" << AclHelper::getActionStr((Action) action) << " objectType:" << AclHelper::getObjectTypeStr((ObjectType) objType) << " name:" << name << " with params " << AclHelper::propertyMapToString(params)); // A typical log looks like: // ACL: Lookup for id:bob@QPID action:create objectType:queue name:q2 // with params { durable=false passive=false autodelete=false // exclusive=false alternate= policytype= maxqueuesize=0 // maxqueuecount=0 } // Default result is blanket decision mode for the entire ACL list. AclResult aclresult = decisionMode; // Test for lists of rules at the intersection of the Action & Object if (actionList[action] && actionList[action][objType]) { // Find the list of rules for this actorId AclData::actObjItr itrRule = actionList[action][objType]->find(id); // If individual actorId not found then find a rule set for '*'. if (itrRule == actionList[action][objType]->end()) { itrRule = actionList[action][objType]->find(ACL_KEYWORD_WILDCARD); } if (itrRule != actionList[action][objType]->end()) { // A list of rules exists for this actor/action/object tuple. // Iterate the rule set to search for a matching rule. ruleSetItr rsItr = itrRule->second.end(); for (int cnt = itrRule->second.size(); cnt != 0; cnt--) { rsItr--; if (lookupMatchRule(rsItr, id, name, params, aclresult)) { return aclresult; } } } else { // The Action-Object list has entries but not for this actorId // nor for *. } } else { // The Action-Object list has no entries. } QPID_LOG(debug,"ACL: No successful match, defaulting to the decision mode " << AclHelper::getAclResultStr(aclresult)); return aclresult; } // // lookupMatchPublishExchangeRule // // check a single publish exchange rule // bool AclData::lookupMatchPublishExchangeRule( const ruleSetItr& rsItr, const std::string& id, const std::string& name, const std::string& routingKey, AclResult& aclresult) { QPID_LOG(debug, "ACL: checking rule " << rsItr->toString()); // Search on exchange name and routing key only if specfied in rule. bool match =true; if (rsItr->pubExchNameInRule) { // substitute user name into object name bool result; if (rsItr->ruleHasUserSub[PROP_NAME]) { std::string sName(rsItr->pubExchName); substituteUserId(sName, id); result = matchProp(sName, name); } else if (rsItr->pubExchNameMatchesBlank) { result = name.empty(); } else { result = matchProp(rsItr->pubExchName, name); } if (result) { QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup exchange name '" << name << "' matched with rule name '" << rsItr->pubExchName << "'"); } else { match= false; QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup exchange name '" << name << "' did not match with rule name '" << rsItr->pubExchName << "'"); } } if (match && rsItr->pubRoutingKeyInRule) { if ((routingKey.find(ACL_KEYWORD_USER_SUBST, 0) != std::string::npos) || (routingKey.find(ACL_KEYWORD_DOMAIN_SUBST, 0) != std::string::npos) || (routingKey.find(ACL_KEYWORD_USERDOMAIN_SUBST, 0) != std::string::npos)) { // The user is not allowed to present a routing key with the substitution key in it QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " User-specified routing key has substitution wildcard:" << routingKey << ". Rule match prohibited."); match = false; } else { bool result; if (rsItr->ruleHasUserSub[PROP_ROUTINGKEY]) { std::string sKey(routingKey); substituteKeywords(sKey, id); result = rsItr->matchRoutingKey(sKey); } else { result = rsItr->matchRoutingKey(routingKey); } if (result) { QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup key name '" << routingKey << "' matched with rule routing key '" << rsItr->pubRoutingKey << "'"); } else { QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup key name '" << routingKey << "' did not match with rule routing key '" << rsItr->pubRoutingKey << "'"); match = false; } } } if (match) { aclresult = rsItr->ruleMode; QPID_LOG(debug,"ACL: Rule: " << rsItr->rawRuleNum << " Successful match, the decision is:" << AclHelper::getAclResultStr(aclresult)); } return match; } // // lookup - special PUBLISH EXCHANGE lookup // // The ACL main business logic function of matching rules and declaring // an allow or deny result. This lookup is the fastpath per-message // lookup to verify if a user is allowed to publish to an exchange with // a given key. // AclResult AclData::lookup( const std::string& id, const Action& action, const ObjectType& objType, const std::string& /*Exchange*/ name, const std::string& routingKey) { QPID_LOG(debug, "ACL: Lookup for id:" << id << " action:" << AclHelper::getActionStr((Action) action) << " objectType:" << AclHelper::getObjectTypeStr((ObjectType) objType) << " exchange name:" << name << " with routing key " << routingKey); AclResult aclresult = decisionMode; if (actionList[action] && actionList[action][objType]){ AclData::actObjItr itrRule = actionList[action][objType]->find(id); if (itrRule == actionList[action][objType]->end()) { itrRule = actionList[action][objType]->find(ACL_KEYWORD_WILDCARD); } if (itrRule != actionList[action][objType]->end() ) { // Found a rule list for this user-action-object set. // Search the rule list for a matching rule. ruleSetItr rsItr = itrRule->second.end(); for (int cnt = itrRule->second.size(); cnt != 0; cnt--) { rsItr--; if (lookupMatchPublishExchangeRule(rsItr, id, name, routingKey, aclresult)) { return aclresult; } } } } QPID_LOG(debug,"ACL: No successful match, defaulting to the decision mode " << AclHelper::getAclResultStr(aclresult)); return aclresult; } // // // void AclData::setConnQuotaRuleSettings ( boost::shared_ptr quotaPtr) { connQuotaRuleSettings = quotaPtr; } // // getConnQuotaForUser // // Return the true or false value of connQuotaRulesExist, // indicating whether any kind of lookup was done or not. // // When lookups are performed return the result value of // 1. The user's setting else // 2. The 'all' user setting else // 3. Zero // When lookups are not performed then return a result value of Zero. // bool AclData::getConnQuotaForUser(const std::string& theUserName, uint16_t* theResult) const { if (this->enforcingConnectionQuotas()) { // look for this user explicitly quotaRuleSetItr nameItr = (*connQuotaRuleSettings).find(theUserName); if (nameItr != (*connQuotaRuleSettings).end()) { QPID_LOG(trace, "ACL: Connection quota for user " << theUserName << " explicitly set to : " << (*nameItr).second); *theResult = (*nameItr).second; } else { // Look for the 'all' user nameItr = (*connQuotaRuleSettings).find(ACL_KEYWORD_ALL); if (nameItr != (*connQuotaRuleSettings).end()) { QPID_LOG(trace, "ACL: Connection quota for user " << theUserName << " chosen through value for 'all' : " << (*nameItr).second); *theResult = (*nameItr).second; } else { // Neither userName nor "all" found. QPID_LOG(trace, "ACL: Connection quota for user " << theUserName << " absent in quota settings. Return value : 0"); *theResult = 0; } } } else { // Rules do not exist QPID_LOG(trace, "ACL: Connection quota for user " << theUserName << " unavailable; quota settings are not specified. Return value : 0"); *theResult = 0; } return this->enforcingConnectionQuotas(); } // // // void AclData::setQueueQuotaRuleSettings ( boost::shared_ptr quotaPtr) { queueQuotaRuleSettings = quotaPtr; } // // getQueueQuotaForUser // // Return the true or false value of queueQuotaRulesExist, // indicating whether any kind of lookup was done or not. // // When lookups are performed return the result value of // 1. The user's setting else // 2. The 'all' user setting else // 3. Zero // When lookups are not performed then return a result value of Zero. // bool AclData::getQueueQuotaForUser(const std::string& theUserName, uint16_t* theResult) const { if (this->enforcingQueueQuotas()) { // look for this user explicitly quotaRuleSetItr nameItr = (*queueQuotaRuleSettings).find(theUserName); if (nameItr != (*queueQuotaRuleSettings).end()) { QPID_LOG(trace, "ACL: Queue quota for user " << theUserName << " explicitly set to : " << (*nameItr).second); *theResult = (*nameItr).second; } else { // Look for the 'all' user nameItr = (*queueQuotaRuleSettings).find(ACL_KEYWORD_ALL); if (nameItr != (*queueQuotaRuleSettings).end()) { QPID_LOG(trace, "ACL: Queue quota for user " << theUserName << " chosen through value for 'all' : " << (*nameItr).second); *theResult = (*nameItr).second; } else { // Neither userName nor "all" found. QPID_LOG(trace, "ACL: Queue quota for user " << theUserName << " absent in quota settings. Return value : 0"); *theResult = 0; } } } else { // Rules do not exist QPID_LOG(trace, "ACL: Queue quota for user " << theUserName << " unavailable; quota settings are not specified. Return value : 0"); *theResult = 0; } return this->enforcingQueueQuotas(); } void AclData::setConnGlobalRules (boost::shared_ptr cgr) { connBWHostsGlobalRules = cgr; } void AclData::setConnUserRules (boost::shared_ptr hurm) { connBWHostsUserRules = hurm; } AclResult AclData::isAllowedConnection(const std::string& userName, const std::string& hostName, std::string& logText) { bool decisionMade(false); AclResult result(ALLOW); for (bwHostRuleSetItr it=connBWHostsGlobalRules->begin(); it!=connBWHostsGlobalRules->end(); it++) { if (it->getAclHost().match(hostName)) { // This host matches a global spec and controls the // allow/deny decision for this connection. result = it->getAclResult(); logText = QPID_MSG("global rule " << it->toString() << (AclHelper::resultAllows(result) ? " allows" : " denies") << " connection for host " << hostName << ", user " << userName); decisionMade = true; break; } else { // This rule in the global spec doesn't match and // does not control the allow/deny decision. } } // Run user black/white list check if (!decisionMade) { bwHostUserRuleMapItr itrRule = connBWHostsUserRules->find(userName); if (itrRule != connBWHostsUserRules->end()) { for (bwHostRuleSetItr it=(*itrRule).second.begin(); it!=(*itrRule).second.end(); it++) { if (it->getAclHost().match(hostName)) { // This host matches a user spec and controls the // allow/deny decision for this connection. result = it->getAclResult(); logText = QPID_MSG("global rule " << it->toString() << (AclHelper::resultAllows(result) ? " allows" : " denies") << " connection for host " << hostName << ", user " << userName); decisionMade = true; break; } else { // This rule in the user's spec doesn't match and // does not control the allow/deny decision. } } } } // Apply global connection mode if (!decisionMade) { result = connectionDecisionMode; logText = QPID_MSG("default connection policy " << (AclHelper::resultAllows(result) ? "allows" : "denies") << " connection for host " << hostName << ", user " << userName); } return result; } // // // AclData::~AclData() { clear(); } // // Limit check an int limit // bool AclData::compareInt(const qpid::acl::SpecProperty theProperty, const std::string theAclValue, const std::string theLookupValue, bool theMaxFlag) { uint64_t aclRuleValue (0); uint64_t lookupValue (0); QPID_LOG(debug, "ACL: " << (theMaxFlag ? "Upper" : "Lower") << "-limit comparison for property " << AclHelper::getPropertyStr(theProperty) << ". Success if lookup(" << theLookupValue << ") " << (theMaxFlag ? "<=" : ">=") << " rule(" << theAclValue << ")"); try { aclRuleValue = boost::lexical_cast(theAclValue); } catch(const boost::bad_lexical_cast&) { assert (false); return false; } if (aclRuleValue == 0) { QPID_LOG(debug, "ACL: Comparison is always true when ACL rule value is zero"); return true; } try { lookupValue = boost::lexical_cast(theLookupValue); } catch(const boost::bad_lexical_cast&) { QPID_LOG(error,"ACL: Illegal value given in lookup for property '" << AclHelper::getPropertyStr(theProperty) << "' : " << theLookupValue); return false; } bool result = (theMaxFlag ? lookupValue > aclRuleValue : lookupValue < aclRuleValue); if ( result ) { QPID_LOG(debug, "ACL: Limit exceeded for property '" << AclHelper::getPropertyStr(theProperty) << "'"); return false; } return true; } const std::string DOMAIN_SEPARATOR("@"); const std::string PERIOD("."); const std::string UNDERSCORE("_"); // // substituteString // Given a name string from an Acl rule, substitute the replacement into it // wherever the placeholder directs. // void AclData::substituteString(std::string& targetString, const std::string& placeholder, const std::string& replacement) { assert (!placeholder.empty()); if (placeholder.empty()) { return; } size_t start_pos(0); while((start_pos = targetString.find(placeholder, start_pos)) != std::string::npos) { targetString.replace(start_pos, placeholder.length(), replacement); start_pos += replacement.length(); } } // // normalizeUserId // Given a name string return it in a form usable as topic keys: // change "@" and "." to "_". // std::string AclData::normalizeUserId(const std::string& userId) { std::string normalId(userId); substituteString(normalId, DOMAIN_SEPARATOR, UNDERSCORE); substituteString(normalId, PERIOD, UNDERSCORE); return normalId; } // // substituteUserId // Given an Acl rule and an authenticated userId // do the keyword substitutions on the rule. // void AclData::substituteUserId(std::string& ruleString, const std::string& userId) { size_t locDomSeparator(0); std::string user(""); std::string domain(""); std::string userdomain = normalizeUserId(userId); locDomSeparator = userId.find(DOMAIN_SEPARATOR); if (std::string::npos == locDomSeparator) { // "@" not found. There's just a user name user = normalizeUserId(userId); } else { // "@" found, split the names. Domain may be blank. user = normalizeUserId(userId.substr(0,locDomSeparator)); domain = normalizeUserId(userId.substr(locDomSeparator+1)); } substituteString(ruleString, ACL_KEYWORD_USER_SUBST, user); substituteString(ruleString, ACL_KEYWORD_DOMAIN_SUBST, domain); substituteString(ruleString, ACL_KEYWORD_USERDOMAIN_SUBST, userdomain); } // // substituteKeywords // Given an Acl rule and an authenticated userId // do reverse keyword substitutions on the rule. // That is, replace the normalized name in the rule string with // the keyword that represents it. This stragegy is used for // topic key lookups where the keyword string proper is in the // topic key search tree. // void AclData::substituteKeywords(std::string& ruleString, const std::string& userId) { size_t locDomSeparator(0); std::string user(""); std::string domain(""); std::string userdomain = normalizeUserId(userId); locDomSeparator = userId.find(DOMAIN_SEPARATOR); if (std::string::npos == locDomSeparator) { // "@" not found. There's just a user name user = normalizeUserId(userId); } else { // "@" found, split the names user = normalizeUserId(userId.substr(0,locDomSeparator)); domain = normalizeUserId(userId.substr(locDomSeparator+1)); } std::string oRule(ruleString); substituteString(ruleString, userdomain, ACL_KEYWORD_USERDOMAIN_SUBST); substituteString(ruleString, user, ACL_KEYWORD_USER_SUBST); substituteString(ruleString, domain, ACL_KEYWORD_DOMAIN_SUBST); } }}