Index: usr.bin/lock/Makefile =================================================================== --- usr.bin/lock/Makefile +++ usr.bin/lock/Makefile @@ -5,6 +5,6 @@ BINOWN= root BINMODE=4555 -LIBADD= crypt +LIBADD= pam .include Index: usr.bin/lock/lock.c =================================================================== --- usr.bin/lock/lock.c +++ usr.bin/lock/lock.c @@ -71,6 +71,9 @@ #include #include +#include +#include /* for openpam_ttyconv() */ + #define TIMEOUT 15 static void quit(int); @@ -89,19 +92,21 @@ int main(int argc, char **argv) { + static const struct pam_conv pamc = { &openpam_ttyconv, NULL }; + pam_handle_t *pamh; struct passwd *pw; struct itimerval ntimer, otimer; struct tm *timp; time_t timval; - int ch, failures, sectimeout, usemine, vtylock; - char *ap, *cryptpw, *mypw, *ttynam, *tzn; + int ch, failures, pam_err, sectimeout, usemine, vtylock; + char *ap, *ttynam, *tzn; char hostname[MAXHOSTNAMELEN], s[BUFSIZ], s1[BUFSIZ]; openlog("lock", 0, LOG_AUTH); sectimeout = TIMEOUT; + pamh = NULL; pw = NULL; - mypw = NULL; usemine = 0; no_timeout = 0; vtylock = 0; @@ -115,7 +120,6 @@ usemine = 1; if (!(pw = getpwuid(getuid()))) errx(1, "unknown uid %d", getuid()); - mypw = strdup(pw->pw_passwd); break; case 'n': no_timeout = 1; @@ -129,9 +133,11 @@ } timeout.tv_sec = sectimeout * 60; - /* discard privs */ - if (setuid(getuid()) != 0) - errx(1, "setuid failed"); + if (!usemine) { /* -p with PAM or S/key needs privs */ + /* discard privs */ + if (setuid(getuid()) != 0) + errx(1, "setuid failed"); + } if (tcgetattr(0, &tty)) /* get information for header */ exit(1); @@ -151,7 +157,11 @@ ntty = tty; ntty.c_lflag &= ~ECHO; (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &ntty); - if (!mypw) { + if (usemine) { + pam_err = pam_start("lock", pw->pw_name, &pamc, &pamh); + if (pam_err != PAM_SUCCESS) + err(1, "pam_start: %s", pam_strerror(NULL, pam_err)); + } else { /* get key and check again */ (void)printf("Key: "); if (!fgets(s, sizeof(s), stdin) || *s == '\n') @@ -169,7 +179,6 @@ exit(1); } s[0] = '\0'; - mypw = s1; } /* set signal handlers */ @@ -214,19 +223,27 @@ failures = 0; for (;;) { + if (usemine) { + pam_err = pam_authenticate(pamh, 0); + if (pam_err == PAM_SUCCESS) + break; + + if (pam_err != PAM_AUTH_ERR && + pam_err != PAM_USER_UNKNOWN && + pam_err != PAM_MAXTRIES) { + syslog(LOG_ERR, "pam_authenticate: %s", + pam_strerror(pamh, pam_err)); + } + + goto tryagain; + } (void)printf("Key: "); if (!fgets(s, sizeof(s), stdin)) { clearerr(stdin); hi(0); goto tryagain; } - if (usemine) { - s[strlen(s) - 1] = '\0'; - cryptpw = crypt(s, mypw); - if (cryptpw != NULL && !strcmp(mypw, cryptpw)) - break; - } - else if (!strcmp(s, s1)) + if (!strcmp(s, s1)) break; (void)printf("\07\n"); failures++; @@ -241,6 +258,8 @@ if (getuid() == 0) syslog(LOG_NOTICE, "ROOT UNLOCK ON hostname %s port %s", hostname, ttynam); + if (usemine) + (void)pam_end(pamh, pam_err); quit(0); return(0); /* not reached */ }