From a26607ab68bf0878f23d2dbddec781b4b760d034 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 23 Mar 2003 07:41:54 +0000 Subject: 2003-03-23 Havoc Pennington * bus/policy.c, bus/bus.c, bus/connection.c: implement allow/deny policies code * dbus/dbus-hash.h: add ULONG hash keys * dbus/dbus-sysdeps.c (_dbus_get_groups): new (_dbus_get_group_id): new function --- bus/bus.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 199 insertions(+), 6 deletions(-) (limited to 'bus/bus.c') diff --git a/bus/bus.c b/bus/bus.c index 4b5b23b5..304faa99 100644 --- a/bus/bus.c +++ b/bus/bus.c @@ -41,7 +41,7 @@ struct BusContext BusActivation *activation; BusRegistry *registry; DBusList *default_rules; /**< Default policy rules */ - DBusList *override_rules; /**< Override policy rules */ + DBusList *mandatory_rules; /**< Mandatory policy rules */ DBusHashTable *rules_by_uid; /**< per-UID policy rules */ DBusHashTable *rules_by_gid; /**< per-GID policy rules */ }; @@ -117,13 +117,26 @@ new_connection_callback (DBusServer *server, } static void -free_rule_func (void *data) +free_rule_func (void *data, + void *user_data) { BusPolicyRule *rule = data; bus_policy_rule_unref (rule); } +static void +free_rule_list_func (void *data) +{ + DBusList **list = data; + + _dbus_list_foreach (list, free_rule_func, NULL); + + _dbus_list_clear (list); + + dbus_free (list); +} + BusContext* bus_context_new (const char *address, const char **service_dirs, @@ -179,18 +192,18 @@ bus_context_new (const char *address, goto failed; } - context->rules_by_uid = _dbus_hash_table_new (DBUS_HASH_INT, + context->rules_by_uid = _dbus_hash_table_new (DBUS_HASH_ULONG, NULL, - free_rule_func); + free_rule_list_func); if (context->rules_by_uid == NULL) { BUS_SET_OOM (error); goto failed; } - context->rules_by_gid = _dbus_hash_table_new (DBUS_HASH_INT, + context->rules_by_gid = _dbus_hash_table_new (DBUS_HASH_ULONG, NULL, - free_rule_func); + free_rule_list_func); if (context->rules_by_gid == NULL) { BUS_SET_OOM (error); @@ -328,3 +341,183 @@ bus_context_get_activation (BusContext *context) { return context->activation; } + +static dbus_bool_t +list_allows_user (dbus_bool_t def, + DBusList **list, + unsigned long uid, + const unsigned long *group_ids, + int n_group_ids) +{ + DBusList *link; + dbus_bool_t allowed; + + allowed = def; + + link = _dbus_list_get_first_link (list); + while (link != NULL) + { + BusPolicyRule *rule = link->data; + link = _dbus_list_get_next_link (list, link); + + if (rule->type == BUS_POLICY_RULE_USER) + { + if (rule->d.user.uid != uid) + continue; + } + else if (rule->type == BUS_POLICY_RULE_GROUP) + { + int i; + + i = 0; + while (i < n_group_ids) + { + if (rule->d.group.gid == group_ids[i]) + break; + ++i; + } + + if (i == n_group_ids) + continue; + } + else + continue; + + allowed = rule->allow; + } + + return allowed; +} + +dbus_bool_t +bus_context_allow_user (BusContext *context, + unsigned long uid) +{ + dbus_bool_t allowed; + unsigned long *group_ids; + int n_group_ids; + + /* On OOM or error we always reject the user */ + if (!_dbus_get_groups (uid, &group_ids, &n_group_ids)) + { + _dbus_verbose ("Did not get any groups for UID %lu\n", + uid); + return FALSE; + } + + allowed = FALSE; + + allowed = list_allows_user (allowed, + &context->default_rules, + uid, + group_ids, n_group_ids); + + allowed = list_allows_user (allowed, + &context->mandatory_rules, + uid, + group_ids, n_group_ids); + + dbus_free (group_ids); + + return allowed; +} + +static dbus_bool_t +add_list_to_policy (DBusList **list, + BusPolicy *policy) +{ + DBusList *link; + + link = _dbus_list_get_first_link (list); + while (link != NULL) + { + BusPolicyRule *rule = link->data; + link = _dbus_list_get_next_link (list, link); + + switch (rule->type) + { + case BUS_POLICY_RULE_USER: + case BUS_POLICY_RULE_GROUP: + /* These aren't per-connection policies */ + break; + + case BUS_POLICY_RULE_OWN: + case BUS_POLICY_RULE_SEND: + case BUS_POLICY_RULE_RECEIVE: + /* These are per-connection */ + if (!bus_policy_append_rule (policy, rule)) + return FALSE; + break; + } + } + + return TRUE; +} + +BusPolicy* +bus_context_create_connection_policy (BusContext *context, + DBusConnection *connection) +{ + BusPolicy *policy; + unsigned long uid; + DBusList **list; + + _dbus_assert (dbus_connection_get_is_authenticated (connection)); + + policy = bus_policy_new (); + if (policy == NULL) + return NULL; + + if (!add_list_to_policy (&context->default_rules, + policy)) + goto failed; + + /* we avoid the overhead of looking up user's groups + * if we don't have any group rules anyway + */ + if (_dbus_hash_table_get_n_entries (context->rules_by_gid) > 0) + { + const unsigned long *groups; + int n_groups; + int i; + + if (!bus_connection_get_groups (connection, &groups, &n_groups)) + goto failed; + + i = 0; + while (i < n_groups) + { + list = _dbus_hash_table_lookup_ulong (context->rules_by_gid, + groups[i]); + + if (list != NULL) + { + if (!add_list_to_policy (list, policy)) + goto failed; + } + + ++i; + } + } + + if (!dbus_connection_get_unix_user (connection, &uid)) + goto failed; + + list = _dbus_hash_table_lookup_ulong (context->rules_by_uid, + uid); + + if (!add_list_to_policy (list, policy)) + goto failed; + + if (!add_list_to_policy (&context->mandatory_rules, + policy)) + goto failed; + + bus_policy_optimize (policy); + + return policy; + + failed: + bus_policy_unref (policy); + return NULL; +} -- cgit