diff options
| author | Charles E. Rolke <chug@apache.org> | 2012-03-01 18:45:45 +0000 |
|---|---|---|
| committer | Charles E. Rolke <chug@apache.org> | 2012-03-01 18:45:45 +0000 |
| commit | 17afa008aae1e5e302e7aa097916a124bf4b7dc7 (patch) | |
| tree | 6c4b74773910b0a07363ba6f1054e41f91b8cf36 /cpp/src/qpid | |
| parent | 74a71b09b9be431ee4fbc2a2b1c08341b9a34b72 (diff) | |
| download | qpid-python-17afa008aae1e5e302e7aa097916a124bf4b7dc7.tar.gz | |
QPID-3799 Acl update. Merge from branches/QPID-3799-acl
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1295730 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid')
| -rw-r--r-- | cpp/src/qpid/acl/Acl.cpp | 78 | ||||
| -rw-r--r-- | cpp/src/qpid/acl/Acl.h | 29 | ||||
| -rw-r--r-- | cpp/src/qpid/acl/AclData.cpp | 568 | ||||
| -rw-r--r-- | cpp/src/qpid/acl/AclData.h | 89 | ||||
| -rw-r--r-- | cpp/src/qpid/acl/AclReader.cpp | 222 | ||||
| -rw-r--r-- | cpp/src/qpid/acl/AclReader.h | 80 | ||||
| -rw-r--r-- | cpp/src/qpid/acl/AclValidator.cpp | 61 | ||||
| -rw-r--r-- | cpp/src/qpid/acl/AclValidator.h | 24 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/AclModule.h | 182 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/ConnectionHandler.h | 1 | ||||
| -rw-r--r-- | cpp/src/qpid/broker/SemanticState.h | 1 |
11 files changed, 890 insertions, 445 deletions
diff --git a/cpp/src/qpid/acl/Acl.cpp b/cpp/src/qpid/acl/Acl.cpp index 12bf13018c..6f758e46bf 100644 --- a/cpp/src/qpid/acl/Acl.cpp +++ b/cpp/src/qpid/acl/Acl.cpp @@ -66,10 +66,15 @@ Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(fals if (mgmtObject!=0) mgmtObject->set_enforcingAcl(1); } -bool Acl::authorise(const std::string& id, const Action& action, const ObjectType& objType, const std::string& name, std::map<Property, std::string>* params) +bool Acl::authorise( + const std::string& id, + const Action& action, + const ObjectType& objType, + const std::string& name, + std::map<Property, std::string>* params) { boost::shared_ptr<AclData> dataLocal; - { + { Mutex::ScopedLock locker(dataLock); dataLocal = data; //rcu copy } @@ -81,7 +86,12 @@ bool Acl::authorise(const std::string& id, const Action& action, const ObjectTyp return result(aclreslt, id, action, objType, name); } -bool Acl::authorise(const std::string& id, const Action& action, const ObjectType& objType, const std::string& ExchangeName, const std::string& RoutingKey) +bool Acl::authorise( + const std::string& id, + const Action& action, + const ObjectType& objType, + const std::string& ExchangeName, + const std::string& RoutingKey) { boost::shared_ptr<AclData> dataLocal; { @@ -96,31 +106,51 @@ bool Acl::authorise(const std::string& id, const Action& action, const ObjectTyp } -bool Acl::result(const AclResult& aclreslt, const std::string& id, const Action& action, const ObjectType& objType, const std::string& name) +bool Acl::result( + const AclResult& aclreslt, + const std::string& id, + const Action& action, + const ObjectType& objType, + const std::string& name) { + bool result(false); + switch (aclreslt) { case ALLOWLOG: - QPID_LOG(info, "ACL Allow id:" << id <<" action:" << AclHelper::getActionStr(action) << - " ObjectType:" << AclHelper::getObjectTypeStr(objType) << " Name:" << name ); + QPID_LOG(info, "ACL Allow id:" << id + << " action:" << AclHelper::getActionStr(action) + << " ObjectType:" << AclHelper::getObjectTypeStr(objType) + << " Name:" << name ); agent->raiseEvent(_qmf::EventAllow(id, AclHelper::getActionStr(action), - AclHelper::getObjectTypeStr(objType), - name, types::Variant::Map())); + AclHelper::getObjectTypeStr(objType), + name, types::Variant::Map())); + // FALLTHROUGH case ALLOW: - return true; - case DENY: - if (mgmtObject!=0) mgmtObject->inc_aclDenyCount(); - return false; + result = true; + break; + case DENYLOG: - if (mgmtObject!=0) mgmtObject->inc_aclDenyCount(); - default: - QPID_LOG(info, "ACL Deny id:" << id << " action:" << AclHelper::getActionStr(action) << " ObjectType:" << AclHelper::getObjectTypeStr(objType) << " Name:" << name); + QPID_LOG(info, "ACL Deny id:" << id + << " action:" << AclHelper::getActionStr(action) + << " ObjectType:" << AclHelper::getObjectTypeStr(objType) + << " Name:" << name); agent->raiseEvent(_qmf::EventDeny(id, AclHelper::getActionStr(action), - AclHelper::getObjectTypeStr(objType), - name, types::Variant::Map())); - return false; + AclHelper::getObjectTypeStr(objType), + name, types::Variant::Map())); + // FALLTHROUGH + case DENY: + if (mgmtObject!=0) + mgmtObject->inc_aclDenyCount(); + result = false; + break; + + default: + assert (false); } - return false; + + QPID_LOG(debug, "ACL result() returns " << result); + return result; } bool Acl::readAclFile(std::string& errorText) @@ -129,7 +159,7 @@ bool Acl::readAclFile(std::string& errorText) return readAclFile(aclValues.aclFile, errorText); } -bool Acl::readAclFile(std::string& aclFile, std::string& errorText) { +bool Acl::readAclFile(std::string& aclFile, std::string& errorText) { boost::shared_ptr<AclData> d(new AclData); AclReader ar; if (ar.read(aclFile, d)){ @@ -142,17 +172,17 @@ bool Acl::readAclFile(std::string& aclFile, std::string& errorText) { AclValidator validator; validator.validate(d); - { + { Mutex::ScopedLock locker(dataLock); data = d; } transferAcl = data->transferAcl; // any transfer ACL if (data->transferAcl){ - QPID_LOG(debug,"Transfer ACL is Enabled!"); + QPID_LOG(debug,"ACL: Transfer ACL is Enabled!"); } - data->aclSource = aclFile; + data->aclSource = aclFile; if (mgmtObject!=0){ mgmtObject->set_transferAcl(transferAcl?1:0); mgmtObject->set_policyFile(aclFile); @@ -174,7 +204,7 @@ ManagementObject* Acl::GetManagementObject(void) const Manageable::status_t Acl::ManagementMethod (uint32_t methodId, Args& /*args*/, string& text) { Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - QPID_LOG (debug, "Queue::ManagementMethod [id=" << methodId << "]"); + QPID_LOG (debug, "ACL: Queue::ManagementMethod [id=" << methodId << "]"); switch (methodId) { diff --git a/cpp/src/qpid/acl/Acl.h b/cpp/src/qpid/acl/Acl.h index 77f43838de..cc90fa4097 100644 --- a/cpp/src/qpid/acl/Acl.h +++ b/cpp/src/qpid/acl/Acl.h @@ -56,22 +56,39 @@ private: boost::shared_ptr<AclData> data; qmf::org::apache::qpid::acl::Acl* mgmtObject; // mgnt owns lifecycle qpid::management::ManagementAgent* agent; - mutable qpid::sys::Mutex dataLock; + mutable qpid::sys::Mutex dataLock; public: Acl (AclValues& av, broker::Broker& b); void initialize(); - + inline virtual bool doTransferAcl() {return transferAcl;}; - + // create specilied authorise methods for cases that need faster matching as needed. - virtual bool authorise(const std::string& id, const Action& action, const ObjectType& objType, const std::string& name, std::map<Property, std::string>* params=0); - virtual bool authorise(const std::string& id, const Action& action, const ObjectType& objType, const std::string& ExchangeName,const std::string& RoutingKey); + virtual bool authorise( + const std::string& id, + const Action& action, + const ObjectType& objType, + const std::string& name, + std::map<Property, + std::string>* params=0); + + virtual bool authorise( + const std::string& id, + const Action& action, + const ObjectType& objType, + const std::string& ExchangeName, + const std::string& RoutingKey); virtual ~Acl(); private: - bool result(const AclResult& aclreslt, const std::string& id, const Action& action, const ObjectType& objType, const std::string& name); + bool result( + const AclResult& aclreslt, + const std::string& id, + const Action& action, + const ObjectType& objType, + const std::string& name); bool readAclFile(std::string& errorText); bool readAclFile(std::string& aclFile, std::string& errorText); virtual qpid::management::ManagementObject* GetManagementObject(void) const; diff --git a/cpp/src/qpid/acl/AclData.cpp b/cpp/src/qpid/acl/AclData.cpp index 06fc223a73..03a8a19db9 100644 --- a/cpp/src/qpid/acl/AclData.cpp +++ b/cpp/src/qpid/acl/AclData.cpp @@ -24,151 +24,301 @@ namespace qpid { namespace acl { - AclData::AclData():decisionMode(qpid::acl::DENY),transferAcl(false),aclSource("UNKNOWN") + // + // constructor + // + AclData::AclData(): + decisionMode(qpid::acl::DENY), + transferAcl(false), + aclSource("UNKNOWN") { - for (unsigned int cnt=0; cnt< qpid::acl::ACTIONSIZE; cnt++){ + 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 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][cnt1]; } delete[] actionList[cnt]; } - } - bool AclData::matchProp(const std::string & src, const std::string& src1) + + // + // matchProp + // + // Compare a rule's property name with a lookup name, + // The rule's name may contains a trailing '*' to specify a wildcard match. + // + bool AclData::matchProp(const std::string& ruleStr, + const std::string& lookupStr) { - // allow wildcard on the end of strings... - if (src.data()[src.size()-1]=='*') { - return (src.compare(0, src.size()-1, src1, 0,src.size()-1 ) == 0); - } else { - return (src.compare(src1)==0) ; + // allow wildcard on the end of rule strings... + if (ruleStr.data()[ruleStr.size()-1]=='*') + { + return ruleStr.compare(0, + ruleStr.size()-1, + lookupStr, + 0, + ruleStr.size()-1 ) == 0; + } + else + { + return ruleStr.compare(lookupStr) == 0; } } - AclResult AclData::lookup(const std::string& id, const Action& action, const ObjectType& objType, - const std::string& name, std::map<Property, std::string>* 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)); - - 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("*"); - - if (itrRule != actionList[action][objType]->end()) { - - QPID_LOG(debug, "ACL: checking the following rules for : " << itrRule->first ); - - //loop the vector - for (ruleSetItr i = itrRule->second.begin(); i < itrRule->second.end(); i++) { - QPID_LOG(debug, "ACL: checking rule " << i->toString()); - // loop the names looking for match - bool match = true; - for (propertyMapItr pMItr = i->props.begin(); (pMItr != i->props.end()) && match; pMItr++) { - //match name is exists first - if (pMItr->first == acl::PROP_NAME) { - if (matchProp(pMItr->second, name)){ - QPID_LOG(debug, "ACL: name '" << name << "' matched with name '" - << pMItr->second << "' given in the rule"); - }else{ + + // + // 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<Property, std::string>* 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("*"); + + 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--; + + 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) + { + if (matchProp(rulePropMapItr->second, name)) + { + 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_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; + + 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: name '" << name << "' didn't match with name '" - << pMItr->second << "' given in the rule"); + QPID_LOG(debug, "ACL: lookup parameter map doesn't contain the rule property '" + << AclHelper::getPropertyStr(rulePropMapItr->first) << "'"); } - } else if (params) { //match pMItr against params - propertyMapItr paramItr = params->find(pMItr->first); - if (paramItr == params->end()) { - match = false; - QPID_LOG(debug, "ACL: the given parameter map in lookup doesn't contain the property '" - << AclHelper::getPropertyStr(pMItr->first) << "'"); - }else if ( pMItr->first == acl::PROP_MAXQUEUECOUNT || pMItr->first == acl::PROP_MAXQUEUESIZE ) { - if ( pMItr->first == paramItr->first ) { - - uint64_t aclMax = 0; - uint64_t paramMax = 0; - - try{ - aclMax = boost::lexical_cast<uint64_t>(pMItr->second); - }catch(const boost::bad_lexical_cast&){ - match = false; - QPID_LOG(error,"Error evaluating rule. " << - "Illegal value given in ACL source <" << aclSource << - "> for property '" << - AclHelper::getPropertyStr(pMItr->first) << "' : " << - boost::lexical_cast<std::string>(pMItr->second)); - break; - } - - try{ - paramMax = boost::lexical_cast<uint64_t>(paramItr->second); - }catch(const boost::bad_lexical_cast&){ + else + { + // Now account for the business of rules + // whose property indexes are mismatched. + switch (rulePropMapItr->first) + { + case acl::SPECPROP_MAXQUEUECOUNTUPPERLIMIT: + case acl::SPECPROP_MAXQUEUESIZEUPPERLIMIT: + limitChecked &= + compareIntMax( + rulePropMapItr->first, + boost::lexical_cast<std::string>(rulePropMapItr->second), + boost::lexical_cast<std::string>(lookupParamItr->second)); + break; + + case acl::SPECPROP_MAXQUEUECOUNTLOWERLIMIT: + case acl::SPECPROP_MAXQUEUESIZELOWERLIMIT: + limitChecked &= + compareIntMin( + rulePropMapItr->first, + boost::lexical_cast<std::string>(rulePropMapItr->second), + boost::lexical_cast<std::string>(lookupParamItr->second)); + break; + + default: + if (matchProp(rulePropMapItr->second, lookupParamItr->second)) + { + 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(error,"Error evaluating rule. " << - "Illegal value given in lookup for property '" << - AclHelper::getPropertyStr(pMItr->first) << "' : " << - boost::lexical_cast<std::string>(paramItr->second)); - break; - } - - QPID_LOG(debug, "ACL: Numeric comparison for property " << - AclHelper::getPropertyStr(paramItr->first) << - " (value given in lookup = " << - boost::lexical_cast<std::string>(paramItr->second) << - ", value give in rule = " << - boost::lexical_cast<std::string>(pMItr->second) << " )"); - - if (( aclMax ) && ( paramMax == 0 || paramMax > aclMax)){ - match = decisionMode == qpid::acl::ALLOW ; - QPID_LOG(debug, "ACL: Limit exceeded and match=" << - (match ? "true": "false") << - " as decision mode is " << AclHelper::getAclResultStr(decisionMode)); + 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"); } - } - }else if (matchProp(pMItr->second, paramItr->second)) { - QPID_LOG(debug, "ACL: the pair(" - << AclHelper::getPropertyStr(paramItr->first) << "," << paramItr->second - << ") given in lookup matched the pair(" - << AclHelper::getPropertyStr(pMItr->first) << "," << pMItr->second << ") given in the rule"); - } else { - QPID_LOG(debug, "ACL: the pair(" - << AclHelper::getPropertyStr(paramItr->first) << "," << paramItr->second - << ") given in lookup doesn't match the pair(" - << AclHelper::getPropertyStr(pMItr->first) << "," << pMItr->second << ") given in the rule"); - match = false; - } + break; + }; + } + } + else + { + // params don't exist. } } - if (match) + } + if (match) + { + aclresult = rsItr->ruleMode; + if (!limitChecked) { - aclresult = getACLResult(i->logOnly, i->log); - QPID_LOG(debug,"Successful match, the decision is:" << AclHelper::getAclResultStr(aclresult)); - return aclresult; + // 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)); + return aclresult; + } + else + { + // This rule did not match the requested lookup and + // does not contribute to an ACL decision. } } } + 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,"No successful match, defaulting to the decision mode " << AclHelper::getAclResultStr(aclresult)); - return aclresult; + QPID_LOG(debug,"ACL: No successful match, defaulting to the decision mode " + << AclHelper::getAclResultStr(aclresult)); + return aclresult; } - AclResult AclData::lookup(const std::string& id, const Action& action, const ObjectType& objType, const std::string& /*Exchange*/ name, const std::string& RoutingKey) + + // + // 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& /*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 + 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; @@ -179,83 +329,181 @@ namespace acl { if (itrRule == actionList[action][objType]->end()) itrRule = actionList[action][objType]->find("*"); - if (itrRule != actionList[action][objType]->end() ) { - - QPID_LOG(debug, "ACL: checking the following rules for : " << itrRule->first ); - + if (itrRule != actionList[action][objType]->end() ) + { //loop the vector - for (ruleSetItr i=itrRule->second.begin(); i<itrRule->second.end(); i++) { - QPID_LOG(debug, "ACL: checking rule " << i->toString()); + ruleSetItr rsItr = itrRule->second.end(); + for (int cnt = itrRule->second.size(); cnt != 0; cnt--) + { + rsItr--; // loop the names looking for match bool match =true; - for (propertyMapItr pMItr = i->props.begin(); (pMItr != i->props.end()) && match; pMItr++) + for (specPropertyMapItr pMItr = rsItr->props.begin(); + (pMItr != rsItr->props.end()) && match; + pMItr++) { //match name is exists first - if (pMItr->first == acl::PROP_NAME){ - if (matchProp(pMItr->second, name)){ - QPID_LOG(debug, "ACL: name '" << name << "' matched with name '" - << pMItr->second << "' given in the rule"); + switch (pMItr->first) + { + case acl::SPECPROP_NAME: + if (matchProp(pMItr->second, name)) + { + QPID_LOG(debug, "ACL: lookup exchange name '" + << name << "' matched with rule name '" + << pMItr->second << "'"); - }else{ + } + else + { match= false; - QPID_LOG(debug, "ACL: name '" << name << "' didn't match with name '" - << pMItr->second << "' given in the rule"); - } - }else if (pMItr->first == acl::PROP_ROUTINGKEY){ - if (matchProp(pMItr->second, RoutingKey)){ - QPID_LOG(debug, "ACL: name '" << name << "' matched with routing_key '" - << pMItr->second << "' given in the rule"); - }else{ + QPID_LOG(debug, "ACL: lookup exchange name '" + << name << "' did not match with rule name '" + << pMItr->second << "'"); + } + break; + + case acl::SPECPROP_ROUTINGKEY: + if (matchProp(pMItr->second, RoutingKey)) + { + QPID_LOG(debug, "ACL: lookup key name '" + << name << "' matched with rule routing key '" + << pMItr->second << "'"); + } + else + { match= false; - QPID_LOG(debug, "ACL: name '" << name << "' didn't match with routing_key '" - << pMItr->second << "' given in the rule"); - } - } + QPID_LOG(debug, "ACL: lookup key name '" + << name << "' did not match with rule routing key '" + << pMItr->second << "'"); + } + break; + + default: + // Don't care + break; + }; } if (match){ - aclresult = getACLResult(i->logOnly, i->log); - QPID_LOG(debug,"Successful match, the decision is:" << AclHelper::getAclResultStr(aclresult)); + aclresult = rsItr->ruleMode; + QPID_LOG(debug,"ACL: Successful match, the decision is:" + << AclHelper::getAclResultStr(aclresult)); return aclresult; } } } } - QPID_LOG(debug,"No successful match, defaulting to the decision mode " << AclHelper::getAclResultStr(aclresult)); + QPID_LOG(debug,"ACL: No successful match, defaulting to the decision mode " + << AclHelper::getAclResultStr(aclresult)); return aclresult; } - AclResult AclData::getACLResult(bool logOnly, bool log) + // + // + // + AclData::~AclData() + { + clear(); + } + + + // + // Limit check a MAX int limit + // + bool AclData::compareIntMax(const qpid::acl::SpecProperty theProperty, + const std::string theAclValue, + const std::string theLookupValue) { - switch (decisionMode) + uint64_t aclMax (0); + uint64_t paramMax (0); + + try { - case qpid::acl::ALLOWLOG: - case qpid::acl::ALLOW: - if (logOnly) return qpid::acl::ALLOWLOG; - if (log) - return qpid::acl::DENYLOG; - else - return qpid::acl::DENY; + aclMax = boost::lexical_cast<uint64_t>(theAclValue); + } + catch(const boost::bad_lexical_cast&) + { + assert (false); + return false; + } + try + { + paramMax = boost::lexical_cast<uint64_t>(theLookupValue); + } + catch(const boost::bad_lexical_cast&) + { + QPID_LOG(error,"ACL: Error evaluating rule. " + << "Illegal value given in lookup for property '" + << AclHelper::getPropertyStr(theProperty) + << "' : " << theLookupValue); + return false; + } - case qpid::acl::DENYLOG: - case qpid::acl::DENY: - if (logOnly) return qpid::acl::DENYLOG; - if (log) - return qpid::acl::ALLOWLOG; - else - return qpid::acl::ALLOW; + QPID_LOG(debug, "ACL: Numeric greater-than comparison for property " + << AclHelper::getPropertyStr(theProperty) + << " (value given in lookup = " << theLookupValue + << ", value give in rule = " << theAclValue << " )"); + + if (( aclMax ) && ( paramMax == 0 || paramMax > aclMax)) + { + QPID_LOG(debug, "ACL: Max limit exceeded for property '" + << AclHelper::getPropertyStr(theProperty) << "'"); + return false; } - QPID_LOG(error, "ACL Decision Failed, setting DENY"); - return qpid::acl::DENY; + return true; } - AclData::~AclData() + + // + // limit check a MIN int limit + // + bool AclData::compareIntMin(const qpid::acl::SpecProperty theProperty, + const std::string theAclValue, + const std::string theLookupValue) { - clear(); + uint64_t aclMin (0); + uint64_t paramMin (0); + + try + { + aclMin = boost::lexical_cast<uint64_t>(theAclValue); + } + catch(const boost::bad_lexical_cast&) + { + assert (false); + return false; + } + + try + { + paramMin = boost::lexical_cast<uint64_t>(theLookupValue); + } + catch(const boost::bad_lexical_cast&) + { + QPID_LOG(error,"ACL: Error evaluating rule. " + << "Illegal value given in lookup for property '" + << AclHelper::getPropertyStr(theProperty) + << "' : " << theLookupValue); + return false; + } + + QPID_LOG(debug, "ACL: Numeric less-than comparison for property " + << AclHelper::getPropertyStr(theProperty) + << " (value given in lookup = " << theLookupValue + << ", value give in rule = " << theAclValue << " )"); + + if (( aclMin ) && ( paramMin == 0 || paramMin < aclMin)) + { + QPID_LOG(debug, "ACL: Min limit exceeded for property '" + << AclHelper::getPropertyStr(theProperty) << "'"); + return false; + } + + return true; } -}} +}} diff --git a/cpp/src/qpid/acl/AclData.h b/cpp/src/qpid/acl/AclData.h index 81125fdcbc..1c1cb3e9c6 100644 --- a/cpp/src/qpid/acl/AclData.h +++ b/cpp/src/qpid/acl/AclData.h @@ -33,50 +33,91 @@ class AclData { public: typedef std::map<qpid::acl::Property, std::string> propertyMap; - typedef propertyMap::const_iterator propertyMapItr; + typedef propertyMap::const_iterator propertyMapItr; + + typedef std::map<qpid::acl::SpecProperty, std::string> specPropertyMap; + typedef specPropertyMap::const_iterator specPropertyMapItr; + + // + // rule + // + // Created by AclReader and stored in a ruleSet vector for subsequent + // run-time lookup matching and allow/deny decisions. + // RuleSet vectors are indexed by Action-Object-actorId so these + // attributes are not part of a rule. + // A single ACL file entry may create many rule entries in + // many ruleset vectors. + // struct rule { - bool log; - bool logOnly; // this is a rule is to log only + int rawRuleNum; // rule number in ACL file + qpid::acl::AclResult ruleMode; // combined allow/deny log/nolog + specPropertyMap props; // - // key value map - //?? - propertyMap props; - - rule (propertyMap& p):log(false),logOnly(false),props(p) {}; + rule (int ruleNum, qpid::acl::AclResult res, specPropertyMap& p) : + rawRuleNum(ruleNum), + ruleMode(res), + props(p) + {}; std::string toString () const { std::ostringstream ruleStr; - ruleStr << "[log=" << log << ", logOnly=" << logOnly << " props{"; - for (propertyMapItr pMItr = props.begin(); pMItr != props.end(); pMItr++) { - ruleStr << " " << AclHelper::getPropertyStr((Property) pMItr-> first) << "=" << pMItr->second; + ruleStr << "[rule " << rawRuleNum + << " ruleMode = " << AclHelper::getAclResultStr(ruleMode) + << " props{"; + for (specPropertyMapItr pMItr = props.begin(); + pMItr != props.end(); + pMItr++) { + ruleStr << " " + << AclHelper::getPropertyStr((SpecProperty) pMItr-> first) + << "=" << pMItr->second; } ruleStr << " }]"; return ruleStr.str(); } }; - typedef std::vector<rule> ruleSet; - typedef ruleSet::const_iterator ruleSetItr; - typedef std::map<std::string, ruleSet > actionObject; // user - typedef actionObject::iterator actObjItr; - typedef actionObject* aclAction; - // Action*[] -> Object*[] -> map<user -> set<Rule> > - aclAction* actionList[qpid::acl::ACTIONSIZE]; - qpid::acl::AclResult decisionMode; // determines if the rule set is a deny or allow mode. - bool transferAcl; - std::string aclSource; + typedef std::vector<rule> ruleSet; + typedef ruleSet::const_iterator ruleSetItr; + typedef std::map<std::string, ruleSet > actionObject; // user + typedef actionObject::iterator actObjItr; + typedef actionObject* aclAction; - AclResult lookup(const std::string& id, const Action& action, const ObjectType& objType, const std::string& name, std::map<Property, std::string>* params=0); - AclResult lookup(const std::string& id, const Action& action, const ObjectType& objType, const std::string& ExchangeName, const std::string& RoutingKey); - AclResult getACLResult(bool logOnly, bool log); + // Action*[] -> Object*[] -> map<user -> set<Rule> > + aclAction* actionList[qpid::acl::ACTIONSIZE]; + qpid::acl::AclResult decisionMode; // allow/deny[-log] if no matching rule found + bool transferAcl; + std::string aclSource; + + AclResult lookup( + const std::string& id, // actor id + const Action& action, + const ObjectType& objType, + const std::string& name, // object name + std::map<Property, std::string>* params=0); + + AclResult lookup( + const std::string& id, // actor id + const Action& action, + const ObjectType& objType, + const std::string& ExchangeName, + const std::string& RoutingKey); bool matchProp(const std::string & src, const std::string& src1); void clear (); AclData(); virtual ~AclData(); + +private: + bool compareIntMax(const qpid::acl::SpecProperty theProperty, + const std::string theAclValue, + const std::string theLookupValue); + + bool compareIntMin(const qpid::acl::SpecProperty theProperty, + const std::string theAclValue, + const std::string theLookupValue); }; }} // namespace qpid::acl diff --git a/cpp/src/qpid/acl/AclReader.cpp b/cpp/src/qpid/acl/AclReader.cpp index 74358a20c1..80debf1bd1 100644 --- a/cpp/src/qpid/acl/AclReader.cpp +++ b/cpp/src/qpid/acl/AclReader.cpp @@ -49,7 +49,7 @@ namespace acl { objStatus = ALL; } - bool AclReader::aclRule::addProperty(const Property p, const std::string v) { + bool AclReader::aclRule::addProperty(const SpecProperty p, const std::string v) { return props.insert(propNvPair(p, v)).second; } @@ -85,146 +85,108 @@ namespace acl { void AclReader::loadDecisionData(boost::shared_ptr<AclData> d) { d->clear(); - QPID_LOG(debug, "ACL Load Rules"); - int cnt = rules.size(); + QPID_LOG(debug, "ACL: Load Rules"); bool foundmode = false; - for (rlCitr i = rules.end(); cnt; cnt--) { + rlCitr i = rules.end(); + for (int cnt = rules.size(); cnt; cnt--) { i--; - QPID_LOG(debug, "ACL Processing " << std::setfill(' ') << std::setw(2) + QPID_LOG(debug, "ACL: Processing " << std::setfill(' ') << std::setw(2) << cnt << " " << (*i)->toString()); if (!foundmode && (*i)->actionAll && (*i)->names.size() == 1 && (*((*i)->names.begin())).compare("*") == 0) { d->decisionMode = (*i)->res; - QPID_LOG(debug, "ACL FoundMode " + QPID_LOG(debug, "ACL: FoundMode " << AclHelper::getAclResultStr(d->decisionMode)); foundmode = true; } else { - AclData::rule rule((*i)->props); - bool addrule = true; - - switch ((*i)->res) { - case qpid::acl::ALLOWLOG: - rule.log = true; - if (d->decisionMode == qpid::acl::ALLOW || - d->decisionMode == qpid::acl::ALLOWLOG) - rule.logOnly = true; - break; - case qpid::acl::ALLOW: - if (d->decisionMode == qpid::acl::ALLOW || - d->decisionMode == qpid::acl::ALLOWLOG) - addrule = false; - break; - case qpid::acl::DENYLOG: - rule.log = true; - if (d->decisionMode == qpid::acl::DENY || - d->decisionMode == qpid::acl::DENYLOG) - rule.logOnly = true; - break; - case qpid::acl::DENY: - if (d->decisionMode == qpid::acl::DENY || - d->decisionMode == qpid::acl::DENYLOG) - addrule = false; - break; - default: - throw Exception("Invalid ACL Result loading rules."); - } + AclData::rule rule(cnt, (*i)->res, (*i)->props); // Action -> Object -> map<user -> set<Rule> > - if (addrule) { - 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 - - 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; - } - - // optimize this loop to limit to valid options only!! - 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("*") == 0) - allNames = true; - - for (nsCitr itr = (allNames ? names.begin() - : (*i)->names.begin()); - itr != (allNames ? names.end() : (*i)->names.end()); - itr++) { - - 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 { - // TODO add code to check for dead rules - // allow peter create queue name=tmp <-- dead rule!! - // allow peter create queue - - itrRule->second.push_back(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 + + 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; } - std::ostringstream objstr; - for (int ocnt = ((*i)->objStatus != aclRule::VALUE ? 0 : (*i)->object); + // TODO: optimize this loop to limit to valid options only!! + 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) << ","; + (*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("*") == 0) + allNames = true; + + for (nsCitr itr = (allNames ? names.begin() : (*i)->names.begin()); + itr != (allNames ? names.end() : (*i)->names.end()); + itr++) { + 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 { + // TODO add code to check for dead rules + // allow peter create queue name=tmp <-- dead rule!! + // allow peter create queue + + itrRule->second.push_back(rule); + } + } } + } - bool allNames = ((*(*i)->names.begin()).compare("*") == 0); - std::ostringstream userstr; - for (nsCitr itr = (allNames ? names.begin() : (*i)->names.begin()); - itr != (allNames ? names.end() : (*i)->names.end()); - itr++) { - userstr << *itr << ","; - } + 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) << ","; + } - 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) - << "}" ); - } else { - QPID_LOG(debug, "ACL Skipping based on Mode:" - << AclHelper::getAclResultStr(d->decisionMode)); + bool allNames = ((*(*i)->names.begin()).compare("*") == 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) + << "}" ); + } } - } @@ -277,7 +239,7 @@ namespace acl { } ifs.close(); if (err) return -3; - QPID_LOG(notice, "Read ACL file \"" << fn << "\""); + QPID_LOG(notice, "ACL: Read file \"" << fn << "\""); } catch (const std::exception& e) { errorStream << "Unable to read ACL file \"" << fn << "\": " << e.what(); ifs.close(); @@ -410,8 +372,8 @@ namespace acl { // Debug aid void AclReader::printNames() const { - QPID_LOG(debug, "Group list: " << groups.size() << " groups found:" ); - std::string tmp; + QPID_LOG(debug, "ACL: Group list: " << groups.size() << " groups found:" ); + std::string tmp("ACL: "); for (gmCitr i=groups.begin(); i!= groups.end(); i++) { tmp += " \""; tmp += i->first; @@ -421,10 +383,10 @@ namespace acl { tmp += *j; } QPID_LOG(debug, tmp); - tmp.clear(); + tmp = "ACL: "; } - QPID_LOG(debug, "Name list: " << names.size() << " names found:" ); - tmp.clear(); + QPID_LOG(debug, "ACL: name list: " << names.size() << " names found:" ); + tmp = "ACL: "; for (nsCitr k=names.begin(); k!=names.end(); k++) { tmp += " "; tmp += *k; @@ -501,9 +463,9 @@ namespace acl { << propNvp.first << "\". (Must be name=value)"; return false; } - Property prop; + SpecProperty prop; try { - prop = AclHelper::getProperty(propNvp.first); + prop = AclHelper::getSpecProperty(propNvp.first); } catch (...) { errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber << ", Unknown property \"" << propNvp.first << "\"."; @@ -532,10 +494,10 @@ namespace acl { // Debug aid void AclReader::printRules() const { - QPID_LOG(debug, "Rule list: " << rules.size() << " ACL rules found:"); - int cnt = 0; + QPID_LOG(debug, "ACL: Rule list: " << rules.size() << " ACL rules found:"); + int cnt = 1; for (rlCitr i=rules.begin(); i<rules.end(); i++,cnt++) { - QPID_LOG(debug, " " << std::setfill(' ') << std::setw(2) << cnt << " " << (*i)->toString()); + QPID_LOG(debug, "ACL: " << std::setfill(' ') << std::setw(2) << cnt << " " << (*i)->toString()); } } diff --git a/cpp/src/qpid/acl/AclReader.h b/cpp/src/qpid/acl/AclReader.h index 62c6f38f37..730013f4ed 100644 --- a/cpp/src/qpid/acl/AclReader.h +++ b/cpp/src/qpid/acl/AclReader.h @@ -33,65 +33,71 @@ namespace qpid { namespace acl { class AclReader { - typedef std::set<std::string> nameSet; - typedef nameSet::const_iterator nsCitr; - typedef boost::shared_ptr<nameSet> nameSetPtr; - - typedef std::pair<std::string, nameSetPtr> groupPair; - typedef std::map<std::string, nameSetPtr> groupMap; - typedef groupMap::const_iterator gmCitr; - typedef std::pair<gmCitr, bool> gmRes; - - typedef std::pair<Property, std::string> propNvPair; - typedef std::map<Property, std::string> propMap; - typedef propMap::const_iterator pmCitr; - + typedef std::set<std::string> nameSet; + typedef nameSet::const_iterator nsCitr; + typedef boost::shared_ptr<nameSet> nameSetPtr; + + typedef std::pair<std::string, nameSetPtr> groupPair; + typedef std::map<std::string, nameSetPtr> groupMap; + typedef groupMap::const_iterator gmCitr; + typedef std::pair<gmCitr, bool> gmRes; + + typedef std::pair<SpecProperty, std::string> propNvPair; + typedef std::map<SpecProperty, std::string> propMap; + typedef propMap::const_iterator pmCitr; + + // + // aclRule + // + // A temporary rule created during ACL file processing. + // class aclRule { public: enum objectStatus {NONE, VALUE, ALL}; - AclResult res; - nameSet names; - bool actionAll; // True if action is set to keyword "all" - Action action; // Ignored if action is set to keyword "all" - objectStatus objStatus; - ObjectType object; // Ignored for all status values except VALUE - propMap props; + + AclResult res; + nameSet names; + bool actionAll; // True if action is set to keyword "all" + Action action; // Ignored if action is set to keyword "all" + objectStatus objStatus; + ObjectType object; // Ignored for all status values except VALUE + propMap props; public: aclRule(const AclResult r, const std::string n, const groupMap& groups); // action = "all" aclRule(const AclResult r, const std::string n, const groupMap& groups, const Action a); void setObjectType(const ObjectType o); void setObjectTypeAll(); - bool addProperty(const Property p, const std::string v); + bool addProperty(const SpecProperty p, const std::string v); bool validate(const AclHelper::objectMapPtr& validationMap); std::string toString(); // debug aid private: void processName(const std::string& name, const groupMap& groups); }; - typedef boost::shared_ptr<aclRule> aclRulePtr; - typedef std::vector<aclRulePtr> ruleList; - typedef ruleList::const_iterator rlCitr; + typedef boost::shared_ptr<aclRule> aclRulePtr; + typedef std::vector<aclRulePtr> ruleList; + typedef ruleList::const_iterator rlCitr; - typedef std::vector<std::string> tokList; - typedef tokList::const_iterator tlCitr; + typedef std::vector<std::string> tokList; + typedef tokList::const_iterator tlCitr; - typedef std::set<std::string> keywordSet; - typedef keywordSet::const_iterator ksCitr; + typedef std::set<std::string> keywordSet; + typedef keywordSet::const_iterator ksCitr; typedef std::pair<std::string, std::string> nvPair; // Name-Value pair - std::string fileName; - int lineNumber; - bool contFlag; - std::string groupName; - nameSet names; - groupMap groups; - ruleList rules; + std::string fileName; + int lineNumber; + bool contFlag; + std::string groupName; + nameSet names; + groupMap groups; + ruleList rules; AclHelper::objectMapPtr validationMap; - std::ostringstream errorStream; + std::ostringstream errorStream; public: AclReader(); virtual ~AclReader(); - int read(const std::string& fn, boost::shared_ptr<AclData> d); + int read(const std::string& fn, boost::shared_ptr<AclData> d); // return=0 for success std::string getError(); private: diff --git a/cpp/src/qpid/acl/AclValidator.cpp b/cpp/src/qpid/acl/AclValidator.cpp index d5a00b005b..49bb65db4b 100644 --- a/cpp/src/qpid/acl/AclValidator.cpp +++ b/cpp/src/qpid/acl/AclValidator.cpp @@ -29,7 +29,7 @@ namespace qpid { namespace acl { - AclValidator::IntPropertyType::IntPropertyType(int64_t i,int64_t j) : min(i), max(j){ + AclValidator::IntPropertyType::IntPropertyType(int64_t i,int64_t j) : min(i), max(j){ } bool AclValidator::IntPropertyType::validate(const std::string& val) { @@ -49,12 +49,12 @@ namespace acl { } std::string AclValidator::IntPropertyType::allowedValues() { - return "values should be between " + + return "values should be between " + boost::lexical_cast<std::string>(min) + " and " + boost::lexical_cast<std::string>(max); } - AclValidator::EnumPropertyType::EnumPropertyType(std::vector<std::string>& allowed): values(allowed){ + AclValidator::EnumPropertyType::EnumPropertyType(std::vector<std::string>& allowed): values(allowed){ } bool AclValidator::EnumPropertyType::validate(const std::string& val) { @@ -78,24 +78,27 @@ namespace acl { } AclValidator::AclValidator(){ - validators.insert(Validator(acl::PROP_MAXQUEUESIZE, - boost::shared_ptr<PropertyType>( - new IntPropertyType(0,std::numeric_limits<int64_t>::max())) - ) - ); - - validators.insert(Validator(acl::PROP_MAXQUEUECOUNT, - boost::shared_ptr<PropertyType>( - new IntPropertyType(0,std::numeric_limits<int64_t>::max())) - ) - ); + validators.insert(Validator(acl::SPECPROP_MAXQUEUESIZELOWERLIMIT, + boost::shared_ptr<PropertyType>( + new IntPropertyType(0,std::numeric_limits<int64_t>::max())))); + + validators.insert(Validator(acl::SPECPROP_MAXQUEUESIZEUPPERLIMIT, + boost::shared_ptr<PropertyType>( + new IntPropertyType(0,std::numeric_limits<int64_t>::max())))); + + validators.insert(Validator(acl::SPECPROP_MAXQUEUECOUNTLOWERLIMIT, + boost::shared_ptr<PropertyType>( + new IntPropertyType(0,std::numeric_limits<int64_t>::max())))); + + validators.insert(Validator(acl::SPECPROP_MAXQUEUECOUNTUPPERLIMIT, + boost::shared_ptr<PropertyType>( + new IntPropertyType(0,std::numeric_limits<int64_t>::max())))); std::string policyTypes[] = {"ring", "ring_strict", "flow_to_disk", "reject"}; std::vector<std::string> v(policyTypes, policyTypes + sizeof(policyTypes) / sizeof(std::string)); - validators.insert(Validator(acl::PROP_POLICYTYPE, - boost::shared_ptr<PropertyType>(new EnumPropertyType(v)) - ) - ); + validators.insert(Validator(acl::SPECPROP_POLICYTYPE, + boost::shared_ptr<PropertyType>( + new EnumPropertyType(v)))); } @@ -114,9 +117,9 @@ namespace acl { if (d->actionList[cnt][cnt1]){ std::for_each(d->actionList[cnt][cnt1]->begin(), - d->actionList[cnt][cnt1]->end(), - boost::bind(&AclValidator::validateRuleSet, this, _1)); - }//if + d->actionList[cnt][cnt1]->end(), + boost::bind(&AclValidator::validateRuleSet, this, _1)); + }//if }//for }//if }//for @@ -125,25 +128,29 @@ namespace acl { void AclValidator::validateRuleSet(std::pair<const std::string, qpid::acl::AclData::ruleSet>& rules){ std::for_each(rules.second.begin(), rules.second.end(), - boost::bind(&AclValidator::validateRule, this, _1)); + boost::bind(&AclValidator::validateRule, this, _1)); } void AclValidator::validateRule(qpid::acl::AclData::rule& rule){ std::for_each(rule.props.begin(), rule.props.end(), - boost::bind(&AclValidator::validateProperty, this, _1)); + boost::bind(&AclValidator::validateProperty, this, _1)); } - void AclValidator::validateProperty(std::pair<const qpid::acl::Property, std::string>& prop){ + void AclValidator::validateProperty(std::pair<const qpid::acl::SpecProperty, std::string>& prop){ ValidatorItr itr = validators.find(prop.first); if (itr != validators.end()){ - QPID_LOG(debug,"Found validator for property " << itr->second->allowedValues()); + QPID_LOG(debug,"ACL: Found validator for property '" << acl::AclHelper::getPropertyStr(itr->first) + << "'. " << itr->second->allowedValues()); if (!itr->second->validate(prop.second)){ - throw Exception( prop.second + " is not a valid value for '" + + QPID_LOG(debug, "ACL: Property failed validation. '" << prop.second << "' is not a valid value for '" + << AclHelper::getPropertyStr(prop.first) << "'"); + + throw Exception( prop.second + " is not a valid value for '" + AclHelper::getPropertyStr(prop.first) + "', " + itr->second->allowedValues()); - } + } } } diff --git a/cpp/src/qpid/acl/AclValidator.h b/cpp/src/qpid/acl/AclValidator.h index 966e5d326b..f85c241b06 100644 --- a/cpp/src/qpid/acl/AclValidator.h +++ b/cpp/src/qpid/acl/AclValidator.h @@ -33,18 +33,18 @@ namespace acl { class AclValidator { /* Base Property */ - class PropertyType{ - + class PropertyType{ + public: virtual ~PropertyType(){}; virtual bool validate(const std::string& val)=0; virtual std::string allowedValues()=0; }; - class IntPropertyType : public PropertyType{ + class IntPropertyType : public PropertyType{ int64_t min; int64_t max; - + public: IntPropertyType(int64_t min,int64_t max); virtual ~IntPropertyType (){}; @@ -53,7 +53,7 @@ class AclValidator { }; class EnumPropertyType : public PropertyType{ - std::vector<std::string> values; + std::vector<std::string> values; public: EnumPropertyType(std::vector<std::string>& allowed); @@ -61,23 +61,23 @@ class AclValidator { virtual bool validate(const std::string& val); virtual std::string allowedValues(); }; - - typedef std::pair<acl::Property,boost::shared_ptr<PropertyType> > Validator; - typedef std::map<acl::Property,boost::shared_ptr<PropertyType> > ValidatorMap; + + typedef std::pair<acl::SpecProperty,boost::shared_ptr<PropertyType> > Validator; + typedef std::map<acl::SpecProperty,boost::shared_ptr<PropertyType> > ValidatorMap; typedef ValidatorMap::iterator ValidatorItr; - + ValidatorMap validators; public: void validateRuleSet(std::pair<const std::string, qpid::acl::AclData::ruleSet>& rules); void validateRule(qpid::acl::AclData::rule& rule); - void validateProperty(std::pair<const qpid::acl::Property, std::string>& prop); - void validate(boost::shared_ptr<AclData> d); + void validateProperty(std::pair<const qpid::acl::SpecProperty, std::string>& prop); + void validate(boost::shared_ptr<AclData> d); AclValidator(); ~AclValidator(); }; - + }} // namespace qpid::acl #endif // QPID_ACL_ACLVALIDATOR_H diff --git a/cpp/src/qpid/broker/AclModule.h b/cpp/src/qpid/broker/AclModule.h index e32ff266b9..be143a23e7 100644 --- a/cpp/src/qpid/broker/AclModule.h +++ b/cpp/src/qpid/broker/AclModule.h @@ -32,17 +32,83 @@ namespace qpid { namespace acl { - enum ObjectType {OBJ_QUEUE, OBJ_EXCHANGE, OBJ_BROKER, OBJ_LINK, - OBJ_METHOD, OBJECTSIZE}; // OBJECTSIZE must be last in list - enum Action {ACT_CONSUME, ACT_PUBLISH, ACT_CREATE, ACT_ACCESS, ACT_BIND, - ACT_UNBIND, ACT_DELETE, ACT_PURGE, ACT_UPDATE, - ACTIONSIZE}; // ACTIONSIZE must be last in list - enum Property {PROP_NAME, PROP_DURABLE, PROP_OWNER, PROP_ROUTINGKEY, - PROP_PASSIVE, PROP_AUTODELETE, PROP_EXCLUSIVE, PROP_TYPE, - PROP_ALTERNATE, PROP_QUEUENAME, PROP_SCHEMAPACKAGE, - PROP_SCHEMACLASS, PROP_POLICYTYPE, PROP_MAXQUEUESIZE, - PROP_MAXQUEUECOUNT}; - enum AclResult {ALLOW, ALLOWLOG, DENY, DENYLOG}; + // Interface enumerations. + // These enumerations define enum lists and implied text strings + // to match. They are used in two areas: + // 1. In the ACL specifications in the ACL file, file parsing, and + // internal rule storage. + // 2. In the authorize interface in the rest of the broker where + // code requests the ACL module to authorize an action. + + // ObjectType shared between ACL spec and ACL authorise interface + enum ObjectType { + OBJ_QUEUE, + OBJ_EXCHANGE, + OBJ_BROKER, + OBJ_LINK, + OBJ_METHOD, + OBJECTSIZE }; // OBJECTSIZE must be last in list + + // Action shared between ACL spec and ACL authorise interface + enum Action { + ACT_CONSUME, + ACT_PUBLISH, + ACT_CREATE, + ACT_ACCESS, + ACT_BIND, + ACT_UNBIND, + ACT_DELETE, + ACT_PURGE, + ACT_UPDATE, + ACTIONSIZE }; // ACTIONSIZE must be last in list + + // Property used in ACL authorize interface + enum Property { + PROP_NAME, + PROP_DURABLE, + PROP_OWNER, + PROP_ROUTINGKEY, + PROP_PASSIVE, + PROP_AUTODELETE, + PROP_EXCLUSIVE, + PROP_TYPE, + PROP_ALTERNATE, + PROP_QUEUENAME, + PROP_SCHEMAPACKAGE, + PROP_SCHEMACLASS, + PROP_POLICYTYPE, + PROP_MAXQUEUESIZE, + PROP_MAXQUEUECOUNT }; + + // Property used in ACL spec file + // Note for properties common to file processing/rule storage and to + // broker rule lookups the identical enum values are used. + enum SpecProperty { + SPECPROP_NAME = PROP_NAME, + SPECPROP_DURABLE = PROP_DURABLE, + SPECPROP_OWNER = PROP_OWNER, + SPECPROP_ROUTINGKEY = PROP_ROUTINGKEY, + SPECPROP_PASSIVE = PROP_PASSIVE, + SPECPROP_AUTODELETE = PROP_AUTODELETE, + SPECPROP_EXCLUSIVE = PROP_EXCLUSIVE, + SPECPROP_TYPE = PROP_TYPE, + SPECPROP_ALTERNATE = PROP_ALTERNATE, + SPECPROP_QUEUENAME = PROP_QUEUENAME, + SPECPROP_SCHEMAPACKAGE = PROP_SCHEMAPACKAGE, + SPECPROP_SCHEMACLASS = PROP_SCHEMACLASS, + SPECPROP_POLICYTYPE = PROP_POLICYTYPE, + + SPECPROP_MAXQUEUESIZELOWERLIMIT, + SPECPROP_MAXQUEUESIZEUPPERLIMIT, + SPECPROP_MAXQUEUECOUNTLOWERLIMIT, + SPECPROP_MAXQUEUECOUNTUPPERLIMIT }; + +// AclResult shared between ACL spec and ACL authorise interface + enum AclResult { + ALLOW, + ALLOWLOG, + DENY, + DENYLOG }; } // namespace acl @@ -54,14 +120,25 @@ namespace broker { public: - // effienty turn off ACL on message transfer. + // Some ACLs are invoked on every message transfer. + // doTransferAcl pervents time consuming ACL calls on a per-message basis. virtual bool doTransferAcl()=0; - virtual bool authorise(const std::string& id, const acl::Action& action, const acl::ObjectType& objType, const std::string& name, + virtual bool authorise( + const std::string& id, + const acl::Action& action, + const acl::ObjectType& objType, + const std::string& name, std::map<acl::Property, std::string>* params=0)=0; - virtual bool authorise(const std::string& id, const acl::Action& action, const acl::ObjectType& objType, const std::string& ExchangeName, - const std::string& RoutingKey)=0; - // create specilied authorise methods for cases that need faster matching as needed. + + virtual bool authorise( + const std::string& id, + const acl::Action& action, + const acl::ObjectType& objType, + const std::string& ExchangeName, + const std::string& RoutingKey)=0; + + // Add specialized authorise() methods as required. virtual ~AclModule() {}; }; @@ -134,7 +211,7 @@ namespace acl { if (str.compare("schemaclass") == 0) return PROP_SCHEMACLASS; if (str.compare("policytype") == 0) return PROP_POLICYTYPE; if (str.compare("maxqueuesize") == 0) return PROP_MAXQUEUESIZE; - if (str.compare("maxqueuecount") == 0) return PROP_MAXQUEUECOUNT; + if (str.compare("maxqueuecount") == 0) return PROP_MAXQUEUECOUNT; throw str; } static inline std::string getPropertyStr(const Property p) { @@ -153,11 +230,57 @@ namespace acl { case PROP_SCHEMACLASS: return "schemaclass"; case PROP_POLICYTYPE: return "policytype"; case PROP_MAXQUEUESIZE: return "maxqueuesize"; - case PROP_MAXQUEUECOUNT: return "maxqueuecount"; + case PROP_MAXQUEUECOUNT: return "maxqueuecount"; default: assert(false); // should never get here } return ""; } + static inline SpecProperty getSpecProperty(const std::string& str) { + if (str.compare("name") == 0) return SPECPROP_NAME; + if (str.compare("durable") == 0) return SPECPROP_DURABLE; + if (str.compare("owner") == 0) return SPECPROP_OWNER; + if (str.compare("routingkey") == 0) return SPECPROP_ROUTINGKEY; + if (str.compare("passive") == 0) return SPECPROP_PASSIVE; + if (str.compare("autodelete") == 0) return SPECPROP_AUTODELETE; + if (str.compare("exclusive") == 0) return SPECPROP_EXCLUSIVE; + if (str.compare("type") == 0) return SPECPROP_TYPE; + if (str.compare("alternate") == 0) return SPECPROP_ALTERNATE; + if (str.compare("queuename") == 0) return SPECPROP_QUEUENAME; + if (str.compare("schemapackage") == 0) return SPECPROP_SCHEMAPACKAGE; + if (str.compare("schemaclass") == 0) return SPECPROP_SCHEMACLASS; + if (str.compare("policytype") == 0) return SPECPROP_POLICYTYPE; + if (str.compare("queuemaxsizelowerlimit") == 0) return SPECPROP_MAXQUEUESIZELOWERLIMIT; + if (str.compare("queuemaxsizeupperlimit") == 0) return SPECPROP_MAXQUEUESIZEUPPERLIMIT; + if (str.compare("queuemaxcountlowerlimit") == 0) return SPECPROP_MAXQUEUECOUNTLOWERLIMIT; + if (str.compare("queuemaxcountupperlimit") == 0) return SPECPROP_MAXQUEUECOUNTUPPERLIMIT; + // Allow old names in ACL file as aliases for newly-named properties + if (str.compare("maxqueuesize") == 0) return SPECPROP_MAXQUEUESIZEUPPERLIMIT; + if (str.compare("maxqueuecount") == 0) return SPECPROP_MAXQUEUECOUNTUPPERLIMIT; + throw str; + } + static inline std::string getPropertyStr(const SpecProperty p) { + switch (p) { + case SPECPROP_NAME: return "name"; + case SPECPROP_DURABLE: return "durable"; + case SPECPROP_OWNER: return "owner"; + case SPECPROP_ROUTINGKEY: return "routingkey"; + case SPECPROP_PASSIVE: return "passive"; + case SPECPROP_AUTODELETE: return "autodelete"; + case SPECPROP_EXCLUSIVE: return "exclusive"; + case SPECPROP_TYPE: return "type"; + case SPECPROP_ALTERNATE: return "alternate"; + case SPECPROP_QUEUENAME: return "queuename"; + case SPECPROP_SCHEMAPACKAGE: return "schemapackage"; + case SPECPROP_SCHEMACLASS: return "schemaclass"; + case SPECPROP_POLICYTYPE: return "policytype"; + case SPECPROP_MAXQUEUESIZELOWERLIMIT: return "queuemaxsizelowerlimit"; + case SPECPROP_MAXQUEUESIZEUPPERLIMIT: return "queuemaxsizeupperlimit"; + case SPECPROP_MAXQUEUECOUNTLOWERLIMIT: return "queuemaxcountlowerlimit"; + case SPECPROP_MAXQUEUECOUNTUPPERLIMIT: return "queuemaxcountupperlimit"; + default: assert(false); // should never get here + } + return ""; + } static inline AclResult getAclResult(const std::string& str) { if (str.compare("allow") == 0) return ALLOW; if (str.compare("allow-log") == 0) return ALLOWLOG; @@ -187,8 +310,11 @@ namespace acl { typedef boost::shared_ptr<objectMap> objectMapPtr; typedef std::map<Property, std::string> propMap; typedef propMap::const_iterator propMapItr; + typedef std::map<SpecProperty, std::string> specPropMap; + typedef specPropMap::const_iterator specPropMapItr; - // This map contains the legal combinations of object/action/properties found in an ACL file + // This map contains the legal combinations of object/action/properties + // found in an ACL file static void loadValidationMap(objectMapPtr& map) { if (!map.get()) return; map->clear(); @@ -260,21 +386,31 @@ namespace acl { map->insert(objectPair(OBJ_METHOD, a4)); } - static std::string propertyMapToString(const std::map<Property, std::string>* params) { + // + // properyMapToString + // + template <typename T> + static std::string propertyMapToString( + const std::map<T, std::string>* params) + { std::ostringstream ss; ss << "{"; if (params) { - for (propMapItr pMItr = params->begin(); pMItr != params->end(); pMItr++) { - ss << " " << getPropertyStr((Property) pMItr-> first) << "=" << pMItr->second; + for (typename std::map<T, std::string>::const_iterator + pMItr = params->begin(); pMItr != params->end(); pMItr++) + { + ss << " " << getPropertyStr((T) pMItr-> first) + << "=" << pMItr->second; } } ss << " }"; return ss.str(); } + }; - + }} // namespace qpid::acl #endif // QPID_ACLMODULE_ACL_H diff --git a/cpp/src/qpid/broker/ConnectionHandler.h b/cpp/src/qpid/broker/ConnectionHandler.h index 05c5f00c57..2e25543308 100644 --- a/cpp/src/qpid/broker/ConnectionHandler.h +++ b/cpp/src/qpid/broker/ConnectionHandler.h @@ -35,7 +35,6 @@ #include "qpid/framing/ProtocolInitiation.h" #include "qpid/framing/ProtocolVersion.h" #include "qpid/Exception.h" -#include "qpid/broker/AclModule.h" #include "qpid/sys/SecurityLayer.h" diff --git a/cpp/src/qpid/broker/SemanticState.h b/cpp/src/qpid/broker/SemanticState.h index 2b4b92e8ac..e5e1d2da16 100644 --- a/cpp/src/qpid/broker/SemanticState.h +++ b/cpp/src/qpid/broker/SemanticState.h @@ -40,7 +40,6 @@ #include "qpid/sys/AggregateOutput.h" #include "qpid/sys/Mutex.h" #include "qpid/sys/AtomicValue.h" -#include "qpid/broker/AclModule.h" #include "qmf/org/apache/qpid/broker/Subscription.h" #include <list> |
