From 4fde420a7b25d1a54bdb4e4ade67770a5ac79d02 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 3 Feb 2023 21:06:38 +0000 Subject: user: Replace usermod -p with chpasswd -e Writing the password to chpasswd's standard input avoids it becoming visible in `/proc/$pid/cmdline` (CVE-2012-6655). Resolves: https://gitlab.freedesktop.org/accountsservice/accountsservice/-/issues/8 Bug-Debian: https://bugs.debian.org/757912 Signed-off-by: Simon McVittie --- src/user.c | 42 ++++++++++++++++++++++++++---------------- src/util.c | 2 +- src/util.h | 3 +++ 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/user.c b/src/user.c index 2203e69..5a6100d 100644 --- a/src/user.c +++ b/src/user.c @@ -2463,6 +2463,13 @@ user_set_password_mode (AccountsUser *auser, return TRUE; } +static void +free_passwords (gchar **strings) +{ + memset (strings[0], 0, strlen (strings[0])); + g_strfreev (strings); +} + static void user_change_password_authorized_cb (Daemon *daemon, User *user, @@ -2473,7 +2480,8 @@ user_change_password_authorized_cb (Daemon *daemon, gchar **strings = data; g_autoptr (GError) error = NULL; - const gchar *argv[6]; + g_autoptr (GSubprocess) process = NULL; + const char *argv[] = { "/usr/sbin/chpasswd", "-e", NULL }; sys_log (context, "set password and hint of user '%s' (%d)", @@ -2482,14 +2490,21 @@ user_change_password_authorized_cb (Daemon *daemon, g_object_freeze_notify (G_OBJECT (user)); - argv[0] = "/usr/sbin/usermod"; - argv[1] = "-p"; - argv[2] = strings[0]; - argv[3] = "--"; - argv[4] = accounts_user_get_user_name (ACCOUNTS_USER (user)); - argv[5] = NULL; + process = g_subprocess_newv (argv, + G_SUBPROCESS_FLAGS_STDIN_PIPE, + &error); - if (!spawn_sync (argv, &error)) { + if (process == NULL) { + throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); + return; + } + + if (!g_subprocess_communicate_utf8 (process, strings[0], NULL, NULL, NULL, &error)) { + throw_error (context, ERROR_FAILED, "writing input to '%s' failed: %s", argv[0], error->message); + return; + } + + if (!compat_check_exit_status (g_subprocess_get_status (process), &error)) { throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); return; } @@ -2505,13 +2520,6 @@ user_change_password_authorized_cb (Daemon *daemon, accounts_user_complete_set_password (ACCOUNTS_USER (user), context); } -static void -free_passwords (gchar **strings) -{ - memset (strings[0], 0, strlen (strings[0])); - g_strfreev (strings); -} - static gboolean user_set_password (AccountsUser *auser, GDBusMethodInvocation *context, @@ -2529,7 +2537,9 @@ user_set_password (AccountsUser *auser, } data = g_new (gchar *, 3); - data[0] = g_strdup (password); + data[0] = g_strdup_printf ("%s:%s\n", + accounts_user_get_user_name (ACCOUNTS_USER (user)), + password); data[1] = g_strdup (hint); data[2] = NULL; diff --git a/src/util.c b/src/util.c index c8ba4cd..449d509 100644 --- a/src/util.c +++ b/src/util.c @@ -156,7 +156,7 @@ sys_log (GDBusMethodInvocation *context, syslog (LOG_NOTICE, "%s", msg); } -static gboolean +gboolean compat_check_exit_status (int estatus, GError **error) { diff --git a/src/util.h b/src/util.h index 43e080b..d2cd6ed 100644 --- a/src/util.h +++ b/src/util.h @@ -49,3 +49,6 @@ void free_dirs (void); const char *get_userdir (void); const char *get_sysconfdir (void); const char *get_icondir (void); + +gboolean compat_check_exit_status (int estatus, + GError **error); -- cgit v1.2.1