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

1.1       millert     1: /*
                      2:  * Copyright (c) 1994-1996,1998-2001 Todd C. Miller <Todd.Miller@courtesan.com>
                      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.
                     33:  */
                     34:
                     35: #include "config.h"
                     36:
                     37: #include <sys/types.h>
                     38: #include <sys/param.h>
                     39: #include <sys/stat.h>
                     40: #include <stdio.h>
                     41: #ifdef STDC_HEADERS
                     42: # include <stdlib.h>
                     43: # include <stddef.h>
                     44: #else
                     45: # ifdef HAVE_STDLIB_H
                     46: #  include <stdlib.h>
                     47: # endif
                     48: #endif /* STDC_HEADERS */
                     49: #ifdef HAVE_STRING_H
                     50: # include <string.h>
                     51: #else
                     52: # ifdef HAVE_STRINGS_H
                     53: #  include <strings.h>
                     54: # endif
                     55: #endif /* HAVE_STRING_H */
                     56: #ifdef HAVE_UNISTD_H
                     57: # include <unistd.h>
                     58: #endif /* HAVE_UNISTD_H */
                     59: #include <pwd.h>
                     60: #include <errno.h>
                     61: #include <grp.h>
                     62: #ifdef HAVE_LOGIN_CAP_H
                     63: # include <login_cap.h>
                     64: #endif
                     65:
                     66: #include "sudo.h"
                     67:
                     68: #ifndef lint
1.4       millert    69: static const char rcsid[] = "$Sudo: set_perms.c,v 1.11 2002/01/16 21:27:09 millert Exp $";
1.1       millert    70: #endif /* lint */
                     71:
                     72: /*
                     73:  * Prototypes
                     74:  */
                     75: static void runas_setup                __P((void));
                     76: static void fatal              __P((char *));
                     77:
1.3       millert    78: #if !defined(NO_SAVED_IDS) && defined(_SC_SAVED_IDS) && defined(_SC_VERSION)
1.1       millert    79: /*
                     80:  * Set real and effective uids and gids based on perm.
                     81:  * Since we have POSIX saved IDs we can get away with just
                     82:  * toggling the effective uid/gid unless we are headed for an exec().
                     83:  */
                     84: void
                     85: set_perms_posix(perm, sudo_mode)
                     86:     int perm;
                     87:     int sudo_mode;
                     88: {
                     89:     int error;
                     90:
                     91:     switch (perm) {
                     92:        case PERM_ROOT:
                     93:                                if (seteuid(0))
                     94:                                    fatal("seteuid(0)");
                     95:                                break;
1.2       millert    96:
                     97:        case PERM_FULL_ROOT:
                     98:                                /* headed for exec() */
                     99:                                (void) seteuid(0);
                    100:                                if (setuid(0))
                    101:                                    fatal("setuid(0)");
                    102:                                break;
                    103:
1.1       millert   104:        case PERM_USER:
                    105:                                (void) setegid(user_gid);
                    106:                                if (seteuid(user_uid))
                    107:                                    fatal("seteuid(user_uid)");
                    108:                                break;
1.4       millert   109:
                    110:        case PERM_FULL_USER:
                    111:                                /* headed for exec() */
                    112:                                (void) setgid(user_gid);
                    113:                                if (setuid(user_uid))
                    114:                                    fatal("setuid(user_uid)");
                    115:                                break;
1.1       millert   116:
                    117:        case PERM_RUNAS:
                    118:                                /* headed for exec(), assume euid == 0 */
                    119:                                runas_setup();
                    120:                                if (def_flag(I_STAY_SETUID))
                    121:                                    error = seteuid(runas_pw->pw_uid);
                    122:                                else
                    123:                                    error = setuid(runas_pw->pw_uid);
                    124:                                if (error)
                    125:                                    fatal("unable to change to runas uid");
                    126:                                break;
                    127:
                    128:        case PERM_SUDOERS:
                    129:                                /* assume euid == 0, ruid == user */
                    130:                                if (setegid(SUDOERS_GID))
                    131:                                    fatal("unable to change to sudoers gid");
                    132:
                    133:                                /*
                    134:                                 * If SUDOERS_UID == 0 and SUDOERS_MODE
                    135:                                 * is group readable we use a non-zero
                    136:                                 * uid in order to avoid NFS lossage.
                    137:                                 * Using uid 1 is a bit bogus but should
                    138:                                 * work on all OS's.
                    139:                                 */
                    140:                                if (SUDOERS_UID == 0) {
                    141:                                    if ((SUDOERS_MODE & 040) && seteuid(1))
                    142:                                        fatal("seteuid(1)");
                    143:                                } else {
                    144:                                    if (seteuid(SUDOERS_UID))
                    145:                                        fatal("seteuid(SUDOERS_UID)");
                    146:                                }
                    147:                                break;
                    148:     }
                    149: }
