From 555799ae183f94b1154bcdab3240124f205c28e4 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Thu, 30 Nov 2017 10:44:25 +1300 Subject: Add guest account support --- data/org.freedesktop.Accounts.User.xml | 10 + data/org.freedesktop.Accounts.xml | 46 ++++ .../libaccountsservice-sections.txt | 7 + src/daemon.c | 125 ++++++++++- src/daemon.h | 1 + src/libaccountsservice/act-user-manager.c | 245 ++++++++++++++++++++- src/libaccountsservice/act-user-manager.h | 13 +- src/libaccountsservice/act-user.c | 30 +++ src/libaccountsservice/act-user.h | 1 + src/user.c | 43 ++++ src/user.h | 3 + 11 files changed, 521 insertions(+), 3 deletions(-) diff --git a/data/org.freedesktop.Accounts.User.xml b/data/org.freedesktop.Accounts.User.xml index 4ab989a..c6063b2 100644 --- a/data/org.freedesktop.Accounts.User.xml +++ b/data/org.freedesktop.Accounts.User.xml @@ -811,6 +811,16 @@ + + + + + Whether this is a guest account or not. + + + + + diff --git a/data/org.freedesktop.Accounts.xml b/data/org.freedesktop.Accounts.xml index 4612c5d..ae5dfe7 100644 --- a/data/org.freedesktop.Accounts.xml +++ b/data/org.freedesktop.Accounts.xml @@ -111,6 +111,27 @@ + + + + Object path of the new user + + + + + Creates a new guest account. + + + + The caller needs the org.freedesktop.accounts.user-administration PolicyKit authorization. + + + if the caller lacks the appropriate PolicyKit authorization + if the operation failed + + + + @@ -182,6 +203,31 @@ if the caller lacks the appropriate PolicyKit authorization + if the user id cannot be resolved + if the operation failed + + + + + + + + The uid to delete + + + + + + Deletes a guest account. Has the same behaviour as DeleteUser but ensures only guest accounts are deleted. + + + + The caller needs the org.freedesktop.accounts.user-administration PolicyKit authorization. + + + if the caller lacks the appropriate PolicyKit authorization + if the user id cannot be resolved + if the user is not a guest account if the operation failed diff --git a/doc/libaccountsservice/libaccountsservice-sections.txt b/doc/libaccountsservice/libaccountsservice-sections.txt index 26c0bc7..a90c3f3 100644 --- a/doc/libaccountsservice/libaccountsservice-sections.txt +++ b/doc/libaccountsservice/libaccountsservice-sections.txt @@ -27,6 +27,7 @@ act_user_get_shell act_user_get_uid act_user_get_user_name act_user_get_x_session +act_user_is_guest_account act_user_is_loaded act_user_is_local_account act_user_is_logged_in @@ -67,9 +68,15 @@ act_user_manager_can_switch act_user_manager_create_user act_user_manager_create_user_async act_user_manager_create_user_finish +act_user_manager_create_guest +act_user_manager_create_guest_async +act_user_manager_create_guest_finish act_user_manager_delete_user act_user_manager_delete_user_async act_user_manager_delete_user_finish +act_user_manager_delete_guest +act_user_manager_delete_guest_async +act_user_manager_delete_guest_finish act_user_manager_get_default act_user_manager_get_user act_user_manager_get_user_by_id diff --git a/src/daemon.c b/src/daemon.c index 9ec153a..05c4b89 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -95,7 +95,8 @@ static const GDBusErrorEntry accounts_error_entries[] = { ERROR_USER_EXISTS, "org.freedesktop.Accounts.Error.UserExists" }, { ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" }, { ERROR_PERMISSION_DENIED, "org.freedesktop.Accounts.Error.PermissionDenied" }, - { ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" } + { ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" }, + { ERROR_USER_NOT_GUEST, "org.freedesktop.Accounts.Error.UserNotGuest" } }; GQuark @@ -126,6 +127,7 @@ error_get_type (void) ENUM_ENTRY (ERROR_USER_DOES_NOT_EXIST, "UserDoesntExist"), ENUM_ENTRY (ERROR_PERMISSION_DENIED, "PermissionDenied"), ENUM_ENTRY (ERROR_NOT_SUPPORTED, "NotSupported"), + ENUM_ENTRY (ERROR_USER_NOT_GUEST, "UserNotGuest"), { 0, 0, 0 } }; g_assert (NUM_ERRORS == G_N_ELEMENTS (values) - 1); @@ -1139,6 +1141,88 @@ daemon_create_user (AccountsAccounts *accounts, return TRUE; } +static gchar * +make_guest_username (void) +{ + const gchar *random_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + GString *user_name; + int i; + + user_name = g_string_new ("guest-"); + for (i = 0; i < 6; i++) { + gint32 j = g_random_int_range (0, strlen (random_chars)); + g_string_append_c (user_name, random_chars[j]); + } + + return g_string_free (user_name, FALSE); +} + +static void +daemon_create_guest_authorized_cb (Daemon *daemon, + User *dummy, + GDBusMethodInvocation *context, + gpointer data) + +{ + User *user; + GError *error; + gchar *user_name; + const gchar *argv[7]; + + sys_log (context, "create guest"); + + while (TRUE) { + user_name = make_guest_username (); + if (getpwnam (user_name) == NULL) + break; + g_free (user_name); + } + + argv[0] = "/usr/sbin/useradd"; + argv[1] = "-m"; + argv[2] = "-c"; + argv[3] = "Guest"; + argv[4] = "--"; + argv[5] = user_name; + argv[6] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { + throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); + g_error_free (error); + g_free (user_name); + return; + } + + user = daemon_local_find_user_by_name (daemon, user_name); + user_update_local_account_property (user, TRUE); + user_update_system_account_property (user, FALSE); + user_update_guest_account_property (user, TRUE); + + cache_user (daemon, user); + + accounts_accounts_complete_create_guest (NULL, context, user_get_object_path (user)); + + g_free (user_name); +} + +static gboolean +daemon_create_guest (AccountsAccounts *accounts, + GDBusMethodInvocation *context) +{ + Daemon *daemon = (Daemon*)accounts; + + daemon_local_check_auth (daemon, + NULL, + "org.freedesktop.accounts.user-administration", + TRUE, + daemon_create_guest_authorized_cb, + context, + NULL, NULL); + + return TRUE; +} + static void daemon_cache_user_authorized_cb (Daemon *daemon, User *dummy, @@ -1243,6 +1327,7 @@ daemon_uncache_user (AccountsAccounts *accounts, typedef struct { uid_t uid; gboolean remove_files; + gboolean only_guest; } DeleteUserData; static void @@ -1269,6 +1354,11 @@ daemon_delete_user_authorized_cb (Daemon *daemon, user = daemon_local_find_user_by_id (daemon, ud->uid); + if (ud->only_guest && ((user == NULL || !user_get_guest_account (user)))) { + throw_error (context, ERROR_USER_NOT_GUEST, "User is not a guest account"); + return; + } + if (user != NULL) { user_set_cached (user, FALSE); @@ -1333,6 +1423,37 @@ daemon_delete_user (AccountsAccounts *accounts, return TRUE; } +static gboolean +daemon_delete_guest (AccountsAccounts *accounts, + GDBusMethodInvocation *context, + gint64 uid, + gboolean remove_files) +{ + Daemon *daemon = (Daemon*)accounts; + DeleteUserData *data; + + if ((uid_t)uid == 0) { + throw_error (context, ERROR_FAILED, "Refuse to delete root user"); + return TRUE; + } + + data = g_new0 (DeleteUserData, 1); + data->uid = (uid_t)uid; + data->only_guest = TRUE; + data->remove_files = TRUE; + + daemon_local_check_auth (daemon, + NULL, + "org.freedesktop.accounts.user-administration", + TRUE, + daemon_delete_user_authorized_cb, + context, + data, + (GDestroyNotify)g_free); + + return TRUE; +} + typedef struct { Daemon *daemon; User *user; @@ -1594,7 +1715,9 @@ static void daemon_accounts_accounts_iface_init (AccountsAccountsIface *iface) { iface->handle_create_user = daemon_create_user; + iface->handle_create_guest = daemon_create_guest; iface->handle_delete_user = daemon_delete_user; + iface->handle_delete_guest = daemon_delete_guest; iface->handle_find_user_by_id = daemon_find_user_by_id; iface->handle_find_user_by_name = daemon_find_user_by_name; iface->handle_list_cached_users = daemon_list_cached_users; diff --git a/src/daemon.h b/src/daemon.h index b7e072e..d78a5fb 100644 --- a/src/daemon.h +++ b/src/daemon.h @@ -57,6 +57,7 @@ typedef enum { ERROR_USER_DOES_NOT_EXIST, ERROR_PERMISSION_DENIED, ERROR_NOT_SUPPORTED, + ERROR_USER_NOT_GUEST, NUM_ERRORS } Error; diff --git a/src/libaccountsservice/act-user-manager.c b/src/libaccountsservice/act-user-manager.c index 3c9ccac..68adc67 100644 --- a/src/libaccountsservice/act-user-manager.c +++ b/src/libaccountsservice/act-user-manager.c @@ -86,6 +86,7 @@ * @ACT_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST: The user does not exist * @ACT_USER_MANAGER_ERROR_PERMISSION_DENIED: Permission denied * @ACT_USER_MANAGER_ERROR_NOT_SUPPORTED: Operation not supported + * @ACT_USER_MANAGER_ERROR_USER_NOT_GUEST: The user is not a guest account * * Various error codes returned by the accounts service. */ @@ -255,7 +256,8 @@ static const GDBusErrorEntry error_entries[] = { { ACT_USER_MANAGER_ERROR_USER_EXISTS, "org.freedesktop.Accounts.Error.UserExists" }, { ACT_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" }, { ACT_USER_MANAGER_ERROR_PERMISSION_DENIED, "org.freedesktop.Accounts.Error.PermissionDenied" }, - { ACT_USER_MANAGER_ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" } + { ACT_USER_MANAGER_ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" }, + { ACT_USER_MANAGER_ERROR_USER_NOT_GUEST, "org.freedesktop.Accounts.Error.UserNotGuest" } }; GQuark @@ -3120,6 +3122,130 @@ act_user_manager_create_user_finish (ActUserManager *manager, return user; } +/** + * act_user_manager_create_guest: + * @manager: a #ActUserManager + * @error: a #GError + * + * Creates a guest account on the system. + * + * Returns: (transfer full): user object + * + * Since: 0.6.46 + */ +ActUser * +act_user_manager_create_guest (ActUserManager *manager, + GError **error) +{ + GError *local_error = NULL; + gboolean res; + gchar *path; + ActUser *user; + + g_debug ("ActUserManager: Creating guest"); + + g_assert (manager->priv->accounts_proxy != NULL); + + local_error = NULL; + res = accounts_accounts_call_create_guest_sync (manager->priv->accounts_proxy, + &path, + NULL, + &local_error); + if (! res) { + g_propagate_error (error, local_error); + return NULL; + } + + user = add_new_user_for_object_path (path, manager); + + g_free (path); + + return user; +} + +/** + * act_user_manager_create_guest_async: + * @manager: a #ActUserManager + * @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 guest account on the system. + * + * For more details, see act_user_manager_create_guest(), which + * is the synchronous version of this call. + * + * Since: 0.6.46 + */ +void +act_user_manager_create_guest_async (ActUserManager *manager, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + g_return_if_fail (ACT_IS_USER_MANAGER (manager)); + g_return_if_fail (manager->priv->accounts_proxy != NULL); + + g_debug ("ActUserManager: Creating guest (async)"); + + g_assert (manager->priv->accounts_proxy != NULL); + + task = g_task_new (G_OBJECT (manager), + cancellable, + callback, user_data); + + accounts_accounts_call_create_guest (manager->priv->accounts_proxy, + cancellable, + act_user_manager_async_complete_handler, task); +} + +/** + * act_user_manager_create_guest_finish: + * @manager: a #ActUserManager + * @result: a #GAsyncResult + * @error: a #GError + * + * Finishes an asynchronous guest creation. + * + * See act_user_manager_create_guest_async(). + * + * Returns: (transfer full): user object + * + * Since: 0.6.46 + */ +ActUser * +act_user_manager_create_guest_finish (ActUserManager *manager, + GAsyncResult *result, + GError **error) +{ + GAsyncResult *inner_result; + ActUser *user = NULL; + gchar *path; + 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_guest_finish (manager->priv->accounts_proxy, + &path, inner_result, &remote_error)) { + user = add_new_user_for_object_path (path, manager); + g_free (path); + } + + 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 @@ -3479,3 +3605,120 @@ act_user_manager_delete_user_finish (ActUserManager *manager, return success; } + +/** + * act_user_manager_delete_guest: + * @manager: a #ActUserManager + * @user: an #ActUser object + * @error: a #GError + * + * Deletes a guest account on the system. + * + * Returns: %TRUE if the user account was successfully deleted + * + * Since: 0.6.46 + */ +gboolean +act_user_manager_delete_guest (ActUserManager *manager, + ActUser *user, + GError **error) +{ + GError *local_error = NULL; + + g_debug ("ActUserManager: Deleting guest '%s' (uid %ld)", act_user_get_user_name (user), (long) act_user_get_uid (user)); + + g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), FALSE); + g_return_val_if_fail (ACT_IS_USER (user), FALSE); + g_return_val_if_fail (manager->priv->accounts_proxy != NULL, FALSE); + + if (!accounts_accounts_call_delete_guest_sync (manager->priv->accounts_proxy, + act_user_get_uid (user), + NULL, + &local_error)) { + g_propagate_error (error, local_error); + return FALSE; + } + + return TRUE; +} + +/** + * act_user_manager_delete_guest_async: + * @manager: a #ActUserManager + * @user: a #ActUser object + * @remove_files: %TRUE to delete the users home directory + * @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 deletes a user account from the system. + * + * For more details, see act_user_manager_delete_guest(), which + * is the synchronous version of this call. + * + * Since: 0.6.46 + */ +void +act_user_manager_delete_guest_async (ActUserManager *manager, + ActUser *user, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + g_return_if_fail (ACT_IS_USER_MANAGER (manager)); + g_return_if_fail (ACT_IS_USER (user)); + g_return_if_fail (manager->priv->accounts_proxy != NULL); + + task = g_task_new (G_OBJECT (manager), + cancellable, + callback, user_data); + + g_debug ("ActUserManager: Deleting (async) guest '%s' (uid %ld)", act_user_get_user_name (user), (long) act_user_get_uid (user)); + + accounts_accounts_call_delete_guest (manager->priv->accounts_proxy, + act_user_get_uid (user), + cancellable, + act_user_manager_async_complete_handler, task); +} + +/** + * act_user_manager_delete_guest_finish: + * @manager: a #ActUserManager + * @result: a #GAsyncResult + * @error: a #GError + * + * Finishes an asynchronous guest account deletion. + * + * See act_user_manager_delete_guest_async(). + * + * Returns: %TRUE if the guest account was successfully deleted + * + * Since: 0.6.46 + */ +gboolean +act_user_manager_delete_guest_finish (ActUserManager *manager, + GAsyncResult *result, + GError **error) +{ + GAsyncResult *inner_result; + gboolean success; + GError *remote_error = NULL; + + inner_result = g_task_propagate_pointer (G_TASK (result), error); + if (inner_result == NULL) { + return FALSE; + } + + success = accounts_accounts_call_delete_guest_finish (manager->priv->accounts_proxy, + inner_result, &remote_error); + if (remote_error) { + g_dbus_error_strip_remote_error (remote_error); + g_propagate_error (error, remote_error); + } + + return success; +} diff --git a/src/libaccountsservice/act-user-manager.h b/src/libaccountsservice/act-user-manager.h index f337ad2..bdcf5b4 100644 --- a/src/libaccountsservice/act-user-manager.h +++ b/src/libaccountsservice/act-user-manager.h @@ -67,7 +67,8 @@ typedef enum ActUserManagerError ACT_USER_MANAGER_ERROR_USER_EXISTS, ACT_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST, ACT_USER_MANAGER_ERROR_PERMISSION_DENIED, - ACT_USER_MANAGER_ERROR_NOT_SUPPORTED + ACT_USER_MANAGER_ERROR_NOT_SUPPORTED, + ACT_USER_MANAGER_ERROR_USER_NOT_GUEST } ActUserManagerError; #define ACT_USER_MANAGER_ERROR act_user_manager_error_quark () @@ -107,6 +108,16 @@ ActUser * act_user_manager_create_user_finish (ActUserManager * GAsyncResult *result, GError **error); +ActUser * act_user_manager_create_guest (ActUserManager *manager, + GError **error); +void act_user_manager_create_guest_async (ActUserManager *manager, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +ActUser * act_user_manager_create_guest_finish (ActUserManager *manager, + GAsyncResult *result, + GError **error); + ActUser * act_user_manager_cache_user (ActUserManager *manager, const char *username, GError **error); diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c index 70691a0..cb2ed62 100644 --- a/src/libaccountsservice/act-user.c +++ b/src/libaccountsservice/act-user.c @@ -86,6 +86,7 @@ enum { PROP_LOCKED, PROP_AUTOMATIC_LOGIN, PROP_SYSTEM_ACCOUNT, + PROP_GUEST_ACCOUNT, PROP_NONEXISTENT, PROP_LOCAL_ACCOUNT, PROP_LOGIN_FREQUENCY, @@ -437,6 +438,14 @@ act_user_class_init (ActUserClass *class) FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + PROP_GUEST_ACCOUNT, + g_param_spec_boolean ("guest-account", + "Guest Account", + "Guest Account", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** * ActUser::changed: @@ -946,6 +955,27 @@ act_user_is_local_account (ActUser *user) return accounts_user_get_local_account (user->accounts_proxy); } +/** + * act_user_is_guest_account: + * @user: a #ActUser + * + * Retrieves whether the user is a guest account or not. + * + * Returns: %TRUE if the user is a guest + * + * Since: 0.6.46 + */ +gboolean +act_user_is_guest_account (ActUser *user) +{ + g_return_val_if_fail (ACT_IS_USER (user), TRUE); + + if (user->accounts_proxy == NULL) + return TRUE; + + return accounts_user_get_guest_account (user->accounts_proxy); +} + /** * act_user_is_nonexistent: * @user: the user object to examine. diff --git a/src/libaccountsservice/act-user.h b/src/libaccountsservice/act-user.h index c685fcc..414f641 100644 --- a/src/libaccountsservice/act-user.h +++ b/src/libaccountsservice/act-user.h @@ -74,6 +74,7 @@ gboolean act_user_get_locked (ActUser *user); gboolean act_user_get_automatic_login (ActUser *user); gboolean act_user_is_system_account (ActUser *user); gboolean act_user_is_local_account (ActUser *user); +gboolean act_user_is_guest_account (ActUser *user); gboolean act_user_is_nonexistent (ActUser *user); const char *act_user_get_icon_file (ActUser *user); const char *act_user_get_language (ActUser *user); diff --git a/src/user.c b/src/user.c index 0dee26c..c960b95 100644 --- a/src/user.c +++ b/src/user.c @@ -70,6 +70,7 @@ enum { PROP_AUTOMATIC_LOGIN, PROP_SYSTEM_ACCOUNT, PROP_LOCAL_ACCOUNT, + PROP_GUEST_ACCOUNT, }; struct User { @@ -110,6 +111,7 @@ struct User { gboolean automatic_login; gboolean system_account; gboolean local_account; + gboolean guest_account; gboolean cached; guint *extension_ids; @@ -361,6 +363,16 @@ user_update_from_keyfile (User *user, } } + if (g_key_file_has_key (keyfile, "User", "GuestAccount", NULL)) { + gboolean guest_account; + + guest_account = g_key_file_get_boolean (keyfile, "User", "GuestAccount", NULL); + if (guest_account != user->guest_account) { + user->guest_account = guest_account; + g_object_notify (G_OBJECT (user), "guest-account"); + } + } + g_clear_pointer (&user->keyfile, g_key_file_unref); user->keyfile = g_key_file_ref (keyfile); user_set_cached (user, TRUE); @@ -388,6 +400,16 @@ user_update_system_account_property (User *user, g_object_notify (G_OBJECT (user), "system-account"); } +void +user_update_guest_account_property (User *user, + gboolean guest) +{ + if (guest == user->guest_account) + return; + user->guest_account = guest; + g_object_notify (G_OBJECT (user), "guest-account"); +} + static void user_save_to_keyfile (User *user, GKeyFile *keyfile) @@ -413,6 +435,7 @@ user_save_to_keyfile (User *user, g_key_file_set_string (keyfile, "User", "Icon", user->icon_file); g_key_file_set_boolean (keyfile, "User", "SystemAccount", user->system_account); + g_key_file_set_boolean (keyfile, "User", "GuestAccount", user->guest_account); user_set_cached (user, TRUE); } @@ -799,6 +822,12 @@ user_get_local_account (User *user) return user->local_account; } +gboolean +user_get_guest_account (User *user) +{ + return user->guest_account; +} + const gchar * user_get_object_path (User *user) { @@ -2156,6 +2185,12 @@ user_real_get_system_account (AccountsUser *user) return USER (user)->system_account; } +static gboolean +user_real_get_guest_account (AccountsUser *user) +{ + return USER (user)->guest_account; +} + static void user_finalize (GObject *object) { @@ -2222,6 +2257,9 @@ user_set_property (GObject *object, case PROP_SYSTEM_ACCOUNT: user->system_account = g_value_get_boolean (value); break; + case PROP_GUEST_ACCOUNT: + user->guest_account = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -2304,6 +2342,9 @@ user_get_property (GObject *object, case PROP_LOCAL_ACCOUNT: g_value_set_boolean (value, user->local_account); break; + case PROP_GUEST_ACCOUNT: + g_value_set_boolean (value, user->guest_account); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -2362,6 +2403,7 @@ user_accounts_user_iface_init (AccountsUserIface *iface) iface->get_password_hint = user_real_get_password_hint; iface->get_automatic_login = user_real_get_automatic_login; iface->get_system_account = user_real_get_system_account; + iface->get_guest_account = user_real_get_guest_account; } static void @@ -2385,6 +2427,7 @@ user_init (User *user) user->locked = FALSE; user->automatic_login = FALSE; user->system_account = FALSE; + user->guest_account = FALSE; user->login_history = NULL; user->keyfile = g_key_file_new (); } diff --git a/src/user.h b/src/user.h index 39c6f13..573d5e8 100644 --- a/src/user.h +++ b/src/user.h @@ -63,6 +63,8 @@ void user_update_local_account_property (User *user, gboolean local); void user_update_system_account_property (User *user, gboolean system); +void user_update_guest_account_property (User *user, + gboolean guest); gboolean user_get_cached (User *user); void user_set_cached (User *user, gboolean cached); @@ -76,6 +78,7 @@ 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); +gboolean user_get_guest_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); -- cgit v1.2.1