From af92d0d2aab4ac4d875c0e0a2f7bf61d3ae9bc56 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Wed, 20 May 2020 14:03:10 +0200 Subject: [PATCH] bus/policy: extract check_* functions No functional changes, just moving code around. This extracts check_send_rule, check_receive_rule, and check_own_rule from their own respective bus_client_policy_can_check_* functions. Change-Id: Ice4b2b96054b33a376bc3f48df29447747e7980e --- bus/policy.c | 882 +++++++++++++++++++++++++++------------------------ 1 file changed, 459 insertions(+), 423 deletions(-) diff --git a/bus/policy.c b/bus/policy.c index ec21d985..5e2c0c90 100644 --- a/bus/policy.c +++ b/bus/policy.c @@ -771,6 +771,440 @@ bus_client_policy_append_rule (BusClientPolicy *policy, return TRUE; } +static dbus_bool_t +check_send_rule (const BusPolicyRule *rule, + BusRegistry *registry, + dbus_bool_t requested_reply, + DBusConnection *receiver, + DBusMessage *message) +{ + /* Rule is skipped if it specifies a different + * message name from the message, or a different + * destination from the message + */ + if (rule->type != BUS_POLICY_RULE_SEND) + { + _dbus_verbose (" (policy) skipping non-send rule\n"); + return FALSE; + } + + 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"); + return FALSE; + } + } + + /* If it's a reply, the requested_reply flag kicks in */ + if (dbus_message_get_reply_serial (message) != 0) + { + /* for allow, requested_reply=true means the rule applies + * only when reply was requested. requested_reply=false means + * always allow. + */ + if (!requested_reply && rule->allow && rule->d.send.requested_reply && !rule->d.send.eavesdrop) + { + _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n"); + return FALSE; + } + + /* for deny, requested_reply=false means the rule applies only + * when the reply was not requested. requested_reply=true means the + * rule always applies. + */ + if (requested_reply && !rule->allow && !rule->d.send.requested_reply) + { + _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n"); + return FALSE; + } + } + + 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"); + return FALSE; + } + } + + if (rule->d.send.interface != NULL) + { + /* The interface is optional in messages. For allow rules, if the message + * has no interface we want to skip the rule (and thus not allow); + * for deny rules, if the message has no interface we want to use the + * rule (and thus deny). + */ + dbus_bool_t no_interface; + + no_interface = dbus_message_get_interface (message) == NULL; + + if ((no_interface && rule->allow) || + (!no_interface && + strcmp (dbus_message_get_interface (message), + rule->d.send.interface) != 0)) + { + _dbus_verbose (" (policy) skipping rule for different interface\n"); + return FALSE; + } + } + + 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"); + return FALSE; + } + } + + 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"); + return FALSE; + } + } + + 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"); + return FALSE; + } + } + /* 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"); + return FALSE; + } + } + + if (rule->d.send.destination != NULL && !rule->d.send.destination_is_prefix) + { + /* receiver can be NULL for messages that are sent to the + * message bus itself, we check the strings in that case as + * built-in services don't have a DBusConnection but messages + * to them have a destination service name. + * + * Similarly, receiver can be NULL when we're deciding whether + * activation should be allowed; we make the authorization decision + * on the assumption that the activated service will have the + * requested name and no others. + */ + if (receiver == NULL) + { + if (!dbus_message_has_destination (message, + rule->d.send.destination)) + { + _dbus_verbose (" (policy) skipping rule because message dest is not %s\n", + rule->d.send.destination); + return FALSE; + } + } + else + { + DBusString str; + BusService *service; + + _dbus_string_init_const (&str, rule->d.send.destination); + + service = bus_registry_lookup (registry, &str); + if (service == NULL) + { + _dbus_verbose (" (policy) skipping rule because dest %s doesn't exist\n", + rule->d.send.destination); + return FALSE; + } + + if (!bus_service_owner_in_queue (service, receiver)) + { + _dbus_verbose (" (policy) skipping rule because receiver isn't primary or queued owner of name %s\n", + rule->d.send.destination); + return FALSE; + } + } + } + + if (rule->d.send.destination != NULL && rule->d.send.destination_is_prefix) + { + /* receiver can be NULL - the same as in !send.destination_is_prefix */ + if (receiver == NULL) + { + const char *destination = dbus_message_get_destination (message); + DBusString dest_name; + + if (destination == NULL) + { + _dbus_verbose (" (policy) skipping rule because message has no dest\n"); + return FALSE; + } + + _dbus_string_init_const (&dest_name, destination); + + if (!_dbus_string_starts_with_words_c_str (&dest_name, + rule->d.send.destination, + '.')) + { + _dbus_verbose (" (policy) skipping rule because message dest doesn't have prefix %s\n", + rule->d.send.destination); + return FALSE; + } + } + else + { + if (!bus_connection_is_queued_owner_by_prefix (receiver, + rule->d.send.destination)) + { + _dbus_verbose (" (policy) skipping rule because recipient isn't primary or queued owner of any name below %s\n", + rule->d.send.destination); + return FALSE; + } + } + } + + if (rule->d.send.min_fds > 0 || + rule->d.send.max_fds < DBUS_MAXIMUM_MESSAGE_UNIX_FDS) + { + unsigned int n_fds = _dbus_message_get_n_unix_fds (message); + + if (n_fds < rule->d.send.min_fds || n_fds > rule->d.send.max_fds) + { + _dbus_verbose (" (policy) skipping rule because message has %u fds " + "and that is outside range [%u,%u]", + n_fds, rule->d.send.min_fds, rule->d.send.max_fds); + return FALSE; + } + } + + /* Use this rule */ + return TRUE; +} + +static dbus_bool_t +check_receive_rule (const BusPolicyRule *rule, + BusRegistry *registry, + dbus_bool_t requested_reply, + DBusConnection *sender, + DBusMessage *message, + dbus_bool_t eavesdropping) +{ + if (rule->type != BUS_POLICY_RULE_RECEIVE) + { + _dbus_verbose (" (policy) skipping non-receive rule\n"); + return FALSE; + } + + if (rule->d.receive.message_type != DBUS_MESSAGE_TYPE_INVALID) + { + if (dbus_message_get_type (message) != rule->d.receive.message_type) + { + _dbus_verbose (" (policy) skipping rule for different message type\n"); + return FALSE; + } + } + + /* 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"); + return FALSE; + } + + /* 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"); + return FALSE; + } + + /* If it's a reply, the requested_reply flag kicks in */ + if (dbus_message_get_reply_serial (message) != 0) + { + /* for allow, requested_reply=true means the rule applies + * only when reply was requested. requested_reply=false means + * always allow. + */ + if (!requested_reply && rule->allow && rule->d.receive.requested_reply && !rule->d.receive.eavesdrop) + { + _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n"); + return FALSE; + } + + /* for deny, requested_reply=false means the rule applies only + * when the reply was not requested. requested_reply=true means the + * rule always applies. + */ + if (requested_reply && !rule->allow && !rule->d.receive.requested_reply) + { + _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n"); + return FALSE; + } + } + + 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"); + return FALSE; + } + } + + if (rule->d.receive.interface != NULL) + { + /* The interface is optional in messages. For allow rules, if the message + * has no interface we want to skip the rule (and thus not allow); + * for deny rules, if the message has no interface we want to use the + * rule (and thus deny). + */ + dbus_bool_t no_interface; + + no_interface = dbus_message_get_interface (message) == NULL; + + if ((no_interface && rule->allow) || + (!no_interface && + strcmp (dbus_message_get_interface (message), + rule->d.receive.interface) != 0)) + { + _dbus_verbose (" (policy) skipping rule for different interface\n"); + return FALSE; + } + } + + 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"); + return FALSE; + } + } + + 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"); + return FALSE; + } + } + + if (rule->d.receive.origin != NULL) + { + /* sender can be NULL for messages that originate from the + * message bus itself, we check the strings in that case as + * built-in services don't have a DBusConnection but will + * still set the sender on their messages. + */ + if (sender == NULL) + { + if (!dbus_message_has_sender (message, + rule->d.receive.origin)) + { + _dbus_verbose (" (policy) skipping rule because message sender is not %s\n", + rule->d.receive.origin); + return FALSE; + } + } + else + { + BusService *service; + DBusString str; + + _dbus_string_init_const (&str, rule->d.receive.origin); + + service = bus_registry_lookup (registry, &str); + + if (service == NULL) + { + _dbus_verbose (" (policy) skipping rule because origin %s doesn't exist\n", + rule->d.receive.origin); + return FALSE; + } + + if (!bus_service_owner_in_queue (service, sender)) + { + _dbus_verbose (" (policy) skipping rule because sender isn't primary or queued owner of %s\n", + rule->d.receive.origin); + return FALSE; + } + } + } + + if (rule->d.receive.min_fds > 0 || + rule->d.receive.max_fds < DBUS_MAXIMUM_MESSAGE_UNIX_FDS) + { + unsigned int n_fds = _dbus_message_get_n_unix_fds (message); + + if (n_fds < rule->d.receive.min_fds || n_fds > rule->d.receive.max_fds) + { + _dbus_verbose (" (policy) skipping rule because message has %u fds " + "and that is outside range [%u,%u]", + n_fds, rule->d.receive.min_fds, + rule->d.receive.max_fds); + return FALSE; + } + } + + /* Use this rule */ + return TRUE; +} + +static dbus_bool_t +check_own_rule (const BusPolicyRule *rule, + const DBusString *service_name) +{ + /* Rule is skipped if it specifies a different service name from + * the desired one. + */ + + if (rule->type != BUS_POLICY_RULE_OWN) + return FALSE; + + if (!rule->d.own.prefix && rule->d.own.service_name != NULL) + { + if (!_dbus_string_equal_c_str (service_name, + rule->d.own.service_name)) + return FALSE; + } + else if (rule->d.own.prefix) + { + if (!_dbus_string_starts_with_words_c_str (service_name, + rule->d.own.service_name, + '.')) + return FALSE; + } + + /* Use this rule */ + return TRUE; +} + dbus_bool_t bus_client_policy_check_can_send (BusClientPolicy *policy, BusRegistry *registry, @@ -782,244 +1216,31 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, { DBusList *link; dbus_bool_t allowed; - + /* policy->rules is in the order the rules appeared * in the config file, i.e. last rule that applies wins */ _dbus_verbose (" (policy) checking send rules\n"); *toggles = 0; - + allowed = FALSE; link = _dbus_list_get_first_link (&policy->rules); while (link != NULL) { - BusPolicyRule *rule = link->data; + const 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 - * destination from the message - */ - - if (rule->type != BUS_POLICY_RULE_SEND) + + if (check_send_rule (rule, registry, requested_reply, receiver, message)) { - _dbus_verbose (" (policy) skipping non-send rule\n"); - continue; + allowed = rule->allow; + *log = rule->d.send.log; + (*toggles)++; + + _dbus_verbose (" (policy) used rule, allow now = %d\n", + allowed); } - - 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 it's a reply, the requested_reply flag kicks in */ - if (dbus_message_get_reply_serial (message) != 0) - { - /* for allow, requested_reply=true means the rule applies - * only when reply was requested. requested_reply=false means - * always allow. - */ - if (!requested_reply && rule->allow && rule->d.send.requested_reply && !rule->d.send.eavesdrop) - { - _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n"); - continue; - } - - /* for deny, requested_reply=false means the rule applies only - * when the reply was not requested. requested_reply=true means the - * rule always applies. - */ - if (requested_reply && !rule->allow && !rule->d.send.requested_reply) - { - _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\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) - { - /* The interface is optional in messages. For allow rules, if the message - * has no interface we want to skip the rule (and thus not allow); - * for deny rules, if the message has no interface we want to use the - * rule (and thus deny). - */ - dbus_bool_t no_interface; - - no_interface = dbus_message_get_interface (message) == NULL; - - if ((no_interface && rule->allow) || - (!no_interface && - strcmp (dbus_message_get_interface (message), - rule->d.send.interface) != 0)) - { - _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.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 && !rule->d.send.destination_is_prefix) - { - /* receiver can be NULL for messages that are sent to the - * message bus itself, we check the strings in that case as - * built-in services don't have a DBusConnection but messages - * to them have a destination service name. - * - * Similarly, receiver can be NULL when we're deciding whether - * activation should be allowed; we make the authorization decision - * on the assumption that the activated service will have the - * requested name and no others. - */ - if (receiver == NULL) - { - if (!dbus_message_has_destination (message, - rule->d.send.destination)) - { - _dbus_verbose (" (policy) skipping rule because message dest is not %s\n", - rule->d.send.destination); - continue; - } - } - else - { - DBusString str; - BusService *service; - - _dbus_string_init_const (&str, rule->d.send.destination); - - service = bus_registry_lookup (registry, &str); - if (service == NULL) - { - _dbus_verbose (" (policy) skipping rule because dest %s doesn't exist\n", - rule->d.send.destination); - continue; - } - - if (!bus_service_owner_in_queue (service, receiver)) - { - _dbus_verbose (" (policy) skipping rule because receiver isn't primary or queued owner of name %s\n", - rule->d.send.destination); - continue; - } - } - } - - if (rule->d.send.destination != NULL && rule->d.send.destination_is_prefix) - { - /* receiver can be NULL - the same as in !send.destination_is_prefix */ - if (receiver == NULL) - { - const char *destination = dbus_message_get_destination (message); - DBusString dest_name; - - if (destination == NULL) - { - _dbus_verbose (" (policy) skipping rule because message has no dest\n"); - continue; - } - - _dbus_string_init_const (&dest_name, destination); - - if (!_dbus_string_starts_with_words_c_str (&dest_name, - rule->d.send.destination, - '.')) - { - _dbus_verbose (" (policy) skipping rule because message dest doesn't have prefix %s\n", - rule->d.send.destination); - continue; - } - } - else - { - if (!bus_connection_is_queued_owner_by_prefix (receiver, - rule->d.send.destination)) - { - _dbus_verbose (" (policy) skipping rule because recipient isn't primary or queued owner of any name below %s\n", - rule->d.send.destination); - continue; - } - } - } - - if (rule->d.send.min_fds > 0 || - rule->d.send.max_fds < DBUS_MAXIMUM_MESSAGE_UNIX_FDS) - { - unsigned int n_fds = _dbus_message_get_n_unix_fds (message); - - if (n_fds < rule->d.send.min_fds || n_fds > rule->d.send.max_fds) - { - _dbus_verbose (" (policy) skipping rule because message has %u fds " - "and that is outside range [%u,%u]", - n_fds, rule->d.send.min_fds, rule->d.send.max_fds); - continue; - } - } - - /* Use this rule */ - allowed = rule->allow; - *log = rule->d.send.log; - (*toggles)++; - - _dbus_verbose (" (policy) used rule, allow now = %d\n", - allowed); } return allowed; @@ -1045,7 +1266,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, eavesdropping = addressed_recipient != proposed_recipient && dbus_message_get_destination (message) != NULL; - + /* policy->rules is in the order the rules appeared * in the config file, i.e. last rule that applies wins */ @@ -1057,191 +1278,25 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, link = _dbus_list_get_first_link (&policy->rules); while (link != NULL) { - BusPolicyRule *rule = link->data; + const BusPolicyRule *rule = link->data; - link = _dbus_list_get_next_link (&policy->rules, link); - - if (rule->type != BUS_POLICY_RULE_RECEIVE) + link = _dbus_list_get_next_link (&policy->rules, link); + + if (check_receive_rule (rule, registry, requested_reply, sender, + message, eavesdropping)) { - _dbus_verbose (" (policy) skipping non-receive rule\n"); - continue; + allowed = rule->allow; + (*toggles)++; + + _dbus_verbose (" (policy) used rule, allow now = %d\n", + allowed); } - if (rule->d.receive.message_type != DBUS_MESSAGE_TYPE_INVALID) - { - if (dbus_message_get_type (message) != rule->d.receive.message_type) - { - _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 it's a reply, the requested_reply flag kicks in */ - if (dbus_message_get_reply_serial (message) != 0) - { - /* for allow, requested_reply=true means the rule applies - * only when reply was requested. requested_reply=false means - * always allow. - */ - if (!requested_reply && rule->allow && rule->d.receive.requested_reply && !rule->d.receive.eavesdrop) - { - _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n"); - continue; - } - - /* for deny, requested_reply=false means the rule applies only - * when the reply was not requested. requested_reply=true means the - * rule always applies. - */ - if (requested_reply && !rule->allow && !rule->d.receive.requested_reply) - { - _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\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) - { - /* The interface is optional in messages. For allow rules, if the message - * has no interface we want to skip the rule (and thus not allow); - * for deny rules, if the message has no interface we want to use the - * rule (and thus deny). - */ - dbus_bool_t no_interface; - - no_interface = dbus_message_get_interface (message) == NULL; - - if ((no_interface && rule->allow) || - (!no_interface && - 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 - * message bus itself, we check the strings in that case as - * built-in services don't have a DBusConnection but will - * still set the sender on their messages. - */ - if (sender == NULL) - { - if (!dbus_message_has_sender (message, - rule->d.receive.origin)) - { - _dbus_verbose (" (policy) skipping rule because message sender is not %s\n", - rule->d.receive.origin); - continue; - } - } - else - { - BusService *service; - DBusString str; - - _dbus_string_init_const (&str, rule->d.receive.origin); - - service = bus_registry_lookup (registry, &str); - - if (service == NULL) - { - _dbus_verbose (" (policy) skipping rule because origin %s doesn't exist\n", - rule->d.receive.origin); - continue; - } - - if (!bus_service_owner_in_queue (service, sender)) - { - _dbus_verbose (" (policy) skipping rule because sender isn't primary or queued owner of %s\n", - rule->d.receive.origin); - continue; - } - } - } - - if (rule->d.receive.min_fds > 0 || - rule->d.receive.max_fds < DBUS_MAXIMUM_MESSAGE_UNIX_FDS) - { - unsigned int n_fds = _dbus_message_get_n_unix_fds (message); - - if (n_fds < rule->d.receive.min_fds || n_fds > rule->d.receive.max_fds) - { - _dbus_verbose (" (policy) skipping rule because message has %u fds " - "and that is outside range [%u,%u]", - n_fds, rule->d.receive.min_fds, - rule->d.receive.max_fds); - continue; - } - } - - /* Use this rule */ - allowed = rule->allow; - (*toggles)++; - - _dbus_verbose (" (policy) used rule, allow now = %d\n", - allowed); } return allowed; } - - static dbus_bool_t bus_rules_check_can_own (DBusList *rules, const DBusString *service_name) @@ -1257,33 +1312,14 @@ bus_rules_check_can_own (DBusList *rules, link = _dbus_list_get_first_link (&rules); while (link != NULL) { - BusPolicyRule *rule = link->data; + const BusPolicyRule *rule = link->data; link = _dbus_list_get_next_link (&rules, link); - /* Rule is skipped if it specifies a different service name from - * the desired one. - */ - - if (rule->type != BUS_POLICY_RULE_OWN) - continue; - - if (!rule->d.own.prefix && rule->d.own.service_name != NULL) + if (check_own_rule (rule, service_name)) { - if (!_dbus_string_equal_c_str (service_name, - rule->d.own.service_name)) - continue; + allowed = rule->allow; } - else if (rule->d.own.prefix) - { - if (!_dbus_string_starts_with_words_c_str (service_name, - rule->d.own.service_name, - '.')) - continue; - } - - /* Use this rule */ - allowed = rule->allow; } return allowed;