2 * Copyright (c) 1994-1996,1998-2006 Todd C. Miller <Todd.Miller@courtesan.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 * Sponsored in part by the Defense Advanced Research Projects
17 * Agency (DARPA) and Air Force Research Laboratory, Air Force
18 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
23 #include <sys/types.h>
24 #include <sys/param.h>
34 #endif /* STDC_HEADERS */
38 # ifdef HAVE_STRINGS_H
41 #endif /* HAVE_STRING_H */
44 #endif /* HAVE_UNISTD_H */
48 # include "emul/err.h"
49 #endif /* HAVE_ERR_H */
53 #ifdef HAVE_LOGIN_CAP_H
54 # include <login_cap.h>
60 __unused static const char rcsid[] = "$Sudo: set_perms.c,v 1.30.2.4 2007/07/06 14:16:22 millert Exp $";
64 # define ROOT_UID 65535
72 static void runas_setup __P((void));
76 * Set real and effective and saved uids and gids based on perm.
77 * We always retain a saved uid of 0 unless we are headed for an exec().
78 * We only flip the effective gid since it only changes for PERM_SUDOERS.
79 * This version of set_perms() works fine with the "stay_setuid" option.
87 if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID))
88 errx(1, "setresuid(ROOT_UID, ROOT_UID, ROOT_UID) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid");
89 (void) setresgid(-1, user_gid, -1);
93 (void) setresgid(-1, user_gid, -1);
94 if (setresuid(user_uid, user_uid, ROOT_UID))
95 err(1, "setresuid(user_uid, user_uid, ROOT_UID)");
99 /* headed for exec() */
100 (void) setgid(user_gid);
101 if (setresuid(user_uid, user_uid, user_uid))
102 err(1, "setresuid(user_uid, user_uid, user_uid)");
106 (void) setresgid(-1, runas_pw->pw_gid, -1);
107 if (setresuid(-1, runas_pw->pw_uid, -1))
108 err(1, "unable to change to runas uid");
111 case PERM_FULL_RUNAS:
112 /* headed for exec(), assume euid == ROOT_UID */
114 if (setresuid(def_stay_setuid ?
115 user_uid : runas_pw->pw_uid,
116 runas_pw->pw_uid, runas_pw->pw_uid))
117 err(1, "unable to change to runas uid");
121 /* assume euid == ROOT_UID, ruid == user */
122 if (setresgid(-1, SUDOERS_GID, -1))
123 err(1, "unable to change to sudoers gid");
126 * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
127 * is group readable we use a non-zero
128 * uid in order to avoid NFS lossage.
129 * Using uid 1 is a bit bogus but should
132 if (SUDOERS_UID == ROOT_UID) {
133 if ((SUDOERS_MODE & 040) && setresuid(ROOT_UID, 1, ROOT_UID))
134 err(1, "setresuid(ROOT_UID, 1, ROOT_UID)");
136 if (setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID))
137 err(1, "setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)");
141 if (setresuid(ROOT_UID, timestamp_uid, ROOT_UID))
142 err(1, "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)");
148 # ifdef HAVE_SETREUID
151 * Set real and effective uids and gids based on perm.
152 * We always retain a real or effective uid of ROOT_UID unless
153 * we are headed for an exec().
154 * This version of set_perms() works fine with the "stay_setuid" option.
162 if (setreuid(-1, ROOT_UID))
163 errx(1, "setreuid(-1, ROOT_UID) failed, your operating system may have a broken setreuid() function\nTry running configure with --disable-setreuid");
164 if (setuid(ROOT_UID))
165 err(1, "setuid(ROOT_UID)");
166 (void) setregid(-1, user_gid);
170 (void) setregid(-1, user_gid);
171 if (setreuid(ROOT_UID, user_uid))
172 err(1, "setreuid(ROOT_UID, user_uid)");
176 /* headed for exec() */
177 (void) setgid(user_gid);
178 if (setreuid(user_uid, user_uid))
179 err(1, "setreuid(user_uid, user_uid)");
183 (void) setregid(-1, runas_pw->pw_gid);
184 if (setreuid(-1, runas_pw->pw_uid))
185 err(1, "unable to change to runas uid");
188 case PERM_FULL_RUNAS:
189 /* headed for exec(), assume euid == ROOT_UID */
191 if (setreuid(def_stay_setuid ? user_uid :
192 runas_pw->pw_uid, runas_pw->pw_uid))
193 err(1, "unable to change to runas uid");
197 /* assume euid == ROOT_UID, ruid == user */
198 if (setregid(-1, SUDOERS_GID))
199 err(1, "unable to change to sudoers gid");
202 * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
203 * is group readable we use a non-zero
204 * uid in order to avoid NFS lossage.
205 * Using uid 1 is a bit bogus but should
208 if (SUDOERS_UID == ROOT_UID) {
209 if ((SUDOERS_MODE & 040) && setreuid(ROOT_UID, 1))
210 err(1, "setreuid(ROOT_UID, 1)");
212 if (setreuid(ROOT_UID, SUDOERS_UID))
213 err(1, "setreuid(ROOT_UID, SUDOERS_UID)");
217 if (setreuid(ROOT_UID, timestamp_uid))
218 err(1, "setreuid(ROOT_UID, timestamp_uid)");
223 # else /* !HAVE_SETRESUID && !HAVE_SETREUID */
227 * Set real and effective uids and gids based on perm.
228 * NOTE: does not support the "stay_setuid" option.
235 * Since we only have setuid() and seteuid() and semantics
236 * for these calls differ on various systems, we set
237 * real and effective uids to ROOT_UID initially to be safe.
239 if (seteuid(ROOT_UID))
240 err(1, "seteuid(ROOT_UID)");
241 if (setuid(ROOT_UID))
242 err(1, "setuid(ROOT_UID)");
247 (void) setegid(user_gid);
251 (void) setegid(user_gid);
252 if (seteuid(user_uid))
253 err(1, "seteuid(user_uid)");
257 /* headed for exec() */
258 (void) setgid(user_gid);
259 if (setuid(user_uid))
260 err(1, "setuid(user_uid)");
264 (void) setegid(runas_pw->pw_gid);
265 if (seteuid(runas_pw->pw_uid))
266 err(1, "unable to change to runas uid");
269 case PERM_FULL_RUNAS:
270 /* headed for exec() */
272 if (setuid(runas_pw->pw_uid))
273 err(1, "unable to change to runas uid");
277 if (setegid(SUDOERS_GID))
278 err(1, "unable to change to sudoers gid");
281 * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
282 * is group readable we use a non-zero
283 * uid in order to avoid NFS lossage.
284 * Using uid 1 is a bit bogus but should
287 if (SUDOERS_UID == ROOT_UID) {
288 if ((SUDOERS_MODE & 040) && seteuid(1))
289 err(1, "seteuid(1)");
291 if (seteuid(SUDOERS_UID))
292 err(1, "seteuid(SUDOERS_UID)");
296 if (seteuid(timestamp_uid))
297 err(1, "seteuid(timestamp_uid)");
302 # else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */
305 * Set uids and gids based on perm via setuid() and setgid().
306 * NOTE: does not support the "stay_setuid" or timestampowner options.
307 * Also, SUDOERS_UID and SUDOERS_GID are not used.
316 if (setuid(ROOT_UID))
317 err(1, "setuid(ROOT_UID)");
321 (void) setgid(user_gid);
322 if (setuid(user_uid))
323 err(1, "setuid(user_uid)");
326 case PERM_FULL_RUNAS:
328 if (setuid(runas_pw->pw_uid))
329 err(1, "unable to change to runas uid");
336 /* Unsupported since we can't set euid. */
340 # endif /* HAVE_SETEUID */
341 # endif /* HAVE_SETREUID */
342 #endif /* HAVE_SETRESUID */
347 #ifdef HAVE_LOGIN_CAP_H
349 extern login_cap_t *lc;
352 if (runas_pw->pw_name != NULL) {
354 pam_prep_user(runas_pw);
355 #endif /* HAVE_PAM */
357 #ifdef HAVE_LOGIN_CAP_H
358 if (def_use_loginclass) {
360 * We don't have setusercontext() set the user since we
361 * may only want to set the effective uid. Depending on
362 * sudoers and/or command line arguments we may not want
363 * setusercontext() to call initgroups().
365 flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
366 if (!def_preserve_groups)
367 SET(flags, LOGIN_SETGROUP);
368 else if (setgid(runas_pw->pw_gid))
369 warn("cannot set gid to runas gid");
370 if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) {
371 if (runas_pw->pw_uid != ROOT_UID)
372 err(1, "unable to set user context");
374 warn("unable to set user context");
377 #endif /* HAVE_LOGIN_CAP_H */
379 if (setgid(runas_pw->pw_gid))
380 warn("cannot set gid to runas gid");
381 #ifdef HAVE_INITGROUPS
383 * Initialize group vector unless asked not to.
385 if (!def_preserve_groups &&
386 initgroups(*user_runas, runas_pw->pw_gid) < 0)
387 warn("cannot set group vector");
388 #endif /* HAVE_INITGROUPS */