[BACK]Return to set_perms.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Annotation of src/usr.bin/sudo/set_perms.c, Revision 1.12

1.1       millert     1: /*
1.11      millert     2:  * Copyright (c) 1994-1996,1998-2006 Todd C. Miller <Todd.Miller@courtesan.com>
1.1       millert     3:  *
1.10      millert     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.
1.1       millert     7:  *
1.10      millert     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.
1.8       millert    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.
1.1       millert    19:  */
                     20:
1.11      millert    21: #include <config.h>
1.1       millert    22:
                     23: #include <sys/types.h>
                     24: #include <sys/param.h>
                     25: #include <sys/stat.h>
                     26: #include <stdio.h>
                     27: #ifdef STDC_HEADERS
                     28: # include <stdlib.h>
                     29: # include <stddef.h>
                     30: #else
                     31: # ifdef HAVE_STDLIB_H
                     32: #  include <stdlib.h>
                     33: # endif
                     34: #endif /* STDC_HEADERS */
                     35: #ifdef HAVE_STRING_H
                     36: # include <string.h>
                     37: #else
                     38: # ifdef HAVE_STRINGS_H
                     39: #  include <strings.h>
                     40: # endif
                     41: #endif /* HAVE_STRING_H */
                     42: #ifdef HAVE_UNISTD_H
                     43: # include <unistd.h>
                     44: #endif /* HAVE_UNISTD_H */
1.11      millert    45: #ifdef HAVE_ERR_H
                     46: # include <err.h>
                     47: #else
                     48: # include "emul/err.h"
                     49: #endif /* HAVE_ERR_H */
1.1       millert    50: #include <pwd.h>
                     51: #include <errno.h>
                     52: #include <grp.h>
                     53: #ifdef HAVE_LOGIN_CAP_H
                     54: # include <login_cap.h>
                     55: #endif
                     56:
                     57: #include "sudo.h"
                     58:
                     59: #ifndef lint
1.12    ! millert    60: __unused static const char rcsid[] = "$Sudo: set_perms.c,v 1.30.2.7 2007/11/27 23:41:23 millert Exp $";
1.1       millert    61: #endif /* lint */
                     62:
1.10      millert    63: #ifdef __TANDEM
                     64: # define ROOT_UID      65535
                     65: #else
                     66: # define ROOT_UID      0
                     67: #endif
                     68:
1.1       millert    69: /*
                     70:  * Prototypes
                     71:  */
                     72: static void runas_setup                __P((void));
1.12    ! millert    73: static void runas_setgroups    __P((void));
        !            74: static void restore_groups     __P((void));
        !            75:
        !            76: static int current_perm = -1;
1.1       millert    77:
1.7       millert    78: #ifdef HAVE_SETRESUID
                     79: /*
                     80:  * Set real and effective and saved uids and gids based on perm.
                     81:  * We always retain a saved uid of 0 unless we are headed for an exec().
                     82:  * We only flip the effective gid since it only changes for PERM_SUDOERS.
                     83:  * This version of set_perms() works fine with the "stay_setuid" option.
                     84:  */
                     85: void
1.11      millert    86: set_perms(perm)
1.7       millert    87:     int perm;
                     88: {
1.12    ! millert    89:     if (perm == current_perm)
        !            90:        return;
        !            91:
1.7       millert    92:     switch (perm) {
                     93:        case PERM_ROOT:
1.10      millert    94:                                if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID))
1.11      millert    95:                                    errx(1, "setresuid(ROOT_UID, ROOT_UID, ROOT_UID) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid");
                     96:                                (void) setresgid(-1, user_gid, -1);
1.12    ! millert    97:                                if (current_perm == PERM_RUNAS)
        !            98:                                    restore_groups();
1.7       millert    99:                                break;
                    100:
                    101:        case PERM_USER:
                    102:                                (void) setresgid(-1, user_gid, -1);
1.10      millert   103:                                if (setresuid(user_uid, user_uid, ROOT_UID))
1.11      millert   104:                                    err(1, "setresuid(user_uid, user_uid, ROOT_UID)");
1.7       millert   105:                                break;
                    106:
                    107:        case PERM_FULL_USER:
                    108:                                /* headed for exec() */
                    109:                                (void) setgid(user_gid);
                    110:                                if (setresuid(user_uid, user_uid, user_uid))
