Blame SOURCES/0001-daemon-Allow-SystemAccount-false-to-be-set-in-cache-.patch

c6c770
From 14c902f42a4ea74ce9450eb53817e1bf5be05d26 Mon Sep 17 00:00:00 2001
c6c770
From: Ray Strode <rstrode@redhat.com>
c6c770
Date: Wed, 8 Sep 2021 16:38:17 -0400
c6c770
Subject: [PATCH 1/2] daemon: Allow SystemAccount=false to be set in cache file
c6c770
c6c770
At the moment we do dodgy checks based on uid to decide whether or not
c6c770
an account is a system account.
c6c770
c6c770
For legacy reasons, sometimes normal users have really low UIDs.
c6c770
c6c770
This commit reshuffles things, so the cache file "wins" for deciding
c6c770
whether or not a user is a system user.
c6c770
---
c6c770
 src/daemon.c | 24 ++++++++++++------------
c6c770
 1 file changed, 12 insertions(+), 12 deletions(-)
c6c770
c6c770
diff --git a/src/daemon.c b/src/daemon.c
c6c770
index 66ac7ba..2b6650b 100644
c6c770
--- a/src/daemon.c
c6c770
+++ b/src/daemon.c
c6c770
@@ -219,60 +219,68 @@ entry_generator_fgetpwent (Daemon       *daemon,
c6c770
                 if (g_hash_table_size (shadow_users) == 0) {
c6c770
                         g_clear_pointer (&shadow_users, g_hash_table_unref);
c6c770
                         return NULL;
c6c770
                 }
c6c770
 
c6c770
                 fp = fopen (PATH_PASSWD, "r");
c6c770
                 if (fp == NULL) {
c6c770
                         g_clear_pointer (&shadow_users, g_hash_table_unref);
c6c770
                         g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno));
c6c770
                         return NULL;
c6c770
                 }
c6c770
 
c6c770
                 generator_state = g_malloc0 (sizeof (*generator_state));
c6c770
                 generator_state->fp = fp;
c6c770
                 generator_state->users = shadow_users;
c6c770
 
c6c770
                 *state = generator_state;
c6c770
         }
c6c770
 
c6c770
         /* Every iteration */
c6c770
         generator_state = *state;
c6c770
 
c6c770
         if (g_hash_table_size (users) < MAX_LOCAL_USERS) {
c6c770
                 pwent = fgetpwent (generator_state->fp);
c6c770
                 if (pwent != NULL) {
c6c770
                         shadow_entry_buffers = g_hash_table_lookup (generator_state->users, pwent->pw_name);
c6c770
 
c6c770
                         if (shadow_entry_buffers != NULL) {
c6c770
                             *spent = &shadow_entry_buffers->spbuf;
c6c770
                         }
c6c770
+
c6c770
+                        /* Skip system users... */
c6c770
+                        if (!user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, (*spent)? (*spent)->sp_pwdp : NULL)) {
c6c770
+                                g_debug ("skipping user: %s", pwent->pw_name);
c6c770
+
c6c770
+                                return entry_generator_fgetpwent (daemon, users, state, spent);
c6c770
+                        }
c6c770
+
c6c770
                         return pwent;
c6c770
                 }
c6c770
         }
c6c770
 
c6c770
         /* Last iteration */
c6c770
         fclose (generator_state->fp);
c6c770
         g_hash_table_unref (generator_state->users);
c6c770
         g_free (generator_state);
c6c770
         *state = NULL;
c6c770
 
c6c770
         return NULL;
c6c770
 }
c6c770
 
c6c770
 static struct passwd *
c6c770
 entry_generator_cachedir (Daemon       *daemon,
c6c770
                           GHashTable   *users,
c6c770
                           gpointer     *state,
c6c770
                           struct spwd **shadow_entry)
c6c770
 {
c6c770
         struct passwd *pwent;
c6c770
         g_autoptr(GError) error = NULL;
c6c770
         gboolean regular;
c6c770
         GHashTableIter iter;
c6c770
         gpointer key, value;
c6c770
         GDir *dir;
c6c770
 
c6c770
         /* First iteration */
c6c770
         if (*state == NULL) {
c6c770
                 *state = g_dir_open (USERDIR, 0, &error);
c6c770
                 if (error != NULL) {
c6c770
@@ -373,66 +381,60 @@ entry_generator_requested_users (Daemon       *daemon,
c6c770
                         }
c6c770
                 }
c6c770
         }
c6c770
 
c6c770
         /* Last iteration */
c6c770
 
c6c770
         *state = NULL;
c6c770
         return NULL;
c6c770
 }
c6c770
 
c6c770
 static void
