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.

[plus a typo fix in an error message -smcv]

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=37890
Bug-NB: NB#269748
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
This commit is contained in:
Cosimo Alfarano 2011-07-11 17:03:00 +01:00 committed by Simon McVittie
parent 0ecd0a02b9
commit a940e7b1d1
2 changed files with 110 additions and 8 deletions

View file

@ -215,6 +215,20 @@ 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;
@ -354,6 +368,16 @@ bus_match_rule_set_destination (BusMatchRule *rule,
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,
@ -1030,6 +1054,31 @@ bus_match_rule_parse (DBusConnection *matches_go_to,
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) */
/* 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,
"eavesdrop='%s' is invalid, "
"it should be 'true' or 'false'\n",
value);
goto failed;
}
}
else if (strncmp (key, "arg", 3) == 0)
{
if (!bus_match_rule_parse_arg_match (rule, key, &tmp_str, error))
@ -1352,6 +1401,9 @@ match_rule_equal (BusMatchRule *a,
strcmp (a->destination, b->destination) != 0)
return FALSE;
/* we already compared the value of flags, and
* BUS_MATCH_CLIENT_IS_EAVESDROPPING does not have another struct member */
if (a->flags & BUS_MATCH_ARGS)
{
int i;
@ -1619,6 +1671,7 @@ match_rule_matches (BusMatchRule *rule,
DBusMessage *message,
BusMatchFlags already_matched)
{
dbus_bool_t wants_to_eavesdrop = FALSE;
int flags;
/* All features of the match rule are AND'd together,
@ -1633,6 +1686,9 @@ match_rule_matches (BusMatchRule *rule,
/* 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);
@ -1686,6 +1742,24 @@ match_rule_matches (BusMatchRule *rule,
}
}
/* 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;
@ -1694,6 +1768,12 @@ match_rule_matches (BusMatchRule *rule,
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)
@ -1707,6 +1787,19 @@ match_rule_matches (BusMatchRule *rule,
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)

View file

@ -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 (BusMatchRule *rule,
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);