diff options
author | David Zeuthen <davidz@redhat.com> | 2009-02-08 14:22:45 -0500 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2009-02-08 14:22:45 -0500 |
commit | bc150368d95ef70b04af3bc9250c1bdfe950a048 (patch) | |
tree | b09e80b4ac2636f7c7f128fe20a9d741f43f12b3 | |
parent | 7b815725b03da8564f7bea835c8f05539e481adc (diff) | |
download | polkit-bc150368d95ef70b04af3bc9250c1bdfe950a048.tar.gz |
implement cancellation of authorization checks
Also add a short example to test this.
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | data/org.freedesktop.PolicyKit1.Authority.xml | 23 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/examples/Makefile.am | 32 | ||||
-rw-r--r-- | src/examples/cancel.c | 124 | ||||
-rw-r--r-- | src/polkit/polkitauthority.c | 75 | ||||
-rw-r--r-- | src/polkit/polkitauthority.h | 67 | ||||
-rw-r--r-- | src/polkit/polkiterror.h | 6 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendauthority.c | 93 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendlocalauthority.c | 44 | ||||
-rw-r--r-- | src/programs/polkit.c | 2 |
11 files changed, 384 insertions, 85 deletions
diff --git a/configure.ac b/configure.ac index 90642ce..d98a0bc 100644 --- a/configure.ac +++ b/configure.ac @@ -415,6 +415,7 @@ src/polkitbackend/Makefile src/polkitagent/Makefile src/polkitd/Makefile src/programs/Makefile +src/examples/Makefile docs/version.xml docs/Makefile docs/polkit/Makefile diff --git a/data/org.freedesktop.PolicyKit1.Authority.xml b/data/org.freedesktop.PolicyKit1.Authority.xml index 2057bd6..34a2b4b 100644 --- a/data/org.freedesktop.PolicyKit1.Authority.xml +++ b/data/org.freedesktop.PolicyKit1.Authority.xml @@ -153,12 +153,21 @@ <annotation name="org.gtk.EggDBus.ErrorDomain.Member" value="org.freedesktop.PolicyKit1.Error.Failed"> <annotation name="org.gtk.EggDBus.DocString" value="The operation failed."/> </annotation> + <annotation name="org.gtk.EggDBus.ErrorDomain.Member" value="org.freedesktop.PolicyKit1.Error.Cancelled"> + <annotation name="org.gtk.EggDBus.DocString" value="The operation was cancelled."/> + </annotation> <annotation name="org.gtk.EggDBus.ErrorDomain.Member" value="org.freedesktop.PolicyKit1.Error.NotSupported"> <annotation name="org.gtk.EggDBus.DocString" value="Operation is not supported."/> </annotation> <annotation name="org.gtk.EggDBus.ErrorDomain.Member" value="org.freedesktop.PolicyKit1.Error.NotAuthorized"> <annotation name="org.gtk.EggDBus.DocString" value="Not authorized to perform operation."/> </annotation> + + <!-- errors not exposed in GObject library follows here --> + <annotation name="org.gtk.EggDBus.ErrorDomain.Member" value="org.freedesktop.PolicyKit1.Error.CancellationIdNotUnique"> + <annotation name="org.gtk.EggDBus.ErrorDomain.Member.Value" value="1000"/> + <annotation name="org.gtk.EggDBus.DocString" value="The passed @cancellation_id is already in use."/> + </annotation> </annotation> <method name="EnumerateActions"> @@ -175,7 +184,7 @@ </method> <method name="CheckAuthorization"> - <annotation name="org.gtk.EggDBus.DocString" value="Checks if @subject is authorized to perform the action with identifier @action_id."/> + <annotation name="org.gtk.EggDBus.DocString" value="<para>Checks if @subject is authorized to perform the action with identifier @action_id.</para><para>If @cancellation_id is non-empty and already in use for the caller, the %org.freedesktop.PolicyKit1.Error.CancellationIdNotUnique error is returned.</para>"/> <arg name="subject" direction="in" type="(sa{sv})"> <annotation name="org.gtk.EggDBus.DocString" value="A #Subject struct."/> @@ -191,12 +200,24 @@ <annotation name="org.gtk.EggDBus.DocString" value="A set of #CheckAuthorizationFlags."/> </arg> + <arg name="cancellation_id" direction="in" type="s"> + <annotation name="org.gtk.EggDBus.DocString" value="A unique id used to cancel the the authentication check via org.freedesktop.PolicyKit1.Authority.CancelCheckAuthorization() or the empty string if cancellation is not needed."/> + </arg> + <arg name="result" direction="out" type="u"> <annotation name="org.gtk.EggDBus.Type" value="AuthorizationResult"/> <annotation name="org.gtk.EggDBus.DocString" value="A value from the #AuthorizationResult enumeration."/> </arg> </method> + <method name="CancelCheckAuthorization"> + <annotation name="org.gtk.EggDBus.DocString" value="Cancels an authorization check."/> + + <arg name="cancellation_id" direction="in" type="s"> + <annotation name="org.gtk.EggDBus.DocString" value="The @cancellation_id passed to org.freedesktop.PolicyKit1.Authority.CheckAuthorization()."/> + </arg> + </method> + <method name="RegisterAuthenticationAgent"> <annotation name="org.gtk.EggDBus.DocString" value="<para>Register an authentication agent.</para><para>Note that current versions of PolicyKit will only work if @session_id is set to the empty string. In the future it might work for non-empty strings if the caller is sufficiently privileged.</para>"/> diff --git a/src/Makefile.am b/src/Makefile.am index 33d3284..d0d1d18 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ -SUBDIRS = polkit polkitbackend polkitagent polkitd programs +SUBDIRS = polkit polkitbackend polkitagent polkitd programs examples clean-local : rm -f *~ diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am new file mode 100644 index 0000000..1c40863 --- /dev/null +++ b/src/examples/Makefile.am @@ -0,0 +1,32 @@ + +NULL = + +INCLUDES = \ + -I$(top_builddir)/src \ + -I$(top_srcdir)/src \ + -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \ + -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ + -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ + -D_POSIX_PTHREAD_SEMANTICS \ + -D_REENTRANT \ + $(NULL) + +noinst_PROGRAMS = cancel + +cancel_SOURCES = cancel.c + +cancel_CFLAGS = \ + $(GLIB_CFLAGS) \ + $(NULL) + +cancel_LDADD = \ + $(GLIB_LDADD) \ + $(top_builddir)/src/polkit/libpolkit-gobject-1.la \ + $(NULL) + +clean-local : + rm -f *~ diff --git a/src/examples/cancel.c b/src/examples/cancel.c new file mode 100644 index 0000000..f0ede35 --- /dev/null +++ b/src/examples/cancel.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +/* Simple example that shows how to check for an authorization including + * cancelling the check. + * + * Cancelling an authorization check is desirable in situations where the + * object/action to check for vanishes. One concrete example of this is + * a disks daemon in which the user needs to authenticate to mount a file + * system. If the disk is removed while the user is busy with the authentication + * dialog, the disks daemon should cancel the authorization check. + */ + +#include <polkit/polkit.h> + +static void +check_authorization_cb (PolkitAuthority *authority, + GAsyncResult *res, + GMainLoop *loop) +{ + GError *error; + PolkitAuthorizationResult result; + + error = NULL; + result = polkit_authority_check_authorization_finish (authority, res, &error); + if (error != NULL) + { + g_print ("Error checking authorization: %s\n", error->message); + g_error_free (error); + } + else + { + gchar *result_str; + switch (result) + { + case POLKIT_AUTHORIZATION_RESULT_NOT_AUTHORIZED: + result_str = g_strdup ("POLKIT_AUTHORIZATION_RESULT_NOT_AUTHORIZED"); + break; + + case POLKIT_AUTHORIZATION_RESULT_AUTHORIZED: + result_str = g_strdup ("POLKIT_AUTHORIZATION_RESULT_AUTHORIZED"); + break; + + case POLKIT_AUTHORIZATION_RESULT_CHALLENGE: + result_str = g_strdup ("POLKIT_AUTHORIZATION_RESULT_CHALLENGE"); + break; + + default: + result_str = g_strdup_printf ("Unknown return code %d", result); + break; + } + g_print ("Authorization result: %s\n", result_str); + g_free (result_str); + } + + g_main_loop_quit (loop); +} + +static gboolean +do_cancel (GCancellable *cancellable) +{ + g_print ("Timer has expired; cancelling authorization check\n"); + g_cancellable_cancel (cancellable); + return FALSE; +} + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + PolkitSubject *calling_process; + PolkitAuthority *authority; + GCancellable *cancellable; + + g_type_init (); + + loop = g_main_loop_new (NULL, FALSE); + + authority = polkit_authority_get (); + + calling_process = polkit_unix_process_new (getppid ()); + + cancellable = g_cancellable_new (); + + g_print ("Will cancel authorization check in 10 seconds\n"); + g_timeout_add (10 * 1000, + (GSourceFunc) do_cancel, + cancellable); + + polkit_authority_check_authorization (authority, + calling_process, + "org.freedesktop.policykit.grant", + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, + cancellable, + (GAsyncReadyCallback) check_authorization_cb, + loop); + + g_main_loop_run (loop); + + g_object_unref (authority); + g_object_unref (calling_process); + g_object_unref (cancellable); + g_main_loop_unref (loop); + + return 0; +} diff --git a/src/polkit/polkitauthority.c b/src/polkit/polkitauthority.c index 24fbd81..c4ab0da 100644 --- a/src/polkit/polkitauthority.c +++ b/src/polkit/polkitauthority.c @@ -26,6 +26,7 @@ #include "polkitauthorizationresult.h" #include "polkitcheckauthorizationflags.h" #include "polkitauthority.h" +#include "polkiterror.h" #include "polkitprivate.h" @@ -60,6 +61,8 @@ struct _PolkitAuthority EggDBusObjectProxy *authority_object_proxy; _PolkitAuthority *real; + + guint cancellation_id_counter; }; struct _PolkitAuthorityClass @@ -334,6 +337,7 @@ polkit_authority_check_authorization_async (PolkitAuthority *autho _PolkitSubject *real_subject; guint call_id; GSimpleAsyncResult *simple; + gchar *cancellation_id; real_subject = polkit_subject_get_real (subject); @@ -342,11 +346,19 @@ polkit_authority_check_authorization_async (PolkitAuthority *autho user_data, polkit_authority_check_authorization_async); + cancellation_id = NULL; + if (cancellable != NULL) + { + cancellation_id = g_strdup_printf ("cancellation-id-%d", authority->cancellation_id_counter++); + g_object_set_data_full (G_OBJECT (simple), "polkit-1-cancellation-id", cancellation_id, g_free); + } + call_id = _polkit_authority_check_authorization (authority->real, - EGG_DBUS_CALL_FLAGS_NONE, + EGG_DBUS_CALL_FLAGS_TIMEOUT_NONE, real_subject, action_id, flags, + cancellation_id, cancellable, generic_async_cb, simple); @@ -391,6 +403,23 @@ polkit_authority_check_authorization (PolkitAuthority *authority, user_data); } +static void +authorization_check_cancelled_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error; + + error = NULL; + if (!_polkit_authority_cancel_check_authorization_finish (_POLKIT_AUTHORITY (source_object), + res, + &error)) + { + g_warning ("Error cancelling authorization check: %s", error->message); + g_error_free (error); + } +} + /** * polkit_authority_check_authorization_finish: * @authority: A #PolkitAuthority. @@ -409,6 +438,7 @@ polkit_authority_check_authorization_finish (PolkitAuthority *authority _PolkitAuthorizationResult result; GSimpleAsyncResult *simple; GAsyncResult *real_res; + GError *local_error; simple = G_SIMPLE_ASYNC_RESULT (res); real_res = G_ASYNC_RESULT (g_simple_async_result_get_op_res_gpointer (simple)); @@ -417,13 +447,44 @@ polkit_authority_check_authorization_finish (PolkitAuthority *authority result = _POLKIT_AUTHORIZATION_RESULT_NOT_AUTHORIZED; - if (!_polkit_authority_check_authorization_finish (authority->real, - &result, - real_res, - error)) - goto out; + local_error = NULL; + _polkit_authority_check_authorization_finish (authority->real, + &result, + real_res, + &local_error); + + if (local_error != NULL) + { + if (local_error->domain == EGG_DBUS_ERROR && local_error->code == EGG_DBUS_ERROR_CANCELLED) + { + const gchar *cancellation_id; + + /* if the operation was cancelled locally, make sure to tell the daemon so the authentication + * dialog etc. can be removed + */ + cancellation_id = g_object_get_data (G_OBJECT (simple), "polkit-1-cancellation-id"); + if (cancellation_id != NULL) + { + _polkit_authority_cancel_check_authorization (authority->real, + EGG_DBUS_CALL_FLAGS_NONE, + cancellation_id, + NULL, + authorization_check_cancelled_cb, + NULL); + } + + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_CANCELLED, + "The operation was cancelled"); + g_error_free (local_error); + } + else + { + g_propagate_error (error, local_error); + } + } - out: g_object_unref (real_res); return result; } diff --git a/src/polkit/polkitauthority.h b/src/polkit/polkitauthority.h index 584e10c..24d7a94 100644 --- a/src/polkit/polkitauthority.h +++ b/src/polkit/polkitauthority.h @@ -65,23 +65,6 @@ PolkitAuthorizationResult polkit_authority_check_authorization_sync (PolkitAuth GCancellable *cancellable, GError **error); -GList *polkit_authority_enumerate_authorizations_sync (PolkitAuthority *authority, - PolkitIdentity *identity, - GCancellable *cancellable, - GError **error); - -gboolean polkit_authority_add_authorization_sync (PolkitAuthority *authority, - PolkitIdentity *identity, - PolkitAuthorization *authorization, - GCancellable *cancellable, - GError **error); - -gboolean polkit_authority_remove_authorization_sync (PolkitAuthority *authority, - PolkitIdentity *identity, - PolkitAuthorization *authorization, - GCancellable *cancellable, - GError **error); - gboolean polkit_authority_register_authentication_agent_sync (PolkitAuthority *authority, const gchar *session_id, const gchar *object_path, @@ -111,24 +94,6 @@ GList * polkit_authority_enumerate_actions_finish (PolkitAuth GAsyncResult *res, GError **error); -void polkit_authority_enumerate_users (PolkitAuthority *authority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -GList * polkit_authority_enumerate_users_finish (PolkitAuthority *authority, - GAsyncResult *res, - GError **error); - -void polkit_authority_enumerate_groups (PolkitAuthority *authority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -GList * polkit_authority_enumerate_groups_finish (PolkitAuthority *authority, - GAsyncResult *res, - GError **error); - void polkit_authority_check_authorization (PolkitAuthority *authority, PolkitSubject *subject, const gchar *action_id, @@ -141,38 +106,6 @@ PolkitAuthorizationResult polkit_authority_check_authorization_finish (PolkitAu GAsyncResult *res, GError **error); -void polkit_authority_enumerate_authorizations (PolkitAuthority *authority, - PolkitIdentity *identity, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -GList * polkit_authority_enumerate_authorizations_finish (PolkitAuthority *authority, - GAsyncResult *res, - GError **error); - -void polkit_authority_add_authorization (PolkitAuthority *authority, - PolkitIdentity *identity, - PolkitAuthorization *authorization, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean polkit_authority_add_authorization_finish (PolkitAuthority *authority, - GAsyncResult *res, - GError **error); - -void polkit_authority_remove_authorization (PolkitAuthority *authority, - PolkitIdentity *identity, - PolkitAuthorization *authorization, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean polkit_authority_remove_authorization_finish (PolkitAuthority *authority, - GAsyncResult *res, - GError **error); - void polkit_authority_register_authentication_agent (PolkitAuthority *authority, const gchar *session_id, diff --git a/src/polkit/polkiterror.h b/src/polkit/polkiterror.h index 9ef2955..780af7f 100644 --- a/src/polkit/polkiterror.h +++ b/src/polkit/polkiterror.h @@ -43,6 +43,7 @@ GType polkit_error_get_type (void) G_GNUC_CONST; /** * PolkitError: * @POLKIT_ERROR_FAILED: The operation failed. + * @POLKIT_ERROR_CANCELLED: The operation was cancelled. * @POLKIT_ERROR_NOT_SUPPORTED: Operation is not supported. * @POLKIT_ERROR_NOT_AUTHORIZED: Not authorized to perform operation. * @@ -51,8 +52,9 @@ GType polkit_error_get_type (void) G_GNUC_CONST; typedef enum { POLKIT_ERROR_FAILED = 0, - POLKIT_ERROR_NOT_SUPPORTED = 1, - POLKIT_ERROR_NOT_AUTHORIZED = 2, + POLKIT_ERROR_CANCELLED = 1, + POLKIT_ERROR_NOT_SUPPORTED = 2, + POLKIT_ERROR_NOT_AUTHORIZED = 3, } PolkitError; G_END_DECLS diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c index cf5ce04..f81fba8 100644 --- a/src/polkitbackend/polkitbackendauthority.c +++ b/src/polkitbackend/polkitbackendauthority.c @@ -530,6 +530,8 @@ struct _Server gulong authority_changed_id; gchar *well_known_name; + + GHashTable *cancellation_id_to_cancellable; }; struct _ServerClass @@ -546,8 +548,12 @@ G_DEFINE_TYPE_WITH_CODE (Server, server, G_TYPE_OBJECT, ); static void -server_init (Server *local_server) +server_init (Server *server) { + server->cancellation_id_to_cancellable = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_object_unref); } static void @@ -569,6 +575,7 @@ server_finalize (GObject *object) g_signal_handler_disconnect (server->authority, server->authority_changed_id); + g_hash_table_unref (server->cancellation_id_to_cancellable); } static void @@ -767,6 +774,7 @@ check_auth_cb (GObject *source_object, gpointer user_data) { EggDBusMethodInvocation *method_invocation = EGG_DBUS_METHOD_INVOCATION (user_data); + const gchar *full_cancellation_id; PolkitAuthorizationResult result; GError *error; @@ -774,6 +782,15 @@ check_auth_cb (GObject *source_object, result = polkit_backend_authority_check_authorization_finish (POLKIT_BACKEND_AUTHORITY (source_object), res, &error); + + full_cancellation_id = g_object_get_data (G_OBJECT (method_invocation), "cancellation-id"); + if (full_cancellation_id != NULL) + { + Server *server; + server = SERVER (g_object_get_data (G_OBJECT (method_invocation), "server")); + g_hash_table_remove (server->cancellation_id_to_cancellable, full_cancellation_id); + } + if (error != NULL) { egg_dbus_method_invocation_return_gerror (method_invocation, error); @@ -790,27 +807,96 @@ authority_handle_check_authorization (_PolkitAuthority *instance, _PolkitSubject *real_subject, const gchar *action_id, _PolkitCheckAuthorizationFlags flags, + const gchar *cancellation_id, EggDBusMethodInvocation *method_invocation) { Server *server = SERVER (instance); + const gchar *caller_name; PolkitSubject *subject; PolkitSubject *caller; + GCancellable *cancellable; - caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation)); + caller_name = egg_dbus_method_invocation_get_caller (method_invocation); + caller = polkit_system_bus_name_new (caller_name); subject = polkit_subject_new_for_real (real_subject); g_object_set_data_full (G_OBJECT (method_invocation), "caller", caller, (GDestroyNotify) g_object_unref); g_object_set_data_full (G_OBJECT (method_invocation), "subject", subject, (GDestroyNotify) g_object_unref); + cancellable = NULL; + if (cancellation_id != NULL && strlen (cancellation_id) > 0) + { + gchar *full_cancellation_id; + + full_cancellation_id = g_strdup_printf ("%s-%s", caller_name, cancellation_id); + + if (g_hash_table_lookup (server->cancellation_id_to_cancellable, full_cancellation_id) != NULL) + { + egg_dbus_method_invocation_return_error (method_invocation, + _POLKIT_ERROR, + _POLKIT_ERROR_CANCELLATION_ID_NOT_UNIQUE, + "Given cancellation_id %s is already in use for name %s", + cancellation_id, + caller_name); + g_free (full_cancellation_id); + goto out; + } + + cancellable = g_cancellable_new (); + + g_hash_table_insert (server->cancellation_id_to_cancellable, + full_cancellation_id, + cancellable); + + g_object_set_data (G_OBJECT (method_invocation), "server", server); + g_object_set_data (G_OBJECT (method_invocation), "cancellation-id", full_cancellation_id); + } + polkit_backend_authority_check_authorization (server->authority, caller, subject, action_id, flags, - NULL, /* TODO: use cancellable */ + cancellable, check_auth_cb, method_invocation); + out: + ; +} + +static void +authority_handle_cancel_check_authorization (_PolkitAuthority *instance, + const gchar *cancellation_id, + EggDBusMethodInvocation *method_invocation) +{ + Server *server = SERVER (instance); + GCancellable *cancellable; + const gchar *caller_name; + gchar *full_cancellation_id; + + caller_name = egg_dbus_method_invocation_get_caller (method_invocation); + + full_cancellation_id = g_strdup_printf ("%s-%s", caller_name, cancellation_id); + + cancellable = g_hash_table_lookup (server->cancellation_id_to_cancellable, full_cancellation_id); + if (cancellable == NULL) + { + egg_dbus_method_invocation_return_error (method_invocation, + _POLKIT_ERROR, + _POLKIT_ERROR_FAILED, + "No such cancellation_id %s for name %s", + cancellation_id, + caller_name); + goto out; + } + + g_cancellable_cancel (cancellable); + + _polkit_authority_handle_cancel_check_authorization_finish (method_invocation); + + out: + g_free (full_cancellation_id); } /* ---------------------------------------------------------------------------------------------------- */ @@ -1064,6 +1150,7 @@ authority_iface_init (_PolkitAuthorityIface *authority_iface) { authority_iface->handle_enumerate_actions = authority_handle_enumerate_actions; authority_iface->handle_check_authorization = authority_handle_check_authorization; + authority_iface->handle_cancel_check_authorization = authority_handle_cancel_check_authorization; authority_iface->handle_register_authentication_agent = authority_handle_register_authentication_agent; authority_iface->handle_unregister_authentication_agent = authority_handle_unregister_authentication_agent; authority_iface->handle_authentication_agent_response = authority_handle_authentication_agent_response; diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c index 1b981e6..15a7f8f 100644 --- a/src/polkitbackend/polkitbackendlocalauthority.c +++ b/src/polkitbackend/polkitbackendlocalauthority.c @@ -91,6 +91,7 @@ static void authentication_agent_initiate_challenge (Authenticati const gchar *action_id, PolkitSubject *caller, PolkitImplicitAuthorization implicit_authorization, + GCancellable *cancellable, AuthenticationAgentCallback callback, gpointer user_data); @@ -665,12 +666,22 @@ polkit_backend_local_authority_check_authorization (PolkitBackendAuthority action_id, caller, implicit_authorization, + cancellable, check_authorization_challenge_cb, simple); - } + /* keep going */ + goto out; + } } + /* Otherwise just return the result */ + g_simple_async_result_set_op_res_gpointer (simple, + GINT_TO_POINTER ((gint) result), + NULL); + g_simple_async_result_complete (simple); + g_object_unref (simple); + out: if (user_of_caller != NULL) @@ -1056,8 +1067,19 @@ struct AuthenticationSession guint call_id; gboolean is_authenticated; + + GCancellable *cancellable; + + gulong cancellable_signal_handler_id; }; +static void +authentication_session_cancelled_cb (GCancellable *cancellable, + AuthenticationSession *session) +{ + authentication_session_cancel (session); +} + static AuthenticationSession * authentication_session_new (AuthenticationAgent *agent, const gchar *cookie, @@ -1068,6 +1090,7 @@ authentication_session_new (AuthenticationAgent *agent, const gchar *action_id, const gchar *initiated_by_system_bus_unique_name, PolkitImplicitAuthorization implicit_authorization, + GCancellable *cancellable, AuthenticationAgentCallback callback, gpointer user_data) { @@ -1084,9 +1107,18 @@ authentication_session_new (AuthenticationAgent *agent, session->action_id = g_strdup (action_id); session->initiated_by_system_bus_unique_name = g_strdup (initiated_by_system_bus_unique_name); session->implicit_authorization = implicit_authorization; + session->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL; session->callback = callback; session->user_data = user_data; + if (session->cancellable != NULL) + { + session->cancellable_signal_handler_id = g_signal_connect (session->cancellable, + "cancelled", + G_CALLBACK (authentication_session_cancelled_cb), + session); + } + return session; } @@ -1101,6 +1133,10 @@ authentication_session_free (AuthenticationSession *session) g_object_unref (session->authority); g_free (session->action_id); g_free (session->initiated_by_system_bus_unique_name); + if (session->cancellable_signal_handler_id > 0) + g_signal_handler_disconnect (session->cancellable, session->cancellable_signal_handler_id); + if (session->cancellable != NULL) + g_object_unref (session->cancellable); g_free (session); } @@ -1307,7 +1343,6 @@ authentication_agent_begin_callback (GObject *source_object, { g_warning ("Error performing authentication: %s", error->message); g_error_free (error); - gained_authorization = FALSE; } else @@ -1339,6 +1374,7 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent, const gchar *action_id, PolkitSubject *caller, PolkitImplicitAuthorization implicit_authorization, + GCancellable *cancellable, AuthenticationAgentCallback callback, gpointer user_data) { @@ -1369,6 +1405,7 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent, action_id, polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)), implicit_authorization, + cancellable, callback, user_data); @@ -1384,7 +1421,7 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent, } session->call_id = _polkit_authentication_agent_begin_authentication (agent_dbus, - EGG_DBUS_CALL_FLAGS_NONE, + EGG_DBUS_CALL_FLAGS_TIMEOUT_NONE, action_id, session->cookie, real_identities, @@ -1525,6 +1562,7 @@ polkit_backend_local_authority_unregister_authentication_agent (PolkitBackendAut priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority); ret = FALSE; + session_for_caller = NULL; if (session_id != NULL && strlen (session_id) > 0) { diff --git a/src/programs/polkit.c b/src/programs/polkit.c index db89d81..ea2cacd 100644 --- a/src/programs/polkit.c +++ b/src/programs/polkit.c @@ -657,7 +657,7 @@ do_run (gint argc, gchar *argv[]) if (result != POLKIT_AUTHORIZATION_RESULT_AUTHORIZED) { - g_printerr ("Error obtaining authorization for action %s\n", action_id); + g_printerr ("Error obtaining authorization for action %s (%d)\n", action_id, result); goto out; } |