1.3       millert   150: #endif /* !NO_SAVED_IDS && _SC_SAVED_IDS && _SC_VERSION */
1.1       millert   151:
                    152: #ifdef HAVE_SETREUID
                    153: /*
                    154:  * Set real and effective uids and gids based on perm.
                    155:  * We always retain a real or effective uid of 0 unless
                    156:  * we are headed for an exec().
                    157:  */
                    158: void
                    159: set_perms_fallback(perm, sudo_mode)
                    160:     int perm;
                    161:     int sudo_mode;
                    162: {
                    163:     int error;
                    164:
                    165:     switch (perm) {
1.2       millert   166:        case PERM_FULL_ROOT:
1.1       millert   167:        case PERM_ROOT:
                    168:                                if (setuid(0))
                    169:                                    fatal("setuid(0)");
                    170:                                break;
1.2       millert   171:
1.1       millert   172:        case PERM_USER:
                    173:                                (void) setegid(user_gid);
                    174:                                if (setreuid(0, user_uid))
                    175:                                    fatal("setreuid(0, user_uid)");
                    176:                                break;
                    177:
1.4       millert   178:        case PERM_FULL_USER:
                    179:                                /* headed for exec() */
                    180:                                (void) setgid(user_gid);
                    181:                                if (setuid(user_uid))
                    182:                                    fatal("setuid(user_uid)");
                    183:                                break;
                    184:
1.1       millert   185:        case PERM_RUNAS:
                    186:                                /* headed for exec(), assume euid == 0 */
                    187:                                runas_setup();
                    188:                                if (def_flag(I_STAY_SETUID))
                    189:                                    error = setreuid(user_uid, runas_pw->pw_uid);
                    190:                                else
                    191:                                    error = setuid(runas_pw->pw_uid);
                    192:                                if (error)
                    193:                                    fatal("unable to change to runas uid");
                    194:                                break;
                    195:
                    196:        case PERM_SUDOERS:
                    197:                                /* assume euid == 0, ruid == user */
                    198:                                if (setegid(SUDOERS_GID))
                    199:                                    fatal("unable to change to sudoers gid");
                    200:
                    201:                                /*
                    202:                                 * If SUDOERS_UID == 0 and SUDOERS_MODE
                    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:                                 */
                    208:                                if (SUDOERS_UID == 0) {
                    209:                                    if ((SUDOERS_MODE & 040) && setreuid(0, 1))
                    210:                                        fatal("setreuid(0, 1)");
                    211:                                } else {
                    212:                                    if (setreuid(0, SUDOERS_UID))
                    213:                                        fatal("setreuid(0, SUDOERS_UID)");
                    214:                                }
                    215:                                break;
                    216:     }
                    217: }
                    218:
                    219: #else
                    220:
                    221: /*
                    222:  * Set real and effective uids and gids based on perm.
                    223:  * NOTE: does not support the "stay_setuid" option.
                    224:  */
                    225: void
                    226: set_perms_fallback(perm, sudo_mode)
                    227:     int perm;
                    228:     int sudo_mode;
                    229: {
                    230:
                    231:     /*
                    232:      * Since we only have setuid() and seteuid() we have to set
                    233:      * real and effective uidss to 0 initially.
                    234:      */
                    235:     if (setuid(0))
                    236:        fatal("setuid(0)");
                    237:
                    238:     switch (perm) {
                    239:        case PERM_USER:
                    240:                                (void) setegid(user_gid);
                    241:                                if (seteuid(user_uid))
                    242:                                    fatal("seteuid(user_uid)");
1.4       millert   243:                                break;
                    244:
                    245:        case PERM_FULL_USER:
                    246:                                /* headed for exec() */
                    247:                                (void) setgid(user_gid);
                    248:                                if (setuid(user_uid))
                    249:                                    fatal("setuid(user_uid)");
1.1       millert   250:                                break;
                    251:
                    252:        case PERM_RUNAS:
                    253:                                /* headed for exec(), assume euid == 0 */
                    254:                                runas_setup();
                    255:                                if (setuid(runas_pw->pw_uid))
                    256:                                    fatal("unable to change to runas uid");
                    257:                                break;
                    258:
                    259:        case PERM_SUDOERS:
                    260:                                /* assume euid == 0, ruid == user */
                    261:                                if (setegid(SUDOERS_GID))
                    262:                                    fatal("unable to change to sudoers gid");
                    263:
                    264:                                /*
                    265:                                 * If SUDOERS_UID == 0 and SUDOERS_MODE
                    266:                                 * is group readable we use a non-zero
                    267:                                 * uid in order to avoid NFS lossage.
                    268:                                 * Using uid 1 is a bit bogus but should
                    269:                                 * work on all OS's.
                    270:                                 */
                    271:                                if (SUDOERS_UID == 0) {
                    272:                                    if ((SUDOERS_MODE & 040) && seteuid(1))
                    273:                                        fatal("seteuid(1)");
                    274:                                } else {
                    275:                                    if (seteuid(SUDOERS_UID))
                    276:                                        fatal("seteuid(SUDOERS_UID)");
                    277:                                }
                    278:                                break;
                    279:     }
                    280: }
                    281: #endif /* HAVE_SETREUID */
                    282:
                    283: static void
                    284: runas_setup()
                    285: {
                    286: #ifdef HAVE_LOGIN_CAP_H
                    287:     int error, flags;
                    288:     extern login_cap_t *lc;
                    289: #endif
                    290:
                    291:     if (runas_pw->pw_name != NULL) {
                    292: #ifdef HAVE_PAM
                    293:        pam_prep_user(runas_pw);
                    294: #endif /* HAVE_PAM */
                    295:
                    296: #ifdef HAVE_LOGIN_CAP_H
                    297:        if (def_flag(I_USE_LOGINCLASS)) {
                    298:            /*
                    299:              * We don't have setusercontext() set the user since we
                    300:              * may only want to set the effective uid.  Depending on
                    301:              * sudoers and/or command line arguments we may not want
                    302:              * setusercontext() to call initgroups().
                    303:             */
                    304:            flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
                    305:            if (!def_flag(I_PRESERVE_GROUPS))
                    306:                flags |= LOGIN_SETGROUP;
                    307:            else if (setgid(runas_pw->pw_gid))
                    308:                perror("cannot set gid to runas gid");
                    309:            error = setusercontext(lc, runas_pw,
                    310:                runas_pw->pw_uid, flags);
                    311:            if (error)
                    312:                perror("unable to set user context");
                    313:        } else
                    314: #endif /* HAVE_LOGIN_CAP_H */
                    315:        {
                    316:            if (setgid(runas_pw->pw_gid))
                    317:                perror("cannot set gid to runas gid");
                    318: #ifdef HAVE_INITGROUPS
                    319:            /*
                    320:             * Initialize group vector unless asked not to.
                    321:             */
                    322:            if (!def_flag(I_PRESERVE_GROUPS) &&
                    323:                initgroups(*user_runas, runas_pw->pw_gid) < 0)
                    324:                perror("cannot set group vector");
                    325: #endif /* HAVE_INITGROUPS */
                    326:        }
                    327:     }
                    328: }
                    329:
                    330: static void
                    331: fatal(str)
                    332:     char *str;
                    333: {
                    334:
                    335:     if (str)
                    336:        perror(str);
                    337:     exit(1);
                    338: }