#include <ctype.h>
#include <errno.h>
+#include <grp.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#if HAVE_BSD_AUTH
-#include <login_cap.h>
-#include <bsd_auth.h>
-#endif
-
#include "arg.h"
#include "util.h"
static Lock **locks;
static int nscreens;
-static Bool running = True;
-static Bool failure = False;
static Bool rr;
static int rrevbase;
static int rrerrbase;
}
#endif
-#ifndef HAVE_BSD_AUTH
-/* only run as root */
static const char *
getpw(void)
{
const char *rval;
struct passwd *pw;
+ /* Check if the current user has a password entry */
errno = 0;
if (!(pw = getpwuid(getuid()))) {
if (errno)
- die("getpwuid: %s\n", strerror(errno));
+ die("slock: getpwuid: %s\n", strerror(errno));
else
- die("cannot retrieve password entry\n");
+ die("slock: cannot retrieve password entry\n");
}
rval = pw->pw_passwd;
if (rval[0] == 'x' && rval[1] == '\0') {
struct spwd *sp;
if (!(sp = getspnam(getenv("USER"))))
- die("cannot retrieve shadow entry (make sure to suid or sgid slock)\n");
+ die("slock: getspnam: cannot retrieve shadow entry (make sure to suid or sgid slock)\n");
rval = sp->sp_pwdp;
}
-#endif
+#else
+ if (rval[0] == '*' && rval[1] == '\0') {
+#ifdef __OpenBSD__
+ if (!(pw = getpwnam_shadow(getenv("USER"))))
+ die("slock: getpwnam_shadow: cannot retrieve shadow entry (make sure to suid or sgid slock)\n");
+ rval = pw->pw_passwd;
+#else
+ die("slock: getpwuid: cannot retrieve shadow entry (make sure to suid or sgid slock)\n");
+#endif /* __OpenBSD__ */
+ }
+#endif /* HAVE_SHADOW_H */
- /* drop privileges */
- if (geteuid() == 0 &&
- ((getegid() != pw->pw_gid && setgid(pw->pw_gid) < 0) || setuid(pw->pw_uid) < 0))
- die("cannot drop privileges\n");
return rval;
}
-#endif
static void
-#ifdef HAVE_BSD_AUTH
-readpw(Display *dpy)
-#else
readpw(Display *dpy, const char *pws)
-#endif
{
char buf[32], passwd[256], *encrypted;
- int num, screen;
+ int num, screen, running, failure;
unsigned int len, color;
KeySym ksym;
XEvent ev;
static int oldc = INIT;
len = 0;
- running = True;
+ running = 1;
+ failure = 0;
/* As "slock" stands for "Simple X display locker", the DPMS settings
* had been removed and you can set it with "xset" or some other
switch (ksym) {
case XK_Return:
passwd[len] = 0;
-#ifdef HAVE_BSD_AUTH
- running = !auth_userokay(getlogin(), NULL, "auth-slock", passwd);
-#else
errno = 0;
if (!(encrypted = crypt(passwd, pws)))
fprintf(stderr, "slock: crypt: %s\n", strerror(errno));
else
running = !!strcmp(encrypted, pws);
-#endif
if (running) {
XBell(dpy, 100);
failure = True;
static void
cleanup(Display *dpy)
{
+ int s;
+
+ for (s = 0; s < nscreens; ++s)
+ unlockscreen(dpy, locks[s]);
+
free(locks);
XCloseDisplay(dpy);
}
XSetWindowAttributes wa;
Cursor invisible;
- if (!running || dpy == NULL || screen < 0 || !(lock = malloc(sizeof(Lock))))
+ if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(Lock))))
return NULL;
lock->screen = screen;
XDefineCursor(dpy, lock->win, invisible);
/* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */
- for (i = 6, ptgrab = kbgrab = -1; i; --i) {
+ for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) {
if (ptgrab != GrabSuccess) {
ptgrab = XGrabPointer(dpy, lock->root, False,
ButtonPressMask | ButtonReleaseMask |
fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n", screen);
if (kbgrab != GrabSuccess)
fprintf(stderr, "slock: unable to grab keyboard for screen %d\n", screen);
- running = 0;
- unlockscreen(dpy, lock);
return NULL;
}
int
main(int argc, char **argv) {
-#ifndef HAVE_BSD_AUTH
+ struct passwd *pwd;
+ struct group *grp;
+ uid_t duid;
+ gid_t dgid;
const char *pws;
-#endif
Display *dpy;
int s, nlocks;
usage();
} ARGEND
+ /* validate drop-user and -group */
+ errno = 0;
+ if (!(pwd = getpwnam(user)))
+ die("slock: getpwnam %s: %s\n", user, errno ?
+ strerror(errno) : "user entry not found");
+ duid = pwd->pw_uid;
+ errno = 0;
+ if (!(grp = getgrnam(group)))
+ die("slock: getgrnam %s: %s\n", group, errno ?
+ strerror(errno) : "group entry not found");
+ dgid = grp->gr_gid;
+
#ifdef __linux__
dontkillme();
#endif
- /* Check if the current user has a password entry */
- errno = 0;
- if (!getpwuid(getuid())) {
- if (errno == 0)
- die("slock: no password entry for current user\n");
- else
- die("slock: getpwuid: %s\n", strerror(errno));
- }
-
-#ifndef HAVE_BSD_AUTH
pws = getpw();
if (strlen(pws) < 2)
die("slock: failed to get user password hash.\n");
-#endif
if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n");
+ /* drop privileges */
+ if (setgroups(0, NULL) < 0)
+ die("slock: setgroups: %s\n", strerror(errno));
+ if (setgid(dgid) < 0)
+ die("slock: setgid: %s\n", strerror(errno));
+ if (setuid(duid) < 0)
+ die("slock: setuid: %s\n", strerror(errno));
+
/* check for Xrandr support */
rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase);
/* get number of screens in display "dpy" and blank them */
nscreens = ScreenCount(dpy);
- if (!(locks = malloc(sizeof(Lock *) * nscreens))) {
+ if (!(locks = calloc(nscreens, sizeof(Lock *)))) {
XCloseDisplay(dpy);
die("slock: out of memory\n");
}
for (nlocks = 0, s = 0; s < nscreens; s++) {
if ((locks[s] = lockscreen(dpy, s)) != NULL)
nlocks++;
+ else
+ break;
}
XSync(dpy, 0);
- /* did we actually manage to lock anything? */
- if (nlocks == 0) {
- /* nothing to protect */
+ /* did we manage to lock everything? */
+ if (nlocks != nscreens) {
cleanup(dpy);
return 1;
}
}
/* everything is now blank. Wait for the correct password */
-#ifdef HAVE_BSD_AUTH
- readpw(dpy);
-#else
readpw(dpy, pws);
-#endif
/* password ok, unlock everything and quit */
- for (s = 0; s < nscreens; s++)
- unlockscreen(dpy, locks[s]);
-
cleanup(dpy);
return 0;