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

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