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

1.1       millert     1: /*
1.7       millert     2:  * Copyright (c) 1994-1996,1998-2003 Todd C. Miller <Todd.Miller@courtesan.com>
1.1       millert     3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  *
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  *
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * 3. The name of the author may not be used to endorse or promote products
                     17:  *    derived from this software without specific prior written permission.
                     18:  *
                     19:  * 4. Products derived from this software may not be called "Sudo" nor
                     20:  *    may "Sudo" appear in their names without specific prior written
                     21:  *    permission from the author.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     24:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     25:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
                     26:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     27:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     28:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     29:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     30:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     31:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     32:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.8     ! millert    33:  *
        !            34:  * Sponsored in part by the Defense Advanced Research Projects
        !            35:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
        !            36:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
1.1       millert    37:  */
                     38:
                     39: #include "config.h"
                     40:
                     41: #include <sys/types.h>
                     42: #include <sys/param.h>
                     43: #include <sys/stat.h>
                     44: #include <stdio.h>
                     45: #ifdef STDC_HEADERS
                     46: # include <stdlib.h>
                     47: # include <stddef.h>
                     48: #else
                     49: # ifdef HAVE_STDLIB_H
                     50: #  include <stdlib.h>
                     51: # endif
                     52: #endif /* STDC_HEADERS */
                     53: #ifdef HAVE_STRING_H
                     54: # include <string.h>
                     55: #else
                     56: # ifdef HAVE_STRINGS_H
                     57: #  include <strings.h>
                     58: # endif
                     59: #endif /* HAVE_STRING_H */
                     60: #ifdef HAVE_UNISTD_H
                     61: # include <unistd.h>
                     62: #endif /* HAVE_UNISTD_H */
                     63: #include <pwd.h>
                     64: #include <errno.h>
                     65: #include <grp.h>
                     66: #ifdef HAVE_LOGIN_CAP_H
                     67: # include <login_cap.h>
                     68: #endif
                     69:
                     70: #include "sudo.h"
                     71:
                     72: #ifndef lint
1.8     ! millert    73: static const char rcsid[] = "$Sudo: set_perms.c,v 1.21 2003/04/16 00:42:10 millert Exp $";
1.1       millert    74: #endif /* lint */
                     75:
                     76: /*
                     77:  * Prototypes
                     78:  */
                     79: static void runas_setup                __P((void));
1.5       millert    80: static void fatal              __P((char *, int));
1.1       millert    81:
1.7       millert    82: #if !defined(HAVE_SETRESUID) && !defined(HAVE_SETREUID) && \
                     83:     !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
1.1       millert    84: /*
                     85:  * Set real and effective uids and gids based on perm.
                     86:  * Since we have POSIX saved IDs we can get away with just
                     87:  * toggling the effective uid/gid unless we are headed for an exec().
                     88:  */
                     89: void
1.7       millert    90: set_perms_posix(perm)
1.1       millert    91:     int perm;
                     92: {
                     93:     int error;
                     94:
                     95:     switch (perm) {
                     96:        case PERM_ROOT:
                     97:                                if (seteuid(0))
1.5       millert    98:                                    fatal("seteuid(0) failed, your operating system may have broken POSIX saved ID support\nTry running configure with --disable-saved-ids", 0);
1.1       millert    99:                                break;
1.2       millert   100:
                    101:        case PERM_FULL_ROOT:
                    102:                                /* headed for exec() */
                    103:                                (void) seteuid(0);
                    104:                                if (setuid(0))
1.5       millert   105:                                    fatal("setuid(0)", 1);
1.2       millert   106:                                break;
                    107:
1.1       millert   108:        case PERM_USER:
                    109:                                (void) setegid(user_gid);
                    110:                                if (seteuid(user_uid))
1.5       millert   111:                                    fatal("seteuid(user_uid)", 1);
1.1       millert   112:                                break;
1.4       millert   113:
                    114:        case PERM_FULL_USER:
                    115:                                /* headed for exec() */
                    116:                                (void) setgid(user_gid);
                    117:                                if (setuid(user_uid))
1.5       millert   118:                                    fatal("setuid(user_uid)", 1);
1.4       millert   119:                                break;
1.1       millert   120:
                    121:        case PERM_RUNAS:
                    122:                                /* headed for exec(), assume euid == 0 */
                    123:                                runas_setup();
                    124:                                if (def_flag(I_STAY_SETUID))
                    125:                                    error = seteuid(runas_pw->pw_uid);
                    126:                                else
                    127:                                    error = setuid(runas_pw->pw_uid);
                    128:                                if (error)
1.5       millert   129:                                    fatal("unable to change to runas uid", 1);
1.1       millert   130:                                break;
                    131:
                    132:        case PERM_SUDOERS:
                    133:                                /* assume euid == 0, ruid == user */
                    134:                                if (setegid(SUDOERS_GID))
1.5       millert   135:                                    fatal("unable to change to sudoers gid", 1);
1.1       millert   136:
                    137:                                /*
                    138:                                 * If SUDOERS_UID == 0 and SUDOERS_MODE
                    139:                                 * is group readable we use a non-zero
                    140:                                 * uid in order to avoid NFS lossage.
                    141:                                 * Using uid 1 is a bit bogus but should
                    142:                                 * work on all OS's.
                    143:                                 */
                    144:                                if (SUDOERS_UID == 0) {
                    145:                                    if ((SUDOERS_MODE & 040) && seteuid(1))
1.5       millert   146:                                        fatal("seteuid(1)", 1);
1.1       millert   147:                                } else {
                    148:                                    if (seteuid(SUDOERS_UID))
1.5       millert   149:                                        fatal("seteuid(SUDOERS_UID)", 1);
1.1       millert   150:                                }
                    151:                                break;
1.7       millert   152:        case PERM_TIMESTAMP:
                    153:                                if (seteuid(timestamp_uid))
                    154:                                    fatal("seteuid(timestamp_uid)", 1);
                    155:                                break;
                    156:
1.1       millert   157:     }
                    158: }
1.3       millert   159: #endif /* !NO_SAVED_IDS && _SC_SAVED_IDS && _SC_VERSION */
1.1       millert   160:
1.7       millert   161: #ifdef HAVE_SETRESUID
                    162: /*
                    163:  * Set real and effective and saved uids and gids based on perm.
                    164:  * We always retain a saved uid of 0 unless we are headed for an exec().
                    165:  * We only flip the effective gid since it only changes for PERM_SUDOERS.
                    166:  * This version of set_perms() works fine with the "stay_setuid" option.
                    167:  */
                    168: void
                    169: set_perms_suid(perm)
                    170:     int perm;
                    171: {
                    172:     int error;
                    173:
                    174:     switch (perm) {
                    175:        case PERM_FULL_ROOT:
                    176:        case PERM_ROOT:
                    177:                                if (setresuid(0, 0, 0))
                    178:                                    fatal("setresuid(0, 0, 0) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid", 0);
                    179:                                break;
                    180:
                    181:        case PERM_USER:
                    182:                                (void) setresgid(-1, user_gid, -1);
                    183:                                if (setresuid(user_uid, user_uid, 0))
                    184:                                    fatal("setresuid(user_uid, user_uid, 0)", 1);
                    185:                                break;
                    186:
                    187:        case PERM_FULL_USER:
                    188:                                /* headed for exec() */
                    189:                                (void) setgid(user_gid);
                    190:                                if (setresuid(user_uid, user_uid, user_uid))
                    191:                                    fatal("setresuid(user_uid, user_uid, user_uid)", 1);
                    192:                                break;
                    193:
                    194:        case PERM_RUNAS:
                    195:                                /* headed for exec(), assume euid == 0 */
                    196:                                runas_setup();
                    197:                                error = setresuid(def_flag(I_STAY_SETUID) ?
                    198:                                    user_uid : runas_pw->pw_uid,
                    199:                                    runas_pw->pw_uid, runas_pw->pw_uid);
                    200:                                if (error)
                    201:                                    fatal("unable to change to runas uid", 1);
                    202:                                break;
                    203:
                    204:        case PERM_SUDOERS:
                    205:                                /* assume euid == 0, ruid == user */
                    206:                                if (setresgid(-1, SUDOERS_GID, -1))
                    207:                                    fatal("unable to change to sudoers gid", 1);
                    208:
                    209:                                /*
                    210:                                 * If SUDOERS_UID == 0 and SUDOERS_MODE
                    211:                                 * is group readable we use a non-zero
                    212:                                 * uid in order to avoid NFS lossage.
                    213:                                 * Using uid 1 is a bit bogus but should
                    214:                                 * work on all OS's.
                    215:                                 */
                    216:                                if (SUDOERS_UID == 0) {
                    217:                                    if ((SUDOERS_MODE & 040) && setresuid(0, 1, 0))
                    218:                                        fatal("setresuid(0, 1, 0)", 1);
                    219:                                } else {
                    220:                                    if (setresuid(0, SUDOERS_UID, 0))
                    221:                                        fatal("setresuid(0, SUDOERS_UID, 0)", 1);
                    222:                                }
                    223:                                break;
                    224:        case PERM_TIMESTAMP:
                    225:                                if (setresuid(0, timestamp_uid, 0))
                    226:                                    fatal("setresuid(0, timestamp_uid, 0)", 1);
                    227:                                break;
                    228:     }
                    229: }
                    230:
                    231: #else
                    232: # ifdef HAVE_SETREUID
                    233:
