PolicyKit: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Sun Jul 26 19:09:38 PDT 2009


 data/org.freedesktop.PolicyKit1.Authority.xml         |   12 
 docs/polkit/polkit-1-sections.txt                     |    4 
 src/polkit/polkitauthority.c                          |  197 ++++++++++++++-
 src/polkit/polkitauthority.h                          |   15 +
 src/polkit/polkitauthorizationresult.c                |    6 
 src/polkitbackend/polkitbackendauthority.c            |   86 +++++-
 src/polkitbackend/polkitbackendauthority.h            |   14 +
 src/polkitbackend/polkitbackendinteractiveauthority.c |  235 +++++++++++++-----
 src/polkitbackend/polkitbackendlocalauthority.c       |   14 +
 9 files changed, 505 insertions(+), 78 deletions(-)

New commits:
commit de0985aaeb9a44090f3cb37e4ea6308c0152797a
Author: David Zeuthen <davidz at redhat.com>
Date:   Sun Jul 26 22:05:38 2009 -0400

    Allow unprivileged callers to check authorizations
    
    But only allow this if
    
     - the caller and the subject being checked is the same user
     - no details are passed (otherwise dialogs can be spoofed)
    
    Also add a RevokeTemporaryAuthorizationById() method.

diff --git a/data/org.freedesktop.PolicyKit1.Authority.xml b/data/org.freedesktop.PolicyKit1.Authority.xml
index 6b29e8e..9b49334 100644
--- a/data/org.freedesktop.PolicyKit1.Authority.xml
+++ b/data/org.freedesktop.PolicyKit1.Authority.xml
@@ -129,7 +129,7 @@
       </annotation>
 
       <annotation name="org.gtk.EggDBus.Struct.Member"  value="Dict<String,String>:details">
-        <annotation name="org.gtk.EggDBus.DocString" value="Details for the result or empty if not authorized."/>
+        <annotation name="org.gtk.EggDBus.DocString" value="Details for the result or empty if not authorized. Known key/value-pairs include <literal>polkit.temporary_authorization_id</literal> (if the authorization is temporary, this is set to the opaque temporary authorization id)."/>
       </annotation>
     </annotation>
 
@@ -223,7 +223,7 @@
       </arg>
 
       <arg name="details" direction="in" type="a{ss}">
-        <annotation name="org.gtk.EggDBus.DocString" value="Details describing the action."/>
+        <annotation name="org.gtk.EggDBus.DocString" value="Details describing the action. Keys starting with <literal>polkit.</literal> are reserved for internal use and cannot be used."/>
       </arg>
 
       <arg name="flags" direction="in" type="u">
@@ -348,6 +348,14 @@
       </arg>
     </method>
 
+    <method name="RevokeTemporaryAuthorizationById">
+      <annotation name="org.gtk.EggDBus.DocString" value="Revokes all temporary authorizations that applies to @subject."/>
+
+      <arg name="id" direction="in" type="s">
+        <annotation name="org.gtk.EggDBus.DocString" value="The opaque identifier of the temporary authorization."/>
+      </arg>
+    </method>
+
     <!-- ---------------------------------------------------------------------------------------------------- -->
 
     <signal name="Changed">
diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt
index f096d2d..c06a55a 100644
--- a/docs/polkit/polkit-1-sections.txt
+++ b/docs/polkit/polkit-1-sections.txt
@@ -35,6 +35,8 @@ polkit_authority_enumerate_temporary_authorizations
 polkit_authority_enumerate_temporary_authorizations_finish
 polkit_authority_revoke_temporary_authorizations
 polkit_authority_revoke_temporary_authorizations_finish
+polkit_authority_revoke_temporary_authorization_by_id
+polkit_authority_revoke_temporary_authorization_by_id_finish
 polkit_authority_check_authorization_sync
 polkit_authority_enumerate_actions_sync
 polkit_authority_register_authentication_agent_sync
@@ -42,6 +44,7 @@ polkit_authority_unregister_authentication_agent_sync
 polkit_authority_authentication_agent_response_sync
 polkit_authority_enumerate_temporary_authorizations_sync
 polkit_authority_revoke_temporary_authorizations_sync
+polkit_authority_revoke_temporary_authorization_by_id_sync
 <SUBSECTION Standard>
 PolkitAuthorityClass
 POLKIT_AUTHORITY
@@ -439,7 +442,6 @@ POLKIT_AGENT_LISTENER_GET_CLASS
 <FILE>polkittemporaryauthorization</FILE>
 <TITLE>PolkitTemporaryAuthorization</TITLE>
 PolkitTemporaryAuthorization
