#ifndef QPID_ACLMODULE_ACL_H #define QPID_ACLMODULE_ACL_H /* * * 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/RefCounted.h" #include #include #include #include #include namespace qpid { namespace acl { // 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 namespace broker { class AclModule { public: // 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, std::map* 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; // Add specialized authorise() methods as required. virtual ~AclModule() {}; }; } // namespace broker namespace acl { class AclHelper { private: AclHelper(){} public: static inline ObjectType getObjectType(const std::string& str) { if (str.compare("queue") == 0) return OBJ_QUEUE; if (str.compare("exchange") == 0) return OBJ_EXCHANGE; if (str.compare("broker") == 0) return OBJ_BROKER; if (str.compare("link") == 0) return OBJ_LINK; if (str.compare("method") == 0) return OBJ_METHOD; throw str; } static inline std::string getObjectTypeStr(const ObjectType o) { switch (o) { case OBJ_QUEUE: return "queue"; case OBJ_EXCHANGE: return "exchange"; case OBJ_BROKER: return "broker"; case OBJ_LINK: return "link"; case OBJ_METHOD: return "method"; default: assert(false); // should never get here } return ""; } static inline Action getAction(const std::string& str) { if (str.compare("consume") == 0) return ACT_CONSUME; if (str.compare("publish") == 0) return ACT_PUBLISH; if (str.compare("create") == 0) return ACT_CREATE; if (str.compare("access") == 0) return ACT_ACCESS; if (str.compare("bind") == 0) return ACT_BIND; if (str.compare("unbind") == 0) return ACT_UNBIND; if (str.compare("delete") == 0) return ACT_DELETE; if (str.compare("purge") == 0) return ACT_PURGE; if (str.compare("update") == 0) return ACT_UPDATE; throw str; } static inline std::string getActionStr(const Action a) { switch (a) { case ACT_CONSUME: return "consume"; case ACT_PUBLISH: return "publish"; case ACT_CREATE: return "create"; case ACT_ACCESS: return "access"; case ACT_BIND: return "bind"; case ACT_UNBIND: return "unbind"; case ACT_DELETE: return "delete"; case ACT_PURGE: return "purge"; case ACT_UPDATE: return "update"; default: assert(false); // should never get here } return ""; } static inline Property getProperty(const std::string& str) { if (str.compare("name") == 0) return PROP_NAME; if (str.compare("durable") == 0) return PROP_DURABLE; if (str.compare("owner") == 0) return PROP_OWNER; if (str.compare("routingkey") == 0) return PROP_ROUTINGKEY; if (str.compare("passive") == 0) return PROP_PASSIVE; if (str.compare("autodelete") == 0) return PROP_AUTODELETE; if (str.compare("exclusive") == 0) return PROP_EXCLUSIVE; if (str.compare("type") == 0) return PROP_TYPE; if (str.compare("alternate") == 0) return PROP_ALTERNATE; if (str.compare("queuename") == 0) return PROP_QUEUENAME; if (str.compare("schemapackage") == 0) return PROP_SCHEMAPACKAGE; 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; throw str; } static inline std::string getPropertyStr(const Property p) { switch (p) { case PROP_NAME: return "name"; case PROP_DURABLE: return "durable"; case PROP_OWNER: return "owner"; case PROP_ROUTINGKEY: return "routingkey"; case PROP_PASSIVE: return "passive"; case PROP_AUTODELETE: return "autodelete"; case PROP_EXCLUSIVE: return "exclusive"; case PROP_TYPE: return "type"; case PROP_ALTERNATE: return "alternate"; case PROP_QUEUENAME: return "queuename"; case PROP_SCHEMAPACKAGE: return "schemapackage"; case PROP_SCHEMACLASS: return "schemaclass"; case PROP_POLICYTYPE: return "policytype"; case PROP_MAXQUEUESIZE: return "maxqueuesize"; 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; if (str.compare("deny") == 0) return DENY; if (str.compare("deny-log") == 0) return DENYLOG; throw str; } static inline std::string getAclResultStr(const AclResult r) { switch (r) { case ALLOW: return "allow"; case ALLOWLOG: return "allow-log"; case DENY: return "deny"; case DENYLOG: return "deny-log"; default: assert(false); // should never get here } return ""; } typedef std::set propSet; typedef boost::shared_ptr propSetPtr; typedef std::pair actionPair; typedef std::map actionMap; typedef boost::shared_ptr actionMapPtr; typedef std::pair objectPair; typedef std::map objectMap; typedef objectMap::const_iterator omCitr; typedef boost::shared_ptr objectMapPtr; typedef std::map propMap; typedef propMap::const_iterator propMapItr; typedef std::map specPropMap; typedef specPropMap::const_iterator specPropMapItr; // 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(); propSetPtr p0; // empty ptr, used for no properties // == Exchanges == propSetPtr p1(new propSet); p1->insert(PROP_TYPE); p1->insert(PROP_ALTERNATE); p1->insert(PROP_PASSIVE); p1->insert(PROP_DURABLE); propSetPtr p2(new propSet); p2->insert(PROP_ROUTINGKEY); propSetPtr p3(new propSet); p3->insert(PROP_QUEUENAME); p3->insert(PROP_ROUTINGKEY); actionMapPtr a0(new actionMap); a0->insert(actionPair(ACT_CREATE, p1)); a0->insert(actionPair(ACT_DELETE, p0)); a0->insert(actionPair(ACT_ACCESS, p0)); a0->insert(actionPair(ACT_BIND, p2)); a0->insert(actionPair(ACT_UNBIND, p2)); a0->insert(actionPair(ACT_ACCESS, p3)); a0->insert(actionPair(ACT_PUBLISH, p0)); map->insert(objectPair(OBJ_EXCHANGE, a0)); // == Queues == propSetPtr p4(new propSet); p4->insert(PROP_ALTERNATE); p4->insert(PROP_PASSIVE); p4->insert(PROP_DURABLE); p4->insert(PROP_EXCLUSIVE); p4->insert(PROP_AUTODELETE); p4->insert(PROP_POLICYTYPE); p4->insert(PROP_MAXQUEUESIZE); p4->insert(PROP_MAXQUEUECOUNT); actionMapPtr a1(new actionMap); a1->insert(actionPair(ACT_ACCESS, p0)); a1->insert(actionPair(ACT_CREATE, p4)); a1->insert(actionPair(ACT_PURGE, p0)); a1->insert(actionPair(ACT_DELETE, p0)); a1->insert(actionPair(ACT_CONSUME, p0)); map->insert(objectPair(OBJ_QUEUE, a1)); // == Links == actionMapPtr a2(new actionMap); a2->insert(actionPair(ACT_CREATE, p0)); map->insert(objectPair(OBJ_LINK, a2)); // == Method == propSetPtr p5(new propSet); p5->insert(PROP_SCHEMAPACKAGE); p5->insert(PROP_SCHEMACLASS); actionMapPtr a4(new actionMap); a4->insert(actionPair(ACT_ACCESS, p5)); map->insert(objectPair(OBJ_METHOD, a4)); } // // properyMapToString // template static std::string propertyMapToString( const std::map* params) { std::ostringstream ss; ss << "{"; if (params) { for (typename std::map::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