a887a512455182a0cb0591910742c980e74c498d
[debian/sudo] / plugins / sudoers / set_perms.c
1 /*
2  * Copyright (c) 1994-1996,1998-2013 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
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.
7  *
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.
15  *
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.
19  */
20
21 #include <config.h>
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <stdio.h>
26 #ifdef STDC_HEADERS
27 # include <stdlib.h>
28 # include <stddef.h>
29 #else
30 # ifdef HAVE_STDLIB_H
31 #  include <stdlib.h>
32 # endif
33 #endif /* STDC_HEADERS */
34 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #endif /* HAVE_STRING_H */
37 #ifdef HAVE_STRINGS_H
38 # include <strings.h>
39 #endif /* HAVE_STRINGS_H */
40 #ifdef HAVE_UNISTD_H
41 # include <unistd.h>
42 #endif /* HAVE_UNISTD_H */
43 #ifdef _AIX
44 # include <sys/id.h>
45 #endif
46 #include <pwd.h>
47 #include <errno.h>
48 #include <grp.h>
49
50 #include "sudoers.h"
51
52 /*
53  * Prototypes
54  */
55 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
56 static struct group_list *runas_setgroups(void);
57 #endif
58
59 /*
60  * We keep track of the current permisstions and use a stack to restore
61  * the old permissions.  A depth of 16 is overkill.
62  */
63 struct perm_state {
64     uid_t ruid;
65     uid_t euid;
66 #if defined(HAVE_SETRESUID) || defined(ID_SAVED)
67     uid_t suid;
68 #endif
69     gid_t rgid;
70     gid_t egid;
71 #if defined(HAVE_SETRESUID) || defined(ID_SAVED)
72     gid_t sgid;
73 #endif
74     struct group_list *grlist;
75 };
76
77 #define PERM_STACK_MAX  16
78 static struct perm_state perm_stack[PERM_STACK_MAX];
79 static int perm_stack_depth = 0;
80
81 #undef ID
82 #define ID(x) (state->x == ostate->x ? -1 : state->x)
83 #undef OID
84 #define OID(x) (ostate->x == state->x ? -1 : ostate->x)
85
86 void
87 rewind_perms(void)
88 {
89     debug_decl(rewind_perms, SUDO_DEBUG_PERMS)
90
91     while (perm_stack_depth > 1)
92         restore_perms();
93     sudo_grlist_delref(perm_stack[0].grlist);
94
95     debug_return;
96 }
97
98 #if defined(HAVE_SETRESUID)
99
100 #define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid || state->suid != ostate->suid)
101 #define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid || state->sgid != ostate->sgid)
102
103 /*
104  * Set real and effective and saved uids and gids based on perm.
105  * We always retain a saved uid of 0 unless we are headed for an exec().
106  * We only flip the effective gid since it only changes for PERM_SUDOERS.
107  * This version of set_perms() works fine with the "stay_setuid" option.
108  */
109 int
110 set_perms(int perm)
111 {
112     struct perm_state *state, *ostate = NULL;
113     char errbuf[1024];
114     const char *errstr = errbuf;
115     int noexit;
116     debug_decl(set_perms, SUDO_DEBUG_PERMS)
117
118     noexit = ISSET(perm, PERM_NOEXIT);
119     CLR(perm, PERM_MASK);
120
121     if (perm_stack_depth == PERM_STACK_MAX) {
122         errstr = N_("perm stack overflow");
123         errno = EINVAL;
124         goto bad;
125     }
126
127     state = &perm_stack[perm_stack_depth];
128     if (perm != PERM_INITIAL) {
129         if (perm_stack_depth == 0) {
130             errstr = N_("perm stack underflow");
131             errno = EINVAL;
132             goto bad;
133         }
134         ostate = &perm_stack[perm_stack_depth - 1];
135     }
136
137     switch (perm) {
138     case PERM_INITIAL:
139         /* Stash initial state */
140 #ifdef HAVE_GETRESUID
141         if (getresuid(&state->ruid, &state->euid, &state->suid)) {
142             errstr = "PERM_INITIAL: getresuid";
143             goto bad;
144
145         }
146         if (getresgid(&state->rgid, &state->egid, &state->sgid)) {
147             errstr = "PERM_INITIAL: getresgid";
148             goto bad;
149         }
150 #else
151         state->ruid = getuid();
152         state->euid = geteuid();
153         state->suid = state->euid; /* in case we are setuid */
154
155         state->rgid = getgid();
156         state->egid = getegid();
157         state->sgid = state->egid; /* in case we are setgid */
158 #endif
159         state->grlist = user_group_list;
160         sudo_grlist_addref(state->grlist);
161         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
162             "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d",
163             __func__, (int)state->ruid, (int)state->euid, (int)state->suid,
164             (int)state->rgid, (int)state->egid, (int)state->sgid);
165         break;
166
167     case PERM_ROOT:
168         state->ruid = ROOT_UID;
169         state->euid = ROOT_UID;
170         state->suid = ROOT_UID;
171         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
172             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
173             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
174             (int)state->ruid, (int)state->euid, (int)state->suid);
175         if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
176             snprintf(errbuf, sizeof(errbuf),
177                 "PERM_ROOT: setresuid(%d, %d, %d)",
178                 ID(ruid), ID(euid), ID(suid));
179             goto bad;
180         }
181         state->rgid = ostate->rgid;
182         state->egid = ROOT_GID;
183         state->sgid = ostate->sgid;
184         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
185             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
186             (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
187             (int)state->rgid, (int)state->egid, (int)state->sgid);
188         if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
189             errstr = N_("unable to change to root gid");
190             goto bad;
191         }
192         state->grlist = ostate->grlist;
193         sudo_grlist_addref(state->grlist);
194         break;
195
196     case PERM_USER:
197         state->rgid = ostate->rgid;
198         state->egid = user_gid;
199         state->sgid = ostate->sgid;
200         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
201             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
202             (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
203             (int)state->rgid, (int)state->egid, (int)state->sgid);
204         if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
205             snprintf(errbuf, sizeof(errbuf), "PERM_USER: setresgid(%d, %d, %d)",
206                 ID(rgid), ID(egid), ID(sgid));
207             goto bad;
208         }
209         state->grlist = user_group_list;
210         sudo_grlist_addref(state->grlist);
211         if (state->grlist != ostate->grlist) {
212             if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
213                 errstr = "PERM_USER: setgroups";
214                 goto bad;
215             }
216         }
217         state->ruid = user_uid;
218         state->euid = user_uid;
219         state->suid = ROOT_UID;
220         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
221             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
222             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
223             (int)state->ruid, (int)state->euid, (int)state->suid);
224         if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
225             snprintf(errbuf, sizeof(errbuf), "PERM_USER: setresuid(%d, %d, %d)",
226                 ID(ruid), ID(euid), ID(suid));
227             goto bad;
228         }
229         break;
230
231     case PERM_FULL_USER:
232         /* headed for exec() */
233         state->rgid = user_gid;
234         state->egid = user_gid;
235         state->sgid = user_gid;
236         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
237             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
238             (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
239             (int)state->rgid, (int)state->egid, (int)state->sgid);
240         if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
241             snprintf(errbuf, sizeof(errbuf),
242                 "PERM_FULL_USER: setresgid(%d, %d, %d)",
243                 ID(rgid), ID(egid), ID(sgid));
244             goto bad;
245         }
246         state->grlist = user_group_list;
247         sudo_grlist_addref(state->grlist);
248         if (state->grlist != ostate->grlist) {
249             if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
250                 errstr = "PERM_FULL_USER: setgroups";
251                 goto bad;
252             }
253         }
254         state->ruid = user_uid;
255         state->euid = user_uid;
256         state->suid = user_uid;
257         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
258             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
259             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
260             (int)state->ruid, (int)state->euid, (int)state->suid);
261         if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
262             snprintf(errbuf, sizeof(errbuf),
263                 "PERM_FULL_USER: setresuid(%d, %d, %d)",
264                 ID(ruid), ID(euid), ID(suid));
265             goto bad;
266         }
267         break;
268
269     case PERM_RUNAS:
270         state->rgid = ostate->rgid;
271         state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
272         state->sgid = ostate->sgid;
273         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
274             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
275             (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
276             (int)state->rgid, (int)state->egid, (int)state->sgid);
277         if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
278             errstr = N_("unable to change to runas gid");
279             goto bad;
280         }
281         state->grlist = runas_setgroups();
282         state->ruid = ostate->ruid;
283         state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
284         state->suid = ostate->suid;
285         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
286             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
287             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
288             (int)state->ruid, (int)state->euid, (int)state->suid);
289         if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
290             errstr = N_("unable to change to runas uid");
291             goto bad;
292         }
293         break;
294
295     case PERM_SUDOERS:
296         state->grlist = ostate->grlist;
297         sudo_grlist_addref(state->grlist);
298
299         /* assumes euid == ROOT_UID, ruid == user */
300         state->rgid = ostate->rgid;
301         state->egid = sudoers_gid;
302         state->sgid = ostate->sgid;
303         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
304             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
305             (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
306             (int)state->rgid, (int)state->egid, (int)state->sgid);
307         if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
308             errstr = N_("unable to change to sudoers gid");
309             goto bad;
310         }
311
312         state->ruid = ROOT_UID;
313         /*
314          * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
315          * we use a non-zero uid in order to avoid NFS lossage.
316          * Using uid 1 is a bit bogus but should work on all OS's.
317          */
318         if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
319             state->euid = 1;
320         else
321             state->euid = sudoers_uid;
322         state->suid = ROOT_UID;
323         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
324             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
325             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
326             (int)state->ruid, (int)state->euid, (int)state->suid);
327         if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
328             snprintf(errbuf, sizeof(errbuf),
329                 "PERM_SUDOERS: setresuid(%d, %d, %d)",
330                 ID(ruid), ID(euid), ID(suid));
331             goto bad;
332         }
333         break;
334
335     case PERM_TIMESTAMP:
336         state->grlist = ostate->grlist;
337         sudo_grlist_addref(state->grlist);
338         state->rgid = ostate->rgid;
339         state->egid = ostate->egid;
340         state->sgid = ostate->sgid;
341         state->ruid = ROOT_UID;
342         state->euid = timestamp_uid;
343         state->suid = ROOT_UID;
344         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
345             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
346             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
347             (int)state->ruid, (int)state->euid, (int)state->suid);
348         if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
349             snprintf(errbuf, sizeof(errbuf),
350                 "PERM_TIMESTAMP: setresuid(%d, %d, %d)",
351                 ID(ruid), ID(euid), ID(suid));
352             goto bad;
353         }
354         break;
355     }
356
357     perm_stack_depth++;
358     debug_return_bool(1);
359 bad:
360     warningx("%s: %s", _(errstr),
361         errno == EAGAIN ? _("too many processes") : strerror(errno));
362     if (noexit)
363         debug_return_bool(0);
364     exit(1);
365 }
366
367 void
368 restore_perms(void)
369 {
370     struct perm_state *state, *ostate;
371     debug_decl(restore_perms, SUDO_DEBUG_PERMS)
372
373     if (perm_stack_depth < 2)
374         debug_return;
375
376     state = &perm_stack[perm_stack_depth - 1];
377     ostate = &perm_stack[perm_stack_depth - 2];
378     perm_stack_depth--;
379
380     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d, %d] -> [%d, %d, %d]",
381         __func__, (int)state->ruid, (int)state->euid, (int)state->suid,
382         (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid);
383     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d, %d] -> [%d, %d, %d]",
384         __func__, (int)state->rgid, (int)state->egid, (int)state->sgid,
385         (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid);
386
387     /* XXX - more cases here where euid != ruid */
388     if (OID(euid) == ROOT_UID) {
389         if (setresuid(-1, ROOT_UID, -1)) {
390             warning("setresuid() [%d, %d, %d] -> [%d, %d, %d]",
391                 (int)state->ruid, (int)state->euid, (int)state->suid,
392                 -1, ROOT_UID, -1);
393             goto bad;
394         }
395     }
396     if (setresuid(OID(ruid), OID(euid), OID(suid))) {
397         warning("setresuid() [%d, %d, %d] -> [%d, %d, %d]",
398             (int)state->ruid, (int)state->euid, (int)state->suid,
399             (int)OID(ruid), (int)OID(euid), (int)OID(suid));
400         goto bad;
401     }
402     if (setresgid(OID(rgid), OID(egid), OID(sgid))) {
403         warning("setresgid() [%d, %d, %d] -> [%d, %d, %d]",
404             (int)state->rgid, (int)state->egid, (int)state->sgid,
405             (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
406         goto bad;
407     }
408     if (state->grlist != ostate->grlist) {
409         if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
410             warning("setgroups()");
411             goto bad;
412         }
413     }
414     sudo_grlist_delref(state->grlist);
415     debug_return;
416
417 bad:
418     exit(1);
419 }
420
421 #elif defined(_AIX) && defined(ID_SAVED)
422
423 #define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid || state->suid != ostate->suid)
424 #define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid || state->sgid != ostate->sgid)
425
426 /*
427  * Set real and effective and saved uids and gids based on perm.
428  * We always retain a saved uid of 0 unless we are headed for an exec().
429  * We only flip the effective gid since it only changes for PERM_SUDOERS.
430  * This version of set_perms() works fine with the "stay_setuid" option.
431  */
432 int
433 set_perms(int perm)
434 {
435     struct perm_state *state, *ostate = NULL;
436     char errbuf[1024];
437     const char *errstr = errbuf;
438     int noexit;
439     debug_decl(set_perms, SUDO_DEBUG_PERMS)
440
441     noexit = ISSET(perm, PERM_NOEXIT);
442     CLR(perm, PERM_MASK);
443
444     if (perm_stack_depth == PERM_STACK_MAX) {
445         errstr = N_("perm stack overflow");
446         errno = EINVAL;
447         goto bad;
448     }
449
450     state = &perm_stack[perm_stack_depth];
451     if (perm != PERM_INITIAL) {
452         if (perm_stack_depth == 0) {
453             errstr = N_("perm stack underflow");
454             errno = EINVAL;
455             goto bad;
456         }
457         ostate = &perm_stack[perm_stack_depth - 1];
458     }
459
460     switch (perm) {
461     case PERM_INITIAL:
462         /* Stash initial state */
463         state->ruid = getuidx(ID_REAL);
464         state->euid = getuidx(ID_EFFECTIVE);
465         state->suid = getuidx(ID_SAVED);
466         state->rgid = getgidx(ID_REAL);
467         state->egid = getgidx(ID_EFFECTIVE);
468         state->sgid = getgidx(ID_SAVED);
469         state->grlist = user_group_list;
470         sudo_grlist_addref(state->grlist);
471         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
472             "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d",
473             __func__, (unsigned int)state->ruid, (unsigned int)state->euid,
474             (unsigned int)state->suid, (unsigned int)state->rgid,
475             (unsigned int)state->egid, (unsigned int)state->sgid);
476         break;
477
478     case PERM_ROOT:
479         state->ruid = ROOT_UID;
480         state->euid = ROOT_UID;
481         state->suid = ROOT_UID;
482         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
483             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
484             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
485             (int)state->ruid, (int)state->euid, (int)state->suid);
486         if (UID_CHANGED && setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
487             snprintf(errbuf, sizeof(errbuf),
488                 "PERM_ROOT: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
489                 ROOT_UID);
490             goto bad;
491         }
492         state->rgid = ostate->rgid;
493         state->egid = ROOT_GID;
494         state->sgid = ostate->sgid;
495         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
496             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
497             (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
498             (int)state->rgid, (int)state->egid, (int)state->sgid);
499         if (GID_CHANGED && setgidx(ID_EFFECTIVE, ROOT_GID)) {
500             errstr = N_("unable to change to root gid");
501             goto bad;
502         }
503         state->grlist = ostate->grlist;
504         sudo_grlist_addref(state->grlist);
505         break;
506
507     case PERM_USER:
508         state->rgid = ostate->rgid;
509         state->egid = user_gid;
510         state->sgid = ostate->sgid;
511         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
512             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
513             (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
514             (int)state->rgid, (int)state->egid, (int)state->sgid);
515         if (GID_CHANGED && setgidx(ID_EFFECTIVE, user_gid)) {
516             snprintf(errbuf, sizeof(errbuf),
517                 "PERM_USER: setgidx(ID_EFFECTIVE, %d)", user_gid);
518             goto bad;
519         }
520         state->grlist = user_group_list;
521         sudo_grlist_addref(state->grlist);
522         if (state->grlist != ostate->grlist) {
523             if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
524                 errstr = "PERM_USER: setgroups";
525                 goto bad;
526             }
527         }
528         state->ruid = user_uid;
529         state->euid = user_uid;
530         state->suid = ROOT_UID;
531         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
532             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
533             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
534             (int)state->ruid, (int)state->euid, (int)state->suid);
535         if (ostate->euid != ROOT_UID || ostate->suid != ROOT_UID) {
536             if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
537                 snprintf(errbuf, sizeof(errbuf),
538                     "PERM_USER: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
539                     ROOT_UID);
540                 goto bad;
541             }
542         }
543         if (setuidx(ID_EFFECTIVE|ID_REAL, user_uid)) {
544             snprintf(errbuf, sizeof(errbuf),
545                 "PERM_USER: setuidx(ID_EFFECTIVE|ID_REAL, %d)", user_uid);
546             goto bad;
547         }
548         break;
549
550     case PERM_FULL_USER:
551         /* headed for exec() */
552         state->rgid = user_gid;
553         state->egid = user_gid;
554         state->sgid = user_gid;
555         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
556             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
557             (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
558             (int)state->rgid, (int)state->egid, (int)state->sgid);
559         if (GID_CHANGED && setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, user_gid)) {
560             snprintf(errbuf, sizeof(errbuf),
561                 "PERM_FULL_USER: setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
562                 user_gid);
563             goto bad;
564         }
565         state->grlist = user_group_list;
566         sudo_grlist_addref(state->grlist);
567         if (state->grlist != ostate->grlist) {
568             if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
569                 errstr = "PERM_FULL_USER: setgroups";
570                 goto bad;
571             }
572         }
573         state->ruid = user_uid;
574         state->euid = user_uid;
575         state->suid = user_uid;
576         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
577             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
578             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
579             (int)state->ruid, (int)state->euid, (int)state->suid);
580         if (UID_CHANGED && setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, user_uid)) {
581             snprintf(errbuf, sizeof(errbuf),
582                 "PERM_FULL_USER: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
583                 user_uid);
584             goto bad;
585         }
586         break;
587
588     case PERM_RUNAS:
589         state->rgid = ostate->rgid;
590         state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
591         state->sgid = ostate->sgid;
592         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
593             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
594             (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
595             (int)state->rgid, (int)state->egid, (int)state->sgid);
596         if (GID_CHANGED && setgidx(ID_EFFECTIVE, state->egid)) {
597             errstr = N_("unable to change to runas gid");
598             goto bad;
599         }
600         state->grlist = runas_setgroups();
601         state->ruid = ostate->ruid;
602         state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
603         state->suid = ostate->suid;
604         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
605             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
606             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
607             (int)state->ruid, (int)state->euid, (int)state->suid);
608         if (UID_CHANGED && setuidx(ID_EFFECTIVE, state->euid)) {
609             errstr = N_("unable to change to runas uid");
610             goto bad;
611         }
612         break;
613
614     case PERM_SUDOERS:
615         state->grlist = ostate->grlist;
616         sudo_grlist_addref(state->grlist);
617
618         /* assume euid == ROOT_UID, ruid == user */
619         state->rgid = ostate->rgid;
620         state->egid = sudoers_gid;
621         state->sgid = ostate->sgid;
622         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
623             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
624             (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
625             (int)state->rgid, (int)state->egid, (int)state->sgid);
626         if (GID_CHANGED && setgidx(ID_EFFECTIVE, sudoers_gid)) {
627             errstr = N_("unable to change to sudoers gid");
628             goto bad;
629         }
630
631         state->ruid = ROOT_UID;
632         /*
633          * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
634          * we use a non-zero uid in order to avoid NFS lossage.
635          * Using uid 1 is a bit bogus but should work on all OS's.
636          */
637         if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
638             state->euid = 1;
639         else
640             state->euid = sudoers_uid;
641         state->suid = ROOT_UID;
642         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
643             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
644             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
645             (int)state->ruid, (int)state->euid, (int)state->suid);
646         if (UID_CHANGED) {
647             if (ostate->ruid != ROOT_UID || ostate->suid != ROOT_UID) {
648                 if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
649                     snprintf(errbuf, sizeof(errbuf),
650                         "PERM_SUDOERS: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
651                         ROOT_UID);
652                     goto bad;
653                 }
654             }
655             if (setuidx(ID_EFFECTIVE, state->euid)) {
656                 snprintf(errbuf, sizeof(errbuf),
657                     "PERM_SUDOERS: setuidx(ID_EFFECTIVE, %d)", sudoers_uid);
658                 goto bad;
659             }
660         }
661         break;
662
663     case PERM_TIMESTAMP:
664         state->grlist = ostate->grlist;
665         sudo_grlist_addref(state->grlist);
666         state->rgid = ostate->rgid;
667         state->egid = ostate->egid;
668         state->sgid = ostate->sgid;
669         state->ruid = ROOT_UID;
670         state->euid = timestamp_uid;
671         state->suid = ROOT_UID;
672         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
673             "[%d, %d, %d] -> [%d, %d, %d]", __func__,
674             (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
675             (int)state->ruid, (int)state->euid, (int)state->suid);
676         if (UID_CHANGED) {
677             if (ostate->ruid != ROOT_UID || ostate->suid != ROOT_UID) {
678                 if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
679                     snprintf(errbuf, sizeof(errbuf),
680                         "PERM_TIMESTAMP: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
681                         ROOT_UID);
682                     goto bad;
683                 }
684             }
685             if (setuidx(ID_EFFECTIVE, timestamp_uid)) {
686                 snprintf(errbuf, sizeof(errbuf),
687                     "PERM_TIMESTAMP: setuidx(ID_EFFECTIVE, %d)", timestamp_uid);
688                 goto bad;
689             }
690         }
691         break;
692     }
693
694     perm_stack_depth++;
695     debug_return_bool(1);
696 bad:
697     warningx("%s: %s", _(errstr),
698         errno == EAGAIN ? _("too many processes") : strerror(errno));
699     if (noexit)
700         debug_return_bool(0);
701     exit(1);
702 }
703
704 void
705 restore_perms(void)
706 {
707     struct perm_state *state, *ostate;
708     debug_decl(restore_perms, SUDO_DEBUG_PERMS)
709
710     if (perm_stack_depth < 2)
711         debug_return;
712
713     state = &perm_stack[perm_stack_depth - 1];
714     ostate = &perm_stack[perm_stack_depth - 2];
715     perm_stack_depth--;
716
717     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d, %d] -> [%d, %d, %d]",
718         __func__, (int)state->ruid, (int)state->euid, (int)state->suid,
719         (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid);
720     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d, %d] -> [%d, %d, %d]",
721         __func__, (int)state->rgid, (int)state->egid, (int)state->sgid,
722         (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid);
723
724     if (OID(ruid) != -1 || OID(euid) != -1 || OID(suid) != -1) {
725         if (OID(euid) == ROOT_UID) {
726             sudo_debug_printf(SUDO_DEBUG_INFO, "%s: setuidx(ID_EFFECTIVE, %d)",
727                 __func__, ROOT_UID);
728             if (setuidx(ID_EFFECTIVE, ROOT_UID)) {
729                 warning("setuidx(ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
730                     (int)state->ruid, (int)state->euid, (int)state->suid,
731                     -1, ROOT_UID, -1);
732                 goto bad;
733             }
734         }
735         if (OID(ruid) == OID(euid) && OID(euid) == OID(suid)) {
736             sudo_debug_printf(SUDO_DEBUG_INFO,
737                 "%s: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
738                 __func__, OID(ruid));
739             if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, OID(ruid))) {
740                 warning("setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED) [%d, %d, %d] -> [%d, %d, %d]",
741                     (int)state->ruid, (int)state->euid, (int)state->suid,
742                     (int)OID(ruid), (int)OID(euid), (int)OID(suid));
743                 goto bad;
744             }
745         } else if (OID(ruid) == -1 && OID(suid) == -1) {
746             /* May have already changed euid to ROOT_UID above. */
747             if (OID(euid) != ROOT_UID) {
748                 sudo_debug_printf(SUDO_DEBUG_INFO,
749                     "%s: setuidx(ID_EFFECTIVE, %d)", __func__, OID(euid));
750                 if (setuidx(ID_EFFECTIVE, OID(euid))) {
751                     warning("setuidx(ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
752                         (int)state->ruid, (int)state->euid, (int)state->suid,
753                         (int)OID(ruid), (int)OID(euid), (int)OID(suid));
754                     goto bad;
755                 }
756             }
757         } else if (OID(suid) == -1) {
758             /* Cannot set the real uid alone. */
759             sudo_debug_printf(SUDO_DEBUG_INFO,
760                 "%s: setuidx(ID_REAL|ID_EFFECTIVE, %d)", __func__, OID(ruid));
761             if (setuidx(ID_REAL|ID_EFFECTIVE, OID(ruid))) {
762                 warning("setuidx(ID_REAL|ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
763                     (int)state->ruid, (int)state->euid, (int)state->suid,
764                     (int)OID(ruid), (int)OID(euid), (int)OID(suid));
765                 goto bad;
766             }
767             /* Restore the effective euid if it doesn't match the ruid. */
768             if (OID(euid) != OID(ruid)) {
769                 sudo_debug_printf(SUDO_DEBUG_INFO,
770                     "%s: setuidx(ID_EFFECTIVE, %d)", __func__, ostate->euid);
771                 if (setuidx(ID_EFFECTIVE, ostate->euid)) {
772                     warning("setuidx(ID_EFFECTIVE, %d)", ostate->euid);
773                     goto bad;
774                 }
775             }
776         }
777     }
778     if (OID(rgid) != -1 || OID(egid) != -1 || OID(sgid) != -1) {
779         if (OID(rgid) == OID(egid) && OID(egid) == OID(sgid)) {
780             sudo_debug_printf(SUDO_DEBUG_INFO,
781                 "%s: setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
782                 __func__, OID(rgid));
783             if (setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, OID(rgid))) {
784                 warning("setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED) [%d, %d, %d] -> [%d, %d, %d]",
785                     (int)state->rgid, (int)state->egid, (int)state->sgid,
786                     (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
787                 goto bad;
788             }
789         } else if (OID(rgid) == -1 && OID(sgid) == -1) {
790             sudo_debug_printf(SUDO_DEBUG_INFO, "%s: setgidx(ID_EFFECTIVE, %d)",
791                 __func__, OID(egid));
792             if (setgidx(ID_EFFECTIVE, OID(egid))) {
793                 warning("setgidx(ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
794                     (int)state->rgid, (int)state->egid, (int)state->sgid,
795                     (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
796                 goto bad;
797             }
798         } else if (OID(sgid) == -1) {
799             sudo_debug_printf(SUDO_DEBUG_INFO,
800                 "%s: setgidx(ID_EFFECTIVE|ID_REAL, %d)", __func__, OID(rgid));
801             if (setgidx(ID_REAL|ID_EFFECTIVE, OID(rgid))) {
802                 warning("setgidx(ID_REAL|ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
803                     (int)state->rgid, (int)state->egid, (int)state->sgid,
804                     (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
805                 goto bad;
806             }
807         }
808     }
809     if (state->grlist != ostate->grlist) {
810         if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
811             warning("setgroups()");
812             goto bad;
813         }
814     }
815     sudo_grlist_delref(state->grlist);
816     debug_return;
817
818 bad:
819     exit(1);
820 }
821
822 #elif defined(HAVE_SETREUID)
823
824 #define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid)
825 #define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid)
826
827 /*
828  * Set real and effective and saved uids and gids based on perm.
829  * We always retain a saved uid of 0 unless we are headed for an exec().
830  * We only flip the effective gid since it only changes for PERM_SUDOERS.
831  * This version of set_perms() works fine with the "stay_setuid" option.
832  */
833 int
834 set_perms(int perm)
835 {
836     struct perm_state *state, *ostate = NULL;
837     char errbuf[1024];
838     const char *errstr = errbuf;
839     int noexit;
840     debug_decl(set_perms, SUDO_DEBUG_PERMS)
841
842     noexit = ISSET(perm, PERM_NOEXIT);
843     CLR(perm, PERM_MASK);
844
845     if (perm_stack_depth == PERM_STACK_MAX) {
846         errstr = N_("perm stack overflow");
847         errno = EINVAL;
848         goto bad;
849     }
850
851     state = &perm_stack[perm_stack_depth];
852     if (perm != PERM_INITIAL) {
853         if (perm_stack_depth == 0) {
854             errstr = N_("perm stack underflow");
855             errno = EINVAL;
856             goto bad;
857         }
858         ostate = &perm_stack[perm_stack_depth - 1];
859     }
860
861     switch (perm) {
862     case PERM_INITIAL:
863         /* Stash initial state */
864         state->ruid = getuid();
865         state->euid = geteuid();
866         state->rgid = getgid();
867         state->egid = getegid();
868         state->grlist = user_group_list;
869         sudo_grlist_addref(state->grlist);
870         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
871             "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__,
872             (int)state->ruid, (int)state->euid,
873             (int)state->rgid, (int)state->egid);
874         break;
875
876     case PERM_ROOT:
877         state->ruid = ROOT_UID;
878         state->euid = ROOT_UID;
879         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
880             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
881             (int)ostate->euid, (int)state->ruid, (int)state->euid);
882         /*
883          * setreuid(0, 0) may fail on some systems if euid is not already 0.
884          */
885         if (ostate->euid != ROOT_UID) {
886             if (setreuid(-1, ROOT_UID)) {
887                 snprintf(errbuf, sizeof(errbuf),
888                     "PERM_ROOT: setreuid(-1, %d)", PERM_ROOT);
889                 goto bad;
890             }
891         }
892         if (ostate->ruid != ROOT_UID) {
893             if (setreuid(ROOT_UID, -1)) {
894                 snprintf(errbuf, sizeof(errbuf),
895                     "PERM_ROOT: setreuid(%d, -1)", ROOT_UID);
896                 goto bad;
897             }
898         }
899         state->rgid = ostate->rgid;
900         state->egid = ROOT_GID;
901         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
902             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
903             (int)ostate->egid, (int)state->rgid, (int)state->egid);
904         if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
905             snprintf(errbuf, sizeof(errbuf),
906                 "PERM_ROOT: setregid(%d, %d)", ID(rgid), ID(egid));
907             goto bad;
908         }
909         state->grlist = ostate->grlist;
910         sudo_grlist_addref(state->grlist);
911         break;
912
913     case PERM_USER:
914         state->rgid = ostate->rgid;
915         state->egid = user_gid;
916         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
917             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
918             (int)ostate->egid, (int)state->rgid, (int)state->egid);
919         if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
920             snprintf(errbuf, sizeof(errbuf),
921                 "PERM_USER: setregid(%d, %d)", ID(rgid), ID(egid));
922             goto bad;
923         }
924         state->grlist = user_group_list;
925         sudo_grlist_addref(state->grlist);
926         if (state->grlist != ostate->grlist) {
927             if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
928                 errstr = "PERM_USER: setgroups";
929                 goto bad;
930             }
931         }
932         state->ruid = ROOT_UID;
933         state->euid = user_uid;
934         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
935             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
936             (int)ostate->euid, (int)state->ruid, (int)state->euid);
937         if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
938             snprintf(errbuf, sizeof(errbuf),
939                 "PERM_USER: setreuid(%d, %d)", ID(ruid), ID(euid));
940             goto bad;
941         }
942         break;
943
944     case PERM_FULL_USER:
945         /* headed for exec() */
946         state->rgid = user_gid;
947         state->egid = user_gid;
948         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
949             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
950             (int)ostate->egid, (int)state->rgid, (int)state->egid);
951         if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
952             snprintf(errbuf, sizeof(errbuf),
953                 "PERM_FULL_USER: setregid(%d, %d)", ID(rgid), ID(egid));
954             goto bad;
955         }
956         state->grlist = user_group_list;
957         sudo_grlist_addref(state->grlist);
958         if (state->grlist != ostate->grlist) {
959             if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
960                 errstr = "PERM_FULL_USER: setgroups";
961                 goto bad;
962             }
963         }
964         state->ruid = user_uid;
965         state->euid = user_uid;
966         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
967             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
968             (int)ostate->euid, (int)state->ruid, (int)state->euid);
969         if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
970             snprintf(errbuf, sizeof(errbuf),
971                 "PERM_FULL_USER: setreuid(%d, %d)", ID(ruid), ID(euid));
972             goto bad;
973         }
974         break;
975
976     case PERM_RUNAS:
977         state->rgid = ostate->rgid;
978         state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
979         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
980             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
981             (int)ostate->egid, (int)state->rgid, (int)state->egid);
982         if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
983             errstr = N_("unable to change to runas gid");
984             goto bad;
985         }
986         state->grlist = runas_setgroups();
987         state->ruid = ROOT_UID;
988         state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
989         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
990             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
991             (int)ostate->euid, (int)state->ruid, (int)state->euid);
992         if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
993             errstr = N_("unable to change to runas uid");
994             goto bad;
995         }
996         break;
997
998     case PERM_SUDOERS:
999         state->grlist = ostate->grlist;
1000         sudo_grlist_addref(state->grlist);
1001
1002         /* assume euid == ROOT_UID, ruid == user */
1003         state->rgid = ostate->rgid;
1004         state->egid = sudoers_gid;
1005         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
1006             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1007             (int)ostate->egid, (int)state->rgid, (int)state->egid);
1008         if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
1009             errstr = N_("unable to change to sudoers gid");
1010             goto bad;
1011         }
1012
1013         state->ruid = ROOT_UID;
1014         /*
1015          * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
1016          * we use a non-zero uid in order to avoid NFS lossage.
1017          * Using uid 1 is a bit bogus but should work on all OS's.
1018          */
1019         if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
1020             state->euid = 1;
1021         else
1022             state->euid = sudoers_uid;
1023         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
1024             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1025             (int)ostate->euid, (int)state->ruid, (int)state->euid);
1026         if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
1027             snprintf(errbuf, sizeof(errbuf),
1028                 "PERM_SUDOERS: setreuid(%d, %d)", ID(ruid), ID(euid));
1029             goto bad;
1030         }
1031         break;
1032
1033     case PERM_TIMESTAMP:
1034         state->grlist = ostate->grlist;
1035         sudo_grlist_addref(state->grlist);
1036         state->rgid = ostate->rgid;
1037         state->egid = ostate->egid;
1038         state->ruid = ROOT_UID;
1039         state->euid = timestamp_uid;
1040         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
1041             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1042             (int)ostate->euid, (int)state->ruid, (int)state->euid);
1043         if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
1044             snprintf(errbuf, sizeof(errbuf),
1045                 "PERM_TIMESTAMP: setreuid(%d, %d)", ID(ruid), ID(euid));
1046             goto bad;
1047         }
1048         break;
1049     }
1050
1051     perm_stack_depth++;
1052     debug_return_bool(1);
1053 bad:
1054     warningx("%s: %s", _(errstr),
1055         errno == EAGAIN ? _("too many processes") : strerror(errno));
1056     if (noexit)
1057         debug_return_bool(0);
1058     exit(1);
1059 }
1060
1061 void
1062 restore_perms(void)
1063 {
1064     struct perm_state *state, *ostate;
1065     debug_decl(restore_perms, SUDO_DEBUG_PERMS)
1066
1067     if (perm_stack_depth < 2)
1068         debug_return;
1069
1070     state = &perm_stack[perm_stack_depth - 1];
1071     ostate = &perm_stack[perm_stack_depth - 2];
1072     perm_stack_depth--;
1073
1074     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d] -> [%d, %d]",
1075         __func__, (int)state->ruid, (int)state->euid,
1076         (int)ostate->ruid, (int)ostate->euid);
1077     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d] -> [%d, %d]",
1078         __func__, (int)state->rgid, (int)state->egid,
1079         (int)ostate->rgid, (int)ostate->egid);
1080
1081     /*
1082      * When changing euid to ROOT_UID, setreuid() may fail even if
1083      * the ruid is ROOT_UID so call setuid() first.
1084      */
1085     if (OID(euid) == ROOT_UID) {
1086         /* setuid() may not set the saved ID unless the euid is ROOT_UID */
1087         if (ID(euid) != ROOT_UID)
1088             ignore_result(setreuid(-1, ROOT_UID));
1089         if (setuid(ROOT_UID)) {
1090             warning("setuid() [%d, %d] -> %d)", (int)state->ruid,
1091                 (int)state->euid, ROOT_UID);
1092             goto bad;
1093         }
1094     }
1095     if (setreuid(OID(ruid), OID(euid))) {
1096         warning("setreuid() [%d, %d] -> [%d, %d]", (int)state->ruid,
1097             (int)state->euid, (int)OID(ruid), (int)OID(euid));
1098         goto bad;
1099     }
1100     if (setregid(OID(rgid), OID(egid))) {
1101         warning("setregid() [%d, %d] -> [%d, %d]", (int)state->rgid,
1102             (int)state->egid, (int)OID(rgid), (int)OID(egid));
1103         goto bad;
1104     }
1105     if (state->grlist != ostate->grlist) {
1106         if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
1107             warning("setgroups()");
1108             goto bad;
1109         }
1110     }
1111     sudo_grlist_delref(state->grlist);
1112     debug_return;
1113
1114 bad:
1115     exit(1);
1116 }
1117
1118 #elif defined(HAVE_SETEUID)
1119
1120 #define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid)
1121
1122 /*
1123  * Set real and effective uids and gids based on perm.
1124  * We always retain a real or effective uid of ROOT_UID unless
1125  * we are headed for an exec().
1126  * This version of set_perms() works fine with the "stay_setuid" option.
1127  */
1128 int
1129 set_perms(int perm)
1130 {
1131     struct perm_state *state, *ostate = NULL;
1132     char errbuf[1024];
1133     const char *errstr = errbuf;
1134     int noexit;
1135     debug_decl(set_perms, SUDO_DEBUG_PERMS)
1136
1137     noexit = ISSET(perm, PERM_NOEXIT);
1138     CLR(perm, PERM_MASK);
1139
1140     if (perm_stack_depth == PERM_STACK_MAX) {
1141         errstr = N_("perm stack overflow");
1142         errno = EINVAL;
1143         goto bad;
1144     }
1145
1146     state = &perm_stack[perm_stack_depth];
1147     if (perm != PERM_INITIAL) {
1148         if (perm_stack_depth == 0) {
1149             errstr = N_("perm stack underflow");
1150             errno = EINVAL;
1151             goto bad;
1152         }
1153         ostate = &perm_stack[perm_stack_depth - 1];
1154     }
1155
1156     /*
1157      * Since we only have setuid() and seteuid() and semantics
1158      * for these calls differ on various systems, we set
1159      * real and effective uids to ROOT_UID initially to be safe.
1160      */
1161     if (perm != PERM_INITIAL) {
1162         if (ostate->euid != ROOT_UID && seteuid(ROOT_UID)) {
1163             snprintf(errbuf, sizeof(errbuf), "set_perms: seteuid(%d)", ROOT_UID);
1164             goto bad;
1165         }
1166         if (ostate->ruid != ROOT_UID && setuid(ROOT_UID)) {
1167             snprintf(errbuf, sizeof(errbuf), "set_perms: setuid(%d)", ROOT_UID);
1168             goto bad;
1169         }
1170     }
1171
1172     switch (perm) {
1173     case PERM_INITIAL:
1174         /* Stash initial state */
1175         state->ruid = getuid();
1176         state->euid = geteuid();
1177         state->rgid = getgid();
1178         state->egid = getegid();
1179         state->grlist = user_group_list;
1180         sudo_grlist_addref(state->grlist);
1181         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
1182             "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__,
1183             (int)state->ruid, (int)state->euid,
1184             (int)state->rgid, (int)state->egid);
1185         break;
1186
1187     case PERM_ROOT:
1188         /* We already set ruid/euid above. */
1189         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
1190             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1191             (int)ostate->euid, ROOT_UID, ROOT_UID);
1192         state->ruid = ROOT_UID;
1193         state->euid = ROOT_UID;
1194         state->rgid = ostate->rgid;
1195         state->egid = ROOT_GID;
1196         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
1197             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1198             (int)ostate->egid, ROOT_GID, ROOT_GID);
1199         if (GID_CHANGED && setegid(ROOT_GID)) {
1200             errstr = N_("unable to change to root gid");
1201             goto bad;
1202         }
1203         state->grlist = ostate->grlist;
1204         sudo_grlist_addref(state->grlist);
1205         break;
1206
1207     case PERM_USER:
1208         state->egid = user_gid;
1209         state->rgid = ostate->rgid;
1210         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
1211             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1212             (int)ostate->egid, (int)state->rgid, (int)state->egid);
1213         if (GID_CHANGED && setegid(user_gid)) {
1214             snprintf(errbuf, sizeof(errbuf),
1215                 "PERM_USER: setegid(%d)", user_gid);
1216             goto bad;
1217         }
1218         state->grlist = user_group_list;
1219         sudo_grlist_addref(state->grlist);
1220         if (state->grlist != ostate->grlist) {
1221             if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
1222                 errstr = "PERM_USER: setgroups";
1223                 goto bad;
1224             }
1225         }
1226         state->ruid = ROOT_UID;
1227         state->euid = user_uid;
1228         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
1229             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1230             (int)ostate->euid, (int)state->ruid, (int)state->euid);
1231         if (seteuid(user_uid)) {
1232             snprintf(errbuf, sizeof(errbuf),
1233                 "PERM_USER: seteuid(%d)", user_uid);
1234             goto bad;
1235         }
1236         break;
1237
1238     case PERM_FULL_USER:
1239         /* headed for exec() */
1240         state->rgid = user_gid;
1241         state->egid = user_gid;
1242         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
1243             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1244             (int)ostate->egid, (int)state->rgid, (int)state->egid);
1245         if (GID_CHANGED && setgid(user_gid)) {
1246             snprintf(errbuf, sizeof(errbuf),
1247                 "PERM_FULL_USER: setgid(%d)", user_gid);
1248             goto bad;
1249         }
1250         state->grlist = user_group_list;
1251         sudo_grlist_addref(state->grlist);
1252         if (state->grlist != ostate->grlist) {
1253             if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
1254                 errstr = "PERM_FULL_USER: setgroups";
1255                 goto bad;
1256             }
1257         }
1258         state->ruid = user_uid;
1259         state->euid = user_uid;
1260         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
1261             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1262             (int)ostate->euid, (int)state->ruid, (int)state->euid);
1263         if (setuid(user_uid)) {
1264             snprintf(errbuf, sizeof(errbuf),
1265                 "PERM_FULL_USER: setuid(%d)", user_uid);
1266             goto bad;
1267         }
1268         break;
1269
1270     case PERM_RUNAS:
1271         state->rgid = ostate->rgid;
1272         state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
1273         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
1274             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1275             (int)ostate->egid, (int)state->rgid, (int)state->egid);
1276         if (GID_CHANGED && setegid(state->egid)) {
1277             errstr = N_("unable to change to runas gid");
1278             goto bad;
1279         }
1280         state->grlist = runas_setgroups();
1281         state->ruid = ostate->ruid;
1282         state->euid = runas_pw ? runas_pw->pw_uid : user_uid;
1283         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
1284             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1285             (int)ostate->euid, (int)state->ruid, (int)state->euid);
1286         if (seteuid(state->euid)) {
1287             errstr = N_("unable to change to runas uid");
1288             goto bad;
1289         }
1290         break;
1291
1292     case PERM_SUDOERS:
1293         state->grlist = ostate->grlist;
1294         sudo_grlist_addref(state->grlist);
1295
1296         /* assume euid == ROOT_UID, ruid == user */
1297         state->rgid = ostate->rgid;
1298         state->egid = sudoers_gid;
1299         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
1300             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
1301             (int)ostate->egid, (int)state->rgid, (int)state->egid);
1302         if (GID_CHANGED && setegid(sudoers_gid)) {
1303             errstr = N_("unable to change to sudoers gid");
1304             goto bad;
1305         }
1306
1307         state->ruid = ROOT_UID;
1308         /*
1309          * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
1310          * we use a non-zero uid in order to avoid NFS lossage.
1311          * Using uid 1 is a bit bogus but should work on all OS's.
1312          */
1313         if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
1314             state->euid = 1;
1315         else
1316             state->euid = sudoers_uid;
1317         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
1318             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1319             (int)ostate->euid, (int)state->ruid, (int)state->euid);
1320         if (seteuid(state->euid)) {
1321             snprintf(errbuf, sizeof(errbuf),
1322                 "PERM_SUDOERS: seteuid(%d)", state->euid);
1323             goto bad;
1324         }
1325         break;
1326
1327     case PERM_TIMESTAMP:
1328         state->grlist = ostate->grlist;
1329         sudo_grlist_addref(state->grlist);
1330         state->rgid = ostate->rgid;
1331         state->egid = ostate->egid;
1332         state->ruid = ROOT_UID;
1333         state->euid = timestamp_uid;
1334         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
1335             "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
1336             (int)ostate->euid, (int)state->ruid, (int)state->euid);
1337         if (seteuid(timestamp_uid)) {
1338             snprintf(errbuf, sizeof(errbuf),
1339                 "PERM_TIMESTAMP: seteuid(%d)", timestamp_uid);
1340             goto bad;
1341         }
1342         break;
1343     }
1344
1345     perm_stack_depth++;
1346     debug_return_bool(1);
1347 bad:
1348     warningx("%s: %s", _(errstr),
1349         errno == EAGAIN ? _("too many processes") : strerror(errno));
1350     if (noexit)
1351         debug_return_bool(0);
1352     exit(1);
1353 }
1354
1355 void
1356 restore_perms(void)
1357 {
1358     struct perm_state *state, *ostate;
1359     debug_decl(restore_perms, SUDO_DEBUG_PERMS)
1360
1361     if (perm_stack_depth < 2)
1362         debug_return;
1363
1364     state = &perm_stack[perm_stack_depth - 1];
1365     ostate = &perm_stack[perm_stack_depth - 2];
1366     perm_stack_depth--;
1367
1368     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d] -> [%d, %d]",
1369         __func__, (int)state->ruid, (int)state->euid,
1370         (int)ostate->ruid, (int)ostate->euid);
1371     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d] -> [%d, %d]",
1372         __func__, (int)state->rgid, (int)state->egid,
1373         (int)ostate->rgid, (int)ostate->egid);
1374
1375     /*
1376      * Since we only have setuid() and seteuid() and semantics
1377      * for these calls differ on various systems, we set
1378      * real and effective uids to ROOT_UID initially to be safe.
1379      */
1380     if (seteuid(ROOT_UID)) {
1381         warningx("seteuid() [%d] -> [%d]", (int)state->euid, ROOT_UID);
1382         goto bad;
1383     }
1384     if (setuid(ROOT_UID)) {
1385         warningx("setuid() [%d, %d] -> [%d, %d]", (int)state->ruid, ROOT_UID,
1386             ROOT_UID, ROOT_UID);
1387         goto bad;
1388     }
1389
1390     if (OID(egid) != -1 && setegid(ostate->egid)) {
1391         warning("setegid(%d)", (int)ostate->egid);
1392         goto bad;
1393     }
1394     if (state->grlist != ostate->grlist) {
1395         if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
1396             warning("setgroups()");
1397             goto bad;
1398         }
1399     }
1400     if (OID(euid) != -1 && seteuid(ostate->euid)) {
1401         warning("seteuid(%d)", ostate->euid);
1402         goto bad;
1403     }
1404     sudo_grlist_delref(state->grlist);
1405     debug_return;
1406
1407 bad:
1408     exit(1);
1409 }
1410
1411 #else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */
1412
1413 /*
1414  * Set uids and gids based on perm via setuid() and setgid().
1415  * NOTE: does not support the "stay_setuid" or timestampowner options.
1416  *       Also, sudoers_uid and sudoers_gid are not used.
1417  */
1418 int
1419 set_perms(int perm)
1420 {
1421     struct perm_state *state, *ostate = NULL;
1422     char errbuf[1024];
1423     const char *errstr = errbuf;
1424     int noexit;
1425     debug_decl(set_perms, SUDO_DEBUG_PERMS)
1426
1427     noexit = ISSET(perm, PERM_NOEXIT);
1428     CLR(perm, PERM_MASK);
1429
1430     if (perm_stack_depth == PERM_STACK_MAX) {
1431         errstr = N_("perm stack overflow");
1432         errno = EINVAL;
1433         goto bad;
1434     }
1435
1436     state = &perm_stack[perm_stack_depth];
1437     if (perm != PERM_INITIAL) {
1438         if (perm_stack_depth == 0) {
1439             errstr = N_("perm stack underflow");
1440             errno = EINVAL;
1441             goto bad;
1442         }
1443         ostate = &perm_stack[perm_stack_depth - 1];
1444     }
1445
1446     switch (perm) {
1447     case PERM_INITIAL:
1448         /* Stash initial state */
1449         state->ruid = geteuid() == ROOT_UID ? ROOT_UID : getuid();
1450         state->rgid = getgid();
1451         state->grlist = user_group_list;
1452         sudo_grlist_addref(state->grlist);
1453         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
1454             "ruid: %d, rgid: %d", __func__, (int)state->ruid, (int)state->rgid);
1455         break;
1456
1457     case PERM_ROOT:
1458         state->ruid = ROOT_UID;
1459         state->rgid = ROOT_GID;
1460         state->grlist = ostate->grlist;
1461         sudo_grlist_addref(state->grlist);
1462         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
1463             "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid);
1464         if (setuid(ROOT_UID)) {
1465             snprintf(errbuf, sizeof(errbuf), "PERM_ROOT: setuid(%d)", ROOT_UID);
1466             goto bad;
1467         }
1468         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
1469             "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid);
1470         if (setgid(ROOT_GID)) {
1471             errstr = N_("unable to change to root gid");
1472             goto bad;
1473         }
1474         break;
1475
1476     case PERM_FULL_USER:
1477         state->rgid = user_gid;
1478         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
1479             "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid);
1480         (void) setgid(user_gid);
1481         state->grlist = user_group_list;
1482         sudo_grlist_addref(state->grlist);
1483         if (state->grlist != ostate->grlist) {
1484             if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) {
1485                 errstr = "PERM_FULL_USER: setgroups";
1486                 goto bad;
1487             }
1488         }
1489         state->ruid = user_uid;
1490         sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
1491             "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid);
1492         if (setuid(user_uid)) {
1493             snprintf(errbuf, sizeof(errbuf),
1494                 "PERM_FULL_USER: setuid(%d)", user_uid);
1495             goto bad;
1496         }
1497         break;
1498
1499     case PERM_USER:
1500     case PERM_SUDOERS:
1501     case PERM_RUNAS:
1502     case PERM_TIMESTAMP:
1503         /* Unsupported since we can't set euid. */
1504         state->ruid = ostate->ruid;
1505         state->rgid = ostate->rgid;
1506         state->grlist = ostate->grlist;
1507         sudo_grlist_addref(state->grlist);
1508         break;
1509     }
1510
1511     perm_stack_depth++;
1512     debug_return_bool(1);
1513 bad:
1514     warningx("%s: %s", _(errstr),
1515         errno == EAGAIN ? _("too many processes") : strerror(errno));
1516     if (noexit)
1517         debug_return_bool(0);
1518     exit(1);
1519 }
1520
1521 void
1522 restore_perms(void)
1523 {
1524     struct perm_state *state, *ostate;
1525     debug_decl(restore_perms, SUDO_DEBUG_PERMS)
1526
1527     if (perm_stack_depth < 2)
1528         debug_return;
1529
1530     state = &perm_stack[perm_stack_depth - 1];
1531     ostate = &perm_stack[perm_stack_depth - 2];
1532     perm_stack_depth--;
1533
1534     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d] -> [%d]",
1535         __func__, (int)state->ruid, (int)ostate->ruid);
1536     sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d] -> [%d]",
1537         __func__, (int)state->rgid, (int)ostate->rgid);
1538
1539     if (OID(rgid) != -1 && setgid(ostate->rgid)) {
1540         warning("setgid(%d)", (int)ostate->rgid);
1541         goto bad;
1542     }
1543     if (state->grlist != ostate->grlist) {
1544         if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) {
1545             warning("setgroups()");
1546             goto bad;
1547         }
1548     }
1549     sudo_grlist_delref(state->grlist);
1550     if (OID(ruid) != -1 && setuid(ostate->ruid)) {
1551         warning("setuid(%d)", (int)ostate->ruid);
1552         goto bad;
1553     }
1554     debug_return;
1555
1556 bad:
1557     exit(1);
1558 }
1559 #endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */
1560
1561 #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
1562 static struct group_list *
1563 runas_setgroups(void)
1564 {
1565     struct passwd *pw;
1566     struct group_list *grlist;
1567     debug_decl(runas_setgroups, SUDO_DEBUG_PERMS)
1568
1569     if (def_preserve_groups) {
1570         sudo_grlist_addref(user_group_list);
1571         debug_return_ptr(user_group_list);
1572     }
1573
1574     pw = runas_pw ? runas_pw : sudo_user.pw;
1575 #ifdef HAVE_SETAUTHDB
1576     aix_setauthdb(pw->pw_name);
1577 #endif
1578     grlist = sudo_get_grlist(pw);
1579 #ifdef HAVE_SETAUTHDB
1580     aix_restoreauthdb();
1581 #endif
1582     if (sudo_setgroups(grlist->ngids, grlist->gids) < 0)
1583         log_fatal(USE_ERRNO|MSG_ONLY, N_("unable to set runas group vector"));
1584     debug_return_ptr(grlist);
1585 }
1586 #endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */