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

Annotation of src/usr.bin/sudo/env.c, Revision 1.15

1.1       millert     1: /*
1.14      millert     2:  * Copyright (c) 2000-2007 Todd C. Miller <Todd.Miller@courtesan.com>
1.1       millert     3:  *
1.9       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.9       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.7       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.14      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.6       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:
                     52: #include "sudo.h"
                     53:
                     54: #ifndef lint
1.15    ! millert    55: __unused static const char rcsid[] = "$Sudo: env.c,v 1.39.2.16 2007/07/29 20:10:19 millert Exp $";
1.1       millert    56: #endif /* lint */
                     57:
                     58: /*
1.5       millert    59:  * Flags used in rebuild_env()
1.1       millert    60:  */
                     61: #undef DID_TERM
1.14      millert    62: #define DID_TERM       0x0001
1.1       millert    63: #undef DID_PATH
1.14      millert    64: #define DID_PATH       0x0002
1.1       millert    65: #undef DID_HOME
1.14      millert    66: #define DID_HOME       0x0004
1.1       millert    67: #undef DID_SHELL
1.14      millert    68: #define DID_SHELL      0x0008
1.1       millert    69: #undef DID_LOGNAME
1.14      millert    70: #define DID_LOGNAME    0x0010
1.9       millert    71: #undef DID_USER
1.14      millert    72: #define DID_USER       0x0020
                     73: #undef DID_USERNAME
                     74: #define DID_USERNAME           0x0040
                     75: #undef DID_MAX
                     76: #define DID_MAX        0x00ff
                     77:
                     78: #undef KEPT_TERM
                     79: #define KEPT_TERM      0x0100
                     80: #undef KEPT_PATH
                     81: #define KEPT_PATH      0x0200
                     82: #undef KEPT_HOME
                     83: #define KEPT_HOME      0x0400
                     84: #undef KEPT_SHELL
                     85: #define KEPT_SHELL     0x0800
                     86: #undef KEPT_LOGNAME
                     87: #define KEPT_LOGNAME   0x1000
                     88: #undef KEPT_USER
                     89: #define KEPT_USER      0x2000
                     90: #undef KEPT_USERNAME
                     91: #define KEPT_USERNAME  0x4000
                     92: #undef KEPT_MAX
                     93: #define KEPT_MAX       0xff00
1.1       millert    94:
1.9       millert    95: #undef VNULL
                     96: #define        VNULL   (VOID *)NULL
                     97:
1.14      millert    98: struct environment {
                     99:     char **envp;               /* pointer to the new environment */
                    100:     size_t env_size;           /* size of new_environ in char **'s */
                    101:     size_t env_len;            /* number of slots used, not counting NULL */
                    102: };
                    103:
1.1       millert   104: /*
                    105:  * Prototypes
                    106:  */
1.9       millert   107: char **rebuild_env             __P((char **, int, int));
1.14      millert   108: static void insert_env         __P((char *, struct environment *, int));
1.9       millert   109: static char *format_env                __P((char *, ...));
1.1       millert   110:
                    111: /*
1.14      millert   112:  * Copy of the sudo-managed environment.
                    113:  */
                    114: static struct environment env;
                    115:
                    116: /*
1.1       millert   117:  * Default table of "bad" variables to remove from the environment.
                    118:  * XXX - how to omit TERMCAP if it starts with '/'?
                    119:  */
