diff options
Diffstat (limited to 'bus/policy.c')
-rw-r--r-- | bus/policy.c | 178 |
1 files changed, 156 insertions, 22 deletions
diff --git a/bus/policy.c b/bus/policy.c index 2f8e2ca3..2d462fb6 100644 --- a/bus/policy.c +++ b/bus/policy.c @@ -52,7 +52,11 @@ bus_policy_rule_new (BusPolicyRuleType type, rule->d.group.gid = DBUS_GID_UNSET; break; case BUS_POLICY_RULE_SEND: + rule->d.send.message_type = DBUS_MESSAGE_TYPE_INVALID; + break; case BUS_POLICY_RULE_RECEIVE: + rule->d.receive.message_type = DBUS_MESSAGE_TYPE_INVALID; + break; case BUS_POLICY_RULE_OWN: break; } @@ -80,11 +84,17 @@ bus_policy_rule_unref (BusPolicyRule *rule) switch (rule->type) { case BUS_POLICY_RULE_SEND: - dbus_free (rule->d.send.message_name); + dbus_free (rule->d.send.path); + dbus_free (rule->d.send.interface); + dbus_free (rule->d.send.member); + dbus_free (rule->d.send.error); dbus_free (rule->d.send.destination); break; case BUS_POLICY_RULE_RECEIVE: - dbus_free (rule->d.receive.message_name); + dbus_free (rule->d.receive.path); + dbus_free (rule->d.receive.interface); + dbus_free (rule->d.receive.member); + dbus_free (rule->d.receive.error); dbus_free (rule->d.receive.origin); break; case BUS_POLICY_RULE_OWN: @@ -680,8 +690,8 @@ bus_client_policy_optimize (BusClientPolicy *policy) /* The idea here is that if we have: * - * <allow send="foo"/> - * <deny send="*"/> + * <allow send_interface="foo.bar"/> + * <deny send_interface="*"/> * * (for example) the deny will always override the allow. So we * delete the allow. Ditto for deny followed by allow, etc. This is @@ -713,12 +723,20 @@ bus_client_policy_optimize (BusClientPolicy *policy) { case BUS_POLICY_RULE_SEND: remove_preceding = - rule->d.send.message_name == NULL && + rule->d.send.message_type == DBUS_MESSAGE_TYPE_INVALID && + rule->d.send.path == NULL && + rule->d.send.interface == NULL && + rule->d.send.member == NULL && + rule->d.send.error == NULL && rule->d.send.destination == NULL; break; case BUS_POLICY_RULE_RECEIVE: remove_preceding = - rule->d.receive.message_name == NULL && + rule->d.receive.message_type == DBUS_MESSAGE_TYPE_INVALID && + rule->d.receive.path == NULL && + rule->d.receive.interface == NULL && + rule->d.receive.member == NULL && + rule->d.receive.error == NULL && rule->d.receive.origin == NULL; break; case BUS_POLICY_RULE_OWN: @@ -791,16 +809,59 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, continue; } - if (rule->d.send.message_name != NULL) + if (rule->d.send.message_type != DBUS_MESSAGE_TYPE_INVALID) + { + if (dbus_message_get_type (message) != rule->d.send.message_type) + { + _dbus_verbose (" (policy) skipping rule for different message type\n"); + continue; + } + } + + if (rule->d.send.path != NULL) + { + if (dbus_message_get_path (message) != NULL && + strcmp (dbus_message_get_path (message), + rule->d.send.path) != 0) + { + _dbus_verbose (" (policy) skipping rule for different path\n"); + continue; + } + } + + if (rule->d.send.interface != NULL) { - if (!dbus_message_has_name (message, - rule->d.send.message_name)) + if (dbus_message_get_interface (message) != NULL && + strcmp (dbus_message_get_interface (message), + rule->d.send.interface) != 0) { - _dbus_verbose (" (policy) skipping rule for different message name\n"); + _dbus_verbose (" (policy) skipping rule for different interface\n"); continue; } } + if (rule->d.send.member != NULL) + { + if (dbus_message_get_member (message) != NULL && + strcmp (dbus_message_get_member (message), + rule->d.send.member) != 0) + { + _dbus_verbose (" (policy) skipping rule for different member\n"); + continue; + } + } + + if (rule->d.send.error != NULL) + { + if (dbus_message_get_error_name (message) != NULL && + strcmp (dbus_message_get_error_name (message), + rule->d.send.error) != 0) + { + _dbus_verbose (" (policy) skipping rule for different error name\n"); + continue; + } + } + if (rule->d.send.destination != NULL) { /* receiver can be NULL for messages that are sent to the @@ -856,16 +917,33 @@ dbus_bool_t bus_client_policy_check_can_receive (BusClientPolicy *policy, BusRegistry *registry, DBusConnection *sender, + DBusConnection *addressed_recipient, + DBusConnection *proposed_recipient, DBusMessage *message) { DBusList *link; dbus_bool_t allowed; + dbus_bool_t eavesdropping; + + /* NULL sender, proposed_recipient means the bus driver. NULL + * addressed_recipient means the message didn't specify an explicit + * target. If proposed_recipient is NULL, then addressed_recipient + * is also NULL but is implicitly the bus driver. + */ + + _dbus_assert (proposed_recipient == NULL || + (dbus_message_get_destination (message) == NULL || + addressed_recipient != NULL)); + + eavesdropping = + (proposed_recipient == NULL || /* explicitly to bus driver */ + (addressed_recipient && addressed_recipient != proposed_recipient)); /* explicitly to a different recipient */ /* policy->rules is in the order the rules appeared * in the config file, i.e. last rule that applies wins */ - _dbus_verbose (" (policy) checking receive rules\n"); + _dbus_verbose (" (policy) checking receive rules, eavesdropping = %d\n", eavesdropping); allowed = FALSE; link = _dbus_list_get_first_link (&policy->rules); @@ -873,12 +951,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, { BusPolicyRule *rule = link->data; - link = _dbus_list_get_next_link (&policy->rules, link); - - /* Rule is skipped if it specifies a different - * message name from the message, or a different - * origin from the message - */ + link = _dbus_list_get_next_link (&policy->rules, link); if (rule->type != BUS_POLICY_RULE_RECEIVE) { @@ -886,16 +959,77 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, continue; } - if (rule->d.receive.message_name != NULL) + if (rule->d.receive.message_type != DBUS_MESSAGE_TYPE_INVALID) { - if (!dbus_message_has_name (message, - rule->d.receive.message_name)) + if (dbus_message_get_type (message) != rule->d.receive.message_type) { - _dbus_verbose (" (policy) skipping rule for different message name\n"); + _dbus_verbose (" (policy) skipping rule for different message type\n"); continue; } } + /* for allow, eavesdrop=false means the rule doesn't apply when + * eavesdropping. eavesdrop=true means always allow. + */ + if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop) + { + _dbus_verbose (" (policy) skipping allow rule since it doesn't apply to eavesdropping\n"); + continue; + } + + /* for deny, eavesdrop=true means the rule applies only when + * eavesdropping; eavesdrop=false means always deny. + */ + if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop) + { + _dbus_verbose (" (policy) skipping deny rule since it only applies to eavesdropping\n"); + continue; + } + + if (rule->d.receive.path != NULL) + { + if (dbus_message_get_path (message) != NULL && + strcmp (dbus_message_get_path (message), + rule->d.receive.path) != 0) + { + _dbus_verbose (" (policy) skipping rule for different path\n"); + continue; + } + } + + if (rule->d.receive.interface != NULL) + { + if (dbus_message_get_interface (message) != NULL && + strcmp (dbus_message_get_interface (message), + rule->d.receive.interface) != 0) + { + _dbus_verbose (" (policy) skipping rule for different interface\n"); + continue; + } + } + + if (rule->d.receive.member != NULL) + { + if (dbus_message_get_member (message) != NULL && + strcmp (dbus_message_get_member (message), + rule->d.receive.member) != 0) + { + _dbus_verbose (" (policy) skipping rule for different member\n"); + continue; + } + } + + if (rule->d.receive.error != NULL) + { + if (dbus_message_get_error_name (message) != NULL && + strcmp (dbus_message_get_error_name (message), + rule->d.receive.error) != 0) + { + _dbus_verbose (" (policy) skipping rule for different error name\n"); + continue; + } + } + if (rule->d.receive.origin != NULL) { /* sender can be NULL for messages that originate from the @@ -937,7 +1071,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, } } } - + /* Use this rule */ allowed = rule->allow; |