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

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

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