mirror of
git://slackware.nl/current.git
synced 2024-12-27 09:59:16 +01:00
5a12e7c134
Wed Aug 26 10:00:38 CDT 2009 Slackware 13.0 x86_64 is released as stable! Thanks to everyone who helped make this release possible -- see the RELEASE_NOTES for the credits. The ISOs are off to the replicator. This time it will be a 6 CD-ROM 32-bit set and a dual-sided 32-bit/64-bit x86/x86_64 DVD. We're taking pre-orders now at store.slackware.com. Please consider picking up a copy to help support the project. Once again, thanks to the entire Slackware community for all the help testing and fixing things and offering suggestions during this development cycle. As always, have fun and enjoy! -P.
274 lines
7.9 KiB
C
274 lines
7.9 KiB
C
/* setuid.c --- management of runtime privileges.
|
|
* xscreensaver, Copyright (c) 1993-1998 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
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation. No representations are made about the suitability of this
|
|
* software for any purpose. It is provided "as is" without express or
|
|
* implied warranty.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# 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>
|
|
#endif
|
|
|
|
#include <pwd.h> /* for getpwnam() and struct passwd */
|
|
#include <grp.h> /* for getgrgid() and struct group */
|
|
|
|
static const char *
|
|
uid_gid_string (uid_t uid, gid_t gid)
|
|
{
|
|
static char buf[255];
|
|
struct passwd *p = 0;
|
|
struct group *g = 0;
|
|
p = getpwuid (uid);
|
|
g = getgrgid (gid);
|
|
sprintf (buf, "%s/%s (%ld/%ld)",
|
|
(p && p->pw_name ? p->pw_name : "???"),
|
|
(g && g->gr_name ? g->gr_name : "???"),
|
|
(long) uid, (long) gid);
|
|
return buf;
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
static int
|
|
set_ids_by_number (uid_t uid, gid_t gid, char **message_ret)
|
|
{
|
|
int uid_errno = 0;
|
|
int gid_errno = 0;
|
|
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
|
|
systems really ought to be using -2 for "nobody", since that works.
|
|
So, if we get a uid (or gid, for good measure) of -1, switch to -2
|
|
instead. Note that this must be done after we've looked up the
|
|
user/group names with getpwuid(-1) and/or getgrgid(-1).
|
|
*/
|
|
if (gid == (gid_t) -1) gid = (gid_t) -2;
|
|
if (uid == (uid_t) -1) uid = (uid_t) -2;
|
|
|
|
errno = 0;
|
|
if (setgid (gid) != 0)
|
|
gid_errno = errno ? errno : -1;
|
|
|
|
errno = 0;
|
|
if (setuid (uid) != 0)
|
|
uid_errno = errno ? errno : -1;
|
|
|
|
if (uid_errno == 0 && gid_errno == 0)
|
|
{
|
|
static char buf [1024];
|
|
sprintf (buf, "changed uid/gid to %s/%s (%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;
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
char buf [1024];
|
|
if (gid_errno)
|
|
{
|
|
sprintf (buf, "%s: couldn't set gid to %s (%ld)",
|
|
blurb(),
|
|
(g && g->gr_name ? g->gr_name : "???"),
|
|
(long) gid);
|
|
if (gid_errno == -1)
|
|
fprintf(stderr, "%s: unknown error\n", buf);
|
|
else
|
|
perror(buf);
|
|
}
|
|
|
|
if (uid_errno)
|
|
{
|
|
sprintf (buf, "%s: couldn't set uid to %s (%ld)",
|
|
blurb(),
|
|
(p && p->pw_name ? p->pw_name : "???"),
|
|
(long) uid);
|
|
if (uid_errno == -1)
|
|
fprintf(stderr, "%s: unknown error\n", buf);
|
|
else
|
|
perror(buf);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
/* If we've been run as setuid or setgid to someone else (most likely root)
|
|
turn off the extra permissions so that random user-specified programs
|
|
don't get special privileges. (On some systems it is necessary to install
|
|
this program as setuid root in order to read the passwd file to implement
|
|
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".
|
|
*/
|
|
void
|
|
hack_uid (saver_info *si)
|
|
{
|
|
|
|
/* 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)
|
|
{
|
|
si->locking_disabled_p = True;
|
|
si->nolock_reason = "running as root";
|
|
}
|
|
|
|
|
|
/* 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 (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);
|
|
}
|
|
|
|
if (set_ids_by_number (p->pw_uid, p->pw_gid, &si->uid_message) != 0)
|
|
saver_exit (si, -1, 0);
|
|
}
|
|
|
|
|
|
/* 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 %s",
|
|
(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;
|
|
}
|
|
}
|
|
}
|