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

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

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