[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.11

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.11    ! millert    60: __unused static const char rcsid[] = "$Sudo: set_perms.c,v 1.30.2.4 2007/07/06 14:16:22 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));
                     73:
1.7       millert    74: #ifdef HAVE_SETRESUID
                     75: /*
                     76:  * Set real and effective and saved uids and gids based on perm.
                     77:  * We always retain a saved uid of 0 unless we are headed for an exec().
                     78:  * We only flip the effective gid since it only changes for PERM_SUDOERS.
                     79:  * This version of set_perms() works fine with the "stay_setuid" option.
                     80:  */
                     81: void
1.11    ! millert    82: set_perms(perm)
1.7       millert    83:     int perm;
                     84: {
                     85:     switch (perm) {
                     86:        case PERM_ROOT:
1.10      millert    87:                                if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID))
1.11    ! millert    88:                                    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");
        !            89:                                (void) setresgid(-1, user_gid, -1);
1.7       millert    90:                                break;
                     91:
                     92:        case PERM_USER:
                     93:                                (void) setresgid(-1, user_gid, -1);
1.10      millert    94:                                if (setresuid(user_uid, user_uid, ROOT_UID))
1.11    ! millert    95:                                    err(1, "setresuid(user_uid, user_uid, ROOT_UID)");
1.7       millert    96:                                break;
                     97:
                     98:        case PERM_FULL_USER:
                     99:                                /* headed for exec() */
                    100:                                (void) setgid(user_gid);
                    101:                                if (setresuid(user_uid, user_uid, user_uid))
1.11    ! millert   102:                                    err(1, "setresuid(user_uid, user_uid, user_uid)");
1.7       millert   103:                                break;
                    104:
                    105:        case PERM_RUNAS:
1.11    ! millert   106:                                (void) setresgid(-1, runas_pw->pw_gid, -1);
1.10      millert   107:                                if (setresuid(-1, runas_pw->pw_uid, -1))
1.11    ! millert   108:                                    err(1, "unable to change to runas uid");
1.10      millert   109:                                break;
                    110:
                    111:        case PERM_FULL_RUNAS:
                    112:                                /* headed for exec(), assume euid == ROOT_UID */
1.7       millert   113:                                runas_setup();
1.11    ! millert   114:                                if (setresuid(def_stay_setuid ?
1.7       millert   115:                                    user_uid : runas_pw->pw_uid,
1.11    ! millert   116:                                    runas_pw->pw_uid, runas_pw->pw_uid))
        !           117:                                    err(1, "unable to change to runas uid");
1.7       millert   118:                                break;
                    119:
                    120:        case PERM_SUDOERS:
1.10      millert   121:                                /* assume euid == ROOT_UID, ruid == user */
1.7       millert   122:                                if (setresgid(-1, SUDOERS_GID, -1))
1.11    ! millert   123:                                    err(1, "unable to change to sudoers gid");
1.7       millert   124:
                    125:                                /*
1.10      millert   126:                                 * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
1.7       millert   127:                                 * is group readable we use a non-zero
                    128:                                 * uid in order to avoid NFS lossage.
                    129:                                 * Using uid 1 is a bit bogus but should
                    130:                                 * work on all OS's.
                    131:                                 */
1.10      millert   132:                                if (SUDOERS_UID == ROOT_UID) {
                    133:                                    if ((SUDOERS_MODE & 040) && setresuid(ROOT_UID, 1, ROOT_UID))
1.11    ! millert   134:                                        err(1, "setresuid(ROOT_UID, 1, ROOT_UID)");
1.7       millert   135:                                } else {
1.10      millert   136:                                    if (setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID))
1.11    ! millert   137:                                        err(1, "setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)");
1.7       millert   138:                                }
                    139:                                break;
                    140:        case PERM_TIMESTAMP:
1.10      millert   141:                                if (setresuid(ROOT_UID, timestamp_uid, ROOT_UID))
1.11    ! millert   142:                                    err(1, "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)");
1.7       millert   143:                                break;
                    144:     }
                    145: }
                    146:
                    147: #else
                    148: # ifdef HAVE_SETREUID
                    149:
