From f15166d1f6a70e31812bf9f77d05b774e0102a7d Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 21 Oct 2015 19:53:12 +0100 Subject: [PATCH 2/3] Add send_broadcast as an attribute of and elements only matches broadcasts, which are signals with a NULL destination. There was previously no way for the policy language to express "NULL destination", only "any destination". only matches non-broadcasts, which are non-signals or signals with a non-NULL destination. There was previously no way for the policy language to express "any non-NULL destination", only "any destination". Bug: https://bugs.freedesktop.org/show_bug.cgi?id=92853 Signed-off-by: Simon McVittie --- bus/config-parser.c | 27 ++++++++++++++++++++++++++- bus/policy.c | 22 +++++++++++++++++++++- bus/policy.h | 8 ++++++++ doc/dbus-daemon.1.xml.in | 8 ++++++++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/bus/config-parser.c b/bus/config-parser.c index 4dc7d927..52576e9d 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -1294,6 +1294,7 @@ append_rule_from_element (BusConfigParser *parser, const char *send_path; const char *send_type; const char *send_requested_reply; + const char *send_broadcast; /* TRUE if any send_ attribute is present */ dbus_bool_t any_send_attribute; @@ -1331,6 +1332,7 @@ append_rule_from_element (BusConfigParser *parser, "send_destination", &send_destination, "send_path", &send_path, "send_type", &send_type, + "send_broadcast", &send_broadcast, "receive_interface", &receive_interface, "receive_member", &receive_member, "receive_error", &receive_error, @@ -1349,6 +1351,7 @@ append_rule_from_element (BusConfigParser *parser, return FALSE; any_send_attribute = (send_destination != NULL || + send_broadcast != NULL || send_path != NULL || send_type != NULL || send_interface != NULL || @@ -1399,7 +1402,7 @@ append_rule_from_element (BusConfigParser *parser, * interface + member * error * - * base send_ can combine with send_destination, send_path, send_type, send_requested_reply, eavesdrop + * base send_ can combine with send_destination, send_path, send_type, send_requested_reply, send_broadcast, eavesdrop * base receive_ with receive_sender, receive_path, receive_type, receive_requested_reply, eavesdrop * * user, group, own, own_prefix must occur alone @@ -1496,6 +1499,16 @@ append_rule_from_element (BusConfigParser *parser, return FALSE; } + if (send_broadcast && + !(strcmp (send_broadcast, "true") == 0 || + strcmp (send_broadcast, "false") == 0)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Bad value \"%s\" for %s attribute, must be true or false", + send_broadcast, "send_broadcast"); + return FALSE; + } + if (send_requested_reply && !(strcmp (send_requested_reply, "true") == 0 || strcmp (send_requested_reply, "false") == 0)) @@ -1519,6 +1532,18 @@ append_rule_from_element (BusConfigParser *parser, if (send_requested_reply) rule->d.send.requested_reply = (strcmp (send_requested_reply, "true") == 0); + if (send_broadcast) + { + if (strcmp (send_broadcast, "true") == 0) + rule->d.send.broadcast = BUS_POLICY_TRISTATE_TRUE; + else + rule->d.send.broadcast = BUS_POLICY_TRISTATE_FALSE; + } + else + { + rule->d.send.broadcast = BUS_POLICY_TRISTATE_ANY; + } + rule->d.send.message_type = message_type; rule->d.send.path = _dbus_strdup (send_path); rule->d.send.interface = _dbus_strdup (send_interface); diff --git a/bus/policy.c b/bus/policy.c index b5cca35a..d8d82f41 100644 --- a/bus/policy.c +++ b/bus/policy.c @@ -996,7 +996,27 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, continue; } } - + + if (rule->d.send.broadcast != BUS_POLICY_TRISTATE_ANY) + { + if (dbus_message_get_destination (message) == NULL && + dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL) + { + /* it's a broadcast */ + if (rule->d.send.broadcast == BUS_POLICY_TRISTATE_FALSE) + { + _dbus_verbose (" (policy) skipping rule because message is a broadcast\n"); + continue; + } + } + /* else it isn't a broadcast: there is some destination */ + else if (rule->d.send.broadcast == BUS_POLICY_TRISTATE_TRUE) + { + _dbus_verbose (" (policy) skipping rule because message is not a broadcast\n"); + continue; + } + } + if (rule->d.send.destination != NULL) { /* receiver can be NULL for messages that are sent to the diff --git a/bus/policy.h b/bus/policy.h index d1d3e72b..c5275a7b 100644 --- a/bus/policy.h +++ b/bus/policy.h @@ -39,6 +39,13 @@ typedef enum BUS_POLICY_RULE_GROUP } BusPolicyRuleType; +typedef enum +{ + BUS_POLICY_TRISTATE_ANY = 0, + BUS_POLICY_TRISTATE_FALSE, + BUS_POLICY_TRISTATE_TRUE +} BusPolicyTristate; + /** determines whether the rule affects a connection, or some global item */ #define BUS_POLICY_RULE_IS_PER_CLIENT(rule) (!((rule)->type == BUS_POLICY_RULE_USER || \ (rule)->type == BUS_POLICY_RULE_GROUP)) @@ -66,6 +73,7 @@ struct BusPolicyRule unsigned int eavesdrop : 1; unsigned int requested_reply : 1; unsigned int log : 1; + unsigned int broadcast : 2; /**< really a BusPolicyTristate */ } send; struct diff --git a/doc/dbus-daemon.1.xml.in b/doc/dbus-daemon.1.xml.in index a9a46eef..1a145786 100644 --- a/doc/dbus-daemon.1.xml.in +++ b/doc/dbus-daemon.1.xml.in @@ -838,6 +838,7 @@ statements, and works just like <deny> but with the inverse meaning. + + Rules with send_broadcast="true" match signal messages with no destination + (broadcasts), while rules with send_broadcast="false" match messages with + any unicast destination (unicast signals, together with all method calls, + replies and errors). + + The other send_* and receive_* attributes are purely textual/by-value matches against the given field in the message header. -- 2.11.0