From: Alejandro Colomar Date: Mon, 5 Jan 2026 23:01:07 +0000 (+0100) Subject: src/usermod.c: -U: Report E_PASSWORDLESS on error due to passwordless account X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a49d2acdb4b59b1f854dc29ac304fd2836d7e1eb;p=thirdparty%2Fshadow.git src/usermod.c: -U: Report E_PASSWORDLESS on error due to passwordless account Reproducer: $ useradd foo $ grep foo /etc/passwd /etc/shadow /etc/passwd:foo:x:1001:1001::/home/foo:/usr/bin/bash /etc/shadow:foo:!:20458:0:99999:7::: $ usermod -U testuser usermod: unlocking the user's password would result in a passwordless account. You should set a password with usermod -p to unlock this user's password. $ echo $? 0 $ grep foo /etc/passwd /etc/shadow /etc/passwd:foo:x:1001:1001::/home/foo:/usr/bin/bash /etc/shadow:foo:!:20458:0:99999:7::: The program failed (didn't change anything, and reported the problem to stderr) but reported success (0). After this patch, the error is reported as E_PASSWORDLESS (20). Closes: Reported-by: Tobias Stoeckmann Acked-by: Tobias Stoeckmann Signed-off-by: Alejandro Colomar --- diff --git a/src/usermod.c b/src/usermod.c index 872583d72..7400bf846 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -28,6 +28,7 @@ #endif /* ACCT_TOOLS_SETUID */ #include #include +#include #include #include #include @@ -97,6 +98,7 @@ #define E_SUB_UID_UPDATE 16 /* can't update the subordinate uid file */ #define E_SUB_GID_UPDATE 18 /* can't update the subordinate gid file */ #endif /* ENABLE_SUBIDS */ +#define E_PASSWORDLESS 20 /* would result in a passwordless account */ #define VALID(s) (!strpbrk(s, ":\n")) @@ -437,7 +439,8 @@ usage (int status) * update encrypted password string (for both shadow and non-shadow * passwords) */ -static char *new_pw_passwd (char *pw_pass) +static char * +new_pw_passwd(char *pw_pass, bool process_selinux) { if (Lflg && ('!' != pw_pass[0])) { #ifdef WITH_AUDIT @@ -452,7 +455,7 @@ static char *new_pw_passwd (char *pw_pass) _("%s: unlocking the user's password would result in a passwordless account.\n" "You should set a password with usermod -p to unlock this user's password.\n"), Prog); - return pw_pass; + fail_exit(E_PASSWORDLESS, process_selinux); } #ifdef WITH_AUDIT @@ -507,7 +510,7 @@ static void new_pwent (struct passwd *pwent, bool process_selinux) */ if ( (!is_shadow_pwd) || !streq(pwent->pw_passwd, SHADOW_PASSWD_STRING)) { - pwent->pw_passwd = new_pw_passwd (pwent->pw_passwd); + pwent->pw_passwd = new_pw_passwd(pwent->pw_passwd, process_selinux); } if (uflg) { @@ -622,7 +625,7 @@ static void new_spent (struct spwd *spent, bool process_selinux) * + there were already both entries * + aging has been requested */ - spent->sp_pwdp = new_pw_passwd (spent->sp_pwdp); + spent->sp_pwdp = new_pw_passwd(spent->sp_pwdp, process_selinux); if (pflg) { spent->sp_lstchg = gettime () / DAY;