1.5       millert   120: static const char *initial_badenv_table[] = {
1.1       millert   121:     "IFS",
1.11      millert   122:     "CDPATH",
1.1       millert   123:     "LOCALDOMAIN",
                    124:     "RES_OPTIONS",
                    125:     "HOSTALIASES",
                    126:     "NLSPATH",
                    127:     "PATH_LOCALE",
                    128:     "LD_*",
                    129:     "_RLD*",
                    130: #ifdef __hpux
                    131:     "SHLIB_PATH",
                    132: #endif /* __hpux */
                    133: #ifdef _AIX
1.14      millert   134:     "LDR_*",
1.1       millert   135:     "LIBPATH",
1.14      millert   136: #endif
1.5       millert   137: #ifdef __APPLE__
                    138:     "DYLD_*",
                    139: #endif
1.1       millert   140: #ifdef HAVE_KERB4
                    141:     "KRB_CONF*",
1.6       millert   142:     "KRBCONFDIR",
1.1       millert   143:     "KRBTKFILE",
                    144: #endif /* HAVE_KERB4 */
                    145: #ifdef HAVE_KERB5
                    146:     "KRB5_CONFIG*",
1.14      millert   147:     "KRB5_KTNAME",
1.1       millert   148: #endif /* HAVE_KERB5 */
                    149: #ifdef HAVE_SECURID
                    150:     "VAR_ACE",
                    151:     "USR_ACE",
                    152:     "DLC_ACE",
                    153: #endif /* HAVE_SECURID */
1.14      millert   154:     "TERMINFO",                        /* terminfo, exclusive path to terminfo files */
                    155:     "TERMINFO_DIRS",           /* terminfo, path(s) to terminfo files */
                    156:     "TERMPATH",                        /* termcap, path(s) to termcap files */
1.1       millert   157:     "TERMCAP",                 /* XXX - only if it starts with '/' */
1.14      millert   158:     "ENV",                     /* ksh, file to source before script runs */
                    159:     "BASH_ENV",                        /* bash, file to source before script runs */
                    160:     "PS4",                     /* bash, prefix for lines in xtrace mode */
                    161:     "GLOBIGNORE",              /* bash, globbing patterns to ignore */
                    162:     "SHELLOPTS",               /* bash, extra command line options */
                    163:     "JAVA_TOOL_OPTIONS",       /* java, extra command line options */
                    164:     "PERLIO_DEBUG ",           /* perl, debugging output file */
                    165:     "PERLLIB",                 /* perl, search path for modules/includes */
                    166:     "PERL5LIB",                        /* perl 5, search path for modules/includes */
                    167:     "PERL5OPT",                        /* perl 5, extra command line options */
                    168:     "PERL5DB",                 /* perl 5, command used to load debugger */
                    169:     "FPATH",                   /* ksh, search path for functions */
                    170:     "NULLCMD",                 /* zsh, command for null file redirection */
                    171:     "READNULLCMD",             /* zsh, command for null file redirection */
                    172:     "ZDOTDIR",                 /* zsh, search path for dot files */
                    173:     "TMPPREFIX",               /* zsh, prefix for temporary files */
                    174:     "PYTHONHOME",              /* python, module search path */
                    175:     "PYTHONPATH",              /* python, search path */
                    176:     "PYTHONINSPEC",            /* python, allow inspection */
                    177:     "RUBYLIB",                 /* ruby, library load path */
                    178:     "RUBYOPT",                 /* ruby, extra command line options */
1.1       millert   179:     NULL
                    180: };
                    181:
                    182: /*
                    183:  * Default table of variables to check for '%' and '/' characters.
                    184:  */
1.5       millert   185: static const char *initial_checkenv_table[] = {
1.14      millert   186:     "COLORTERM",
1.1       millert   187:     "LANG",
                    188:     "LANGUAGE",
1.14      millert   189:     "LC_*",
                    190:     "LINGUAS",
                    191:     "TERM",
1.1       millert   192:     NULL
                    193: };
                    194:
                    195: /*
1.14      millert   196:  * Default table of variables to preserve in the environment.
1.1       millert   197:  */
1.14      millert   198: static const char *initial_keepenv_table[] = {
                    199:     "COLORS",
                    200:     "DISPLAY",
                    201:     "HOSTNAME",
                    202:     "KRB5CCNAME",
                    203:     "LS_COLORS",
                    204:     "MAIL",
                    205:     "PATH",
                    206:     "PS1",
                    207:     "PS2",
                    208:     "TZ",
                    209:     "XAUTHORITY",
                    210:     "XAUTHORIZATION",
                    211:     NULL
                    212: };
