Ensure Polyphemus-Mitigation and properly drop privileges

Don't hide privilege drops inside readpw() and actually make it
configurable what you are dropping to in config.h.

The privilege drop comes after opening the Display because the
user "nobody" with "nogroup" can't do that.

So why do I call this strategy the Polyphemus-Mitigation?

"""
After the giant returns in the evening and eats two more of the men,
Odysseus offers Polyphemus some strong and undiluted wine given to him
earlier on his journey. Drunk and unwary, the giant asks Odysseus his
name, promising him a guest-gift if he answers. Odysseus tells him
"Οὖτις", which means "nobody" and Polyphemus promises to eat this
"Nobody" last of all. With that, he falls into a drunken sleep. Odysseus
had meanwhile hardened a wooden stake in the fire and now drives it into
Polyphemus' eye. When Polyphemus shouts for help from his fellow giants,
saying that "Nobody" has hurt him, they think Polyphemus is being
afflicted by divine power and recommend prayer as the answer.
"""

(source: https://en.wikipedia.org/wiki/Polyphemus)
This commit is contained in:
FRIGN 2016-09-07 13:32:29 +02:00 committed by Markus Teich
parent 04143fd68d
commit 22eba05f36
3 changed files with 30 additions and 6 deletions

View file

@ -1,3 +1,7 @@
/* user and group to drop privileges to */
static const char *user = "nobody";
static const char *group = "nogroup";
static const char *colorname[NUMCOLS] = { static const char *colorname[NUMCOLS] = {
"black", /* after initialization */ "black", /* after initialization */
"#005577", /* during input */ "#005577", /* during input */

View file

@ -15,7 +15,7 @@ INCS = -I. -I/usr/include -I${X11INC}
LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr
# flags # flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
LDFLAGS = -s ${LIBS} LDFLAGS = -s ${LIBS}
COMPATSRC = explicit_bzero.c COMPATSRC = explicit_bzero.c

30
slock.c
View file

@ -6,6 +6,7 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <grp.h>
#include <pwd.h> #include <pwd.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
@ -83,7 +84,6 @@ dontkillme(void)
} }
#endif #endif
/* only run as root */
static const char * static const char *
getpw(void) getpw(void)
{ {
@ -119,10 +119,6 @@ getpw(void)
} }
#endif /* HAVE_SHADOW_H */ #endif /* HAVE_SHADOW_H */
/* drop privileges */
if (geteuid() == 0 &&
((getegid() != pw->pw_gid && setgid(pw->pw_gid) < 0) || setuid(pw->pw_uid) < 0))
die("slock: cannot drop privileges\n");
return rval; return rval;
} }
@ -316,6 +312,10 @@ usage(void)
int int
main(int argc, char **argv) { main(int argc, char **argv) {
struct passwd *pwd;
struct group *grp;
uid_t duid;
gid_t dgid;
const char *pws; const char *pws;
Display *dpy; Display *dpy;
int s, nlocks; int s, nlocks;
@ -328,6 +328,18 @@ main(int argc, char **argv) {
usage(); usage();
} ARGEND } 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__ #ifdef __linux__
dontkillme(); dontkillme();
#endif #endif
@ -339,6 +351,14 @@ main(int argc, char **argv) {
if (!(dpy = XOpenDisplay(NULL))) if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n"); 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 */ /* check for Xrandr support */
rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase); rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase);