Hey,

this patch should enable Linux-PAM support in slock. It's my first try with
Linux-PAM whatsoever so there's a chance it won't work everywhere :) Maybe
it could be useful to some...

-- 
Petr 'contyk' Sabata, Red Hat, Brno

()  ascii ribbon campaign - against html e-mail 
/\  www.asciiribbon.org   - against proprietary attachments
diff -r 4d3769ac5d02 config.mk
--- a/config.mk Thu Nov 26 12:53:26 2009 +0000
+++ b/config.mk Tue Nov 16 11:32:30 2010 +0100
@@ -20,6 +20,7 @@
 
 # On *BSD remove -DHAVE_SHADOW_H from CPPFLAGS and add -DHAVE_BSD_AUTH
 # On OpenBSD and Darwin remove -lcrypt from LIBS
+# To use Linux-PAM, use -DHAVE_PAM instead of SHADOW_H or BSD_AUTH in CPPFLAGS 
and add -lpam to LIBS
 
 # compiler and linker
 CC = cc
diff -r 4d3769ac5d02 slock.c
--- a/slock.c   Thu Nov 26 12:53:26 2009 +0000
+++ b/slock.c   Tue Nov 16 11:32:30 2010 +0100
@@ -1,6 +1,7 @@
 /* See LICENSE file for license details. */
 #define _XOPEN_SOURCE 500
-#if HAVE_SHADOW_H
+#define PASSLEN 256
+#if defined(HAVE_SHADOW_H)
 #include <shadow.h>
 #endif
 
@@ -17,11 +18,16 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 
-#if HAVE_BSD_AUTH
+#if defined(HAVE_BSD_AUTH)
 #include <login_cap.h>
 #include <bsd_auth.h>
 #endif
 
+#if defined(HAVE_PAM)
+#define PAM_REALM "login"
+#include <security/pam_appl.h>
+#endif
+
 struct st_lock {
        int screen;
        Window root, w;
@@ -44,7 +50,7 @@
        exit(EXIT_FAILURE);
 }
 