1.1       millert   213:
                    214: /*
                    215:  * Given a variable and value, allocate and format an environment string.
                    216:  */
                    217: static char *
1.9       millert   218: #ifdef __STDC__
                    219: format_env(char *var, ...)
                    220: #else
                    221: format_env(var, va_alist)
1.1       millert   222:     char *var;
1.9       millert   223:     va_dcl
                    224: #endif
1.1       millert   225: {
1.5       millert   226:     char *estring;
1.9       millert   227:     char *val;
1.5       millert   228:     size_t esize;
1.9       millert   229:     va_list ap;
1.1       millert   230:
1.9       millert   231: #ifdef __STDC__
                    232:     va_start(ap, var);
                    233: #else
                    234:     va_start(ap);
                    235: #endif
                    236:     esize = strlen(var) + 2;
                    237:     while ((val = va_arg(ap, char *)) != NULL)
                    238:        esize += strlen(val);
                    239:     va_end(ap);
1.5       millert   240:     estring = (char *) emalloc(esize);
                    241:
1.9       millert   242:     /* Store variable name and the '=' separator.  */
1.5       millert   243:     if (strlcpy(estring, var, esize) >= esize ||
1.9       millert   244:        strlcat(estring, "=", esize) >= esize) {
1.6       millert   245:
                    246:        errx(1, "internal error, format_env() overflow");
1.5       millert   247:     }
1.1       millert   248:
1.9       millert   249:     /* Now store the variable's value (if any) */
                    250: #ifdef __STDC__
                    251:     va_start(ap, var);
                    252: #else
                    253:     va_start(ap);
                    254: #endif
                    255:     while ((val = va_arg(ap, char *)) != NULL) {
                    256:        if (strlcat(estring, val, esize) >= esize)
                    257:            errx(1, "internal error, format_env() overflow");
                    258:     }
                    259:     va_end(ap);
                    260:
1.1       millert   261:     return(estring);
                    262: }
                    263:
                    264: /*
1.14      millert   265:  * Insert str into e->envp, assumes str has an '=' in it.
1.1       millert   266:  */
                    267: static void