1.11      millert   111:                                    err(1, "setresuid(user_uid, user_uid, user_uid)");
1.7       millert   112:                                break;
                    113:
                    114:        case PERM_RUNAS:
1.12    ! millert   115:                                runas_setgroups();
1.11      millert   116:                                (void) setresgid(-1, runas_pw->pw_gid, -1);
1.10      millert   117:                                if (setresuid(-1, runas_pw->pw_uid, -1))
1.11      millert   118:                                    err(1, "unable to change to runas uid");
1.10      millert   119:                                break;
                    120:
                    121:        case PERM_FULL_RUNAS:
                    122:                                /* headed for exec(), assume euid == ROOT_UID */
1.7       millert   123:                                runas_setup();
1.11      millert   124:                                if (setresuid(def_stay_setuid ?
1.7       millert   125:                                    user_uid : runas_pw->pw_uid,
1.11      millert   126:                                    runas_pw->pw_uid, runas_pw->pw_uid))
                    127:                                    err(1, "unable to change to runas uid");
1.7       millert   128:                                break;
                    129:
                    130:        case PERM_SUDOERS:
1.10      millert   131:                                /* assume euid == ROOT_UID, ruid == user */
1.7       millert   132:                                if (setresgid(-1, SUDOERS_GID, -1))
1.11      millert   133:                                    err(1, "unable to change to sudoers gid");
1.7       millert   134:
                    135:                                /*
1.10      millert   136:                                 * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
1.7       millert   137:                                 * is group readable we use a non-zero
                    138:                                 * uid in order to avoid NFS lossage.
                    139:                                 * Using uid 1 is a bit bogus but should
                    140:                                 * work on all OS's.
                    141:                                 */
1.10      millert   142:                                if (SUDOERS_UID == ROOT_UID) {
                    143:                                    if ((SUDOERS_MODE & 040) && setresuid(ROOT_UID, 1, ROOT_UID))
1.11      millert   144:                                        err(1, "setresuid(ROOT_UID, 1, ROOT_UID)");
1.7       millert   145:                                } else {
1.10      millert   146:                                    if (setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID))
1.11      millert   147:                                        err(1, "setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)");
1.7       millert   148:                                }
                    149:                                break;
                    150:        case PERM_TIMESTAMP:
1.10      millert   151:                                if (setresuid(ROOT_UID, timestamp_uid, ROOT_UID))
1.11      millert   152:                                    err(1, "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)");
1.7       millert   153:                                break;
                    154:     }
1.12    ! millert   155:
        !           156:     current_perm = perm;
1.7       millert   157: }
                    158:
                    159: #else
                    160: # ifdef HAVE_SETREUID
                    161:
1.1       millert   162: /*
                    163:  * Set real and effective uids and gids based on perm.
1.10      millert   164:  * We always retain a real or effective uid of ROOT_UID unless
1.1       millert   165:  * we are headed for an exec().
1.7       millert   166:  * This version of set_perms() works fine with the "stay_setuid" option.
1.1       millert   167:  */
                    168: void
