PolicyKit: Branch 'master' - 2 commits

David Zeuthen david at kemper.freedesktop.org
Sun Feb 8 11:24:57 PST 2009


 configure.ac                                    |    1 
 data/org.freedesktop.PolicyKit1.Authority.xml   |   23 ++++
 src/Makefile.am                                 |    2 
 src/examples/Makefile.am                        |   32 ++++++
 src/examples/cancel.c                           |  124 ++++++++++++++++++++++++
 src/polkit/polkitauthority.c                    |   75 +++++++++++++-
 src/polkit/polkitauthority.h                    |   67 ------------
 src/polkit/polkiterror.h                        |    6 -
 src/polkitbackend/polkitbackendauthority.c      |   93 +++++++++++++++++-
 src/polkitbackend/polkitbackendlocalauthority.c |   44 +++++++-
 src/polkitbackend/polkitbackendsessionmonitor.c |   17 ++-
 src/programs/polkit.c                           |    2 
 12 files changed, 399 insertions(+), 87 deletions(-)

New commits:
commit bc150368d95ef70b04af3bc9250c1bdfe950a048
Author: David Zeuthen <davidz at redhat.com>
Date:   Sun Feb 8 14:22:45 2009 -0500

    implement cancellation of authorization checks
    
    Also add a short example to test this.

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 at 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;
     }
 
commit 7b815725b03da8564f7bea835c8f05539e481adc
Author: David Zeuthen <davidz at redhat.com>
Date:   Sun Feb 8 14:10:52 2009 -0500

    don't hardcode the uid, look it up in /proc

diff --git a/src/polkitbackend/polkitbackendsessionmonitor.c b/src/polkitbackend/polkitbackendsessionmonitor.c
index 212c3ef..667401e 100644
--- a/src/polkitbackend/polkitbackendsessionmonitor.c
+++ b/src/polkitbackend/polkitbackendsessionmonitor.c
@@ -24,6 +24,8 @@
 #include <pwd.h>
 #include <grp.h>
 #include <string.h>
+#include <glib/gstdio.h>
+
 #include <polkit/polkit.h>
 #include "polkitbackendsessionmonitor.h"
 #include "ckbindings.h"
@@ -380,11 +382,22 @@ polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor
   if (POLKIT_IS_UNIX_PROCESS (subject))
     {
       pid_t pid;
+      gchar *proc_path;
+      struct stat statbuf;
 
       pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject));
-      uid = 500; /* TODO */
 
-      user = polkit_unix_user_new (uid);
+      proc_path = g_strdup_printf ("/proc/%d", pid);
+      if (g_stat (proc_path, &statbuf) != 0)
+        {
+          g_set_error (error,
+                       POLKIT_ERROR,
+                       POLKIT_ERROR_FAILED,
+                       "Cannot get user for pid %d",
+                       pid);
+          goto out;
+        }
+      user = polkit_unix_user_new (statbuf.st_uid);
     }
   else if (POLKIT_IS_UNIX_SESSION (subject))
     {


More information about the hal-commit mailing list