1.14      millert   268: insert_env(str, e, dupcheck)
1.1       millert   269:     char *str;
1.14      millert   270:     struct environment *e;
1.5       millert   271:     int dupcheck;
1.1       millert   272: {
1.5       millert   273:     char **nep;
1.1       millert   274:     size_t varlen;
                    275:
1.8       millert   276:     /* Make sure there is room for the new entry plus a NULL. */
1.14      millert   277:     if (e->env_len + 2 > e->env_size) {
                    278:        e->env_size += 128;
                    279:        e->envp = erealloc3(e->envp, e->env_size, sizeof(char *));
1.5       millert   280:     }
                    281:
                    282:     if (dupcheck) {
                    283:            varlen = (strchr(str, '=') - str) + 1;
1.1       millert   284:
1.14      millert   285:            for (nep = e->envp; *nep; nep++) {
1.5       millert   286:                if (strncmp(str, *nep, varlen) == 0) {
                    287:                    *nep = str;
                    288:                    return;
                    289:                }
                    290:            }
                    291:     } else
1.14      millert   292:        nep = e->envp + e->env_len;
1.5       millert   293:
1.14      millert   294:     e->env_len++;
1.5       millert   295:     *nep++ = str;
                    296:     *nep = NULL;
1.1       millert   297: }
                    298:
                    299: /*
1.14      millert   300:  * Check the env_delete blacklist.
                    301:  * Returns TRUE if the variable was found, else false.
                    302:  */
                    303: static int
                    304: matches_env_delete(var)
                    305:     const char *var;
                    306: {
                    307:     struct list_member *cur;
                    308:     size_t len;
                    309:     int iswild, match = FALSE;
                    310:
                    311:     /* Skip anything listed in env_delete. */
                    312:     for (cur = def_env_delete; cur; cur = cur->next) {
                    313:        len = strlen(cur->value);
                    314:        /* Deal with '*' wildcard */
                    315:        if (cur->value[len - 1] == '*') {
                    316:            len--;
                    317:            iswild = TRUE;
                    318:        } else
                    319:            iswild = FALSE;
                    320:        if (strncmp(cur->value, var, len) == 0 &&
                    321:            (iswild || var[len] == '=')) {
                    322:            match = TRUE;
                    323:            break;
                    324:        }
                    325:     }
                    326:     return(match);
                    327: }
                    328:
                    329: /*
                    330:  * Apply the env_check list.
                    331:  * Returns TRUE if the variable is allowed, FALSE if denied
                    332:  * or -1 if no match.
                    333:  */
                    334: static int
                    335: matches_env_check(var)
                    336:     const char *var;
                    337: {
                    338:     struct list_member *cur;
                    339:     size_t len;
                    340:     int iswild, keepit = -1;
                    341:
                    342:     for (cur = def_env_check; cur; cur = cur->next) {
                    343:        len = strlen(cur->value);
                    344:        /* Deal with '*' wildcard */
                    345:        if (cur->value[len - 1] == '*') {
                    346:            len--;
                    347:            iswild = TRUE;
                    348:        } else
                    349:            iswild = FALSE;
                    350:        if (strncmp(cur->value, var, len) == 0 &&
                    351:            (iswild || var[len] == '=')) {
                    352:            keepit = !strpbrk(var, "/%");
                    353:            break;
                    354:        }
                    355:     }
                    356:     return(keepit);
                    357: }
                    358:
                    359: /*
                    360:  * Check the env_keep list.
                    361:  * Returns TRUE if the variable is allowed else FALSE.
                    362:  */
                    363: static int
                    364: matches_env_keep(var)
                    365:     const char *var;
                    366: {
                    367:     struct list_member *cur;
                    368:     size_t len;
                    369:     int iswild, keepit = FALSE;
                    370:
                    371:     for (cur = def_env_keep; cur; cur = cur->next) {
                    372:        len = strlen(cur->value);
                    373:        /* Deal with '*' wildcard */
                    374:        if (cur->value[len - 1] == '*') {
                    375:            len--;
                    376:            iswild = TRUE;
                    377:        } else
                    378:            iswild = FALSE;
                    379:        if (strncmp(cur->value, var, len) == 0 &&
                    380:            (iswild || var[len] == '=')) {
                    381:            keepit = TRUE;
                    382:            break;
                    383:        }
                    384:     }
                    385:     return(keepit);
                    386: }
                    387:
                    388: /*
1.1       millert   389:  * Build a new environment and ether clear potentially dangerous
                    390:  * variables from the old one or start with a clean slate.
                    391:  * Also adds sudo-specific variables (SUDO_*).
                    392:  */
                    393: char **
1.9       millert   394: rebuild_env(envp, sudo_mode, noexec)
                    395:     char **envp;
