Annotation of embedaddon/sudo/plugins/sudoers/env.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 2000-2005, 2007-2011
                      3:  *     Todd C. Miller <Todd.Miller@courtesan.com>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  *
                     17:  * Sponsored in part by the Defense Advanced Research Projects
                     18:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
                     19:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
                     20:  */
                     21: 
                     22: #include <config.h>
                     23: 
                     24: #include <sys/types.h>
                     25: #include <sys/param.h>
                     26: #include <sys/stat.h>
                     27: #include <stdio.h>
                     28: #ifdef STDC_HEADERS
                     29: # include <stdlib.h>
                     30: # include <stddef.h>
                     31: #else
                     32: # ifdef HAVE_STDLIB_H
                     33: #  include <stdlib.h>
                     34: # endif
                     35: #endif /* STDC_HEADERS */
                     36: #ifdef HAVE_STRING_H
                     37: # include <string.h>
                     38: #endif /* HAVE_STRING_H */
                     39: #ifdef HAVE_STRINGS_H
                     40: # include <strings.h>
                     41: #endif /* HAVE_STRINGS_H */
                     42: #ifdef HAVE_UNISTD_H
                     43: # include <unistd.h>
                     44: #endif /* HAVE_UNISTD_H */
                     45: #include <ctype.h>
                     46: #include <errno.h>
                     47: #include <pwd.h>
                     48: 
                     49: #include "sudoers.h"
                     50: 
                     51: /*
                     52:  * Flags used in rebuild_env()
                     53:  */
                     54: #undef DID_TERM
                     55: #define DID_TERM       0x0001
                     56: #undef DID_PATH
                     57: #define DID_PATH       0x0002
                     58: #undef DID_HOME
                     59: #define DID_HOME       0x0004
                     60: #undef DID_SHELL
                     61: #define DID_SHELL      0x0008
                     62: #undef DID_LOGNAME
                     63: #define DID_LOGNAME    0x0010
                     64: #undef DID_USER
                     65: #define DID_USER       0x0020
                     66: #undef DID_USERNAME
                     67: #define DID_USERNAME           0x0040
                     68: #undef DID_MAIL
                     69: #define DID_MAIL       0x0080
                     70: #undef DID_MAX
                     71: #define DID_MAX        0x00ff
                     72: 
                     73: #undef KEPT_TERM
                     74: #define KEPT_TERM      0x0100
                     75: #undef KEPT_PATH
                     76: #define KEPT_PATH      0x0200
                     77: #undef KEPT_HOME
                     78: #define KEPT_HOME      0x0400
                     79: #undef KEPT_SHELL
                     80: #define KEPT_SHELL     0x0800
                     81: #undef KEPT_LOGNAME
                     82: #define KEPT_LOGNAME   0x1000
                     83: #undef KEPT_USER
                     84: #define KEPT_USER      0x2000
                     85: #undef KEPT_USERNAME
                     86: #define KEPT_USERNAME  0x4000
                     87: #undef KEPT_MAIL
                     88: #define KEPT_MAIL      0x8000
                     89: #undef KEPT_MAX
                     90: #define KEPT_MAX       0xff00
                     91: 
                     92: struct environment {
                     93:     char **envp;               /* pointer to the new environment */
                     94:     size_t env_size;           /* size of new_environ in char **'s */
                     95:     size_t env_len;            /* number of slots used, not counting NULL */
                     96: };
                     97: 
                     98: /*
                     99:  * Prototypes
                    100:  */
                    101: static void sudo_setenv(const char *, const char *, int);
                    102: static void sudo_putenv(char *, int, int);
                    103: 
                    104: /*
                    105:  * Copy of the sudo-managed environment.
                    106:  */
                    107: static struct environment env;
                    108: 
                    109: /*
                    110:  * Default table of "bad" variables to remove from the environment.
                    111:  * XXX - how to omit TERMCAP if it starts with '/'?
                    112:  */
                    113: static const char *initial_badenv_table[] = {
                    114:     "IFS",
                    115:     "CDPATH",
                    116:     "LOCALDOMAIN",
                    117:     "RES_OPTIONS",
                    118:     "HOSTALIASES",
                    119:     "NLSPATH",
                    120:     "PATH_LOCALE",
                    121:     "LD_*",
                    122:     "_RLD*",
                    123: #ifdef __hpux
                    124:     "SHLIB_PATH",
                    125: #endif /* __hpux */
                    126: #ifdef _AIX
                    127:     "LDR_*",
                    128:     "LIBPATH",
                    129:     "AUTHSTATE",
                    130: #endif
                    131: #ifdef __APPLE__
                    132:     "DYLD_*",
                    133: #endif
                    134: #ifdef HAVE_KERB4
                    135:     "KRB_CONF*",
                    136:     "KRBCONFDIR",
                    137:     "KRBTKFILE",
                    138: #endif /* HAVE_KERB4 */
                    139: #ifdef HAVE_KERB5
                    140:     "KRB5_CONFIG*",
                    141:     "KRB5_KTNAME",
                    142: #endif /* HAVE_KERB5 */
                    143: #ifdef HAVE_SECURID
                    144:     "VAR_ACE",
                    145:     "USR_ACE",
                    146:     "DLC_ACE",
                    147: #endif /* HAVE_SECURID */
                    148:     "TERMINFO",                        /* terminfo, exclusive path to terminfo files */
                    149:     "TERMINFO_DIRS",           /* terminfo, path(s) to terminfo files */
                    150:     "TERMPATH",                        /* termcap, path(s) to termcap files */
                    151:     "TERMCAP",                 /* XXX - only if it starts with '/' */
                    152:     "ENV",                     /* ksh, file to source before script runs */
                    153:     "BASH_ENV",                        /* bash, file to source before script runs */
                    154:     "PS4",                     /* bash, prefix for lines in xtrace mode */
                    155:     "GLOBIGNORE",              /* bash, globbing patterns to ignore */
                    156:     "SHELLOPTS",               /* bash, extra command line options */
                    157:     "JAVA_TOOL_OPTIONS",       /* java, extra command line options */
                    158:     "PERLIO_DEBUG ",           /* perl, debugging output file */
                    159:     "PERLLIB",                 /* perl, search path for modules/includes */
                    160:     "PERL5LIB",                        /* perl 5, search path for modules/includes */
                    161:     "PERL5OPT",                        /* perl 5, extra command line options */
                    162:     "PERL5DB",                 /* perl 5, command used to load debugger */
                    163:     "FPATH",                   /* ksh, search path for functions */
                    164:     "NULLCMD",                 /* zsh, command for null file redirection */
                    165:     "READNULLCMD",             /* zsh, command for null file redirection */
                    166:     "ZDOTDIR",                 /* zsh, search path for dot files */
                    167:     "TMPPREFIX",               /* zsh, prefix for temporary files */
                    168:     "PYTHONHOME",              /* python, module search path */
                    169:     "PYTHONPATH",              /* python, search path */
                    170:     "PYTHONINSPECT",           /* python, allow inspection */
                    171:     "PYTHONUSERBASE",          /* python, per user site-packages directory */
                    172:     "RUBYLIB",                 /* ruby, library load path */
                    173:     "RUBYOPT",                 /* ruby, extra command line options */
                    174:     NULL
                    175: };
                    176: 
                    177: /*
                    178:  * Default table of variables to check for '%' and '/' characters.
                    179:  */
                    180: static const char *initial_checkenv_table[] = {
                    181:     "COLORTERM",
                    182:     "LANG",
                    183:     "LANGUAGE",
                    184:     "LC_*",
                    185:     "LINGUAS",
                    186:     "TERM",
                    187:     NULL
                    188: };
                    189: 
                    190: /*
                    191:  * Default table of variables to preserve in the environment.
                    192:  */
                    193: static const char *initial_keepenv_table[] = {
                    194:     "COLORS",
                    195:     "DISPLAY",
                    196:     "HOSTNAME",
                    197:     "KRB5CCNAME",
                    198:     "LS_COLORS",
                    199:     "PATH",
                    200:     "PS1",
                    201:     "PS2",
                    202:     "TZ",
                    203:     "XAUTHORITY",
                    204:     "XAUTHORIZATION",
                    205: #ifdef _AIX
                    206:     "ODMDIR",
                    207: #endif
                    208:     NULL
                    209: };
                    210: 
                    211: /*
                    212:  * Initialize env based on envp.
                    213:  */
                    214: void
                    215: env_init(char * const envp[])
                    216: {
                    217:     char * const *ep;
                    218:     size_t len;
                    219: 
                    220:     for (ep = envp; *ep != NULL; ep++)
                    221:        continue;
                    222:     len = (size_t)(ep - envp);
                    223: 
                    224:     env.env_len = len;
                    225:     env.env_size = len + 1 + 128;
                    226:     env.envp = emalloc2(env.env_size, sizeof(char *));
                    227: #ifdef ENV_DEBUG
                    228:     memset(env.envp, 0, env.env_size * sizeof(char *));
                    229: #endif
                    230:     memcpy(env.envp, envp, len * sizeof(char *));
                    231:     env.envp[len] = '\0';
                    232: }
                    233: 
                    234: char **
                    235: env_get(void)
                    236: {
                    237:     return env.envp;
                    238: }
                    239: 
                    240: /*
                    241:  * Similar to setenv(3) but operates on sudo's private copy of the environment
                    242:  * (not environ) and it always overwrites.  The dupcheck param determines
                    243:  * whether we need to verify that the variable is not already set.
                    244:  */
                    245: static void
                    246: sudo_setenv(const char *var, const char *val, int dupcheck)
                    247: {
                    248:     char *estring;
                    249:     size_t esize;
                    250: 
                    251:     esize = strlen(var) + 1 + strlen(val) + 1;
                    252:     estring = emalloc(esize);
                    253: 
                    254:     /* Build environment string and insert it. */
                    255:     if (strlcpy(estring, var, esize) >= esize ||
                    256:        strlcat(estring, "=", esize) >= esize ||
                    257:        strlcat(estring, val, esize) >= esize) {
                    258: 
                    259:        errorx(1, _("internal error, sudo_setenv() overflow"));
                    260:     }
                    261:     sudo_putenv(estring, dupcheck, TRUE);
                    262: }
                    263: 
                    264: /*
                    265:  * Similar to putenv(3) but operates on sudo's private copy of the
                    266:  * environment (not environ) and it always overwrites.  The dupcheck param
                    267:  * determines whether we need to verify that the variable is not already set.
                    268:  * Will only overwrite an existing variable if overwrite is set.
                    269:  */
                    270: static void
                    271: sudo_putenv(char *str, int dupcheck, int overwrite)
                    272: {
                    273:     char **ep;
                    274:     size_t len;
                    275:     int found = FALSE;
                    276: 
                    277:     /* Make sure there is room for the new entry plus a NULL. */
                    278:     if (env.env_len + 2 > env.env_size) {
                    279:        env.env_size += 128;
                    280:        env.envp = erealloc3(env.envp, env.env_size, sizeof(char *));
                    281: #ifdef ENV_DEBUG
                    282:        memset(env.envp + env.env_len, 0,
                    283:            (env.env_size - env.env_len) * sizeof(char *));
                    284: #endif
                    285:     }
                    286: 
                    287: #ifdef ENV_DEBUG
                    288:     if (env.envp[env.env_len] != NULL)
                    289:        errorx(1, _("sudo_putenv: corrupted envp, length mismatch"));
                    290: #endif
                    291: 
                    292:     if (dupcheck) {
                    293:        len = (strchr(str, '=') - str) + 1;
                    294:        for (ep = env.envp; !found && *ep != NULL; ep++) {
                    295:            if (strncmp(str, *ep, len) == 0) {
                    296:                if (overwrite)
                    297:                    *ep = str;
                    298:                found = TRUE;
                    299:            }
                    300:        }
                    301:        /* Prune out duplicate variables. */
                    302:        if (found && overwrite) {
                    303:            while (*ep != NULL) {
                    304:                if (strncmp(str, *ep, len) == 0) {
                    305:                    char **cur = ep;
                    306:                    while ((*cur = *(cur + 1)) != NULL)
                    307:                        cur++;
                    308:                } else {
                    309:                    ep++;
                    310:                }
                    311:            }
                    312:            env.env_len = ep - env.envp;
                    313:        }
                    314:     }
                    315: 
                    316:     if (!found) {
                    317:        ep = env.envp + env.env_len;
                    318:        env.env_len++;
                    319:        *ep++ = str;
                    320:        *ep = NULL;
                    321:     }
                    322: }
                    323: 
                    324: /*
                    325:  * Check the env_delete blacklist.
                    326:  * Returns TRUE if the variable was found, else false.
                    327:  */
                    328: static int
                    329: matches_env_delete(const char *var)
                    330: {
                    331:     struct list_member *cur;
                    332:     size_t len;
                    333:     int iswild, match = FALSE;
                    334: 
                    335:     /* Skip anything listed in env_delete. */
                    336:     for (cur = def_env_delete; cur; cur = cur->next) {
                    337:        len = strlen(cur->value);
                    338:        /* Deal with '*' wildcard */
                    339:        if (cur->value[len - 1] == '*') {
                    340:            len--;
                    341:            iswild = TRUE;
                    342:        } else
                    343:            iswild = FALSE;
                    344:        if (strncmp(cur->value, var, len) == 0 &&
                    345:            (iswild || var[len] == '=')) {
                    346:            match = TRUE;
                    347:            break;
                    348:        }
                    349:     }
                    350:     return match;
                    351: }
                    352: 
                    353: /*
                    354:  * Apply the env_check list.
                    355:  * Returns TRUE if the variable is allowed, FALSE if denied
                    356:  * or -1 if no match.
                    357:  */
                    358: static int
                    359: matches_env_check(const char *var)
                    360: {
                    361:     struct list_member *cur;
                    362:     size_t len;
                    363:     int iswild, keepit = -1;
                    364: 
                    365:     for (cur = def_env_check; cur; cur = cur->next) {
                    366:        len = strlen(cur->value);
                    367:        /* Deal with '*' wildcard */
                    368:        if (cur->value[len - 1] == '*') {
                    369:            len--;
                    370:            iswild = TRUE;
                    371:        } else
                    372:            iswild = FALSE;
                    373:        if (strncmp(cur->value, var, len) == 0 &&
                    374:            (iswild || var[len] == '=')) {
                    375:            keepit = !strpbrk(var, "/%");
                    376:            break;
                    377:        }
                    378:     }
                    379:     return keepit;
                    380: }
                    381: 
                    382: /*
                    383:  * Check the env_keep list.
                    384:  * Returns TRUE if the variable is allowed else FALSE.
                    385:  */
                    386: static int
                    387: matches_env_keep(const char *var)
                    388: {
                    389:     struct list_member *cur;
                    390:     size_t len;
                    391:     int iswild, keepit = FALSE;
                    392: 
                    393:     /* Preserve SHELL variable for "sudo -s". */
                    394:     if (ISSET(sudo_mode, MODE_SHELL) && strncmp(var, "SHELL=", 6) == 0)
                    395:        return TRUE;
                    396: 
                    397:     for (cur = def_env_keep; cur; cur = cur->next) {
                    398:        len = strlen(cur->value);
                    399:        /* Deal with '*' wildcard */
                    400:        if (cur->value[len - 1] == '*') {
                    401:            len--;
                    402:            iswild = TRUE;
                    403:        } else
                    404:            iswild = FALSE;
                    405:        if (strncmp(cur->value, var, len) == 0 &&
                    406:            (iswild || var[len] == '=')) {
                    407:            keepit = TRUE;
                    408:            break;
                    409:        }
                    410:     }
                    411:     return keepit;
                    412: }
                    413: 
                    414: /*
                    415:  * Build a new environment and ether clear potentially dangerous
                    416:  * variables from the old one or start with a clean slate.
                    417:  * Also adds sudo-specific variables (SUDO_*).
                    418:  */
                    419: void
                    420: rebuild_env(void)
                    421: {
                    422:     char **old_envp, **ep, *cp, *ps1;
                    423:     char idbuf[MAX_UID_T_LEN];
                    424:     unsigned int didvar;
                    425:     int reset_home = FALSE;
                    426: 
                    427:     /*
                    428:      * Either clean out the environment or reset to a safe default.
                    429:      */
                    430:     ps1 = NULL;
                    431:     didvar = 0;
                    432:     env.env_len = 0;
                    433:     env.env_size = 128;
                    434:     old_envp = env.envp;
                    435:     env.envp = emalloc2(env.env_size, sizeof(char *));
                    436: #ifdef ENV_DEBUG
                    437:     memset(env.envp, 0, env.env_size * sizeof(char *));
                    438: #endif
                    439: 
                    440:     /* Reset HOME based on target user if configured to. */
                    441:     if (ISSET(sudo_mode, MODE_RUN)) {
                    442:        if (def_always_set_home ||
                    443:            ISSET(sudo_mode, MODE_RESET_HOME | MODE_LOGIN_SHELL) || 
                    444:            (ISSET(sudo_mode, MODE_SHELL) && def_set_home))
                    445:            reset_home = TRUE;
                    446:     }
                    447: 
                    448:     if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
                    449:        /* Pull in vars we want to keep from the old environment. */
                    450:        for (ep = old_envp; *ep; ep++) {
                    451:            int keepit;
                    452: 
                    453:            /* Skip variables with values beginning with () (bash functions) */
                    454:            if ((cp = strchr(*ep, '=')) != NULL) {
                    455:                if (strncmp(cp, "=() ", 3) == 0)
                    456:                    continue;
                    457:            }
                    458: 
                    459:            /*
                    460:             * First check certain variables for '%' and '/' characters.
                    461:             * If no match there, check the keep list.
                    462:             * If nothing matched, we remove it from the environment.
                    463:             */
                    464:            keepit = matches_env_check(*ep);
                    465:            if (keepit == -1)
                    466:                keepit = matches_env_keep(*ep);
                    467: 
                    468:            /* For SUDO_PS1 -> PS1 conversion. */
                    469:            if (strncmp(*ep, "SUDO_PS1=", 8) == 0)
                    470:                ps1 = *ep + 5;
                    471: 
                    472:            if (keepit) {
                    473:                /* Preserve variable. */
                    474:                switch (**ep) {
                    475:                    case 'H':
                    476:                        if (strncmp(*ep, "HOME=", 5) == 0)
                    477:                            SET(didvar, DID_HOME);
                    478:                        break;
                    479:                    case 'L':
                    480:                        if (strncmp(*ep, "LOGNAME=", 8) == 0)
                    481:                            SET(didvar, DID_LOGNAME);
                    482:                        break;
                    483:                    case 'M':
                    484:                        if (strncmp(*ep, "MAIL=", 5) == 0)
                    485:                            SET(didvar, DID_MAIL);
                    486:                        break;
                    487:                    case 'P':
                    488:                        if (strncmp(*ep, "PATH=", 5) == 0)
                    489:                            SET(didvar, DID_PATH);
                    490:                        break;
                    491:                    case 'S':
                    492:                        if (strncmp(*ep, "SHELL=", 6) == 0)
                    493:                            SET(didvar, DID_SHELL);
                    494:                        break;
                    495:                    case 'T':
                    496:                        if (strncmp(*ep, "TERM=", 5) == 0)
                    497:                            SET(didvar, DID_TERM);
                    498:                        break;
                    499:                    case 'U':
                    500:                        if (strncmp(*ep, "USER=", 5) == 0)
                    501:                            SET(didvar, DID_USER);
                    502:                        if (strncmp(*ep, "USERNAME=", 5) == 0)
                    503:                            SET(didvar, DID_USERNAME);
                    504:                        break;
                    505:                }
                    506:                sudo_putenv(*ep, FALSE, FALSE);
                    507:            }
                    508:        }
                    509:        didvar |= didvar << 8;          /* convert DID_* to KEPT_* */
                    510: 
                    511:        /*
                    512:         * Add in defaults.  In -i mode these come from the runas user,
                    513:         * otherwise they may be from the user's environment (depends
                    514:         * on sudoers options).
                    515:         */
                    516:        if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
                    517:            sudo_setenv("SHELL", runas_pw->pw_shell, ISSET(didvar, DID_SHELL));
                    518:            sudo_setenv("LOGNAME", runas_pw->pw_name,
                    519:                ISSET(didvar, DID_LOGNAME));
                    520:            sudo_setenv("USER", runas_pw->pw_name, ISSET(didvar, DID_USER));
                    521:            sudo_setenv("USERNAME", runas_pw->pw_name,
                    522:                ISSET(didvar, DID_USERNAME));
                    523:        } else {
                    524:            if (!ISSET(didvar, DID_SHELL))
                    525:                sudo_setenv("SHELL", sudo_user.pw->pw_shell, FALSE);
                    526:            if (!ISSET(didvar, DID_LOGNAME))
                    527:                sudo_setenv("LOGNAME", user_name, FALSE);
                    528:            if (!ISSET(didvar, DID_USER))
                    529:                sudo_setenv("USER", user_name, FALSE);
                    530:            if (!ISSET(didvar, DID_USERNAME))
                    531:                sudo_setenv("USERNAME", user_name, FALSE);
                    532:        }
                    533: 
                    534:        /* If we didn't keep HOME, reset it based on target user. */
                    535:        if (!ISSET(didvar, KEPT_HOME))
                    536:            reset_home = TRUE;
                    537: 
                    538:        /*
                    539:         * Set MAIL to target user in -i mode or if MAIL is not preserved
                    540:         * from user's environment.
                    541:         */
                    542:        if (ISSET(sudo_mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) {
                    543:            cp = _PATH_MAILDIR;
                    544:            if (cp[sizeof(_PATH_MAILDIR) - 2] == '/')
                    545:                easprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name);
                    546:            else
                    547:                easprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name);
                    548:            sudo_putenv(cp, ISSET(didvar, DID_MAIL), TRUE);
                    549:        }
                    550:     } else {
                    551:        /*
                    552:         * Copy environ entries as long as they don't match env_delete or
                    553:         * env_check.
                    554:         */
                    555:        for (ep = old_envp; *ep; ep++) {
                    556:            int okvar;
                    557: 
                    558:            /* Skip variables with values beginning with () (bash functions) */
                    559:            if ((cp = strchr(*ep, '=')) != NULL) {
                    560:                if (strncmp(cp, "=() ", 3) == 0)
                    561:                    continue;
                    562:            }
                    563: 
                    564:            /*
                    565:             * First check variables against the blacklist in env_delete.
                    566:             * If no match there check for '%' and '/' characters.
                    567:             */
                    568:            okvar = matches_env_delete(*ep) != TRUE;
                    569:            if (okvar)
                    570:                okvar = matches_env_check(*ep) != FALSE;
                    571: 
                    572:            if (okvar) {
                    573:                if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
                    574:                    ps1 = *ep + 5;
                    575:                else if (strncmp(*ep, "PATH=", 5) == 0)
                    576:                    SET(didvar, DID_PATH);
                    577:                else if (strncmp(*ep, "TERM=", 5) == 0)
                    578:                    SET(didvar, DID_TERM);
                    579:                sudo_putenv(*ep, FALSE, FALSE);
                    580:            }
                    581:        }
                    582:     }
                    583:     /* Replace the PATH envariable with a secure one? */
                    584:     if (def_secure_path && !user_is_exempt()) {
                    585:        sudo_setenv("PATH", def_secure_path, TRUE);
                    586:        SET(didvar, DID_PATH);
                    587:     }
                    588: 
                    589:     /*
                    590:      * Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is not
                    591:      * disabled.  We skip this if we are running a login shell (because
                    592:      * they have already been set them) or sudoedit (because we want the
                    593:      * editor to find the user's startup files).
                    594:      */
                    595:     if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL|MODE_EDIT)) {
                    596:        if (!ISSET(didvar, KEPT_LOGNAME))
                    597:            sudo_setenv("LOGNAME", runas_pw->pw_name, TRUE);
                    598:        if (!ISSET(didvar, KEPT_USER))
                    599:            sudo_setenv("USER", runas_pw->pw_name, TRUE);
                    600:        if (!ISSET(didvar, KEPT_USERNAME))
                    601:            sudo_setenv("USERNAME", runas_pw->pw_name, TRUE);
                    602:     }
                    603: 
                    604:     /* Set $HOME to target user if not preserving user's value. */
                    605:     if (reset_home)
                    606:        sudo_setenv("HOME", runas_pw->pw_dir, TRUE);
                    607: 
                    608:     /* Provide default values for $TERM and $PATH if they are not set. */
                    609:     if (!ISSET(didvar, DID_TERM))
                    610:        sudo_putenv("TERM=unknown", FALSE, FALSE);
                    611:     if (!ISSET(didvar, DID_PATH))
                    612:        sudo_setenv("PATH", _PATH_STDPATH, FALSE);
                    613: 
                    614:     /* Set PS1 if SUDO_PS1 is set. */
                    615:     if (ps1 != NULL)
                    616:        sudo_putenv(ps1, TRUE, TRUE);
                    617: 
                    618:     /* Add the SUDO_COMMAND envariable (cmnd + args). */
                    619:     if (user_args) {
                    620:        easprintf(&cp, "%s %s", user_cmnd, user_args);
                    621:        sudo_setenv("SUDO_COMMAND", cp, TRUE);
                    622:        efree(cp);
                    623:     } else {
                    624:        sudo_setenv("SUDO_COMMAND", user_cmnd, TRUE);
                    625:     }
                    626: 
                    627:     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
                    628:     sudo_setenv("SUDO_USER", user_name, TRUE);
                    629:     snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_uid);
                    630:     sudo_setenv("SUDO_UID", idbuf, TRUE);
                    631:     snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_gid);
                    632:     sudo_setenv("SUDO_GID", idbuf, TRUE);
                    633: 
                    634:     /* Free old environment. */
                    635:     efree(old_envp);
                    636: }
                    637: 
                    638: void
                    639: insert_env_vars(char * const envp[])
                    640: {
                    641:     char * const *ep;
                    642: 
                    643:     if (envp == NULL)
                    644:        return;
                    645: 
                    646:     /* Add user-specified environment variables. */
                    647:     for (ep = envp; *ep != NULL; ep++)
                    648:        sudo_putenv(*ep, TRUE, TRUE);
                    649: }
                    650: 
                    651: /*
                    652:  * Validate the list of environment variables passed in on the command
                    653:  * line against env_delete, env_check, and env_keep.
                    654:  * Calls log_error() if any specified variables are not allowed.
                    655:  */
                    656: void
                    657: validate_env_vars(char * const env_vars[])
                    658: {
                    659:     char * const *ep;
                    660:     char *eq, *bad = NULL;
                    661:     size_t len, blen = 0, bsize = 0;
                    662:     int okvar;
                    663: 
                    664:     if (env_vars == NULL)
                    665:        return;
                    666: 
                    667:     /* Add user-specified environment variables. */
                    668:     for (ep = env_vars; *ep != NULL; ep++) {
                    669:        if (def_secure_path && !user_is_exempt() &&
                    670:            strncmp(*ep, "PATH=", 5) == 0) {
                    671:            okvar = FALSE;
                    672:        } else if (def_env_reset) {
                    673:            okvar = matches_env_check(*ep);
                    674:            if (okvar == -1)
                    675:                okvar = matches_env_keep(*ep);
                    676:        } else {
                    677:            okvar = matches_env_delete(*ep) == FALSE;
                    678:            if (okvar == FALSE)
                    679:                okvar = matches_env_check(*ep) != FALSE;
                    680:        }
                    681:        if (okvar == FALSE) {
                    682:            /* Not allowed, add to error string, allocating as needed. */
                    683:            if ((eq = strchr(*ep, '=')) != NULL)
                    684:                *eq = '\0';
                    685:            len = strlen(*ep) + 2;
                    686:            if (blen + len >= bsize) {
                    687:                do {
                    688:                    bsize += 1024;
                    689:                } while (blen + len >= bsize);
                    690:                bad = erealloc(bad, bsize);
                    691:                bad[blen] = '\0';
                    692:            }
                    693:            strlcat(bad, *ep, bsize);
                    694:            strlcat(bad, ", ", bsize);
                    695:            blen += len;
                    696:            if (eq != NULL)
                    697:                *eq = '=';
                    698:        }
                    699:     }
                    700:     if (bad != NULL) {
                    701:        bad[blen - 2] = '\0';           /* remove trailing ", " */
                    702:        log_error(NO_MAIL,
                    703:            _("sorry, you are not allowed to set the following environment variables: %s"), bad);
                    704:        /* NOTREACHED */
                    705:        efree(bad);
                    706:     }
                    707: }
                    708: 
                    709: /*
                    710:  * Read in /etc/environment ala AIX and Linux.
                    711:  * Lines may be in either of three formats:
                    712:  *  NAME=VALUE
                    713:  *  NAME="VALUE"
                    714:  *  NAME='VALUE'
                    715:  * with an optional "export" prefix so the shell can source the file.
                    716:  * Invalid lines, blank lines, or lines consisting solely of a comment
                    717:  * character are skipped.
                    718:  */
                    719: void
                    720: read_env_file(const char *path, int overwrite)
                    721: {
                    722:     FILE *fp;
                    723:     char *cp, *var, *val;
                    724:     size_t var_len, val_len;
                    725: 
                    726:     if ((fp = fopen(path, "r")) == NULL)
                    727:        return;
                    728: 
                    729:     while ((var = sudo_parseln(fp)) != NULL) {
                    730:        /* Skip blank or comment lines */
                    731:        if (*var == '\0')
                    732:            continue;
                    733: 
                    734:        /* Skip optional "export " */
                    735:        if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) {
                    736:            var += 7;
                    737:            while (isspace((unsigned char) *var)) {
                    738:                var++;
                    739:            }
                    740:        }
                    741: 
                    742:        /* Must be of the form name=["']value['"] */
                    743:        for (val = var; *val != '\0' && *val != '='; val++)
                    744:            ;
                    745:        if (var == val || *val != '=')
                    746:            continue;
                    747:        var_len = (size_t)(val - var);
                    748:        val_len = strlen(++val);
                    749: 
                    750:        /* Strip leading and trailing single/double quotes */
                    751:        if ((val[0] == '\'' || val[0] == '\"') && val[0] == val[val_len - 1]) {
                    752:            val[val_len - 1] = '\0';
                    753:            val++;
                    754:            val_len -= 2;
                    755:        }
                    756: 
                    757:        cp = emalloc(var_len + 1 + val_len + 1);
                    758:        memcpy(cp, var, var_len + 1); /* includes '=' */
                    759:        memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */
                    760: 
                    761:        sudo_putenv(cp, TRUE, overwrite);
                    762:     }
                    763:     fclose(fp);
                    764: }
                    765: 
                    766: void
                    767: init_envtables(void)
                    768: {
                    769:     struct list_member *cur;
                    770:     const char **p;
                    771: 
                    772:     /* Fill in the "env_delete" list. */
                    773:     for (p = initial_badenv_table; *p; p++) {
                    774:        cur = emalloc(sizeof(struct list_member));
                    775:        cur->value = estrdup(*p);
                    776:        cur->next = def_env_delete;
                    777:        def_env_delete = cur;
                    778:     }
                    779: 
                    780:     /* Fill in the "env_check" list. */
                    781:     for (p = initial_checkenv_table; *p; p++) {
                    782:        cur = emalloc(sizeof(struct list_member));
                    783:        cur->value = estrdup(*p);
                    784:        cur->next = def_env_check;
                    785:        def_env_check = cur;
                    786:     }
                    787: 
                    788:     /* Fill in the "env_keep" list. */
                    789:     for (p = initial_keepenv_table; *p; p++) {
                    790:        cur = emalloc(sizeof(struct list_member));
                    791:        cur->value = estrdup(*p);
                    792:        cur->next = def_env_keep;
                    793:        def_env_keep = cur;
                    794:     }
                    795: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>