Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 11 Feb 2018 13:35:31 +0000 (UTC)
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r329123 - head/usr.bin/lock
Message-ID:  <201802111335.w1BDZVIL026043@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 */
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802111335.w1BDZVIL026043>