diff options
Diffstat (limited to 'driver/setuid.c')
-rw-r--r-- | driver/setuid.c | 229 |
1 files changed, 69 insertions, 160 deletions
diff --git a/driver/setuid.c b/driver/setuid.c index 3ac78e4..164576f 100644 --- a/driver/setuid.c +++ b/driver/setuid.c @@ -1,5 +1,5 @@ /* setuid.c --- management of runtime privileges. - * xscreensaver, Copyright (c) 1993-1998, 2005 Jamie Zawinski <jwz@jwz.org> + * xscreensaver, Copyright © 1993-2021 Jamie Zawinski <jwz@jwz.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -14,24 +14,20 @@ # include "config.h" #endif -#include <X11/Xlib.h> /* not used for much... */ - -/* This file doesn't need the Xt headers, so stub these types out... */ -#undef XtPointer -#define XtAppContext void* -#define XrmDatabase void* -#define XtIntervalId void* -#define XtPointer void* -#define Widget void* - -#include "xscreensaver.h" - -#ifndef EPERM -#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> #endif +#include <string.h> #include <pwd.h> /* for getpwnam() and struct passwd */ #include <grp.h> /* for getgrgid() and struct group */ +#include <errno.h> + +#include "blurb.h" +#include "auth.h" + static const char * uid_gid_string (uid_t uid, gid_t gid) @@ -49,31 +45,6 @@ uid_gid_string (uid_t uid, gid_t gid) } -void -describe_uids (saver_info *si, FILE *out) -{ - uid_t uid = getuid(); - gid_t gid = getgid(); - uid_t euid = geteuid(); - gid_t egid = getegid(); - char *s1 = strdup (uid_gid_string (uid, gid)); - char *s2 = strdup (uid_gid_string (euid, egid)); - - if (si->orig_uid && *si->orig_uid && - (!!strcmp (si->orig_uid, s1) || - !!strcmp (si->orig_uid, s2))) - fprintf (out, "%s: initial effective uid/gid was %s\n", blurb(), - si->orig_uid); - - fprintf (out, "%s: running as %s", blurb(), s1); - if (uid != euid || gid != egid) - fprintf (out, "; effectively %s", s2); - fprintf(out, "\n"); - free(s1); - free(s2); -} - - /* Returns true if we need to call setgroups(). Without calling setgroups(), the process will retain any supplementary @@ -113,7 +84,7 @@ setgroups_needed_p (uid_t target_group) static int -set_ids_by_number (uid_t uid, gid_t gid, char **message_ret) +set_ids_by_number (uid_t uid, gid_t gid) { int uid_errno = 0; int gid_errno = 0; @@ -121,9 +92,6 @@ set_ids_by_number (uid_t uid, gid_t gid, char **message_ret) struct passwd *p = getpwuid (uid); struct group *g = getgrgid (gid); - if (message_ret) - *message_ret = 0; - /* Rumor has it that some implementations of of setuid() do nothing when called with -1; therefore, if the "nobody" user has a uid of -1, then that would be Really Bad. Rumor further has it that such @@ -150,13 +118,12 @@ set_ids_by_number (uid_t uid, gid_t gid, char **message_ret) if (uid_errno == 0 && gid_errno == 0 && sgs_errno == 0) { - static char buf [1024]; - sprintf (buf, "changed uid/gid to %.100s/%.100s (%ld/%ld).", - (p && p->pw_name ? p->pw_name : "???"), - (g && g->gr_name ? g->gr_name : "???"), - (long) uid, (long) gid); - if (message_ret) - *message_ret = buf; + if (verbose_p) + fprintf (stderr, "%s: changed uid/gid to %.100s/%.100s (%ld/%ld)\n", + blurb(), + (p && p->pw_name ? p->pw_name : "???"), + (g && g->gr_name ? g->gr_name : "???"), + (long) uid, (long) gid); return 0; } else @@ -176,7 +143,7 @@ set_ids_by_number (uid_t uid, gid_t gid, char **message_ret) else { errno = sgs_errno; - perror(buf); + perror (buf); } fprintf (stderr, "%s: effective group list: ", blurb()); @@ -206,11 +173,11 @@ set_ids_by_number (uid_t uid, gid_t gid, char **message_ret) (g && g->gr_name ? g->gr_name : "???"), (long) gid); if (gid_errno == -1) - fprintf(stderr, "%s: unknown error\n", buf); + fprintf (stderr, "%s: unknown error\n", buf); else { errno = gid_errno; - perror(buf); + perror (buf); } } @@ -241,121 +208,63 @@ set_ids_by_number (uid_t uid, gid_t gid, char **message_ret) lock-mode.) *** WARNING: DO NOT DISABLE ANY OF THE FOLLOWING CODE! - If you do so, you will open a security hole. See the sections - of the xscreensaver manual titled "LOCKING AND ROOT LOGINS", - and "USING XDM". + If you do so, you will open a security hole. + Do not log in to an X11 desktop as root. + Log in as a normal users and 'sudo' as needed. */ void -hack_uid (saver_info *si) +disavow_privileges (void) { + uid_t euid = geteuid(); + gid_t egid = getegid(); + uid_t uid = getuid(); + gid_t gid = getgid(); + struct passwd *p; - /* Discard privileges, and set the effective user/group ids to the - real user/group ids. That is, give up our "chmod +s" rights. - */ - { - uid_t euid = geteuid(); - gid_t egid = getegid(); - uid_t uid = getuid(); - gid_t gid = getgid(); - - si->orig_uid = strdup (uid_gid_string (euid, egid)); - - if (uid != euid || gid != egid) - if (set_ids_by_number (uid, gid, &si->uid_message) != 0) - saver_exit (si, 1, 0); - } - - - /* Locking can't work when running as root, because we have no way of - knowing what the user id of the logged in user is (so we don't know - whose password to prompt for.) - - *** WARNING: DO NOT DISABLE THIS CODE! - If you do so, you will open a security hole. See the sections - of the xscreensaver manual titled "LOCKING AND ROOT LOGINS", - and "USING XDM". - */ - if (getuid() == (uid_t) 0) + if (uid != euid || gid != egid) { - si->locking_disabled_p = True; - si->nolock_reason = "running as root"; + if (verbose_p) + fprintf (stderr, "%s: initial effective uid/gid was %s\n", blurb(), + uid_gid_string (euid, egid)); + if (set_ids_by_number (uid, gid) != 0) + exit (1); /* already printed error */ } - - /* If we're running as root, switch to a safer user. This is above and - beyond the fact that we've disabling locking, above -- the theory is - that running graphics demos as root is just always a stupid thing - to do, since they have probably never been security reviewed and are - more likely to be buggy than just about any other kind of program. - (And that assumes non-malicious code. There are also attacks here.) - - *** WARNING: DO NOT DISABLE THIS CODE! - If you do so, you will open a security hole. See the sections - of the xscreensaver manual titled "LOCKING AND ROOT LOGINS", - and "USING XDM". + /* If we're still running as root, or if the user we are running at seems + to be in any way hinky, exit and do not allow password authentication + to continue. */ - if (getuid() == (uid_t) 0) - { - struct passwd *p; - - p = getpwnam ("nobody"); - if (! p) p = getpwnam ("noaccess"); - if (! p) p = getpwnam ("daemon"); - if (! p) - { - fprintf (stderr, - "%s: running as root, and couldn't find a safer uid.\n", - blurb()); - saver_exit(si, 1, 0); - } + uid = getuid (); /* get it again */ + p = getpwuid (uid); - if (set_ids_by_number (p->pw_uid, p->pw_gid, &si->uid_message) != 0) - saver_exit (si, -1, 0); + if (!p || + uid == (uid_t) 0 || + uid == (uid_t) -1 || + uid == (uid_t) -2 || + p->pw_uid == (uid_t) 0 || + p->pw_uid == (uid_t) -1 || + p->pw_uid == (uid_t) -2 || + !p->pw_name || + !*p->pw_name || + !strcmp (p->pw_name, "root") || + !strcmp (p->pw_name, "nobody") || + !strcmp (p->pw_name, "noaccess") || + !strcmp (p->pw_name, "operator") || + !strcmp (p->pw_name, "daemon") || + !strcmp (p->pw_name, "bin") || + !strcmp (p->pw_name, "adm") || + !strcmp (p->pw_name, "sys") || + !strcmp (p->pw_name, "games")) + { + fprintf (stderr, + "%s: running as user \"%s\" -- authentication disallowed\n", + blurb(), + (p && p->pw_name && *p->pw_name + ? p->pw_name + : "<unknown>")); + exit (1); } - - /* If there's anything even remotely funny looking about the passwd struct, - or if we're running as some other user from the list below (a - non-comprehensive selection of users known to be privileged in some way, - and not normal end-users) then disable locking. If it was possible, - switching to "nobody" would be the thing to do, but only root itself has - the privs to do that. - - *** WARNING: DO NOT DISABLE THIS CODE! - If you do so, you will open a security hole. See the sections - of the xscreensaver manual titled "LOCKING AND ROOT LOGINS", - and "USING XDM". - */ - { - uid_t uid = getuid (); /* get it again */ - struct passwd *p = getpwuid (uid); /* get it again */ - - if (!p || - uid == (uid_t) 0 || - uid == (uid_t) -1 || - uid == (uid_t) -2 || - p->pw_uid == (uid_t) 0 || - p->pw_uid == (uid_t) -1 || - p->pw_uid == (uid_t) -2 || - !p->pw_name || - !*p->pw_name || - !strcmp (p->pw_name, "root") || - !strcmp (p->pw_name, "nobody") || - !strcmp (p->pw_name, "noaccess") || - !strcmp (p->pw_name, "operator") || - !strcmp (p->pw_name, "daemon") || - !strcmp (p->pw_name, "bin") || - !strcmp (p->pw_name, "adm") || - !strcmp (p->pw_name, "sys") || - !strcmp (p->pw_name, "games")) - { - static char buf [1024]; - sprintf (buf, "running as %.100s", - (p && p->pw_name && *p->pw_name - ? p->pw_name : "<unknown>")); - si->nolock_reason = buf; - si->locking_disabled_p = True; - si->dangerous_uid_p = True; - } - } + if (verbose_p) + fprintf (stderr, "%s: running as user \"%s\"\n", blurb(), p->pw_name); } |