c6c770
 load_entries (Daemon             *daemon,
c6c770
               GHashTable         *users,
c6c770
               gboolean            explicitly_requested,
c6c770
               EntryGeneratorFunc  entry_generator)
c6c770
 {
c6c770
         DaemonPrivate *priv = daemon_get_instance_private (daemon);
c6c770
         gpointer generator_state = NULL;
c6c770
         struct passwd *pwent;
c6c770
         struct spwd *spent = NULL;
c6c770
         User *user = NULL;
c6c770
 
c6c770
         g_assert (entry_generator != NULL);
c6c770
 
c6c770
         for (;;) {
c6c770
                 spent = NULL;
c6c770
                 pwent = entry_generator (daemon, users, &generator_state, &spent);
c6c770
                 if (pwent == NULL)
c6c770
                         break;
c6c770
 
c6c770
-                /* Skip system users... */
c6c770
-                if (!explicitly_requested && !user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, spent? spent->sp_pwdp : NULL)) {
c6c770
-                        g_debug ("skipping user: %s", pwent->pw_name);
c6c770
-                        continue;
c6c770
-                }
c6c770
-
c6c770
                 /* Only process users that haven't been processed yet.
c6c770
                  * We do always make sure entries get promoted
c6c770
                  * to "cached" status if they are supposed to be
c6c770
                  */
c6c770
 
c6c770
                 user = g_hash_table_lookup (users, pwent->pw_name);
c6c770
 
c6c770
                 if (user == NULL) {
c6c770
                         user = g_hash_table_lookup (priv->users, pwent->pw_name);
c6c770
                         if (user == NULL) {
c6c770
                                 user = user_new (daemon, pwent->pw_uid);
c6c770
                         } else {
c6c770
                                 g_object_ref (user);
c6c770
                         }
c6c770
 
c6c770
                         /* freeze & update users not already in the new list */
c6c770
                         g_object_freeze_notify (G_OBJECT (user));
c6c770
                         user_update_from_pwent (user, pwent, spent);
c6c770
 
c6c770
                         g_hash_table_insert (users, g_strdup (user_get_user_name (user)), user);
c6c770
                         g_debug ("loaded user: %s", user_get_user_name (user));
c6c770
                 }
c6c770
 
c6c770
                 if (!explicitly_requested) {
c6c770
                         user_set_cached (user, TRUE);
c6c770
                 }
c6c770
         }
c6c770
 
c6c770
         /* Generator should have cleaned up */
c6c770
         g_assert (generator_state == NULL);
c6c770
@@ -501,66 +503,66 @@ has_network_realms (Daemon *daemon)
c6c770
 
c6c770
 static void
c6c770
 reload_users (Daemon *daemon)
c6c770
 {
c6c770
         DaemonPrivate *priv = daemon_get_instance_private (daemon);
c6c770
         AccountsAccounts *accounts = ACCOUNTS_ACCOUNTS (daemon);
c6c770
         gboolean had_no_users, has_no_users, had_multiple_users, has_multiple_users;
c6c770
         GHashTable *users;
c6c770
         GHashTable *old_users;
c6c770
         GHashTable *local;
c6c770
         GHashTableIter iter;
c6c770
         gsize number_of_normal_users = 0;
c6c770
         gpointer name, value;
c6c770
 
c6c770
         /* Track the users that we saw during our (re)load */
c6c770
         users = create_users_hash_table ();
c6c770
 
c6c770
         /*
c6c770
          * NOTE: As we load data from all the sources, notifies are
c6c770
          * frozen in load_entries() and then thawed as we process
c6c770
          * them below.
c6c770
          */
c6c770
 
c6c770
         /* Load the local users into our hash table */
c6c770
         load_entries (daemon, users, FALSE, entry_generator_fgetpwent);
c6c770
         local = g_hash_table_new (g_str_hash, g_str_equal);
c6c770
         g_hash_table_iter_init (&iter, users);
c6c770
         while (g_hash_table_iter_next (&iter, &name, NULL))
c6c770
                 g_hash_table_add (local, name);
c6c770
 
c6c770
-        /* and add users to hash table that were explicitly requested  */
c6c770
-        load_entries (daemon, users, TRUE, entry_generator_requested_users);
c6c770
-
c6c770
         /* Now add/update users from other sources, possibly non-local */
c6c770
         load_entries (daemon, users, FALSE, entry_generator_cachedir);
c6c770
 
c6c770
+        /* and add users to hash table that were explicitly requested  */
c6c770
+        load_entries (daemon, users, TRUE, entry_generator_requested_users);
c6c770
+
c6c770
         wtmp_helper_update_login_frequencies (users);
c6c770
 
c6c770
         /* Count the non-system users. Mark which users are local, which are not. */
c6c770
         g_hash_table_iter_init (&iter, users);
c6c770
         while (g_hash_table_iter_next (&iter, &name, &value)) {
c6c770
                 User *user = value;
c6c770
                 if (!user_get_system_account (user))
c6c770
                         number_of_normal_users++;
c6c770
                 user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL);
c6c770
         }
