From 41b371736f6750990f3e09aa884c75b3eef066bb Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 19 Jul 2017 15:53:17 +0100 Subject: [PATCH] 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 --- Be clearer that send_broadcast="false" matches exactly those messages that send_broadcast="true" does not, and neither is the same as send_destination="*". --- bus/config-parser.c | 27 ++++++++++++++++++++++++++- bus/policy.c | 22 +++++++++++++++++++++- bus/policy.h | 8 ++++++++ doc/dbus-daemon.1.xml.in | 11 +++++++++++ 4 files changed, 66 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 a1ef6e2f..cd2577dd 100644 --- a/doc/dbus-daemon.1.xml.in +++ b/doc/dbus-daemon.1.xml.in @@ -842,6 +842,7 @@ statements, and works just like <deny> but with the inverse meaning.receive_sender="*" similarly matches any message. + Rules with send_broadcast="true" match signal messages + with no destination (broadcasts). Rules with + send_broadcast="false" are the inverse: they match any + unicast destination (unicast signals, together with all method calls, replies + and errors) but do not match messages with no destination (broadcasts). This + is not the same as send_destination="*", which matches any + sent message, regardless of whether it has a destination or not. + + + The other send_* and receive_* attributes are purely textual/by-value matches against the given field in the message header, except that for the attributes where it is allowed, -- 2.13.3