1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
From: Ilias Tsitsimpis <i.tsitsimpis@gmail.com>
Date: Tue, 13 Oct 2015 20:24:46 +0300
Subject: slock: Use PAM for authentication
Patch slock to use PAM for authentication instead of querying the shadow
file. This means that slock can authenticate the user using some other
mechanism for login (i.e., NIS passwords, fingerprint readers, etc). In
addition, it doesn't require slock to has the effective user ID.
This patch has been written in a way that is as less intrusive as
possible so as to be easily applied to newer version.
Upstream is not interested in using PAM.
Bug-Debian: https://bugs.debian.org/739629
Forwarded: http://lists.suckless.org/dev/1011/6405.html
---
slock/config.mk | 4 +--
slock/slock.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+), 2 deletions(-)
Index: b/slock/config.mk
===================================================================
--- a/slock/config.mk
+++ b/slock/config.mk
@@ -12,10 +12,10 @@ X11LIB = /usr/X11R6/lib
# includes and libs
INCS =
-LIBS = -lc -lcrypt -lX11 -lXext -lXrandr
+LIBS = -lc -lpam -lX11 -lXext -lXrandr
# flags
-CPPFLAGS += -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
+CPPFLAGS += -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_PAM
CFLAGS += -std=c99 -pedantic -Wall ${INCS} ${CPPFLAGS}
LDFLAGS += ${LIBS}
COMPATSRC = explicit_bzero.c
Index: b/slock/slock.c
===================================================================
--- a/slock/slock.c
+++ b/slock/slock.c
@@ -25,6 +25,18 @@
char *argv0;
+#ifdef HAVE_PAM
+#include <security/pam_appl.h>
+#define PAM_SERVICE_NAME "slock"
+
+static const char *pam_passwd;
+static pam_handle_t *pamh = NULL;
+
+static void pam_init(void);
+static void pam_destroy(void);
+static int pam_auth(const char *passwd);
+#endif
+
enum {
INIT,
INPUT,
@@ -164,10 +176,14 @@ readpw(Display *dpy, struct xrandr *rr,
case XK_Return:
passwd[len] = '\0';
errno = 0;
+#ifdef HAVE_PAM
+ running = !!pam_auth(passwd);
+#else
if (!(inputhash = crypt(passwd, hash)))
fprintf(stderr, "slock: crypt: %s\n", strerror(errno));
else
running = !!strcmp(inputhash, hash);
+#endif
if (running) {
XBell(dpy, 100);
failure = 1;
@@ -328,10 +344,14 @@ main(int argc, char **argv) {
dontkillme();
#endif
+#ifdef HAVE_PAM
+ pam_init();
+#else
hash = gethash();
errno = 0;
if (!crypt("", hash))
die("slock: crypt: %s\n", strerror(errno));
+#endif
if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n");
@@ -370,5 +390,75 @@ main(int argc, char **argv) {
/* everything is now blank. Wait for the correct password */
readpw(dpy, &rr, locks, nscreens, hash);
+#ifdef HAVE_PAM
+ pam_destroy();
+#endif
+
return 0;
}
+
+
+#ifdef HAVE_PAM
+static int pam_conv(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr)
+{
+ int i;
+
+ *resp = calloc(num_msg, sizeof(**resp));
+ if (*resp == NULL)
+ return PAM_BUF_ERR;
+
+ for (i = 0; i < num_msg; i++) {
+ /* return code is currently not used but should be set to zero */
+ resp[i]->resp_retcode = 0;
+
+ if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF ||
+ msg[i]->msg_style == PAM_PROMPT_ECHO_ON)
+ resp[i]->resp = strdup(pam_passwd);
+ }
+
+ return PAM_SUCCESS;
+}
+
+static int pam_auth(const char *passwd)
+{
+ int pamret;
+
+ /* Authenticate user */
+ pam_passwd = passwd;
+ pamret = pam_authenticate(pamh, 0);
+
+ /* Check account status */
+ if (pamret == PAM_SUCCESS)
+ pamret = pam_acct_mgmt(pamh, 0);
+
+ return (pamret == PAM_SUCCESS) ? 0 : 1;
+}
+
+static void pam_init(void)
+{
+ int pamret;
+ struct passwd *pw;
+ struct pam_conv conv = {pam_conv, NULL};
+
+ pw = getpwuid(getuid());
+ if (!pw) {
+ if (errno)
+ die("slock: getpwuid: %s\n", strerror(errno));
+ else
+ die("slock: cannot retrieve username for user ID %d"
+ " from password file entry\n", getuid());
+ }
+
+ /* Start PAM */
+ pamret = pam_start(PAM_SERVICE_NAME, pw->pw_name, &conv, &pamh);
+ if (pamret != PAM_SUCCESS)
+ die("slock: pam_start() failed");
+}
+
+static void pam_destroy(void)
+{
+ /* Close PAM handle */
+ pam_end(pamh, PAM_SUCCESS);
+}
+#endif
|