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
> @@ -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;
> @@ -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') {
> @@ -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
> @@ -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
> @@ -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;
> @@ -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)
> @@ -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)
> @@ -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)
> @@ -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
> @@ -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

Reply via email to