You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by gs...@apache.org on 2019/02/28 17:57:13 UTC

[qpid-dispatch] branch master updated: DISPATCH-1273: check permission to send to target for anonymous sender links

This is an automated email from the ASF dual-hosted git repository.

gsim pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git


The following commit(s) were added to refs/heads/master by this push:
     new ee82bac  DISPATCH-1273: check permission to send to target for anonymous sender links
ee82bac is described below

commit ee82bac3d890f652bc5776c5b3954e6b30bde9c0
Author: Gordon Sim <gs...@redhat.com>
AuthorDate: Thu Feb 28 10:25:02 2019 +0000

    DISPATCH-1273: check permission to send to target for anonymous sender links
---
 src/policy.c                                  | 37 +++++++++++++++++++++++++++
 src/policy.h                                  |  7 +++++
 src/router_node.c                             | 21 +++++++++++----
 tests/system_tests_authz_service_plugin.py.in | 22 +++++++++++++++-
 4 files changed, 81 insertions(+), 6 deletions(-)

diff --git a/src/policy.c b/src/policy.c
index d9ecddc..81eaee0 100644
--- a/src/policy.c
+++ b/src/policy.c
@@ -892,6 +892,43 @@ static bool qd_policy_terminus_is_waypoint(pn_terminus_t *term)
     return false;
 }
 