1.1       millert   150: /*
                    151:  * Set real and effective uids and gids based on perm.
1.10      millert   152:  * We always retain a real or effective uid of ROOT_UID unless
1.1       millert   153:  * we are headed for an exec().
1.7       millert   154:  * This version of set_perms() works fine with the "stay_setuid" option.
1.1       millert   155:  */
                    156: void
1.11    ! millert   157: set_perms(perm)
1.1       millert   158:     int perm;
                    159: {
                    160:     switch (perm) {
                    161:        case PERM_ROOT:
1.10      millert   162:                                if (setreuid(-1, ROOT_UID))
1.11    ! millert   163:                                    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   164:                                if (setuid(ROOT_UID))
1.11    ! millert   165:                                    err(1, "setuid(ROOT_UID)");
        !           166:                                (void) setregid(-1, user_gid);
1.1       millert   167:                                break;
1.2       millert   168:
1.1       millert   169:        case PERM_USER:
1.7       millert   170:                                (void) setregid(-1, user_gid);
1.10      millert   171:                                if (setreuid(ROOT_UID, user_uid))
1.11    ! millert   172:                                    err(1, "setreuid(ROOT_UID, user_uid)");
1.1       millert   173:                                break;
                    174:
1.4       millert   175:        case PERM_FULL_USER:
                    176:                                /* headed for exec() */
                    177:                                (void) setgid(user_gid);
1.7       millert   178:                                if (setreuid(user_uid, user_uid))
1.11    ! millert   179:                                    err(1, "setreuid(user_uid, user_uid)");
1.4       millert   180:                                break;
                    181:
1.1       millert   182:        case PERM_RUNAS:
1.11    ! millert   183:                                (void) setregid(-1, runas_pw->pw_gid);
1.10      millert   184:                                if (setreuid(-1, runas_pw->pw_uid))
1.11    ! millert   185:                                    err(1, "unable to change to runas uid");
1.10      millert   186:                                break;
                    187:
                    188:        case PERM_FULL_RUNAS:
                    189:                                /* headed for exec(), assume euid == ROOT_UID */
1.1       millert   190:                                runas_setup();
1.11    ! millert   191:                                if (setreuid(def_stay_setuid ? user_uid :
        !           192:                                    runas_pw->pw_uid, runas_pw->pw_uid))
        !           193:                                    err(1, "unable to change to runas uid");
1.1       millert   194:                                break;
                    195:
                    196:        case PERM_SUDOERS:
1.10      millert   197:                                /* assume euid == ROOT_UID, ruid == user */
1.7       millert   198:                                if (setregid(-1, SUDOERS_GID))
1.11    ! millert   199:                                    err(1, "unable to change to sudoers gid");
1.1       millert   200:
                    201:                                /*
1.10      millert   202:                                 * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
1.1       millert   203:                                 * is group readable we use a non-zero
                    204:                                 * uid in order to avoid NFS lossage.
                    205:                                 * Using uid 1 is a bit bogus but should
                    206:                                 * work on all OS's.
                    207:                                 */
1.10      millert   208:                                if (SUDOERS_UID == ROOT_UID) {
                    209:                                    if ((SUDOERS_MODE & 040) && setreuid(ROOT_UID, 1))
1.11    ! millert   210:                                        err(1, "setreuid(ROOT_UID, 1)");
1.1       millert   211:                                } else {
1.10      millert   212:                                    if (setreuid(ROOT_UID, SUDOERS_UID))
1.11    ! millert   213:                                        err(1, "setreuid(ROOT_UID, SUDOERS_UID)");
1.1       millert   214:                                }
                    215:                                break;
1.7       millert   216:        case PERM_TIMESTAMP:
1.10      millert   217:                                if (setreuid(ROOT_UID, timestamp_uid))
1.11    ! millert   218:                                    err(1, "setreuid(ROOT_UID, timestamp_uid)");
1.7       millert   219:                                break;
1.1       millert   220:     }
                    221: }
                    222:
