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

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

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