From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1RuLkx-0000nL-7w for garchives@archives.gentoo.org; Mon, 06 Feb 2012 10:25:07 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id CF3FCE05B4; Mon, 6 Feb 2012 10:24:57 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id 7A40BE05B4 for ; Mon, 6 Feb 2012 10:24:57 +0000 (UTC) Received: from pelican.gentoo.org (unknown [66.219.59.40]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id C86F31B4051 for ; Mon, 6 Feb 2012 10:24:56 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by pelican.gentoo.org (Postfix) with ESMTP id EE64880043 for ; Mon, 6 Feb 2012 10:24:55 +0000 (UTC) From: "Alexandre Restovtsev" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Alexandre Restovtsev" Message-ID: <52f4dc6163ecbc334f9ba949d6436f650ecf138d.tetromino@gentoo> Subject: [gentoo-commits] proj/openrc-settingsd:master commit in: src/ X-VCS-Repository: proj/openrc-settingsd X-VCS-Files: src/bus-utils.c src/bus-utils.h src/hostnamed.c X-VCS-Directories: src/ X-VCS-Committer: tetromino X-VCS-Committer-Name: Alexandre Restovtsev X-VCS-Revision: 52f4dc6163ecbc334f9ba949d6436f650ecf138d Date: Mon, 6 Feb 2012 10:24:55 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: d6e2fb98-9a0b-4372-b9f7-96564353bd76 X-Archives-Hash: 11c33179bb2b4f246310a4d064678cee commit: 52f4dc6163ecbc334f9ba949d6436f650ecf138d Author: Alexandre Rostovtsev gentoo org> AuthorDate: Mon Feb 6 10:19:08 2012 +0000 Commit: Alexandre Restovtsev gmail com> CommitDate: Mon Feb 6 10:19:08 2012 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/openrc-settin= gsd.git;a=3Dcommit;h=3D52f4dc61 Check polkit authorization asynchronously The other alternative (spawning a thread for each authorization request) seems less elegant, since such requests can take arbitrarily long to complete. --- src/bus-utils.c | 137 +++++++++++++++++++++------- src/bus-utils.h | 13 ++- src/hostnamed.c | 275 ++++++++++++++++++++++++++++++++++++++-----------= ------ 3 files changed, 302 insertions(+), 123 deletions(-) diff --git a/src/bus-utils.c b/src/bus-utils.c index d3bc7b2..aef8037 100644 --- a/src/bus-utils.c +++ b/src/bus-utils.c @@ -20,44 +20,115 @@ #include #include =20 +#include "bus-utils.h" + +struct check_polkit_data { + const gchar *unique_name; + const gchar *action_id; + gboolean user_interaction; + GAsyncReadyCallback callback; + gpointer user_data; + + PolkitAuthority *authority; + PolkitSubject *subject; +}; + +void +check_polkit_data_free (struct check_polkit_data *data) +{ + if (data =3D=3D NULL) + return; + + if (data->subject !=3D NULL) + g_object_unref (data->subject); + if (data->authority !=3D NULL) + g_object_unref (data->authority); + =20 + g_free (data); +} + gboolean -check_polkit (const gchar *unique_name, - const gchar *action_id, - const gboolean user_interaction, - GError **error) +check_polkit_finish (GAsyncResult *res, + GError **error) { - gboolean ret =3D FALSE; - GDBusConnection *connection =3D NULL; - PolkitAuthority *authority =3D NULL; - PolkitSubject *subject =3D NULL; - PolkitAuthorizationResult *result =3D NULL; - - if ((authority =3D polkit_authority_get_sync (NULL, error)) =3D=3D N= ULL) - goto end; - - if (unique_name =3D=3D NULL || action_id =3D=3D NULL ||=20 - (subject =3D polkit_system_bus_name_new (unique_name)) =3D=3D NU= LL) { - g_propagate_error (error, - g_error_new (POLKIT_ERROR, POLKIT_ERROR_FAILED, - "Authorizing for '%s': failed sanity che= ck", action_id)); - goto end; - } + GSimpleAsyncResult *simple; + + simple =3D G_SIMPLE_ASYNC_RESULT (res); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + + return g_simple_async_result_get_op_res_gboolean (simple); +} + +static void +check_polkit_authorization_cb (GObject *source_object, + GAsyncResult *res, + gpointer _data) +{ + struct check_polkit_data *data; + PolkitAuthorizationResult *result; + GSimpleAsyncResult *simple; + GError *err =3D NULL; =20 - if ((result =3D polkit_authority_check_authorization_sync (authority= , subject, action_id, NULL, (PolkitCheckAuthorizationFlags) user_interact= ion, NULL, error)) =3D=3D NULL) - goto end; + data =3D (struct check_polkit_data *) _data; + if ((result =3D polkit_authority_check_authorization_finish (data->a= uthority, res, &err)) =3D=3D NULL) { + g_simple_async_report_take_gerror_in_idle (NULL, data->callback,= data->user_data, err); + goto out; + } =20 - if ((ret =3D polkit_authorization_result_get_is_authorized (result))= =3D=3D FALSE) { - g_propagate_error (error, - g_error_new (POLKIT_ERROR, POLKIT_ERROR_NOT_AUTHORIZ= ED, - "Authorizing for '%s': not authorized", = action_id)); + if (!polkit_authorization_result_get_is_authorized (result)) { + g_simple_async_report_error_in_idle (NULL, data->callback, data-= >user_data, POLKIT_ERROR, POLKIT_ERROR_NOT_AUTHORIZED, "Authorizing for '= %s': not authorized", data->action_id); + goto out; } - =20 - end: + simple =3D g_simple_async_result_new (NULL, data->callback, data->us= er_data, check_polkit_async); + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + + out: + check_polkit_data_free (data); if (result !=3D NULL) g_object_unref (result); - if (subject !=3D NULL) - g_object_unref (subject); - if (authority !=3D NULL) - g_object_unref (authority); - return ret; +} + +static void +check_polkit_authority_cb (GObject *source_object, + GAsyncResult *res, + gpointer _data) +{ + struct check_polkit_data *data; + GError *err =3D NULL; + + data =3D (struct check_polkit_data *) _data; + if ((data->authority =3D polkit_authority_get_finish (res, &err)) =3D= =3D NULL) { + g_simple_async_report_take_gerror_in_idle (NULL, data->callback,= data->user_data, err); + check_polkit_data_free (data); + return; + } + if (data->unique_name =3D=3D NULL || data->action_id =3D=3D NULL ||=20 + (data->subject =3D polkit_system_bus_name_new (data->unique_name= )) =3D=3D NULL) { + g_simple_async_report_error_in_idle (NULL, data->callback, data-= >user_data, POLKIT_ERROR, POLKIT_ERROR_FAILED, "Authorizing for '%s': fai= led sanity check", data->action_id); + check_polkit_data_free (data); + return; + } + polkit_authority_check_authorization (data->authority, data->subject= , data->action_id, NULL, (PolkitCheckAuthorizationFlags) data->user_inter= action, NULL, check_polkit_authorization_cb, data); +} + +void +check_polkit_async (const gchar *unique_name, + const gchar *action_id, + const gboolean user_interaction, + GAsyncReadyCallback callback, + gpointer user_data) +{ + struct check_polkit_data *data; + + data =3D g_new0 (struct check_polkit_data, 1); + data->unique_name =3D unique_name; + data->action_id =3D action_id; + data->user_interaction =3D user_interaction; + data->callback =3D callback; + data->user_data =3D user_data; + + polkit_authority_get_async (NULL, check_polkit_authority_cb, data); } \ No newline at end of file diff --git a/src/bus-utils.h b/src/bus-utils.h index 31a2ef1..f2e80ea 100644 --- a/src/bus-utils.h +++ b/src/bus-utils.h @@ -21,10 +21,15 @@ =20 #include =20 +void +check_polkit_async (const gchar *unique_name, + const gchar *action_id, + const gboolean user_interaction, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean -check_polkit (const gchar *unique_name, - const gchar *action_id, - const gboolean user_interaction, - GError **error); +check_polkit_finish (GAsyncResult *res, + GError **error); =20 #endif \ No newline at end of file diff --git a/src/hostnamed.c b/src/hostnamed.c index 4f95d04..c5914bd 100644 --- a/src/hostnamed.c +++ b/src/hostnamed.c @@ -36,6 +36,11 @@ #define QUOTE(macro) #macro #define STR(macro) QUOTE(macro) =20 +struct invoked_name { + GDBusMethodInvocation *invocation; + gchar *name; /* newly allocated */ +}; + guint bus_id =3D 0; gboolean read_only =3D FALSE; =20 @@ -103,152 +108,250 @@ guess_icon_name () icon_name =3D g_strdup ("computer"); } =20 -static gboolean -on_handle_set_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1, - GDBusMethodInvocation *invocation, - const gchar *name, - const gboolean user_interaction, - gpointer user_data) +static void +on_handle_set_hostname_authorized_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { GError *err =3D NULL; - - if (read_only) { - g_dbus_method_invocation_return_dbus_error (invocation, - DBUS_ERROR_NOT_SUPPO= RTED, - "openrc-settingsd ho= stnamed is in read-only mode"); - goto end; - } - - if (!check_polkit (g_dbus_method_invocation_get_sender (invocation),= "org.freedesktop.hostname1.set-hostname", user_interaction, &err)) { - g_dbus_method_invocation_return_gerror (invocation, err); - goto end; + struct invoked_name *data; + =20 + data =3D (struct invoked_name *) user_data; + if (!check_polkit_finish (res, &err)) { + g_dbus_method_invocation_return_gerror (data->invocation, err); + goto out; } =20 G_LOCK (hostname); /* Don't allow an empty or invalid hostname */ - if (!hostname_is_valid (name)) { - name =3D hostname; - if (!hostname_is_valid (name)) - name =3D "localhost"; + if (!hostname_is_valid (data->name)) { + if (data->name !=3D NULL) + g_free (data->name); + + if (hostname_is_valid (hostname)) + data->name =3D g_strdup (hostname); + else + data->name =3D g_strdup ("localhost"); } - if (sethostname (name, strlen(name))) { + if (sethostname (data->name, strlen(data->name))) { int errsv =3D errno; - g_dbus_method_invocation_return_dbus_error (invocation, + g_dbus_method_invocation_return_dbus_error (data->invocation, DBUS_ERROR_FAILED, strerror (errsv)); G_UNLOCK (hostname); - goto end; + goto out; } - g_strlcpy (hostname, name, HOST_NAME_MAX + 1); - openrc_settingsd_hostnamed_hostname1_complete_set_hostname (hostname= 1, invocation); + g_strlcpy (hostname, data->name, HOST_NAME_MAX + 1); + openrc_settingsd_hostnamed_hostname1_complete_set_hostname (hostname= 1, data->invocation); openrc_settingsd_hostnamed_hostname1_set_hostname (hostname1, hostna= me); G_UNLOCK (hostname); =20 - end: - return TRUE; + out: + g_free (data->name); + g_free (data); + if (err !=3D NULL) + g_error_free (err); } =20 static gboolean -on_handle_set_static_hostname (OpenrcSettingsdHostnamedHostname1 *hostna= me1, - GDBusMethodInvocation *invocation, - const gchar *name, - const gboolean user_interaction, - gpointer user_data) +on_handle_set_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1, + GDBusMethodInvocation *invocation, + const gchar *name, + const gboolean user_interaction, + gpointer user_data) { - ShellUtilsTrivial *confd_file =3D NULL; - GError *err =3D NULL; - - if (read_only) { + if (read_only) g_dbus_method_invocation_return_dbus_error (invocation, DBUS_ERROR_NOT_SUPPO= RTED, "openrc-settingsd ho= stnamed is in read-only mode"); - goto end; + else { + struct invoked_name *data; + data =3D g_new0 (struct invoked_name, 1); + data->invocation =3D invocation; + data->name =3D g_strdup (name); + check_polkit_async (g_dbus_method_invocation_get_sender (invocat= ion), "org.freedesktop.hostname1.set-hostname", user_interaction, on_hand= le_set_hostname_authorized_cb, data); } =20 - if (!check_polkit (g_dbus_method_invocation_get_sender (invocation),= "org.freedesktop.hostname1.set-static-hostname", user_interaction, &err)= ) { - g_dbus_method_invocation_return_gerror (invocation, err); - goto end; + return TRUE; +} + +static void +on_handle_set_static_hostname_authorized_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *err =3D NULL; + struct invoked_name *data; + =20 + data =3D (struct invoked_name *) user_data; + if (!check_polkit_finish (res, &err)) { + g_dbus_method_invocation_return_gerror (data->invocation, err); + goto out; } =20 G_LOCK (static_hostname); /* Don't allow an empty or invalid hostname */ - if (!hostname_is_valid (name)) - name =3D "localhost"; + if (!hostname_is_valid (data->name)) { + if (data->name !=3D NULL) + g_free (data->name); + + data->name =3D g_strdup ("localhost"); + } =20 - if (!shell_utils_trivial_set_and_save (static_hostname_file, &err, "= hostname", "HOSTNAME", name, NULL)) { - g_dbus_method_invocation_return_gerror (invocation, err); + if (!shell_utils_trivial_set_and_save (static_hostname_file, &err, "= hostname", "HOSTNAME", data->name, NULL)) { + g_dbus_method_invocation_return_gerror (data->invocation, err); G_UNLOCK (static_hostname); - goto end; + goto out; } =20 g_free (static_hostname); - static_hostname =3D g_strdup (name); - openrc_settingsd_hostnamed_hostname1_complete_set_static_hostname (h= ostname1, invocation); + static_hostname =3D data->name; /* data->name is g_strdup-ed already= */; + openrc_settingsd_hostnamed_hostname1_complete_set_static_hostname (h= ostname1, data->invocation); openrc_settingsd_hostnamed_hostname1_set_static_hostname (hostname1,= static_hostname); G_UNLOCK (static_hostname); =20 - end: - shell_utils_trivial_free (confd_file); + out: + g_free (data); if (err !=3D NULL) g_error_free (err); +} + +static gboolean +on_handle_set_static_hostname (OpenrcSettingsdHostnamedHostname1 *hostna= me1, + GDBusMethodInvocation *invocation, + const gchar *name, + const gboolean user_interaction, + gpointer user_data) +{ + if (read_only) + g_dbus_method_invocation_return_dbus_error (invocation, + DBUS_ERROR_NOT_SUPPO= RTED, + "openrc-settingsd ho= stnamed is in read-only mode"); + else { + struct invoked_name *data; + data =3D g_new0 (struct invoked_name, 1); + data->invocation =3D invocation; + data->name =3D g_strdup (name); + check_polkit_async (g_dbus_method_invocation_get_sender (invocat= ion), "org.freedesktop.hostname1.set-static-hostname", user_interaction, = on_handle_set_static_hostname_authorized_cb, data); + } =20 return TRUE; /* Always return TRUE to indicate signal has been handl= ed */ } =20 -static gboolean -on_handle_set_machine_info (OpenrcSettingsdHostnamedHostname1 *hostname1= , - GDBusMethodInvocation *invocation, - const gchar *name, - const gboolean user_interaction, - gpointer user_data) +static void +on_handle_set_pretty_hostname_authorized_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - ShellUtilsTrivial *confd_file =3D NULL; GError *err =3D NULL; - gboolean is_pretty_hostname =3D GPOINTER_TO_INT(user_data); + struct invoked_name *data; + =20 + data =3D (struct invoked_name *) user_data; + if (!check_polkit_finish (res, &err)) { + g_dbus_method_invocation_return_gerror (data->invocation, err); + goto out; + } + + G_LOCK (machine_info); + /* Don't allow a null pretty hostname */ + if (data->name =3D=3D NULL) + data->name =3D g_strdup (""); =20 - if (read_only) { + if (!shell_utils_trivial_set_and_save (machine_info_file, &err, "PRE= TTY_HOSTNAME", NULL, data->name, NULL)) { + g_dbus_method_invocation_return_gerror (data->invocation, err); + G_UNLOCK (machine_info); + goto out; + } + + g_free (pretty_hostname); + pretty_hostname =3D data->name; /* data->name is g_strdup-ed already= */ + openrc_settingsd_hostnamed_hostname1_complete_set_pretty_hostname (h= ostname1, data->invocation); + openrc_settingsd_hostnamed_hostname1_set_pretty_hostname (hostname1,= pretty_hostname); + G_UNLOCK (machine_info); + + out: + g_free (data); + if (err !=3D NULL) + g_error_free (err); +} + +static gboolean +on_handle_set_pretty_hostname (OpenrcSettingsdHostnamedHostname1 *hostna= me1, + GDBusMethodInvocation *invocation, + const gchar *name, + const gboolean user_interaction, + gpointer user_data) +{ + if (read_only) g_dbus_method_invocation_return_dbus_error (invocation, DBUS_ERROR_NOT_SUPPO= RTED, "openrc-settingsd ho= stnamed is in read-only mode"); - goto end; + else { + struct invoked_name *data; + data =3D g_new0 (struct invoked_name, 1); + data->invocation =3D invocation; + data->name =3D g_strdup (name); + check_polkit_async (g_dbus_method_invocation_get_sender (invocat= ion), "org.freedesktop.hostname1.set-machine-info", user_interaction, on_= handle_set_pretty_hostname_authorized_cb, data); } =20 - if (!check_polkit (g_dbus_method_invocation_get_sender (invocation),= "org.freedesktop.hostname1.set-machine-info", user_interaction, &err)) { - g_dbus_method_invocation_return_gerror (invocation, err); - goto end; + return TRUE; /* Always return TRUE to indicate signal has been handl= ed */ +} + +static void +on_handle_set_icon_name_authorized_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *err =3D NULL; + struct invoked_name *data; + =20 + data =3D (struct invoked_name *) user_data; + if (!check_polkit_finish (res, &err)) { + g_dbus_method_invocation_return_gerror (data->invocation, err); + goto out; } =20 G_LOCK (machine_info); /* Don't allow a null pretty hostname */ - if (name =3D=3D NULL) - name =3D ""; + if (data->name =3D=3D NULL) + data->name =3D g_strdup (""); =20 - if ((is_pretty_hostname && - !shell_utils_trivial_set_and_save (machine_info_file, &err, = "PRETTY_HOSTNAME", NULL, name, NULL)) || - (!is_pretty_hostname && - !shell_utils_trivial_set_and_save (machine_info_file, &err, = "ICON_NAME", NULL, name, NULL))) { - g_dbus_method_invocation_return_gerror (invocation, err); + if (!shell_utils_trivial_set_and_save (machine_info_file, &err, "ICO= N_NAME", NULL, data->name, NULL)) { + g_dbus_method_invocation_return_gerror (data->invocation, err); G_UNLOCK (machine_info); - goto end; + goto out; } =20 - if (is_pretty_hostname) { - g_free (pretty_hostname); - pretty_hostname =3D g_strdup (name); - openrc_settingsd_hostnamed_hostname1_complete_set_pretty_hostnam= e (hostname1, invocation); - openrc_settingsd_hostnamed_hostname1_set_pretty_hostname (hostna= me1, pretty_hostname); - } else { - g_free (icon_name); - icon_name =3D g_strdup (name); - openrc_settingsd_hostnamed_hostname1_complete_set_icon_name (hos= tname1, invocation); - openrc_settingsd_hostnamed_hostname1_set_icon_name (hostname1, i= con_name); - } + g_free (icon_name); + icon_name =3D data->name; /* data->name is g_strdup-ed already */ + openrc_settingsd_hostnamed_hostname1_complete_set_icon_name (hostnam= e1, data->invocation); + openrc_settingsd_hostnamed_hostname1_set_icon_name (hostname1, icon_= name); G_UNLOCK (machine_info); =20 - end: - shell_utils_trivial_free (confd_file); + out: + g_free (data); if (err !=3D NULL) g_error_free (err); +} + +static gboolean +on_handle_set_icon_name (OpenrcSettingsdHostnamedHostname1 *hostname1, + GDBusMethodInvocation *invocation, + const gchar *name, + const gboolean user_interaction, + gpointer user_data) +{ + if (read_only) + g_dbus_method_invocation_return_dbus_error (invocation, + DBUS_ERROR_NOT_SUPPO= RTED, + "openrc-settingsd ho= stnamed is in read-only mode"); + else { + struct invoked_name *data; + data =3D g_new0 (struct invoked_name, 1); + data->invocation =3D invocation; + data->name =3D g_strdup (name); + check_polkit_async (g_dbus_method_invocation_get_sender (invocat= ion), "org.freedesktop.hostname1.set-machine-info", user_interaction, on_= handle_set_icon_name_authorized_cb, data); + } =20 return TRUE; /* Always return TRUE to indicate signal has been handl= ed */ } @@ -272,8 +375,8 @@ on_bus_acquired (GDBusConnection *connection, =20 g_signal_connect (hostname1, "handle-set-hostname", G_CALLBACK (on_h= andle_set_hostname), NULL); g_signal_connect (hostname1, "handle-set-static-hostname", G_CALLBAC= K (on_handle_set_static_hostname), NULL); - g_signal_connect (hostname1, "handle-set-pretty-hostname", G_CALLBAC= K (on_handle_set_machine_info), GINT_TO_POINTER(TRUE)); - g_signal_connect (hostname1, "handle-set-icon-name", G_CALLBACK (on_= handle_set_machine_info), GINT_TO_POINTER(FALSE)); + g_signal_connect (hostname1, "handle-set-pretty-hostname", G_CALLBAC= K (on_handle_set_pretty_hostname), NULL); + g_signal_connect (hostname1, "handle-set-icon-name", G_CALLBACK (on_= handle_set_icon_name), NULL); =20 if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (ho= stname1), connection,