File: Use-PAM-for-authentication.patch

package info (click to toggle)
suckless-tools 49-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 944 kB
  • sloc: ansic: 5,586; makefile: 464; sh: 80
file content (167 lines) | stat: -rw-r--r-- 4,209 bytes parent folder | download
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