1.11    ! millert   223: # else /* !HAVE_SETRESUID && !HAVE_SETREUID */
        !           224: # ifdef HAVE_SETEUID
1.1       millert   225:
                    226: /*
                    227:  * Set real and effective uids and gids based on perm.
                    228:  * NOTE: does not support the "stay_setuid" option.
                    229:  */
                    230: void
1.11    ! millert   231: set_perms(perm)
1.1       millert   232:     int perm;
                    233: {
                    234:     /*
1.11    ! millert   235:      * Since we only have setuid() and seteuid() and semantics
        !           236:      * for these calls differ on various systems, we set
        !           237:      * real and effective uids to ROOT_UID initially to be safe.
1.1       millert   238:      */
1.11    ! millert   239:     if (seteuid(ROOT_UID))
        !           240:        err(1, "seteuid(ROOT_UID)");
1.10      millert   241:     if (setuid(ROOT_UID))
1.11    ! millert   242:        err(1, "setuid(ROOT_UID)");
1.1       millert   243:
                    244:     switch (perm) {
1.11    ! millert   245:        case PERM_ROOT:
        !           246:                                /* uid set above */
        !           247:                                (void) setegid(user_gid);
        !           248:                                break;
        !           249:
1.1       millert   250:        case PERM_USER:
                    251:                                (void) setegid(user_gid);
                    252:                                if (seteuid(user_uid))
1.11    ! millert   253:                                    err(1, "seteuid(user_uid)");
1.4       millert   254:                                break;
                    255:
                    256:        case PERM_FULL_USER:
                    257:                                /* headed for exec() */
                    258:                                (void) setgid(user_gid);
                    259:                                if (setuid(user_uid))
1.11    ! millert   260:                                    err(1, "setuid(user_uid)");
1.1       millert   261:                                break;
                    262:
                    263:        case PERM_RUNAS:
1.11    ! millert   264:                                (void) setegid(runas_pw->pw_gid);
1.10      millert   265:                                if (seteuid(runas_pw->pw_uid))
1.11    ! millert   266:                                    err(1, "unable to change to runas uid");
1.10      millert   267:                                break;
                    268:
                    269:        case PERM_FULL_RUNAS:
1.11    ! millert   270:                                /* headed for exec() */
1.1       millert   271:                                runas_setup();
                    272:                                if (setuid(runas_pw->pw_uid))
1.11    ! millert   273:                                    err(1, "unable to change to runas uid");
1.1       millert   274:                                break;
                    275:
                    276:        case PERM_SUDOERS:
                    277:                                if (setegid(SUDOERS_GID))
1.11    ! millert   278:                                    err(1, "unable to change to sudoers gid");
1.1       millert   279:
                    280:                                /*
1.10      millert   281:                                 * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE
1.1       millert   282:                                 * is group readable we use a non-zero
                    283:                                 * uid in order to avoid NFS lossage.
                    284:                                 * Using uid 1 is a bit bogus but should
                    285:                                 * work on all OS's.
                    286:                                 */
1.10      millert   287:                                if (SUDOERS_UID == ROOT_UID) {
1.1       millert   288:                                    if ((SUDOERS_MODE & 040) && seteuid(1))
1.11    ! millert   289:                                        err(1, "seteuid(1)");
1.1       millert   290:                                } else {
                    291:                                    if (seteuid(SUDOERS_UID))
1.11    ! millert   292:                                        err(1, "seteuid(SUDOERS_UID)");
1.1       millert   293:                                }
                    294:                                break;
1.7       millert   295:        case PERM_TIMESTAMP:
                    296:                                if (seteuid(timestamp_uid))
1.11    ! millert   297:                                    err(1, "seteuid(timestamp_uid)");
1.7       millert   298:                                break;
1.1       millert   299:     }
                    300: }