-PolkitTemporaryAuthorizationClass
 polkit_temporary_authorization_get_id
 polkit_temporary_authorization_get_action_id
 polkit_temporary_authorization_get_subject
diff --git a/src/polkit/polkitauthority.c b/src/polkit/polkitauthority.c
index 4d34b16..7d2c235 100644
--- a/src/polkit/polkitauthority.c
+++ b/src/polkit/polkitauthority.c
@@ -396,7 +396,8 @@ polkit_authority_check_authorization_async (PolkitAuthority               *autho
  * @authority: A #PolkitAuthority.
  * @subject: A #PolkitSubject.
  * @action_id: The action to check for.
- * @details: Details about the action or %NULL.
+ * @details: Details about the action or %NULL. Keys starting with <literal>polkit.</literal> are reserved
+ * for internal use and cannot be used.
  * @flags: A set of #PolkitCheckAuthorizationFlags.
  * @cancellable: A #GCancellable or %NULL.
  * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
@@ -528,7 +529,8 @@ polkit_authority_check_authorization_finish (PolkitAuthority          *authority
  * @authority: A #PolkitAuthority.
  * @subject: A #PolkitSubject.
  * @action_id: The action to check for.
- * @details: Details about the action or %NULL.
+ * @details: Details about the action or %NULL. Keys starting with <literal>polkit.</literal> are reserved
+ * for internal use and cannot be used.
  * @flags: A set of #PolkitCheckAuthorizationFlags.
  * @cancellable: A #GCancellable or %NULL.
  * @error: Return location for error or %NULL.
@@ -1035,6 +1037,20 @@ polkit_authority_enumerate_temporary_authorizations_async (PolkitAuthority     *
   return call_id;
 }
 
+/**
+ * polkit_authority_enumerate_temporary_authorizations:
+ * @authority: A #PolkitAuthority.
+ * @subject: A #PolkitSubject, typically a #PolkitUnixSession.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: The data to pass to @callback.
+ *
+ * Asynchronously gets all temporary authorizations for @subject.
+ *
+ * When the operation is finished, @callback will be invoked. You can then
+ * call polkit_authority_enumerate_temporary_authorizations_finish() to get the result of
+ * the operation.
+ **/
 void
 polkit_authority_enumerate_temporary_authorizations (PolkitAuthority     *authority,
                                                      PolkitSubject       *subject,
@@ -1045,6 +1061,17 @@ polkit_authority_enumerate_temporary_authorizations (PolkitAuthority     *author
   polkit_authority_enumerate_temporary_authorizations_async (authority, subject, cancellable, callback, user_data);
 }
 
+/**
+ * polkit_authority_enumerate_temporary_authorizations_finish:
+ * @authority: A #PolkitAuthority.
+ * @res: A #GAsyncResult obtained from the callback.
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes retrieving all registered actions.
+ *
+ * Returns: A list of #PolkitTemporaryAuthorization objects or %NULL if @error is set. The returned list
+ * should be freed with g_list_free() after each element have been freed with g_object_unref().
+ **/
 GList *
 polkit_authority_enumerate_temporary_authorizations_finish (PolkitAuthority *authority,
                                                             GAsyncResult    *res,
@@ -1087,6 +1114,18 @@ polkit_authority_enumerate_temporary_authorizations_finish (PolkitAuthority *aut
   return result;
 }
 
+/**
+ * polkit_authority_enumerate_temporary_authorizations_sync:
+ * @authority: A #PolkitAuthority.
+ * @subject: A #PolkitSubject, typically a #PolkitUnixSession.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronousky gets all temporary authorizations for @subject.
+ *
+ * Returns: A list of #PolkitTemporaryAuthorization objects or %NULL if @error is set. The returned list
+ * should be freed with g_list_free() after each element have been freed with g_object_unref().
+ **/
 GList *
 polkit_authority_enumerate_temporary_authorizations_sync (PolkitAuthority     *authority,
                                                           PolkitSubject       *subject,
@@ -1140,6 +1179,20 @@ polkit_authority_revoke_temporary_authorizations_async (PolkitAuthority     *aut
   return call_id;
 }
 
+/**
+ * polkit_authority_revoke_temporary_authorizations:
+ * @authority: A #PolkitAuthority.
+ * @subject: The subject to revoke authorizations from, typically a #PolkitUnixSession.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: The data to pass to @callback.
+ *
+ * Asynchronously revokes all temporary authorizations for @subject.
+ *
+ * When the operation is finished, @callback will be invoked. You can then
+ * call polkit_authority_revoke_temporary_authorizations_finish() to get the result of
+ * the operation.
+ **/
 void
 polkit_authority_revoke_temporary_authorizations (PolkitAuthority     *authority,
                                                   PolkitSubject       *subject,
@@ -1150,6 +1203,16 @@ polkit_authority_revoke_temporary_authorizations (PolkitAuthority     *authority
   polkit_authority_revoke_temporary_authorizations_async (authority, subject, cancellable, callback, user_data);
 }
 
+/**
+ * polkit_authority_revoke_temporary_authorizations_finish:
+ * @authority: A #PolkitAuthority.
+ * @res: A #GAsyncResult obtained from the callback.
+ * @error: Return location for error or %NULL.
+ *
+ * Finished revoking temporary authorizations.
+ *
+ * Returns: %TRUE if all the temporary authorizations was revoked, %FALSE if error is set.
+ **/
 gboolean
 polkit_authority_revoke_temporary_authorizations_finish (PolkitAuthority *authority,
                                                          GAsyncResult    *res,
@@ -1176,6 +1239,17 @@ polkit_authority_revoke_temporary_authorizations_finish (PolkitAuthority *author
   return ret;
 }
 
+/**
+ * polkit_authority_revoke_temporary_authorizations_sync:
+ * @authority: A #PolkitAuthority.
+ * @subject: The subject to revoke authorizations from, typically a #PolkitUnixSession.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously revokes all temporary authorization from @subject.
+ *
+ * Returns: %TRUE if the temporary authorization was revoked, %FALSE if error is set.
+ **/
 gboolean
 polkit_authority_revoke_temporary_authorizations_sync (PolkitAuthority     *authority,
                                                        PolkitSubject       *subject,
@@ -1198,3 +1272,122 @@ polkit_authority_revoke_temporary_authorizations_sync (PolkitAuthority     *auth
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
+
+static guint
+polkit_authority_revoke_temporary_authorization_by_id_async (PolkitAuthority     *authority,
+                                                             const gchar         *id,
+                                                             GCancellable        *cancellable,
+                                                             GAsyncReadyCallback  callback,
+                                                             gpointer             user_data)
+{
+  guint call_id;
+  GSimpleAsyncResult *simple;
+
+  simple = g_simple_async_result_new (G_OBJECT (authority),
+                                      callback,
+                                      user_data,
+                                      polkit_authority_revoke_temporary_authorizations_async);
+
+  call_id = _polkit_authority_revoke_temporary_authorization_by_id (authority->real,
+                                                                    EGG_DBUS_CALL_FLAGS_NONE,
+                                                                    id,
+                                                                    cancellable,
+                                                                    generic_async_cb,
+                                                                    simple);
+
+  return call_id;
+}
+
+/**
+ * polkit_authority_revoke_temporary_authorization_by_id:
+ * @authority: A #PolkitAuthority.
+ * @id: The opaque identifier for the temporary authorization.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: The data to pass to @callback.
+ *
+ * Asynchronously revoke a temporary authorization.
+ *
+ * When the operation is finished, @callback will be invoked. You can then
+ * call polkit_authority_revoke_temporary_authorization_by_id_finish() to get the result of
+ * the operation.
+ */
+void
+polkit_authority_revoke_temporary_authorization_by_id (PolkitAuthority     *authority,
+                                                       const gchar         *id,
+                                                       GCancellable        *cancellable,
+                                                       GAsyncReadyCallback  callback,
+                                                       gpointer             user_data)
+{
+  polkit_authority_revoke_temporary_authorization_by_id_async (authority, id, cancellable, callback, user_data);
+}
+
+/**
+ * polkit_authority_revoke_temporary_authorization_by_id_finish:
+ * @authority: A #PolkitAuthority.
+ * @res: A #GAsyncResult obtained from the callback.
+ * @error: Return location for error or %NULL.
+ *
+ * Finished revoking a temporary authorization by id.
+ *
+ * Returns: %TRUE if the temporary authorization was revoked, %FALSE if error is set.
+ **/
+gboolean
+polkit_authority_revoke_temporary_authorization_by_id_finish (PolkitAuthority *authority,
+                                                              GAsyncResult    *res,
+                                                              GError         **error)
+{
+  GSimpleAsyncResult *simple;
+  GAsyncResult *real_res;
+  gboolean ret;
+
+  simple = G_SIMPLE_ASYNC_RESULT (res);
+  real_res = G_ASYNC_RESULT (g_simple_async_result_get_op_res_gpointer (simple));
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_authority_revoke_temporary_authorizations_async);
+
+  ret = _polkit_authority_revoke_temporary_authorization_by_id_finish (authority->real,
+                                                                       real_res,
+                                                                       error);
+
+  if (!ret)
+    goto out;
+
+ out:
+  g_object_unref (real_res);
+  return ret;
+}
+
+/**
+ * polkit_authority_revoke_temporary_authorization_by_id_sync:
+ * @authority: A #PolkitAuthority.
+ * @id: The opaque identifier for the temporary authorization.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously revokes a temporary authorization.
+ *
+ * Returns: %TRUE if the temporary authorization was revoked, %FALSE if error is set.
+ **/
+gboolean
+polkit_authority_revoke_temporary_authorization_by_id_sync (PolkitAuthority     *authority,
+                                                            const gchar         *id,
+                                                            GCancellable        *cancellable,
+                                                            GError             **error)
+{
+  guint call_id;
+  GAsyncResult *res;
+  gboolean result;
+
+  call_id = polkit_authority_revoke_temporary_authorization_by_id_async (authority, id, cancellable, generic_cb, &res);
+
+  egg_dbus_connection_pending_call_block (authority->system_bus, call_id);
+
+  result = polkit_authority_revoke_temporary_authorization_by_id_finish (authority, res, error);
+
+  g_object_unref (res);
+
+  return result;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/polkit/polkitauthority.h b/src/polkit/polkitauthority.h
index 61a6e7c..e45b3a1 100644
--- a/src/polkit/polkitauthority.h
+++ b/src/polkit/polkitauthority.h
@@ -99,6 +99,11 @@ gboolean                   polkit_authority_revoke_temporary_authorizations_sync
                                                                                   GCancellable        *cancellable,
                                                                                   GError             **error);
 
+gboolean                   polkit_authority_revoke_temporary_authorization_by_id_sync (PolkitAuthority     *authority,
+                                                                                       const gchar         *id,
+                                                                                       GCancellable        *cancellable,
+                                                                                       GError             **error);
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 void                       polkit_authority_enumerate_actions (PolkitAuthority     *authority,
@@ -177,6 +182,16 @@ gboolean                   polkit_authority_revoke_temporary_authorizations_fini
                                                                                     GAsyncResult    *res,
                                                                                     GError         **error);
 
+void                       polkit_authority_revoke_temporary_authorization_by_id (PolkitAuthority     *authority,
+                                                                                  const gchar         *id,
+                                                                                  GCancellable        *cancellable,
+                                                                                  GAsyncReadyCallback  callback,
+                                                                                  gpointer             user_data);
+
+gboolean                   polkit_authority_revoke_temporary_authorization_by_id_finish (PolkitAuthority *authority,
+                                                                                         GAsyncResult    *res,
+                                                                                         GError         **error);
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 G_END_DECLS
diff --git a/src/polkit/polkitauthorizationresult.c b/src/polkit/polkitauthorizationresult.c
index 6786a5a..08911ef 100644
--- a/src/polkit/polkitauthorizationresult.c
+++ b/src/polkit/polkitauthorizationresult.c
@@ -187,6 +187,12 @@ polkit_authorization_result_get_is_challenge (PolkitAuthorizationResult *result)
  *
  * Gets the details about the result.
  *
+ * If the authorization is temporary the opaque identifier for the
+ * temporary authorization
+ * (cf. polkit_temporary_authorization_get_id()) is set available as
+ * the value for the
+ * <literal>polkit.temporary_authorization_id</literal> key.
+ *
  * Returns: A #PolkitDetails object. This object is owned by @result
  * and should not be freed by the caller.
  */
diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
index eec0664..63caf0f 100644
--- a/src/polkitbackend/polkitbackendauthority.c
+++ b/src/polkitbackend/polkitbackendauthority.c
@@ -381,7 +381,7 @@ polkit_backend_authority_enumerate_temporary_authorizations (PolkitBackendAuthor
  *
  * Revokes temporary authorizations for @subject.
  *
- * Returns: %TRUE if the operatoin succeeded, %FALSE if @error is set.
+ * Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
  **/
 gboolean
 polkit_backend_authority_revoke_temporary_authorizations (PolkitBackendAuthority   *authority,
@@ -407,6 +407,41 @@ polkit_backend_authority_revoke_temporary_authorizations (PolkitBackendAuthority
     }
 }
 
+/**
+ * polkit_backend_authority_revoke_temporary_authorization_by_id:
+ * @authority: A #PolkitBackendAuthority.
+ * @caller: The system bus name that initiated the query.
+ * @id: The opaque identifier of the temporary authorization.
+ * @error: Return location for error.
+ *
+ * Revokes a temporary authorizations with opaque identifier @id.
+ *
+ * Returns: %TRUE if the operatoin succeeded, %FALSE if @error is set.
+ **/
+gboolean
+polkit_backend_authority_revoke_temporary_authorization_by_id (PolkitBackendAuthority   *authority,
+                                                               PolkitSubject            *caller,
+                                                               const gchar              *id,
+                                                               GError                  **error)
+{
+  PolkitBackendAuthorityClass *klass;
+
+  klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);
+
+  if (klass->revoke_temporary_authorization_by_id == NULL)
+    {
+      g_set_error (error,
+                   POLKIT_ERROR,
+                   POLKIT_ERROR_NOT_SUPPORTED,
+                   "Operation not supported");
+      return FALSE;
+    }
+  else
+    {
+      return klass->revoke_temporary_authorization_by_id (authority, caller, id, error);
+    }
+}
+
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -917,16 +952,49 @@ authority_handle_revoke_temporary_authorizations (_PolkitAuthority        *insta
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
+authority_handle_revoke_temporary_authorization_by_id (_PolkitAuthority        *instance,
+                                                       const gchar             *id,
+                                                       EggDBusMethodInvocation *method_invocation)
+{
+  Server *server = SERVER (instance);
+  GError *error;
+  PolkitSubject *caller;
+
+  error = NULL;
+
+  caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation));
+
+  polkit_backend_authority_revoke_temporary_authorization_by_id (server->authority,
+                                                                 caller,
+                                                                 id,
+                                                                 &error);
+  if (error != NULL)
+    {
+      egg_dbus_method_invocation_return_gerror (method_invocation, error);
+      g_error_free (error);
+      goto out;
+    }
+
+  _polkit_authority_handle_revoke_temporary_authorization_by_id_finish (method_invocation);
+
+ out:
+  g_object_unref (caller);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
 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;
-  authority_iface->handle_enumerate_temporary_authorizations = authority_handle_enumerate_temporary_authorizations;
-  authority_iface->handle_revoke_temporary_authorizations    = authority_handle_revoke_temporary_authorizations;
+  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;
+  authority_iface->handle_enumerate_temporary_authorizations   = authority_handle_enumerate_temporary_authorizations;
+  authority_iface->handle_revoke_temporary_authorizations      = authority_handle_revoke_temporary_authorizations;
+  authority_iface->handle_revoke_temporary_authorization_by_id = authority_handle_revoke_temporary_authorization_by_id;
 }
 
 static void
diff --git a/src/polkitbackend/polkitbackendauthority.h b/src/polkitbackend/polkitbackendauthority.h
index ca784ef..56d46be 100644
--- a/src/polkitbackend/polkitbackendauthority.h
+++ b/src/polkitbackend/polkitbackendauthority.h
@@ -94,6 +94,10 @@ struct _PolkitBackendAuthority
  * authorizations or %NULL if the backend doesn't support the operation.
  * See polkit_backend_authority_revoke_temporary_authorizations()
  * for details.
+ * @revoke_temporary_authorization_by_id: Called to revoke a temporary
+ * authorization identified by id or %NULL if the backend doesn't support
+ * the operation. See polkit_backend_authority_revoke_temporary_authorization_by_id()
+ * for details.
  * @system_bus_name_owner_changed: temporary VFunc, to be removed before 1.0.
  *
  * VFuncs that authority backends need to implement.
@@ -156,6 +160,11 @@ struct _PolkitBackendAuthorityClass
                                                PolkitSubject            *subject,
                                                GError                  **error);
 
+  gboolean (*revoke_temporary_authorization_by_id) (PolkitBackendAuthority   *authority,
+                                                    PolkitSubject            *caller,
+                                                    const gchar              *id,
+                                                    GError                  **error);
+
   /* TODO: need something more efficient such that we don't watch all name changes */
   void (*system_bus_name_owner_changed)  (PolkitBackendAuthority   *authority,
                                           const gchar              *name,
@@ -255,6 +264,11 @@ gboolean polkit_backend_authority_revoke_temporary_authorizations (PolkitBackend
                                                                    PolkitSubject            *subject,
                                                                    GError                  **error);
 
+gboolean polkit_backend_authority_revoke_temporary_authorization_by_id (PolkitBackendAuthority   *authority,
+                                                                        PolkitSubject            *caller,
+                                                                        const gchar              *id,
+                                                                        GError                  **error);
+
 /* --- */
 
 PolkitBackendAuthority *polkit_backend_authority_get (void);
diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
index 1677404..af58ed3 100644
--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
@@ -55,12 +55,13 @@ static void                         temporary_authorization_store_free (Temporar
 
 static gboolean temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *store,
                                                                  PolkitSubject               *subject,
-                                                                 const gchar                 *action_id);
+                                                                 const gchar                 *action_id,
+                                                                 const gchar                **out_tmp_authz_id);
 
-static void     temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *store,
-                                                                 PolkitSubject               *subject,
-                                                                 PolkitSubject               *session,
-                                                                 const gchar                 *action_id);
+static const gchar *temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *store,
+                                                                     PolkitSubject               *subject,
+                                                                     PolkitSubject               *session,
+                                                                     const gchar                 *action_id);
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -173,6 +174,11 @@ static gboolean polkit_backend_interactive_authority_revoke_temporary_authorizat
                                                                                       PolkitSubject            *subject,
                                                                                       GError                  **error);
 
+static gboolean polkit_backend_interactive_authority_revoke_temporary_authorization_by_id (PolkitBackendAuthority   *authority,
+                                                                                           PolkitSubject            *caller,
+                                                                                           const gchar              *id,
+                                                                                           GError                  **error);
+
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -275,6 +281,7 @@ polkit_backend_interactive_authority_class_init (PolkitBackendInteractiveAuthori
   authority_class->authentication_agent_response   = polkit_backend_interactive_authority_authentication_agent_response;
   authority_class->enumerate_temporary_authorizations = polkit_backend_interactive_authority_enumerate_temporary_authorizations;
   authority_class->revoke_temporary_authorizations = polkit_backend_interactive_authority_revoke_temporary_authorizations;
+  authority_class->revoke_temporary_authorization_by_id = polkit_backend_interactive_authority_revoke_temporary_authorization_by_id;
 
 
 
@@ -333,19 +340,29 @@ check_authorization_challenge_cb (AuthenticationAgent         *agent,
 
   if (authentication_success)
     {
-      result = polkit_authorization_result_new (TRUE, FALSE, NULL);
+      PolkitDetails *details;
+
+      details = polkit_details_new ();
 
       /* store temporary authorization depending on value of implicit_authorization */
       if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
           implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
         {
-          temporary_authorization_store_add_authorization (priv->temporary_authorization_store,
-                                                           subject,
-                                                           authentication_agent_get_session (agent),
-                                                           action_id);
+          const gchar *id;
+
+          id = temporary_authorization_store_add_authorization (priv->temporary_authorization_store,
+                                                                subject,
+                                                                authentication_agent_get_session (agent),
+                                                                action_id);
+
+          polkit_details_insert (details, "polkit.temporary_authorization_id", id);
+
           /* we've added a temporary authorization, let the user know */
           g_signal_emit_by_name (authority, "changed");
         }
+
+      result = polkit_authorization_result_new (TRUE, FALSE, details);
+      g_object_unref (details);
     }
   else
     {
@@ -387,14 +404,14 @@ polkit_backend_interactive_authority_check_authorization_finish (PolkitBackendAu
 
 static void
 polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority         *authority,
-                                                    PolkitSubject                  *caller,
-                                                    PolkitSubject                  *subject,
-                                                    const gchar                    *action_id,
-                                                    PolkitDetails                  *details,
-                                                    PolkitCheckAuthorizationFlags   flags,
-                                                    GCancellable                   *cancellable,
-                                                    GAsyncReadyCallback             callback,
-                                                    gpointer                        user_data)
+                                                          PolkitSubject                  *caller,
+                                                          PolkitSubject                  *subject,
+                                                          const gchar                    *action_id,
+                                                          PolkitDetails                  *details,
+                                                          PolkitCheckAuthorizationFlags   flags,
+                                                          GCancellable                   *cancellable,
+                                                          GAsyncReadyCallback             callback,
+                                                          gpointer                        user_data)
 {
   PolkitBackendInteractiveAuthority *interactive_authority;
   PolkitBackendInteractiveAuthorityPrivate *priv;
@@ -408,6 +425,8 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority
   PolkitImplicitAuthorization implicit_authorization;
   GError *error;
   GSimpleAsyncResult *simple;
+  gboolean has_details;
+  gchar **detail_keys;
 
   interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
   priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
@@ -449,20 +468,6 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority
   user_of_caller_str = polkit_identity_to_string (user_of_caller);
   g_debug (" user of caller is %s", user_of_caller_str);
 
-  /* we only allow trusted callers (uid 0 + others) to check authorizations */
-  if (!POLKIT_IS_UNIX_USER (user_of_caller) ||
-      polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_caller)) != 0) /* TODO: allow other uids like 'haldaemon'? */
-    {
-      g_simple_async_result_set_error (simple,
-                                       POLKIT_ERROR,
-                                       POLKIT_ERROR_NOT_AUTHORIZED,
-                                       "Only trusted callers can use CheckAuthorization(), %s is not trusted",
-                                       user_of_caller_str);
-      g_simple_async_result_complete (simple);
-      g_object_unref (simple);
-      goto out;
-    }
-
   user_of_subject = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
                                                                          subject,
                                                                          &error);
@@ -478,6 +483,38 @@ polkit_backend_interactive_authority_check_authorization (PolkitBackendAuthority
   user_of_subject_str = polkit_identity_to_string (user_of_subject);
   g_debug (" user of subject is %s", user_of_subject_str);
 
+  has_details = FALSE;
+  if (details != NULL)
+    {
+      detail_keys = polkit_details_get_keys (details);
+      if (detail_keys != NULL)
+        {
+          if (g_strv_length (detail_keys) > 0)
+            has_details = TRUE;
+          g_strfreev (detail_keys);
+        }
+    }
+  if (!polkit_identity_equal (user_of_caller, user_of_subject) || has_details)
+    {
+      /* we only allow trusted callers (uid 0 + others) to check authorizations for subjects
+       * they don't own - and only if there are no details passed (to avoid spoofing dialogs).
+       *
+       * TODO: allow other uids like 'haldaemon'?
+       */
+      if (!POLKIT_IS_UNIX_USER (user_of_caller) ||
+          polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_caller)) != 0)
+        {
+          g_simple_async_result_set_error (simple,
+                                           POLKIT_ERROR,
+                                           POLKIT_ERROR_NOT_AUTHORIZED,
+                                           "Only trusted callers can use CheckAuthorization() for subjects "
+                                           "belonging to other identities and/or pass details");
+          g_simple_async_result_complete (simple);
+          g_object_unref (simple);
+          goto out;
+        }
+    }
+
   implicit_authorization = POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED;
   result = check_authorization_sync (authority,
                                      caller,
@@ -571,6 +608,7 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
   gboolean session_is_local;
   gboolean session_is_active;
   PolkitImplicitAuthorization implicit_authorization;
+  const gchar *tmp_authz_id;
 
   interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
   priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
@@ -673,37 +711,19 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
   /* then see if there's a temporary authorization for the subject */
   if (temporary_authorization_store_has_authorization (priv->temporary_authorization_store,
                                                        subject,
-                                                       action_id))
+                                                       action_id,
+                                                       &tmp_authz_id))
     {
-      g_debug (" is authorized (has temporary authorization)");
-      result = polkit_authorization_result_new (TRUE, FALSE, NULL);
-      goto out;
-    }
+      PolkitDetails *details;
 
-#if 0
-  /* then see if we have an authorization for the user */
-  if (check_authorization_for_identity (interactive_authority, user_of_subject, action_id))
-    {
-      g_debug (" is authorized (user identity has authorization)");
-      result = polkit_authorization_result_new (TRUE, FALSE, NULL);
+      g_debug (" is authorized (has temporary authorization)");
+      details = polkit_details_new ();
+      polkit_details_insert (details, "polkit.temporary_authorization_id", tmp_authz_id);
+      result = polkit_authorization_result_new (TRUE, FALSE, details);
+      g_object_unref (details);
       goto out;
     }
 
-  /* then see if we have a permanent authorization for any of the groups the user is in */
-  groups_of_user = get_groups_for_user (interactive_authority, user_of_subject);
-  for (l = groups_of_user; l != NULL; l = l->next)
-    {
-      PolkitIdentity *group = POLKIT_IDENTITY (l->data);
-
-      if (check_authorization_for_identity (interactive_authority, group, action_id))
-        {
-          g_debug (" is authorized (group identity has authorization)");
-          result = polkit_authorization_result_new (TRUE, FALSE, NULL);
-          goto out;
-        }
-    }
-#endif
-
   if (implicit_authorization != POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED)
     {
       result = polkit_authorization_result_new (FALSE, TRUE, NULL);
@@ -1900,7 +1920,8 @@ temporary_authorization_store_free (TemporaryAuthorizationStore *store)
 static gboolean
 temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *store,
                                                  PolkitSubject               *subject,
-                                                 const gchar                 *action_id)
+                                                 const gchar                 *action_id,
+                                                 const gchar                **out_tmp_authz_id)
 {
   GList *l;
   gboolean ret;
@@ -1918,6 +1939,8 @@ temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *st
         polkit_subject_equal (subject, authorization->subject))
       {
         ret = TRUE;
+        if (out_tmp_authz_id != NULL)
+          *out_tmp_authz_id = authorization->id;
         goto out;
       }
   }
