Annotation of embedaddon/sudo/plugins/sudoers/set_perms.c, revision 1.1.1.6

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>