From 1caa349041a7ee522aa66e2e0a96e3298d97413f Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 20 May 2013 08:53:23 -0400 Subject: [PATCH 1/8] daemon: cache users explicitly created via AccountsService AccountsService can be used for creating user accounts, but shouldn't be used for creating system accounts. Therefore, all accounts created with AccountsService can safely be considered user accounts. This commit changes the daemon to immediately, implicitly cache all user accounts created via the accounts service. This ensures they'll never get errnoneously tagged as system accounts. https://bugs.freedesktop.org/show_bug.cgi?id=64769 --- src/daemon.c | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/daemon.c b/src/daemon.c index c25d39f..67048d9 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -1072,60 +1072,88 @@ finish_list_cached_users (gpointer user_data) return FALSE; } static gboolean daemon_list_cached_users (AccountsAccounts *accounts, GDBusMethodInvocation *context) { Daemon *daemon = (Daemon*)accounts; ListUserData *data; data = list_user_data_new (daemon, context); if (daemon->priv->reload_id > 0) { /* reload in progress, wait a bit */ g_idle_add (finish_list_cached_users, data); } else { finish_list_cached_users (data); } return TRUE; } static const gchar * daemon_get_daemon_version (AccountsAccounts *object) { return VERSION; } +static void +cache_user (Daemon *daemon, + User *user) +{ + GError *error = NULL; + gchar *filename; + gchar *comment; + const char *user_name; + + /* Always use the canonical user name looked up */ + user_name = user_get_user_name (user); + + filename = g_build_filename (USERDIR, user_name, NULL); + if (!g_file_test (filename, G_FILE_TEST_EXISTS)) { + comment = g_strdup_printf ("# Cached file for %s\n\n", user_name); + g_file_set_contents (filename, comment, -1, &error); + g_free (comment); + + if (error != NULL) { + g_warning ("Couldn't write user cache file: %s: %s", + filename, error->message); + g_error_free (error); + } + } + + g_free (filename); +} + typedef struct { gchar *user_name; gchar *real_name; gint account_type; } CreateUserData; static void create_data_free (gpointer data) { CreateUserData *cd = data; g_free (cd->user_name); g_free (cd->real_name); g_free (cd); } static void daemon_create_user_authorized_cb (Daemon *daemon, User *dummy, GDBusMethodInvocation *context, gpointer data) { CreateUserData *cd = data; User *user; GError *error; const gchar *argv[9]; if (getpwnam (cd->user_name) != NULL) { throw_error (context, ERROR_USER_EXISTS, "A user with name '%s' already exists", cd->user_name); @@ -1139,128 +1167,111 @@ daemon_create_user_authorized_cb (Daemon *daemon, argv[1] = "-m"; argv[2] = "-c"; argv[3] = cd->real_name; if (cd->account_type == ACCOUNT_TYPE_ADMINISTRATOR) { argv[4] = "-G"; argv[5] = ADMIN_GROUP; argv[6] = "--"; argv[7] = cd->user_name; argv[8] = NULL; } else if (cd->account_type == ACCOUNT_TYPE_STANDARD) { argv[4] = "--"; argv[5] = cd->user_name; argv[6] = NULL; } else { throw_error (context, ERROR_FAILED, "Don't know how to add user of type %d", cd->account_type); return; } error = NULL; if (!spawn_with_login_uid (context, argv, &error)) { throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); g_error_free (error); return; } user = daemon_local_find_user_by_name (daemon, cd->user_name); user_update_local_account_property (user, TRUE); + cache_user (daemon, user); + accounts_accounts_complete_create_user (NULL, context, user_get_object_path (user)); } static gboolean daemon_create_user (AccountsAccounts *accounts, GDBusMethodInvocation *context, const gchar *user_name, const gchar *real_name, gint account_type) { Daemon *daemon = (Daemon*)accounts; CreateUserData *data; data = g_new0 (CreateUserData, 1); data->user_name = g_strdup (user_name); data->real_name = g_strdup (real_name); data->account_type = account_type; daemon_local_check_auth (daemon, NULL, "org.freedesktop.accounts.user-administration", TRUE, daemon_create_user_authorized_cb, context, data, (GDestroyNotify)create_data_free); return TRUE; } static void daemon_cache_user_authorized_cb (Daemon *daemon, User *dummy, GDBusMethodInvocation *context, gpointer data) { const gchar *user_name = data; - GError *error = NULL; - gchar *filename; - gchar *comment; User *user; sys_log (context, "cache user '%s'", user_name); user = daemon_local_find_user_by_name (daemon, user_name); if (user == NULL) { throw_error (context, ERROR_USER_DOES_NOT_EXIST, "No user with the name %s found", user_name); return; } - /* Always use the canonical user name looked up */ - user_name = user_get_user_name (user); - - filename = g_build_filename (USERDIR, user_name, NULL); - if (!g_file_test (filename, G_FILE_TEST_EXISTS)) { - comment = g_strdup_printf ("# Cached file for %s\n\n", user_name); - g_file_set_contents (filename, comment, -1, &error); - g_free (comment); - - if (error != NULL) { - g_warning ("Couldn't write user cache file: %s: %s", - filename, error->message); - g_error_free (error); - } - } - - g_free (filename); + cache_user (daemon, user); accounts_accounts_complete_cache_user (NULL, context, user_get_object_path (user)); } static gboolean daemon_cache_user (AccountsAccounts *accounts, GDBusMethodInvocation *context, const gchar *user_name) { Daemon *daemon = (Daemon*)accounts; /* Can't have a slash in the user name */ if (strchr (user_name, '/') != NULL) { g_dbus_method_invocation_return_error (context, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid user name: %s", user_name); return TRUE; } daemon_local_check_auth (daemon, NULL, "org.freedesktop.accounts.user-administration", TRUE, daemon_cache_user_authorized_cb, context, g_strdup (user_name), g_free); return TRUE; } -- 1.8.2.1