From 8674bf5e4745e199c6ed5524f9ac3a7ceca892b7 Mon Sep 17 00:00:00 2001 From: Cosimo Alfarano Date: Fri, 1 Jul 2011 15:46:28 +0100 Subject: [PATCH 1/2] Do not allow eavedropping unless rule owner explicitely declare it Adds "eavesdrop=true" as a match rule, meaning that the owner intend to eavedrop. Otherwise the owner will receive only broadcasted messages and the ones meant to be delivered to it. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=37890 Bug-NB: NB#269748 Origin: vendor, Maemo --- bus/signals.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bus/signals.h | 25 +++++++++++----- 2 files changed, 105 insertions(+), 8 deletions(-) --- a/bus/signals.c +++ b/bus/signals.c @@ -241,6 +241,19 @@ match_rule_to_string (BusMatchRule *rule goto nomem; } + if (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) + { + if (_dbus_string_get_length (&str) > 0) + { + if (!_dbus_string_append (&str, ",")) + goto nomem; + } + + if (!_dbus_string_append_printf (&str, "eavesdrop='%s'", + (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) ? "true" : "false")) + goto nomem; + } + if (rule->flags & BUS_MATCH_ARGS) { int i; @@ -379,6 +392,16 @@ bus_match_rule_set_destination (BusMatch return TRUE; } +void +bus_match_rule_set_client_is_eavesdropping (BusMatchRule *rule, + dbus_bool_t is_eavesdropping) +{ + if (is_eavesdropping) + rule->flags |= BUS_MATCH_CLIENT_IS_EAVESDROPPING; + else + rule->flags &= ~(BUS_MATCH_CLIENT_IS_EAVESDROPPING); +} + dbus_bool_t bus_match_rule_set_path (BusMatchRule *rule, const char *path, @@ -1055,6 +1078,31 @@ bus_match_rule_parse (DBusConnection * goto failed; } } + else if (strcmp (key, "eavesdrop") == 0) + { + /* do not detect "eavesdrop" being used more than once in rule: + * 1) it's not possible, it's only in the flags + * 2) it might be used twice to disable eavesdropping when it's + * automatically added (eg dbus-monitor/bustle) */ + + _dbus_assert ((rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) == FALSE); + /* we accept only "true|false" as possible values */ + if ((strcmp (value, "true") == 0)) + { + bus_match_rule_set_client_is_eavesdropping (rule, TRUE); + } + else if (strcmp (value, "false") == 0) + { + bus_match_rule_set_client_is_eavesdropping (rule, FALSE); + } + else + { + dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, + "Eavesdropper client value '%s' is invalid\n", + value); + goto failed; + } + } else if (strncmp (key, "arg", 3) == 0) { if (!bus_match_rule_parse_arg_match (rule, key, &tmp_str, error)) @@ -1439,6 +1487,8 @@ match_rule_equal (BusMatchRule *a, strcmp (a->destination, b->destination) != 0) return FALSE; + /* BUS_MATCH_CLIENT_IS_EAVESDROPPING: we already matched flags */ + if (a->flags & BUS_MATCH_ARGS) { int i; @@ -1706,6 +1756,7 @@ match_rule_matches (BusMatchRule *rul DBusMessage *message, BusMatchFlags already_matched) { + dbus_bool_t wants_to_eavesdrop = FALSE; int flags; /* All features of the match rule are AND'd together, @@ -1720,6 +1771,9 @@ match_rule_matches (BusMatchRule *rul /* Don't bother re-matching features we've already checked implicitly. */ flags = rule->flags & (~already_matched); + if (flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) + wants_to_eavesdrop = TRUE; + if (flags & BUS_MATCH_MESSAGE_TYPE) { _dbus_assert (rule->message_type != DBUS_MESSAGE_TYPE_INVALID); @@ -1773,6 +1827,24 @@ match_rule_matches (BusMatchRule *rul } } + /* Note: this part is relevant for eavesdropper rules: + * Two cases: + * 1) rule has a destination to be matched + * (flag BUS_MATCH_DESTINATION present). Rule will match if: + * - rule->destination matches the addressed_recipient + * AND + * - wants_to_eavesdrop=TRUE + * + * Note: (the case in which addressed_recipient is the actual rule owner + * is handled elsewere in dispatch.c:bus_dispatch_matches(). + * + * 2) rule has no destination. Rule will match if: + * - message has no specified destination (ie broadcasts) + * (Note: this will rule out unicast method calls and unicast signals, + * fixing FDO#269748) + * OR + * - wants_to_eavesdrop=TRUE (destination-catch-all situation) + */ if (flags & BUS_MATCH_DESTINATION) { const char *destination; @@ -1781,6 +1853,12 @@ match_rule_matches (BusMatchRule *rul destination = dbus_message_get_destination (message); if (destination == NULL) + /* broadcast, but this rule specified a destination: no match */ + return FALSE; + + /* rule owner does not intend to eavesdrop: we'll deliver only msgs + * directed to it, NOT MATCHING */ + if (!wants_to_eavesdrop) return FALSE; if (addressed_recipient == NULL) @@ -1794,6 +1872,19 @@ match_rule_matches (BusMatchRule *rul if (!connection_is_primary_owner (addressed_recipient, rule->destination)) return FALSE; } + } else { /* no destination in rule */ + dbus_bool_t msg_is_broadcast; + + _dbus_assert (rule->destination == NULL); + + msg_is_broadcast = (dbus_message_get_destination (message) == NULL); + + if (!wants_to_eavesdrop && !msg_is_broadcast) + return FALSE; + + /* if we are here rule owner intends to eavesdrop + * OR + * message is being broadcasted */ } if (flags & BUS_MATCH_PATH) --- a/bus/signals.h +++ b/bus/signals.h @@ -31,14 +31,15 @@ typedef enum { - BUS_MATCH_MESSAGE_TYPE = 1 << 0, - BUS_MATCH_INTERFACE = 1 << 1, - BUS_MATCH_MEMBER = 1 << 2, - BUS_MATCH_SENDER = 1 << 3, - BUS_MATCH_DESTINATION = 1 << 4, - BUS_MATCH_PATH = 1 << 5, - BUS_MATCH_ARGS = 1 << 6, - BUS_MATCH_PATH_NAMESPACE = 1 << 7 + BUS_MATCH_MESSAGE_TYPE = 1 << 0, + BUS_MATCH_INTERFACE = 1 << 1, + BUS_MATCH_MEMBER = 1 << 2, + BUS_MATCH_SENDER = 1 << 3, + BUS_MATCH_DESTINATION = 1 << 4, + BUS_MATCH_PATH = 1 << 5, + BUS_MATCH_ARGS = 1 << 6, + BUS_MATCH_PATH_NAMESPACE = 1 << 7, + BUS_MATCH_CLIENT_IS_EAVESDROPPING = 1 << 8 } BusMatchFlags; BusMatchRule* bus_match_rule_new (DBusConnection *matches_go_to); @@ -64,6 +65,14 @@ dbus_bool_t bus_match_rule_set_arg dbus_bool_t is_path, dbus_bool_t is_namespace); +/* Calling this methods a client declares that it is creating a rule which + * needs to eavesdrop (e.g., dbus-monitor), any other created rules not + * setting themselves as eavesdropping won't receive any message not addressed + * to them, when eavedrop is enabled in the policy. On the other hand, when + * eavedrop is not enabled in policy, this method won't have any effect */ +void bus_match_rule_set_client_is_eavesdropping (BusMatchRule *rule, + dbus_bool_t is_eavesdropping); + BusMatchRule* bus_match_rule_parse (DBusConnection *matches_go_to, const DBusString *rule_text, DBusError *error);