1.11      millert   169: set_perms(perm)
1.1       millert   170:     int perm;
                    171: {
1.12    ! millert   172:     if (perm == current_perm)
        !           173:        return;
        !           174:
1.1       millert   175:     switch (perm) {
                    176:        case PERM_ROOT:
1.10      millert   177:                                if (setreuid(-1, ROOT_UID))
1.11      millert   178:                                    errx(1, "setreuid(-1, ROOT_UID) failed, your operating system may have a broken setreuid() function\nTry running configure with --disable-setreuid");
1.10      millert   179:                                if (setuid(ROOT_UID))
1.11      millert   180:                                    err(1, "setuid(ROOT_UID)");
                    181:                                (void) setregid(-1, user_gid);
1.12    ! millert   182:                                if (current_perm == PERM_RUNAS)
        !           183:                                    restore_groups();
1.1       millert   184:                                break;
1.2       millert   185:
1.1       millert   186:        case PERM_USER:
1.7       millert   187:                                (void) setregid(-1, user_gid);
1.10      millert   188:                                if (setreuid(ROOT_UID, user_uid))
1.11      millert   189:                                    err(1, "setreuid(ROOT_UID, user_uid)");
1.1       millert   190:                                break;
                    191:
1.4       millert   192:        case PERM_FULL_USER:
                    193:                                /* headed for exec() */
                    194:                                (void) setgid(user_gid);
1.7       millert   195:                                if (setreuid(user_uid, user_uid))
1.11      millert   196:                                    err(1, "setreuid(user_uid, user_uid)");
1.4       millert   197:                                break;
                    198:
1.1       millert   199:        case PERM_RUNAS:
1.12    ! millert   200:                                runas_setgroups();
1.11      millert   201:                                (void) setregid(-1, runas_pw->pw_gid);
1.10      millert   202:                                if (setreuid(-1, runas_pw->pw_uid))
1.11      millert   203:                                    err(1, "unable to change to runas uid");
1.10      millert   204:                                break;
                    205:
                    206:        case PERM_FULL_RUNAS:
                    207:                                /* headed for exec(), assume euid == ROOT_UID */
1.1       millert   208:                                runas_setup();
1.11      millert   209:                                if (setreuid(def_stay_setuid ? user_uid :
                    210:                                    runas_pw->pw_uid, runas_pw->pw_uid))
                    211:                                    err(1, "unable to change to runas uid");
1.1       millert   212:                                break;
                    213:
                    214:        case PERM_SUDOERS:
1.10      millert   215:                                /* assume euid == ROOT_UID, ruid == user */
1.7       millert   216:                                if (setregid(-1, SUDOERS_GID))
1.11      millert   217:                                    err(1, "unable to change to sudoers gid");
1.1       millert   218:
                    219:                                /*
1.10      millert   220:                                 * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
1.1       millert   221:                                 * is group readable we use a non-zero
                    222:                                 * uid in order to avoid NFS lossage.
                    223:                                 * Using uid 1 is a bit bogus but should
                    224:                                 * work on all OS's.
                    225:                                 */
1.10      millert   226:                                if (SUDOERS_UID == ROOT_UID) {
                    227:                                    if ((SUDOERS_MODE & 040) && setreuid(ROOT_UID, 1))
1.11      millert   228:                                        err(1, "setreuid(ROOT_UID, 1)");
1.1       millert   229:                                } else {
1.10      millert   230:                                    if (setreuid(ROOT_UID, SUDOERS_UID))
1.11      millert   231:                                        err(1, "setreuid(ROOT_UID, SUDOERS_UID)");
1.1       millert   232:                                }
                    233:                                break;
1.7       millert   234:        case PERM_TIMESTAMP:
1.10      millert   235:                                if (setreuid(ROOT_UID, timestamp_uid))
1.11      millert   236:                                    err(1, "setreuid(ROOT_UID, timestamp_uid)");
1.7       millert   237:                                break;
1.1       millert   238:     }
1.12    ! millert   239:
        !           240:     current_perm = perm;
1.1       millert   241: }
                    242:
1.11      millert   243: # else /* !HAVE_SETRESUID && !HAVE_SETREUID */
                    244: # ifdef HAVE_SETEUID
1.1       millert   245:
                    246: /*
                    247:  * Set real and effective uids and gids based on perm.
                    248:  * NOTE: does not support the "stay_setuid" option.
                    249:  */
                    250: void
