summaryrefslogtreecommitdiffstats
path: root/bus/bus.c
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-03-23 07:41:54 +0000
committerHavoc Pennington <hp@redhat.com>2003-03-23 07:41:54 +0000
commita26607ab68bf0878f23d2dbddec781b4b760d034 (patch)
treefe9153c14712ce893b605a7b23b47e4e7e8d17d8 /bus/bus.c
parentb6ffea177fccb6cc4e65992da7d8b390054277f7 (diff)
2003-03-23 Havoc Pennington <hp@pobox.com>
* 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
Diffstat (limited to 'bus/bus.c')
-rw-r--r--bus/bus.c205
1 files changed, 199 insertions, 6 deletions
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;
+}