PolicyKit: Branch 'master' - 3 commits

David Zeuthen david at kemper.freedesktop.org
Wed Aug 12 09:00:24 PDT 2009


 src/polkit/polkitunixprocess.c                        |    7 
 src/polkitbackend/polkitbackendauthority.c            |    2 
 src/polkitbackend/polkitbackendinteractiveauthority.c |  150 +++++++++++++++++-
 src/polkitbackend/polkitbackendsessionmonitor.c       |   37 ++++
 4 files changed, 186 insertions(+), 10 deletions(-)

New commits:
commit f1e312653c7c7d3eafcfb6a55b884faa19e5ea5d
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed Aug 12 11:52:46 2009 -0400

    Remove temporary authorization when the subject it applies to vanishes
    
    This makes it easier to write the desktop component showing a
    notification icon - said component now only needs to watch ::changed
    and reenumerate temporary authorizations. If this is done, then the
    notification icon is updated in near-realtime.
    
    Also emit ::changed on ConsoleKit changes. This helps remind
    Mechanisms that they should redo an authorization check (if this is
    how the Mechanism decides to cache authorizations).

diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
index c5cf4d2..811d169 100644
--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
@@ -63,6 +63,9 @@ static const gchar *temporary_authorization_store_add_authorization (TemporaryAu
                                                                      PolkitSubject               *session,
                                                                      const gchar                 *action_id);
 
+static void temporary_authorization_store_remove_authorizations_for_system_bus_name (TemporaryAuthorizationStore *store,
+                                                                                     const gchar *name);
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 struct AuthenticationAgent;
@@ -214,6 +217,14 @@ action_pool_changed (PolkitBackendActionPool *action_pool,
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
+on_session_monitor_changed (PolkitBackendSessionMonitor *monitor,
+                            gpointer                     user_data)
+{
+  PolkitBackendInteractiveAuthority *authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (user_data);
+  g_signal_emit_by_name (authority, "changed");
+}
+
+static void
 polkit_backend_interactive_authority_init (PolkitBackendInteractiveAuthority *authority)
 {
   PolkitBackendInteractiveAuthorityPrivate *priv;
@@ -237,6 +248,10 @@ polkit_backend_interactive_authority_init (PolkitBackendInteractiveAuthority *au
                                                                       (GDestroyNotify) authentication_agent_free);
 
   priv->session_monitor = polkit_backend_session_monitor_new ();
+  g_signal_connect (priv->session_monitor,
+                    "changed",
+                    G_CALLBACK (on_session_monitor_changed),
+                    authority);
 }
 
 static void
@@ -1868,6 +1883,12 @@ polkit_backend_interactive_authority_system_bus_name_owner_changed (PolkitBacken
         }
       g_list_free (sessions);
 
+      /* remove all temporary authorizations that applies to the vanished name
+       * (temporary_authorization_store_add_authorization for the code path for handling processes)
+       */
+      temporary_authorization_store_remove_authorizations_for_system_bus_name (priv->temporary_authorization_store,
+                                                                               name);
+
     }
 
 }
@@ -1893,6 +1914,7 @@ struct TemporaryAuthorization
   guint64 time_granted;
   guint64 time_expires;
   guint expiration_timeout_id;
+  guint check_vanished_timeout_id;
 };
 
 static void
@@ -1904,6 +1926,8 @@ temporary_authorization_free (TemporaryAuthorization *authorization)
   g_free (authorization->action_id);
   if (authorization->expiration_timeout_id > 0)
     g_source_remove (authorization->expiration_timeout_id);
+  if (authorization->check_vanished_timeout_id > 0)
+    g_source_remove (authorization->check_vanished_timeout_id);
   g_free (authorization);
 }
 
@@ -1963,6 +1987,15 @@ static gboolean
 on_expiration_timeout (gpointer user_data)
 {
   TemporaryAuthorization *authorization = user_data;
+  gchar *s;
+
+  s = polkit_subject_to_string (authorization->subject);
+  g_debug ("Removing tempoary authorization with id `%s' for action-id `%s' for subject `%s': "
+           "authorization has expired",
+           authorization->id,
+           authorization->action_id,
+           s);
+  g_free (s);
 
   authorization->store->authorizations = g_list_remove (authorization->store->authorizations,
                                                         authorization);
@@ -1974,6 +2007,86 @@ on_expiration_timeout (gpointer user_data)
   return FALSE;
 }
 
