diff options
-rw-r--r-- | qpid/cpp/src/qpid/acl/Acl.cpp | 10 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/acl/Acl.h | 5 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp | 2 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/acl/AclData.cpp | 2 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/acl/AclData.h | 1 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/acl/AclReader.cpp | 4 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/acl/management-schema.xml | 1 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/broker/AclModule.h | 5 | ||||
-rw-r--r-- | qpid/cpp/src/qpid/broker/ConnectionHandler.cpp | 20 | ||||
-rwxr-xr-x | qpid/cpp/src/tests/ha_test.py | 11 |
10 files changed, 55 insertions, 6 deletions
diff --git a/qpid/cpp/src/qpid/acl/Acl.cpp b/qpid/cpp/src/qpid/acl/Acl.cpp index aeee42563c..bdec6791b8 100644 --- a/qpid/cpp/src/qpid/acl/Acl.cpp +++ b/qpid/cpp/src/qpid/acl/Acl.cpp @@ -53,7 +53,7 @@ using qpid::management::Manageable; using qpid::management::Args; namespace _qmf = qmf::org::apache::qpid::acl; -Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(false), +Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(false), createlinkAcl(false), connectionCounter(new ConnectionCounter(*this, aclValues.aclMaxConnectPerUser, aclValues.aclMaxConnectPerIp, aclValues.aclMaxConnectTotal)), resourceCounter(new ResourceCounter(*this, aclValues.aclMaxQueuesPerUser)){ @@ -254,12 +254,17 @@ bool Acl::readAclFile(std::string& aclFile, std::string& errorText) { Mutex::ScopedLock locker(dataLock); data = d; } - transferAcl = data->transferAcl; // any transfer ACL + transferAcl = data->transferAcl; // any PUBLISH EXCHANGE transfer ACL + createlinkAcl = data->createlinkAcl; // any CREATE LINK ACL if (data->transferAcl){ QPID_LOG(debug,"ACL: Transfer ACL is Enabled!"); } + if (data->createlinkAcl){ + QPID_LOG(debug,"ACL: CREATE LINK ACL is Enabled!"); + } + if (data->enforcingConnectionQuotas()){ QPID_LOG(debug, "ACL: Connection quotas are Enabled."); } @@ -271,6 +276,7 @@ bool Acl::readAclFile(std::string& aclFile, std::string& errorText) { data->aclSource = aclFile; if (mgmtObject!=0){ mgmtObject->set_transferAcl(transferAcl?1:0); + mgmtObject->set_createLinkAcl(createlinkAcl?1:0); mgmtObject->set_policyFile(aclFile); sys::AbsTime now = sys::AbsTime::now(); int64_t ns = sys::Duration(sys::EPOCH, now); diff --git a/qpid/cpp/src/qpid/acl/Acl.h b/qpid/cpp/src/qpid/acl/Acl.h index ea3c6586a3..9721a60fba 100644 --- a/qpid/cpp/src/qpid/acl/Acl.h +++ b/qpid/cpp/src/qpid/acl/Acl.h @@ -61,6 +61,7 @@ private: acl::AclValues aclValues; broker::Broker* broker; bool transferAcl; + bool createlinkAcl; boost::shared_ptr<AclData> data; qmf::org::apache::qpid::acl::Acl::shared_ptr mgmtObject; qpid::management::ManagementAgent* agent; @@ -81,6 +82,10 @@ public: return transferAcl; }; + inline virtual bool isCreatelinkAcl() { + return createlinkAcl; + }; + inline virtual uint16_t getMaxConnectTotal() { return aclValues.aclMaxConnectTotal; }; diff --git a/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp b/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp index 875137bf55..80a7a32790 100644 --- a/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp +++ b/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp @@ -288,7 +288,7 @@ std::string ConnectionCounter::getClientHost(const std::string mgmtId) } // no hyphen found - use whole string - assert(false); + //assert(false); return mgmtId; } diff --git a/qpid/cpp/src/qpid/acl/AclData.cpp b/qpid/cpp/src/qpid/acl/AclData.cpp index 922f65ba69..5ffd0462dc 100644 --- a/qpid/cpp/src/qpid/acl/AclData.cpp +++ b/qpid/cpp/src/qpid/acl/AclData.cpp @@ -46,6 +46,7 @@ namespace acl { AclData::AclData(): decisionMode(qpid::acl::DENY), transferAcl(false), + createlinkAcl(false), aclSource("UNKNOWN"), connQuotaRulesExist(false), connQuotaRuleSettings(new quotaRuleSet), @@ -74,6 +75,7 @@ namespace acl { delete[] actionList[cnt]; } transferAcl = false; + createlinkAcl = false; connQuotaRulesExist = false; connQuotaRuleSettings->clear(); queueQuotaRulesExist = false; diff --git a/qpid/cpp/src/qpid/acl/AclData.h b/qpid/cpp/src/qpid/acl/AclData.h index c561b95e09..ad8b741be5 100644 --- a/qpid/cpp/src/qpid/acl/AclData.h +++ b/qpid/cpp/src/qpid/acl/AclData.h @@ -118,6 +118,7 @@ public: aclAction* actionList[qpid::acl::ACTIONSIZE]; qpid::acl::AclResult decisionMode; // allow/deny[-log] if no matching rule found bool transferAcl; + bool createlinkAcl; std::string aclSource; AclResult lookup( diff --git a/qpid/cpp/src/qpid/acl/AclReader.cpp b/qpid/cpp/src/qpid/acl/AclReader.cpp index 1fd5445b52..f0974b8585 100644 --- a/qpid/cpp/src/qpid/acl/AclReader.cpp +++ b/qpid/cpp/src/qpid/acl/AclReader.cpp @@ -160,6 +160,10 @@ namespace acl { ocnt < acl::OBJECTSIZE; (*i)->objStatus != aclRule::VALUE ? ocnt++ : ocnt = acl::OBJECTSIZE) { + // Observe existance of CREATE LINK rules + if (acnt == acl::ACT_CREATE && ocnt == acl::OBJ_LINK) + d->createlinkAcl = true; + //find the Object, create if not exist if (d->actionList[acnt][ocnt] == NULL) d->actionList[acnt][ocnt] = diff --git a/qpid/cpp/src/qpid/acl/management-schema.xml b/qpid/cpp/src/qpid/acl/management-schema.xml index 2ac20bb324..e0368db96b 100644 --- a/qpid/cpp/src/qpid/acl/management-schema.xml +++ b/qpid/cpp/src/qpid/acl/management-schema.xml @@ -26,6 +26,7 @@ <property name="maxConnectionsPerIp" type="uint16" access="RO" desc="Maximum allowed connections"/> <property name="maxConnectionsPerUser" type="uint16" access="RO" desc="Maximum allowed connections"/> <property name="maxQueuesPerUser" type="uint16" access="RO" desc="Maximum allowed queues"/> + <property name="createLinkAcl" type="bool" access="RO" desc="Create Link ACL rules may allow link creation"/> <statistic name="aclDenyCount" type="count64" unit="request" desc="Number of ACL requests denied"/> <statistic name="connectionDenyCount" type="count64" unit="connection" desc="Number of connections denied"/> <statistic name="queueQuotaDenyCount" type="count64" unit="queue" desc="Number of queue creations denied"/> diff --git a/qpid/cpp/src/qpid/broker/AclModule.h b/qpid/cpp/src/qpid/broker/AclModule.h index c01697ace9..1c138c62a8 100644 --- a/qpid/cpp/src/qpid/broker/AclModule.h +++ b/qpid/cpp/src/qpid/broker/AclModule.h @@ -132,6 +132,11 @@ namespace broker { // doTransferAcl pervents time consuming ACL calls on a per-message basis. virtual bool doTransferAcl()=0; + // Federation link creation is denied unless ACL module is loaded and + // at least one CREATE LINK rule is specified. + // This flag indicates that a CREATE LINK rule was processed. + virtual bool isCreatelinkAcl()=0; + virtual uint16_t getMaxConnectTotal()=0; virtual bool authorise( diff --git a/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp b/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp index 977c706ebd..39a8664aab 100644 --- a/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp +++ b/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp @@ -201,11 +201,25 @@ void ConnectionHandler::Handler::startOk(const ConnectionStartOkBody& body) if (connection.isFederationLink()) { AclModule* acl = connection.getBroker().getAcl(); FieldTable properties; - if (acl && !acl->authorise(connection.getUserId(),acl::ACT_CREATE,acl::OBJ_LINK,"")){ + if (acl) { + if (acl->isCreatelinkAcl()) { + if (!acl->authorise(connection.getUserId(),acl::ACT_CREATE,acl::OBJ_LINK,"")){ + proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED, + QPID_MSG("ACL denied " << connection.getUserId() + << " creating a federation link")); + return; + } + } else { + proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED, + QPID_MSG("ACL denied " << connection.getUserId() + << ". Federation links require explicit CREATE LINK ACL rules")); + return; + } + } else { proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED, QPID_MSG("ACL denied " << connection.getUserId() - << " creating a federation link")); - return; + << ". Federation links require ACL module and explicit CREATE LINK ACL rules")); + return; } QPID_LOG(info, "Connection is a federation link"); } diff --git a/qpid/cpp/src/tests/ha_test.py b/qpid/cpp/src/tests/ha_test.py index f2ebb16ccc..5c42780f50 100755 --- a/qpid/cpp/src/tests/ha_test.py +++ b/qpid/cpp/src/tests/ha_test.py @@ -79,6 +79,17 @@ class HaBroker(Broker): if ha_replicate is not None: args += [ "--ha-replicate=%s"%ha_replicate ] if brokers_url: args += [ "--ha-brokers-url", brokers_url ] + # Set up default ACL file to allow all create link + acl=os.path.join(os.getcwd(), "unrestricted.acl") + if not os.path.exists(acl): + aclf=file(acl,"w") + aclf.write(""" +acl allow all create link +acl allow all all + """) + aclf.close() + if not "--acl-file" in args: + args += [ "--acl-file", acl, "--load-module", os.getenv("ACL_LIB") ] Broker.__init__(self, test, args, **kwargs) self.qpid_ha_path=os.path.join(os.getenv("PYTHON_COMMANDS"), "qpid-ha") assert os.path.exists(self.qpid_ha_path) |