summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qpid/cpp/src/qpid/acl/Acl.cpp10
-rw-r--r--qpid/cpp/src/qpid/acl/Acl.h5
-rw-r--r--qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp2
-rw-r--r--qpid/cpp/src/qpid/acl/AclData.cpp2
-rw-r--r--qpid/cpp/src/qpid/acl/AclData.h1
-rw-r--r--qpid/cpp/src/qpid/acl/AclReader.cpp4
-rw-r--r--qpid/cpp/src/qpid/acl/management-schema.xml1
-rw-r--r--qpid/cpp/src/qpid/broker/AclModule.h5
-rw-r--r--qpid/cpp/src/qpid/broker/ConnectionHandler.cpp20
-rwxr-xr-xqpid/cpp/src/tests/ha_test.py11
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)