1.1       millert   234: /*
                    235:  * Set real and effective uids and gids based on perm.
                    236:  * We always retain a real or effective uid of 0 unless
                    237:  * we are headed for an exec().
1.7       millert   238:  * This version of set_perms() works fine with the "stay_setuid" option.
1.1       millert   239:  */
                    240: void
1.7       millert   241: set_perms_suid(perm)
1.1       millert   242:     int perm;
                    243: {
                    244:     int error;
                    245:
                    246:     switch (perm) {
1.2       millert   247:        case PERM_FULL_ROOT:
1.1       millert   248:        case PERM_ROOT:
1.7       millert   249:                                if (setreuid(0, 0))
                    250:                                    fatal("setreuid(0, 0) failed, your operating system may have a broken setreuid() function\nTry running configure with --disable-setreuid", 0);
1.1       millert   251:                                break;
1.2       millert   252:
1.1       millert   253:        case PERM_USER:
1.7       millert   254:                                (void) setregid(-1, user_gid);
1.1       millert   255:                                if (setreuid(0, user_uid))
1.5       millert   256:                                    fatal("setreuid(0, user_uid)", 1);
1.1       millert   257:                                break;
                    258:
1.4       millert   259:        case PERM_FULL_USER:
                    260:                                /* headed for exec() */
                    261:                                (void) setgid(user_gid);
1.7       millert   262:                                if (setreuid(user_uid, user_uid))
                    263:                                    fatal("setreuid(user_uid, user_uid)", 1);
1.4       millert   264:                                break;
                    265:
1.1       millert   266:        case PERM_RUNAS:
                    267:                                /* headed for exec(), assume euid == 0 */
                    268:                                runas_setup();
1.7       millert   269:                                error = setreuid(def_flag(I_STAY_SETUID) ?
                    270:                                    user_uid : runas_pw->pw_uid,
                    271:                                    runas_pw->pw_uid);
1.1       millert   272:                                if (error)
1.5       millert   273:                                    fatal("unable to change to runas uid", 1);
1.1       millert   274:                                break;
                    275:
                    276:        case PERM_SUDOERS:
                    277:                                /* assume euid == 0, ruid == user */
1.7       millert   278:                                if (setregid(-1, SUDOERS_GID))
1.5       millert   279:                                    fatal("unable to change to sudoers gid", 1);
1.1       millert   280:
                    281:                                /*
                    282:                                 * If SUDOERS_UID == 0 and SUDOERS_MODE
                    283:                                 * is group readable we use a non-zero
                    284:                                 * uid in order to avoid NFS lossage.
                    285:                                 * Using uid 1 is a bit bogus but should
                    286:                                 * work on all OS's.
                    287:                                 */
                    288:                                if (SUDOERS_UID == 0) {
                    289:                                    if ((SUDOERS_MODE & 040) && setreuid(0, 1))
1.5       millert   290:                                        fatal("setreuid(0, 1)", 1);
1.1       millert   291:                                } else {
                    292:                                    if (setreuid(0, SUDOERS_UID))
1.5       millert   293:                                        fatal("setreuid(0, SUDOERS_UID)", 1);
1.1       millert   294:                                }
                    295:                                break;
1.7       millert   296:        case PERM_TIMESTAMP:
                    297:                                if (setreuid(0, timestamp_uid))
                    298:                                    fatal("setreuid(0, timestamp_uid)", 1);
                    299:                                break;
1.1       millert   300:     }
                    301: }
                    302:
1.7       millert   303: # else
1.1       millert   304:
                    305: /*
                    306:  * Set real and effective uids and gids based on perm.
                    307:  * NOTE: does not support the "stay_setuid" option.
                    308:  */
                    309: void
