mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-09 09:38:09 +02:00
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
This commit is contained in:
parent
9cba634305
commit
af92d0d2aa
1 changed files with 459 additions and 423 deletions
882
bus/policy.c
882
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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue