diff --git a/SOURCES/0001-daemon-don-t-treat-explicitly-requested-users-as-cac.patch b/SOURCES/0001-daemon-don-t-treat-explicitly-requested-users-as-cac.patch
new file mode 100644
index 0000000..bbf9cdd
--- /dev/null
+++ b/SOURCES/0001-daemon-don-t-treat-explicitly-requested-users-as-cac.patch
@@ -0,0 +1,741 @@
+From 83567748f5f5c4eabc233680a553f3edd803a24d Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Thu, 4 May 2017 12:04:05 -0400
+Subject: [PATCH] daemon: don't treat explicitly requested users as "cached"
+
+The ListCachedUsers method currently returns users that have
+been explicitly requested by a client.  It's weird that merely
+querying a user can make it show up in login screen user lists.
+Furthermore, UncacheUser is broken since commit
+177509e9460b149ecbf85e75c930be2ea00b7d05 because the user has
+been explicitly requested in order to uncache it.  So trying
+to uncache a user inadvertently caches the user.
+
+This commit fixes that.
+
+https://bugs.freedesktop.org/show_bug.cgi?id=101052
+---
+ src/daemon.c | 71 +++++++++++++++++++++++++++++++++++++++---------------------
+ src/user.c   | 17 +++++++++++++++
+ src/user.h   |  3 +++
+ 3 files changed, 66 insertions(+), 25 deletions(-)
+
+diff --git a/src/daemon.c b/src/daemon.c
+index 4586eff..fce5a60 100644
+--- a/src/daemon.c
++++ b/src/daemon.c
+@@ -481,100 +481,108 @@ entry_generator_requested_users (Daemon       *daemon,
+                 while (node != NULL) {
+                         const char *name;
+ 
+                         name = node->data;
+                         node = node->next;
+ 
+                         *state = node;
+ 
+                         if (!g_hash_table_lookup (users, name)) {
+                                 pwent = getpwnam (name);
+                                 if (pwent == NULL) {
+                                         g_debug ("user '%s' requested previously but not present on system", name);
+                                 } else {
+                                         *shadow_entry = getspnam (pwent->pw_name);
+ 
+                                         return pwent;
+                                 }
+                         }
+                 }
+         }
+ 
+         /* Last iteration */
+ 
+         *state = NULL;
+         return NULL;
+ }
+ 
+ static void
+ load_entries (Daemon             *daemon,
+               GHashTable         *users,
+-              gboolean            allow_system_users,
++              gboolean            explicitly_requested,
+               EntryGeneratorFunc  entry_generator)
+ {
+         gpointer generator_state = NULL;
+         struct passwd *pwent;
+         struct spwd *spent = NULL;
+         User *user = NULL;
+ 
+         g_assert (entry_generator != NULL);
+ 
+         for (;;) {
+                 spent = NULL;
+                 pwent = entry_generator (daemon, users, &generator_state, &spent);
+                 if (pwent == NULL)
+                         break;
+ 
+                 /* Skip system users... */
+-                if (!allow_system_users && !user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, spent? spent->sp_pwdp : NULL)) {
++                if (!explicitly_requested && !user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, spent? spent->sp_pwdp : NULL)) {
+                         g_debug ("skipping user: %s", pwent->pw_name);
+                         continue;
+                 }
+ 
+-                /* ignore duplicate entries */
+-                if (g_hash_table_lookup (users, pwent->pw_name)) {
+-                        continue;
+-                }
++                /* Only process users that haven't been processed yet.
++                 * We do always make sure entries get promoted
++                 * to "cached" status if they are supposed to be
++                 */
++
++                user = g_hash_table_lookup (users, pwent->pw_name);
+ 
+-                user = g_hash_table_lookup (daemon->priv->users, pwent->pw_name);
+                 if (user == NULL) {
+-                        user = user_new (daemon, pwent->pw_uid);
+-                } else {
+-                        g_object_ref (user);
+-                }
++                        user = g_hash_table_lookup (daemon->priv->users, pwent->pw_name);
++                        if (user == NULL) {
++                                user = user_new (daemon, pwent->pw_uid);
++                        } else {
++                                g_object_ref (user);
++                        }
++
++                        /* freeze & update users not already in the new list */
++                        g_object_freeze_notify (G_OBJECT (user));
++                        user_update_from_pwent (user, pwent, spent);
+ 
+-                /* freeze & update users not already in the new list */
+-                g_object_freeze_notify (G_OBJECT (user));
+-                user_update_from_pwent (user, pwent, spent);
++                        g_hash_table_insert (users, g_strdup (user_get_user_name (user)), user);
++                        g_debug ("loaded user: %s", user_get_user_name (user));
++                }
+ 
+-                g_hash_table_insert (users, g_strdup (user_get_user_name (user)), user);
+-                g_debug ("loaded user: %s", user_get_user_name (user));
++                if (!explicitly_requested) {
++                        user_set_cached (user, TRUE);
++                }
+         }
+ 
+         /* Generator should have cleaned up */
+         g_assert (generator_state == NULL);
+ }
+ 
+ static GHashTable *
+ create_users_hash_table (void)
+ {
+         return g_hash_table_new_full (g_str_hash,
+                                       g_str_equal,
+                                       g_free,
+                                       g_object_unref);
+ }
+ 
+ static void
+ reload_users (Daemon *daemon)
+ {
+         GHashTable *users;
+         GHashTable *old_users;
+         GHashTable *local;
+         GHashTableIter iter;
+         gpointer name;
+         User *user;
+ 
+         /* Track the users that we saw during our (re)load */
+         users = create_users_hash_table ();
+ 
+         /*
+          * NOTE: As we load data from all the sources, notifies are
+@@ -586,71 +594,79 @@ reload_users (Daemon *daemon)
+         load_entries (daemon, users, FALSE, entry_generator_fgetpwent);
+         local = g_hash_table_new (g_str_hash, g_str_equal);
+         g_hash_table_iter_init (&iter, users);
+         while (g_hash_table_iter_next (&iter, &name, NULL))
+                 g_hash_table_add (local, name);
+ 
+         /* and add users to hash table that were explicitly requested  */
+         load_entries (daemon, users, TRUE, entry_generator_requested_users);
+ 
+         /* Now add/update users from other sources, possibly non-local */
+         load_entries (daemon, users, FALSE, entry_generator_cachedir);
+ 
+ #ifdef HAVE_UTMPX_H
+         wtmp_update_login_frequencies (users);
+ #endif
+ 
+         /* Mark which users are local, which are not */
+         g_hash_table_iter_init (&iter, users);
+         while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user))
+                 user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL);
+ 
+         g_hash_table_destroy (local);
+ 
+         /* Swap out the users */
+         old_users = daemon->priv->users;
+         daemon->priv->users = users;
+ 
+         /* Remove all the old users */
+         g_hash_table_iter_init (&iter, old_users);
+         while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
+-                if (!g_hash_table_lookup (users, name)) {
++                User *refreshed_user;
++
++                refreshed_user = g_hash_table_lookup (users, name);
++
++                if (!refreshed_user || !user_get_cached (refreshed_user)) {
+                         user_unregister (user);
+                         accounts_accounts_emit_user_deleted (ACCOUNTS_ACCOUNTS (daemon),
+                                                              user_get_object_path (user));
+                 }
+         }
+ 
+         /* Register all the new users */
+         g_hash_table_iter_init (&iter, users);
+         while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
+-                if (!g_hash_table_lookup (old_users, name)) {
++                User *stale_user;
++
++                stale_user = g_hash_table_lookup (old_users, name);
++
++                if (!stale_user || !user_get_cached (stale_user) && user_get_cached (user)) {
+                         user_register (user);
+                         accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon),
+                                                            user_get_object_path (user));
+                 }
+                 g_object_thaw_notify (G_OBJECT (user));
+         }
+ 
+         g_hash_table_destroy (old_users);
+ }
+ 
+ static gboolean
+ reload_users_timeout (Daemon *daemon)
+ {
+         reload_users (daemon);
+         daemon->priv->reload_id = 0;
+ 
+         return FALSE;
+ }
+ 
+ static gboolean load_autologin (Daemon    *daemon,
+                                 gchar    **name,
+                                 gboolean  *enabled,
+                                 GError   **error);
+ 
+ static gboolean
+ reload_autologin_timeout (Daemon *daemon)
+ {
+         gboolean enabled;
+         gchar *name = NULL;
+         GError *error = NULL;
+@@ -1063,60 +1079,65 @@ list_user_data_new (Daemon                *daemon,
+ static void
+ list_user_data_free (ListUserData *data)
+ {
+         g_object_unref (data->daemon);
+         g_free (data);
+ }
+ 
+ static gboolean
+ finish_list_cached_users (gpointer user_data)
+ {
+         ListUserData *data = user_data;
+         GPtrArray *object_paths;
+         GHashTableIter iter;
+         const gchar *name;
+         User *user;
+         uid_t uid;
+         const gchar *shell;
+ 
+         object_paths = g_ptr_array_new ();
+ 
+         g_hash_table_iter_init (&iter, data->daemon->priv->users);
+         while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&user)) {
+                 uid = user_get_uid (user);
+                 shell = user_get_shell (user);
+ 
+                 if (!user_classify_is_human (uid, name, shell, NULL)) {
+                         g_debug ("user %s %ld excluded", name, (long) uid);
+                         continue;
+                 }
+ 
++                if (!user_get_cached (user)) {
++                        g_debug ("user %s %ld not cached", name, (long) uid);
++                        continue;
++                }
++
+                 g_debug ("user %s %ld not excluded", name, (long) uid);
+                 g_ptr_array_add (object_paths, (gpointer) user_get_object_path (user));
+         }
+         g_ptr_array_add (object_paths, NULL);
+ 
+         accounts_accounts_complete_list_cached_users (NULL, data->context, (const gchar * const *) object_paths->pdata);
+ 
+         g_ptr_array_free (object_paths, TRUE);
+ 
+         list_user_data_free (data);
+ 
+         return FALSE;
+ }
+ 
+ static gboolean
+ daemon_list_cached_users (AccountsAccounts      *accounts,
+                           GDBusMethodInvocation *context)
+ {
+         Daemon *daemon = (Daemon*)accounts;
+         ListUserData *data;
+ 
+         data = list_user_data_new (daemon, context);
+ 
+         if (daemon->priv->reload_id > 0) {
+                 /* reload in progress, wait a bit */
+                 g_idle_add (finish_list_cached_users, data);
+         }
+         else {
+                 finish_list_cached_users (data);
+         }
+@@ -1303,123 +1324,123 @@ daemon_cache_user (AccountsAccounts      *accounts,
+ static void
+ daemon_uncache_user_authorized_cb (Daemon                *daemon,
+                                    User                  *dummy,
+                                    GDBusMethodInvocation *context,
+                                    gpointer               data)
+ {
+         const gchar *user_name = data;
+         gchar       *filename;
+         User        *user;
+ 
+         sys_log (context, "uncache user '%s'", user_name);
+ 
+         user = daemon_local_find_user_by_name (daemon, user_name);
+         if (user == NULL) {
+                 throw_error (context, ERROR_USER_DOES_NOT_EXIST,
+                              "No user with the name %s found", user_name);
+                 return;
+         }
+ 
+         /* Always use the canonical user name looked up */
+         user_name = user_get_user_name (user);
+ 
+         filename = g_build_filename (USERDIR, user_name, NULL);
+         g_remove (filename);
+         g_free (filename);
+ 
+         filename = g_build_filename (ICONDIR, user_name, NULL);
+         g_remove (filename);
+         g_free (filename);
+ 
++        user_set_cached (user, FALSE);
++
+         accounts_accounts_complete_uncache_user (NULL, context);
+ 
+         queue_reload_users (daemon);
+ }
+ 
+ static gboolean
+ daemon_uncache_user (AccountsAccounts      *accounts,
+                      GDBusMethodInvocation *context,
+                      const gchar           *user_name)
+ {
+         Daemon *daemon = (Daemon*)accounts;
+ 
+         daemon_local_check_auth (daemon,
+                                  NULL,
+                                  "org.freedesktop.accounts.user-administration",
+                                  TRUE,
+                                  daemon_uncache_user_authorized_cb,
+                                  context,
+                                  g_strdup (user_name),
+                                  g_free);
+ 
+         return TRUE;
+ }
+ 
+ typedef struct {
+         uid_t uid;
+         gboolean remove_files;
+ } DeleteUserData;
+ 
+ static void
+ daemon_delete_user_authorized_cb (Daemon                *daemon,
+                                   User                  *dummy,
+                                   GDBusMethodInvocation *context,
+                                   gpointer               data)
+ 
+ {
+         DeleteUserData *ud = data;
+         GError *error;
+         gchar *filename;
+         struct passwd *pwent;
+         const gchar *argv[6];
++        User *user;
+ 
+         pwent = getpwuid (ud->uid);
+ 
+         if (pwent == NULL) {
+                 throw_error (context, ERROR_USER_DOES_NOT_EXIST, "No user with uid %d found", ud->uid);
+ 
+                 return;
+         }
+ 
+         sys_log (context, "delete user '%s' (%d)", pwent->pw_name, ud->uid);
+ 
+-        if (daemon->priv->autologin != NULL) {
+-                User *user;
++        user = daemon_local_find_user_by_id (daemon, ud->uid);
+ 
+-                user = daemon_local_find_user_by_id (daemon, ud->uid);
++        if (user != NULL) {
++                user_set_cached (user, FALSE);
+ 
+-                g_assert (user != NULL);
+-
+-                if (daemon->priv->autologin == user) {
++                if (daemon->priv->autologin  == user) {
+                         daemon_local_set_automatic_login (daemon, user, FALSE, NULL);
+                 }
+-
+         }
+ 
+         filename = g_build_filename (USERDIR, pwent->pw_name, NULL);
+         g_remove (filename);
+         g_free (filename);
+ 
+         filename = g_build_filename (ICONDIR, pwent->pw_name, NULL);
+         g_remove (filename);
+         g_free (filename);
+ 
+         argv[0] = "/usr/sbin/userdel";
+         if (ud->remove_files) {
+                 argv[1] = "-f";
+                 argv[2] = "-r";
+                 argv[3] = "--";
+                 argv[4] = pwent->pw_name;
+                 argv[5] = NULL;
+         }
+         else {
+                 argv[1] = "-f";
+                 argv[2] = "--";
+                 argv[3] = pwent->pw_name;
+                 argv[4] = NULL;
+         }
+ 
+         error = NULL;
+         if (!spawn_with_login_uid (context, argv, &error)) {
+                 throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
+                 g_error_free (error);
+                 return;
+diff --git a/src/user.c b/src/user.c
+index 247ca2f..056be2f 100644
+--- a/src/user.c
++++ b/src/user.c
+@@ -77,60 +77,61 @@ struct User {
+ 
+         GDBusConnection *system_bus_connection;
+         gchar *object_path;
+ 
+         Daemon       *daemon;
+ 
+         GKeyFile     *keyfile;
+ 
+         uid_t         uid;
+         gid_t         gid;
+         gchar        *user_name;
+         gchar        *real_name;
+         AccountType   account_type;
+         PasswordMode  password_mode;
+         gchar        *password_hint;
+         gchar        *home_dir;
+         gchar        *shell;
+         gchar        *email;
+         gchar        *language;
+         gchar        *x_session;
+         gchar        *location;
+         guint64       login_frequency;
+         gint64        login_time;
+         GVariant     *login_history;
+         gchar        *icon_file;
+         gchar        *default_icon_file;
+         gboolean      locked;
+         gboolean      automatic_login;
+         gboolean      system_account;
+         gboolean      local_account;
++        gboolean      cached;
+ };
+ 
+ typedef struct UserClass
+ {
+         AccountsUserSkeletonClass parent_class;
+ } UserClass;
+ 
+ static void user_accounts_user_iface_init (AccountsUserIface *iface);
+ 
+ G_DEFINE_TYPE_WITH_CODE (User, user, ACCOUNTS_TYPE_USER_SKELETON, G_IMPLEMENT_INTERFACE (ACCOUNTS_TYPE_USER, user_accounts_user_iface_init));
+ 
+ static gint
+ account_type_from_pwent (struct passwd *pwent)
+ {
+         struct group *grp;
+         gint i;
+ 
+         if (pwent->pw_uid == 0) {
+                 g_debug ("user is root so account type is administrator");
+                 return ACCOUNT_TYPE_ADMINISTRATOR;
+         }
+ 
+         grp = getgrnam (ADMIN_GROUP);
+         if (grp == NULL) {
+                 g_debug (ADMIN_GROUP " group not found");
+                 return ACCOUNT_TYPE_STANDARD;
+         }
+ 
+         for (i = 0; grp->gr_mem[i] != NULL; i++) {
+                 if (g_strcmp0 (grp->gr_mem[i], pwent->pw_name) == 0) {
+@@ -323,109 +324,112 @@ user_update_from_keyfile (User     *user,
+                 user->location = s;
+                 g_object_notify (G_OBJECT (user), "location");
+         }
+ 
+         s = g_key_file_get_string (keyfile, "User", "PasswordHint", NULL);
+         if (s != NULL) {
+                 g_free (user->password_hint);
+                 user->password_hint = s;
+                 g_object_notify (G_OBJECT (user), "password-hint");
+         }
+ 
+         s = g_key_file_get_string (keyfile, "User", "Icon", NULL);
+         if (s != NULL) {
+                 g_free (user->icon_file);
+                 user->icon_file = s;
+                 g_object_notify (G_OBJECT (user), "icon-file");
+         }
+ 
+         if (g_key_file_has_key (keyfile, "User", "SystemAccount", NULL)) {
+             gboolean system_account;
+ 
+             system_account = g_key_file_get_boolean (keyfile, "User", "SystemAccount", NULL);
+             if (system_account != user->system_account) {
+                     user->system_account = system_account;
+                     g_object_notify (G_OBJECT (user), "system-account");
+             }
+         }
+ 
+         g_clear_pointer (&user->keyfile, g_key_file_unref);
+         user->keyfile = g_key_file_ref (keyfile);
++        user_set_cached (user, TRUE);
+ 
+         g_object_thaw_notify (G_OBJECT (user));
+ }
+ 
+ void
+ user_update_local_account_property (User          *user,
+                                     gboolean       local)
+ {
+         if (local == user->local_account)
+                 return;
+         user->local_account = local;
+         g_object_notify (G_OBJECT (user), "local-account");
+ }
+ 
+ void
+ user_update_system_account_property (User          *user,
+                                      gboolean       system)
+ {
+         if (system == user->system_account)
+                 return;
+         user->system_account = system;
+         g_object_notify (G_OBJECT (user), "system-account");
+ }
+ 
+ static void
+ user_save_to_keyfile (User     *user,
+                       GKeyFile *keyfile)
+ {
+         g_key_file_remove_group (keyfile, "User", NULL);
+ 
+         if (user->email)
+                 g_key_file_set_string (keyfile, "User", "Email", user->email);
+ 
+         if (user->language)
+                 g_key_file_set_string (keyfile, "User", "Language", user->language);
+ 
+         if (user->x_session)
+                 g_key_file_set_string (keyfile, "User", "XSession", user->x_session);
+ 
+         if (user->location)
+                 g_key_file_set_string (keyfile, "User", "Location", user->location);
+ 
+         if (user->password_hint)
+                 g_key_file_set_string (keyfile, "User", "PasswordHint", user->password_hint);
+ 
+         if (user->icon_file)
+                 g_key_file_set_string (keyfile, "User", "Icon", user->icon_file);
+ 
+         g_key_file_set_boolean (keyfile, "User", "SystemAccount", user->system_account);
++
++        user_set_cached (user, TRUE);
+ }
+ 
+ static void
+ save_extra_data (User *user)
+ {
+         gchar *filename;
+         gchar *data;
+         GError *error;
+ 
+         user_save_to_keyfile (user, user->keyfile);
+ 
+         error = NULL;
+         data = g_key_file_to_data (user->keyfile, NULL, &error);
+         if (error == NULL) {
+                 filename = g_build_filename (USERDIR,
+                                              user->user_name,
+                                              NULL);
+                 g_file_set_contents (filename, data, -1, &error);
+                 g_free (filename);
+                 g_free (data);
+         }
+         if (error) {
+                 g_warning ("Saving data for user %s failed: %s",
+                            user->user_name, error->message);
+                 g_error_free (error);
+         }
+ }
+ 
+ static void
+ move_extra_data (const gchar *old_name,
+@@ -524,60 +528,73 @@ user_get_user_name (User *user)
+ gboolean
+ user_get_system_account (User *user)
+ {
+         return user->system_account;
+ }
+ 
+ gboolean
+ user_get_local_account (User *user)
+ {
+         return user->local_account;
+ }
+ 
+ const gchar *
+ user_get_object_path (User *user)
+ {
+         return user->object_path;
+ }
+ 
+ uid_t
+ user_get_uid (User *user)
+ {
+         return user->uid;
+ }
+ 
+ const gchar *
+ user_get_shell(User *user)
+ {
+ 	return user->shell;
+ }
+ 
++gboolean
++user_get_cached (User *user)
++{
++        return user->cached;
++}
++
++void
++user_set_cached (User     *user,
++                 gboolean  cached)
++{
++        user->cached = cached;
++}
++
+ static void
+ throw_error (GDBusMethodInvocation *context,
+              gint                   error_code,
+              const gchar           *format,
+              ...)
+ {
+         va_list args;
+         gchar *message;
+ 
+         va_start (args, format);
+         message = g_strdup_vprintf (format, args);
+         va_end (args);
+ 
+         g_dbus_method_invocation_return_error (context, ERROR, error_code, "%s", message);
+ 
+         g_free (message);
+ }
+ 
+ static void
+ user_change_real_name_authorized_cb (Daemon                *daemon,
+                                      User                  *user,
+                                      GDBusMethodInvocation *context,
+                                      gpointer               data)
+ 
+ {
+         gchar *name = data;
+         GError *error;
+         const gchar *argv[6];
+ 
+         if (g_strcmp0 (user->real_name, name) != 0) {
+diff --git a/src/user.h b/src/user.h
+index 22548f9..39c6f13 100644
+--- a/src/user.h
++++ b/src/user.h
+@@ -36,47 +36,50 @@ G_BEGIN_DECLS
+ #define IS_USER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TYPE_USER))
+ 
+ typedef enum {
+         ACCOUNT_TYPE_STANDARD,
+         ACCOUNT_TYPE_ADMINISTRATOR,
+ #define ACCOUNT_TYPE_LAST ACCOUNT_TYPE_ADMINISTRATOR
+ } AccountType;
+ 
+ typedef enum {
+         PASSWORD_MODE_REGULAR,
+         PASSWORD_MODE_SET_AT_LOGIN,
+         PASSWORD_MODE_NONE,
+ #define PASSWORD_MODE_LAST PASSWORD_MODE_NONE
+ } PasswordMode;
+ 
+ /* local methods */
+ 
+ GType          user_get_type                (void) G_GNUC_CONST;
+ User *         user_new                     (Daemon        *daemon,
+                                              uid_t          uid);
+ 
+ void           user_update_from_pwent       (User          *user,
+                                              struct passwd *pwent,
+                                              struct spwd   *spent);
+ void           user_update_from_keyfile     (User          *user,
+                                              GKeyFile      *keyfile);
+ void           user_update_local_account_property (User          *user,
+                                                    gboolean       local);
+ void           user_update_system_account_property (User          *user,
+                                                     gboolean       system);
++gboolean       user_get_cached              (User          *user);
++void           user_set_cached              (User          *user,
++                                             gboolean       cached);
+ 
+ void           user_register                (User          *user);
+ void           user_unregister              (User          *user);
+ void           user_changed                 (User          *user);
+ 
+ void           user_save                    (User          *user);
+ 
+ const gchar *  user_get_user_name           (User          *user);
+ gboolean       user_get_system_account      (User          *user);
+ gboolean       user_get_local_account       (User          *user);
+ const gchar *  user_get_object_path         (User          *user);
+ uid_t          user_get_uid                 (User          *user);
+ const gchar *  user_get_shell               (User          *user);
+ 
+ G_END_DECLS
+ 
+ #endif
+-- 
+2.12.2
+
diff --git a/SOURCES/0001-daemon-make-sure-explicitly-requested-users-aren-t-l.patch b/SOURCES/0001-daemon-make-sure-explicitly-requested-users-aren-t-l.patch
new file mode 100644
index 0000000..f35251c
--- /dev/null
+++ b/SOURCES/0001-daemon-make-sure-explicitly-requested-users-aren-t-l.patch
@@ -0,0 +1,584 @@
+From 691d11c09d40cf6e9745e0c61e3fc59f77865e04 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Thu, 23 Mar 2017 16:59:11 -0400
+Subject: [PATCH] daemon: make sure explicitly requested users aren't lost on
+ reloads
+
+Right now, a user proxy can suddenly become defunct if the
+/etc/passwd file is updated or some other reason leads to a reload.
+
+This commit makes sure that the objects associated with proxies
+stick around across reloads.
+---
+ src/daemon.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 67 insertions(+), 7 deletions(-)
+
+diff --git a/src/daemon.c b/src/daemon.c
+index 815e2c9..4586eff 100644
+--- a/src/daemon.c
++++ b/src/daemon.c
+@@ -41,78 +41,79 @@
+ 
+ #include <glib.h>
+ #include <glib/gi18n.h>
+ #include <glib-object.h>
+ #include <glib/gstdio.h>
+ #include <gio/gio.h>
+ #include <polkit/polkit.h>
+ 
+ #include "user-classify.h"
+ #include "daemon.h"
+ #include "util.h"
+ 
+ #define PATH_PASSWD "/etc/passwd"
+ #define PATH_SHADOW "/etc/shadow"
+ #define PATH_GROUP "/etc/group"
+ #define PATH_GDM_CUSTOM "/etc/gdm/custom.conf"
+ #ifdef HAVE_UTMPX_H
+ #define PATH_WTMP _PATH_WTMPX
+ #endif
+ 
+ enum {
+         PROP_0,
+         PROP_DAEMON_VERSION
+ };
+ 
+ struct DaemonPrivate {
+         GDBusConnection *bus_connection;
+         GDBusProxy *bus_proxy;
+ 
+         GHashTable *users;
++        GList *explicitly_requested_users;
+ 
+         User *autologin;
+ 
+         GFileMonitor *passwd_monitor;
+         GFileMonitor *shadow_monitor;
+         GFileMonitor *group_monitor;
+         GFileMonitor *gdm_monitor;
+ #ifdef HAVE_UTMPX_H
+         GFileMonitor *wtmp_monitor;
+ #endif
+ 
+         guint reload_id;
+         guint autologin_id;
+ 
+         PolkitAuthority *authority;
+ };
+ 
+-typedef struct passwd * (* EntryGeneratorFunc) (GHashTable *, gpointer *, struct spwd **shadow_entry);
++typedef struct passwd * (* EntryGeneratorFunc) (Daemon *, GHashTable *, gpointer *, struct spwd **shadow_entry);
+ 
+ static void daemon_accounts_accounts_iface_init (AccountsAccountsIface *iface);
+ 
+ G_DEFINE_TYPE_WITH_CODE (Daemon, daemon, ACCOUNTS_TYPE_ACCOUNTS_SKELETON, G_IMPLEMENT_INTERFACE (ACCOUNTS_TYPE_ACCOUNTS, daemon_accounts_accounts_iface_init));
+ 
+ #define DAEMON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_DAEMON, DaemonPrivate))
+ 
+ static const GDBusErrorEntry accounts_error_entries[] =
+ { 
+         { ERROR_FAILED, "org.freedesktop.Accounts.Error.Failed" },
+         { ERROR_USER_EXISTS, "org.freedesktop.Accounts.Error.UserExists" },
+         { ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" },
+         { ERROR_PERMISSION_DENIED, "org.freedesktop.Accounts.Error.PermissionDenied" },
+         { ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" }
+ };
+ 
+ GQuark
+ error_quark (void)
+ {
+         static volatile gsize quark_volatile = 0;
+ 
+         g_dbus_error_register_error_domain ("accounts_error",
+                                             &quark_volatile,
+                                             accounts_error_entries,
+                                             G_N_ELEMENTS (accounts_error_entries));
+ 
+         return (GQuark) quark_volatile;
+ }
+ #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+ 
+@@ -265,61 +266,62 @@ wtmp_update_login_frequencies (GHashTable *users)
+ 
+                 g_object_set (user, "login-frequency", accounting->frequency, NULL);
+                 g_object_set (user, "login-time", accounting->time, NULL);
+ 
+                 builder = g_variant_builder_new (G_VARIANT_TYPE ("a(xxa{sv})"));
+                 for (l = g_list_last (accounting->previous_logins); l != NULL; l = l->prev) {
+                         previous_login = l->data;
+ 
+                         builder2 = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+                         g_variant_builder_add (builder2, "{sv}", "type", g_variant_new_string (previous_login->id));
+                         g_variant_builder_add (builder, "(xxa{sv})", previous_login->login_time, previous_login->logout_time, builder2);
+                         g_variant_builder_unref (builder2);
+                 }
+                 g_object_set (user, "login-history", g_variant_new ("a(xxa{sv})", builder), NULL);
+                 g_variant_builder_unref (builder);
+                 g_list_free_full (accounting->previous_logins, (GDestroyNotify) user_previous_login_free);
+ 
+                 user_changed (user);
+         }
+ 
+         g_hash_table_unref (login_hash);
+         g_hash_table_unref (logout_hash);
+ }
+ #endif /* HAVE_UTMPX_H */
+ 
+ #ifndef MAX_LOCAL_USERS
+ #define MAX_LOCAL_USERS 50
+ #endif
+ 
+ static struct passwd *
+-entry_generator_fgetpwent (GHashTable   *users,
++entry_generator_fgetpwent (Daemon       *daemon,
++                           GHashTable   *users,
+                            gpointer     *state,
+                            struct spwd **spent)
+ {
+         struct passwd *pwent;
+ 
+         struct {
+                 struct spwd spbuf;
+                 char buf[1024];
+         } *shadow_entry_buffers;
+ 
+         struct {
+                 FILE *fp;
+                 GHashTable *users;
+         } *generator_state;
+ 
+         /* First iteration */
+         if (*state == NULL) {
+                 GHashTable *shadow_users = NULL;
+                 FILE *fp;
+                 struct spwd *shadow_entry;
+ 
+                 fp = fopen (PATH_SHADOW, "r");
+                 if (fp == NULL) {
+                         g_warning ("Unable to open %s: %s", PATH_SHADOW, g_strerror (errno));
+                         return NULL;
+                 }
+ 
+                 shadow_users = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ 
+                 do {
+@@ -358,61 +360,62 @@ entry_generator_fgetpwent (GHashTable   *users,
+                 generator_state->users = shadow_users;
+ 
+                 *state = generator_state;
+         }
+ 
+         /* Every iteration */
+         generator_state = *state;
+ 
+         if (g_hash_table_size (users) < MAX_LOCAL_USERS) {
+                 pwent = fgetpwent (generator_state->fp);
+                 if (pwent != NULL) {
+                         shadow_entry_buffers = g_hash_table_lookup (generator_state->users, pwent->pw_name);
+ 
+                         if (shadow_entry_buffers != NULL) {
+                             *spent = &shadow_entry_buffers->spbuf;
+                             return pwent;
+                         }
+                 }
+         }
+ 
+         /* Last iteration */
+         fclose (generator_state->fp);
+         g_hash_table_unref (generator_state->users);
+         g_free (generator_state);
+         *state = NULL;
+ 
+         return NULL;
+ }
+ 
+ static struct passwd *
+-entry_generator_cachedir (GHashTable   *users,
++entry_generator_cachedir (Daemon       *daemon,
++                          GHashTable   *users,
+                           gpointer     *state,
+                           struct spwd **shadow_entry)
+ {
+         struct passwd *pwent;
+         const gchar *name;
+         GError *error = NULL;
+         gchar *filename;
+         gboolean regular;
+         GHashTableIter iter;
+         GKeyFile *key_file;
+         User *user;
+         GDir *dir;
+ 
+         /* First iteration */
+         if (*state == NULL) {
+                 *state = g_dir_open (USERDIR, 0, &error);
+                 if (error != NULL) {
+                         if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
+                                 g_warning ("couldn't list user cache directory: %s", USERDIR);
+                         g_error_free (error);
+                         return NULL;
+                 }
+         }
+ 
+         /* Every iteration */
+ 
+         /*
+          * Use names of files of regular type to lookup information
+          * about each user. Loop until we find something valid.
+          */
+@@ -430,145 +433,194 @@ entry_generator_cachedir (GHashTable   *users,
+                 if (regular) {
+                         pwent = getpwnam (name);
+                         if (pwent == NULL) {
+                                 g_debug ("user '%s' in cache dir but not present on system", name);
+                         } else {
+                                 *shadow_entry = getspnam (pwent->pw_name);
+ 
+                                 return pwent;
+                         }
+                 }
+         }
+ 
+         /* Last iteration */
+         g_dir_close (dir);
+ 
+         /* Update all the users from the files in the cache dir */
+         g_hash_table_iter_init (&iter, users);
+         while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&user)) {
+                 filename = g_build_filename (USERDIR, name, NULL);
+                 key_file = g_key_file_new ();
+                 if (g_key_file_load_from_file (key_file, filename, 0, NULL))
+                         user_update_from_keyfile (user, key_file);
+                 g_key_file_unref (key_file);
+                 g_free (filename);
+         }
+ 
+         *state = NULL;
+         return NULL;
+ }
+ 
++static struct passwd *
++entry_generator_requested_users (Daemon       *daemon,
++                                 GHashTable   *users,
++                                 gpointer     *state,
++                                 struct spwd **shadow_entry)
++{
++        struct passwd *pwent;
++        GList *node;
++
++        /* First iteration */
++        if (*state == NULL) {
++                *state = daemon->priv->explicitly_requested_users;
++        }
++
++        /* Every iteration */
++
++        if (g_hash_table_size (users) < MAX_LOCAL_USERS) {
++                node = *state;
++                while (node != NULL) {
++                        const char *name;
++
++                        name = node->data;
++                        node = node->next;
++
++                        *state = node;
++
++                        if (!g_hash_table_lookup (users, name)) {
++                                pwent = getpwnam (name);
++                                if (pwent == NULL) {
++                                        g_debug ("user '%s' requested previously but not present on system", name);
++                                } else {
++                                        *shadow_entry = getspnam (pwent->pw_name);
++
++                                        return pwent;
++                                }
++                        }
++                }
++        }
++
++        /* Last iteration */
++
++        *state = NULL;
++        return NULL;
++}
++
+ static void
+ load_entries (Daemon             *daemon,
+               GHashTable         *users,
++              gboolean            allow_system_users,
+               EntryGeneratorFunc  entry_generator)
+ {
+         gpointer generator_state = NULL;
+         struct passwd *pwent;
+         struct spwd *spent = NULL;
+         User *user = NULL;
+ 
+         g_assert (entry_generator != NULL);
+ 
+         for (;;) {
+                 spent = NULL;
+-                pwent = entry_generator (users, &generator_state, &spent);
++                pwent = entry_generator (daemon, users, &generator_state, &spent);
+                 if (pwent == NULL)
+                         break;
+ 
+                 /* Skip system users... */
+-                if (!user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, spent? spent->sp_pwdp : NULL)) {
++                if (!allow_system_users && !user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, spent? spent->sp_pwdp : NULL)) {
+                         g_debug ("skipping user: %s", pwent->pw_name);
+                         continue;
+                 }
+ 
+                 /* ignore duplicate entries */
+                 if (g_hash_table_lookup (users, pwent->pw_name)) {
+                         continue;
+                 }
+ 
+                 user = g_hash_table_lookup (daemon->priv->users, pwent->pw_name);
+                 if (user == NULL) {
+                         user = user_new (daemon, pwent->pw_uid);
+                 } else {
+                         g_object_ref (user);
+                 }
+ 
+                 /* freeze & update users not already in the new list */
+                 g_object_freeze_notify (G_OBJECT (user));
+                 user_update_from_pwent (user, pwent, spent);
+ 
+                 g_hash_table_insert (users, g_strdup (user_get_user_name (user)), user);
+                 g_debug ("loaded user: %s", user_get_user_name (user));
+         }
+ 
+         /* Generator should have cleaned up */
+         g_assert (generator_state == NULL);
+ }
+ 
+ static GHashTable *
+ create_users_hash_table (void)
+ {
+         return g_hash_table_new_full (g_str_hash,
+                                       g_str_equal,
+                                       g_free,
+                                       g_object_unref);
+ }
+ 
+ static void
+ reload_users (Daemon *daemon)
+ {
+         GHashTable *users;
+         GHashTable *old_users;
+         GHashTable *local;
+         GHashTableIter iter;
+         gpointer name;
+         User *user;
+ 
+         /* Track the users that we saw during our (re)load */
+         users = create_users_hash_table ();
+ 
+         /*
+          * NOTE: As we load data from all the sources, notifies are
+          * frozen in load_entries() and then thawed as we process
+          * them below.
+          */
+ 
+         /* Load the local users into our hash table */
+-        load_entries (daemon, users, entry_generator_fgetpwent);
++        load_entries (daemon, users, FALSE, entry_generator_fgetpwent);
+         local = g_hash_table_new (g_str_hash, g_str_equal);
+         g_hash_table_iter_init (&iter, users);
+         while (g_hash_table_iter_next (&iter, &name, NULL))
+                 g_hash_table_add (local, name);
+ 
++        /* and add users to hash table that were explicitly requested  */
++        load_entries (daemon, users, TRUE, entry_generator_requested_users);
++
+         /* Now add/update users from other sources, possibly non-local */
+-        load_entries (daemon, users, entry_generator_cachedir);
++        load_entries (daemon, users, FALSE, entry_generator_cachedir);
+ 
+ #ifdef HAVE_UTMPX_H
+         wtmp_update_login_frequencies (users);
+ #endif
+ 
+         /* Mark which users are local, which are not */
+         g_hash_table_iter_init (&iter, users);
+         while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user))
+                 user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL);
+ 
+         g_hash_table_destroy (local);
+ 
+         /* Swap out the users */
+         old_users = daemon->priv->users;
+         daemon->priv->users = users;
+ 
+         /* Remove all the old users */
+         g_hash_table_iter_init (&iter, old_users);
+         while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
+                 if (!g_hash_table_lookup (users, name)) {
+                         user_unregister (user);
+                         accounts_accounts_emit_user_deleted (ACCOUNTS_ACCOUNTS (daemon),
+                                                              user_get_object_path (user));
+                 }
+         }
+ 
+         /* Register all the new users */
+         g_hash_table_iter_init (&iter, users);
+         while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
+                 if (!g_hash_table_lookup (old_users, name)) {
+@@ -757,60 +809,62 @@ daemon_init (Daemon *daemon)
+ 
+ #ifdef HAVE_UTMPX_H
+         daemon->priv->wtmp_monitor = setup_monitor (daemon,
+                                                     PATH_WTMP,
+                                                     on_users_monitor_changed);
+ #endif
+ 
+         daemon->priv->gdm_monitor = setup_monitor (daemon,
+                                                    PATH_GDM_CUSTOM,
+                                                    on_gdm_monitor_changed);
+ 
+         queue_reload_users (daemon);
+         queue_reload_autologin (daemon);
+ }
+ 
+ static void
+ daemon_finalize (GObject *object)
+ {
+         Daemon *daemon;
+ 
+         g_return_if_fail (IS_DAEMON (object));
+ 
+         daemon = DAEMON (object);
+ 
+         if (daemon->priv->bus_proxy != NULL)
+                 g_object_unref (daemon->priv->bus_proxy);
+ 
+         if (daemon->priv->bus_connection != NULL)
+                 g_object_unref (daemon->priv->bus_connection);
+ 
++        g_list_free_full (daemon->priv->explicitly_requested_users, g_free);
++
+         g_hash_table_destroy (daemon->priv->users);
+ 
+         G_OBJECT_CLASS (daemon_parent_class)->finalize (object);
+ }
+ 
+ static gboolean
+ register_accounts_daemon (Daemon *daemon)
+ {
+         GError *error = NULL;
+ 
+         daemon->priv->authority = polkit_authority_get_sync (NULL, &error);
+ 
+         if (daemon->priv->authority == NULL) {
+                 if (error != NULL) {
+                         g_critical ("error getting polkit authority: %s", error->message);
+                         g_error_free (error);
+                 }
+                 goto error;
+         }
+ 
+         daemon->priv->bus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+         if (daemon->priv->bus_connection == NULL) {
+                 if (error != NULL) {
+                         g_critical ("error getting system bus: %s", error->message);
+                         g_error_free (error);
+                 }
+                 goto error;
+         }
+ 
+         if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon),
+@@ -878,84 +932,90 @@ add_new_user_for_pwent (Daemon        *daemon,
+         user_register (user);
+ 
+         g_hash_table_insert (daemon->priv->users,
+                              g_strdup (user_get_user_name (user)),
+                              user);
+ 
+         accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon), user_get_object_path (user));
+ 
+         return user;
+ }
+ 
+ User *
+ daemon_local_find_user_by_id (Daemon *daemon,
+                               uid_t   uid)
+ {
+         User *user;
+         struct passwd *pwent;
+ 
+         pwent = getpwuid (uid);
+         if (pwent == NULL) {
+                 g_debug ("unable to lookup uid %d", (int)uid);
+                 return NULL;
+         }
+ 
+         user = g_hash_table_lookup (daemon->priv->users, pwent->pw_name);
+ 
+         if (user == NULL) {
+                 struct spwd *spent;
+                 spent = getspnam (pwent->pw_name);
+                 user = add_new_user_for_pwent (daemon, pwent, spent);
++
++                daemon->priv->explicitly_requested_users = g_list_append (daemon->priv->explicitly_requested_users,
++                                                                          g_strdup (pwent->pw_name));
+         }
+ 
+         return user;
+ }
+ 
+ User *
+ daemon_local_find_user_by_name (Daemon      *daemon,
+                                 const gchar *name)
+ {
+         User *user;
+         struct passwd *pwent;
+ 
+         pwent = getpwnam (name);
+         if (pwent == NULL) {
+                 g_debug ("unable to lookup name %s: %s", name, g_strerror (errno));
+                 return NULL;
+         }
+ 
+         user = g_hash_table_lookup (daemon->priv->users, pwent->pw_name);
+ 
+         if (user == NULL) {
+                 struct spwd *spent;
+                 spent = getspnam (pwent->pw_name);
+                 user = add_new_user_for_pwent (daemon, pwent, spent);
++
++                daemon->priv->explicitly_requested_users = g_list_append (daemon->priv->explicitly_requested_users,
++                                                                          g_strdup (pwent->pw_name));
+         }
+ 
+         return user;
+ }
+ 
+ User *
+ daemon_local_get_automatic_login_user (Daemon *daemon)
+ {
+         return daemon->priv->autologin;
+ }
+ 
+ static gboolean
+ daemon_find_user_by_id (AccountsAccounts      *accounts,
+                         GDBusMethodInvocation *context,
+                         gint64                 uid)
+ {
+         Daemon *daemon = (Daemon*)accounts;
+         User *user;
+ 
+         user = daemon_local_find_user_by_id (daemon, uid);
+ 
+         if (user) {
+                 accounts_accounts_complete_find_user_by_id (NULL, context, user_get_object_path (user));
+         }
+         else {
+                 throw_error (context, ERROR_FAILED, "Failed to look up user with uid %d.", (int)uid);
+         }
+ 
+         return TRUE;
+ }
+-- 
+2.12.0
+
diff --git a/SPECS/accountsservice.spec b/SPECS/accountsservice.spec
index cdce0e5..e4ce1c7 100644
--- a/SPECS/accountsservice.spec
+++ b/SPECS/accountsservice.spec
@@ -2,7 +2,7 @@
 
 Name:           accountsservice
 Version:        0.6.35
-Release:        12%{?dist}
+Release:        14%{?dist}
 Summary:        D-Bus interfaces for querying and manipulating user account information
 
 Group:          System Environment/Daemons
@@ -39,6 +39,8 @@ Patch7: scale-better.patch
 Patch8: fix-log-leak.patch
 Patch9: 0001-user-classify-exclude-nologin-users.patch
 Patch10: 0001-configure-actually-define-HAVE_GETUSERSHELL.patch
+Patch11: 0001-daemon-make-sure-explicitly-requested-users-aren-t-l.patch
+Patch12: 0001-daemon-don-t-treat-explicitly-requested-users-as-cac.patch
 
 %package libs
 Summary: Client-side library to talk to accountsservice
@@ -80,6 +82,8 @@ of these interfaces, based on the useradd, usermod and userdel commands.
 %patch8 -p1 -b .fix-log-leak
 %patch9 -p1 -b .hide-nologin-users
 %patch10 -p1 -b .define-HAVE_GETUSERSHELL
+%patch11 -p1 -b .crashfix
+%patch12 -p1 -b .uncache-fix
 
 %build
 autoreconf -f -i
@@ -134,6 +138,14 @@ rm $RPM_BUILD_ROOT%{_libdir}/*.a
 %{_datadir}/gtk-doc/html/libaccountsservice/*
 
 %changelog
+* Mon May 15 2017 Ray Strode <rstrode@redhat.com> - 0.6.35-14
+- address uncache regression introduced in last commit
+  Related: #1432602
+
+* Mon Apr 24 2017 Ray Strode <rstrode@redhat.com> - 0.6.35-13
+- address libaccountsservice crash when /etc/passwd changes
+  Resolves: #1432602
+
 * Tue Sep 06 2016 Ray Strode <rstrode@redhat.com> - 0.6.35-12
 - hide users with /sbin/nologin shell
   Resolves: #1341276