summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--data/org.freedesktop.PolicyKit1.Authority.xml23
-rw-r--r--src/Makefile.am2
-rw-r--r--src/examples/Makefile.am32
-rw-r--r--src/examples/cancel.c124
-rw-r--r--src/polkit/polkitauthority.c75
-rw-r--r--src/polkit/polkitauthority.h67
-rw-r--r--src/polkit/polkiterror.h6
-rw-r--r--src/polkitbackend/polkitbackendauthority.c93
-rw-r--r--src/polkitbackend/polkitbackendlocalauthority.c44
-rw-r--r--src/programs/polkit.c2
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;
}