From 056d76d809dc341b0dce160d3f79062604565c77 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 20 Mar 2003 07:57:39 +0000 Subject: 2003-03-20 Havoc Pennington * bus/connection.c (bus_connection_send_oom_error): assert that message has a sender (connection_execute_transaction): ditto (bus_connection_preallocate_oom_error): fix to set the sender, and set recipient to the destination service, not the bus driver * bus/policy.c: hacking * dbus/dbus-message.c (dbus_message_service_is): new function (dbus_message_sender_is): new --- bus/Makefile.am | 2 + bus/connection.c | 17 +++- bus/policy.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- bus/policy.h | 31 ++++--- 4 files changed, 279 insertions(+), 25 deletions(-) (limited to 'bus') diff --git a/bus/Makefile.am b/bus/Makefile.am index aee6e37a..bc64032c 100644 --- a/bus/Makefile.am +++ b/bus/Makefile.am @@ -21,6 +21,8 @@ BUS_SOURCES= \ driver.h \ loop.c \ loop.h \ + policy.c \ + policy.h \ services.c \ services.h \ test.c \ diff --git a/bus/connection.c b/bus/connection.c index 1b59819f..b01cbde6 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -504,7 +504,8 @@ bus_connection_preallocate_oom_error (DBusConnection *connection) if (preallocated == NULL) return FALSE; - message = dbus_message_new (DBUS_SERVICE_DBUS, + /* d->name may be NULL, but that should be OK */ + message = dbus_message_new (d->name, DBUS_ERROR_NO_MEMORY); if (message == NULL) { @@ -513,6 +514,14 @@ bus_connection_preallocate_oom_error (DBusConnection *connection) } dbus_message_set_is_error (message, TRUE); + + if (!dbus_message_set_sender (message, + DBUS_SERVICE_DBUS)) + { + dbus_connection_free_preallocated_send (connection, preallocated); + dbus_message_unref (message); + return FALSE; + } /* set reply serial to placeholder value just so space is already allocated * for it. @@ -546,6 +555,8 @@ bus_connection_send_oom_error (DBusConnection *connection, dbus_message_get_serial (in_reply_to))) _dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message"); + _dbus_assert (dbus_message_get_sender (d->oom_message) != NULL); + dbus_connection_send_preallocated (connection, d->oom_preallocated, d->oom_message, NULL); @@ -681,6 +692,8 @@ bus_transaction_send_message (BusTransaction *transaction, dbus_message_get_name (message), dbus_connection_get_is_connected (connection) ? "" : " (disconnected)"); + + _dbus_assert (dbus_message_get_sender (message) != NULL); if (!dbus_connection_get_is_connected (connection)) return TRUE; /* silently ignore disconnected connections */ @@ -811,6 +824,8 @@ connection_execute_transaction (DBusConnection *connection, _dbus_list_remove_link (&d->transaction_messages, link); + _dbus_assert (dbus_message_get_sender (m->message) != NULL); + dbus_connection_send_preallocated (connection, m->preallocated, m->message, diff --git a/bus/policy.c b/bus/policy.c index c94c17e1..f916383c 100644 --- a/bus/policy.c +++ b/bus/policy.c @@ -22,6 +22,9 @@ */ #include "policy.h" +#include "services.h" +#include +#include BusPolicyRule* bus_policy_rule_new (BusPolicyRuleType type, @@ -59,15 +62,15 @@ bus_policy_rule_unref (BusPolicyRule *rule) { switch (rule->type) { - case DBUS_POLICY_RULE_SEND: + case BUS_POLICY_RULE_SEND: dbus_free (rule->d.send.message_name); dbus_free (rule->d.send.destination); break; - case DBUS_POLICY_RULE_RECEIVE: + case BUS_POLICY_RULE_RECEIVE: dbus_free (rule->d.receive.message_name); dbus_free (rule->d.receive.origin); break; - case DBUS_POLICY_RULE_OWN: + case BUS_POLICY_RULE_OWN: dbus_free (rule->d.own.service_name); break; } @@ -133,31 +136,262 @@ bus_policy_unref (BusPolicy *policy) } } +static void +remove_rules_by_type_up_to (BusPolicy *policy, + BusPolicyRuleType type, + DBusList *up_to) +{ + DBusList *link; + + link = _dbus_list_get_first (&policy->rules); + while (link != up_to) + { + BusPolicyRule *rule = link->data; + DBusList *next = _dbus_list_get_next_link (&policy->rules, link); + + bus_policy_rule_unref (rule); + _dbus_list_remove_link (&policy->rules, link); + + link = next; + } +} + +static void +bus_policy_optimize (BusPolicy *policy) +{ + DBusList *link; + + /* The idea here is that if we have: + * + * + * + * + * (for example) the deny will always override the allow. So we + * delete the allow. Ditto for deny followed by allow, etc. This is + * a dumb thing to put in a config file, but the feature + * of files allows for an "inheritance and override" pattern where + * it could make sense. If an included file wants to "start over" + * with a blanket deny, no point keeping the rules from the parent + * file. + */ + + link = _dbus_list_get_first (&policy->rules); + while (link != NULL) + { + BusPolicyRule *rule = link->data; + DBusList *next = _dbus_list_get_next_link (&policy->rules, link); + dbus_bool_t remove_preceding; + + remove_preceding = FALSE; + + switch (rule->type) + { + case BUS_POLICY_RULE_SEND: + remove_preceding = + rule->d.send.message_name == NULL && + rule->d.send.destination == NULL; + break; + case BUS_POLICY_RULE_RECEIVE: + remove_preceding = + rule->d.receive.message_name == NULL && + rule->d.receive.origin == NULL; + break; + case BUS_POLICY_RULE_OWN: + remove_preceding = + rule->d.own.service_name == NULL; + break; + } + + if (remove_preceding) + remove_rules_by_type_up_to (policy, rule->type, + link); + + link = next; + } +} + dbus_bool_t bus_policy_check_can_send (BusPolicy *policy, - DBusConnection *sender, + BusRegistry *registry, + DBusConnection *receiver, DBusMessage *message) { + 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 + */ + + allowed = FALSE; + link = _dbus_list_get_first (&policy->rules); + while (link != NULL) + { + 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) + continue; + + if (rule->d.send.message_name != NULL) + { + if (!dbus_message_name_is (message, + rule->d.send.message_name)) + continue; + } + + if (rule->d.send.destination != NULL) + { + /* 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. + */ + if (receiver == NULL) + { + if (!dbus_message_sender_is (message, + 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) + continue; + + if (!bus_service_has_owner (service, receiver)) + continue; + } + } + + /* Use this rule */ + allowed = rule->allow; + } + return allowed; } dbus_bool_t bus_policy_check_can_receive (BusPolicy *policy, - DBusConnection *receiver, + BusRegistry *registry, + DBusConnection *sender, DBusMessage *message) { + 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 + */ + + allowed = FALSE; + link = _dbus_list_get_first (&policy->rules); + while (link != NULL) + { + 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 + */ + + if (rule->type != BUS_POLICY_RULE_RECEIVE) + continue; + + if (rule->d.receive.message_name != NULL) + { + if (!dbus_message_name_is (message, + rule->d.receive.message_name)) + 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_sender_is (message, + 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) + continue; + + if (!bus_service_has_owner (service, sender)) + continue; + } + } + /* Use this rule */ + allowed = rule->allow; + } + return allowed; } dbus_bool_t -bus_policy_check_can_own (BusPolicy *policy, - DBusConnection *connection, - const char *service_name) +bus_policy_check_can_own (BusPolicy *policy, + DBusConnection *connection, + const DBusString *service_name) { + 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 + */ + allowed = FALSE; + link = _dbus_list_get_first (&policy->rules); + while (link != NULL) + { + BusPolicyRule *rule = link->data; -} + link = _dbus_list_get_next_link (&policy->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.service_name != NULL) + { + if (!_dbus_string_equal_c_str (service_name, + rule->d.own.service_name)) + continue; + } -#endif /* BUS_POLICY_H */ + /* Use this rule */ + allowed = rule->allow; + } + + return allowed; +} diff --git a/bus/policy.h b/bus/policy.h index f146c528..00d60baa 100644 --- a/bus/policy.h +++ b/bus/policy.h @@ -25,6 +25,7 @@ #define BUS_POLICY_H #include +#include #include "bus.h" typedef struct BusPolicy BusPolicy; @@ -32,9 +33,9 @@ typedef struct BusPolicyRule BusPolicyRule; typedef enum { - DBUS_POLICY_RULE_SEND, - DBUS_POLICY_RULE_RECEIVE, - DBUS_POLICY_RULE_OWN + BUS_POLICY_RULE_SEND, + BUS_POLICY_RULE_RECEIVE, + BUS_POLICY_RULE_OWN } BusPolicyRuleType; struct BusPolicyRule @@ -76,17 +77,19 @@ void bus_policy_rule_ref (BusPolicyRule *rule); void bus_policy_rule_unref (BusPolicyRule *rule); BusPolicy* bus_policy_new (void); -void bus_policy_ref (BusPolicy *policy); -void bus_policy_unref (BusPolicy *policy); -dbus_bool_t bus_policy_check_can_send (BusPolicy *policy, - DBusConnection *sender, - DBusMessage *message); -dbus_bool_t bus_policy_check_can_receive (BusPolicy *policy, - DBusConnection *receiver, - DBusMessage *message); -dbus_bool_t bus_policy_check_can_own (BusPolicy *policy, - DBusConnection *connection, - const char *service_name); +void bus_policy_ref (BusPolicy *policy); +void bus_policy_unref (BusPolicy *policy); +dbus_bool_t bus_policy_check_can_send (BusPolicy *policy, + BusRegistry *registry, + DBusConnection *receiver, + DBusMessage *message); +dbus_bool_t bus_policy_check_can_receive (BusPolicy *policy, + BusRegistry *registry, + DBusConnection *sender, + DBusMessage *message); +dbus_bool_t bus_policy_check_can_own (BusPolicy *policy, + DBusConnection *connection, + const DBusString *service_name); -- cgit