From: Christian Franke Date: Sun, 24 Jan 2010 01:09:39 +0100 Subject: [PATCH] Added PAM Support --- config.mk | 4 +- slock.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 95 insertions(+), 16 deletions(-) diff --git a/config.mk b/config.mk index cfa5369..acfc784 100644 --- a/config.mk +++ b/config.mk @@ -11,10 +11,10 @@ X11LIB = /usr/X11R6/lib # includes and libs INCS = -I. -I/usr/include -I${X11INC} -LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lpam # flags -CPPFLAGS = -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H +CPPFLAGS = -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H -DUSE_PAM_AUTH CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} LDFLAGS = -s ${LIBS} diff --git a/slock.c b/slock.c index 6f2e8af..aca2158 100644 --- a/slock.c +++ b/slock.c @@ -12,16 +12,60 @@ #include #include #include +#include #include #include #include #include -#if HAVE_BSD_AUTH +#if USE_BSD_AUTH #include #include #endif +#if !defined(USE_PAM_AUTH) && !defined(USE_COMMON_AUTH) && !defined(USE_BSD_AUTH) +#error Sorry, but you have to use at least one authentication method. +#endif + +#ifdef USE_PAM_AUTH +#include +#define PAM_ASSERT(w,x,y) do { if (x != PAM_SUCCESS) { \ + syslog(LOG_ERR, "Error " y ": %s", pam_strerror(w,x)); \ + goto out; \ + } } while(0) + +static char* emptystr = ""; + +int our_conv(int num_msg, const struct pam_message **msgm, + struct pam_response **response, void *appdata_ptr) { + int count = 0; + struct pam_response *reply; + + if (num_msg <= 0) + return PAM_CONV_ERR; + + reply = calloc(num_msg, sizeof(struct pam_response)); + if (!reply) + return PAM_CONV_ERR; + + for (count = 0; count < num_msg; count++) { + switch (msgm[count]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + reply[count].resp_retcode = 0; + reply[count].resp = strdup((char*)appdata_ptr); + break; + default: + reply[count].resp_retcode = 0; + reply[count].resp = strdup(emptystr); + break; + } + } + + *response = reply; + return PAM_SUCCESS; +} + +#endif static void die(const char *errstr, ...) { va_list ap; @@ -32,17 +76,17 @@ die(const char *errstr, ...) { exit(EXIT_FAILURE); } -#ifndef HAVE_BSD_AUTH +#ifdef USE_COMMON_AUTH static const char * get_password() { /* only run as root */ const char *rval; - struct passwd *pw; + struct password *pw; if(geteuid() != 0) die("slock: cannot retrieve password entry (make sure to suid slock)\n"); pw = getpwuid(getuid()); endpwent(); - rval = pw->pw_passwd; + rval = pw->pw_password; #if HAVE_SHADOW_H { @@ -63,12 +107,23 @@ get_password() { /* only run as root */ int main(int argc, char **argv) { char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; - char buf[32], passwd[256]; + char buf[32], password[256]; int num, screen; -#ifndef HAVE_BSD_AUTH +#ifdef USE_COMMON_AUTH const char *pws; #endif +#ifdef USE_PAM_AUTH + pam_handle_t *pamh = NULL; + int pam_ec; + struct pam_conv conv = { + our_conv, + (void*)password + }; + struct passwd *pwd; + pwd = getpwuid(getuid()); + endpwent(); +#endif unsigned int len; Bool running = True; Cursor invisible; @@ -85,7 +140,8 @@ main(int argc, char **argv) { else if(argc != 1) die("usage: slock [-v]\n"); -#ifndef HAVE_BSD_AUTH + openlog("slock", LOG_CONS | LOG_NDELAY, LOG_AUTHPRIV); +#ifdef USE_COMMON_AUTH pws = get_password(); #endif @@ -144,11 +200,33 @@ main(int argc, char **argv) { continue; 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); + password[len] = 0; +#ifdef USE_BSD_AUTH + running = !auth_userokay(getlogin(), NULL, "auth-xlock", password); +#endif +#ifdef USE_COMMON_AUTH + running = strcmp(crypt(password, pws), pws); +#endif +#ifdef USE_PAM_AUTH + pam_ec = pam_start("system-auth", pwd->pw_name, &conv, &pamh); + if (pam_ec != PAM_SUCCESS) + pamh = NULL; + PAM_ASSERT(pamh, pam_ec, "getting PAM session"); + + pam_ec = pam_authenticate(pamh, 0); + PAM_ASSERT(pamh, pam_ec, "authenticating"); + + pam_ec = pam_acct_mgmt(pamh, 0); + PAM_ASSERT(pamh, pam_ec, "verifying account"); + + /* since we got here, password and account are valid */ + running = 0; +out: + if (pamh) { + pam_ec = pam_end(pamh, pam_ec); + if (pam_ec != PAM_SUCCESS) + syslog(LOG_ERR, "Error closing PAM session: %s", pam_strerror(pamh, pam_ec)); + } #endif if (running != 0) XBell(dpy, 100); @@ -162,8 +240,8 @@ main(int argc, char **argv) { --len; break; default: - if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd)) { - memcpy(passwd + len, buf, num); + if(num && !iscntrl((int) buf[0]) && (len + num < sizeof password)) { + memcpy(password + len, buf, num); len += num; } break; @@ -174,5 +252,6 @@ main(int argc, char **argv) { XFreePixmap(dpy, pmap); XDestroyWindow(dpy, w); XCloseDisplay(dpy); + closelog(); return 0; } -- 1.6.5.1