---
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
Received on Mon Jan 15 2018 - 04:45:55 CET
This archive was generated by hypermail 2.3.0 : Mon Jan 15 2018 - 04:48:22 CET