1.10      millert   301:
1.11    ! millert   302: # else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */
1.10      millert   303:
                    304: /*
                    305:  * Set uids and gids based on perm via setuid() and setgid().
                    306:  * NOTE: does not support the "stay_setuid" or timestampowner options.
                    307:  *       Also, SUDOERS_UID and SUDOERS_GID are not used.
                    308:  */
                    309: void
1.11    ! millert   310: set_perms(perm)
1.10      millert   311:     int perm;
                    312: {
                    313:
                    314:     switch (perm) {
                    315:        case PERM_ROOT:
                    316:                                if (setuid(ROOT_UID))
1.11    ! millert   317:                                        err(1, "setuid(ROOT_UID)");
1.10      millert   318:                                break;
                    319:
                    320:        case PERM_FULL_USER:
                    321:                                (void) setgid(user_gid);
                    322:                                if (setuid(user_uid))
1.11    ! millert   323:                                    err(1, "setuid(user_uid)");
1.10      millert   324:                                break;
                    325:
                    326:        case PERM_FULL_RUNAS:
                    327:                                runas_setup();
                    328:                                if (setuid(runas_pw->pw_uid))
1.11    ! millert   329:                                    err(1, "unable to change to runas uid");
1.10      millert   330:                                break;
                    331:
                    332:        case PERM_USER:
                    333:        case PERM_SUDOERS:
                    334:        case PERM_RUNAS:
                    335:        case PERM_TIMESTAMP:
                    336:                                /* Unsupported since we can't set euid. */
                    337:                                break;
                    338:     }
                    339: }
                    340: #  endif /* HAVE_SETEUID */
1.7       millert   341: # endif /* HAVE_SETREUID */
                    342: #endif /* HAVE_SETRESUID */
1.1       millert   343:
                    344: static void
                    345: runas_setup()
                    346: {
                    347: #ifdef HAVE_LOGIN_CAP_H
1.11    ! millert   348:     int flags;
1.1       millert   349:     extern login_cap_t *lc;
                    350: #endif
                    351:
                    352:     if (runas_pw->pw_name != NULL) {
                    353: #ifdef HAVE_PAM
                    354:        pam_prep_user(runas_pw);
                    355: #endif /* HAVE_PAM */
                    356:
                    357: #ifdef HAVE_LOGIN_CAP_H
1.10      millert   358:        if (def_use_loginclass) {
1.1       millert   359:            /*
                    360:              * We don't have setusercontext() set the user since we
                    361:              * may only want to set the effective uid.  Depending on
                    362:              * sudoers and/or command line arguments we may not want
                    363:              * setusercontext() to call initgroups().
                    364:             */
                    365:            flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
1.10      millert   366:            if (!def_preserve_groups)
                    367:                SET(flags, LOGIN_SETGROUP);
1.1       millert   368:            else if (setgid(runas_pw->pw_gid))
1.11    ! millert   369:                warn("cannot set gid to runas gid");
        !           370:            if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) {
1.10      millert   371:                if (runas_pw->pw_uid != ROOT_UID)
1.11    ! millert   372:                    err(1, "unable to set user context");
1.7       millert   373:                else
1.11    ! millert   374:                    warn("unable to set user context");
1.7       millert   375:            }
1.1       millert   376:        } else
                    377: #endif /* HAVE_LOGIN_CAP_H */
                    378:        {
1.7       millert   379:            if (setgid(runas_pw->pw_gid))
1.11    ! millert   380:                warn("cannot set gid to runas gid");
1.1       millert   381: #ifdef HAVE_INITGROUPS
                    382:            /*
                    383:             * Initialize group vector unless asked not to.
                    384:             */
1.10      millert   385:            if (!def_preserve_groups &&
1.1       millert   386:                initgroups(*user_runas, runas_pw->pw_gid) < 0)
1.11    ! millert   387:                warn("cannot set group vector");
1.1       millert   388: #endif /* HAVE_INITGROUPS */
                    389:        }
                    390:     }
                    391: }