Author: trasz
Date: Sun Feb 11 13:35:31 2018
New Revision: 329123
URL: https://svnweb.freebsd.org/changeset/base/329123

Log:
  Make lock(1) use PAM.  This makes the -p option work again.  (Well, kind of,
  because the whole idea of this utility is rather broken.)
  
  This originally come from NetBSD, and was later reworked a bit.
  
  Reviewed by:  des@ (earlier version)
  MFC after:    2 weeks
  Differential Revision:        https://reviews.freebsd.org/D4981

Modified:
  head/usr.bin/lock/Makefile
  head/usr.bin/lock/lock.c

Modified: head/usr.bin/lock/Makefile
==============================================================================
--- head/usr.bin/lock/Makefile  Sun Feb 11 10:23:32 2018        (r329122)
+++ head/usr.bin/lock/Makefile  Sun Feb 11 13:35:31 2018        (r329123)
@@ -5,6 +5,6 @@ PROG=   lock
 BINOWN=        root
 BINMODE=4555
 
-LIBADD=        crypt
+LIBADD=        pam
 
 .include <bsd.prog.mk>

Modified: head/usr.bin/lock/lock.c
==============================================================================
--- head/usr.bin/lock/lock.c    Sun Feb 11 10:23:32 2018        (r329122)
+++ head/usr.bin/lock/lock.c    Sun Feb 11 13:35:31 2018        (r329123)
@@ -73,6 +73,9 @@ __FBSDID("$FreeBSD$");
 #include <time.h>
 #include <unistd.h>
 
+#include <security/pam_appl.h>
+#include <security/openpam.h>  /* for openpam_ttyconv() */
+
 #define        TIMEOUT 15
 
 static void quit(int);
@@ -91,19 +94,23 @@ static int          vtyunlock;              /* Unlock flag 
and code. */
 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);
 
+       pam_err = PAM_SYSTEM_ERR; /* pacify GCC */
+
        sectimeout = TIMEOUT;
+       pamh = NULL;
        pw = NULL;
-       mypw = NULL;
        usemine = 0;
        no_timeout = 0;
        vtylock = 0;
@@ -117,7 +124,6 @@ main(int argc, char **argv)
                        usemine = 1;
                        if (!(pw = getpwuid(getuid())))
                                errx(1, "unknown uid %d", getuid());
-                       mypw = strdup(pw->pw_passwd);
                        break;
                case 'n':
                        no_timeout = 1;
@@ -131,9 +137,11 @@ main(int argc, char **argv)
                }
        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);
@@ -153,7 +161,11 @@ main(int argc, char **argv)
        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')
@@ -171,7 +183,6 @@ main(int argc, char **argv)
                        exit(1);
                }
                s[0] = '\0';
-               mypw = s1;
        }
 
        /* set signal handlers */
@@ -216,19 +227,27 @@ main(int argc, char **argv)
        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++;
@@ -243,6 +262,8 @@ tryagain:
        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 */
 }
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to