diff --git a/passwd.h b/passwd.h index c986116..88881f7 100644 --- a/passwd.h +++ b/passwd.h @@ -1,4 +1,5 @@ /* See LICENSE file for copyright and license details. */ /* passwd.c */ -int pw_scan(char *, struct passwd *); +int pw_check(struct passwd *, const char *); int pw_copy(int, int, const struct passwd *); +int pw_scan(char *, struct passwd *); diff --git a/util/passwd.c b/util/passwd.c index d65038e..4929317 100644 --- a/util/passwd.c +++ b/util/passwd.c @@ -1,11 +1,101 @@ /* See LICENSE file for copyright and license details. */ +#include #include +#include #include #include #include +#include +#include "../passwd.h" #include "../text.h" #include "../util.h" +int +pw_check(struct passwd *pw, const char *pass) +{ + char *cryptpass, *p; + struct spwd *spw; + + p = pw->pw_passwd; + switch (pw->pw_passwd[0]) { + case '!': + case '*': + eprintf("denied\n"); + } + + if (pw->pw_passwd[0] == '\0') + return 1; + + if (pw->pw_passwd[0] == 'x' && pw->pw_passwd[1] == '\0') { + errno = 0; + spw = getspnam(pw->pw_name); + if (errno) + eprintf("getspnam: %:", pw->pw_name); + else if (!spw) + eprintf("who are you?\n"); + switch (spw->sp_pwdp[0]) { + case '!': + case '*': + eprintf("denied\n"); + } + p = spw->sp_pwdp; + } + + cryptpass = crypt(pass, p); + if (!cryptpass) + eprintf("crypt:"); + if (strcmp(cryptpass, p) != 0) + return 0; + return 1; +} + +int +pw_copy(int ffd, int tfd, const struct passwd *newpw) +{ + struct passwd pw; + char *buf = NULL, *p; + size_t size = 0; + FILE *from, *to; + + from = fdopen(ffd, "r"); + if (!from) { + weprintf("fdopen:"); + return -1; + } + to = fdopen(tfd, "w"); + if (!to) { + weprintf("fdopen:"); + return -1; + } + while (agetline(&buf, &size, from) != -1) { + p = strdup(buf); + if (!p) { + weprintf("strdup:"); + return -1; + } + if (newpw) { + if (pw_scan(p, &pw) < 0) + return -1; + if (strcmp(pw.pw_name, newpw->pw_name) == 0) { + fprintf(to, "%s:%s:%u:%u:%s:%s:%s\n", + newpw->pw_name, + newpw->pw_passwd, + newpw->pw_uid, + newpw->pw_gid, + newpw->pw_gecos, + newpw->pw_dir, + newpw->pw_shell); + continue; + } + } + fprintf(to, "%s", buf); + free(p); + } + fflush(to); + free(buf); + return 0; +} + int pw_scan(char *bp, struct passwd *pw) { @@ -65,50 +155,3 @@ corrupt: weprintf("corrupted passwd entry\n"); return -1; } - -int -pw_copy(int ffd, int tfd, const struct passwd *newpw) -{ - struct passwd pw; - char *buf = NULL, *p; - size_t size = 0; - FILE *from, *to; - - from = fdopen(ffd, "r"); - if (!from) { - weprintf("fdopen:"); - return -1; - } - to = fdopen(tfd, "w"); - if (!to) { - weprintf("fdopen:"); - return -1; - } - while (agetline(&buf, &size, from) != -1) { - p = strdup(buf); - if (!p) { - weprintf("strdup:"); - return -1; - } - if (newpw) { - if (pw_scan(p, &pw) < 0) - return -1; - if (strcmp(pw.pw_name, newpw->pw_name) == 0) { - fprintf(to, "%s:%s:%u:%u:%s:%s:%s\n", - newpw->pw_name, - newpw->pw_passwd, - newpw->pw_uid, - newpw->pw_gid, - newpw->pw_gecos, - newpw->pw_dir, - newpw->pw_shell); - continue; - } - } - fprintf(to, "%s", buf); - free(p); - } - fflush(to); - free(buf); - return 0; -}