1.11      millert   251: set_perms(perm)
1.1       millert   252:     int perm;
                    253: {
1.12    ! millert   254:     if (perm == current_perm)
        !           255:        return;
        !           256:
1.1       millert   257:     /*
1.11      millert   258:      * Since we only have setuid() and seteuid() and semantics
                    259:      * for these calls differ on various systems, we set
                    260:      * real and effective uids to ROOT_UID initially to be safe.
1.1       millert   261:      */
1.11      millert   262:     if (seteuid(ROOT_UID))
                    263:        err(1, "seteuid(ROOT_UID)");
1.10      millert   264:     if (setuid(ROOT_UID))
1.11      millert   265:        err(1, "setuid(ROOT_UID)");
1.1       millert   266:
                    267:     switch (perm) {
1.11      millert   268:        case PERM_ROOT:
                    269:                                /* uid set above */
                    270:                                (void) setegid(user_gid);
1.12    ! millert   271:                                if (current_perm == PERM_RUNAS)
        !           272:                                    restore_groups();
1.11      millert   273:                                break;
                    274:
1.1       millert   275:        case PERM_USER:
                    276:                                (void) setegid(user_gid);
                    277:                                if (seteuid(user_uid))
1.11      millert   278:                                    err(1, "seteuid(user_uid)");
1.4       millert   279:                                break;
                    280:
                    281:        case PERM_FULL_USER:
                    282:                                /* headed for exec() */
                    283:                                (void) setgid(user_gid);
                    284:                                if (setuid(user_uid))
1.11      millert   285:                                    err(1, "setuid(user_uid)");
1.1       millert   286:                                break;
                    287:
                    288:        case PERM_RUNAS:
1.12    ! millert   289:                                runas_setgroups();
1.11      millert   290:                                (void) setegid(runas_pw->pw_gid);
1.10      millert   291:                                if (seteuid(runas_pw->pw_uid))
1.11      millert   292:                                    err(1, "unable to change to runas uid");
1.10      millert   293:                                break;
                    294:
                    295:        case PERM_FULL_RUNAS:
1.11      millert   296:                                /* headed for exec() */
1.1       millert   297:                                runas_setup();
                    298:                                if (setuid(runas_pw->pw_uid))
1.11      millert   299:                                    err(1, "unable to change to runas uid");
1.1       millert   300:                                break;
                    301:
                    302:        case PERM_SUDOERS:
                    303:                                if (setegid(SUDOERS_GID))
1.11      millert   304:                                    err(1, "unable to change to sudoers gid");
1.1       millert   305:
                    306:                                /*
1.10      millert   307:                                 * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
1.1       millert   308:                                 * is group readable we use a non-zero
                    309:                                 * uid in order to avoid NFS lossage.
                    310:                                 * Using uid 1 is a bit bogus but should
                    311:                                 * work on all OS's.
                    312:                                 */
1.10      millert   313:                                if (SUDOERS_UID == ROOT_UID) {
1.1       millert   314:                                    if ((SUDOERS_MODE & 040) && seteuid(1))
1.11      millert   315:                                        err(1, "seteuid(1)");
1.1       millert   316:                                } else {
                    317:                                    if (seteuid(SUDOERS_UID))
1.11      millert   318:                                        err(1, "seteuid(SUDOERS_UID)");
1.1       millert   319:                                }
                    320:                                break;
1.7       millert   321:        case PERM_TIMESTAMP:
                    322:                                if (seteuid(timestamp_uid))
1.11      millert   323:                                    err(1, "seteuid(timestamp_uid)");
1.7       millert   324:                                break;
1.1       millert   325:     }
1.12    ! millert   326:
        !           327:     current_perm = perm;
1.1       millert   328: }
1.10      millert   329:
1.11      millert   330: # else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */
1.10      millert   331:
                    332: /*
                    333:  * Set uids and gids based on perm via setuid() and setgid().
                    334:  * NOTE: does not support the "stay_setuid" or timestampowner options.
                    335:  *       Also, SUDOERS_UID and SUDOERS_GID are not used.
                    336:  */
                    337: void
1.11      millert   338: set_perms(perm)
1.10      millert   339:     int perm;
                    340: {
1.12    ! millert   341:     if (perm == current_perm)
        !           342:        return;
1.10      millert   343:
                    344:     switch (perm) {
                    345:        case PERM_ROOT:
                    346:                                if (setuid(ROOT_UID))
1.11      millert   347:                                        err(1, "setuid(ROOT_UID)");
1.12    ! millert   348:                                if (current_perm == PERM_RUNAS)
        !           349:                                    restore_groups();
1.10      millert   350:                                break;
                    351:
                    352:        case PERM_FULL_USER:
                    353:                                (void) setgid(user_gid);
                    354:                                if (setuid(user_uid))
1.11      millert   355:                                    err(1, "setuid(user_uid)");
1.10      millert   356:                                break;
                    357:
                    358:        case PERM_FULL_RUNAS:
                    359:                                runas_setup();
                    360:                                if (setuid(runas_pw->pw_uid))
1.11      millert   361:                                    err(1, "unable to change to runas uid");
1.10      millert   362:                                break;
                    363:
                    364:        case PERM_USER:
                    365:        case PERM_SUDOERS:
                    366:        case PERM_RUNAS:
                    367:        case PERM_TIMESTAMP:
                    368:                                /* Unsupported since we can't set euid. */
                    369:                                break;
                    370:     }
1.12    ! millert   371:
        !           372:     current_perm = perm;
1.10      millert   373: }
                    374: #  endif /* HAVE_SETEUID */
