1 /* setuid.c --- management of runtime priveleges.
2 * xscreensaver, Copyright (c) 1993-1998 Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
17 #ifndef NO_SETUID /* whole file */
19 #include <X11/Xlib.h> /* not used for much... */
21 /* This file doesn't need the Xt headers, so stub these types out... */
23 #define XtAppContext void*
24 #define XrmDatabase void*
25 #define XtIntervalId void*
26 #define XtPointer void*
29 #include "xscreensaver.h"
35 #include <pwd.h> /* for getpwnam() and struct passwd */
36 #include <grp.h> /* for getgrgid() and struct group */
40 uid_gid_string(uid_t uid, gid_t gid)
47 sprintf (buf, "%s/%s (%ld/%ld)",
48 (p && p->pw_name ? p->pw_name : "???"),
49 (g && g->gr_name ? g->gr_name : "???"),
50 (long) uid, (long) gid);
56 describe_uids (saver_info *si, FILE *out)
60 uid_t euid = geteuid();
61 gid_t egid = getegid();
62 char *s1 = strdup (uid_gid_string (uid, gid));
63 char *s2 = strdup (uid_gid_string (euid, egid));
65 if (si->orig_uid && *si->orig_uid)
66 fprintf (out, "%s: initial effective uid/gid was %s\n", blurb(),
68 fprintf (out, "%s: running as %s", blurb(), s1);
69 if (uid != euid || gid != egid)
70 fprintf (out, "; effectively %s", s2);
77 /* If we've been run as setuid or setgid to someone else (most likely root)
78 turn off the extra permissions so that random user-specified programs
79 don't get special privileges. (On some systems it is necessary to install
80 this program as setuid root in order to read the passwd file to implement
84 hack_uid (saver_info *si)
86 si->orig_uid = strdup (uid_gid_string (geteuid(), getegid()));
91 /* If we're being run as root (as from xdm) then switch the user id
100 /* Locking can't work when running as root, because we have no way of
101 knowing what the user id of the logged in user is (so we don't know
102 whose password to prompt for.)
104 si->locking_disabled_p = True;
105 si->nolock_reason = "running as root";
106 p = getpwnam ("nobody");
107 if (! p) p = getpwnam ("noaccess");
108 if (! p) p = getpwnam ("daemon");
112 "%s: running as root, and couldn't find a safer uid.\n",
114 saver_exit(si, 1, 0);
117 g = getgrgid (p->pw_gid);
119 /* Rumor has it that some implementations of of setuid() do nothing
120 when called with -1; therefore, if the "nobody" user has a uid of
121 -1, then that would be Really Bad. Rumor further has it that such
122 systems really ought to be using -2 for "nobody", since that works.
123 So, if we get a uid (or gid, for good measure) of -1, switch to -2
127 if (p->pw_gid == -1) p->pw_gid = -2;
128 if (p->pw_uid == -1) p->pw_uid = -2;
131 /* Change the gid to be a safe one, then change the uid to be a safe
132 one (must do it in this order, because root privs vanish when uid
133 is changed, and after that, gid can't be changed.)
135 if (setgid (p->pw_gid) != 0)
136 gid_errno = errno ? errno : -1;
137 if (setuid (p->pw_uid) != 0)
138 uid_errno = errno ? errno : -1;
140 if (uid_errno == 0 && gid_errno == 0)
142 static char buf [1024];
143 sprintf (buf, "changed uid/gid to %s/%s (%ld/%ld).",
144 p->pw_name, (g ? g->gr_name : "???"),
145 (long) p->pw_uid, (long) p->pw_gid);
146 si->uid_message = buf;
153 sprintf (buf, "%s: couldn't set gid to %s (%ld)",
155 (g ? g->gr_name : "???"),
158 fprintf(stderr, "%s: unknown error\n", buf);
165 sprintf (buf, "%s: couldn't set uid to %s (%ld)",
167 (p ? p->pw_name : "???"),
170 fprintf(stderr, "%s: unknown error\n", buf);
178 /* We'd better exit rather than continue running as root.
179 But if we switched uid but not gid, continue running,
180 since that doesn't really matter. (Right?)
182 saver_exit (si, -1, 0);
186 else /* disable locking if already being run as "someone else" */
188 struct passwd *p = getpwuid (getuid ());
190 !strcmp (p->pw_name, "root") ||
191 !strcmp (p->pw_name, "nobody") ||
192 !strcmp (p->pw_name, "noaccess") ||
193 !strcmp (p->pw_name, "operator") ||
194 !strcmp (p->pw_name, "daemon") ||
195 !strcmp (p->pw_name, "bin") ||
196 !strcmp (p->pw_name, "adm") ||
197 !strcmp (p->pw_name, "sys") ||
198 !strcmp (p->pw_name, "games"))
200 static char buf [1024];
201 sprintf (buf, "running as %s", p->pw_name);
202 si->nolock_reason = buf;
203 si->locking_disabled_p = True;
206 # endif /* !NO_LOCKING */
209 #else /* !NO_SETUID */
211 void hack_uid (saver_info *si) { }
212 void hack_uid_warn (saver_info *si) { }
213 void describe_uids (saver_info *si) { }
215 #endif /* NO_SETUID */