@@ -1941,7 +1964,7 @@ on_expiration_timeout (gpointer user_data)
   return FALSE;
 }
 
-static void
+static const gchar *
 temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *store,
                                                  PolkitSubject               *subject,
                                                  PolkitSubject               *session,
@@ -1950,10 +1973,10 @@ temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *st
   TemporaryAuthorization *authorization;
   guint expiration_seconds;
 
-  g_return_if_fail (store != NULL);
-  g_return_if_fail (POLKIT_IS_SUBJECT (subject));
-  g_return_if_fail (action_id != NULL);
-  g_return_if_fail (!temporary_authorization_store_has_authorization (store, subject, action_id));
+  g_return_val_if_fail (store != NULL, NULL);
+  g_return_val_if_fail (POLKIT_IS_SUBJECT (subject), NULL);
+  g_return_val_if_fail (action_id != NULL, NULL);
+  g_return_val_if_fail (!temporary_authorization_store_has_authorization (store, subject, action_id, NULL), NULL);
 
   /* TODO: right now this is hard-coded - we could make it a propery on the
    *       PolkitBackendInteractiveAuthority class. Or we could even read
@@ -1974,6 +1997,8 @@ temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *st
                                                         authorization);
 
   store->authorizations = g_list_prepend (store->authorizations, authorization);
+
+  return authorization->id;
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -2131,3 +2156,85 @@ polkit_backend_interactive_authority_revoke_temporary_authorizations (PolkitBack
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+polkit_backend_interactive_authority_revoke_temporary_authorization_by_id (PolkitBackendAuthority   *authority,
+                                                                           PolkitSubject            *caller,
+                                                                           const gchar              *id,
+                                                                           GError                  **error)
+{
+  PolkitBackendInteractiveAuthority *interactive_authority;
+  PolkitBackendInteractiveAuthorityPrivate *priv;
+  PolkitSubject *session_for_caller;
+  gboolean ret;
+  GList *l;
+  GList *ll;
+  guint num_removed;
+
+  interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
+  priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
+
+  ret = FALSE;
+  session_for_caller = NULL;
+
+  session_for_caller = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor,
+                                                                               caller,
+                                                                               NULL);
+  if (session_for_caller == NULL)
+    {
+      g_set_error (error,
+                   POLKIT_ERROR,
+                   POLKIT_ERROR_FAILED,
+                   "Cannot determine session the caller is in");
+      goto out;
+    }
+
+  num_removed = 0;
+  for (l = priv->temporary_authorization_store->authorizations; l != NULL; l = ll)
+    {
+      TemporaryAuthorization *ta = l->data;
+
+      ll = l->next;
+
+      if (strcmp (ta->id, id) != 0)
+        continue;
+
+      if (!polkit_subject_equal (session_for_caller, ta->session))
+        {
+          g_set_error (error,
+                       POLKIT_ERROR,
+                       POLKIT_ERROR_FAILED,
+                       "Cannot remove a temporary authorization belonging to another subject.");
+          goto out;
+        }
+
+      priv->temporary_authorization_store->authorizations = g_list_remove (priv->temporary_authorization_store->authorizations, ta);
+      temporary_authorization_free (ta);
+
+      num_removed++;
+    }
+
+  if (num_removed > 0)
+    {
+      g_signal_emit_by_name (authority, "changed");
+    }
+  else
+    {
+      g_set_error (error,
+                   POLKIT_ERROR,
+                   POLKIT_ERROR_FAILED,
+                   "No such authorization with id `%s'",
+                   id);
+      goto out;
+    }
+
+  ret = TRUE;
+
+ out:
+  if (session_for_caller != NULL)
+    g_object_unref (session_for_caller);
+
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c
index 06073cf..e100c56 100644
--- a/src/polkitbackend/polkitbackendlocalauthority.c
+++ b/src/polkitbackend/polkitbackendlocalauthority.c
@@ -95,6 +95,15 @@ G_DEFINE_TYPE_WITH_CODE (PolkitBackendLocalAuthority,
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
+on_store_changed (PolkitBackendLocalAuthorizationStore *store,
+                  gpointer                              user_data)
+{
+  PolkitBackendLocalAuthority *authority = POLKIT_BACKEND_LOCAL_AUTHORITY (user_data);
+
+  g_signal_emit_by_name (authority, "changed");
+}
+
+static void
 polkit_backend_local_authority_init (PolkitBackendLocalAuthority *authority)
 {
   PolkitBackendLocalAuthorityPrivate *priv;
@@ -124,6 +133,11 @@ polkit_backend_local_authority_init (PolkitBackendLocalAuthority *authority)
       store = polkit_backend_local_authorization_store_new (directory, ".pkla");
       priv->authorization_stores = g_list_prepend (priv->authorization_stores, store);
       g_object_unref (directory);
+
+      g_signal_connect (store,
+                        "changed",
+                        G_CALLBACK (on_store_changed),
+                        authority);
     }
   priv->authorization_stores = g_list_reverse (priv->authorization_stores);
 }


More information about the hal-commit mailing list