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

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