| #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 "qpid/Exception.h" |
| #include <boost/shared_ptr.hpp> |
| #include <map> |
| #include <set> |
| #include <string> |
| #include <sstream> |
| |
| 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_AUTODELETE, |
| PROP_EXCLUSIVE, |
| PROP_TYPE, |
| PROP_ALTERNATE, |
| PROP_QUEUENAME, |
| PROP_SCHEMAPACKAGE, |
| PROP_SCHEMACLASS, |
| PROP_POLICYTYPE, |
| PROP_MAXQUEUESIZE, |
| PROP_MAXQUEUECOUNT, |
| PROP_MAXFILESIZE, |
| PROP_MAXFILECOUNT, |
| PROPERTYSIZE // PROPERTYSIZE must be last in list |
| }; |
| |
| // 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_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, |
| SPECPROP_MAXFILESIZELOWERLIMIT, |
| SPECPROP_MAXFILESIZEUPPERLIMIT, |
| SPECPROP_MAXFILECOUNTLOWERLIMIT, |
| SPECPROP_MAXFILECOUNTUPPERLIMIT }; |
| |
| // AclResult shared between ACL spec and ACL authorise interface |
| enum AclResult { |
| ALLOW, |
| ALLOWLOG, |
| DENY, |
| DENYLOG }; |
| |
| } // namespace acl |
| |
| namespace broker { |
| |
| class Connection; |
| |
| 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 uint16_t getMaxConnectTotal()=0; |
| |
| 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; |
| |
| // Add specialized authorise() methods as required. |
| |
| /** Approve connection by counting connections total, per-IP, and |
| * per-user. |
| */ |
| virtual bool approveConnection (const Connection& connection)=0; |
| |
| /** Approve queue creation by counting per-user. |
| */ |
| virtual bool approveCreateQueue(const std::string& userId, const std::string& queueName)=0; |
| virtual void recordDestroyQueue(const std::string& queueName)=0; |
| |
| 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 qpid::Exception(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 qpid::Exception(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("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; |
| if (str.compare("maxfilesize") == 0) return PROP_MAXFILESIZE; |
| if (str.compare("maxfilecount") == 0) return PROP_MAXFILECOUNT; |
| throw qpid::Exception(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_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"; |
| case PROP_MAXFILESIZE: return "maxfilesize"; |
| case PROP_MAXFILECOUNT: return "maxfilecount"; |
| 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("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; |
| if (str.compare("filemaxsizelowerlimit") == 0) return SPECPROP_MAXFILESIZELOWERLIMIT; |
| if (str.compare("filemaxsizeupperlimit") == 0) return SPECPROP_MAXFILESIZEUPPERLIMIT; |
| if (str.compare("filemaxcountlowerlimit") == 0) return SPECPROP_MAXFILECOUNTLOWERLIMIT; |
| if (str.compare("filemaxcountupperlimit") == 0) return SPECPROP_MAXFILECOUNTUPPERLIMIT; |
| // 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 qpid::Exception(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_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"; |
| case SPECPROP_MAXFILESIZELOWERLIMIT: return "filemaxsizelowerlimit"; |
| case SPECPROP_MAXFILESIZEUPPERLIMIT: return "filemaxsizeupperlimit"; |
| case SPECPROP_MAXFILECOUNTLOWERLIMIT: return "filemaxcountlowerlimit"; |
| case SPECPROP_MAXFILECOUNTUPPERLIMIT: return "filemaxcountupperlimit"; |
| 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 qpid::Exception(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<Property> propSet; |
| typedef boost::shared_ptr<propSet> propSetPtr; |
| typedef std::pair<Action, propSetPtr> actionPair; |
| typedef std::map<Action, propSetPtr> actionMap; |
| typedef boost::shared_ptr<actionMap> actionMapPtr; |
| typedef std::pair<ObjectType, actionMapPtr> objectPair; |
| typedef std::map<ObjectType, actionMapPtr> objectMap; |
| typedef objectMap::const_iterator omCitr; |
| 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 |
| 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_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_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 <typename T> |
| static std::string propertyMapToString( |
| const std::map<T, std::string>* params) |
| { |
| std::ostringstream ss; |
| ss << "{"; |
| if (params) |
| { |
| 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 |