1.1       millert   396:     int sudo_mode;
1.9       millert   397:     int noexec;
1.1       millert   398: {
1.5       millert   399:     char **ep, *cp, *ps1;
1.14      millert   400:     unsigned int didvar;
1.1       millert   401:
                    402:     /*
                    403:      * Either clean out the environment or reset to a safe default.
                    404:      */
                    405:     ps1 = NULL;
                    406:     didvar = 0;
1.14      millert   407:     memset(&env, 0, sizeof(env));
1.9       millert   408:     if (def_env_reset) {
1.1       millert   409:        /* Pull in vars we want to keep from the old environment. */
                    410:        for (ep = envp; *ep; ep++) {
1.14      millert   411:            int keepit;
1.10      millert   412:
                    413:            /* Skip variables with values beginning with () (bash functions) */
                    414:            if ((cp = strchr(*ep, '=')) != NULL) {
                    415:                if (strncmp(cp, "=() ", 3) == 0)
                    416:                    continue;
                    417:            }
                    418:
1.14      millert   419:            /*
                    420:             * First check certain variables for '%' and '/' characters.
                    421:             * If no match there, check the keep list.
                    422:             * If nothing matched, we remove it from the environment.
                    423:             */
                    424:            keepit = matches_env_check(*ep);
                    425:            if (keepit == -1)
                    426:                keepit = matches_env_keep(*ep);
1.1       millert   427:
                    428:            /* For SUDO_PS1 -> PS1 conversion. */
                    429:            if (strncmp(*ep, "SUDO_PS1=", 8) == 0)
                    430:                ps1 = *ep + 5;
                    431:
                    432:            if (keepit) {
                    433:                /* Preserve variable. */
                    434:                switch (**ep) {
                    435:                    case 'H':
                    436:                        if (strncmp(*ep, "HOME=", 5) == 0)
1.9       millert   437:                            SET(didvar, DID_HOME);
1.5       millert   438:                        break;
1.14      millert   439:                    case 'L':
                    440:                        if (strncmp(*ep, "LOGNAME=", 8) == 0)
                    441:                            SET(didvar, DID_LOGNAME);
                    442:                        break;
                    443:                    case 'P':
                    444:                        if (strncmp(*ep, "PATH=", 5) == 0)
                    445:                            SET(didvar, DID_PATH);
                    446:                        break;
1.1       millert   447:                    case 'S':
                    448:                        if (strncmp(*ep, "SHELL=", 6) == 0)
1.9       millert   449:                            SET(didvar, DID_SHELL);
1.5       millert   450:                        break;
1.14      millert   451:                    case 'T':
                    452:                        if (strncmp(*ep, "TERM=", 5) == 0)
                    453:                            SET(didvar, DID_TERM);
1.5       millert   454:                        break;
1.1       millert   455:                    case 'U':
                    456:                        if (strncmp(*ep, "USER=", 5) == 0)
1.9       millert   457:                            SET(didvar, DID_USER);
1.14      millert   458:                        if (strncmp(*ep, "USERNAME=", 5) == 0)
                    459:                            SET(didvar, DID_USERNAME);
1.5       millert   460:                        break;
1.1       millert   461:                }
1.14      millert   462:                insert_env(*ep, &env, 0);
1.1       millert   463:            }
                    464:        }
1.14      millert   465:        didvar |= didvar << 8;          /* convert DID_* to KEPT_* */
1.1       millert   466:
                    467:        /*
1.9       millert   468:         * Add in defaults.  In -i mode these come from the runas user,
                    469:         * otherwise they may be from the user's environment (depends
                    470:         * on sudoers options).
1.1       millert   471:         */
1.9       millert   472:        if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
1.14      millert   473:            insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), &env,
                    474:                ISSET(didvar, DID_HOME));
                    475:            insert_env(format_env("SHELL", runas_pw->pw_shell, VNULL), &env,
                    476:                ISSET(didvar, DID_SHELL));
                    477:            insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), &env,
                    478:                ISSET(didvar, DID_LOGNAME));
                    479:            insert_env(format_env("USER", runas_pw->pw_name, VNULL), &env,
                    480:                ISSET(didvar, DID_USER));
                    481:            insert_env(format_env("USERNAME", runas_pw->pw_name, VNULL), &env,
                    482:                ISSET(didvar, DID_USERNAME));
