On Mon 16-05-2016 11:54 -0700, Eric Pruitt wrote:

> I have a suggestion -- I think you should add another color option to
> the configuration. Since PAM configurations typically enforce a delay
> before you can reauthenticate after an incorrect password is entered,
> it would be nice if there was another color to indicate that slock is
> waiting for the PAM functions to return.

As far as my test go, only if the password was entered incorrectly, PAM
waits for a moment.  In this case it would be nice to have a different
color that indicates that the password has been handed to PAM.  However,
when the password is correct, PAM immediately returns.  In this case,
the screen would quickly change colors.  Not sure if this desirable.

Attached you find the patch that adds this feature.  What do you think?

Jan Christoph
--
Jan Christoph Ebersbach
I didn’t want some petty, inferior brand of righteousness that comes
from keeping a list of rules when I could get the robust kind that comes
from trusting Christ - God’s righteousness.  Phil 3:9
Author: Jan Christoph Ebersbach <j...@e-jc.de>
URL: http://tools.suckless.org/slock/patches/pam_auth
Replaces shadow support with PAM authentication support.

Change variable `pam_service` in `config.def.h` to the corresponding PAM
service.  The default configuration is for ArchLinux's `login` service.

Index: slock-patches/slock/config.def.h
===================================================================
--- slock-patches.orig/slock/config.def.h
+++ slock-patches/slock/config.def.h
@@ -2,7 +2,11 @@ static const char *colorname[NUMCOLS] =
 	"black",     /* after initialization */
 	"#005577",   /* during input */
 	"#CC3333",   /* wrong password */
+	"#FCCB1D",   /* waiting for PAM */
 };
 
 /* treat a cleared input like a wrong password */
 static const int failonclear = 1;
+
+/* PAM service that's used for authentication */
+static const char* pam_service = "login";
Index: slock-patches/slock/config.mk
===================================================================
--- slock-patches.orig/slock/config.mk
+++ slock-patches/slock/config.mk
@@ -12,7 +12,7 @@ X11LIB = /usr/X11R6/lib
 
 # includes and libs
 INCS = -I. -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr
+LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lpam
 
 # flags
 CPPFLAGS = -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H
Index: slock-patches/slock/slock.c
===================================================================
--- slock-patches.orig/slock/slock.c
+++ slock-patches/slock/slock.c
@@ -17,6 +17,8 @@
 #include <X11/keysym.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
 
 #if HAVE_BSD_AUTH
 #include <login_cap.h>
@@ -27,6 +29,7 @@ enum {
 	INIT,
 	INPUT,
 	FAILED,
+	PAM,
 	NUMCOLS
 };
 
@@ -39,6 +42,9 @@ typedef struct {
 	unsigned long colors[NUMCOLS];
 } Lock;
 
+static int pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr);
+struct pam_conv pamc = {pam_conv, NULL};
+char passwd[256];
 static Lock **locks;
 static int nscreens;
 static Bool running = True;
@@ -112,6 +118,31 @@ getpw(void)
 }
 #endif
 
+static int
+pam_conv(int num_msg, const struct pam_message **msg,
+		struct pam_response **resp, void *appdata_ptr)
+{
+	int retval = PAM_CONV_ERR;
+	for(int i=0; i<num_msg; i++) {
+		if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF &&
+				strncmp(msg[i]->msg, "Password: ", 10) == 0) {
+			struct pam_response *resp_msg = malloc(sizeof(struct pam_response));
+			if (!resp_msg)
+				die("malloc failed");
+			char *password = malloc(strlen(passwd) + 1);
+			if (!password)
+				die("malloc failed");
+			memset(password, 0, strlen(passwd) + 1);
+			strcpy(password, passwd);
+			resp_msg->resp_retcode = 0;
+			resp_msg->resp = password;
+			resp[i] = resp_msg;
+			retval = PAM_SUCCESS;
+		}
+	}
+	return retval;
+}
+
 static void
 #ifdef HAVE_BSD_AUTH
 readpw(Display *dpy)
@@ -119,12 +150,15 @@ readpw(Display *dpy)
 readpw(Display *dpy, const char *pws)
 #endif
 {
-	char buf[32], passwd[256];
-	int num, screen;
+	char buf[32];
+	struct passwd* pw;
+	int num, screen, retval;
 	unsigned int len, color;
 	KeySym ksym;
 	XEvent ev;
 	static int oldc = INIT;
+	pam_handle_t *pamh;
+
 
 	len = 0;
 	running = True;
@@ -155,7 +189,30 @@ readpw(Display *dpy, const char *pws)
 #ifdef HAVE_BSD_AUTH
 				running = !auth_userokay(getlogin(), NULL, "auth-xlock", passwd);
 #else
-				running = !!strcmp(crypt(passwd, pws), pws);
+
+				color = PAM;
+				fprintf(stderr, "go\n");
+				for (screen = 0; screen < nscreens; screen++) {
+					XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]);
+					XClearWindow(dpy, locks[screen]->win);
+					XRaiseWindow(dpy, locks[screen]->win);
+					XSync(dpy, False);
+				}
+
+				pw = getpwuid(getuid());
+				retval = pam_start(pam_service, pw->pw_name, &pamc, &pamh);
+
+				if (retval == PAM_SUCCESS)
+					retval = pam_authenticate(pamh, 0);
+				if (retval == PAM_SUCCESS)
+					retval = pam_acct_mgmt(pamh, 0);
+
+				running = 1;
+				if (retval == PAM_SUCCESS)
+					running = 0;
+				else
+					fprintf(stderr, "slock: %s\n", pam_strerror(pamh, retval));
+				pam_end(pamh, retval);
 #endif
 				if (running) {
 					XBell(dpy, 100);
@@ -299,10 +356,10 @@ main(int argc, char **argv) {
 	dontkillme();
 #endif
 
+#ifndef HAVE_BSD_AUTH
 	if (!getpwuid(getuid()))
 		die("no passwd entry for you\n");
 
-#ifndef HAVE_BSD_AUTH
 	pws = getpw();
 #endif
 

Attachment: signature.asc
Description: PGP signature

Reply via email to