You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
GConf2/polkit1.patch

1339 lines
41 KiB

diff -u -r GConf-2.26.0/configure.in hacked/configure.in
--- GConf-2.26.0/configure.in 2009-03-16 22:54:22.000000000 -0400
+++ hacked/configure.in 2009-05-11 22:12:16.772360600 -0400
@@ -172,7 +172,7 @@
[enable_defaults_service="$enableval"],
[enable_defaults_service=auto])
if test "x$enable_defaults_service" != "xno" ; then
- PKG_CHECK_MODULES(DEFAULTS, glib-2.0 gobject-2.0 dbus-1 dbus-glib-1 polkit-dbus, HAVE_POLKIT=yes, HAVE_POLKIT=no)
+ PKG_CHECK_MODULES(DEFAULTS, glib-2.0 gobject-2.0 dbus-1 dbus-glib-1 polkit-gobject-1, HAVE_POLKIT=yes, HAVE_POLKIT=no)
if test "x$HAVE_POLKIT" = "xno"; then
if test "x$enable_defaults_service" = "xyes" ; then
AC_MSG_ERROR([[
@@ -187,12 +187,6 @@
if test "x$enable_defaults_service" != "xno" ; then
AC_DEFINE(ENABLE_DEFAULTS_SERVICE, 1, [enable defaults DBus service])
-
- AC_CHECK_PROG([POLKIT_POLICY_FILE_VALIDATE],
- [polkit-policy-file-validate], [polkit-policy-file-validate])
- if test -z "$POLKIT_POLICY_FILE_VALIDATE"; then
- AC_MSG_ERROR([polkit-policy-file-validate not found])
- fi
fi
AM_CONDITIONAL(ENABLE_DEFAULTS_SERVICE, [test "x$enable_defaults_service" != "xno"])
diff -u -r GConf-2.26.0/defaults/gconf-defaults.c hacked/defaults/gconf-defaults.c
--- GConf-2.26.0/defaults/gconf-defaults.c 2009-02-16 13:17:44.000000000 -0500
+++ hacked/defaults/gconf-defaults.c 2009-05-13 17:44:52.474938376 -0400
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
- * Copyright (C) 2008 Matthias Clasen <mclasen@redhat.com>
+ * Copyright (C) 2008, 2009 Matthias Clasen <mclasen@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,7 +37,6 @@
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
-#include <polkit-dbus/polkit-dbus.h>
#include <polkit/polkit.h>
#define GCONF_ENABLE_INTERNALS
@@ -56,10 +55,14 @@
}
static guint timer_id = 0;
+gboolean disable_killtimer = FALSE;
static void
stop_killtimer (void)
{
+ if (disable_killtimer)
+ return;
+
if (timer_id > 0) {
g_source_remove (timer_id);
timer_id = 0;
@@ -69,15 +72,38 @@
static void
start_killtimer (void)
{
- g_debug ("Setting killtimer to 30 seconds...");
- timer_id = g_timeout_add_seconds (30, do_exit, NULL);
+ if (disable_killtimer)
+ return;
+
+ if (timer_id == 0) {
+ g_debug ("Setting killtimer to 30 seconds...");
+ timer_id = g_timeout_add_seconds (30, do_exit, NULL);
+ }
+}
+
+static gint operations = 0;
+
+static void
+start_operation (void)
+{
+ if (operations == 0)
+ stop_killtimer ();
+ operations++;
+}
+
+static void
+stop_operation (void)
+{
+ if (operations == 1)
+ start_killtimer ();
+ operations --;
}
struct GConfDefaultsPrivate
{
DBusGConnection *system_bus_connection;
DBusGProxy *system_bus_proxy;
- PolKitContext *pol_ctx;
+ PolkitAuthority *auth;
};
static void gconf_defaults_finalize (GObject *object);
@@ -105,7 +131,7 @@
gconf_defaults_error_get_type (void)
{
static GType etype = 0;
-
+
if (etype == 0)
{
static const GEnumValue values[] =
@@ -114,12 +140,12 @@
ENUM_ENTRY (GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
{ 0, 0, 0 }
};
-
+
g_assert (GCONF_DEFAULTS_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
-
+
etype = g_enum_register_static ("GConfDefaultsError", values);
}
-
+
return etype;
}
@@ -191,56 +217,18 @@
g_return_if_fail (mechanism->priv != NULL);
+ g_object_unref (mechanism->priv->auth);
g_object_unref (mechanism->priv->system_bus_proxy);
G_OBJECT_CLASS (gconf_defaults_parent_class)->finalize (object);
}
static gboolean
-pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
-{
- int fd;
- PolKitContext *pk_context = user_data;
- fd = g_io_channel_unix_get_fd (channel);
- polkit_context_io_func (pk_context, fd);
- return TRUE;
-}
-
-static int
-pk_io_add_watch (PolKitContext *pk_context, int fd)
-{
- guint id = 0;
- GIOChannel *channel;
- channel = g_io_channel_unix_new (fd);
- if (channel == NULL)
- goto out;
- id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context);
- if (id == 0) {
- g_io_channel_unref (channel);
- goto out;
- }
- g_io_channel_unref (channel);
-out:
- return id;
-}
-
-static void
-pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
-{
- g_source_remove (watch_id);
-}
-
-static gboolean
register_mechanism (GConfDefaults *mechanism)
{
GError *error = NULL;
- mechanism->priv->pol_ctx = polkit_context_new ();
- polkit_context_set_io_watch_functions (mechanism->priv->pol_ctx, pk_io_add_watch, pk_io_remove_watch);
- if (!polkit_context_init (mechanism->priv->pol_ctx, NULL)) {
- g_critical ("cannot initialize libpolkit");
- goto error;
- }
+ mechanism->priv->auth = polkit_authority_get ();
error = NULL;
mechanism->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
@@ -252,7 +240,7 @@
goto error;
}
- dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/",
+ dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/",
G_OBJECT (mechanism));
mechanism->priv->system_bus_proxy = dbus_g_proxy_new_for_name (mechanism->priv->system_bus_connection,
@@ -288,33 +276,37 @@
static const char *
polkit_action_for_gconf_path (GConfDefaults *mechanism,
+ GList *action_descriptions,
const char *annotation_key,
const char *path)
{
- PolKitPolicyCache *cache;
- PolKitPolicyFileEntry *entry;
char *prefix, *p;
const char *action;
+ GList *l;
+ PolkitActionDescription *action_description;
+ const gchar *annotation;
- cache = polkit_context_get_policy_cache (mechanism->priv->pol_ctx);
prefix = g_strdup (path);
while (1) {
- entry = polkit_policy_cache_get_entry_by_annotation (cache,
- annotation_key,
- prefix);
- if (entry) {
- action = polkit_policy_file_entry_get_id (entry);
- break;
+ for (l = action_descriptions; l; l = l->next) {
+ action_description = l->data;
+
+ annotation = polkit_action_description_get_annotation (action_description, annotation_key);
+ if (g_strcmp0 (prefix, annotation) == 0) {
+ action = polkit_action_description_get_action_id (action_description);
+ g_debug ("action for path '%s': '%s'\n", action, path);
+ break;
+ }
}
-
+
p = strrchr (prefix, '/');
if (p == NULL || p == prefix) {
action = NULL;
break;
}
-
+
*p = 0;
}
@@ -323,56 +315,158 @@
return action;
}
-static gboolean
-check_polkit_for_action (GConfDefaults *mechanism,
- DBusGMethodInvocation *context,
- const char *action)
-{
- const char *sender;
- GError *error;
- DBusError dbus_error;
- PolKitCaller *pk_caller;
- PolKitAction *pk_action;
- PolKitResult pk_result;
+static void
+throw_error (DBusGMethodInvocation *context,
+ gint error_code,
+ const gchar *format,
+ ...)
+{
+ GError *error;
+ va_list args;
+ gchar *message;
- error = NULL;
+ va_start (args, format);
+ message = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ error = g_error_new (GCONF_DEFAULTS_ERROR,
+ error_code,
+ "%s", message);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ g_free (message);
+}
+
+typedef void (*AuthObtainedCallback) (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gpointer user_data);
+
+typedef struct
+{
+ GConfDefaults *mechanism;
+ DBusGMethodInvocation *context;
+ gchar **actions;
+ gint id;
+ gint flags;
+ AuthObtainedCallback auth_obtained_callback;
+ GAsyncReadyCallback check_auth_callback;
+ gpointer user_data;
+ GDestroyNotify destroy;
+ PolkitSubject *subject;
+} CheckAuthData;
- /* Check that caller is privileged */
- sender = dbus_g_method_get_sender (context);
- dbus_error_init (&dbus_error);
- pk_caller = polkit_caller_new_from_dbus_name (
- dbus_g_connection_get_connection (mechanism->priv->system_bus_connection),
- sender,
- &dbus_error);
- if (pk_caller == NULL) {
- error = g_error_new (GCONF_DEFAULTS_ERROR,
- GCONF_DEFAULTS_ERROR_GENERAL,
- "Error getting information about caller: %s: %s",
- dbus_error.name, dbus_error.message);
- dbus_error_free (&dbus_error);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return FALSE;
- }
+static void
+check_auth_data_free (CheckAuthData *data)
+{
+ g_object_unref (data->mechanism);
+ g_strfreev (data->actions);
+ if (data->destroy)
+ data->destroy (data->user_data);
+ g_object_unref (data->subject);
+ g_free (data);
+}
- pk_action = polkit_action_new ();
- polkit_action_set_action_id (pk_action, action);
- pk_result = polkit_context_is_caller_authorized (mechanism->priv->pol_ctx, pk_action, pk_caller, TRUE, NULL);
- polkit_caller_unref (pk_caller);
-
- if (pk_result != POLKIT_RESULT_YES) {
- dbus_error_init (&dbus_error);
- polkit_dbus_error_generate (pk_action, pk_result, &dbus_error);
- dbus_set_g_error (&error, &dbus_error);
- dbus_g_method_return_error (context, error);
- dbus_error_free (&dbus_error);
- g_error_free (error);
- polkit_action_unref (pk_action);
- return FALSE;
- }
+static void check_next_action (CheckAuthData *data);
- polkit_action_unref (pk_action);
- return TRUE;
+static void
+check_authorization_callback (PolkitAuthority *authority,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CheckAuthData *data = user_data;
+ PolkitAuthorizationResult *result;
+ GError *error;
+ gboolean is_authorized;
+
+ is_authorized = FALSE;
+
+ error = NULL;
+ result = polkit_authority_check_authorization_finish (authority,
+ res,
+ &error);
+ if (error != NULL) {
+ g_debug ("error checking action '%s'\n", error->message);
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+ "Not Authorized: %s", error->message);
+ g_error_free (error);
+ }
+ else {
+ if (polkit_authorization_result_get_is_authorized (result)) {
+ g_debug ("result for '%s': authorized\n",
+ data->actions[data->id]);
+ is_authorized = TRUE;
+ }
+ else if (polkit_authorization_result_get_is_challenge (result)) {
+ g_debug ("result for '%s': challenge\n",
+ data->actions[data->id]);
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+ "Authorization is required");
+ }
+ else {
+ g_debug ("result for '%s': not authorized\n",
+ data->actions[data->id]);
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+ "Not Authorized");
+ }
+ }
+
+ if (is_authorized) {
+ data->id++;
+ if (data->actions[data->id] == NULL)
+ data->auth_obtained_callback (data->mechanism,
+ data->context,
+ data->user_data);
+ else {
+ check_next_action (data);
+ return; /* continue operation */
+ }
+ }
+
+ check_auth_data_free (data);
+ g_object_unref (result);
+ stop_operation ();
+}
+
+static void
+check_next_action (CheckAuthData *data)
+{
+ g_debug ("checking action '%s'\n", data->actions[data->id]);
+ polkit_authority_check_authorization (data->mechanism->priv->auth,
+ data->subject,
+ data->actions[data->id],
+ NULL,
+ data->flags,
+ NULL,
+ data->check_auth_callback,
+ data);
+}
+
+static void
+check_polkit_for_actions (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gchar **actions,
+ AuthObtainedCallback auth_obtained_callback,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ CheckAuthData *data;
+
+ data = g_new0 (CheckAuthData, 1);
+ data->mechanism = g_object_ref (mechanism);
+ data->context = context;
+ data->actions = actions;
+ data->flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
+ data->id = 0;
+ data->auth_obtained_callback = auth_obtained_callback;
+ data->check_auth_callback = (GAsyncReadyCallback)check_authorization_callback;
+ data->user_data = user_data;
+ data->destroy = destroy;
+ data->subject = polkit_system_bus_name_new (dbus_g_method_get_sender (context));
+
+ check_next_action (data);
}
static char *
@@ -398,11 +492,11 @@
dbus_error_free (&error);
return NULL;
}
-
+
pwd = getpwuid (uid);
if (pwd == NULL) {
- g_set_error (gerror,
- 0, 0,
+ g_set_error (gerror,
+ 0, 0,
"Failed to get passwd information for uid %d", uid);
return NULL;
}
@@ -434,13 +528,13 @@
GSList *list, *l;
GConfEntry *entry;
- if (path_is_excluded (path, excludes))
+ if (path_is_excluded (path, excludes))
return;
list = gconf_client_all_entries (src, path, NULL);
for (l = list; l; l = l->next) {
entry = l->data;
- if (!path_is_excluded (entry->key, excludes))
+ if (!path_is_excluded (entry->key, excludes))
gconf_change_set_set (changes, entry->key, entry->value);
}
g_slist_foreach (list, (GFunc)gconf_entry_free, NULL);
@@ -461,7 +555,7 @@
{
GConfValue *value;
- if (path_is_excluded (path, excludes))
+ if (path_is_excluded (path, excludes))
return;
value = gconf_client_get (src, path, NULL);
@@ -471,69 +565,66 @@
}
}
+typedef void (*ChangeSetCallback) (GConfDefaults *mechanism,
+ GConfChangeSet *changes,
+ gpointer data);
+
+typedef struct
+{
+ GConfDefaults *mechanism;
+ DBusGMethodInvocation *context;
+ const char *dest_address;
+ char **actions;
+ char **includes;
+ char **excludes;
+ ChangeSetCallback changeset_callback;
+ gpointer user_data;
+ GDestroyNotify destroy;
+} CopyData;
static void
-do_copy (GConfDefaults *mechanism,
- gboolean mandatory,
- const char **includes,
- const char **excludes,
- DBusGMethodInvocation *context,
- GConfChangeSet **changeset_out)
+copy_data_free (gpointer user_data)
{
- char *address = NULL;
- GConfClient *source = NULL;
+ CopyData *data = user_data;
+
+ g_object_unref (data->mechanism);
+ g_strfreev (data->includes);
+ g_strfreev (data->excludes);
+ g_strfreev (data->actions);
+ if (data->destroy)
+ data->destroy (data->user_data);
+ g_free (data);
+}
+
+static void
+do_copy_authorized (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ CopyData *data = user_data;
+ GConfClient *source = NULL;
GConfClient *dest = NULL;
GConfChangeSet *changes = NULL;
GConfEngine *engine;
+ char *address = NULL;
+ gint i;
GError *error;
- GError *error2;
- const char *action;
- const char *annotation_key;
- const char *default_action;
- const char *dest_address;
- int i;
-
- if (changeset_out)
- *changeset_out = NULL;
-
- stop_killtimer ();
-
- /* check privileges for each include */
- if (mandatory) {
- annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
- default_action = "org.gnome.gconf.defaults.set-mandatory";
- dest_address = "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory";
- }
- else {
- annotation_key = "org.gnome.gconf.defaults.set-system.prefix";
- default_action = "org.gnome.gconf.defaults.set-system";
- dest_address = "xml:merged:" SYSGCONFDIR "/gconf.xml.system";
- }
-
- for (i = 0; includes[i]; i++) {
- action = polkit_action_for_gconf_path (mechanism, annotation_key, includes[i]);
- if (action == NULL)
- action = default_action;
-
- if (!check_polkit_for_action (mechanism, context, action))
- goto out;
- }
error = NULL;
- engine = gconf_engine_get_local (dest_address, &error);
- if (error)
- goto cleanup;
+ engine = gconf_engine_get_local (data->dest_address, &error);
+ if (error)
+ goto cleanup;
dest = gconf_client_get_for_engine (engine);
gconf_engine_unref (engine);
/* find the address to from the caller id */
- address = gconf_address_for_caller (mechanism, context, &error);
+ address = gconf_address_for_caller (data->mechanism, data->context, &error);
if (error)
goto cleanup;
engine = gconf_engine_get_local (address, &error);
- if (error)
+ if (error)
goto cleanup;
source = gconf_client_get_for_engine (engine);
@@ -542,45 +633,175 @@
changes = gconf_change_set_new ();
/* recursively copy each include, leaving out the excludes */
- for (i = 0; includes[i]; i++) {
- if (gconf_client_dir_exists (source, includes[i], NULL))
- copy_tree (source, includes[i], changes, excludes);
+ for (i = 0; data->includes[i]; i++) {
+ if (gconf_client_dir_exists (source, data->includes[i], NULL))
+ copy_tree (source, data->includes[i], changes, (const char **)data->excludes);
else
- copy_entry (source, includes[i], changes, excludes);
+ copy_entry (source, data->includes[i], changes, (const char **)data->excludes);
}
gconf_client_commit_change_set (dest, changes, FALSE, &error);
gconf_client_suggest_sync (dest, NULL);
- if (changeset_out) {
- *changeset_out = changes;
- changes = NULL;
+ if (data->changeset_callback) {
+ data->changeset_callback (data->mechanism, changes, data->user_data);
}
cleanup:
g_free (address);
if (changes)
gconf_change_set_unref (changes);
- if (dest)
+ if (dest)
g_object_unref (dest);
if (source)
g_object_unref (source);
if (error) {
- g_print ("failed to set GConf values: %s\n", error->message);
- error2 = g_error_new_literal (GCONF_DEFAULTS_ERROR,
- GCONF_DEFAULTS_ERROR_GENERAL,
- error->message);
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_GENERAL,
+ "%s", error->message);
g_error_free (error);
-
- dbus_g_method_return_error (context, error2);
- g_error_free (error2);
}
else
- dbus_g_method_return (context);
+ dbus_g_method_return (data->context);
+}
-out:
- start_killtimer ();
+typedef void (*ActionsReadyCallback) (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gchar **actions,
+ AuthObtainedCallback auth_obtained_callback,
+ gpointer data,
+ GDestroyNotify destroy);
+
+typedef struct
+{
+ GConfDefaults *mechanism;
+ DBusGMethodInvocation *context;
+ char **includes;
+ const char *default_action;
+ const char *annotation_key;
+ ActionsReadyCallback actions_ready_callback;
+ AuthObtainedCallback auth_obtained_callback;
+ gpointer data;
+ GDestroyNotify destroy;
+} ActionData;
+
+static void
+action_data_free (ActionData *data)
+{
+ g_object_unref (data->mechanism);
+ g_strfreev (data->includes);
+ if (data->destroy)
+ data->destroy (data->data);
+ g_free (data);
+}
+
+static void
+actions_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ ActionData *data = user_data;
+ GList *action_descriptions;
+ GError *error = NULL;
+ int i;
+ GHashTable *obtained;
+ GHashTableIter iter;
+ const gchar *action;
+ gchar **actions;
+ gpointer key, value;
+
+ action_descriptions = polkit_authority_enumerate_actions_finish (data->mechanism->priv->auth, res, &error);
+
+ if (error) {
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_GENERAL,
+ "Failed to get action descriptions: %s", error->message);
+ g_error_free (error);
+ action_data_free (data);
+ stop_operation ();
+ return;
+ }
+
+ obtained = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for (i = 0; data->includes[i]; i++) {
+ action = polkit_action_for_gconf_path (data->mechanism, action_descriptions, data->annotation_key, data->includes[i]);
+ if (action == NULL) {
+ g_debug ("using default action '%s' for path '%s'",
+ data->default_action, data->includes[i]);
+ action = data->default_action;
+ }
+
+ g_hash_table_insert (obtained, (gpointer)action, (gpointer)action);
+ }
+ actions = g_new0 (char *, g_hash_table_size (obtained) + 1);
+ g_hash_table_iter_init (&iter, obtained);
+ i = 0;
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ actions[i] = g_strdup ((char *)key);
+ i++;
+ }
+ g_hash_table_destroy (obtained);
+ g_list_foreach (action_descriptions, (GFunc)g_object_unref, NULL);
+ g_list_free (action_descriptions);
+
+ data->actions_ready_callback (data->mechanism, data->context, actions, data->auth_obtained_callback, data->data, data->destroy);
+
+ data->destroy = NULL;
+ action_data_free (data);
+}
+
+static void
+do_copy (GConfDefaults *mechanism,
+ gboolean mandatory,
+ const gchar **includes,
+ const gchar **excludes,
+ DBusGMethodInvocation *context,
+ ChangeSetCallback changeset_callback,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ CopyData *cdata;
+ ActionData *adata;
+
+ start_operation ();
+
+ cdata = g_new0 (CopyData, 1);
+ cdata->mechanism = g_object_ref (mechanism);
+ cdata->context = context;
+ cdata->includes = g_strdupv ((gchar **)includes);
+ cdata->excludes = g_strdupv ((gchar **)excludes);
+ cdata->actions = NULL;
+ cdata->changeset_callback = changeset_callback;
+ cdata->user_data = user_data;
+ cdata->destroy = destroy;
+
+ adata = g_new0 (ActionData, 1);
+ adata->mechanism = g_object_ref (mechanism);
+ adata->context = context;
+ adata->includes = g_strdupv ((gchar **)includes);
+ adata->actions_ready_callback = check_polkit_for_actions;
+ adata->auth_obtained_callback = do_copy_authorized;
+ adata->data = cdata;
+ adata->destroy = copy_data_free;
+
+ /* check privileges for each include */
+ if (mandatory) {
+ adata->annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
+ adata->default_action = "org.gnome.gconf.defaults.set-mandatory";
+ cdata->dest_address = "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory";
+ }
+ else {
+ adata->annotation_key = "org.gnome.gconf.defaults.set-system.prefix";
+ adata->default_action = "org.gnome.gconf.defaults.set-system";
+ cdata->dest_address = "xml:merged:" SYSGCONFDIR "/gconf.xml.system";
+ }
+
+ polkit_authority_enumerate_actions (mechanism->priv->auth,
+ NULL,
+ actions_ready_cb,
+ adata);
}
static void
@@ -594,20 +815,13 @@
g_ptr_array_add (keys, (gpointer) key);
}
-void
-gconf_defaults_set_system (GConfDefaults *mechanism,
- const char **includes,
- const char **excludes,
- DBusGMethodInvocation *context)
+static void
+set_system_changes (GConfDefaults *mechanism,
+ GConfChangeSet *changes,
+ gpointer data)
{
- GConfChangeSet *changes = NULL;
GPtrArray *keys;
- do_copy (mechanism, FALSE, includes, excludes, context, &changes);
-
- if (!changes)
- return;
-
keys = g_ptr_array_new ();
gconf_change_set_foreach (changes, append_key, keys);
g_ptr_array_add (keys, NULL);
@@ -615,7 +829,15 @@
g_signal_emit (mechanism, signals[SYSTEM_SET], 0, keys->pdata);
g_ptr_array_free (keys, TRUE);
- gconf_change_set_unref (changes);
+}
+
+void
+gconf_defaults_set_system (GConfDefaults *mechanism,
+ const char **includes,
+ const char **excludes,
+ DBusGMethodInvocation *context)
+{
+ do_copy (mechanism, FALSE, includes, excludes, context, set_system_changes, NULL, NULL);
}
void
@@ -624,7 +846,7 @@
const char **excludes,
DBusGMethodInvocation *context)
{
- do_copy (mechanism, TRUE, includes, excludes, context, NULL);
+ do_copy (mechanism, TRUE, includes, excludes, context, NULL, NULL, NULL);
}
static void
@@ -636,13 +858,13 @@
GSList *list, *l;
GConfEntry *entry;
- if (path_is_excluded (path, excludes))
+ if (path_is_excluded (path, excludes))
return;
list = gconf_client_all_entries (dest, path, NULL);
for (l = list; l; l = l->next) {
entry = l->data;
- if (!path_is_excluded (entry->key, excludes))
+ if (!path_is_excluded (entry->key, excludes))
gconf_change_set_unset (changes, entry->key);
}
g_slist_foreach (list, (GFunc)gconf_entry_free, NULL);
@@ -654,25 +876,25 @@
g_slist_foreach (list, (GFunc)g_free, NULL);
g_slist_free (list);
}
-
+
static void
unset_entry (GConfClient *dest,
const char *path,
GConfChangeSet *changes,
const char **excludes)
{
- if (path_is_excluded (path, excludes))
+ if (path_is_excluded (path, excludes))
return;
gconf_change_set_unset (changes, path);
}
-
+
static void
-unset_in_db (GConfDefaults *mechanism,
- const char *address,
- const char **includes,
- const char **excludes,
- GError **error)
+unset_in_db (GConfDefaults *mechanism,
+ const gchar *address,
+ const gchar **includes,
+ const gchar **excludes,
+ GError **error)
{
GConfEngine *engine;
GConfClient *dest = NULL;
@@ -680,7 +902,7 @@
int i;
engine = gconf_engine_get_local (address, error);
- if (*error)
+ if (*error)
goto out;
dest = gconf_client_get_for_engine (engine);
@@ -706,48 +928,219 @@
gconf_change_set_unref (changes);
}
+typedef struct
+{
+ GConfDefaults *mechanism;
+ DBusGMethodInvocation *context;
+ char **includes;
+ char **excludes;
+} UnsetData;
+
+static void
+unset_data_free (gpointer user_data)
+{
+ UnsetData *data = user_data;
+
+ g_object_unref (data->mechanism);
+ g_strfreev (data->includes);
+ g_strfreev (data->excludes);
+ g_free (data);
+}
+
+static void
+do_unset_authorized (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ UnsetData *data = user_data;
+ GError *error;
+
+ error = NULL;
+ unset_in_db (mechanism, "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory",
+ (const gchar **)data->includes,
+ (const gchar **)data->excludes, &error);
+
+ if (error) {
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR,
+ GCONF_DEFAULTS_ERROR_GENERAL,
+ "%s", error->message);
+ g_error_free (error);
+ }
+ else
+ dbus_g_method_return (data->context);
+}
+
void
gconf_defaults_unset_mandatory (GConfDefaults *mechanism,
const char **includes,
const char **excludes,
DBusGMethodInvocation *context)
{
- const char *annotation_key;
- const char *default_action;
- int i;
- const char *action;
- GError *error;
- GError *error2;
+ UnsetData *udata;
+ ActionData *adata;
- stop_killtimer ();
+ start_operation ();
- annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
- default_action = "org.gnome.gconf.defaults.set-mandatory";
+ udata = g_new0 (UnsetData, 1);
+ udata->mechanism = g_object_ref (mechanism);
+ udata->context = context;
+ udata->includes = g_strdupv ((gchar **)includes);
+ udata->excludes = g_strdupv ((gchar **)excludes);
+
+ adata = g_new0 (ActionData, 1);
+ adata->mechanism = g_object_ref (mechanism);
+ adata->context = context;
+ adata->includes = g_strdupv ((gchar **)includes);
+ adata->auth_obtained_callback = do_unset_authorized;
+ adata->data = udata;
+ adata->destroy = unset_data_free;
+
+ adata->annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
+ adata->default_action = "org.gnome.gconf.defaults.set-mandatory";
+
+ polkit_authority_enumerate_actions (mechanism->priv->auth,
+ NULL,
+ actions_ready_cb,
+ adata);
+}
- for (i = 0; includes[i]; i++) {
- action = polkit_action_for_gconf_path (mechanism, annotation_key, includes[i]);
- if (action == NULL)
- action = default_action;
+static void
+check_authorization_only_callback (PolkitAuthority *authority,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CheckAuthData *data = user_data;
+ PolkitAuthorizationResult *result;
+ GError *error;
+ gboolean is_authorized;
- if (!check_polkit_for_action (mechanism, context, action))
- goto out;
- }
+ is_authorized = FALSE;
error = NULL;
- unset_in_db (mechanism, "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory",
- includes, excludes, &error);
-
- if (error) {
- error2 = g_error_new_literal (GCONF_DEFAULTS_ERROR,
- GCONF_DEFAULTS_ERROR_GENERAL,
- error->message);
+ result = polkit_authority_check_authorization_finish (authority,
+ res,
+ &error);
+ if (error != NULL) {
+ g_debug ("error checking action '%s'\n", error->message);
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+ "Not Authorized: %s", error->message);
g_error_free (error);
+ goto out;
+ }
+ else {
+ if (polkit_authorization_result_get_is_authorized (result)) {
+ g_debug ("result for '%s': authorized\n",
+ data->actions[data->id]);
+ is_authorized = TRUE;
+ }
+ else if (polkit_authorization_result_get_is_challenge (result)) {
+ g_debug ("result for '%s': challenge\n",
+ data->actions[data->id]);
+ is_authorized = TRUE;
+ }
+ else {
+ g_debug ("result for '%s': not authorized\n",
+ data->actions[data->id]);
+ is_authorized = FALSE;
+ }
+ }
- dbus_g_method_return_error (context, error2);
- g_error_free (error2);
+ if (is_authorized) {
+ data->id++;
+ if (data->actions[data->id] == NULL) {
+ g_debug ("return TRUE\n");
+ dbus_g_method_return (data->context, TRUE);
+ }
+ else {
+ check_next_action (data);
+ return; /* continue operation */
+ }
}
- else
- dbus_g_method_return (context);
+ else {
+ g_debug ("return FALSE\n");
+ dbus_g_method_return (data->context, FALSE);
+ }
+
out:
- start_killtimer();
+ check_auth_data_free (data);
+ g_object_unref (result);
+ stop_operation ();
+}
+
+static void
+check_permissions_only (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gchar **actions,
+ AuthObtainedCallback auth_obtained_callback,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ CheckAuthData *data;
+
+ data = g_new0 (CheckAuthData, 1);
+ data->mechanism = g_object_ref (mechanism);
+ data->context = context;
+ data->actions = actions;
+ data->flags = 0;
+ data->id = 0;
+ data->check_auth_callback = (GAsyncReadyCallback)check_authorization_only_callback;
+ data->auth_obtained_callback = NULL;
+ data->user_data = NULL;
+ data->destroy = NULL;
+ data->subject = polkit_system_bus_name_new (dbus_g_method_get_sender (context));
+
+ check_next_action (data);
+}
+
+static void
+do_check (GConfDefaults *mechanism,
+ gboolean mandatory,
+ const gchar **includes,
+ DBusGMethodInvocation *context)
+{
+ ActionData *adata;
+
+ start_operation ();
+
+ adata = g_new0 (ActionData, 1);
+ adata->mechanism = g_object_ref (mechanism);
+ adata->context = context;
+ adata->includes = g_strdupv ((gchar **)includes);
+ adata->actions_ready_callback = check_permissions_only;
+ adata->auth_obtained_callback = NULL;
+ adata->data = NULL;
+ adata->destroy = NULL;
+
+ if (mandatory) {
+ adata->annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
+ adata->default_action = "org.gnome.gconf.defaults.set-mandatory";
+ }
+ else {
+ adata->annotation_key = "org.gnome.gconf.defaults.set-system.prefix";
+ adata->default_action = "org.gnome.gconf.defaults.set-system";
+ }
+
+ polkit_authority_enumerate_actions (mechanism->priv->auth,
+ NULL,
+ actions_ready_cb,
+ adata);
+}
+
+void
+gconf_defaults_can_set_system (GConfDefaults *mechanism,
+ const char **includes,
+ DBusGMethodInvocation *context)
+{
+ do_check (mechanism, FALSE, includes, context);
}
+
+void
+gconf_defaults_can_set_mandatory (GConfDefaults *mechanism,
+ const char **includes,
+ DBusGMethodInvocation *context)
+{
+ do_check (mechanism, TRUE, includes, context);
+}
+
diff -u -r GConf-2.26.0/defaults/gconf-defaults.h hacked/defaults/gconf-defaults.h
--- GConf-2.26.0/defaults/gconf-defaults.h 2008-12-02 11:06:14.000000000 -0500
+++ hacked/defaults/gconf-defaults.h 2009-05-12 13:27:54.300540238 -0400
@@ -83,6 +83,14 @@
const char **excludes,
DBusGMethodInvocation *context);
+void gconf_defaults_can_set_system (GConfDefaults *mechanism,
+ const char **includes,
+ DBusGMethodInvocation *context);
+
+void gconf_defaults_can_set_mandatory (GConfDefaults *mechanism,
+ const char **includes,
+ DBusGMethodInvocation *context);
+
G_END_DECLS
#endif /* GCONF_DEFAULTS_H */
diff -u -r GConf-2.26.0/defaults/gconf-defaults-main.c hacked/defaults/gconf-defaults-main.c
--- GConf-2.26.0/defaults/gconf-defaults-main.c 2008-12-02 11:06:14.000000000 -0500
+++ hacked/defaults/gconf-defaults-main.c 2009-05-12 13:37:59.046345548 -0400
@@ -122,6 +122,29 @@
return bus;
}
+extern gboolean disable_killtimer;
+gboolean debug = FALSE;
+
+GOptionEntry entries [] = {
+ { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, "Emit debug output", NULL },
+ { "no-kill", 0, 0, G_OPTION_ARG_NONE, &disable_killtimer, "Don't exit when idle", NULL },
+ { NULL, }
+};
+
+static gint log_levels = (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
+
+void
+log_default_handler (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer unused_data)
+{
+ if ((log_level & log_levels) != 0) {
+ g_log_default_handler (log_domain, log_level, message, unused_data);
+ }
+}
+
+
int
main (int argc, char **argv)
{
@@ -130,6 +153,8 @@
DBusGProxy *bus_proxy;
DBusGConnection *connection;
int ret;
+ GOptionContext *options;
+ GError *error = NULL;
ret = 1;
@@ -139,8 +164,22 @@
dbus_g_thread_init ();
g_type_init ();
+ options = g_option_context_new (NULL);
+ g_option_context_add_main_entries (options, entries, NULL);
+ if (!g_option_context_parse (options, &argc, &argv, &error)) {
+ g_warning ("Failed to parse options: %s\n", error->message);
+ g_error_free (error);
+ }
+ g_option_context_free (options);
+
+ g_log_set_default_handler (log_default_handler, NULL);
+ if (debug) {
+ log_levels = log_levels | G_LOG_LEVEL_DEBUG;
+ }
+
connection = get_system_bus ();
if (connection == NULL) {
+ g_warning ("Could not get system bus connection; bailing out");
goto out;
}
diff -u -r GConf-2.26.0/defaults/gconf-defaults.xml hacked/defaults/gconf-defaults.xml
--- GConf-2.26.0/defaults/gconf-defaults.xml 2008-12-02 11:06:14.000000000 -0500
+++ hacked/defaults/gconf-defaults.xml 2009-05-12 13:18:12.873380233 -0400
@@ -2,12 +2,12 @@
<node name="/">
<interface name="org.gnome.GConf.Defaults">
<!--
- includes: an array of GConf paths to copy from the
+ includes: an array of GConf paths to copy from the
callers GConf database to the system database
excludes: an array of GConf paths to omit
- Copies values from the callers GConf database to the system-wide
- database. The subtree below each included path is copied recursively,
+ Copies values from the callers GConf database to the system-wide
+ database. The subtree below each included path is copied recursively,
skipping the excluded subtrees.
To decide which PolicyKit privilege to require for the copying of
each path in includes, the mechanism looks for a privilege with an
@@ -21,16 +21,22 @@
<arg name="excludes" direction="in" type="as"/>
</method>
+ <method name="CanSetSystem">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="includes" direction="in" type="as"/>
+ <arg name="result" direction="out" type="b"/>
+ </method>
+
<signal name="SystemSet">
<arg name="keys" type="as"/>
</signal>
<!--
- includes: an array of GConf paths to copy from the
+ includes: an array of GConf paths to copy from the
callers GConf database to the mandatory database
excludes: an array of GConf paths to omit
- Copies values from the callers GConf database to the system-wide
- mandatory database. The subtree below each included path is copied
+ Copies values from the callers GConf database to the system-wide
+ mandatory database. The subtree below each included path is copied
recursively, skipping the excluded subtrees.
To decide which PolicyKit privilege to require for the copying of
each path in includes, the mechanism looks for a privilege with an
@@ -41,12 +47,12 @@
<method name="SetMandatory">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="includes" direction="in" type="as"/>
- <arg name="excludes" direction="in" type="as"/>
+ <arg name="result" direction="out" type="b"/>
</method>
<!--
Unsets keys in the system-wide mandatory GConf database, making the
- keys writable again. The subtree below each included path is copied
+ keys writable again. The subtree below each included path is copied
recursively, skipping the excluded subtrees.
To decide which PolicyKit privilege to require for the copying of
each path in includes, the mechanism looks for a privilege with an
@@ -59,6 +65,12 @@
<arg name="includes" direction="in" type="as"/>
<arg name="excludes" direction="in" type="as"/>
</method>
-
+
+ <method name="CanSetMandatory">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="includes" direction="in" type="as"/>
+ <arg name="result" direction="out" type="b"/>
+ </method>
+
</interface>
</node>
diff -u -r GConf-2.26.0/defaults/Makefile.am hacked/defaults/Makefile.am
--- GConf-2.26.0/defaults/Makefile.am 2009-02-16 13:17:44.000000000 -0500
+++ hacked/defaults/Makefile.am 2009-05-11 22:12:16.773368001 -0400
@@ -20,13 +20,13 @@
gconf_defaults_mechanism_LDADD = \
$(top_builddir)/gconf/libgconf-2.la \
- $(DEFAULTS_LIBS)
+ $(DEFAULTS_LIBS)
BUILT_SOURCES = gconf-defaults-glue.h
dbus_servicesdir = $(datadir)/dbus-1/system-services
dbus_confdir = $(sysconfdir)/dbus-1/system.d
-polkitdir = $(datadir)/PolicyKit/policy
+polkitdir = $(datadir)/polkit-1/actions
dbus_services_in_files = org.gnome.GConf.Defaults.service.in
polkit_in_files = org.gnome.gconf.defaults.policy.in
@@ -41,9 +41,6 @@
@INTLTOOL_POLICY_RULE@
polkit_DATA = $(polkit_in_files:.policy.in=.policy)
-check:
- $(POLKIT_POLICY_FILE_VALIDATE) $(polkit_DATA)
-
EXTRA_DIST = \
$(dbus_services_in_files) \
org.gnome.GConf.Defaults.conf \