1.9       millert   483:        } else {
                    484:            if (!ISSET(didvar, DID_HOME))
1.14      millert   485:                insert_env(format_env("HOME", user_dir, VNULL), &env, 0);
1.9       millert   486:            if (!ISSET(didvar, DID_SHELL))
1.14      millert   487:                insert_env(format_env("SHELL", sudo_user.pw->pw_shell, VNULL),
                    488:                    &env, 0);
1.9       millert   489:            if (!ISSET(didvar, DID_LOGNAME))
1.14      millert   490:                insert_env(format_env("LOGNAME", user_name, VNULL), &env, 0);
1.9       millert   491:            if (!ISSET(didvar, DID_USER))
1.14      millert   492:                insert_env(format_env("USER", user_name, VNULL), &env, 0);
                    493:            if (!ISSET(didvar, DID_USERNAME))
                    494:                insert_env(format_env("USERNAME", user_name, VNULL), &env, 0);
1.9       millert   495:        }
1.1       millert   496:     } else {
                    497:        /*
                    498:         * Copy envp entries as long as they don't match env_delete or
                    499:         * env_check.
                    500:         */
                    501:        for (ep = envp; *ep; ep++) {
1.14      millert   502:            int okvar;
1.10      millert   503:
                    504:            /* Skip variables with values beginning with () (bash functions) */
                    505:            if ((cp = strchr(*ep, '=')) != NULL) {
                    506:                if (strncmp(cp, "=() ", 3) == 0)
                    507:                    continue;
                    508:            }
1.1       millert   509:
1.14      millert   510:            /*
                    511:             * First check variables against the blacklist in env_delete.
                    512:             * If no match there check for '%' and '/' characters.
                    513:             */
                    514:            okvar = matches_env_delete(*ep) != TRUE;
                    515:            if (okvar)
                    516:                okvar = matches_env_check(*ep) != FALSE;
1.1       millert   517:
                    518:            if (okvar) {
                    519:                if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
                    520:                    ps1 = *ep + 5;
                    521:                else if (strncmp(*ep, "PATH=", 5) == 0)
1.9       millert   522:                    SET(didvar, DID_PATH);
1.1       millert   523:                else if (strncmp(*ep, "TERM=", 5) == 0)
1.9       millert   524:                    SET(didvar, DID_TERM);
1.14      millert   525:                insert_env(*ep, &env, 0);
1.1       millert   526:            }
                    527:        }
                    528:     }
                    529:
                    530: #ifdef SECURE_PATH
                    531:     /* Replace the PATH envariable with a secure one. */
1.14      millert   532:     if (!user_is_exempt()) {
                    533:        insert_env(format_env("PATH", SECURE_PATH, VNULL), &env, 1);
                    534:        SET(didvar, DID_PATH);
                    535:     }
1.1       millert   536: #endif
                    537:
1.14      millert   538:     /* Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is true. */
1.9       millert   539:     if (def_set_logname && runas_pw->pw_name) {
1.14      millert   540:        if (!ISSET(didvar, KEPT_LOGNAME))
                    541:            insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), &env, 1);
                    542:        if (!ISSET(didvar, KEPT_USER))
                    543:            insert_env(format_env("USER", runas_pw->pw_name, VNULL), &env, 1);
                    544:        if (!ISSET(didvar, KEPT_USERNAME))
                    545:            insert_env(format_env("USERNAME", runas_pw->pw_name, VNULL), &env, 1);
1.1       millert   546:     }
                    547:
1.9       millert   548:     /* Set $HOME for `sudo -H'.  Only valid at PERM_FULL_RUNAS. */
1.14      millert   549:     if (runas_pw->pw_dir) {
                    550:        if (ISSET(sudo_mode, MODE_RESET_HOME) ||
                    551:            (ISSET(sudo_mode, MODE_RUN) && (def_always_set_home ||
                    552:            (ISSET(sudo_mode, MODE_SHELL) && def_set_home))))
                    553:            insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), &env, 1);
                    554:     }
                    555:
                    556:     /* Provide default values for $TERM and $PATH if they are not set. */
                    557:     if (!ISSET(didvar, DID_TERM))
                    558:        insert_env("TERM=unknown", &env, 0);
                    559:     if (!ISSET(didvar, DID_PATH))
                    560:        insert_env(format_env("PATH", _PATH_DEFPATH, VNULL), &env, 0);
