From 7facd87e8ba34654fc9c46b4a42943e92acafffb Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 7 Feb 2018 11:03:21 -0500 Subject: [PATCH 16/16] daemon: don't return account expiration policy if not known Right now we assume the user's shadow entry will always be available. If it's not available, we return fields from it initialized to 0. That leads to spurious password expired notifications in GNOME. This commit throws a NOT_SUPPORTED error if the shadow file is off limits. --- src/user.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/user.c b/src/user.c index a83cfe4..cf7eb26 100644 --- a/src/user.c +++ b/src/user.c @@ -79,60 +79,61 @@ struct User { gchar *object_path; Daemon *daemon; GKeyFile *keyfile; uid_t uid; gid_t gid; gchar *user_name; gchar *real_name; AccountType account_type; PasswordMode password_mode; gchar *password_hint; gchar *home_dir; gchar *shell; gchar *email; gchar *language; gchar *x_session; gchar *location; guint64 login_frequency; gint64 login_time; 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 locked; gboolean automatic_login; gboolean system_account; gboolean local_account; gboolean cached; guint *extension_ids; guint n_extension_ids; }; typedef struct UserClass { AccountsUserSkeletonClass parent_class; } UserClass; static void user_accounts_user_iface_init (AccountsUserIface *iface); G_DEFINE_TYPE_WITH_CODE (User, user, ACCOUNTS_TYPE_USER_SKELETON, G_IMPLEMENT_INTERFACE (ACCOUNTS_TYPE_USER, user_accounts_user_iface_init)); static gint account_type_from_pwent (struct passwd *pwent) { struct group *grp; gint i; if (pwent->pw_uid == 0) { g_debug ("user is root so account type is administrator"); return ACCOUNT_TYPE_ADMINISTRATOR; } @@ -261,60 +262,61 @@ user_update_from_pwent (User *user, locked = TRUE; } else { locked = FALSE; } if (user->locked != locked) { user->locked = locked; changed = TRUE; g_object_notify (G_OBJECT (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; } if (user->password_mode != mode) { user->password_mode = mode; changed = TRUE; g_object_notify (G_OBJECT (user), "password-mode"); } user->system_account = !user_classify_is_human (user->uid, user->user_name, pwent->pw_shell, passwd); g_object_thaw_notify (G_OBJECT (user)); if (changed) accounts_user_emit_changed (ACCOUNTS_USER (user)); } 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) { /* TODO: validate / normalize */ g_free (user->language); user->language = s; g_object_notify (G_OBJECT (user), "language"); @@ -1154,60 +1156,65 @@ user_set_x_session (AccountsUser *auser, if (!get_caller_uid (context, &uid)) { throw_error (context, ERROR_FAILED, "identifying caller failed"); return FALSE; } if (user->uid == (uid_t) uid) action_id = "org.freedesktop.accounts.change-own-user-data"; else action_id = "org.freedesktop.accounts.user-administration"; daemon_local_check_auth (user->daemon, user, action_id, TRUE, user_change_x_session_authorized_cb, context, g_strdup (x_session), (GDestroyNotify) g_free); return TRUE; } static void user_get_password_expiration_policy_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, gpointer data) { + if (!user->account_expiration_policy_known) { + throw_error (context, ERROR_NOT_SUPPORTED, "account expiration policy unknown to accounts service"); + return; + } + accounts_user_complete_get_password_expiration_policy (ACCOUNTS_USER (user), context, user->expiration_time, user->last_change_time, user->min_days_between_changes, user->max_days_between_changes, user->days_to_warn, user->days_after_expiration_until_lock); } static gboolean user_get_password_expiration_policy (AccountsUser *auser, GDBusMethodInvocation *context) { User *user = (User*)auser; int uid; const gchar *action_id; if (!get_caller_uid (context, &uid)) { throw_error (context, ERROR_FAILED, "identifying caller failed"); return FALSE; } if (user->uid == (uid_t) uid) action_id = "org.freedesktop.accounts.change-own-user-data"; else action_id = "org.freedesktop.accounts.user-administration"; daemon_local_check_auth (user->daemon, user, -- 2.14.3