c6c770
         g_hash_table_destroy (local);
c6c770
 
c6c770
         had_no_users = accounts_accounts_get_has_no_users (accounts);
c6c770
         has_no_users = number_of_normal_users == 0;
c6c770
 
c6c770
         if (has_no_users && has_network_realms (daemon)) {
c6c770
                 g_debug ("No local users, but network realms detected, presuming there are remote users");
c6c770
                 has_no_users = FALSE;
c6c770
         }
c6c770
 
c6c770
         if (had_no_users != has_no_users)
c6c770
                 accounts_accounts_set_has_no_users (accounts, has_no_users);
c6c770
 
c6c770
         had_multiple_users = accounts_accounts_get_has_multiple_users (accounts);
c6c770
         has_multiple_users = number_of_normal_users > 1;
c6c770
 
c6c770
         if (had_multiple_users != has_multiple_users)
c6c770
                 accounts_accounts_set_has_multiple_users (accounts, has_multiple_users);
c6c770
 
c6c770
         /* Swap out the users */
c6c770
@@ -1017,73 +1019,71 @@ daemon_find_user_by_name (AccountsAccounts      *accounts,
c6c770
 
c6c770
 static ListUserData *
c6c770
 list_user_data_new (Daemon                *daemon,
c6c770
                     GDBusMethodInvocation *context)
c6c770
 {
c6c770
         ListUserData *data;
c6c770
 
c6c770
         data = g_new0 (ListUserData, 1);
c6c770
 
c6c770
         data->daemon = g_object_ref (daemon);
c6c770
         data->context = context;
c6c770
 
c6c770
         return data;
c6c770
 }
c6c770
 
c6c770
 static void
c6c770
 list_user_data_free (ListUserData *data)
c6c770
 {
c6c770
         g_object_unref (data->daemon);
c6c770
         g_free (data);
c6c770
 }
c6c770
 
c6c770
 static void
c6c770
 finish_list_cached_users (ListUserData *data)
c6c770
 {
c6c770
         DaemonPrivate *priv = daemon_get_instance_private (data->daemon);
c6c770
         g_autoptr(GPtrArray) object_paths = NULL;
c6c770
         GHashTableIter iter;
c6c770
         gpointer key, value;
c6c770
         uid_t uid;
c6c770
-        const gchar *shell;
c6c770
 
c6c770
         object_paths = g_ptr_array_new ();
c6c770
 
c6c770
         g_hash_table_iter_init (&iter, priv->users);
c6c770
         while (g_hash_table_iter_next (&iter, &key, &value)) {
c6c770
                 const gchar *name = key;
c6c770
                 User *user = value;
c6c770
 
c6c770
                 uid = user_get_uid (user);
c6c770
-                shell = user_get_shell (user);
c6c770
 
c6c770
-                if (!user_classify_is_human (uid, name, shell, NULL)) {
c6c770
+                if (user_get_system_account (user)) {
c6c770
                         g_debug ("user %s %ld excluded", name, (long) uid);
c6c770
                         continue;
c6c770
                 }
c6c770
 
c6c770
                 if (!user_get_cached (user)) {
c6c770
                         g_debug ("user %s %ld not cached", name, (long) uid);
c6c770
                         continue;
c6c770
                 }
c6c770
 
c6c770
                 g_debug ("user %s %ld not excluded", name, (long) uid);
c6c770
                 g_ptr_array_add (object_paths, (gpointer) user_get_object_path (user));
c6c770
         }
c6c770
         g_ptr_array_add (object_paths, NULL);
c6c770
 
c6c770
         accounts_accounts_complete_list_cached_users (NULL, data->context, (const gchar * const *) object_paths->pdata);
c6c770
 
c6c770
         list_user_data_free (data);
c6c770
 }
c6c770
 
c6c770
 static gboolean
c6c770
 daemon_list_cached_users (AccountsAccounts      *accounts,
c6c770
                           GDBusMethodInvocation *context)
c6c770
 {
c6c770
         Daemon *daemon = (Daemon*)accounts;
c6c770
         DaemonPrivate *priv = daemon_get_instance_private (daemon);
c6c770
         ListUserData *data;
c6c770
 
c6c770
         data = list_user_data_new (daemon, context);
c6c770
 
c6c770
         if (priv->reload_id > 0) {
c6c770
-- 
c6c770
2.31.1
c6c770