Blob Blame History Raw
From 781e865705b0c134271c9ec21655cd5d8ce37fec Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sat, 14 Dec 2019 13:50:53 -0500
Subject: [PATCH] display: ask accountservice if there are users rather than
 enumerate users

At the moment we ask accountsservice to give us the list of users just
to find out if there is a list of users.

That's rather inefficient and might be wrong for directory server users
that have never logged in before.

This commit changes gdm to ask accountsservice the question we really
want to know the answer to; whether or not there are users.
---
 daemon/gdm-display.c | 55 ++++++++++++++++++--------------------------
 1 file changed, 22 insertions(+), 33 deletions(-)

diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 878be88da..875534272 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -57,62 +57,60 @@
 struct GdmDisplayPrivate
 {
         char                 *id;
         char                 *seat_id;
         char                 *session_id;
         char                 *session_class;
         char                 *session_type;
 
         char                 *remote_hostname;
         int                   x11_display_number;
         char                 *x11_display_name;
         int                   status;
         time_t                creation_time;
         GTimer               *server_timer;
 
         char                 *x11_cookie;
         gsize                 x11_cookie_size;
         GdmDisplayAccessFile *access_file;
 
         guint                 finish_idle_id;
 
         xcb_connection_t     *xcb_connection;
         int                   xcb_screen_number;
 
         GDBusConnection      *connection;
         GdmDisplayAccessFile *user_access_file;
 
         GdmDBusDisplay       *display_skeleton;
         GDBusObjectSkeleton  *object_skeleton;
 
-        GDBusProxy           *accountsservice_proxy;
-
         /* this spawns and controls the greeter session */
         GdmLaunchEnvironment *launch_environment;
 
         guint                 is_local : 1;
         guint                 is_initial : 1;
         guint                 allow_timed_login : 1;
         guint                 have_existing_user_accounts : 1;
         guint                 doing_initial_setup : 1;
 };
 
 enum {
         PROP_0,
         PROP_ID,
         PROP_STATUS,
         PROP_SEAT_ID,
         PROP_SESSION_ID,
         PROP_SESSION_CLASS,
         PROP_SESSION_TYPE,
         PROP_REMOTE_HOSTNAME,
         PROP_X11_DISPLAY_NUMBER,
         PROP_X11_DISPLAY_NAME,
         PROP_X11_COOKIE,
         PROP_X11_AUTHORITY_FILE,
         PROP_IS_CONNECTED,
         PROP_IS_LOCAL,
         PROP_LAUNCH_ENVIRONMENT,
         PROP_IS_INITIAL,
         PROP_ALLOW_TIMED_LOGIN,
         PROP_HAVE_EXISTING_USER_ACCOUNTS,
         PROP_DOING_INITIAL_SETUP,
@@ -512,96 +510,88 @@ queue_finish (GdmDisplay *self)
         if (self->priv->finish_idle_id == 0) {
                 self->priv->finish_idle_id = g_idle_add ((GSourceFunc)finish_idle, self);
         }
 }
 
 static void
 _gdm_display_set_status (GdmDisplay *self,
                          int         status)
 {
         if (status != self->priv->status) {
                 self->priv->status = status;
                 g_object_notify (G_OBJECT (self), "status");
         }
 }
 
 static gboolean
 gdm_display_real_prepare (GdmDisplay *self)
 {
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
 
         g_debug ("GdmDisplay: prepare display");
 
         _gdm_display_set_status (self, GDM_DISPLAY_PREPARED);
 
         return TRUE;
 }
 
 static void
 look_for_existing_users_sync (GdmDisplay *self)
 {
-        GError *error = NULL;
-        GVariant *call_result;
-        GVariant *user_list;
-
-        self->priv->accountsservice_proxy = g_dbus_proxy_new_sync (self->priv->connection,
-                                                                   0, NULL,
-                                                                   "org.freedesktop.Accounts",
-                                                                   "/org/freedesktop/Accounts",
-                                                                   "org.freedesktop.Accounts",
-                                                                   NULL,
-                                                                   &error);
-
-        if (!self->priv->accountsservice_proxy) {
-                g_warning ("Failed to contact accountsservice: %s", error->message);
-                goto out;
-        }
-
-        call_result = g_dbus_proxy_call_sync (self->priv->accountsservice_proxy,
-                                              "ListCachedUsers",
-                                              NULL,
-                                              0,
+        g_autoptr (GVariant) result = NULL;
+        g_autoptr (GVariant) result_child = NULL;
+        g_autoptr (GError) error = NULL;
+        gboolean has_no_users = FALSE;
+
+        result = g_dbus_connection_call_sync (self->priv->connection,
+                                              "org.freedesktop.Accounts",
+                                              "/org/freedesktop/Accounts",
+                                              "org.freedesktop.DBus.Properties",
+                                              "Get",
+                                              g_variant_new ("(ss)", "org.freedesktop.Accounts", "HasNoUsers"),
+                                              G_VARIANT_TYPE ("(v)"),
+                                              G_DBUS_CALL_FLAGS_NONE,
                                               -1,
                                               NULL,
                                               &error);
 
-        if (!call_result) {
-                g_warning ("Failed to list cached users: %s", error->message);
-                goto out;
+        if (result == NULL) {
+                g_warning ("Failed to contact accountsservice: %s", error->message);
+                return;
         }
 
-        g_variant_get (call_result, "(@ao)", &user_list);
-        self->priv->have_existing_user_accounts = g_variant_n_children (user_list) > 0;
-        g_variant_unref (user_list);
-        g_variant_unref (call_result);
-out:
-        g_clear_error (&error);
+        g_variant_get (result, "(v)", &result_child);
+        has_no_users = g_variant_get_boolean (result_child);
+        self->priv->have_existing_user_accounts = !has_no_users;
+
+        g_debug ("GdmDisplay: machine does %shave existing user accounts",
+                 has_no_users? "not " : "");
 }
 
 gboolean
 gdm_display_prepare (GdmDisplay *self)
 {
         gboolean ret;
 
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
 
         g_debug ("GdmDisplay: Preparing display: %s", self->priv->id);
 
         /* FIXME: we should probably do this in a more global place,
          * asynchronously
          */
         look_for_existing_users_sync (self);
 
         self->priv->doing_initial_setup = wants_initial_setup (self);
 
         g_object_ref (self);
         ret = GDM_DISPLAY_GET_CLASS (self)->prepare (self);
         g_object_unref (self);
 
         return ret;
 }
 
 gboolean
 gdm_display_manage (GdmDisplay *self)
 {
         gboolean res;
 
@@ -1332,61 +1322,60 @@ gdm_display_init (GdmDisplay *self)
 
         self->priv = GDM_DISPLAY_GET_PRIVATE (self);
 
         self->priv->creation_time = time (NULL);
         self->priv->server_timer = g_timer_new ();
 }
 
 static void
 gdm_display_finalize (GObject *object)
 {
         GdmDisplay *self;
 
         g_return_if_fail (object != NULL);
         g_return_if_fail (GDM_IS_DISPLAY (object));
 
         self = GDM_DISPLAY (object);
 
         g_return_if_fail (self->priv != NULL);
 
         g_debug ("GdmDisplay: Finalizing display: %s", self->priv->id);
         g_free (self->priv->id);
         g_free (self->priv->seat_id);
         g_free (self->priv->session_class);
         g_free (self->priv->remote_hostname);
         g_free (self->priv->x11_display_name);
         g_free (self->priv->x11_cookie);
 
         g_clear_object (&self->priv->display_skeleton);
         g_clear_object (&self->priv->object_skeleton);
         g_clear_object (&self->priv->connection);
-        g_clear_object (&self->priv->accountsservice_proxy);
 
         if (self->priv->access_file != NULL) {
                 g_object_unref (self->priv->access_file);
         }
 
         if (self->priv->user_access_file != NULL) {
                 g_object_unref (self->priv->user_access_file);
         }
 
         if (self->priv->server_timer != NULL) {
                 g_timer_destroy (self->priv->server_timer);
         }
 
         G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object);
 }
 
 GDBusObjectSkeleton *
 gdm_display_get_object_skeleton (GdmDisplay *self)
 {
         return self->priv->object_skeleton;
 }
 
 static void
 on_launch_environment_session_opened (GdmLaunchEnvironment *launch_environment,
                                       GdmDisplay           *self)
 {
         char       *session_id;
 
         g_debug ("GdmDisplay: Greeter session opened");
         session_id = gdm_launch_environment_get_session_id (launch_environment);
-- 
2.21.0