diff -up GConf-2.26.2/configure.in.polkit1 GConf-2.26.2/configure.in --- GConf-2.26.2/configure.in.polkit1 2009-05-14 11:18:34.000000000 -0400 +++ GConf-2.26.2/configure.in 2009-06-12 13:00:27.978836073 -0400 @@ -181,7 +181,7 @@ AC_ARG_ENABLE(defaults_service, , 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) + PKG_CHECK_MODULES(DEFAULTS, glib-2.0 gobject-2.0 dbus-1 dbus-glib-1 polkit-gobject-1, HAVE_POLKIT=yes) if test "x$HAVE_POLKIT" = "xno"; then if test "x$enable_defaults_service" = "xyes" ; then AC_MSG_ERROR([[ @@ -194,13 +194,6 @@ fi 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 -up GConf-2.26.2/defaults/gconf-defaults.c.polkit1 GConf-2.26.2/defaults/gconf-defaults.c --- GConf-2.26.2/defaults/gconf-defaults.c.polkit1 2009-05-14 11:13:40.000000000 -0400 +++ GConf-2.26.2/defaults/gconf-defaults.c 2009-06-12 14:21:50.117398713 -0400 @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * - * Copyright (C) 2008 Matthias Clasen + * Copyright (C) 2008, 2009 Matthias Clasen * * 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 #include -#include #include #define GCONF_ENABLE_INTERNALS @@ -56,10 +55,14 @@ do_exit (gpointer user_data) } 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 @@ stop_killtimer (void) 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 @@ GType gconf_defaults_error_get_type (void) { static GType etype = 0; - + if (etype == 0) { static const GEnumValue values[] = @@ -114,12 +140,12 @@ gconf_defaults_error_get_type (void) 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 @@ gconf_defaults_finalize (GObject *object 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 @@ register_mechanism (GConfDefaults *mecha 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 @@ gconf_defaults_new (void) 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,160 @@ polkit_action_for_gconf_path (GConfDefau 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; + gboolean challenge; +} 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)); + data->challenge = FALSE; + + check_next_action (data); } static char * @@ -398,11 +494,11 @@ gconf_address_for_caller (GConfDefaults 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 +530,13 @@ copy_tree (GConfClient *src, 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 +557,7 @@ copy_entry (GConfClient *src, { GConfValue *value; - if (path_is_excluded (path, excludes)) + if (path_is_excluded (path, excludes)) return; value = gconf_client_get (src, path, NULL); @@ -471,69 +567,66 @@ copy_entry (GConfClient *src, } } +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 +635,175 @@ do_copy (GConfDefaults *mechani 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 +817,13 @@ append_key (GConfChangeSet *cs, 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 +831,15 @@ gconf_defaults_set_system (GConfDefaults 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 +848,7 @@ gconf_defaults_set_mandatory (GConfDefau 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 +860,13 @@ unset_tree (GConfClient *dest, 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 +878,25 @@ unset_tree (GConfClient *dest, 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 +904,7 @@ unset_in_db (GConfDefaults *mechanism, int i; engine = gconf_engine_get_local (address, error); - if (*error) + if (*error) goto out; dest = gconf_client_get_for_engine (engine); @@ -706,48 +930,224 @@ out: 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; + data->challenge = 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) { + gint result; + + result = data->challenge ? 1 : 2; + g_debug ("return %d\n", result); + dbus_g_method_return (data->context, result); + } + else { + check_next_action (data); + return; /* continue operation */ + } } - else - dbus_g_method_return (context); + else { + g_debug ("return 0\n"); + dbus_g_method_return (data->context, 0); + } + 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)); + data->challenge = FALSE; + + 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 -up GConf-2.26.2/defaults/gconf-defaults.h.polkit1 GConf-2.26.2/defaults/gconf-defaults.h --- GConf-2.26.2/defaults/gconf-defaults.h.polkit1 2009-05-14 11:13:40.000000000 -0400 +++ GConf-2.26.2/defaults/gconf-defaults.h 2009-06-12 13:00:27.984836059 -0400 @@ -83,6 +83,14 @@ void gconf_defaults_unset_mand 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 -up GConf-2.26.2/defaults/gconf-defaults-main.c.polkit1 GConf-2.26.2/defaults/gconf-defaults-main.c --- GConf-2.26.2/defaults/gconf-defaults-main.c.polkit1 2009-05-05 20:37:32.000000000 -0400 +++ GConf-2.26.2/defaults/gconf-defaults-main.c 2009-06-12 13:00:27.987836052 -0400 @@ -122,6 +122,29 @@ get_system_bus (void) 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 @@ main (int argc, char **argv) DBusGProxy *bus_proxy; DBusGConnection *connection; int ret; + GOptionContext *options; + GError *error = NULL; ret = 1; @@ -139,8 +164,22 @@ main (int argc, char **argv) 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 -up GConf-2.26.2/defaults/gconf-defaults.xml.polkit1 GConf-2.26.2/defaults/gconf-defaults.xml --- GConf-2.26.2/defaults/gconf-defaults.xml.polkit1 2009-05-14 11:13:40.000000000 -0400 +++ GConf-2.26.2/defaults/gconf-defaults.xml 2009-06-12 14:21:43.646401662 -0400 @@ -2,12 +2,12 @@