1.9       millert   561:
                    562:     /*
                    563:      * Preload a noexec file?  For a list of LD_PRELOAD-alikes, see
                    564:      * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
                    565:      * XXX - should prepend to original value, if any
                    566:      */
1.12      millert   567:     if (noexec && def_noexec_file != NULL) {
1.9       millert   568: #if defined(__darwin__) || defined(__APPLE__)
1.14      millert   569:        insert_env(format_env("DYLD_INSERT_LIBRARIES", def_noexec_file, VNULL),
                    570:            &env, 1);
                    571:        insert_env(format_env("DYLD_FORCE_FLAT_NAMESPACE", VNULL), &env, 1);
1.9       millert   572: #else
                    573: # if defined(__osf__) || defined(__sgi)
1.14      millert   574:        insert_env(format_env("_RLD_LIST", def_noexec_file, ":DEFAULT", VNULL),
                    575:            &env, 1);
1.9       millert   576: # else
1.14      millert   577: #  ifdef _AIX
                    578:        insert_env(format_env("LDR_PRELOAD", def_noexec_file, VNULL), &env, 1);
                    579: #  else
                    580:        insert_env(format_env("LD_PRELOAD", def_noexec_file, VNULL), &env, 1);
                    581: #  endif /* _AIX */
                    582: # endif /* __osf__ || __sgi */
                    583: #endif /* __darwin__ || __APPLE__ */
1.12      millert   584:     }
1.1       millert   585:
                    586:     /* Set PS1 if SUDO_PS1 is set. */
                    587:     if (ps1)
1.14      millert   588:        insert_env(ps1, &env, 1);
1.1       millert   589:
                    590:     /* Add the SUDO_COMMAND envariable (cmnd + args). */
1.9       millert   591:     if (user_args)
1.14      millert   592:        insert_env(format_env("SUDO_COMMAND", user_cmnd, " ", user_args, VNULL),
                    593:            &env, 1);
1.9       millert   594:     else
1.14      millert   595:        insert_env(format_env("SUDO_COMMAND", user_cmnd, VNULL), &env, 1);
1.1       millert   596:
                    597:     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