+static gboolean
+on_unix_process_check_vanished_timeout (gpointer user_data)
+{
+  TemporaryAuthorization *authorization = user_data;
+  GError *error;
+
+  /* we know that this is a PolkitUnixProcess so the check is fast (no IPC involved) */
+  error = NULL;
+  if (!polkit_subject_exists_sync (authorization->subject,
+                                   NULL,
+                                   &error))
+    {
+      if (error != NULL)
+        {
+          g_warning ("Error checking if process exists: %s", error->message);
+          g_error_free (error);
+        }
+      else
+        {
+          gchar *s;
+
+          s = polkit_subject_to_string (authorization->subject);
+          g_debug ("Removing tempoary authorization with id `%s' for action-id `%s' for subject `%s': "
+                   "subject has vanished",
+                   authorization->id,
+                   authorization->action_id,
+                   s);
+          g_free (s);
+
+          authorization->store->authorizations = g_list_remove (authorization->store->authorizations,
+                                                                authorization);
+          g_signal_emit_by_name (authorization->store->authority, "changed");
+          temporary_authorization_free (authorization);
+        }
+    }
+
+  /* keep source around */
+  return TRUE;
+}
+
+static void
+temporary_authorization_store_remove_authorizations_for_system_bus_name (TemporaryAuthorizationStore *store,
+                                                                         const gchar *name)
+{
+  guint num_removed;
+  GList *l, *ll;
+
+  num_removed = 0;
+  for (l = store->authorizations; l != NULL; l = ll)
+    {
+      TemporaryAuthorization *ta = l->data;
+      gchar *s;
+
+      ll = l->next;
+
+      if (!POLKIT_IS_SYSTEM_BUS_NAME (ta->subject))
+        continue;
+
+      if (g_strcmp0 (name, polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (ta->subject))) != 0)
+        continue;
+
+
+      s = polkit_subject_to_string (ta->subject);
+      g_debug ("Removing tempoary authorization with id `%s' for action-id `%s' for subject `%s': "
+               "subject has vanished",
+               ta->id,
+               ta->action_id,
+               s);
+      g_free (s);
+
+      store->authorizations = g_list_remove (store->authorizations, ta);
+      temporary_authorization_free (ta);
+
+      num_removed++;
+    }
+
+  if (num_removed > 0)
+    g_signal_emit_by_name (store->authority, "changed");
+}
+
 static const gchar *
 temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *store,
                                                  PolkitSubject               *subject,
@@ -1988,9 +2101,10 @@ temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *st
   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
-   *       it per action from an annotation.
+  /* TODO: right now the time the temporary authorization is kept is hard-coded - we
+   *       could make it a propery on the PolkitBackendInteractiveAuthority class (so
+   *       the local authority could read it from a config file) or a vfunc
+   *       (so the local authority could read it from an annotation on the action).
    */
   expiration_seconds = 5 * 60;
 
@@ -2006,6 +2120,36 @@ temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *st
                                                         on_expiration_timeout,
                                                         authorization);
 
+  if (POLKIT_IS_UNIX_PROCESS (authorization->subject))
+    {
+      /* For now, set up a timer to poll every two seconds - this is used to determine
+       * when the process vanishes. We want to do this so we can remove the temporary
+       * authorization - this is because we want agents to update e.g. a notification
+       * area icon saying the user has temporary authorizations (e.g. remove the icon).
+       *
+       * Ideally we'd just do
+       *
+       *   g_signal_connect (kernel, "process-exited", G_CALLBACK (on_process_exited), user_data);
+       *
+       * but that is not how things work right now (and, hey, it's not like the kernel
+       * is a GObject either!) - so we poll.
+       *
+       * TODO: On Linux, it might be possible to obtain notifications by connecting
+       *       to the netlink socket. Needs looking into.
+       */
+
+      authorization->check_vanished_timeout_id = g_timeout_add_seconds (2,
+                                                                        on_unix_process_check_vanished_timeout,
+                                                                        authorization);
+    }
+#if 0
+  else if (POLKIT_IS_SYSTEM_BUS_NAME (authorization->subject))
+    {
+      /* This is currently handled in polkit_backend_interactive_authority_system_bus_name_owner_changed()  */
+    }
+#endif
+
+
   store->authorizations = g_list_prepend (store->authorizations, authorization);
 
   return authorization->id;
diff --git a/src/polkitbackend/polkitbackendsessionmonitor.c b/src/polkitbackend/polkitbackendsessionmonitor.c
index eca8bd8..ecdd6a6 100644
--- a/src/polkitbackend/polkitbackendsessionmonitor.c
+++ b/src/polkitbackend/polkitbackendsessionmonitor.c
@@ -55,8 +55,18 @@ struct _PolkitBackendSessionMonitorClass
 {
   GObjectClass parent_class;
 
+  void (*changed) (PolkitBackendSessionMonitor *monitor);
 };
 
