Re: [hackers] [PATCHv2] passwd, login: Support empty passwords

From: Hiltjo Posthuma <hiltjo_AT_codemadness.org>
Date: Mon, 15 Jan 2018 20:31:21 +0100

On Sun, Jan 14, 2018 at 10:45:55PM -0500, Drew DeVault wrote:
> These are useful for daemon users, etc.
> ---
> Sorry for the noise. Initially I just updated my original patch without
> much thought and sent it along, but when I tested it more, I found out
> that it was total dogshit. This patch actually works and (hopefully)
> doesn't introduce blatantly obvious security holes.
>
> libutil/passwd.c | 38 ++++++++++++++++++++++----------------
> login.c | 13 +++++++++----
> passwd.c | 28 +++++++++++++++++++++++-----
> passwd.h | 3 ++-
> 4 files changed, 56 insertions(+), 26 deletions(-)
>
> diff --git a/libutil/passwd.c b/libutil/passwd.c
> index 0798225..d60000c 100644
> --- a/libutil/passwd.c
> +++ b/libutil/passwd.c
> _AT_@ -14,10 +14,9 @@
> #include "../text.h"
> #include "../util.h"
>
> -/* Returns -1 on error, 0 for incorrect password
> - * and 1 if all went OK */
> -int
> -pw_check(const struct passwd *pw, const char *pass)
> +/* Returns NULL on error or a string pointer if all went OK */
> +const char *
> +pw_get(const struct passwd *pw)
> {
> char *cryptpass, *p;
> struct spwd *spw;
> _AT_@ -25,14 +24,7 @@ pw_check(const struct passwd *pw, const char *pass)
> p = pw->pw_passwd;
> if (p[0] == '!' || p[0] == '*') {
> weprintf("denied\n");
> - return -1;
> - }
> -
> - if (pw->pw_passwd[0] == '\0') {
> - if (pass[0] == '\0')
> - return 1;
> - weprintf("incorrect password\n");
> - return 0;
> + return NULL;
> }
>
> if (pw->pw_passwd[0] == 'x' && pw->pw_passwd[1] == '\0') {
> _AT_@ -43,21 +35,35 @@ pw_check(const struct passwd *pw, const char *pass)
> weprintf("getspnam: %s:", pw->pw_name);
> else
> weprintf("who are you?\n");
> - return -1;
> + return NULL;
> }
> p = spw->sp_pwdp;
> if (p[0] == '!' || p[0] == '*') {
> weprintf("denied\n");
> - return -1;
> + return NULL;
> }
> + return p;
> + }
> +}
> +
> +/* Returns -1 on error, 0 for incorrect password
> + * and 1 if all went OK */
> +int
> +pw_check(const char *hash, const char *pass)
> +{
> + char *cryptpass;
> +
> + if (!hash || hash[0] == '!' || hash[0] == '*') {
> + weprintf("denied\n");
> + return -1;
> }
>
> - cryptpass = crypt(pass, p);
> + cryptpass = crypt(pass, hash);
> if (!cryptpass) {
> weprintf("crypt:");
> return -1;
> }
> - if (strcmp(cryptpass, p) != 0) {
> + if (strcmp(cryptpass, hash) != 0) {
> weprintf("incorrect password\n");
> return 0;
> }
> diff --git a/login.c b/login.c
> index 25a59e4..3490632 100644
> --- a/login.c
> +++ b/login.c
> _AT_@ -107,11 +107,16 @@ main(int argc, char *argv[])
> /* Flush pending input */
> ioctl(0, TCFLSH, (void *)0);
>
> - pass = getpass("Password: ");
> - if (!pass)
> - eprintf("getpass:");
> - if (pw_check(pw, pass) <= 0)
> + const char *hash = pw_get(pw);
> + if (!hash)
> exit(1);
> + else if (*hash) {
> + pass = getpass("Password: ");
> + if (!pass)
> + eprintf("getpass:");
> + if (pw_check(hash, pass) <= 0)
> + exit(1);
> + }
>
> tty = ttyname(0);
> if (!tty)
> diff --git a/passwd.c b/passwd.c
> index 52b70a8..cd70c64 100644
> --- a/passwd.c
> +++ b/passwd.c
> _AT_@ -164,9 +164,12 @@ main(int argc, char *argv[])
> struct passwd *pw;
> struct spwd *spw = NULL;
> FILE *fp = NULL;
> - int r = -1, status = 1;
> + int r = -1, status = 1, fdel = 0;
>
> ARGBEGIN {
> + case 'd':
> + fdel = 1;
> + break;
> default:
> usage();
> } ARGEND;
> _AT_@ -216,6 +219,14 @@ main(int argc, char *argv[])
> prevhash = pw->pw_passwd;
> }
>
> + printf("%s\n", prevhash);
> + if (!*prevhash) {
> + if (pw->pw_uid == getuid())
> + goto newpass;
> + else
> + eprintf("denied\n");
> + }
> +
> printf("Changing password for %s\n", pw->pw_name);
> inpass = getpass("Old password: ");
> if (!inpass)
> _AT_@ -230,10 +241,15 @@ main(int argc, char *argv[])
> eprintf("incorrect password\n");
>
> newpass:
> - inpass = getpass("Enter new password: ");
> + if (fdel) {
> + cryptpass3 = estrdup("");
> + goto writepass;
> + } else {
> + inpass = getpass("Enter new password: ");
> + }
> if (!inpass)
> eprintf("getpass:");
> - if (inpass[0] == '\0')
> + if (inpass[0] == '\0' && !fdel)
> eprintf("no password supplied\n");
> p = crypt(inpass, prevhash);
> if (!p)
> _AT_@ -249,10 +265,11 @@ newpass:
> /* Flush pending input */
> ioctl(0, TCFLSH, (void *)0);
>
> - inpass = getpass("Retype new password: ");
> + if (!fdel)
> + inpass = getpass("Retype new password: ");
> if (!inpass)
> eprintf("getpass:");
> - if (inpass[0] == '\0')
> + if (inpass[0] == '\0' && !fdel)
> eprintf("no password supplied\n");
> p = crypt(inpass, salt);
> if (!p)
> _AT_@ -261,6 +278,7 @@ newpass:
> if (strcmp(cryptpass2, cryptpass3) != 0)
> eprintf("passwords don't match\n");
>
> +writepass:
> fp = spw_get_file(pw->pw_name);
> if (fp) {
> r = spw_write_file(fp, spw, cryptpass3);
> diff --git a/passwd.h b/passwd.h
> index ec8286b..f39a826 100644
> --- a/passwd.h
> +++ b/passwd.h
> _AT_@ -1,4 +1,5 @@
> /* See LICENSE file for copyright and license details. */
> /* passwd.c */
> -int pw_check(const struct passwd *, const char *);
> +const char *pw_get(const struct passwd *);
> +int pw_check(const char *, const char *);
> int pw_init(void);
> --
> 2.15.0
>
>

Hi,

This looks too complicated for what it should do to me.
You also added functionality (like a -d) option. This should be separated in
a different patch.

Please pay more attention.

-- 
Kind regards,
Hiltjo
Received on Mon Jan 15 2018 - 20:31:21 CET

This archive was generated by hypermail 2.3.0 : Mon Jan 15 2018 - 20:36:24 CET