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

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

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