From bbbdbc5c30055f7fdbf70a4cd9e6656d3985ac3f Mon Sep 17 00:00:00 2001 From: eabdullin Date: Tue, 11 Nov 2025 08:50:13 +0000 Subject: [PATCH] import CS accountsservice-23.13.9-8.el10 --- .accountsservice.metadata | 1 - .gitignore | 2 +- 0001-mocklibc-Fix-compiler-warning.patch | 54 + ...manager-Fix-another-compiler-warning.patch | 145 ++ ...-reentrant-interfaces-of-crypt-_gens.patch | 110 + ...temAccount-false-to-be-set-in-cache-.patch | 304 --- ...al-users-check-if-machine-is-enrolle.patch | 1839 ----------------- ...end-change-updates-for-login-history.patch | 88 - .../0001-lib-save-os-when-creating-user.patch | 894 -------- ...ser-templates-for-setting-default-se.patch | 925 --------- ...w-cache-files-to-be-marked-immutable.patch | 195 -- SOURCES/user-template | 13 - ...countsservice.spec => accountsservice.spec | 216 +- gecos-allow-lastname-comma-firstname.patch | 54 + sources | 1 + 15 files changed, 508 insertions(+), 4333 deletions(-) delete mode 100644 .accountsservice.metadata create mode 100644 0001-mocklibc-Fix-compiler-warning.patch create mode 100644 0002-user-manager-Fix-another-compiler-warning.patch create mode 100644 0003-act-user-Use-the-reentrant-interfaces-of-crypt-_gens.patch delete mode 100644 SOURCES/0001-daemon-Allow-SystemAccount-false-to-be-set-in-cache-.patch delete mode 100644 SOURCES/0001-daemon-if-no-local-users-check-if-machine-is-enrolle.patch delete mode 100644 SOURCES/0001-data-don-t-send-change-updates-for-login-history.patch delete mode 100644 SOURCES/0001-lib-save-os-when-creating-user.patch delete mode 100644 SOURCES/0001-user-Introduce-user-templates-for-setting-default-se.patch delete mode 100644 SOURCES/0002-main-Allow-cache-files-to-be-marked-immutable.patch delete mode 100644 SOURCES/user-template rename SPECS/accountsservice.spec => accountsservice.spec (62%) create mode 100644 gecos-allow-lastname-comma-firstname.patch create mode 100644 sources diff --git a/.accountsservice.metadata b/.accountsservice.metadata deleted file mode 100644 index 6799259..0000000 --- a/.accountsservice.metadata +++ /dev/null @@ -1 +0,0 @@ -bab4f37144196d8ba06195bc72b4a9937c62b9fd SOURCES/accountsservice-0.6.55.tar.xz diff --git a/.gitignore b/.gitignore index 37d0a71..254d915 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/accountsservice-0.6.55.tar.xz +accountsservice-23.13.9.tar.xz diff --git a/0001-mocklibc-Fix-compiler-warning.patch b/0001-mocklibc-Fix-compiler-warning.patch new file mode 100644 index 0000000..c4052a1 --- /dev/null +++ b/0001-mocklibc-Fix-compiler-warning.patch @@ -0,0 +1,54 @@ +From da65bee12d9118fe1a49c8718d428fe61d232339 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 11 Apr 2023 10:09:07 -0400 +Subject: [PATCH 1/2] mocklibc: Fix compiler warning + +print_indent is defined in one file and used in another without a +forward declaration. That leads to a compiler warning/error. + +This commit fixes that. +--- + subprojects/mocklibc.wrap | 2 ++ + subprojects/packagefiles/mocklibc-print-indent.diff | 13 +++++++++++++ + 2 files changed, 15 insertions(+) + create mode 100644 subprojects/packagefiles/mocklibc-print-indent.diff + +diff --git a/subprojects/mocklibc.wrap b/subprojects/mocklibc.wrap +index af82298..539ee83 100644 +--- a/subprojects/mocklibc.wrap ++++ b/subprojects/mocklibc.wrap +@@ -1,10 +1,12 @@ + [wrap-file] + directory = mocklibc-1.0 + + source_url = https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/mocklibc/mocklibc-1.0.tar.gz + source_filename = mocklibc-1.0.tar.gz + source_hash = b2236a6af1028414783e9734a46ea051916ec226479d6a55a3bb823bff68f120 + + patch_url = https://wrapdb.mesonbuild.com/v1/projects/mocklibc/1.0/2/get_zip + patch_filename = mocklibc-1.0-2-wrap.zip + patch_hash = 0280f96a2eeb3c023e5acf4e00cef03d362868218d4a85347ea45137c0ef6c56 ++ ++diff_files = mocklibc-print-indent.diff +diff --git a/subprojects/packagefiles/mocklibc-print-indent.diff b/subprojects/packagefiles/mocklibc-print-indent.diff +new file mode 100644 +index 0000000..4aaed40 +--- /dev/null ++++ b/subprojects/packagefiles/mocklibc-print-indent.diff +@@ -0,0 +1,13 @@ ++diff -up mocklibc-1.0/src/netgroup-debug.c.print-indent mocklibc-1.0/src/netgroup-debug.c ++--- mocklibc-1.0/src/netgroup-debug.c.print-indent 2023-04-11 10:20:53.717381559 -0400 +++++ mocklibc-1.0/src/netgroup-debug.c 2023-04-11 10:21:02.296270333 -0400 ++@@ -21,6 +21,9 @@ ++ #include ++ #include ++ +++void print_indent (FILE *stream, +++ unsigned int indent); +++ ++ void netgroup_debug_print_entry(struct entry *entry, FILE *stream, unsigned int indent) { ++ print_indent(stream, indent); ++ +-- +2.39.2 + diff --git a/0002-user-manager-Fix-another-compiler-warning.patch b/0002-user-manager-Fix-another-compiler-warning.patch new file mode 100644 index 0000000..47b510e --- /dev/null +++ b/0002-user-manager-Fix-another-compiler-warning.patch @@ -0,0 +1,145 @@ +From 99aa57bfa59e2578c4ef47e84338f7de85c6f61b Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 11 Apr 2023 10:11:05 -0400 +Subject: [PATCH 2/2] user-manager: Fix another compiler warning + +-Wswitch-enum apparently complains about missing entries even if there +is a default:. + +This commit ensures ACT_USER_MANAGER_SEAT_STATE_UNLOADED is added to the +default case to fix that warning. +--- + src/libaccountsservice/act-user-manager.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/libaccountsservice/act-user-manager.c b/src/libaccountsservice/act-user-manager.c +index 61b4da5..3bbd480 100644 +--- a/src/libaccountsservice/act-user-manager.c ++++ b/src/libaccountsservice/act-user-manager.c +@@ -1727,60 +1727,61 @@ unload_seat (ActUserManager *manager) + { + ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); + + priv->seat.state = ACT_USER_MANAGER_SEAT_STATE_UNLOADED; + + g_free (priv->seat.id); + priv->seat.id = NULL; + + g_free (priv->seat.session_id); + priv->seat.session_id = NULL; + + g_debug ("ActUserManager: seat unloaded, so trying to set loaded property"); + maybe_set_is_loaded (manager); + } + + static void + load_new_session_incrementally (ActUserManagerNewSession *new_session) + { + switch (new_session->state) { + case ACT_USER_MANAGER_NEW_SESSION_STATE_GET_UID: + get_uid_for_new_session (new_session); + break; + case ACT_USER_MANAGER_NEW_SESSION_STATE_GET_X11_DISPLAY: + get_x11_display_for_new_session (new_session); + break; + case ACT_USER_MANAGER_NEW_SESSION_STATE_MAYBE_ADD: + maybe_add_new_session (new_session); + break; + case ACT_USER_MANAGER_NEW_SESSION_STATE_LOADED: + break; ++ case ACT_USER_MANAGER_NEW_SESSION_STATE_UNLOADED: + default: + g_assert_not_reached (); + } + } + + static void + free_fetch_user_request (ActUserManagerFetchUserRequest *request) + { + ActUserManager *manager = request->manager; + ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); + + if (request->user != NULL) { + g_object_set_data (G_OBJECT (request->user), "fetch-user-request", NULL); + g_object_weak_unref (G_OBJECT (request->user), (GWeakNotify) on_user_destroyed, manager); + } + + priv->fetch_user_requests = g_slist_remove (priv->fetch_user_requests, request); + if (request->type == ACT_USER_MANAGER_FETCH_USER_FROM_USERNAME_REQUEST) { + g_free (request->username); + } + + g_free (request->object_path); + g_free (request->description); + + g_cancellable_cancel (request->cancellable); + g_object_unref (request->cancellable); + + + g_debug ("ActUserManager: unrefing manager owned by fetch user request"); + g_object_unref (manager); +@@ -2243,60 +2244,61 @@ load_users (ActUserManager *manager) + return; + } + + load_user_paths (manager, (const char * const *) user_paths); + + load_included_usernames (manager); + + priv->list_cached_users_done = TRUE; + } + + static gboolean + load_seat_incrementally (ActUserManager *manager) + { + ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); + + priv->seat.load_idle_id = 0; + + switch (priv->seat.state) { + case ACT_USER_MANAGER_SEAT_STATE_GET_SESSION_ID: + get_current_session_id (manager); + break; + case ACT_USER_MANAGER_SEAT_STATE_GET_ID: + get_seat_id_for_current_session (manager); + break; + case ACT_USER_MANAGER_SEAT_STATE_GET_SEAT_PROXY: + get_seat_proxy (manager); + break; + case ACT_USER_MANAGER_SEAT_STATE_LOADED: + g_debug ("ActUserManager: Seat loading sequence complete"); + break; ++ case ACT_USER_MANAGER_NEW_SESSION_STATE_UNLOADED: + default: + g_assert_not_reached (); + } + + if (priv->seat.state == ACT_USER_MANAGER_SEAT_STATE_LOADED) { + load_sessions (manager); + } + + maybe_set_is_loaded (manager); + + return FALSE; + } + + static gboolean + load_idle (ActUserManager *manager) + { + ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); + + priv->seat.state = ACT_USER_MANAGER_SEAT_STATE_UNLOADED + 1; + load_seat_incrementally (manager); + priv->load_id = 0; + + return FALSE; + } + + static void + queue_load_seat (ActUserManager *manager) + { + ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); + +-- +2.39.2 + diff --git a/0003-act-user-Use-the-reentrant-interfaces-of-crypt-_gens.patch b/0003-act-user-Use-the-reentrant-interfaces-of-crypt-_gens.patch new file mode 100644 index 0000000..6541834 --- /dev/null +++ b/0003-act-user-Use-the-reentrant-interfaces-of-crypt-_gens.patch @@ -0,0 +1,110 @@ +From e050e4aa99818f7559ab48568ea6662dc4104317 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Thu, 30 Jan 2025 12:36:21 +0100 +Subject: [PATCH 3/3] act-user: Use the reentrant interfaces of + crypt{,_gensalt}(3) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The crypt(3) function is known to clobber its static allocated internal +buffer when called multiple times consecutively or (especially) when +called in parallel (e.g. from independently operation threads), and +should generally not be used if a reentrant implementation exists. + +The reentrant interface, named crypt_rn(3), operates in the same way as +the well known crypt(3) function, but takes an extra parameter of +'struct crypt_data' which includes space for its result (among other +things), so applications can utilize the reentrant interface, in a way +each invocation of the crypt_rn(3) function will freely operate on their +own dedicated memory areas when hashing passphrases. + +The same applies for the crypt_gensalt(3) function, to which libxcrypt +offers a variety of reentrant interfaces as well. + +Also ensure the buffers in use are properly zeroized. + +Signed-off-by: Bj√∂rn Esser +--- + src/libaccountsservice/act-user.c | 53 ++++++++----------------------- + 1 file changed, 13 insertions(+), 40 deletions(-) + +diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c +index 77b7b2f..4fd2c62 100644 +--- a/src/libaccountsservice/act-user.c ++++ b/src/libaccountsservice/act-user.c +@@ -1748,51 +1748,22 @@ act_user_set_account_type (ActUser *user, + } + } + +-#ifdef HAVE_CRYPT_GENSALT + static gchar * +-generate_salt_for_crypt_hash (void) +-{ +- return g_strdup (crypt_gensalt (NULL, 0, NULL, 0)); +-} +-#else +-static const gchar +-salt_char (GRand *rand) ++make_crypted (const gchar *plain) + { +- const gchar salt[] = "ABCDEFGHIJKLMNOPQRSTUVXYZ" +- "abcdefghijklmnopqrstuvxyz" +- "./0123456789"; +- +- return salt[g_rand_int_range (rand, 0, G_N_ELEMENTS (salt))]; +-} ++ gchar *crypted = NULL; ++ g_autofree struct crypt_data *cd = NULL; + +-static gchar * +-generate_salt_for_crypt_hash (void) +-{ +- g_autoptr (GString) salt = NULL; +- g_autoptr (GRand) rand = NULL; +- gint i; ++ cd = g_malloc0 (sizeof (struct crypt_data)); + +- rand = g_rand_new (); +- salt = g_string_sized_new (21); ++ crypt_gensalt_rn (NULL, 0, NULL, 0, ++ cd->input, sizeof (cd->input)); ++ crypted = g_strdup (crypt_rn (plain, cd->input, ++ cd, sizeof (struct crypt_data))); + +- /* sha512crypt */ +- g_string_append (salt, "$6$"); +- for (i = 0; i < 16; i++) { +- g_string_append_c (salt, salt_char (rand)); +- } +- g_string_append_c (salt, '$'); ++ explicit_bzero (cd, sizeof (struct crypt_data)); + +- return g_strdup (salt->str); +-} +-#endif +- +-static gchar * +-make_crypted (const gchar *plain) +-{ +- g_autofree char *salt = NULL; +- +- salt = generate_salt_for_crypt_hash (); +- return g_strdup (crypt (plain, salt)); ++ return crypted; + } + + /** +@@ -1828,7 +1799,9 @@ act_user_set_password (ActUser *user, + &error)) { + g_warning ("SetPassword call failed: %s", error->message); + } +- memset (crypted, 0, strlen (crypted)); ++ if (crypted) { ++ explicit_bzero (crypted, strlen (crypted)); ++ } + } + + /** +-- +2.48.1 diff --git a/SOURCES/0001-daemon-Allow-SystemAccount-false-to-be-set-in-cache-.patch b/SOURCES/0001-daemon-Allow-SystemAccount-false-to-be-set-in-cache-.patch deleted file mode 100644 index 84d5265..0000000 --- a/SOURCES/0001-daemon-Allow-SystemAccount-false-to-be-set-in-cache-.patch +++ /dev/null @@ -1,304 +0,0 @@ -From 14c902f42a4ea74ce9450eb53817e1bf5be05d26 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 8 Sep 2021 16:38:17 -0400 -Subject: [PATCH 1/2] daemon: Allow SystemAccount=false to be set in cache file - -At the moment we do dodgy checks based on uid to decide whether or not -an account is a system account. - -For legacy reasons, sometimes normal users have really low UIDs. - -This commit reshuffles things, so the cache file "wins" for deciding -whether or not a user is a system user. ---- - src/daemon.c | 24 ++++++++++++------------ - 1 file changed, 12 insertions(+), 12 deletions(-) - -diff --git a/src/daemon.c b/src/daemon.c -index 66ac7ba..2b6650b 100644 ---- a/src/daemon.c -+++ b/src/daemon.c -@@ -219,60 +219,68 @@ entry_generator_fgetpwent (Daemon *daemon, - if (g_hash_table_size (shadow_users) == 0) { - g_clear_pointer (&shadow_users, g_hash_table_unref); - return NULL; - } - - fp = fopen (PATH_PASSWD, "r"); - if (fp == NULL) { - g_clear_pointer (&shadow_users, g_hash_table_unref); - g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno)); - return NULL; - } - - generator_state = g_malloc0 (sizeof (*generator_state)); - generator_state->fp = fp; - 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; - } -+ -+ /* Skip system users... */ -+ if (!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); -+ -+ return entry_generator_fgetpwent (daemon, users, state, spent); -+ } -+ - 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 (Daemon *daemon, - GHashTable *users, - gpointer *state, - struct spwd **shadow_entry) - { - struct passwd *pwent; - g_autoptr(GError) error = NULL; - gboolean regular; - GHashTableIter iter; - gpointer key, value; - GDir *dir; - - /* First iteration */ - if (*state == NULL) { - *state = g_dir_open (USERDIR, 0, &error); - if (error != NULL) { -@@ -373,66 +381,60 @@ entry_generator_requested_users (Daemon *daemon, - } - } - } - - /* Last iteration */ - - *state = NULL; - return NULL; - } - - static void - load_entries (Daemon *daemon, - GHashTable *users, - gboolean explicitly_requested, - EntryGeneratorFunc entry_generator) - { - DaemonPrivate *priv = daemon_get_instance_private (daemon); - 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 (!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; -- } -- - /* 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); - - if (user == NULL) { - user = g_hash_table_lookup (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)); - } - - if (!explicitly_requested) { - user_set_cached (user, TRUE); - } - } - - /* Generator should have cleaned up */ - g_assert (generator_state == NULL); -@@ -501,66 +503,66 @@ has_network_realms (Daemon *daemon) - - static void - reload_users (Daemon *daemon) - { - DaemonPrivate *priv = daemon_get_instance_private (daemon); - AccountsAccounts *accounts = ACCOUNTS_ACCOUNTS (daemon); - gboolean had_no_users, has_no_users, had_multiple_users, has_multiple_users; - GHashTable *users; - GHashTable *old_users; - GHashTable *local; - GHashTableIter iter; - gsize number_of_normal_users = 0; - gpointer name, value; - - /* 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, 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); - -+ /* and add users to hash table that were explicitly requested */ -+ load_entries (daemon, users, TRUE, entry_generator_requested_users); -+ - wtmp_helper_update_login_frequencies (users); - - /* Count the non-system users. Mark which users are local, which are not. */ - g_hash_table_iter_init (&iter, users); - while (g_hash_table_iter_next (&iter, &name, &value)) { - User *user = value; - if (!user_get_system_account (user)) - number_of_normal_users++; - user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL); - } - g_hash_table_destroy (local); - - had_no_users = accounts_accounts_get_has_no_users (accounts); - has_no_users = number_of_normal_users == 0; - - if (has_no_users && has_network_realms (daemon)) { - g_debug ("No local users, but network realms detected, presuming there are remote users"); - has_no_users = FALSE; - } - - if (had_no_users != has_no_users) - accounts_accounts_set_has_no_users (accounts, has_no_users); - - had_multiple_users = accounts_accounts_get_has_multiple_users (accounts); - has_multiple_users = number_of_normal_users > 1; - - if (had_multiple_users != has_multiple_users) - accounts_accounts_set_has_multiple_users (accounts, has_multiple_users); - - /* Swap out the users */ -@@ -1017,73 +1019,71 @@ daemon_find_user_by_name (AccountsAccounts *accounts, - - static ListUserData * - list_user_data_new (Daemon *daemon, - GDBusMethodInvocation *context) - { - ListUserData *data; - - data = g_new0 (ListUserData, 1); - - data->daemon = g_object_ref (daemon); - data->context = context; - - return data; - } - - static void - list_user_data_free (ListUserData *data) - { - g_object_unref (data->daemon); - g_free (data); - } - - static void - finish_list_cached_users (ListUserData *data) - { - DaemonPrivate *priv = daemon_get_instance_private (data->daemon); - g_autoptr(GPtrArray) object_paths = NULL; - GHashTableIter iter; - gpointer key, value; - uid_t uid; -- const gchar *shell; - - object_paths = g_ptr_array_new (); - - g_hash_table_iter_init (&iter, priv->users); - while (g_hash_table_iter_next (&iter, &key, &value)) { - const gchar *name = key; - User *user = value; - - uid = user_get_uid (user); -- shell = user_get_shell (user); - -- if (!user_classify_is_human (uid, name, shell, NULL)) { -+ if (user_get_system_account (user)) { - 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); - - list_user_data_free (data); - } - - static gboolean - daemon_list_cached_users (AccountsAccounts *accounts, - GDBusMethodInvocation *context) - { - Daemon *daemon = (Daemon*)accounts; - DaemonPrivate *priv = daemon_get_instance_private (daemon); - ListUserData *data; - - data = list_user_data_new (daemon, context); - - if (priv->reload_id > 0) { --- -2.31.1 - diff --git a/SOURCES/0001-daemon-if-no-local-users-check-if-machine-is-enrolle.patch b/SOURCES/0001-daemon-if-no-local-users-check-if-machine-is-enrolle.patch deleted file mode 100644 index 5185345..0000000 --- a/SOURCES/0001-daemon-if-no-local-users-check-if-machine-is-enrolle.patch +++ /dev/null @@ -1,1839 +0,0 @@ -From 54b207649979475ea7f1fa5eaaea94be31d20935 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 13 Dec 2019 15:16:06 -0500 -Subject: [PATCH] daemon: if no local users, check if machine is enrolled in - network - -GDM will show gnome initial-setup if a machine has no local users. -But it's totally possible that a machine has only remote users, -and shouldn't have a local user. - -This commit detects that case, and avoids setting the HasNoUsers -property. ---- - data/org.freedesktop.realmd.xml | 730 ++++++++++++++++++++++++++++++++ - src/daemon.c | 63 ++- - src/meson.build | 1 + - src/org.freedesktop.realmd.xml | 730 ++++++++++++++++++++++++++++++++ - 4 files changed, 1520 insertions(+), 4 deletions(-) - create mode 100644 data/org.freedesktop.realmd.xml - create mode 100644 src/org.freedesktop.realmd.xml - -diff --git a/data/org.freedesktop.realmd.xml b/data/org.freedesktop.realmd.xml -new file mode 100644 -index 0000000..c34a47a ---- /dev/null -+++ b/data/org.freedesktop.realmd.xml -@@ -0,0 +1,730 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/src/daemon.c b/src/daemon.c -index c52bda3..5ce0216 100644 ---- a/src/daemon.c -+++ b/src/daemon.c -@@ -20,60 +20,61 @@ - * Written by: Matthias Clasen - */ - - #include "config.h" - - #include - #include - #include - #include - #include - #include - #include - #ifdef HAVE_SHADOW_H - #include - #endif - #include - #include - #include - - #include - #include - #include - #include - #include - #include - - #include "user-classify.h" - #include "wtmp-helper.h" - #include "daemon.h" - #include "util.h" -+#include "realmd-generated.h" - - #define PATH_PASSWD "/etc/passwd" - #define PATH_SHADOW "/etc/shadow" - #define PATH_GROUP "/etc/group" - - enum { - PROP_0, - PROP_DAEMON_VERSION - }; - - typedef struct { - GDBusConnection *bus_connection; - - GHashTable *users; - gsize number_of_normal_users; - GList *explicitly_requested_users; - - User *autologin; - - GFileMonitor *passwd_monitor; - GFileMonitor *shadow_monitor; - GFileMonitor *group_monitor; - GFileMonitor *gdm_monitor; - GFileMonitor *wtmp_monitor; - - GQueue *pending_list_cached_users; - - guint reload_id; - guint autologin_id; - -@@ -425,110 +426,167 @@ load_entries (Daemon *daemon, - } 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)); - } - - 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 gboolean -+ensure_bus_connection (Daemon *daemon) -+{ -+ DaemonPrivate *priv = daemon_get_instance_private (daemon); -+ g_autoptr (GError) error = NULL; -+ -+ if (priv->bus_connection != NULL) -+ return TRUE; -+ -+ priv->bus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); -+ if (priv->bus_connection == NULL) { -+ if (error != NULL) -+ g_critical ("error getting system bus: %s", error->message); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static gboolean -+has_network_realms (Daemon *daemon) -+{ -+ DaemonPrivate *priv = daemon_get_instance_private (daemon); -+ g_autoptr (AccountsRealmdProvider) realmd_provider = NULL; -+ g_autoptr (GError) error = NULL; -+ const char *const *realms = NULL; -+ -+ if (!ensure_bus_connection (daemon)) { -+ return FALSE; -+ } -+ -+ realmd_provider = accounts_realmd_provider_proxy_new_sync (priv->bus_connection, -+ G_DBUS_PROXY_FLAGS_NONE, -+ "org.freedesktop.realmd", -+ "/org/freedesktop/realmd", -+ NULL, -+ &error); -+ if (realmd_provider == NULL) { -+ g_debug ("failed to contact realmd: %s", error->message); -+ return FALSE; -+ } -+ -+ realms = accounts_realmd_provider_get_realms (realmd_provider); -+ -+ if (!realms) { -+ g_debug("realmd provider 'Realms' property is unset"); -+ return FALSE; -+ } -+ -+ return realms[0] != NULL; -+} -+ - static void - reload_users (Daemon *daemon) - { - DaemonPrivate *priv = daemon_get_instance_private (daemon); - AccountsAccounts *accounts = ACCOUNTS_ACCOUNTS (daemon); - gboolean had_no_users, has_no_users, had_multiple_users, has_multiple_users; - GHashTable *users; - GHashTable *old_users; - GHashTable *local; - GHashTableIter iter; - gsize number_of_normal_users = 0; - gpointer name, value; - - /* 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, 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); - - wtmp_helper_update_login_frequencies (users); - - /* Count the non-system users. Mark which users are local, which are not. */ - g_hash_table_iter_init (&iter, users); - while (g_hash_table_iter_next (&iter, &name, &value)) { - User *user = value; - if (!user_get_system_account (user)) - number_of_normal_users++; - user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL); - } - g_hash_table_destroy (local); - - had_no_users = accounts_accounts_get_has_no_users (accounts); - has_no_users = number_of_normal_users == 0; - -+ if (has_no_users && has_network_realms (daemon)) { -+ g_debug ("No local users, but network realms detected, presuming there are remote users"); -+ has_no_users = FALSE; -+ } -+ - if (had_no_users != has_no_users) - accounts_accounts_set_has_no_users (accounts, has_no_users); - - had_multiple_users = accounts_accounts_get_has_multiple_users (accounts); - has_multiple_users = number_of_normal_users > 1; - - if (had_multiple_users != has_multiple_users) - accounts_accounts_set_has_multiple_users (accounts, has_multiple_users); - - /* Swap out the users */ - old_users = priv->users; - priv->users = users; - - /* Remove all the old users */ - g_hash_table_iter_init (&iter, old_users); - while (g_hash_table_iter_next (&iter, &name, &value)) { - User *user = value; - User *refreshed_user; - - refreshed_user = g_hash_table_lookup (users, name); - - if (!refreshed_user || (user_get_cached (user) && !user_get_cached (refreshed_user))) { - accounts_accounts_emit_user_deleted (ACCOUNTS_ACCOUNTS (daemon), - user_get_object_path (user)); - user_unregister (user); - } - } - - /* Register all the new users */ - g_hash_table_iter_init (&iter, users); -@@ -766,64 +824,61 @@ daemon_finalize (GObject *object) - priv = daemon_get_instance_private (daemon); - - if (priv->bus_connection != NULL) - g_object_unref (priv->bus_connection); - - g_queue_free_full (priv->pending_list_cached_users, - (GDestroyNotify) list_user_data_free); - - g_list_free_full (priv->explicitly_requested_users, g_free); - - g_hash_table_destroy (priv->users); - - g_hash_table_unref (priv->extension_ifaces); - - G_OBJECT_CLASS (daemon_parent_class)->finalize (object); - } - - static gboolean - register_accounts_daemon (Daemon *daemon) - { - DaemonPrivate *priv = daemon_get_instance_private (daemon); - g_autoptr(GError) error = NULL; - - priv->authority = polkit_authority_get_sync (NULL, &error); - if (priv->authority == NULL) { - if (error != NULL) - g_critical ("error getting polkit authority: %s", error->message); - return FALSE; - } - -- priv->bus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); -- if (priv->bus_connection == NULL) { -- if (error != NULL) -- g_critical ("error getting system bus: %s", error->message); -+ if (!ensure_bus_connection (daemon)) { - return FALSE; - } - - if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon), - priv->bus_connection, - "/org/freedesktop/Accounts", - &error)) { - if (error != NULL) - g_critical ("error exporting interface: %s", error->message); - return FALSE; - } - - return TRUE; - } - - Daemon * - daemon_new (void) - { - g_autoptr(Daemon) daemon = NULL; - - daemon = DAEMON (g_object_new (TYPE_DAEMON, NULL)); - - if (!register_accounts_daemon (DAEMON (daemon))) { - return NULL; - } - - return g_steal_pointer (&daemon); - } - - static void -diff --git a/src/meson.build b/src/meson.build -index 20d5276..3970749 100644 ---- a/src/meson.build -+++ b/src/meson.build -@@ -1,37 +1,38 @@ - sources = [] - - gdbus_headers = [] - - ifaces = [ - ['accounts-generated', 'org.freedesktop.', 'Accounts'], - ['accounts-user-generated', act_namespace + '.', 'User'], -+ ['realmd-generated', 'org.freedesktop.', 'realmd'], - ] - - foreach iface: ifaces - gdbus_sources = gnome.gdbus_codegen( - iface[0], - join_paths(data_dir, iface[1] + iface[2] + '.xml'), - interface_prefix: iface[1], - namespace: 'Accounts', - ) - sources += gdbus_sources - gdbus_headers += gdbus_sources[1] - endforeach - - deps = [ - gio_dep, - gio_unix_dep, - ] - - cflags = [ - '-DLOCALSTATEDIR="@0@"'.format(act_localstatedir), - '-DDATADIR="@0@"'.format(act_datadir), - '-DICONDIR="@0@"'.format(join_paths(act_localstatedir, 'lib', 'AccountsService', 'icons')), - '-DUSERDIR="@0@"'.format(join_paths(act_localstatedir, 'lib', 'AccountsService', 'users')), - ] - - libaccounts_generated = static_library( - 'accounts-generated', - sources: sources, - include_directories: top_inc, - dependencies: deps, -diff --git a/src/org.freedesktop.realmd.xml b/src/org.freedesktop.realmd.xml -new file mode 100644 -index 0000000..c34a47a ---- /dev/null -+++ b/src/org.freedesktop.realmd.xml -@@ -0,0 +1,730 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ --- -2.27.0 - diff --git a/SOURCES/0001-data-don-t-send-change-updates-for-login-history.patch b/SOURCES/0001-data-don-t-send-change-updates-for-login-history.patch deleted file mode 100644 index 94d6c7a..0000000 --- a/SOURCES/0001-data-don-t-send-change-updates-for-login-history.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 50edc5e45bb984576506e7b2bfb4c267ac566099 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 9 May 2019 14:58:34 -0400 -Subject: [PATCH] data: don't send change updates for login-history - -The login-history property of user objects can be quite large. -If wtmp is changed frequently, that can lead to memory fragmentation -in clients. - -Furthermore, most clients never check login-history, so it's -wasted memory and wasted cpu. - -This commit disables change notification for that property. If -a client really needs to get updates, they can manually refresh -their cache when appropriate. ---- - data/org.freedesktop.Accounts.User.xml | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/data/org.freedesktop.Accounts.User.xml b/data/org.freedesktop.Accounts.User.xml -index 8d3fe1c..3b839a3 100644 ---- a/data/org.freedesktop.Accounts.User.xml -+++ b/data/org.freedesktop.Accounts.User.xml -@@ -785,60 +785,61 @@ - - - - The users location. - - - - - - - - - - How often the user has logged in. - - - - - - - - - - The last login time. - - - - - - -+ - - - - The login history for this user. - Each entry in the array represents a login session. The first two - members are the login time and logout time, as timestamps (seconds since the epoch). If the session is still running, the logout time - is 0. - - - The a{sv} member is a dictionary containing additional information - about the session. Possible members include 'type' (with values like ':0', 'tty0', 'pts/0' etc). - - - - - - - - - - The filename of a png file containing the users icon. - - - - - - - - - --- -2.27.0 - diff --git a/SOURCES/0001-lib-save-os-when-creating-user.patch b/SOURCES/0001-lib-save-os-when-creating-user.patch deleted file mode 100644 index 08d953d..0000000 --- a/SOURCES/0001-lib-save-os-when-creating-user.patch +++ /dev/null @@ -1,894 +0,0 @@ -From 5124220f12a157ff285072a4f786db2c94c3ca8a Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 14 Jan 2021 15:07:34 -0500 -Subject: [PATCH] lib: save os when creating user - -In order to identify that a user has upgraded from rhel 7 to -rhel 8, we need to know what os they were using when created. - -This commit saves that information using a red hat specific -extension to accountsservice. ---- - .../com.redhat.AccountsServiceUser.System.xml | 10 ++ - data/meson.build | 1 + - meson.build | 1 + - meson_post_install.py | 15 +++ - src/libaccountsservice/act-user-manager.c | 123 ++++++++++++++++++ - src/libaccountsservice/meson.build | 7 + - 6 files changed, 157 insertions(+) - create mode 100644 data/com.redhat.AccountsServiceUser.System.xml - -diff --git a/data/com.redhat.AccountsServiceUser.System.xml b/data/com.redhat.AccountsServiceUser.System.xml -new file mode 100644 -index 0000000..67f5f30 ---- /dev/null -+++ b/data/com.redhat.AccountsServiceUser.System.xml -@@ -0,0 +1,10 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/data/meson.build b/data/meson.build -index 4987937..2dc57c2 100644 ---- a/data/meson.build -+++ b/data/meson.build -@@ -1,33 +1,34 @@ - ifaces = files( - act_namespace + '.xml', - act_namespace + '.User.xml', -+ 'com.redhat.AccountsServiceUser.System.xml', - ) - - install_data( - ifaces, - install_dir: dbus_ifaces_dir, - ) - - install_data( - act_namespace + '.conf', - install_dir: dbus_conf_dir, - ) - - service_conf = configuration_data() - service_conf.set('libexecdir', act_libexecdir) - - service = act_namespace + '.service' - - configure_file( - input: service + '.in', - output: service, - configuration: service_conf, - install: true, - install_dir: dbus_sys_dir, - ) - - policy = act_namespace.to_lower() + '.policy' - - i18n.merge_file( - policy, - input: policy + '.in', -diff --git a/meson.build b/meson.build -index 4465a26..e37c451 100644 ---- a/meson.build -+++ b/meson.build -@@ -174,38 +174,39 @@ assert(not enable_systemd or not enable_elogind, 'systemd and elogind support re - if enable_systemd - logind_dep = dependency('libsystemd', version: '>= 186') - endif - - if enable_elogind - logind_dep = dependency('libelogind', version: '>= 229.4') - endif - config_h.set('WITH_SYSTEMD', enable_systemd or enable_elogind) - - subdir('data') - subdir('src') - subdir('po') - - enable_docbook = get_option('docbook') - if enable_docbook - subdir('doc/dbus') - endif - - if get_option('gtk_doc') - subdir('doc/libaccountsservice') - endif - - configure_file( - output: 'config.h', - configuration: config_h, - ) - - meson.add_install_script( - 'meson_post_install.py', - act_localstatedir, -+ act_datadir, - ) - - output = '\n' + meson.project_name() + ' was configured with the following options:\n' - output += '** DocBook documentation build: ' + enable_docbook.to_string() + '\n' - output += '** Administrator group: ' + admin_group + '\n' - output += '** Extra administrator groups: ' + extra_admin_groups + '\n' - output += '** GDM configuration: ' + gdm_conf_file - message(output) -diff --git a/meson_post_install.py b/meson_post_install.py -index 5cc2dc4..e1d5a71 100644 ---- a/meson_post_install.py -+++ b/meson_post_install.py -@@ -1,18 +1,33 @@ - #!/usr/bin/env python3 - - import os - import sys - - destdir = os.environ.get('DESTDIR', '') - localstatedir = os.path.normpath(destdir + os.sep + sys.argv[1]) -+datadir = os.path.normpath(destdir + os.sep + sys.argv[2]) -+interfacedir = os.path.join(datadir, 'accountsservice', 'interfaces') - - # FIXME: meson will not track the creation of these directories - # https://github.com/mesonbuild/meson/blob/master/mesonbuild/scripts/uninstall.py#L39 - dst_dirs = [ - (os.path.join(localstatedir, 'lib', 'AccountsService', 'icons'), 0o775), - (os.path.join(localstatedir, 'lib', 'AccountsService', 'users'), 0o700), -+ (interfacedir, 0o775), - ] - - for (dst_dir, dst_dir_mode) in dst_dirs: - if not os.path.exists(dst_dir): - os.makedirs(dst_dir, mode=dst_dir_mode) -+ -+interface_files = [ -+ 'com.redhat.AccountsServiceUser.System.xml', -+] -+ -+for interface_file in interface_files: -+ src_path = os.path.join('../../dbus-1/interfaces', interface_file) -+ dst_path = os.path.join(interfacedir, interface_file) -+ if not os.path.exists(dst_path): -+ os.symlink(src_path, dst_path) -+ -+ -diff --git a/src/libaccountsservice/act-user-manager.c b/src/libaccountsservice/act-user-manager.c -index 1b5298d..f4598c4 100644 ---- a/src/libaccountsservice/act-user-manager.c -+++ b/src/libaccountsservice/act-user-manager.c -@@ -27,60 +27,61 @@ - #include - #include - #include - #include - #include - - #ifdef HAVE_PATHS_H - #include - #endif /* HAVE_PATHS_H */ - - #include - #include - #include - #include - #include - #include - - #ifdef WITH_SYSTEMD - #include - - /* check if logind is running */ - #define LOGIND_RUNNING() (access("/run/systemd/seats/", F_OK) >= 0) - #endif - - #include "act-user-manager.h" - #include "act-user-private.h" - #include "accounts-generated.h" - #include "ck-manager-generated.h" - #include "ck-seat-generated.h" - #include "ck-session-generated.h" -+#include "com.redhat.AccountsServiceUser.System.h" - - /** - * SECTION:act-user-manager - * @title: ActUserManager - * @short_description: manages ActUser objects - * - * ActUserManager is a manager object that gives access to user - * creation, deletion, enumeration, etc. - * - * There is typically a singleton ActUserManager object, which - * can be obtained by act_user_manager_get_default(). - */ - - /** - * ActUserManager: - * - * A user manager object. - */ - - /** - * ACT_USER_MANAGER_ERROR: - * - * The GError domain for #ActUserManagerError errors - */ - - /** - * ActUserManagerError: - * @ACT_USER_MANAGER_ERROR_FAILED: Generic failure - * @ACT_USER_MANAGER_ERROR_USER_EXISTS: The user already exists - * @ACT_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST: The user does not exist -@@ -165,60 +166,63 @@ typedef struct - ActUser *user; - ActUserManagerFetchUserRequestType type; - union { - char *username; - uid_t uid; - }; - char *object_path; - char *description; - } ActUserManagerFetchUserRequest; - - typedef struct - { - GHashTable *normal_users_by_name; - GHashTable *system_users_by_name; - GHashTable *users_by_object_path; - GHashTable *sessions; - GDBusConnection *connection; - AccountsAccounts *accounts_proxy; - ConsoleKitManager *ck_manager_proxy; - - ActUserManagerSeat seat; - - GSList *new_sessions; - GSList *new_users; - GSList *new_users_inhibiting_load; - GSList *fetch_user_requests; - - GSList *exclude_usernames; - GSList *include_usernames; - -+ char *os_id; -+ char *os_version_id; -+ - guint load_id; - - gboolean is_loaded; - gboolean has_multiple_users; - gboolean getting_sessions; - gboolean list_cached_users_done; - } ActUserManagerPrivate; - - enum { - PROP_0, - PROP_INCLUDE_USERNAMES_LIST, - PROP_EXCLUDE_USERNAMES_LIST, - PROP_IS_LOADED, - PROP_HAS_MULTIPLE_USERS - }; - - enum { - USER_ADDED, - USER_REMOVED, - USER_IS_LOGGED_IN_CHANGED, - USER_CHANGED, - LAST_SIGNAL - }; - - static guint signals [LAST_SIGNAL] = { 0, }; - - static void act_user_manager_class_init (ActUserManagerClass *klass); - static void act_user_manager_init (ActUserManager *user_manager); - static void act_user_manager_finalize (GObject *object); - -@@ -2942,100 +2946,173 @@ ensure_accounts_proxy (ActUserManager *manager) - G_DBUS_PROXY_FLAGS_NONE, - ACCOUNTS_NAME, - ACCOUNTS_PATH, - NULL, - &error); - if (error != NULL) { - g_debug ("ActUserManager: getting account proxy failed: %s", error->message); - return FALSE; - } - - g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (priv->accounts_proxy), G_MAXINT); - - g_object_bind_property (G_OBJECT (priv->accounts_proxy), - "has-multiple-users", - G_OBJECT (manager), - "has-multiple-users", - G_BINDING_SYNC_CREATE); - - g_signal_connect (priv->accounts_proxy, - "user-added", - G_CALLBACK (on_new_user_in_accounts_service), - manager); - g_signal_connect (priv->accounts_proxy, - "user-deleted", - G_CALLBACK (on_user_removed_in_accounts_service), - manager); - - return TRUE; - } - -+static inline gboolean -+is_valid_char (gchar c, -+ gboolean first) -+{ -+ return (!first && g_ascii_isdigit (c)) || -+ c == '_' || -+ g_ascii_isalpha (c); -+} -+ -+static void -+load_os_release (ActUserManager *manager) -+{ -+ ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); -+ g_autoptr(GFile) file = NULL; -+ g_autoptr(GError) error = NULL; -+ g_autofree char *contents = NULL; -+ g_auto(GStrv) lines = NULL; -+ size_t i; -+ -+ file = g_file_new_for_path ("/etc/os-release"); -+ -+ if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, &error)) { -+ g_debug ("ActUserManager: couldn't load /etc/os-release: %s", error->message); -+ return; -+ } -+ -+ lines = g_strsplit (contents, "\n", -1); -+ for (i = 0; lines[i] != NULL; i++) { -+ char *p, *name, *name_end, *value, *value_end; -+ -+ p = lines[i]; -+ -+ while (g_ascii_isspace (*p)) -+ p++; -+ -+ if (*p == '#' || *p == '\0') -+ continue; -+ name = p; -+ while (is_valid_char (*p, p == name)) -+ p++; -+ name_end = p; -+ while (g_ascii_isspace (*p)) -+ p++; -+ if (name == name_end || *p != '=') { -+ continue; -+ } -+ *name_end = '\0'; -+ -+ p++; -+ -+ while (g_ascii_isspace (*p)) -+ p++; -+ -+ value = p; -+ value_end = value + strlen (value) - 1; -+ -+ if (value != value_end && *value == '"' && *value_end == '"') { -+ value++; -+ *value_end = '\0'; -+ } -+ -+ if (strcmp (name, "ID") == 0) { -+ g_debug ("ActUserManager: system OS is '%s'", value); -+ priv->os_id = g_strdup (value); -+ } else if (strcmp (name, "VERSION_ID") == 0) { -+ g_debug ("ActUserManager: system OS version is '%s'", value); -+ priv->os_version_id = g_strdup (value); -+ } -+ } -+} -+ - static void - act_user_manager_init (ActUserManager *manager) - { - ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); - g_autoptr(GError) error = NULL; - - act_user_manager_error_quark (); /* register dbus errors */ - - /* sessions */ - priv->sessions = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_object_unref); - - /* users */ - priv->normal_users_by_name = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_object_unref); - priv->system_users_by_name = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_object_unref); - priv->users_by_object_path = g_hash_table_new_full (g_str_hash, - g_str_equal, - NULL, - g_object_unref); - - priv->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); - if (priv->connection == NULL) { - if (error != NULL) { - g_warning ("Failed to connect to the D-Bus daemon: %s", error->message); - } else { - g_warning ("Failed to connect to the D-Bus daemon"); - } - return; - } - - ensure_accounts_proxy (manager); - -+ load_os_release (manager); -+ - priv->seat.state = ACT_USER_MANAGER_SEAT_STATE_UNLOADED; - } - - static void - act_user_manager_finalize (GObject *object) - { - ActUserManager *manager = ACT_USER_MANAGER (object); - ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); - GSList *node; - - g_debug ("ActUserManager: finalizing user manager"); - - g_slist_foreach (priv->new_sessions, - (GFunc) unload_new_session, NULL); - g_slist_free (priv->new_sessions); - - g_slist_foreach (priv->fetch_user_requests, - (GFunc) free_fetch_user_request, NULL); - g_slist_free (priv->fetch_user_requests); - - g_slist_free (priv->new_users_inhibiting_load); - - node = priv->new_users; - while (node != NULL) { - ActUser *user; - GSList *next_node; - - user = ACT_USER (node->data); - next_node = node->next; - -@@ -3071,143 +3148,181 @@ act_user_manager_finalize (GObject *object) - - #ifdef WITH_SYSTEMD - if (priv->seat.session_monitor != NULL) { - sd_login_monitor_unref (priv->seat.session_monitor); - } - - if (priv->seat.session_monitor_stream != NULL) { - g_object_unref (priv->seat.session_monitor_stream); - } - - if (priv->seat.session_monitor_source_id != 0) { - g_source_remove (priv->seat.session_monitor_source_id); - } - #endif - - if (priv->accounts_proxy != NULL) { - g_object_unref (priv->accounts_proxy); - } - - if (priv->load_id > 0) { - g_source_remove (priv->load_id); - priv->load_id = 0; - } - - g_hash_table_destroy (priv->sessions); - - g_hash_table_destroy (priv->normal_users_by_name); - g_hash_table_destroy (priv->system_users_by_name); - g_hash_table_destroy (priv->users_by_object_path); - -+ g_free (priv->os_id); -+ g_free (priv->os_version_id); -+ - G_OBJECT_CLASS (act_user_manager_parent_class)->finalize (object); - } - - /** - * act_user_manager_get_default: - * - * Returns the user manager singleton instance. Calling this function will - * automatically being loading the user list if it isn't loaded already. - * The #ActUserManager:is-loaded property will be set to %TRUE when the users - * are finished loading and then act_user_manager_list_users() can be called. - * - * Returns: (transfer none): user manager object - */ - ActUserManager * - act_user_manager_get_default (void) - { - if (user_manager_object == NULL) { - user_manager_object = g_object_new (ACT_TYPE_USER_MANAGER, NULL); - g_object_add_weak_pointer (user_manager_object, - (gpointer *) &user_manager_object); - act_user_manager_queue_load (user_manager_object); - } - - return ACT_USER_MANAGER (user_manager_object); - } - - /** - * act_user_manager_no_service: - * @manager: a #ActUserManager - * - * Check whether or not the accounts service is running. - * - * Returns: whether or not accounts service is running - */ - gboolean - act_user_manager_no_service (ActUserManager *manager) - { - ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); - return priv->accounts_proxy == NULL; - } - -+static void -+save_system_info (ActUserManager *manager, -+ const char *user_path) -+{ -+ ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); -+ ActUserSystem *user_system_proxy = NULL; -+ g_autoptr(GError) error = NULL; -+ -+ if (priv->os_id == NULL && priv->os_version_id == NULL) -+ return; -+ -+ user_system_proxy = act_user_system_proxy_new_sync (priv->connection, -+ G_DBUS_PROXY_FLAGS_NONE, -+ ACCOUNTS_NAME, -+ user_path, -+ NULL, -+ &error); -+ if (user_system_proxy != NULL) { -+ if (priv->os_id != NULL) -+ act_user_system_set_id (user_system_proxy, priv->os_id); -+ -+ if (priv->os_version_id != NULL) -+ act_user_system_set_version_id (user_system_proxy, priv->os_version_id); -+ } else { -+ /* probably means accountsservice and lib are out of sync */ -+ g_debug ("ActUserManager: failed to create user system proxy: %s", -+ error? error->message: ""); -+ g_clear_error (&error); -+ } -+ -+ g_clear_object (&user_system_proxy); -+} -+ - /** - * act_user_manager_create_user: - * @manager: a #ActUserManager - * @username: a unix user name - * @fullname: a unix GECOS value - * @accounttype: a #ActUserAccountType - * @error: a #GError - * - * Creates a user account on the system. - * - * Returns: (transfer full): user object - */ - ActUser * - act_user_manager_create_user (ActUserManager *manager, - const char *username, - const char *fullname, - ActUserAccountType accounttype, - GError **error) - { - ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); - GError *local_error = NULL; - gboolean res; - g_autofree gchar *path = NULL; - ActUser *user; - - g_debug ("ActUserManager: Creating user '%s', '%s', %d", - username, fullname, accounttype); - - g_assert (priv->accounts_proxy != NULL); - - res = accounts_accounts_call_create_user_sync (priv->accounts_proxy, - username, - fullname, - accounttype, - &path, - NULL, - &local_error); - if (!res) { - g_propagate_error (error, local_error); - return NULL; - } - -+ save_system_info (manager, path); -+ - user = add_new_user_for_object_path (path, manager); - - return user; - } - - static void - act_user_manager_async_complete_handler (GObject *source, - GAsyncResult *result, - gpointer user_data) - { - GTask *task = user_data; - - g_task_return_pointer (task, g_object_ref (result), g_object_unref); - g_object_unref (task); - } - - /** - * act_user_manager_create_user_async: - * @manager: a #ActUserManager - * @username: a unix user name - * @fullname: a unix GECOS value - * @accounttype: a #ActUserAccountType - * @cancellable: (allow-none): optional #GCancellable object, - * %NULL to ignore - * @callback: (scope async): a #GAsyncReadyCallback to call - * when the request is satisfied - * @user_data: (closure): the data to pass to @callback - * - * Asynchronously creates a user account on the system. - * -@@ -3253,106 +3368,111 @@ act_user_manager_create_user_async (ActUserManager *manager, - * @manager: a #ActUserManager - * @result: a #GAsyncResult - * @error: a #GError - * - * Finishes an asynchronous user creation. - * - * See act_user_manager_create_user_async(). - * - * Returns: (transfer full): user object - * - * Since: 0.6.27 - */ - ActUser * - act_user_manager_create_user_finish (ActUserManager *manager, - GAsyncResult *result, - GError **error) - { - ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); - GAsyncResult *inner_result; - ActUser *user = NULL; - g_autofree gchar *path = NULL; - GError *remote_error = NULL; - - inner_result = g_task_propagate_pointer (G_TASK (result), error); - if (inner_result == NULL) { - return FALSE; - } - - if (accounts_accounts_call_create_user_finish (priv->accounts_proxy, - &path, inner_result, &remote_error)) { -+ -+ save_system_info (manager, path); -+ - user = add_new_user_for_object_path (path, manager); - } - - if (remote_error) { - g_dbus_error_strip_remote_error (remote_error); - g_propagate_error (error, remote_error); - } - - return user; - } - - /** - * act_user_manager_cache_user: - * @manager: a #ActUserManager - * @username: a user name - * @error: a #GError - * - * Caches a user account so it shows up via act_user_manager_list_users(). - * - * Returns: (transfer full): user object - */ - ActUser * - act_user_manager_cache_user (ActUserManager *manager, - const char *username, - GError **error) - { - ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); - GError *local_error = NULL; - gboolean res; - g_autofree gchar *path = NULL; - - g_debug ("ActUserManager: Caching user '%s'", - username); - - g_assert (priv->accounts_proxy != NULL); - - res = accounts_accounts_call_cache_user_sync (priv->accounts_proxy, - username, - &path, - NULL, - &local_error); - if (!res) { - g_propagate_error (error, local_error); - return NULL; - } - -+ save_system_info (manager, path); -+ - return add_new_user_for_object_path (path, manager); - } - - - /** - * act_user_manager_cache_user_async: - * @manager: a #ActUserManager - * @username: a unix user name - * @cancellable: (allow-none): optional #GCancellable object, - * %NULL to ignore - * @callback: (scope async): a #GAsyncReadyCallback to call - * when the request is satisfied - * @user_data: (closure): the data to pass to @callback - * - * Asynchronously caches a user account so it shows up via - * act_user_manager_list_users(). - * - * For more details, see act_user_manager_cache_user(), which - * is the synchronous version of this call. - * - * Since: 0.6.27 - */ - void - act_user_manager_cache_user_async (ActUserManager *manager, - const char *username, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) - { - ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); -@@ -3378,60 +3498,63 @@ act_user_manager_cache_user_async (ActUserManager *manager, - * @manager: a #ActUserManager - * @result: a #GAsyncResult - * @error: a #GError - * - * Finishes an asynchronous user caching. - * - * See act_user_manager_cache_user_async(). - * - * Returns: (transfer full): user object - * - * Since: 0.6.27 - */ - ActUser * - act_user_manager_cache_user_finish (ActUserManager *manager, - GAsyncResult *result, - GError **error) - { - ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); - GAsyncResult *inner_result; - ActUser *user = NULL; - g_autofree gchar *path = NULL; - GError *remote_error = NULL; - - inner_result = g_task_propagate_pointer (G_TASK (result), error); - if (inner_result == NULL) { - return FALSE; - } - - if (accounts_accounts_call_cache_user_finish (priv->accounts_proxy, - &path, inner_result, &remote_error)) { -+ -+ save_system_info (manager, path); -+ - user = add_new_user_for_object_path (path, manager); - } - - if (remote_error) { - g_dbus_error_strip_remote_error (remote_error); - g_propagate_error (error, remote_error); - } - - return user; - } - - /** - * act_user_manager_uncache_user: - * @manager: a #ActUserManager - * @username: a user name - * @error: a #GError - * - * Releases all metadata about a user account, including icon, - * language and session. If the user account is from a remote - * server and the user has never logged in before, then that - * account will no longer show up in ListCachedUsers() output. - * - * Returns: %TRUE if successful, otherwise %FALSE - */ - gboolean - act_user_manager_uncache_user (ActUserManager *manager, - const char *username, - GError **error) - { - ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); -diff --git a/src/libaccountsservice/meson.build b/src/libaccountsservice/meson.build -index 4e134db..9e85bba 100644 ---- a/src/libaccountsservice/meson.build -+++ b/src/libaccountsservice/meson.build -@@ -21,60 +21,67 @@ enum_types = 'act-user-enum-types' - - enum_sources = gnome.mkenums( - enum_types, - sources: headers, - c_template: enum_types + '.c.template', - h_template: enum_types + '.h.template', - install_header: true, - install_dir: join_paths(act_pkgincludedir, subdir), - ) - - dbus_sources = [] - - ifaces = [ - 'Manager', - 'Seat', - 'Session', - ] - - namespace = 'ConsoleKit' - prefix = 'org.freedesktop.' + namespace - - foreach iface: ifaces - dbus_sources += gnome.gdbus_codegen( - 'ck-@0@-generated'.format(iface.to_lower()), - '@0@.@1@.xml'.format(prefix, iface), - interface_prefix: prefix, - namespace: namespace, - ) - endforeach - -+dbus_sources += gnome.gdbus_codegen( -+ 'com.redhat.AccountsServiceUser.System', -+ join_paths(data_dir, 'com.redhat.AccountsServiceUser.System.xml'), -+ interface_prefix: 'com.redhat.AccountsService', -+ namespace: 'Act', -+) -+ - deps = [ - crypt_dep, - gio_unix_dep, - glib_dep, - libaccounts_generated_dep, - ] - - symbol_map = join_paths(meson.current_source_dir(), 'symbol.map') - ldflags = cc.get_supported_link_arguments('-Wl,--version-script,@0@'.format(symbol_map)) - - if enable_systemd or enable_elogind - deps += logind_dep - endif - - libaccountsservice = shared_library( - act_name, - sources: sources + enum_sources + dbus_sources, - version: libversion, - include_directories: top_inc, - dependencies: deps, - c_args: '-DG_LOG_DOMAIN="@0@"'.format(meson.project_name()), - link_args: ldflags, - link_depends: symbol_map, - install: true, - ) - - libaccountsservice_dep = declare_dependency( - sources: enum_sources[1], - include_directories: include_directories('.'), - dependencies: [gio_dep, glib_dep], --- -2.27.0 - diff --git a/SOURCES/0001-user-Introduce-user-templates-for-setting-default-se.patch b/SOURCES/0001-user-Introduce-user-templates-for-setting-default-se.patch deleted file mode 100644 index 001de67..0000000 --- a/SOURCES/0001-user-Introduce-user-templates-for-setting-default-se.patch +++ /dev/null @@ -1,925 +0,0 @@ -From 72427bd4fcae931298c670093f9cbd34ad58f59a Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 4 Aug 2021 19:54:59 -0400 -Subject: [PATCH] user: Introduce user templates for setting default session - etc - -At the moment there's no easy way to set a default session, or -face icon or whatever for all users. If a user has never logged in -before, we just generate their cache file from hardcoded defaults. - -This commit introduces a template system to make it possible for -admins to set up defaults on their own. - -Admins can write either -/etc/accountsservice/user-templates/administrator -or -/etc/accountsservice/user-templates/standard - -files. These files follow the same format as - -/var/lib/AccountsService/users/username - -files, but will support substituting $HOME and $USER to the appropriate -user specific values. - -User templates also support an additional group [Template] that -have an additional key EnvironmentFiles that specify a list -of environment files to load (files with KEY=VALUE pairs in them). -Any keys listed in those environment files will also get substituted. ---- - data/administrator | 6 + - data/meson.build | 10 ++ - data/standard | 6 + - src/daemon.c | 8 +- - src/meson.build | 1 + - src/user.c | 284 ++++++++++++++++++++++++++++++++++++++++++++- - src/user.h | 3 +- - 7 files changed, 305 insertions(+), 13 deletions(-) - create mode 100644 data/administrator - create mode 100644 data/standard - -diff --git a/data/administrator b/data/administrator -new file mode 100644 -index 0000000..ea043c9 ---- /dev/null -+++ b/data/administrator -@@ -0,0 +1,6 @@ -+[Template] -+#EnvironmentFiles=/etc/os-release; -+ -+[User] -+Session= -+Icon=${HOME}/.face -diff --git a/data/meson.build b/data/meson.build -index 2dc57c2..7d9bdcd 100644 ---- a/data/meson.build -+++ b/data/meson.build -@@ -22,30 +22,40 @@ service = act_namespace + '.service' - configure_file( - input: service + '.in', - output: service, - configuration: service_conf, - install: true, - install_dir: dbus_sys_dir, - ) - - policy = act_namespace.to_lower() + '.policy' - - i18n.merge_file( - policy, - input: policy + '.in', - output: policy, - po_dir: po_dir, - install: true, - install_dir: policy_dir, - ) - - if install_systemd_unit_dir - service = 'accounts-daemon.service' - - configure_file( - input: service + '.in', - output: service, - configuration: service_conf, - install: true, - install_dir: systemd_system_unit_dir, - ) - endif -+ -+install_data( -+ 'administrator', -+ install_dir: join_paths(act_datadir, 'accountsservice', 'user-templates'), -+) -+ -+install_data( -+ 'standard', -+ install_dir: join_paths(act_datadir, 'accountsservice', 'user-templates'), -+) -diff --git a/data/standard b/data/standard -new file mode 100644 -index 0000000..ea043c9 ---- /dev/null -+++ b/data/standard -@@ -0,0 +1,6 @@ -+[Template] -+#EnvironmentFiles=/etc/os-release; -+ -+[User] -+Session= -+Icon=${HOME}/.face -diff --git a/src/daemon.c b/src/daemon.c -index 5ce0216..66ac7ba 100644 ---- a/src/daemon.c -+++ b/src/daemon.c -@@ -298,69 +298,63 @@ entry_generator_cachedir (Daemon *daemon, - break; - - /* Only load files in this directory */ - filename = g_build_filename (USERDIR, name, NULL); - regular = g_file_test (filename, G_FILE_TEST_IS_REGULAR); - - if (regular) { - errno = 0; - pwent = getpwnam (name); - if (pwent != NULL) { - *shadow_entry = getspnam (pwent->pw_name); - - return pwent; - } else if (errno == 0) { - g_debug ("user '%s' in cache dir but not present on system, removing", name); - remove_cache_files (name); - } - else { - g_warning ("failed to check if user '%s' in cache dir is present on system: %s", - name, g_strerror (errno)); - } - } - } - - /* 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, &key, &value)) { -- const gchar *name = key; - User *user = value; -- g_autofree gchar *filename = NULL; -- g_autoptr(GKeyFile) key_file = NULL; - -- 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); -+ user_update_from_cache (user); - } - - *state = NULL; - return NULL; - } - - static struct passwd * - entry_generator_requested_users (Daemon *daemon, - GHashTable *users, - gpointer *state, - struct spwd **shadow_entry) - { - DaemonPrivate *priv = daemon_get_instance_private (daemon); - struct passwd *pwent; - GList *node; - - /* First iteration */ - if (*state == NULL) { - *state = 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; -diff --git a/src/meson.build b/src/meson.build -index 3970749..d3b0cb9 100644 ---- a/src/meson.build -+++ b/src/meson.build -@@ -1,59 +1,60 @@ - sources = [] - - gdbus_headers = [] - - ifaces = [ - ['accounts-generated', 'org.freedesktop.', 'Accounts'], - ['accounts-user-generated', act_namespace + '.', 'User'], - ['realmd-generated', 'org.freedesktop.', 'realmd'], - ] - - foreach iface: ifaces - gdbus_sources = gnome.gdbus_codegen( - iface[0], - join_paths(data_dir, iface[1] + iface[2] + '.xml'), - interface_prefix: iface[1], - namespace: 'Accounts', - ) - sources += gdbus_sources - gdbus_headers += gdbus_sources[1] - endforeach - - deps = [ - gio_dep, - gio_unix_dep, - ] - - cflags = [ - '-DLOCALSTATEDIR="@0@"'.format(act_localstatedir), - '-DDATADIR="@0@"'.format(act_datadir), -+ '-DSYSCONFDIR="@0@"'.format(act_sysconfdir), - '-DICONDIR="@0@"'.format(join_paths(act_localstatedir, 'lib', 'AccountsService', 'icons')), - '-DUSERDIR="@0@"'.format(join_paths(act_localstatedir, 'lib', 'AccountsService', 'users')), - ] - - libaccounts_generated = static_library( - 'accounts-generated', - sources: sources, - include_directories: top_inc, - dependencies: deps, - c_args: cflags, - ) - - libaccounts_generated_dep = declare_dependency( - sources: gdbus_headers, - include_directories: include_directories('.'), - dependencies: gio_dep, - link_with: libaccounts_generated, - ) - - sources = files( - 'daemon.c', - 'extensions.c', - 'main.c', - 'user.c', - 'user-classify.c', - 'util.c', - 'wtmp-helper.c', - ) - - deps = [ -diff --git a/src/user.c b/src/user.c -index 9f57af5..16c7721 100644 ---- a/src/user.c -+++ b/src/user.c -@@ -43,127 +43,384 @@ - #include - - #include "user-classify.h" - #include "daemon.h" - #include "user.h" - #include "accounts-user-generated.h" - #include "util.h" - - struct User { - AccountsUserSkeleton parent; - - GDBusConnection *system_bus_connection; - gchar *object_path; - - Daemon *daemon; - - GKeyFile *keyfile; - - gid_t gid; - gint64 expiration_time; - gint64 last_change_time; - gint64 min_days_between_changes; - gint64 max_days_between_changes; - gint64 days_to_warn; - gint64 days_after_expiration_until_lock; - GVariant *login_history; - gchar *icon_file; - gchar *default_icon_file; - gboolean account_expiration_policy_known; - gboolean cached; -+ gboolean template_loaded; - - guint *extension_ids; - guint n_extension_ids; - - guint changed_timeout_id; - }; - - typedef struct UserClass - { - AccountsUserSkeletonClass parent_class; - } UserClass; - - static void user_accounts_user_iface_init (AccountsUserIface *iface); -+static void user_update_from_keyfile (User *user, GKeyFile *keyfile); - - 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) { - return ACCOUNT_TYPE_ADMINISTRATOR; - } - } - - return ACCOUNT_TYPE_STANDARD; - } - - static void - user_reset_icon_file (User *user) - { - const char *icon_file; - gboolean icon_is_default; - const char *home_dir; - - icon_file = accounts_user_get_icon_file (ACCOUNTS_USER (user)); - - if (icon_file == NULL || g_strcmp0 (icon_file, user->default_icon_file) == 0) { - icon_is_default = TRUE; - } else { - icon_is_default = FALSE; - } - - g_free (user->default_icon_file); - home_dir = accounts_user_get_home_directory (ACCOUNTS_USER (user)); - - user->default_icon_file = g_build_filename (home_dir, ".face", NULL); - - if (icon_is_default) { - accounts_user_set_icon_file (ACCOUNTS_USER (user), user->default_icon_file); - } - } - -+static gboolean -+user_has_cache_file (User *user) -+{ -+ g_autofree char *filename = NULL; -+ -+ filename = g_build_filename (USERDIR, user_get_user_name (user), NULL); -+ -+ return g_file_test (filename, G_FILE_TEST_EXISTS); -+} -+ -+static gboolean -+is_valid_shell_identifier_character (char c, -+ gboolean first) -+{ -+ return (!first && g_ascii_isdigit (c)) || -+ c == '_' || -+ g_ascii_isalpha (c); -+} -+ -+static char * -+expand_template_variables (User *user, -+ GHashTable *template_variables, -+ const char *str) -+{ -+ GString *s = g_string_new (""); -+ const char *p, *start; -+ char c; -+ -+ p = str; -+ while (*p) { -+ c = *p; -+ if (c == '\\') { -+ p++; -+ c = *p; -+ if (c != '\0') { -+ p++; -+ switch (c) { -+ case '\\': -+ g_string_append_c (s, '\\'); -+ break; -+ case '$': -+ g_string_append_c (s, '$'); -+ break; -+ default: -+ g_string_append_c (s, '\\'); -+ g_string_append_c (s, c); -+ break; -+ } -+ } -+ } else if (c == '$') { -+ gboolean brackets = FALSE; -+ p++; -+ if (*p == '{') { -+ brackets = TRUE; -+ p++; -+ } -+ start = p; -+ while (*p != '\0' && -+ is_valid_shell_identifier_character (*p, p == start)) -+ p++; -+ if (p == start || (brackets && *p != '}')) { -+ g_string_append_c (s, '$'); -+ if (brackets) -+ g_string_append_c (s, '{'); -+ g_string_append_len (s, start, p - start); -+ } else { -+ g_autofree char *variable = NULL; -+ const char *value; -+ -+ if (brackets && *p == '}') -+ p++; -+ -+ variable = g_strndup (start, p - start - 1); -+ -+ value = g_hash_table_lookup (template_variables, variable); -+ if (value) { -+ g_string_append (s, value); -+ } -+ } -+ } else { -+ p++; -+ g_string_append_c (s, c); -+ } -+ } -+ return g_string_free (s, FALSE); -+} -+ -+static void -+load_template_environment_file (User *user, -+ GHashTable *variables, -+ const char *file) -+{ -+ g_autofree char *contents = NULL; -+ g_auto (GStrv) lines = NULL; -+ g_autoptr (GError) error = NULL; -+ gboolean file_loaded; -+ size_t i; -+ -+ file_loaded = g_file_get_contents (file, &contents, NULL, &error); -+ -+ if (!file_loaded) { -+ g_debug ("Couldn't load template environment file %s: %s", -+ file, error->message); -+ return; -+ } -+ -+ lines = g_strsplit (contents, "\n", -1); -+ -+ for (i = 0; lines[i] != NULL; i++) { -+ char *p; -+ char *variable_end; -+ const char *variable; -+ const char *value; -+ -+ p = lines[i]; -+ while (g_ascii_isspace (*p)) -+ p++; -+ if (*p == '#' || *p == '\0') -+ continue; -+ variable = p; -+ while (is_valid_shell_identifier_character (*p, p == variable)) -+ p++; -+ variable_end = p; -+ while (g_ascii_isspace (*p)) -+ p++; -+ if (variable_end == variable || *p != '=') { -+ g_debug ("template environment file %s has invalid line '%s'\n", file, lines[i]); -+ continue; -+ } -+ *variable_end = '\0'; -+ p++; -+ while (g_ascii_isspace (*p)) -+ p++; -+ value = p; -+ -+ if (g_hash_table_lookup (variables, variable) == NULL) { -+ g_hash_table_insert (variables, -+ g_strdup (variable), -+ g_strdup (value)); -+ } -+ -+ } -+} -+ -+static void -+initialize_template_environment (User *user, -+ GHashTable *variables, -+ const char * const *files) -+{ -+ size_t i; -+ -+ g_hash_table_insert (variables, g_strdup ("HOME"), g_strdup (accounts_user_get_home_directory (ACCOUNTS_USER (user)))); -+ g_hash_table_insert (variables, g_strdup ("USER"), g_strdup (user_get_user_name (user))); -+ -+ if (files == NULL) -+ return; -+ -+ for (i = 0; files[i] != NULL; i++) { -+ load_template_environment_file (user, variables, files[i]); -+ } -+} -+ -+static void -+user_update_from_template (User *user) -+{ -+ g_autofree char *filename = NULL; -+ g_autoptr (GKeyFile) key_file = NULL; -+ g_autoptr (GError) error = NULL; -+ g_autoptr (GHashTable) template_variables = NULL; -+ g_auto (GStrv) template_environment_files = NULL; -+ gboolean key_file_loaded = FALSE; -+ const char * const *system_dirs[] = { -+ (const char *[]) { "/run", SYSCONFDIR, NULL }, -+ g_get_system_data_dirs (), -+ NULL -+ }; -+ g_autoptr (GPtrArray) dirs = NULL; -+ AccountType account_type; -+ const char *account_type_string; -+ size_t i, j; -+ g_autofree char *contents = NULL; -+ g_autofree char *expanded = NULL; -+ g_auto (GStrv) lines = NULL; -+ -+ if (user->template_loaded) -+ return; -+ -+ filename = g_build_filename (USERDIR, -+ accounts_user_get_user_name (ACCOUNTS_USER (user)), -+ NULL); -+ -+ account_type = accounts_user_get_account_type (ACCOUNTS_USER (user)); -+ if (account_type == ACCOUNT_TYPE_ADMINISTRATOR) -+ account_type_string = "administrator"; -+ else -+ account_type_string = "standard"; -+ -+ dirs = g_ptr_array_new (); -+ for (i = 0; system_dirs[i] != NULL; i++) { -+ for (j = 0; system_dirs[i][j] != NULL; j++) { -+ char *dir; -+ -+ dir = g_build_filename (system_dirs[i][j], -+ "accountsservice", -+ "user-templates", -+ NULL); -+ g_ptr_array_add (dirs, dir); -+ } -+ } -+ g_ptr_array_add (dirs, NULL); -+ -+ key_file = g_key_file_new (); -+ key_file_loaded = g_key_file_load_from_dirs (key_file, -+ account_type_string, -+ (const char **) dirs->pdata, -+ NULL, -+ G_KEY_FILE_KEEP_COMMENTS, -+ &error); -+ -+ if (!key_file_loaded) { -+ g_debug ("failed to load user template: %s", error->message); -+ return; -+ } -+ -+ template_variables = g_hash_table_new_full (g_str_hash, -+ g_str_equal, -+ g_free, -+ g_free); -+ -+ template_environment_files = g_key_file_get_string_list (key_file, -+ "Template", -+ "EnvironmentFiles", -+ NULL, -+ NULL); -+ -+ initialize_template_environment (user, template_variables, (const char * const *) template_environment_files); -+ -+ g_key_file_remove_group (key_file, "Template", NULL); -+ contents = g_key_file_to_data (key_file, NULL, NULL); -+ lines = g_strsplit (contents, "\n", -1); -+ -+ expanded = expand_template_variables (user, template_variables, contents); -+ -+ key_file_loaded = g_key_file_load_from_data (key_file, -+ expanded, -+ strlen (expanded), -+ G_KEY_FILE_KEEP_COMMENTS, -+ &error); -+ -+ if (key_file_loaded) -+ user_update_from_keyfile (user, key_file); -+ -+ user->template_loaded = key_file_loaded; -+} -+ - void - user_update_from_pwent (User *user, - struct passwd *pwent, - struct spwd *spent) - { - g_autofree gchar *real_name = NULL; - gboolean is_system_account; - const gchar *passwd; - gboolean locked; - PasswordMode mode; - AccountType account_type; - - g_object_freeze_notify (G_OBJECT (user)); - - if (pwent->pw_gecos && pwent->pw_gecos[0] != '\0') { - gchar *first_comma = NULL; - gchar *valid_utf8_name = NULL; - - if (g_utf8_validate (pwent->pw_gecos, -1, NULL)) { - valid_utf8_name = pwent->pw_gecos; - first_comma = g_utf8_strchr (valid_utf8_name, -1, ','); - } - else { - g_warning ("User %s has invalid UTF-8 in GECOS field. " - "It would be a good thing to check /etc/passwd.", - pwent->pw_name ? pwent->pw_name : ""); - } - - if (first_comma) { - real_name = g_strndup (valid_utf8_name, -@@ -212,134 +469,150 @@ user_update_from_pwent (User *user, - accounts_user_set_locked (ACCOUNTS_USER (user), locked); - - if (passwd == NULL || passwd[0] != 0) { - mode = PASSWORD_MODE_REGULAR; - } - else { - mode = PASSWORD_MODE_NONE; - } - - if (spent) { - if (spent->sp_lstchg == 0) { - mode = PASSWORD_MODE_SET_AT_LOGIN; - } - - user->expiration_time = spent->sp_expire; - user->last_change_time = spent->sp_lstchg; - user->min_days_between_changes = spent->sp_min; - user->max_days_between_changes = spent->sp_max; - user->days_to_warn = spent->sp_warn; - user->days_after_expiration_until_lock = spent->sp_inact; - user->account_expiration_policy_known = TRUE; - } - - accounts_user_set_password_mode (ACCOUNTS_USER (user), mode); - is_system_account = !user_classify_is_human (accounts_user_get_uid (ACCOUNTS_USER (user)), - accounts_user_get_user_name (ACCOUNTS_USER (user)), - accounts_user_get_shell (ACCOUNTS_USER (user)), - passwd); - accounts_user_set_system_account (ACCOUNTS_USER (user), is_system_account); - -+ if (!user_has_cache_file (user)) -+ user_update_from_template (user); - g_object_thaw_notify (G_OBJECT (user)); - } - --void -+static void - user_update_from_keyfile (User *user, - GKeyFile *keyfile) - { - gchar *s; - -- g_object_freeze_notify (G_OBJECT (user)); -- - s = g_key_file_get_string (keyfile, "User", "Language", NULL); - if (s != NULL) { - accounts_user_set_language (ACCOUNTS_USER (user), s); - g_clear_pointer (&s, g_free); - } - - s = g_key_file_get_string (keyfile, "User", "XSession", NULL); - if (s != NULL) { - accounts_user_set_xsession (ACCOUNTS_USER (user), s); - - /* for backward compat */ - accounts_user_set_session (ACCOUNTS_USER (user), s); - g_clear_pointer (&s, g_free); - } - - s = g_key_file_get_string (keyfile, "User", "Session", NULL); - if (s != NULL) { - accounts_user_set_session (ACCOUNTS_USER (user), s); - g_clear_pointer (&s, g_free); - } - - s = g_key_file_get_string (keyfile, "User", "SessionType", NULL); - if (s != NULL) { - accounts_user_set_session_type (ACCOUNTS_USER (user), s); - g_clear_pointer (&s, g_free); - } - - s = g_key_file_get_string (keyfile, "User", "Email", NULL); - if (s != NULL) { - accounts_user_set_email (ACCOUNTS_USER (user), s); - g_clear_pointer (&s, g_free); - } - - s = g_key_file_get_string (keyfile, "User", "Location", NULL); - if (s != NULL) { - accounts_user_set_location (ACCOUNTS_USER (user), s); - g_clear_pointer (&s, g_free); - } - - s = g_key_file_get_string (keyfile, "User", "PasswordHint", NULL); - if (s != NULL) { - accounts_user_set_password_hint (ACCOUNTS_USER (user), s); - g_clear_pointer (&s, g_free); - } - - s = g_key_file_get_string (keyfile, "User", "Icon", NULL); - if (s != NULL) { - accounts_user_set_icon_file (ACCOUNTS_USER (user), s); - g_clear_pointer (&s, g_free); - } - - if (g_key_file_has_key (keyfile, "User", "SystemAccount", NULL)) { - gboolean system_account; - - system_account = g_key_file_get_boolean (keyfile, "User", "SystemAccount", NULL); - accounts_user_set_system_account (ACCOUNTS_USER (user), system_account); - } - - g_clear_pointer (&user->keyfile, g_key_file_unref); - user->keyfile = g_key_file_ref (keyfile); -+} -+ -+void -+user_update_from_cache (User *user) -+{ -+ g_autofree gchar *filename = NULL; -+ g_autoptr(GKeyFile) key_file = NULL; -+ -+ filename = g_build_filename (USERDIR, accounts_user_get_user_name (ACCOUNTS_USER (user)), NULL); -+ -+ key_file = g_key_file_new (); -+ -+ if (!g_key_file_load_from_file (key_file, filename, 0, NULL)) -+ return; -+ -+ g_object_freeze_notify (G_OBJECT (user)); -+ user_update_from_keyfile (user, key_file); - user_set_cached (user, TRUE); - user_set_saved (user, TRUE); -- - g_object_thaw_notify (G_OBJECT (user)); - } - - void - user_update_local_account_property (User *user, - gboolean local) - { - accounts_user_set_local_account (ACCOUNTS_USER (user), local); - } - - void - user_update_system_account_property (User *user, - gboolean system) - { - accounts_user_set_system_account (ACCOUNTS_USER (user), system); - } - - static void - user_save_to_keyfile (User *user, - GKeyFile *keyfile) - { - g_key_file_remove_group (keyfile, "User", NULL); - - if (accounts_user_get_email (ACCOUNTS_USER (user))) - g_key_file_set_string (keyfile, "User", "Email", accounts_user_get_email (ACCOUNTS_USER (user))); - - if (accounts_user_get_language (ACCOUNTS_USER (user))) - g_key_file_set_string (keyfile, "User", "Language", accounts_user_get_language (ACCOUNTS_USER (user))); - - if (accounts_user_get_session (ACCOUNTS_USER (user))) -@@ -509,60 +782,63 @@ user_extension_set_property (User *user, - if (!prev || !g_str_equal (printed, prev)) { - g_key_file_set_value (user->keyfile, interface->name, property->name, printed); - - /* Emit a change signal. Use invalidation - * because the data may not be world-readable. - */ - g_dbus_connection_emit_signal (g_dbus_method_invocation_get_connection (invocation), - NULL, /* destination_bus_name */ - g_dbus_method_invocation_get_object_path (invocation), - "org.freedesktop.DBus.Properties", "PropertiesChanged", - g_variant_new_parsed ("( %s, %a{sv}, [ %s ] )", - interface->name, NULL, property->name), - NULL); - - accounts_user_emit_changed (ACCOUNTS_USER (user)); - save_extra_data (user); - } - - g_dbus_method_invocation_return_value (invocation, g_variant_new ("()")); - } - - static void - user_extension_authentication_done (Daemon *daemon, - User *user, - GDBusMethodInvocation *invocation, - gpointer user_data) - { - GDBusInterfaceInfo *interface = user_data; - const gchar *method_name; - -+ if (!user_has_cache_file (user)) -+ user_update_from_template (user); -+ - method_name = g_dbus_method_invocation_get_method_name (invocation); - - if (g_str_equal (method_name, "Get")) - user_extension_get_property (user, daemon, interface, invocation); - else if (g_str_equal (method_name, "GetAll")) - user_extension_get_all_properties (user, daemon, interface, invocation); - else if (g_str_equal (method_name, "Set")) - user_extension_set_property (user, daemon, interface, invocation); - else - g_assert_not_reached (); - } - - static void - user_extension_method_call (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) - { - User *user = user_data; - GDBusInterfaceInfo *iface_info; - const gchar *annotation_name; - const gchar *action_id; - gint uid; - gint i; - - /* We don't allow method calls on extension interfaces, so we -diff --git a/src/user.h b/src/user.h -index b3b3380..eb81918 100644 ---- a/src/user.h -+++ b/src/user.h -@@ -30,58 +30,57 @@ - #include "types.h" - - G_BEGIN_DECLS - - #define TYPE_USER (user_get_type ()) - #define USER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TYPE_USER, User)) - #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_from_cache (User *user); - 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_set_saved (User *user, - gboolean saved); - - 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.27.0 - diff --git a/SOURCES/0002-main-Allow-cache-files-to-be-marked-immutable.patch b/SOURCES/0002-main-Allow-cache-files-to-be-marked-immutable.patch deleted file mode 100644 index 991a879..0000000 --- a/SOURCES/0002-main-Allow-cache-files-to-be-marked-immutable.patch +++ /dev/null @@ -1,195 +0,0 @@ -From 12127d9c04e8151c51bd14114dce424ff8448345 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 9 Sep 2021 09:40:49 -0400 -Subject: [PATCH 2/2] main: Allow cache files to be marked immutable - -At the moment, at start up we unconditionally reset permission of all -cache files in /var/lib/AccountsService/users. If the mode of the files -can't be reset, accountsservice fails to start. - -But there's a situation where we should proceed anyway: If the -mode is already correct, and the file is read-only, there is no reason -to refuse to proceed. - -This commit changes the code to explicitly validate the permissions of -the file before failing. ---- - src/main.c | 29 +++++++++++++++++++++++++---- - 1 file changed, 25 insertions(+), 4 deletions(-) - -diff --git a/src/main.c b/src/main.c -index 01cb617..36a2d7e 100644 ---- a/src/main.c -+++ b/src/main.c -@@ -16,143 +16,164 @@ - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Written by: Matthias Clasen - */ - - #include "config.h" - - #include - #include - #include - #include - #include - #include - #include - - #include - #include - #include - #include - - #include "daemon.h" - - #define NAME_TO_CLAIM "org.freedesktop.Accounts" - - static gboolean - ensure_directory (const char *path, - gint mode, - GError **error) - { -+ GStatBuf stat_buffer = { 0 }; -+ - if (g_mkdir_with_parents (path, mode) < 0) { - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "Failed to create directory %s: %m", - path); - return FALSE; - } - -- if (g_chmod (path, mode) < 0) { -+ g_chmod (path, mode); -+ -+ if (g_stat (path, &stat_buffer) < 0) { -+ g_clear_error (error); -+ - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), -- "Failed to change permissions of directory %s: %m", -+ "Failed to validate permissions of directory %s: %m", - path); - return FALSE; - } - -+ if ((stat_buffer.st_mode & ~S_IFMT) != mode) { -+ g_set_error (error, -+ G_FILE_ERROR, -+ g_file_error_from_errno (errno), -+ "Directory %s has wrong mode %o; it should be %o", -+ path, stat_buffer.st_mode, mode); -+ return FALSE; -+ } -+ - return TRUE; - } - - static gboolean - ensure_file_permissions (const char *dir_path, - gint file_mode, - GError **error) - { - GDir *dir = NULL; - const gchar *filename; - gint errsv = 0; - - dir = g_dir_open (dir_path, 0, error); - if (dir == NULL) - return FALSE; - - while ((filename = g_dir_read_name (dir)) != NULL) { -+ GStatBuf stat_buffer = { 0 }; -+ - gchar *file_path = g_build_filename (dir_path, filename, NULL); - - g_debug ("Changing permission of %s to %04o", file_path, file_mode); -- if (g_chmod (file_path, file_mode) < 0) -+ g_chmod (file_path, file_mode); -+ -+ if (g_stat (file_path, &stat_buffer) < 0) - errsv = errno; - -+ if ((stat_buffer.st_mode & ~S_IFMT) != file_mode) -+ errsv = EACCES; -+ - g_free (file_path); - } - - g_dir_close (dir); - - /* Report any errors after all chmod()s have been attempted. */ - if (errsv != 0) { - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - "Failed to change permissions of files in directory %s: %m", - dir_path); - return FALSE; - } - - return TRUE; - } - - static void - on_bus_acquired (GDBusConnection *connection, - const gchar *name, - gpointer user_data) - { - GMainLoop *loop = user_data; - Daemon *daemon; - g_autoptr(GError) error = NULL; - - if (!ensure_directory (ICONDIR, 0775, &error) || - !ensure_directory (USERDIR, 0700, &error) || - !ensure_file_permissions (USERDIR, 0600, &error)) { - g_printerr ("%s\n", error->message); - g_main_loop_quit (loop); - return; - } - - daemon = daemon_new (); - if (daemon == NULL) { - g_printerr ("Failed to initialize daemon\n"); - g_main_loop_quit (loop); - return; - } -- - openlog ("accounts-daemon", LOG_PID, LOG_DAEMON); - syslog (LOG_INFO, "started daemon version %s", VERSION); - closelog (); - openlog ("accounts-daemon", 0, LOG_AUTHPRIV); - } - - static void - on_name_lost (GDBusConnection *connection, - const gchar *name, - gpointer user_data) - { - GMainLoop *loop = user_data; - - g_debug ("got NameLost, exiting"); - g_main_loop_quit (loop); - } - - static gboolean debug; - - static void - on_log_debug (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) - { - g_autoptr(GString) string = NULL; - const gchar *progname; - int ret G_GNUC_UNUSED; - - string = g_string_new (NULL); --- -2.31.1 - diff --git a/SOURCES/user-template b/SOURCES/user-template deleted file mode 100644 index d36c8e9..0000000 --- a/SOURCES/user-template +++ /dev/null @@ -1,13 +0,0 @@ -# This file contains defaults for new users. To edit, first -# copy it to /etc/accountsservice/user-templates and make changes -# there -[Template] -EnvironmentFiles=/etc/os-release; - -[com.redhat.AccountsServiceUser.System] -id='${ID}' -version-id='${VERSION_ID}' - -[User] -Session=gnome -Icon=${HOME}/.face diff --git a/SPECS/accountsservice.spec b/accountsservice.spec similarity index 62% rename from SPECS/accountsservice.spec rename to accountsservice.spec index de6c508..34d5050 100644 --- a/SPECS/accountsservice.spec +++ b/accountsservice.spec @@ -1,15 +1,12 @@ -%global _hardened_build 1 - Name: accountsservice -Version: 0.6.55 -Release: 4%{?dist} +Version: 23.13.9 +Release: 8%{?dist} Summary: D-Bus interfaces for querying and manipulating user account information -License: GPLv3+ +License: GPL-3.0-or-later URL: https://www.freedesktop.org/wiki/Software/AccountsService/ -#VCS: git:git://git.freedesktop.org/accountsservice -Source0: http://www.freedesktop.org/software/accountsservice/accountsservice-%{version}.tar.xz -Source1: user-template +#VCS: git:git://gitlab.freedesktop.org/accountsservice/accountsservice +Source0: https://www.freedesktop.org/software/accountsservice/accountsservice-%{version}.tar.xz BuildRequires: gettext-devel BuildRequires: pkgconfig(dbus-1) @@ -21,21 +18,19 @@ BuildRequires: gobject-introspection-devel BuildRequires: gtk-doc BuildRequires: git BuildRequires: meson +BuildRequires: vala +BuildRequires: python3-dbusmock +BuildRequires: libxcrypt-devel Requires: polkit Requires: shadow-utils %{?systemd_requires} -Patch10001: 0001-data-don-t-send-change-updates-for-login-history.patch - -Patch20001: 0001-daemon-if-no-local-users-check-if-machine-is-enrolle.patch - -Patch30001: 0001-lib-save-os-when-creating-user.patch - -Patch40001: 0001-user-Introduce-user-templates-for-setting-default-se.patch - -Patch50001: 0001-daemon-Allow-SystemAccount-false-to-be-set-in-cache-.patch -Patch50002: 0002-main-Allow-cache-files-to-be-marked-immutable.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2185850 +Patch10001: 0001-mocklibc-Fix-compiler-warning.patch +Patch10002: 0002-user-manager-Fix-another-compiler-warning.patch +Patch10003: 0003-act-user-Use-the-reentrant-interfaces-of-crypt-_gens.patch +Patch10004: gecos-allow-lastname-comma-firstname.patch %description The accountsservice project provides a set of D-Bus interfaces for @@ -44,7 +39,7 @@ of these interfaces, based on the useradd, usermod and userdel commands. %package libs Summary: Client-side library to talk to accountsservice -Requires: %{name} = %{version}-%{release} +Requires: %{name}%{?_isa} = %{version}-%{release} %description libs The accountsservice-libs package contains a library that can @@ -53,7 +48,7 @@ daemon. %package devel Summary: Development files for accountsservice-libs -Requires: %{name}-libs = %{version}-%{release} +Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description devel The accountsservice-devel package contains headers and other @@ -64,17 +59,15 @@ files needed to build applications that use accountsservice-libs. %autosetup -S git %build -%meson -Dgtk_doc=true -Dsystemd=true -Duser_heuristics=true +%meson \ + -Dgtk_doc=true \ + -Dadmin_group=wheel %meson_build - %install %meson_install -mkdir -p $RPM_BUILD_ROOT%{_datadir}/accountsservice/user-templates $RPM_BUILD_ROOT%{_sysconfdir}/accountsservice/user-templates -cp $RPM_SOURCE_DIR/user-template $RPM_BUILD_ROOT%{_datadir}/accountsservice/user-templates/standard -cp $RPM_SOURCE_DIR/user-template $RPM_BUILD_ROOT%{_datadir}/accountsservice/user-templates/administrator - +mkdir -p $RPM_BUILD_ROOT%{_datadir}/accountsservice/interfaces/ %find_lang accounts-service @@ -92,84 +85,161 @@ cp $RPM_SOURCE_DIR/user-template $RPM_BUILD_ROOT%{_datadir}/accountsservice/user %files -f accounts-service.lang %license COPYING %doc README.md AUTHORS -%dir %{_sysconfdir}/accountsservice/user-templates -%dir %{_sysconfdir}/accountsservice -%{_sysconfdir}/dbus-1/system.d/org.freedesktop.Accounts.conf %{_libexecdir}/accounts-daemon +%dir %{_datadir}/accountsservice/ +%dir %{_datadir}/accountsservice/interfaces/ +%{_datadir}/accountsservice/user-templates/ %{_datadir}/dbus-1/interfaces/org.freedesktop.Accounts.xml %{_datadir}/dbus-1/interfaces/org.freedesktop.Accounts.User.xml +%{_datadir}/dbus-1/system.d/org.freedesktop.Accounts.conf %{_datadir}/dbus-1/system-services/org.freedesktop.Accounts.service %{_datadir}/polkit-1/actions/org.freedesktop.accounts.policy -%{_datadir}/accountsservice/interfaces/com.redhat.AccountsServiceUser.System.xml -%{_datadir}/accountsservice/user-templates/administrator -%{_datadir}/accountsservice/user-templates/standard -%{_datadir}/dbus-1/interfaces/com.redhat.AccountsServiceUser.System.xml %dir %{_localstatedir}/lib/AccountsService/ -%attr(0700, root, root) %dir %{_localstatedir}/lib/AccountsService/users -%attr(0775, root, root) %dir %{_localstatedir}/lib/AccountsService/icons +%dir %{_localstatedir}/lib/AccountsService/users/ +%dir %{_localstatedir}/lib/AccountsService/icons/ %{_unitdir}/accounts-daemon.service %files libs %{_libdir}/libaccountsservice.so.* +%dir %{_libdir}/girepository-1.0/ %{_libdir}/girepository-1.0/AccountsService-1.0.typelib %files devel %{_includedir}/accountsservice-1.0 %{_libdir}/libaccountsservice.so %{_libdir}/pkgconfig/accountsservice.pc +%dir %{_datadir}/gir-1.0/ %{_datadir}/gir-1.0/AccountsService-1.0.gir %dir %{_datadir}/gtk-doc/html/libaccountsservice %{_datadir}/gtk-doc/html/libaccountsservice/* +%dir %{_datadir}/vala/ +%dir %{_datadir}/vala/vapi/ +%{_datadir}/vala/vapi/accountsservice.* %changelog -* Mon Oct 25 2021 Ray Strode - 0.6.55-4 -- Synchronize permissions and group ownership for icon and users dirs - between rpm file manifest and daemon expectations - Resolves: #1919300 +* Fri Apr 25 2025 Adrian Vovk - 23.13.9-8 -* Tue Oct 12 2021 Ray Strode - 0.6.55-3 -- Allow cache files to configure and override system accounts - Resolves: #2012331 +- Allow "Lastname, Firstname" in /etc/passwd + Resolves: RHEL-12265 -* Wed Aug 04 2021 Ray Strode - 0.6.55-2 -- Add support for user templates so user can specify default session - Resolves: #1812788 +* Fri Apr 18 2025 Adrian Vovk - 23.13.9-7 -* Fri Jan 15 2021 Ray Strode - 0.6.55-1 -- Rebase to 0.6.55 - Resolves: #1846376 +- Backport changes from Fedora 40 + Resolves: RHEL-78526 -* Sun Dec 15 2019 Ray Strode - 0.6.50-8 -- Don't set HasNoUsers=true if realmd has providers - Related: #1750516 +* Tue Oct 29 2024 Troy Dawson - 23.13.9-6 +- Bump release for October 2024 mass rebuild: + Resolves: RHEL-64018 -* Mon Jun 17 2019 Ray Strode - 0.6.50-7 -- Don't send change updates for login history changes - Resolves: #1713080 +* Mon Jun 24 2024 Troy Dawson - 23.13.9-5 +- Bump release for June 2024 mass rebuild -* Mon Nov 26 2018 Ray Strode - 0.6.50-6 -- Fix user switching before screen lock - Resolves: #1653263 +* Wed Jan 24 2024 Fedora Release Engineering - 23.13.9-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild -* Mon Oct 15 2018 Ray Strode - 0.6.50-5 -- Turn off aliasing optimizations until glib codegen is fixed - Related: #1628060 1639428 +* Fri Jan 19 2024 Fedora Release Engineering - 23.13.9-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild -* Fri Oct 12 2018 Ray Strode - 0.6.50-4 - Correct rpmdiff complaints - Related: #1628060 +* Wed Jul 19 2023 Fedora Release Engineering - 23.13.9-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild -* Fri Oct 12 2018 Ray Strode - 0.6.50-3 -- Record OS in user data when creating new users - Related: #1628060 +* Tue Apr 11 2023 Ray Strode - 23.13.9-1 +- Update to 23.13.9 +- Fix C99 compile error + Resolves: #2185850 -* Mon Aug 20 2018 Ray Strode - 0.6.50-2 -- add new api needed for handling upgrades from RHEL 7 - Related: #1612915 1595825 +* Fri Mar 24 2023 Ray Strode - 23.11.69-2 +- Fix delay during boot for some users + Resolves: #2180768 -* Fri Jul 13 2018 Ray Strode - 0.6.50-1 -- Update to 0.6.50 - Related: #1597499 +* Wed Mar 15 2023 Ray Strode - 23.11.69-1 +- Update to 23.11.69 + +* Wed Jan 18 2023 Fedora Release Engineering - 22.08.8-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Mon Sep 26 2022 Kalev Lember - 22.08.8-2 +- Rebuild + +* Sat Aug 27 2022 Leigh Scott - 22.08.8-1 +- Update to 22.08.8 + +* Tue Jul 26 2022 Tomas Popela - 0.6.55-11 +- Fix the build with meson 0.60+ + +* Wed Jul 20 2022 Fedora Release Engineering - 0.6.55-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Wed Jan 19 2022 Fedora Release Engineering - 0.6.55-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Wed Jul 21 2021 Fedora Release Engineering - 0.6.55-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Fri Jun 25 2021 Björn Esser - 0.6.55-7 ++ accountsservice-0.6.55-7 +- Add patch to use yescrypt for new user passwords, fixes rhbz#1976334 + +* Mon Jan 25 2021 Fedora Release Engineering - 0.6.55-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Fri Sep 04 2020 Bastien Nocera - 0.6.55-5 ++ accountsservice-0.6.55-5 +- Own /usr/share/accountsservice + +* Fri Jul 31 2020 Fedora Release Engineering - 0.6.55-4 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 27 2020 Fedora Release Engineering - 0.6.55-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jan 28 2020 Fedora Release Engineering - 0.6.55-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Sep 26 2019 Benjamin Berg - 0.6.55-1 +- Update to 0.6.55 + Resolves: #1755838 + +* Wed Jul 24 2019 Fedora Release Engineering - 0.6.54-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Thu Jan 31 2019 Fedora Release Engineering - 0.6.54-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Jan 21 2019 Alexandru-Sever Horin - 0.6.54-4 +- Add patch from upstream to fix UID detection + Resolves: #1646418 + +* Thu Jan 17 2019 Adam Williamson - 0.6.54-3 +- Explicitly enable systemd support (#1576903) (Elliott Sales de Andrade) + +* Mon Jan 14 2019 Björn Esser - 0.6.54-2 +- Rebuilt for libcrypt.so.2 (#1666033) + +* Sat Sep 29 2018 Ray Strode - 0.6.54-1 +- Update to 0.6.54 + +* Thu Sep 27 2018 Ray Strode - 0.6.53-1 +- Update to 0.6.53 + +* Mon Sep 24 2018 Adam Williamson - 0.6.50-1 +- Update to 0.6.50, plus a couple of backported patches + Resolves: #1576903 + +* Thu Jul 12 2018 Fedora Release Engineering - 0.6.49-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Thu May 10 2018 Ray Strode - 0.6.49-1 +- Update to 0.6.49 (brown bag release) + +* Thu May 10 2018 Ray Strode - 0.6.48-1 +- Update to 0.6.48 + Resolves: #1575780 + +* Fri May 04 2018 Ray Strode - 0.6.47-2 +- fix crash on user deletion + Resolves: #1573550 * Tue Apr 24 2018 Ray Strode - 0.6.47-1 - Update to 0.6.47 @@ -303,7 +373,7 @@ cp $RPM_SOURCE_DIR/user-template $RPM_BUILD_ROOT%{_datadir}/accountsservice/user - Fixes CVE-2012-2737 - local file disclosure Related: #832532 -* Thu May 31 2012 Matthias Clasen 0.6.21-1 +* Thu May 30 2012 Matthias Clasen 0.6.21-1 - Update to 0.6.21 * Fri May 04 2012 Ray Strode 0.6.20-1 diff --git a/gecos-allow-lastname-comma-firstname.patch b/gecos-allow-lastname-comma-firstname.patch new file mode 100644 index 0000000..fe7f020 --- /dev/null +++ b/gecos-allow-lastname-comma-firstname.patch @@ -0,0 +1,54 @@ +From 091513774c7049618dcc180a7345ec2acfdb7b26 Mon Sep 17 00:00:00 2001 +From: Adrian Vovk +Date: Fri, 18 Apr 2025 17:36:52 -0400 +Subject: [PATCH] Allow "Lastname, Firstname" in /etc/passwd + +While accountsservice itself doesn't allow this to be set, other +programs may write these values in /etc/passwd. For presentation +purposes we display "Lastname, Firstname" names. We use a heuristic to +determine whether we're looking at separated GECOS fields or +"Lastname, Firstname". + +Resolves: https://issues.redhat.com/browse/RHEL-12265 +--- + src/user.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/src/user.c b/src/user.c +index 1fa047e..da6428c 100644 +--- a/src/user.c ++++ b/src/user.c +@@ -429,6 +429,7 @@ user_update_from_pwent (User *user, + g_clear_pointer (&user->gecos, g_free); + if (pwent->pw_gecos && pwent->pw_gecos[0] != '\0') { + gchar *first_comma = NULL; ++ gchar *second_comma = NULL; + gchar *valid_utf8_name = NULL; + + if (g_utf8_validate (pwent->pw_gecos, -1, NULL)) { +@@ -442,8 +443,21 @@ user_update_from_pwent (User *user, + } + + if (first_comma) { +- real_name = g_strndup (valid_utf8_name, +- (first_comma - valid_utf8_name)); ++ second_comma = g_utf8_strchr (first_comma + 1, -1, ','); ++ ++ /* Sometimes, /etc/password will contain names in `LastName, FirstName` format. ++ * This is, strictly speaking, incorrect because GECOS fields are separated by ++ * commas. However, we can pretty reliably guess when this has happened. If ++ * using GECOS fields, you wouldn't start the office number with a space. When ++ * using a `LastName, FirstName` format, you wouldn't have more than one comma. ++ * So, if we detect something that _looks_ like `LastName, FirstName`, let's use ++ * it for display purposes. */ ++ if (first_comma[1] == ' ' && !second_comma) { ++ real_name = g_strdup (valid_utf8_name); ++ } else { ++ real_name = g_strndup (valid_utf8_name, ++ (first_comma - valid_utf8_name)); ++ } + } else if (valid_utf8_name) { + real_name = g_strdup (valid_utf8_name); + } else { +-- +GitLab diff --git a/sources b/sources new file mode 100644 index 0000000..6c4f2b6 --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA512 (accountsservice-23.13.9.tar.xz) = c6eb543ce2e07b61bbdfa454e388949bc688517be0536b14f30c66383ed105b15d3fab8b6c62b1eaa08f67d9bdc29b928729d9f7c704f47de4decf0de8e12f89