File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / set_perms.c
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:12:54 2014 UTC (10 years, 3 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_10p3_0, v1_8_10p3, HEAD
sudo v 1.8.10p3

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

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