diff -abBpur xtrlock-2.0/Makefile.noimake xtrlock-2.0.akira/Makefile.noimake --- xtrlock-2.0/Makefile.noimake 1995-11-07 15:51:48.000000000 +0100 +++ xtrlock-2.0.akira/Makefile.noimake 2005-03-22 18:01:29.616637928 +0100 @@ -13,17 +13,47 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -LDLIBS=-lX11 -CC=gcc -CFLAGS=-Wall +ifdef PAM +PAM_LDLIBS = -lpam -lpam_misc +PAM_CFLAGS = -DPAM_PWD +else +PAM_LDLIBS = +PAM_CFLAGS = +endif + +ifdef SHADOW +SHADOW_LDLIBS = +SHADOW_CFLAGS = -DSHADOW_PWD +else +SHADOW_LDLIBS = +SHADOW_CFLAGS = +endif + +CC ?= gcc +override CFLAGS += -Wall $(PAM_CFLAGS) $(SHADOW_CFLAGS) +override LDFLAGS += -L/usr/X11R6/lib +override LDLIBS += -lX11 -lcrypt $(PAM_LDLIBS) $(SHADOW_LDLIBS) + INSTALL=install -xtrlock: xtrlock.o +first : xtrlock -xtrlock.o: xtrlock.c lock.bitmap mask.bitmap patchlevel.h +clean : + rm -fr *.o + +distclean: + rm -fr *.o xtrlock install: xtrlock $(INSTALL) -c -m 755 xtrlock /usr/bin/X11 install.man: $(INSTALL) -c -m 644 xtrlock.man /usr/man/man1/xtrlock.1x + +# +########################################################## +xtrlock: xtrlock.o + +xtrlock.o: xtrlock.c lock.bitmap mask.bitmap patchlevel.h + + diff -abBpur xtrlock-2.0/xtrlock.c xtrlock-2.0.akira/xtrlock.c --- xtrlock-2.0/xtrlock.c 1997-10-22 12:32:28.000000000 +0200 +++ xtrlock-2.0.akira/xtrlock.c 2005-03-22 18:10:08.490757072 +0100 @@ -1,21 +1,24 @@ -/* - * xtrlock.c - * - * X Transparent Lock - * - * Copyright (C)1993,1994 Ian Jackson - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ +/*------------------------------------------------------------------*\ + xtrlock.c + X Transparent Lock + + Copyright (C)1993,1994 Ian Jackson + + This is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +\*------------------------------------------------------------------*/ + +/*------------------------------------------------------------------*\ +\*------------------------------------------------------------------*/ #include #include #include @@ -39,21 +42,121 @@ #ifdef SHADOW_PWD #include -#endif +#endif /* SHADOW_PWD */ + +#ifdef PAM_PWD +#include +#include +#endif /* PAM_PWD */ + +/*----------------------------------------------*\ +\*----------------------------------------------*/ #include "lock.bitmap" #include "mask.bitmap" #include "patchlevel.h" -Display *display; -Window window, root; +/*------------------------------------------------------------------*\ + globals +\*------------------------------------------------------------------*/ #define TIMEOUTPERATTEMPT 30000 #define MAXGOODWILL (TIMEOUTPERATTEMPT*5) #define INITIALGOODWILL MAXGOODWILL #define GOODWILLPORTION 0.3 +Display *display; +Window window, root; struct passwd *pw; + + +/*------------------------------------------------------------------*\ + pam-related stuff + + taken from pure-ftpd's authstuff, but you can see similar stuff + in xlockmore, openssh and basicly all pam-related apps :) +\*------------------------------------------------------------------*/ +#ifdef PAM_PWD +#define PAM_YN { \ + if (PAM_error != 0 || pam_error != PAM_SUCCESS) { \ + fprintf(stderr, "pam error:%s\n", pam_strerror(pam_handle, pam_error)); \ + pam_end(pam_handle, pam_error); \ + return 0;\ + } \ +} + +#define GET_MEM \ + size += sizeof(struct pam_response); \ + if ((reply = realloc(reply, size)) == NULL) { \ + PAM_error = 1; \ + return PAM_CONV_ERR; \ + } + +static const char* PAM_username = NULL; +static const char* PAM_password = NULL; +static int PAM_error = 0; +static int pam_error = PAM_SUCCESS; + +static int PAM_conv(int num_msg, const struct pam_message **msgs, + struct pam_response **resp, void *appdata_ptr) { + + int count = 0; + unsigned int replies = 0U; + struct pam_response *reply = NULL; + size_t size = (size_t) 0U; + + (void) appdata_ptr; + *resp = NULL; + for (count = 0; count < num_msg; count++) { + switch (msgs[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: + GET_MEM; + memset(&reply[replies], 0, sizeof reply[replies]); + if ((reply[replies].resp = strdup(PAM_username)) == NULL) { +#ifdef PAM_BUF_ERR + reply[replies].resp_retcode = PAM_BUF_ERR; +#endif + PAM_error = 1; + return PAM_CONV_ERR; + } + reply[replies++].resp_retcode = PAM_SUCCESS; + /* PAM frees resp */ + break; + case PAM_PROMPT_ECHO_OFF: + GET_MEM; + memset(&reply[replies], 0, sizeof reply[replies]); + if ((reply[replies].resp = strdup(PAM_password)) == NULL) { +#ifdef PAM_BUF_ERR + reply[replies].resp_retcode = PAM_BUF_ERR; +#endif + PAM_error = 1; + return PAM_CONV_ERR; + } + reply[replies++].resp_retcode = PAM_SUCCESS; + /* PAM frees resp */ + break; + case PAM_TEXT_INFO: + /* ignore it... */ + break; + case PAM_ERROR_MSG: + default: + /* Must be an error of some sort... */ + free(reply); + PAM_error = 1; + return PAM_CONV_ERR; + } + } + *resp = reply; + return PAM_SUCCESS; +} + +static struct pam_conv PAM_conversation = { + &PAM_conv, NULL +}; +#endif +/*------------------------------------------------------------------*\ +\*------------------------------------------------------------------*/ + int passwordok(const char *s) { #if 0 char key[3]; @@ -67,21 +170,39 @@ int passwordok(const char *s) { #else /* simpler, and should work with crypt() algorithms using longer salt strings (like the md5-based one on freebsd). --marekm */ +#ifdef PAM_PWD + pam_handle_t* pam_handle = NULL; + PAM_username = pw->pw_name; + PAM_password = s; + pam_error = pam_start("login", PAM_username, &PAM_conversation, &pam_handle); + PAM_YN; + pam_error = pam_authenticate(pam_handle, 0); + PAM_YN; + pam_error = pam_end(pam_handle, pam_error); + PAM_YN; + return 1; +#else return !strcmp(crypt(s, pw->pw_passwd), pw->pw_passwd); -#endif +#endif /* PAM_PWD */ +#endif /* 0 */ } -int main(int argc, char **argv){ + +/*------------------------------------------------------------------*\ +\*------------------------------------------------------------------*/ + +int main(int argc, char **argv) { XEvent ev; KeySym ks; char cbuf[10], rbuf[50]; - int clen, rlen=0; - long goodwill= INITIALGOODWILL, timeout= 0; + int clen, rlen = 0; + long goodwill = INITIALGOODWILL, timeout = 0; XSetWindowAttributes attrib; Cursor cursor; - Pixmap csr_source,csr_mask; + Pixmap csr_source, csr_mask; XColor csr_fg, csr_bg, dummy; int ret; + #ifdef SHADOW_PWD struct spwd *sp; #endif @@ -87,12 +208,17 @@ int main(int argc, char **argv){ #endif if (argc != 1) { - fprintf(stderr,"xtrlock (version %s): no arguments allowed\n",program_version); + fprintf(stderr, "xtrlock (version %s): no arguments allowed\n", + program_version); exit(1); } - errno=0; pw= getpwuid(getuid()); - if (!pw) { perror("password entry for uid not found"); exit(1); } + errno = 0; + pw = getpwuid(getuid()); + if (!pw) { + perror("password entry for uid not found"); + exit(1); + } #ifdef SHADOW_PWD sp = getspnam(pw->pw_name); if (sp) @@ -102,103 +228,121 @@ int main(int argc, char **argv){ /* we can be installed setuid root to support shadow passwords, and we don't need root privileges any longer. --marekm */ setuid(getuid()); +#ifndef PAM_PWD if (strlen(pw->pw_passwd) < 13) { - fputs("password entry has no pwd\n",stderr); exit(1); + fputs("password entry has no pwd\n", stderr); + exit(1); } +#endif /* PAM_PWD */ - display= XOpenDisplay(0); + display = XOpenDisplay(0); - if (display==NULL) { - fprintf(stderr,"xtrlock (version %s): cannot open display\n", + if (display == NULL) { + fprintf(stderr, "xtrlock (version %s): cannot open display\n", program_version); exit(1); } - attrib.override_redirect= True; - window= XCreateWindow(display,DefaultRootWindow(display), - 0,0,1,1,0,CopyFromParent,InputOnly,CopyFromParent, - CWOverrideRedirect,&attrib); - - XSelectInput(display,window,KeyPressMask|KeyReleaseMask); - - csr_source= XCreateBitmapFromData(display,window,lock_bits,lock_width,lock_height); - csr_mask= XCreateBitmapFromData(display,window,mask_bits,mask_width,mask_height); + attrib.override_redirect = True; + window = XCreateWindow(display, DefaultRootWindow(display), + 0, 0, 1, 1, 0, CopyFromParent, InputOnly, + CopyFromParent, CWOverrideRedirect, &attrib); + + XSelectInput(display, window, KeyPressMask | KeyReleaseMask); + + csr_source = + XCreateBitmapFromData(display, window, lock_bits, lock_width, + lock_height); + csr_mask = + XCreateBitmapFromData(display, window, mask_bits, mask_width, + mask_height); ret = XAllocNamedColor(display, DefaultColormap(display, DefaultScreen(display)), - "steelblue3", - &dummy, &csr_bg); - if (ret==0) + "steelblue3", &dummy, &csr_bg); + if (ret == 0) XAllocNamedColor(display, DefaultColormap(display, DefaultScreen(display)), - "black", - &dummy, &csr_bg); + "black", &dummy, &csr_bg); ret = XAllocNamedColor(display, - DefaultColormap(display,DefaultScreen(display)), - "grey25", - &dummy, &csr_fg); - if (ret==0) + DefaultColormap(display, DefaultScreen(display)), + "grey25", &dummy, &csr_fg); + if (ret == 0) XAllocNamedColor(display, DefaultColormap(display, DefaultScreen(display)), - "white", - &dummy, &csr_bg); + "white", &dummy, &csr_bg); - cursor= XCreatePixmapCursor(display,csr_source,csr_mask,&csr_fg,&csr_bg, - lock_x_hot,lock_y_hot); + cursor = + XCreatePixmapCursor(display, csr_source, csr_mask, &csr_fg, &csr_bg, + lock_x_hot, lock_y_hot); - XMapWindow(display,window); - if (XGrabKeyboard(display,window,False,GrabModeAsync,GrabModeAsync, - CurrentTime)!=GrabSuccess) { + XMapWindow(display, window); + if (XGrabKeyboard(display, window, False, GrabModeAsync, GrabModeAsync, + CurrentTime) != GrabSuccess) { exit(1); } - if (XGrabPointer(display,window,False,(KeyPressMask|KeyReleaseMask)&0, - GrabModeAsync,GrabModeAsync,None, - cursor,CurrentTime)!=GrabSuccess) { - XUngrabKeyboard(display,CurrentTime); + if (XGrabPointer + (display, window, False, (KeyPressMask | KeyReleaseMask) & 0, + GrabModeAsync, GrabModeAsync, None, cursor, + CurrentTime) != GrabSuccess) { + XUngrabKeyboard(display, CurrentTime); exit(1); } - for (;;) { - XNextEvent(display,&ev); + for(;;) { + XNextEvent(display, &ev); switch (ev.type) { case KeyPress: - if (ev.xkey.time < timeout) { XBell(display,0); break; } - clen= XLookupString(&ev.xkey,cbuf,9,&ks,0); + if (ev.xkey.time < timeout) { + XBell(display, 0); + break; + } + clen = XLookupString(&ev.xkey, cbuf, 9, &ks, 0); switch (ks) { - case XK_Escape: case XK_Clear: - rlen=0; break; - case XK_Delete: case XK_BackSpace: - if (rlen>0) rlen--; - break; - case XK_Linefeed: case XK_Return: - if (rlen==0) break; - rbuf[rlen]=0; - if (passwordok(rbuf)) goto loop_x; - XBell(display,0); - rlen= 0; + case XK_Escape: + case XK_Clear: + rlen = 0; + break; + case XK_Delete: + case XK_BackSpace: + if (rlen > 0) + rlen--; + break; + case XK_Linefeed: + case XK_Return: + if (rlen == 0) + break; + rbuf[rlen] = 0; + if (passwordok(rbuf)) + return 0; + XBell(display, 0); + rlen = 0; if (timeout) { - goodwill+= ev.xkey.time - timeout; + goodwill += ev.xkey.time - timeout; if (goodwill > MAXGOODWILL) { - goodwill= MAXGOODWILL; + goodwill = MAXGOODWILL; } } - timeout= -goodwill*GOODWILLPORTION; - goodwill+= timeout; - timeout+= ev.xkey.time + TIMEOUTPERATTEMPT; + timeout = -goodwill * GOODWILLPORTION; + goodwill += timeout; + timeout += ev.xkey.time + TIMEOUTPERATTEMPT; break; default: - if (clen != 1) break; - if (rlen < sizeof(rbuf)) rbuf[rlen]= cbuf[0]; + if (clen != 1) + break; + if (rlen < sizeof(rbuf)) + rbuf[rlen] = cbuf[0]; rlen++; break; } break; default: + break; } } - loop_x: - exit(0); + + return 0; }