+bool qd_policy_approve_message_target(qd_iterator_t *address, qd_connection_t *qd_conn)
+{
+#define ON_STACK_SIZE 2048
+    char  on_stack[ON_STACK_SIZE + 1];
+    char *buffer    = on_stack;
+    bool  on_heap = false;
+    int   length  = qd_iterator_length(address);
+
+    if (length > ON_STACK_SIZE) {
+        buffer    = (char*) malloc(length + 1);
+        on_heap = true;
+    }
+
+    const char* target = qd_iterator_strncpy(address, buffer, length + 1);
+
+    bool lookup = false;
+    if (qd_conn->policy_settings->targetParseTree) {
+        lookup = _qd_policy_approve_link_name_tree(qd_conn->user_id, qd_conn->policy_settings->targetPattern, target, qd_conn->policy_settings->targetParseTree);
+    } else if (qd_conn->policy_settings->targets) {
+        lookup = _qd_policy_approve_link_name(qd_conn->user_id, qd_conn->policy_settings->targets, target);
+    }
+
+    const char *hostip = qd_connection_remote_ip(qd_conn);
+    const char *vhost = pn_connection_remote_hostname(qd_connection_pn(qd_conn));
+    qd_log(qd_server_dispatch(qd_conn->server)->policy->log_source, (lookup ? QD_LOG_TRACE : QD_LOG_INFO),
+           "[%"PRIu64"]: %s AMQP message to '%s' for user '%s', rhost '%s', vhost '%s' based on target address",
+           qd_conn->connection_id, (lookup ? "ALLOW" : "DENY"), target, qd_conn->user_id, hostip, vhost);
+
+    if (on_heap)
+        free(buffer);
+
+    if (!lookup) {
+        return false;
+    } else {
+        return true;
+    }
+}
 
 bool qd_policy_approve_amqp_sender_link(pn_link_t *pn_link, qd_connection_t *qd_conn)
 {
diff --git a/src/policy.h b/src/policy.h
index 0b9fc0d..f1b9d0d 100644
--- a/src/policy.h
+++ b/src/policy.h
@@ -215,4 +215,11 @@ char * qd_policy_host_pattern_lookup(qd_policy_t *policy, const char *hostPatter
  * @return the ruleset string to be used in policy settings.
  */
 char * qd_policy_compile_allowed_csv(char * csv);
+/**
+ * Approve sending of message on anonymous link based on connection's policy.
+ *
+ * @param[in] address the address from the message 'to' field
+ * @param[in] qd_conn dispatch connection with policy settings
+ */
+bool qd_policy_approve_message_target(qd_iterator_t *address, qd_connection_t *qd_conn);
 #endif
diff --git a/src/router_node.c b/src/router_node.c
index 2402abe..6e9cc25 100644
--- a/src/router_node.c
+++ b/src/router_node.c
@@ -550,11 +550,22 @@ static bool AMQP_rx_handler(void* context, qd_link_t *link)
         }
 
         if (addr_iter) {
-            qd_iterator_reset_view(addr_iter, ITER_VIEW_ADDRESS_HASH);
-            if (phase > 0)
-                qd_iterator_annotate_phase(addr_iter, '0' + (char) phase);
-            delivery = qdr_link_deliver_to(rlink, msg, ingress_iter, addr_iter, pn_delivery_settled(pnd),
-                                           link_exclusions, ingress_index);
+            if (!conn->policy_settings || qd_policy_approve_message_target(addr_iter, conn)) {
+                qd_iterator_reset_view(addr_iter, ITER_VIEW_ADDRESS_HASH);
+                if (phase > 0)
+                    qd_iterator_annotate_phase(addr_iter, '0' + (char) phase);
+                delivery = qdr_link_deliver_to(rlink, msg, ingress_iter, addr_iter, pn_delivery_settled(pnd),
+                                               link_exclusions, ingress_index);
+            } else {
+                //reject
+                qd_log(router->log_source, QD_LOG_DEBUG, "Message rejected due to policy violation on target. User:%s", conn->user_id);
+                pn_link_flow(pn_link, 1);
+                pn_delivery_update(pnd, PN_REJECTED);
+                pn_delivery_settle(pnd);
+                qd_message_free(msg);
+                qd_iterator_free(addr_iter);
+                return next_delivery;
+            }
         }
     } else {
         //
diff --git a/tests/system_tests_authz_service_plugin.py.in b/tests/system_tests_authz_service_plugin.py.in
index a214df9..f3c4383 100644
--- a/tests/system_tests_authz_service_plugin.py.in
+++ b/tests/system_tests_authz_service_plugin.py.in
@@ -126,9 +126,20 @@ mech_list: SCRAM-SHA-1 PLAIN
         client = DynamicSourceAnonymousSender()
         container.connect("admin:admin@127.0.0.1:%d" % self.router_port, handler=client)
         container.run()
+        self.assertEqual(1, client.accepted)
         self.assertEqual('hello', client.message)
         self.assertEqual(0, len(client.errors))
 
+    @SkipIfNeeded(not SASL.extended(), "Cyrus library not available. skipping test")
+    def test_unauthorized_anonymous_sender_target(self):
+        container = Container()
+        client = DynamicSourceAnonymousSender()
+        container.connect("guest:guest@127.0.0.1:%d" % self.router_port, handler=client)
+        container.run()
+        self.assertEqual(0, client.accepted)
+        self.assertEqual(1, client.rejected)
+        self.assertEqual(None, client.message)
+
 
 class AuthServicePluginAuthzDeprecatedTest(AuthServicePluginAuthzTest):
     @classmethod
@@ -189,11 +200,12 @@ class DynamicSourceAnonymousSender(MessagingHandler):
         super(DynamicSourceAnonymousSender, self).__init__()
         self.sender = None
         self.message = None
+        self.accepted = 0
+        self.rejected = 0
         self.errors = []
 
     def on_message(self, event):
         self.message = event.message.body;
-        event.connection.close()
 
     def on_link_opened(self, event):
         if event.receiver:
@@ -203,6 +215,14 @@ class DynamicSourceAnonymousSender(MessagingHandler):
         event.container.create_receiver(event.connection, None, dynamic=True)
         self.sender = event.container.create_sender(event.connection, None)
 
+    def on_accepted(self, event):
+        self.accepted += 1
+        event.connection.close()
+
+    def on_rejected(self, event):
+        self.rejected += 1
+        event.connection.close()
+
 if __name__ == '__main__':
     unittest.main(main_module())
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org