+
+enum
+{
+  CHANGED_SIGNAL,
+  LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
 static void seat_session_added (CkSeat      *seat,
                                 const gchar *object_path,
                                 gpointer     user_data);
@@ -154,6 +164,8 @@ manager_seat_added (CkManager   *manager,
   //g_debug ("seat %s added", object_path);
 
   add_seat (monitor, object_path);
+
+  g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
 }
 
 static void
@@ -166,6 +178,8 @@ manager_seat_removed (CkManager   *manager,
   //g_debug ("seat %s removed", object_path);
 
   remove_seat (monitor, object_path);
+
+  g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
 }
 
 static void
@@ -178,6 +192,8 @@ seat_session_added (CkSeat      *seat,
   //g_debug ("session %s added", object_path);
 
   add_session (monitor, object_path);
+
+  g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
 }
 
 static void
@@ -190,6 +206,8 @@ seat_session_removed (CkSeat      *seat,
   //g_debug ("session %s removed", object_path);
 
   remove_session (monitor, object_path);
+
+  g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
 }
 
 static void
@@ -197,6 +215,7 @@ session_active_changed (CkSession   *session,
                         gboolean     is_active,
                         gpointer     user_data)
 {
+  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
   EggDBusObjectProxy *object_proxy;
 
   object_proxy = egg_dbus_interface_proxy_get_object_proxy (EGG_DBUS_INTERFACE_PROXY (session));
@@ -204,6 +223,8 @@ session_active_changed (CkSession   *session,
   //g_debug ("session %s active changed to %d", egg_dbus_object_proxy_get_object_path (object_proxy), is_active);
 
   egg_dbus_object_proxy_invalidate_properties (object_proxy);
+
+  g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -307,6 +328,22 @@ polkit_backend_session_monitor_class_init (PolkitBackendSessionMonitorClass *kla
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->finalize = polkit_backend_session_monitor_finalize;
+
+  /**
+   * PolkitBackendSessionMonitor::changed:
+   * @monitor: A #PolkitBackendSessionMonitor
+   *
+   * Emitted when something changes.
+   */
+  signals[CHANGED_SIGNAL] = g_signal_new ("changed",
+                                          POLKIT_BACKEND_TYPE_SESSION_MONITOR,
+                                          G_SIGNAL_RUN_LAST,
+                                          G_STRUCT_OFFSET (PolkitBackendSessionMonitorClass, changed),
+                                          NULL,                   /* accumulator      */
+                                          NULL,                   /* accumulator data */
+                                          g_cclosure_marshal_VOID__VOID,
+                                          G_TYPE_NONE,
+                                          0);
 }
 
 PolkitBackendSessionMonitor *
commit 6806b4883077745c3f288cfe679181a61849f97f
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed Aug 12 11:51:52 2009 -0400

    Don't set the GError if the process doesn't exist

diff --git a/src/polkit/polkitunixprocess.c b/src/polkit/polkitunixprocess.c
index a3813c2..d559a4f 100644
--- a/src/polkit/polkitunixprocess.c
+++ b/src/polkit/polkitunixprocess.c
@@ -354,7 +354,7 @@ polkit_unix_process_exists_sync (PolkitSubject   *subject,
   start_time = get_start_time_for_pid (process->pid, &local_error);
   if (local_error != NULL)
     {
-      g_propagate_error (error, local_error);
+      /* Don't propagate the error - it just means there is no process with this pid */
       g_error_free (local_error);
       ret = FALSE;
     }
@@ -363,11 +363,6 @@ polkit_unix_process_exists_sync (PolkitSubject   *subject,
       if (start_time != process->start_time)
         {
           ret = FALSE;
-          g_set_error (error,
-                       POLKIT_ERROR,
-                       POLKIT_ERROR_FAILED,
-                       "Start times for pid %d do not match",
-                       (gint) process->pid);
         }
     }
 
commit f207e4f204a303269e94417ec7247570dd527786
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed Aug 12 11:51:14 2009 -0400

    Pass the right struct offset for the ::changed class signal handler

diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
index 63caf0f..28731af 100644
--- a/src/polkitbackend/polkitbackendauthority.c
+++ b/src/polkitbackend/polkitbackendauthority.c
@@ -71,7 +71,7 @@ polkit_backend_authority_class_init (PolkitBackendAuthorityClass *klass)
   signals[CHANGED_SIGNAL] = g_signal_new ("changed",
                                           POLKIT_BACKEND_TYPE_AUTHORITY,
                                           G_SIGNAL_RUN_LAST,
-                                          0,                      /* class offset     */
+                                          G_STRUCT_OFFSET (PolkitBackendAuthorityClass, changed),
                                           NULL,                   /* accumulator      */
                                           NULL,                   /* accumulator data */
                                           g_cclosure_marshal_VOID__VOID,


More information about the hal-commit mailing list