1.14      millert   598:     insert_env(format_env("SUDO_USER", user_name, VNULL), &env, 1);
1.5       millert   599:     easprintf(&cp, "SUDO_UID=%lu", (unsigned long) user_uid);
1.14      millert   600:     insert_env(cp, &env, 1);
1.5       millert   601:     easprintf(&cp, "SUDO_GID=%lu", (unsigned long) user_gid);
1.14      millert   602:     insert_env(cp, &env, 1);
                    603:
                    604:     return(env.envp);
                    605: }
                    606:
                    607: char **
                    608: insert_env_vars(envp, env_vars)
                    609:     char **envp;
                    610:     struct list_member *env_vars;
                    611: {
                    612:     struct list_member *cur;
                    613:
                    614:     if (env_vars == NULL)
                    615:        return (envp);
                    616:
                    617:     /*
                    618:      * Make sure we still own the environment and steal it back if not.
                    619:      */
                    620:     if (env.envp != envp) {
                    621:        size_t evlen;
                    622:        char **ep;
                    623:
                    624:        for (ep = envp; *ep != NULL; ep++)
                    625:            continue;
                    626:        evlen = ep - envp;
                    627:        if (evlen + 1 > env.env_size) {
                    628:            efree(env.envp);
                    629:            env.env_size = evlen + 1 + 128;
                    630:            env.envp = emalloc2(env.env_size, sizeof(char *));
                    631:        }
1.15    ! millert   632:        memcpy(env.envp, envp, (evlen + 1) * sizeof(char *));
1.14      millert   633:        env.env_len = evlen;
                    634:     }
                    635:
                    636:     /* Add user-specified environment variables. */
                    637:     for (cur = env_vars; cur != NULL; cur = cur->next)
                    638:        insert_env(cur->value, &env, 1);
                    639:
                    640:     return(env.envp);
                    641: }
                    642:
                    643: /*
                    644:  * Validate the list of environment variables passed in on the command
                    645:  * line against env_delete, env_check, and env_keep.
                    646:  * Calls log_error() if any specified variables are not allowed.
                    647:  */
                    648: void
                    649: validate_env_vars(env_vars)
                    650:     struct list_member *env_vars;
                    651: {
                    652:     struct list_member *var;
                    653:     char *eq, *bad = NULL;
                    654:     size_t len, blen = 0, bsize = 0;
                    655:     int okvar;
1.1       millert   656:
1.14      millert   657:     for (var = env_vars; var != NULL; var = var->next) {
                    658: #ifdef SECURE_PATH
                    659:        if (!user_is_exempt() && strncmp(var->value, "PATH=", 5) == 0) {
                    660:            okvar = FALSE;
                    661:        } else
                    662: #endif
                    663:        if (def_env_reset) {
                    664:            okvar = matches_env_check(var->value);
                    665:            if (okvar == -1)
                    666:                okvar = matches_env_keep(var->value);
                    667:        } else {
                    668:            okvar = matches_env_delete(var->value) == FALSE;
                    669:            if (okvar == FALSE)
                    670:                okvar = matches_env_check(var->value) != FALSE;
                    671:        }
                    672:        if (okvar == FALSE) {
                    673:            /* Not allowed, add to error string, allocating as needed. */
                    674:            if ((eq = strchr(var->value, '=')) != NULL)
                    675:                *eq = '\0';
                    676:            len = strlen(var->value) + 2;
                    677:            if (blen + len >= bsize) {
                    678:                do {
                    679:                    bsize += 1024;
                    680:                } while (blen + len >= bsize);
                    681:                bad = erealloc(bad, bsize);
                    682:                bad[blen] = '\0';
                    683:            }
                    684:            strlcat(bad, var->value, bsize);
                    685:            strlcat(bad, ", ", bsize);
                    686:            blen += len;
                    687:            if (eq != NULL)
                    688:                *eq = '=';
                    689:        }
                    690:     }
                    691:     if (bad != NULL) {
                    692:        bad[blen - 2] = '\0';           /* remove trailing ", " */
                    693:        log_error(NO_MAIL,
                    694:            "sorry, you are not allowed to set the following environment variables: %s", bad);
                    695:        /* NOTREACHED */
                    696:        efree(bad);
                    697:     }
1.1       millert   698: }
                    699:
                    700: void
                    701: init_envtables()
                    702: {
                    703:     struct list_member *cur;
1.5       millert   704:     const char **p;
1.1       millert   705:
1.14      millert   706:     /* Fill in the "env_delete" list. */
1.1       millert   707:     for (p = initial_badenv_table; *p; p++) {
                    708:        cur = emalloc(sizeof(struct list_member));
                    709:        cur->value = estrdup(*p);
1.9       millert   710:        cur->next = def_env_delete;
                    711:        def_env_delete = cur;
1.1       millert   712:     }
                    713:
1.14      millert   714:     /* Fill in the "env_check" list. */
1.1       millert   715:     for (p = initial_checkenv_table; *p; p++) {
                    716:        cur = emalloc(sizeof(struct list_member));
                    717:        cur->value = estrdup(*p);
1.9       millert   718:        cur->next = def_env_check;
                    719:        def_env_check = cur;
1.14      millert   720:     }
                    721:
                    722:     /* Fill in the "env_keep" list. */
                    723:     for (p = initial_keepenv_table; *p; p++) {
                    724:        cur = emalloc(sizeof(struct list_member));
                    725:        cur->value = estrdup(*p);
                    726:        cur->next = def_env_keep;
                    727:        def_env_keep = cur;
1.1       millert   728:     }
                    729: }