1.7       millert   375: # endif /* HAVE_SETREUID */
                    376: #endif /* HAVE_SETRESUID */
1.1       millert   377:
1.12    ! millert   378: #ifdef HAVE_INITGROUPS
        !           379: static void
        !           380: runas_setgroups()
        !           381: {
        !           382:     static int ngroups = -1;
        !           383:     static GETGROUPS_T *groups;
        !           384:     struct passwd *pw;
        !           385:
        !           386:     if (def_preserve_groups)
        !           387:        return;
        !           388:
        !           389:     /*
        !           390:      * Use stashed copy of runas groups if available, else initgroups and stash.
        !           391:      */
        !           392:     if (ngroups == -1) {
        !           393:        pw = runas_pw ? runas_pw : sudo_user.pw;
        !           394:        if (initgroups(pw->pw_name, pw->pw_gid) < 0)
        !           395:            log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
        !           396:        if ((ngroups = getgroups(0, NULL)) < 0)
        !           397:            log_error(USE_ERRNO|MSG_ONLY, "can't get runas ngroups");
        !           398:        groups = emalloc2(ngroups, sizeof(GETGROUPS_T));
        !           399:        if (getgroups(ngroups, groups) < 0)
        !           400:            log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector");
        !           401:     } else {
        !           402:        if (setgroups(ngroups, groups) < 0)
        !           403:            log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");
        !           404:     }
        !           405: }
        !           406:
        !           407: static void
        !           408: restore_groups()
        !           409: {
        !           410:     if (setgroups(user_ngroups, user_groups) < 0)
        !           411:        log_error(USE_ERRNO|MSG_ONLY, "can't reset user group vector");
        !           412: }
        !           413:
        !           414: #else
        !           415:
        !           416: static void
        !           417: runas_setgroups()
        !           418: {
        !           419:     /* STUB */
        !           420: }
        !           421:
        !           422: static void
        !           423: restore_groups()
        !           424: {
        !           425:     /* STUB */
        !           426: }
        !           427:
        !           428: #endif /* HAVE_INITGROUPS */
        !           429:
1.1       millert   430: static void
                    431: runas_setup()
                    432: {
                    433: #ifdef HAVE_LOGIN_CAP_H
1.11      millert   434:     int flags;
1.1       millert   435:     extern login_cap_t *lc;
                    436: #endif
                    437:
                    438:     if (runas_pw->pw_name != NULL) {
                    439: #ifdef HAVE_PAM
                    440:        pam_prep_user(runas_pw);
                    441: #endif /* HAVE_PAM */
                    442:
                    443: #ifdef HAVE_LOGIN_CAP_H
1.10      millert   444:        if (def_use_loginclass) {
1.1       millert   445:            /*
1.12    ! millert   446:              * We only use setusercontext() set the nice value and rlimits.
1.1       millert   447:             */
                    448:            flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
1.10      millert   449:            if (!def_preserve_groups)
                    450:                SET(flags, LOGIN_SETGROUP);
1.1       millert   451:            else if (setgid(runas_pw->pw_gid))
1.11      millert   452:                warn("cannot set gid to runas gid");
                    453:            if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) {
1.10      millert   454:                if (runas_pw->pw_uid != ROOT_UID)
1.11      millert   455:                    err(1, "unable to set user context");
1.7       millert   456:                else
1.11      millert   457:                    warn("unable to set user context");
1.7       millert   458:            }
1.12    ! millert   459:        }
1.1       millert   460: #endif /* HAVE_LOGIN_CAP_H */
1.12    ! millert   461:        if (setgid(runas_pw->pw_gid))
        !           462:            warn("cannot set gid to runas gid");
        !           463:        /*
        !           464:         * Initialize group vector unless asked not to.
        !           465:         */
        !           466:        runas_setgroups();
1.1       millert   467:     }
                    468: }