1.7       millert   310: set_perms_nosuid(perm)
1.1       millert   311:     int perm;
                    312: {
                    313:
                    314:     /*
                    315:      * Since we only have setuid() and seteuid() we have to set
1.7       millert   316:      * real and effective uids to 0 initially.
1.1       millert   317:      */
                    318:     if (setuid(0))
1.5       millert   319:        fatal("setuid(0)", 1);
1.1       millert   320:
                    321:     switch (perm) {
                    322:        case PERM_USER:
                    323:                                (void) setegid(user_gid);
                    324:                                if (seteuid(user_uid))
1.5       millert   325:                                    fatal("seteuid(user_uid)", 1);
1.4       millert   326:                                break;
                    327:
                    328:        case PERM_FULL_USER:
                    329:                                /* headed for exec() */
                    330:                                (void) setgid(user_gid);
                    331:                                if (setuid(user_uid))
1.5       millert   332:                                    fatal("setuid(user_uid)", 1);
1.1       millert   333:                                break;
                    334:
                    335:        case PERM_RUNAS:
                    336:                                /* headed for exec(), assume euid == 0 */
                    337:                                runas_setup();
                    338:                                if (setuid(runas_pw->pw_uid))
1.5       millert   339:                                    fatal("unable to change to runas uid", 1);
1.1       millert   340:                                break;
                    341:
                    342:        case PERM_SUDOERS:
                    343:                                /* assume euid == 0, ruid == user */
                    344:                                if (setegid(SUDOERS_GID))
1.5       millert   345:                                    fatal("unable to change to sudoers gid", 1);
1.1       millert   346:
                    347:                                /*
                    348:                                 * If SUDOERS_UID == 0 and SUDOERS_MODE
                    349:                                 * is group readable we use a non-zero
                    350:                                 * uid in order to avoid NFS lossage.
                    351:                                 * Using uid 1 is a bit bogus but should
                    352:                                 * work on all OS's.
                    353:                                 */
                    354:                                if (SUDOERS_UID == 0) {
                    355:                                    if ((SUDOERS_MODE & 040) && seteuid(1))
1.5       millert   356:                                        fatal("seteuid(1)", 1);
1.1       millert   357:                                } else {
                    358:                                    if (seteuid(SUDOERS_UID))
1.5       millert   359:                                        fatal("seteuid(SUDOERS_UID)", 1);
1.1       millert   360:                                }
                    361:                                break;
1.7       millert   362:        case PERM_TIMESTAMP:
                    363:                                if (seteuid(timestamp_uid))
                    364:                                    fatal("seteuid(timestamp_uid)", 1);
                    365:                                break;
1.1       millert   366:     }
                    367: }
1.7       millert   368: # endif /* HAVE_SETREUID */
                    369: #endif /* HAVE_SETRESUID */
1.1       millert   370:
                    371: static void
                    372: runas_setup()
                    373: {
                    374: #ifdef HAVE_LOGIN_CAP_H
                    375:     int error, flags;
                    376:     extern login_cap_t *lc;
                    377: #endif
                    378:
                    379:     if (runas_pw->pw_name != NULL) {
                    380: #ifdef HAVE_PAM
                    381:        pam_prep_user(runas_pw);
                    382: #endif /* HAVE_PAM */
                    383:
                    384: #ifdef HAVE_LOGIN_CAP_H
                    385:        if (def_flag(I_USE_LOGINCLASS)) {
                    386:            /*
                    387:              * We don't have setusercontext() set the user since we
                    388:              * may only want to set the effective uid.  Depending on
                    389:              * sudoers and/or command line arguments we may not want
                    390:              * setusercontext() to call initgroups().
                    391:             */
                    392:            flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
                    393:            if (!def_flag(I_PRESERVE_GROUPS))
                    394:                flags |= LOGIN_SETGROUP;
                    395:            else if (setgid(runas_pw->pw_gid))
                    396:                perror("cannot set gid to runas gid");
                    397:            error = setusercontext(lc, runas_pw,
                    398:                runas_pw->pw_uid, flags);
1.7       millert   399:            if (error) {
                    400:                if (runas_pw->pw_uid != 0)
                    401:                    fatal("unable to set user context", 1);
                    402:                else
                    403:                    perror("unable to set user context");
                    404:            }
1.1       millert   405:        } else
                    406: #endif /* HAVE_LOGIN_CAP_H */
                    407:        {
1.7       millert   408:            if (setgid(runas_pw->pw_gid))
                    409:                perror("cannot set gid to runas gid");
1.1       millert   410: #ifdef HAVE_INITGROUPS
                    411:            /*
                    412:             * Initialize group vector unless asked not to.
                    413:             */
                    414:            if (!def_flag(I_PRESERVE_GROUPS) &&
                    415:                initgroups(*user_runas, runas_pw->pw_gid) < 0)
                    416:                perror("cannot set group vector");
                    417: #endif /* HAVE_INITGROUPS */
                    418:        }
                    419:     }
                    420: }
                    421:
                    422: static void
1.5       millert   423: fatal(str, printerr)
1.1       millert   424:     char *str;
                    425: {
                    426:
1.5       millert   427:     if (str) {
                    428:        if (printerr)
                    429:            perror(str);
                    430:        else {
                    431:            fputs(str, stderr);
                    432:            fputc('\n', stderr);
                    433:        }
                    434:     }
1.1       millert   435:     exit(1);
                    436: }