-#ifndef HAVE_BSD_AUTH
+#if !defined(HAVE_BSD_AUTH) && !defined(HAVE_PAM)
 static const char *
 get_password(void) { /* only run as root */
        const char *rval;
@@ -56,7 +62,7 @@
        endpwent();
        rval =  pw->pw_passwd;
 
-#if HAVE_SHADOW_H
+#if defined(HAVE_SHADOW_H)
        {
                struct spwd *sp;
                sp = getspnam(getenv("USER"));
@@ -73,29 +79,24 @@
 #endif
 
 static void
-#ifdef HAVE_BSD_AUTH
-read_password(Display *dpy)
-#else
-read_password(Display *dpy, const char *pws)
-#endif
+read_password(Display *dpy, char *passwd)
 {
-       char buf[32], passwd[256];
+       char buf[32];
        int num;
 
        unsigned int len;
-       Bool running = True;
        KeySym ksym;
        XEvent ev;
 
        len = 0;
-       running = True;
 
        /* As "slock" stands for "Simple X display locker", the DPMS settings
         * had been removed and you can set it with "xset" or some other
         * utility. This way the user can easily set a customized DPMS
         * timeout. */
 
-       while(running && !XNextEvent(dpy, &ev)) {
+       for(;;) {
+               XNextEvent(dpy, &ev);
                if(ev.type == KeyPress) {
                        buf[0] = 0;
                        num = XLookupString(&ev.xkey, buf, sizeof buf, &ksym, 
0);
@@ -112,14 +113,7 @@
                        switch(ksym) {
                        case XK_Return:
                                passwd[len] = 0;
-#ifdef HAVE_BSD_AUTH
-                               running = !auth_userokay(getlogin(), NULL, 
"auth-xlock", passwd);
-#else
-                               running = strcmp(crypt(passwd, pws), pws);
-#endif
-                               if (running != 0)
-                                       XBell(dpy, 100);
-                               len = 0;
+                               return;
                                break;
                        case XK_Escape:
                                len = 0;
@@ -127,11 +121,13 @@
                        case XK_BackSpace:
                                if(len)
                                        --len;
-                               break;
+                               passwd[len] = 0;
+                       break;
                        default:
-                               if(num && !iscntrl((int) buf[0]) && (len + num 
< sizeof passwd)) { 
+                               if(num && !iscntrl((int) buf[0]) && (len + num 
< PASSLEN)) { 
                                        memcpy(passwd + len, buf, num);
                                        len += num;
+                                       passwd[len] = 0;
                                }
                                break;
                        }
@@ -139,6 +135,40 @@
        }
 }
 
+#if defined(HAVE_PAM)
+static int
+pamconv(int num_msg, const struct pam_message **msg, struct pam_response 
**resp, void *appdata_ptr) {
+       int i;
+       *resp = (struct pam_response *) calloc(num_msg, sizeof(struct 
pam_response));
+       for (i = 0; i < num_msg; ++i) {
+               if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF) {
+                       if ((resp[i]->resp = malloc(PASSLEN)) == NULL )
+                               die("Not enough memory");
+                       read_password((Display *) appdata_ptr, resp[i]->resp);
+               }
+               resp[i]->resp_retcode = 0;
+       }
+       return PAM_SUCCESS;
+}
+#endif
+
+#if !defined(HAVE_PAM)
+static Bool
+#if defined(HAVE_BSD_AUTH)
+authenticate(const char *user, const char *passwd) {
+#else
+authenticate(const char *user, const char *passwd, const char *pws) {
+#endif
+       Bool ret;
+#if defined(HAVE_BSD_AUTH)
+       ret = auth_userokay(user, NULL, "auth-xlock", passwd) ? True : False;
+#else
+       ret = !strcmp(crypt(passwd, pws), pws) ? True : False;
+#endif
+       return ret;
+}
+#endif
+
 static void
 unlockscreen(Display *dpy, struct st_lock *lock) {
        if (dpy == NULL || lock == NULL)
@@ -215,9 +245,15 @@
 
 int
 main(int argc, char **argv) {
-#ifndef HAVE_BSD_AUTH
+#if !defined(HAVE_BSD_AUTH) && !defined(HAVE_PAM)
        const char *pws;
 #endif
+#if defined(HAVE_PAM)
+       pam_handle_t *pamh = NULL;
+       int pamret;
+       struct pam_conv conv;
+#endif
+       char *passwd = NULL;
        Display *dpy;
        int nscreens, screen;
 
@@ -228,7 +264,7 @@
        else if(argc != 1)
                usage();
 
-#ifndef HAVE_BSD_AUTH
+#if !defined(HAVE_BSD_AUTH) && !defined(HAVE_PAM)
        pws = get_password();
 #endif
 
@@ -247,10 +283,28 @@
        XSync(dpy, False);
 
        /* Everything is now blank. Now wait for the correct password. */
-#ifdef HAVE_BSD_AUTH
-       read_password(dpy);
+       if ((passwd = malloc(PASSLEN)) == NULL)
+               die("Not enough memory");
+       passwd[0] = 0;
+#if defined(HAVE_PAM)
+       conv.conv = pamconv;
+       conv.appdata_ptr = dpy;
+       pamret = pam_start(PAM_REALM, getenv("USER"), &conv, &pamh);
+       if (pamret != PAM_SUCCESS)
+               die("PAM not available");
+#endif
+       do {
+               XBell(dpy, 100);
+#if defined(HAVE_BSD_AUTH)
+               read_password(dpy, passwd);
+       } while (!authenticate(getlogin(), passwd));
+#elif defined(HAVE_PAM)
+       } while ((pamret = pam_authenticate(pamh, 0)) != PAM_SUCCESS);
+       if (pam_end(pamh, pamret) != PAM_SUCCESS)
+               pamh = NULL;
 #else
-       read_password(dpy, pws);
+               read_password(dpy, passwd);
+       } while (!authenticate(getenv("USER"), passwd, pws));
 #endif
 
        /* Password ok, unlock everything and quit. */
@@ -258,6 +312,7 @@
                unlockscreen(dpy, locks[screen]);
 
        free(locks);
+       free(passwd);
 
        XCloseDisplay(dpy);
 

Attachment: pgpnokbWhIYH0.pgp
Description: PGP signature

Reply via email to