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

1.1       misho       1: /*
1.1.1.4   misho       2:  * Copyright (c) 2000-2005, 2007-2013
1.1       misho       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/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: #endif /* HAVE_STRING_H */
                     38: #ifdef HAVE_STRINGS_H
                     39: # include <strings.h>
                     40: #endif /* HAVE_STRINGS_H */
                     41: #ifdef HAVE_UNISTD_H
                     42: # include <unistd.h>
                     43: #endif /* HAVE_UNISTD_H */
1.1.1.3   misho      44: #ifdef HAVE_INTTYPES_H
                     45: # include <inttypes.h>
                     46: #endif
1.1.1.2   misho      47: #ifdef HAVE_LOGIN_CAP_H
                     48: # include <login_cap.h>
                     49: # ifndef LOGIN_SETENV
                     50: #  define LOGIN_SETENV 0
                     51: # endif
                     52: #endif /* HAVE_LOGIN_CAP_H */
1.1       misho      53: #include <ctype.h>
                     54: #include <errno.h>
1.1.1.3   misho      55: #include <limits.h>
1.1       misho      56: #include <pwd.h>
                     57: 
                     58: #include "sudoers.h"
                     59: 
                     60: /*
1.1.1.3   misho      61:  * If there is no SIZE_MAX or SIZE_T_MAX we have to assume that size_t
                     62:  * could be signed (as it is on SunOS 4.x).  This just means that
                     63:  * emalloc2() and erealloc3() cannot allocate huge amounts on such a
                     64:  * platform but that is OK since sudo doesn't need to do so anyway.
                     65:  */
                     66: #ifndef SIZE_MAX
                     67: # ifdef SIZE_T_MAX
                     68: #  define SIZE_MAX     SIZE_T_MAX
                     69: # else
                     70: #  define SIZE_MAX     INT_MAX
                     71: # endif /* SIZE_T_MAX */
                     72: #endif /* SIZE_MAX */
                     73:        
                     74: /*
1.1       misho      75:  * Flags used in rebuild_env()
                     76:  */
                     77: #undef DID_TERM
                     78: #define DID_TERM       0x0001
                     79: #undef DID_PATH
                     80: #define DID_PATH       0x0002
                     81: #undef DID_HOME
                     82: #define DID_HOME       0x0004
                     83: #undef DID_SHELL
                     84: #define DID_SHELL      0x0008
                     85: #undef DID_LOGNAME
                     86: #define DID_LOGNAME    0x0010
                     87: #undef DID_USER
                     88: #define DID_USER       0x0020
                     89: #undef DID_USERNAME
                     90: #define DID_USERNAME           0x0040
                     91: #undef DID_MAIL
                     92: #define DID_MAIL       0x0080
                     93: #undef DID_MAX
                     94: #define DID_MAX        0x00ff
                     95: 
                     96: #undef KEPT_TERM
                     97: #define KEPT_TERM      0x0100
                     98: #undef KEPT_PATH
                     99: #define KEPT_PATH      0x0200
                    100: #undef KEPT_HOME
                    101: #define KEPT_HOME      0x0400
                    102: #undef KEPT_SHELL
                    103: #define KEPT_SHELL     0x0800
                    104: #undef KEPT_LOGNAME
                    105: #define KEPT_LOGNAME   0x1000
                    106: #undef KEPT_USER
                    107: #define KEPT_USER      0x2000
                    108: #undef KEPT_USERNAME
                    109: #define KEPT_USERNAME  0x4000
                    110: #undef KEPT_MAIL
                    111: #define KEPT_MAIL      0x8000
                    112: #undef KEPT_MAX
                    113: #define KEPT_MAX       0xff00
                    114: 
                    115: struct environment {
1.1.1.2   misho     116:     char * const *old_envp;    /* pointer the environment we passed back */
1.1       misho     117:     char **envp;               /* pointer to the new environment */
                    118:     size_t env_size;           /* size of new_environ in char **'s */
                    119:     size_t env_len;            /* number of slots used, not counting NULL */
                    120: };
                    121: 
                    122: /*
                    123:  * Copy of the sudo-managed environment.
                    124:  */
                    125: static struct environment env;
                    126: 
                    127: /*
                    128:  * Default table of "bad" variables to remove from the environment.
                    129:  * XXX - how to omit TERMCAP if it starts with '/'?
                    130:  */
                    131: static const char *initial_badenv_table[] = {
                    132:     "IFS",
                    133:     "CDPATH",
                    134:     "LOCALDOMAIN",
                    135:     "RES_OPTIONS",
                    136:     "HOSTALIASES",
                    137:     "NLSPATH",
                    138:     "PATH_LOCALE",
                    139:     "LD_*",
                    140:     "_RLD*",
                    141: #ifdef __hpux
                    142:     "SHLIB_PATH",
                    143: #endif /* __hpux */
                    144: #ifdef _AIX
                    145:     "LDR_*",
                    146:     "LIBPATH",
                    147:     "AUTHSTATE",
                    148: #endif
                    149: #ifdef __APPLE__
                    150:     "DYLD_*",
                    151: #endif
                    152: #ifdef HAVE_KERB5
                    153:     "KRB5_CONFIG*",
                    154:     "KRB5_KTNAME",
                    155: #endif /* HAVE_KERB5 */
                    156: #ifdef HAVE_SECURID
                    157:     "VAR_ACE",
                    158:     "USR_ACE",
                    159:     "DLC_ACE",
                    160: #endif /* HAVE_SECURID */
                    161:     "TERMINFO",                        /* terminfo, exclusive path to terminfo files */
                    162:     "TERMINFO_DIRS",           /* terminfo, path(s) to terminfo files */
                    163:     "TERMPATH",                        /* termcap, path(s) to termcap files */
                    164:     "TERMCAP",                 /* XXX - only if it starts with '/' */
                    165:     "ENV",                     /* ksh, file to source before script runs */
                    166:     "BASH_ENV",                        /* bash, file to source before script runs */
                    167:     "PS4",                     /* bash, prefix for lines in xtrace mode */
                    168:     "GLOBIGNORE",              /* bash, globbing patterns to ignore */
                    169:     "SHELLOPTS",               /* bash, extra command line options */
                    170:     "JAVA_TOOL_OPTIONS",       /* java, extra command line options */
                    171:     "PERLIO_DEBUG ",           /* perl, debugging output file */
                    172:     "PERLLIB",                 /* perl, search path for modules/includes */
                    173:     "PERL5LIB",                        /* perl 5, search path for modules/includes */
                    174:     "PERL5OPT",                        /* perl 5, extra command line options */
                    175:     "PERL5DB",                 /* perl 5, command used to load debugger */
                    176:     "FPATH",                   /* ksh, search path for functions */
                    177:     "NULLCMD",                 /* zsh, command for null file redirection */
                    178:     "READNULLCMD",             /* zsh, command for null file redirection */
                    179:     "ZDOTDIR",                 /* zsh, search path for dot files */
                    180:     "TMPPREFIX",               /* zsh, prefix for temporary files */
                    181:     "PYTHONHOME",              /* python, module search path */
                    182:     "PYTHONPATH",              /* python, search path */
                    183:     "PYTHONINSPECT",           /* python, allow inspection */
                    184:     "PYTHONUSERBASE",          /* python, per user site-packages directory */
                    185:     "RUBYLIB",                 /* ruby, library load path */
                    186:     "RUBYOPT",                 /* ruby, extra command line options */
                    187:     NULL
                    188: };
                    189: 
                    190: /*
                    191:  * Default table of variables to check for '%' and '/' characters.
                    192:  */
                    193: static const char *initial_checkenv_table[] = {
                    194:     "COLORTERM",
                    195:     "LANG",
                    196:     "LANGUAGE",
                    197:     "LC_*",
                    198:     "LINGUAS",
                    199:     "TERM",
                    200:     NULL
                    201: };
                    202: 
                    203: /*
                    204:  * Default table of variables to preserve in the environment.
                    205:  */
                    206: static const char *initial_keepenv_table[] = {
                    207:     "COLORS",
                    208:     "DISPLAY",
                    209:     "HOSTNAME",
                    210:     "KRB5CCNAME",
                    211:     "LS_COLORS",
                    212:     "PATH",
                    213:     "PS1",
                    214:     "PS2",
                    215:     "TZ",
                    216:     "XAUTHORITY",
                    217:     "XAUTHORIZATION",
                    218:     NULL
                    219: };
                    220: 
                    221: /*
                    222:  * Initialize env based on envp.
                    223:  */
                    224: void
                    225: env_init(char * const envp[])
                    226: {
                    227:     char * const *ep;
                    228:     size_t len;
1.1.1.2   misho     229:     debug_decl(env_init, SUDO_DEBUG_ENV)
1.1       misho     230: 
1.1.1.2   misho     231:     if (envp == NULL) {
                    232:        /* Reset to initial state but keep a pointer to what we allocated. */
                    233:        envp = env.envp;
                    234:        memset(&env, 0, sizeof(env));
                    235:        env.old_envp = envp;
                    236:     } else {
                    237:        /* Make private copy of envp. */
                    238:        for (ep = envp; *ep != NULL; ep++)
                    239:            continue;
                    240:        len = (size_t)(ep - envp);
1.1       misho     241: 
1.1.1.2   misho     242:        env.env_len = len;
                    243:        env.env_size = len + 1 + 128;
                    244:        env.envp = emalloc2(env.env_size, sizeof(char *));
1.1       misho     245: #ifdef ENV_DEBUG
1.1.1.2   misho     246:        memset(env.envp, 0, env.env_size * sizeof(char *));
1.1       misho     247: #endif
1.1.1.2   misho     248:        memcpy(env.envp, envp, len * sizeof(char *));
1.1.1.3   misho     249:        env.envp[len] = NULL;
1.1       misho     250: 
1.1.1.2   misho     251:        /* Free the old envp we allocated, if any. */
                    252:        if (env.old_envp != NULL)
                    253:            efree((void *)env.old_envp);
                    254:     }
                    255: 
                    256:     debug_return;
1.1       misho     257: }
                    258: 
                    259: /*
1.1.1.2   misho     260:  * Getter for private copy of the environment.
1.1       misho     261:  */
1.1.1.2   misho     262: char **
                    263: env_get(void)
1.1       misho     264: {
1.1.1.2   misho     265:     return env.envp;
1.1       misho     266: }
                    267: 
                    268: /*
                    269:  * Similar to putenv(3) but operates on sudo's private copy of the
                    270:  * environment (not environ) and it always overwrites.  The dupcheck param
                    271:  * determines whether we need to verify that the variable is not already set.
                    272:  * Will only overwrite an existing variable if overwrite is set.
1.1.1.2   misho     273:  * Does not include warnings or debugging to avoid recursive calls.
1.1       misho     274:  */
1.1.1.2   misho     275: static int
                    276: sudo_putenv_nodebug(char *str, bool dupcheck, bool overwrite)
1.1       misho     277: {
                    278:     char **ep;
                    279:     size_t len;
1.1.1.2   misho     280:     bool found = false;
1.1       misho     281: 
                    282:     /* Make sure there is room for the new entry plus a NULL. */
1.1.1.3   misho     283:     if (env.env_size > 2 && env.env_len > env.env_size - 2) {
1.1.1.2   misho     284:        char **nenvp;
1.1.1.3   misho     285:        size_t nsize;
                    286: 
                    287:        if (env.env_size > SIZE_MAX - 128) {
1.1.1.6 ! misho     288:            fatalx_nodebug(U_("internal error, %s overflow"),
1.1.1.3   misho     289:                "sudo_putenv_nodebug()");
                    290:        }
                    291:        nsize = env.env_size + 128;
                    292:        if (nsize > SIZE_MAX / sizeof(char *)) {
1.1.1.6 ! misho     293:            fatalx_nodebug(U_("internal error, %s overflow"),
1.1.1.3   misho     294:                "sudo_putenv_nodebug()");
                    295:        }
                    296:        nenvp = realloc(env.envp, nsize * sizeof(char *));
1.1.1.2   misho     297:        if (nenvp == NULL) {
                    298:            errno = ENOMEM;
                    299:            return -1;
                    300:        }
                    301:        env.envp = nenvp;
                    302:        env.env_size = nsize;
1.1       misho     303: #ifdef ENV_DEBUG
                    304:        memset(env.envp + env.env_len, 0,
                    305:            (env.env_size - env.env_len) * sizeof(char *));
                    306: #endif
                    307:     }
                    308: 
                    309: #ifdef ENV_DEBUG
1.1.1.2   misho     310:     if (env.envp[env.env_len] != NULL) {
                    311:        errno = EINVAL;
                    312:        return -1;
                    313:     }
1.1       misho     314: #endif
                    315: 
                    316:     if (dupcheck) {
                    317:        len = (strchr(str, '=') - str) + 1;
1.1.1.3   misho     318:        for (ep = env.envp; *ep != NULL; ep++) {
1.1       misho     319:            if (strncmp(str, *ep, len) == 0) {
                    320:                if (overwrite)
                    321:                    *ep = str;
1.1.1.2   misho     322:                found = true;
1.1.1.3   misho     323:                break;
1.1       misho     324:            }
                    325:        }
1.1.1.3   misho     326:        /* Prune out extra instances of the variable we just overwrote. */
1.1       misho     327:        if (found && overwrite) {
1.1.1.3   misho     328:            while (*++ep != NULL) {
1.1       misho     329:                if (strncmp(str, *ep, len) == 0) {
                    330:                    char **cur = ep;
                    331:                    while ((*cur = *(cur + 1)) != NULL)
                    332:                        cur++;
1.1.1.3   misho     333:                    ep--;
1.1       misho     334:                }
                    335:            }
                    336:            env.env_len = ep - env.envp;
                    337:        }
                    338:     }
                    339: 
                    340:     if (!found) {
                    341:        ep = env.envp + env.env_len;
                    342:        env.env_len++;
                    343:        *ep++ = str;
                    344:        *ep = NULL;
                    345:     }
1.1.1.2   misho     346:     return 0;
1.1       misho     347: }
                    348: 
                    349: /*
1.1.1.2   misho     350:  * Similar to putenv(3) but operates on sudo's private copy of the
                    351:  * environment (not environ) and it always overwrites.  The dupcheck param
                    352:  * determines whether we need to verify that the variable is not already set.
                    353:  * Will only overwrite an existing variable if overwrite is set.
1.1       misho     354:  */
                    355: static int
1.1.1.2   misho     356: sudo_putenv(char *str, bool dupcheck, bool overwrite)
                    357: {
                    358:     int rval;
                    359:     debug_decl(sudo_putenv, SUDO_DEBUG_ENV)
                    360: 
1.1.1.3   misho     361:     sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_putenv: %s", str);
                    362: 
1.1.1.2   misho     363:     rval = sudo_putenv_nodebug(str, dupcheck, overwrite);
                    364:     if (rval == -1) {
                    365: #ifdef ENV_DEBUG
                    366:        if (env.envp[env.env_len] != NULL)
1.1.1.6 ! misho     367:            fatalx(U_("sudo_putenv: corrupted envp, length mismatch"));
1.1.1.2   misho     368: #endif
1.1.1.5   misho     369:        fatal(NULL);
1.1.1.2   misho     370:     }
                    371:     debug_return_int(rval);
                    372: }
                    373: 
                    374: /*
                    375:  * Similar to setenv(3) but operates on a private copy of the environment.
                    376:  * The dupcheck param determines whether we need to verify that the variable
                    377:  * is not already set.
                    378:  */
                    379: static int
                    380: sudo_setenv2(const char *var, const char *val, bool dupcheck, bool overwrite)
                    381: {
                    382:     char *estring;
                    383:     size_t esize;
1.1.1.3   misho     384:     int rval;
1.1.1.2   misho     385:     debug_decl(sudo_setenv2, SUDO_DEBUG_ENV)
                    386: 
                    387:     esize = strlen(var) + 1 + strlen(val) + 1;
                    388:     estring = emalloc(esize);
                    389: 
                    390:     /* Build environment string and insert it. */
                    391:     if (strlcpy(estring, var, esize) >= esize ||
                    392:        strlcat(estring, "=", esize) >= esize ||
                    393:        strlcat(estring, val, esize) >= esize) {
                    394: 
1.1.1.6 ! misho     395:        fatalx(U_("internal error, %s overflow"), "sudo_setenv2()");
1.1.1.2   misho     396:     }
1.1.1.3   misho     397:     rval = sudo_putenv(estring, dupcheck, overwrite);
                    398:     if (rval == -1)
                    399:        efree(estring);
                    400:     debug_return_int(rval);
1.1.1.2   misho     401: }
                    402: 
                    403: /*
                    404:  * Similar to setenv(3) but operates on a private copy of the environment.
1.1.1.4   misho     405:  */
                    406: int
                    407: sudo_setenv(const char *var, const char *val, int overwrite)
                    408: {
                    409:     return sudo_setenv2(var, val, true, (bool)overwrite);
                    410: }
                    411: 
                    412: /*
                    413:  * Similar to setenv(3) but operates on a private copy of the environment.
1.1.1.2   misho     414:  * Does not include warnings or debugging to avoid recursive calls.
                    415:  */
                    416: static int
                    417: sudo_setenv_nodebug(const char *var, const char *val, int overwrite)
                    418: {
1.1.1.4   misho     419:     char *ep, *estring = NULL;
                    420:     const char *cp;
1.1.1.2   misho     421:     size_t esize;
1.1.1.3   misho     422:     int rval = -1;
1.1.1.2   misho     423: 
1.1.1.4   misho     424:     if (var == NULL || *var == '\0') {
                    425:        errno = EINVAL;
1.1.1.3   misho     426:        goto done;
1.1.1.2   misho     427:     }
                    428: 
1.1.1.4   misho     429:     /*
                    430:      * POSIX says a var name with '=' is an error but BSD
                    431:      * just ignores the '=' and anything after it.
                    432:      */
                    433:     for (cp = var; *cp && *cp != '='; cp++)
                    434:        ;
                    435:     esize = (size_t)(cp - var) + 2;
                    436:     if (val) {
                    437:        esize += strlen(val);   /* glibc treats a NULL val as "" */
                    438:     }
1.1.1.2   misho     439: 
1.1.1.4   misho     440:     /* Allocate and fill in estring. */
                    441:     if ((estring = ep = malloc(esize)) == NULL) {
                    442:        errno = ENOMEM;
1.1.1.3   misho     443:        goto done;
1.1.1.2   misho     444:     }
1.1.1.4   misho     445:     for (cp = var; *cp && *cp != '='; cp++)
                    446:        *ep++ = *cp;
                    447:     *ep++ = '=';
                    448:     if (val) {
                    449:        for (cp = val; *cp; cp++)
                    450:            *ep++ = *cp;
                    451:     }
                    452:     *ep = '\0';
                    453: 
1.1.1.3   misho     454:     rval = sudo_putenv_nodebug(estring, true, overwrite);
                    455: done:
                    456:     if (rval == -1)
1.1.1.4   misho     457:        free(estring);
1.1.1.3   misho     458:     return rval;
1.1.1.2   misho     459: }
                    460: 
                    461: /*
                    462:  * Similar to unsetenv(3) but operates on a private copy of the environment.
                    463:  * Does not include warnings or debugging to avoid recursive calls.
                    464:  */
                    465: static int
                    466: sudo_unsetenv_nodebug(const char *var)
                    467: {
                    468:     char **ep = env.envp;
                    469:     size_t len;
                    470: 
                    471:     if (ep == NULL || var == NULL || *var == '\0' || strchr(var, '=') != NULL) {
                    472:        errno = EINVAL;
                    473:        return -1;
                    474:     }
                    475: 
                    476:     len = strlen(var);
                    477:     while (*ep != NULL) {
                    478:        if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') {
                    479:            /* Found it; shift remainder + NULL over by one. */
                    480:            char **cur = ep;
                    481:            while ((*cur = *(cur + 1)) != NULL)
                    482:                cur++;
                    483:            /* Keep going, could be multiple instances of the var. */
                    484:        } else {
                    485:            ep++;
                    486:        }
                    487:     }
                    488:     return 0;
                    489: }
                    490: 
                    491: /*
                    492:  * Similar to unsetenv(3) but operates on a private copy of the environment.
                    493:  */
                    494: int
                    495: sudo_unsetenv(const char *name)
                    496: {
                    497:     int rval;
                    498:     debug_decl(sudo_unsetenv, SUDO_DEBUG_ENV)
                    499: 
1.1.1.3   misho     500:     sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_unsetenv: %s", name);
                    501: 
1.1.1.2   misho     502:     rval = sudo_unsetenv_nodebug(name);
                    503: 
                    504:     debug_return_int(rval);
                    505: }
                    506: 
                    507: /*
                    508:  * Similar to getenv(3) but operates on a private copy of the environment.
                    509:  * Does not include warnings or debugging to avoid recursive calls.
                    510:  */
                    511: static char *
                    512: sudo_getenv_nodebug(const char *name)
                    513: {
                    514:     char **ep, *val = NULL;
                    515:     size_t namelen = 0;
                    516: 
                    517:     if (env.env_len != 0) {
                    518:        /* For BSD compatibility, treat '=' in name like end of string. */
                    519:        while (name[namelen] != '\0' && name[namelen] != '=')
                    520:            namelen++;
                    521:        for (ep = env.envp; *ep != NULL; ep++) {
                    522:            if (strncmp(*ep, name, namelen) == 0 && (*ep)[namelen] == '=') {
                    523:                val = *ep + namelen + 1;
                    524:                break;
                    525:            }
                    526:        }
                    527:     }
                    528:     return val;
                    529: }
                    530: 
                    531: /*
                    532:  * Similar to getenv(3) but operates on a private copy of the environment.
                    533:  */
                    534: char *
                    535: sudo_getenv(const char *name)
                    536: {
                    537:     char *val;
                    538:     debug_decl(sudo_getenv, SUDO_DEBUG_ENV)
                    539: 
1.1.1.3   misho     540:     sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_getenv: %s", name);
                    541: 
1.1.1.2   misho     542:     val = sudo_getenv_nodebug(name);
                    543: 
                    544:     debug_return_str(val);
                    545: }
                    546: 
                    547: /*
                    548:  * Check the env_delete blacklist.
                    549:  * Returns true if the variable was found, else false.
                    550:  */
                    551: static bool
1.1       misho     552: matches_env_delete(const char *var)
                    553: {
                    554:     struct list_member *cur;
                    555:     size_t len;
1.1.1.2   misho     556:     bool iswild;
                    557:     bool match = false;
                    558:     debug_decl(matches_env_delete, SUDO_DEBUG_ENV)
1.1       misho     559: 
                    560:     /* Skip anything listed in env_delete. */
1.1.1.6 ! misho     561:     SLIST_FOREACH(cur, &def_env_delete, entries) {
1.1       misho     562:        len = strlen(cur->value);
                    563:        /* Deal with '*' wildcard */
                    564:        if (cur->value[len - 1] == '*') {
                    565:            len--;
1.1.1.2   misho     566:            iswild = true;
1.1       misho     567:        } else
1.1.1.2   misho     568:            iswild = false;
1.1       misho     569:        if (strncmp(cur->value, var, len) == 0 &&
                    570:            (iswild || var[len] == '=')) {
1.1.1.2   misho     571:            match = true;
1.1       misho     572:            break;
                    573:        }
                    574:     }
1.1.1.2   misho     575:     debug_return_bool(match);
1.1       misho     576: }
                    577: 
                    578: /*
                    579:  * Apply the env_check list.
1.1.1.2   misho     580:  * Returns true if the variable is allowed, false if denied
1.1       misho     581:  * or -1 if no match.
                    582:  */
                    583: static int
                    584: matches_env_check(const char *var)
                    585: {
                    586:     struct list_member *cur;
                    587:     size_t len;
1.1.1.2   misho     588:     bool iswild;
                    589:     int keepit = -1;
                    590:     debug_decl(matches_env_check, SUDO_DEBUG_ENV)
1.1       misho     591: 
1.1.1.6 ! misho     592:     SLIST_FOREACH(cur, &def_env_check, entries) {
1.1       misho     593:        len = strlen(cur->value);
                    594:        /* Deal with '*' wildcard */
                    595:        if (cur->value[len - 1] == '*') {
                    596:            len--;
1.1.1.2   misho     597:            iswild = true;
1.1       misho     598:        } else
1.1.1.2   misho     599:            iswild = false;
1.1       misho     600:        if (strncmp(cur->value, var, len) == 0 &&
                    601:            (iswild || var[len] == '=')) {
                    602:            keepit = !strpbrk(var, "/%");
                    603:            break;
                    604:        }
                    605:     }
1.1.1.2   misho     606:     debug_return_bool(keepit);
1.1       misho     607: }
                    608: 
                    609: /*
                    610:  * Check the env_keep list.
1.1.1.2   misho     611:  * Returns true if the variable is allowed else false.
1.1       misho     612:  */
1.1.1.2   misho     613: static bool
1.1       misho     614: matches_env_keep(const char *var)
                    615: {
                    616:     struct list_member *cur;
                    617:     size_t len;
1.1.1.2   misho     618:     bool iswild, keepit = false;
                    619:     debug_decl(matches_env_keep, SUDO_DEBUG_ENV)
1.1       misho     620: 
                    621:     /* Preserve SHELL variable for "sudo -s". */
1.1.1.2   misho     622:     if (ISSET(sudo_mode, MODE_SHELL) && strncmp(var, "SHELL=", 6) == 0) {
                    623:        keepit = true;
                    624:        goto done;
                    625:     }
1.1       misho     626: 
1.1.1.6 ! misho     627:     SLIST_FOREACH(cur, &def_env_keep, entries) {
1.1       misho     628:        len = strlen(cur->value);
                    629:        /* Deal with '*' wildcard */
                    630:        if (cur->value[len - 1] == '*') {
                    631:            len--;
1.1.1.2   misho     632:            iswild = true;
1.1       misho     633:        } else
1.1.1.2   misho     634:            iswild = false;
1.1       misho     635:        if (strncmp(cur->value, var, len) == 0 &&
                    636:            (iswild || var[len] == '=')) {
1.1.1.2   misho     637:            keepit = true;
1.1       misho     638:            break;
                    639:        }
                    640:     }
1.1.1.2   misho     641: done:
                    642:     debug_return_bool(keepit);
                    643: }
                    644: 
                    645: /*
                    646:  * Look up var in the env_delete and env_check.
                    647:  * Returns true if we should delete the variable, else false.
                    648:  */
                    649: static bool
                    650: env_should_delete(const char *var)
                    651: {
                    652:     int delete_it;
                    653:     debug_decl(env_should_delete, SUDO_DEBUG_ENV);
                    654: 
                    655:     delete_it = matches_env_delete(var);
                    656:     if (!delete_it)
                    657:        delete_it = matches_env_check(var) == false;
1.1.1.3   misho     658: 
                    659:     sudo_debug_printf(SUDO_DEBUG_INFO, "delete %s: %s",
                    660:        var, delete_it ? "YES" : "NO");
1.1.1.2   misho     661:     debug_return_bool(delete_it);
                    662: }
                    663: 
                    664: /*
                    665:  * Lookup var in the env_check and env_keep lists.
                    666:  * Returns true if the variable is allowed else false.
                    667:  */
                    668: static bool
                    669: env_should_keep(const char *var)
                    670: {
                    671:     int keepit;
                    672:     debug_decl(env_should_keep, SUDO_DEBUG_ENV)
                    673: 
                    674:     keepit = matches_env_check(var);
                    675:     if (keepit == -1)
                    676:        keepit = matches_env_keep(var);
                    677: 
1.1.1.3   misho     678:     sudo_debug_printf(SUDO_DEBUG_INFO, "keep %s: %s",
                    679:        var, keepit ? "YES" : "NO");
1.1.1.2   misho     680:     debug_return_bool(keepit == true);
                    681: }
                    682: 
1.1.1.5   misho     683: /*
                    684:  * Merge another environment with our private copy.
                    685:  * Only overwrite an existing variable if it is not
                    686:  * being preserved from the user's environment.
                    687:  */
                    688: void
                    689: env_merge(char * const envp[])
                    690: {
                    691:     char * const *ep;
                    692:     debug_decl(env_merge, SUDO_DEBUG_ENV)
                    693: 
                    694:     for (ep = envp; *ep != NULL; ep++)
                    695:        sudo_putenv(*ep, true, !env_should_keep(*ep));
                    696: 
                    697:     debug_return;
                    698: }
                    699: 
1.1.1.2   misho     700: static void
                    701: env_update_didvar(const char *ep, unsigned int *didvar)
                    702: {
                    703:     switch (*ep) {
                    704:        case 'H':
                    705:            if (strncmp(ep, "HOME=", 5) == 0)
                    706:                SET(*didvar, DID_HOME);
                    707:            break;
                    708:        case 'L':
                    709:            if (strncmp(ep, "LOGNAME=", 8) == 0)
                    710:                SET(*didvar, DID_LOGNAME);
                    711:            break;
                    712:        case 'M':
                    713:            if (strncmp(ep, "MAIL=", 5) == 0)
                    714:                SET(*didvar, DID_MAIL);
                    715:            break;
                    716:        case 'P':
                    717:            if (strncmp(ep, "PATH=", 5) == 0)
                    718:                SET(*didvar, DID_PATH);
                    719:            break;
                    720:        case 'S':
                    721:            if (strncmp(ep, "SHELL=", 6) == 0)
                    722:                SET(*didvar, DID_SHELL);
                    723:            break;
                    724:        case 'T':
                    725:            if (strncmp(ep, "TERM=", 5) == 0)
                    726:                SET(*didvar, DID_TERM);
                    727:            break;
                    728:        case 'U':
                    729:            if (strncmp(ep, "USER=", 5) == 0)
                    730:                SET(*didvar, DID_USER);
                    731:            if (strncmp(ep, "USERNAME=", 5) == 0)
                    732:                SET(*didvar, DID_USERNAME);
                    733:            break;
                    734:     }
1.1       misho     735: }
                    736: 
                    737: /*
                    738:  * Build a new environment and ether clear potentially dangerous
                    739:  * variables from the old one or start with a clean slate.
                    740:  * Also adds sudo-specific variables (SUDO_*).
                    741:  */
                    742: void
                    743: rebuild_env(void)
                    744: {
                    745:     char **old_envp, **ep, *cp, *ps1;
1.1.1.3   misho     746:     char idbuf[MAX_UID_T_LEN + 1];
1.1       misho     747:     unsigned int didvar;
1.1.1.2   misho     748:     bool reset_home = false;
1.1       misho     749: 
                    750:     /*
                    751:      * Either clean out the environment or reset to a safe default.
                    752:      */
                    753:     ps1 = NULL;
                    754:     didvar = 0;
                    755:     env.env_len = 0;
                    756:     env.env_size = 128;
                    757:     old_envp = env.envp;
                    758:     env.envp = emalloc2(env.env_size, sizeof(char *));
                    759: #ifdef ENV_DEBUG
                    760:     memset(env.envp, 0, env.env_size * sizeof(char *));
1.1.1.2   misho     761: #else
                    762:     env.envp[0] = NULL;
1.1       misho     763: #endif
                    764: 
                    765:     /* Reset HOME based on target user if configured to. */
                    766:     if (ISSET(sudo_mode, MODE_RUN)) {
                    767:        if (def_always_set_home ||
                    768:            ISSET(sudo_mode, MODE_RESET_HOME | MODE_LOGIN_SHELL) || 
                    769:            (ISSET(sudo_mode, MODE_SHELL) && def_set_home))
1.1.1.2   misho     770:            reset_home = true;
1.1       misho     771:     }
                    772: 
                    773:     if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
1.1.1.2   misho     774:        /*
                    775:         * If starting with a fresh environment, initialize it based on
                    776:         * /etc/environment or login.conf.  For "sudo -i" we want those
                    777:         * variables to override the invoking user's environment, so we
                    778:         * defer reading them until later.
                    779:         */
                    780:        if (!ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
                    781: #ifdef HAVE_LOGIN_CAP_H
                    782:            /* Insert login class environment variables. */
                    783:            if (login_class) {
                    784:                login_cap_t *lc = login_getclass(login_class);
                    785:                if (lc != NULL) {
                    786:                    setusercontext(lc, runas_pw, runas_pw->pw_uid,
                    787:                        LOGIN_SETPATH|LOGIN_SETENV);
                    788:                    login_close(lc);
                    789:                }
                    790:            }
                    791: #endif /* HAVE_LOGIN_CAP_H */
                    792: #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM))
                    793:            /* Insert system-wide environment variables. */
                    794:            read_env_file(_PATH_ENVIRONMENT, true);
                    795: #endif
                    796:            for (ep = env.envp; *ep; ep++)
                    797:                env_update_didvar(*ep, &didvar);
                    798:        }
                    799: 
1.1       misho     800:        /* Pull in vars we want to keep from the old environment. */
                    801:        for (ep = old_envp; *ep; ep++) {
1.1.1.2   misho     802:            bool keepit;
1.1       misho     803: 
                    804:            /* Skip variables with values beginning with () (bash functions) */
                    805:            if ((cp = strchr(*ep, '=')) != NULL) {
                    806:                if (strncmp(cp, "=() ", 3) == 0)
                    807:                    continue;
                    808:            }
                    809: 
                    810:            /*
1.1.1.2   misho     811:             * Look up the variable in the env_check and env_keep lists.
1.1       misho     812:             */
1.1.1.2   misho     813:            keepit = env_should_keep(*ep);
1.1       misho     814: 
1.1.1.2   misho     815:            /*
                    816:             * Do SUDO_PS1 -> PS1 conversion.
                    817:             * This must happen *after* env_should_keep() is called.
                    818:             */
1.1       misho     819:            if (strncmp(*ep, "SUDO_PS1=", 8) == 0)
                    820:                ps1 = *ep + 5;
                    821: 
                    822:            if (keepit) {
                    823:                /* Preserve variable. */
1.1.1.2   misho     824:                sudo_putenv(*ep, false, false);
                    825:                env_update_didvar(*ep, &didvar);
1.1       misho     826:            }
                    827:        }
                    828:        didvar |= didvar << 8;          /* convert DID_* to KEPT_* */
                    829: 
                    830:        /*
                    831:         * Add in defaults.  In -i mode these come from the runas user,
                    832:         * otherwise they may be from the user's environment (depends
                    833:         * on sudoers options).
                    834:         */
                    835:        if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
1.1.1.2   misho     836:            sudo_setenv2("SHELL", runas_pw->pw_shell,
                    837:                ISSET(didvar, DID_SHELL), true);
                    838:            sudo_setenv2("LOGNAME", runas_pw->pw_name,
                    839:                ISSET(didvar, DID_LOGNAME), true);
                    840:            sudo_setenv2("USER", runas_pw->pw_name,
                    841:                ISSET(didvar, DID_USER), true);
                    842:            sudo_setenv2("USERNAME", runas_pw->pw_name,
                    843:                ISSET(didvar, DID_USERNAME), true);
1.1       misho     844:        } else {
                    845:            if (!ISSET(didvar, DID_SHELL))
1.1.1.2   misho     846:                sudo_setenv2("SHELL", sudo_user.pw->pw_shell, false, true);
1.1.1.3   misho     847:            /* We will set LOGNAME later in the !def_set_logname case. */
                    848:            if (!def_set_logname) {
                    849:                if (!ISSET(didvar, DID_LOGNAME))
                    850:                    sudo_setenv2("LOGNAME", user_name, false, true);
                    851:                if (!ISSET(didvar, DID_USER))
                    852:                    sudo_setenv2("USER", user_name, false, true);
                    853:                if (!ISSET(didvar, DID_USERNAME))
                    854:                    sudo_setenv2("USERNAME", user_name, false, true);
                    855:            }
1.1       misho     856:        }
                    857: 
                    858:        /* If we didn't keep HOME, reset it based on target user. */
                    859:        if (!ISSET(didvar, KEPT_HOME))
1.1.1.2   misho     860:            reset_home = true;
1.1       misho     861: 
                    862:        /*
                    863:         * Set MAIL to target user in -i mode or if MAIL is not preserved
                    864:         * from user's environment.
                    865:         */
                    866:        if (ISSET(sudo_mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) {
                    867:            cp = _PATH_MAILDIR;
                    868:            if (cp[sizeof(_PATH_MAILDIR) - 2] == '/')
                    869:                easprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name);
                    870:            else
                    871:                easprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name);
1.1.1.2   misho     872:            sudo_putenv(cp, ISSET(didvar, DID_MAIL), true);
1.1       misho     873:        }
                    874:     } else {
                    875:        /*
                    876:         * Copy environ entries as long as they don't match env_delete or
                    877:         * env_check.
                    878:         */
                    879:        for (ep = old_envp; *ep; ep++) {
                    880:            /* Skip variables with values beginning with () (bash functions) */
                    881:            if ((cp = strchr(*ep, '=')) != NULL) {
                    882:                if (strncmp(cp, "=() ", 3) == 0)
                    883:                    continue;
                    884:            }
                    885: 
1.1.1.2   misho     886:            /* Add variable unless it matches a black list. */
                    887:            if (!env_should_delete(*ep)) {
1.1       misho     888:                if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
                    889:                    ps1 = *ep + 5;
                    890:                else if (strncmp(*ep, "PATH=", 5) == 0)
                    891:                    SET(didvar, DID_PATH);
                    892:                else if (strncmp(*ep, "TERM=", 5) == 0)
                    893:                    SET(didvar, DID_TERM);
1.1.1.2   misho     894:                sudo_putenv(*ep, false, false);
1.1       misho     895:            }
                    896:        }
                    897:     }
                    898:     /* Replace the PATH envariable with a secure one? */
                    899:     if (def_secure_path && !user_is_exempt()) {
1.1.1.2   misho     900:        sudo_setenv2("PATH", def_secure_path, true, true);
1.1       misho     901:        SET(didvar, DID_PATH);
                    902:     }
                    903: 
                    904:     /*
                    905:      * Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is not
                    906:      * disabled.  We skip this if we are running a login shell (because
1.1.1.3   misho     907:      * they have already been set) or sudoedit (because we want the editor
                    908:      * to find the invoking user's startup files).
1.1       misho     909:      */
                    910:     if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL|MODE_EDIT)) {
                    911:        if (!ISSET(didvar, KEPT_LOGNAME))
1.1.1.2   misho     912:            sudo_setenv2("LOGNAME", runas_pw->pw_name, true, true);
1.1       misho     913:        if (!ISSET(didvar, KEPT_USER))
1.1.1.2   misho     914:            sudo_setenv2("USER", runas_pw->pw_name, true, true);
1.1       misho     915:        if (!ISSET(didvar, KEPT_USERNAME))
1.1.1.2   misho     916:            sudo_setenv2("USERNAME", runas_pw->pw_name, true, true);
1.1       misho     917:     }
                    918: 
                    919:     /* Set $HOME to target user if not preserving user's value. */
                    920:     if (reset_home)
1.1.1.2   misho     921:        sudo_setenv2("HOME", runas_pw->pw_dir, true, true);
1.1       misho     922: 
                    923:     /* Provide default values for $TERM and $PATH if they are not set. */
                    924:     if (!ISSET(didvar, DID_TERM))
1.1.1.2   misho     925:        sudo_putenv("TERM=unknown", false, false);
1.1       misho     926:     if (!ISSET(didvar, DID_PATH))
1.1.1.2   misho     927:        sudo_setenv2("PATH", _PATH_STDPATH, false, true);
1.1       misho     928: 
                    929:     /* Set PS1 if SUDO_PS1 is set. */
                    930:     if (ps1 != NULL)
1.1.1.2   misho     931:        sudo_putenv(ps1, true, true);
1.1       misho     932: 
                    933:     /* Add the SUDO_COMMAND envariable (cmnd + args). */
                    934:     if (user_args) {
                    935:        easprintf(&cp, "%s %s", user_cmnd, user_args);
1.1.1.2   misho     936:        sudo_setenv2("SUDO_COMMAND", cp, true, true);
1.1       misho     937:        efree(cp);
                    938:     } else {
1.1.1.2   misho     939:        sudo_setenv2("SUDO_COMMAND", user_cmnd, true, true);
1.1       misho     940:     }
                    941: 
                    942:     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
1.1.1.2   misho     943:     sudo_setenv2("SUDO_USER", user_name, true, true);
1.1       misho     944:     snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_uid);
1.1.1.2   misho     945:     sudo_setenv2("SUDO_UID", idbuf, true, true);
1.1       misho     946:     snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_gid);
1.1.1.2   misho     947:     sudo_setenv2("SUDO_GID", idbuf, true, true);
1.1       misho     948: 
                    949:     /* Free old environment. */
                    950:     efree(old_envp);
                    951: }
                    952: 
                    953: void
                    954: insert_env_vars(char * const envp[])
                    955: {
                    956:     char * const *ep;
                    957: 
                    958:     if (envp == NULL)
                    959:        return;
                    960: 
                    961:     /* Add user-specified environment variables. */
                    962:     for (ep = envp; *ep != NULL; ep++)
1.1.1.2   misho     963:        sudo_putenv(*ep, true, true);
1.1       misho     964: }
                    965: 
                    966: /*
                    967:  * Validate the list of environment variables passed in on the command
                    968:  * line against env_delete, env_check, and env_keep.
1.1.1.2   misho     969:  * Calls log_fatal() if any specified variables are not allowed.
1.1       misho     970:  */
                    971: void
                    972: validate_env_vars(char * const env_vars[])
                    973: {
                    974:     char * const *ep;
                    975:     char *eq, *bad = NULL;
                    976:     size_t len, blen = 0, bsize = 0;
1.1.1.2   misho     977:     bool okvar;
1.1       misho     978: 
                    979:     if (env_vars == NULL)
                    980:        return;
                    981: 
                    982:     /* Add user-specified environment variables. */
                    983:     for (ep = env_vars; *ep != NULL; ep++) {
                    984:        if (def_secure_path && !user_is_exempt() &&
                    985:            strncmp(*ep, "PATH=", 5) == 0) {
1.1.1.2   misho     986:            okvar = false;
1.1       misho     987:        } else if (def_env_reset) {
1.1.1.2   misho     988:            okvar = env_should_keep(*ep);
1.1       misho     989:        } else {
1.1.1.2   misho     990:            okvar = !env_should_delete(*ep);
1.1       misho     991:        }
1.1.1.2   misho     992:        if (okvar == false) {
1.1       misho     993:            /* Not allowed, add to error string, allocating as needed. */
                    994:            if ((eq = strchr(*ep, '=')) != NULL)
                    995:                *eq = '\0';
                    996:            len = strlen(*ep) + 2;
                    997:            if (blen + len >= bsize) {
                    998:                do {
                    999:                    bsize += 1024;
                   1000:                } while (blen + len >= bsize);
                   1001:                bad = erealloc(bad, bsize);
                   1002:                bad[blen] = '\0';
                   1003:            }
                   1004:            strlcat(bad, *ep, bsize);
                   1005:            strlcat(bad, ", ", bsize);
                   1006:            blen += len;
                   1007:            if (eq != NULL)
                   1008:                *eq = '=';
                   1009:        }
                   1010:     }
                   1011:     if (bad != NULL) {
                   1012:        bad[blen - 2] = '\0';           /* remove trailing ", " */
1.1.1.2   misho    1013:        log_fatal(NO_MAIL,
1.1.1.4   misho    1014:            N_("sorry, you are not allowed to set the following environment variables: %s"), bad);
1.1       misho    1015:        /* NOTREACHED */
                   1016:        efree(bad);
                   1017:     }
                   1018: }
                   1019: 
                   1020: /*
                   1021:  * Read in /etc/environment ala AIX and Linux.
                   1022:  * Lines may be in either of three formats:
                   1023:  *  NAME=VALUE
                   1024:  *  NAME="VALUE"
                   1025:  *  NAME='VALUE'
                   1026:  * with an optional "export" prefix so the shell can source the file.
                   1027:  * Invalid lines, blank lines, or lines consisting solely of a comment
                   1028:  * character are skipped.
                   1029:  */
                   1030: void
                   1031: read_env_file(const char *path, int overwrite)
                   1032: {
                   1033:     FILE *fp;
1.1.1.4   misho    1034:     char *cp, *var, *val, *line = NULL;
                   1035:     size_t var_len, val_len, linesize = 0;
1.1       misho    1036: 
                   1037:     if ((fp = fopen(path, "r")) == NULL)
                   1038:        return;
                   1039: 
1.1.1.4   misho    1040:     while (sudo_parseln(&line, &linesize, NULL, fp) != -1) {
1.1       misho    1041:        /* Skip blank or comment lines */
1.1.1.4   misho    1042:        if (*(var = line) == '\0')
1.1       misho    1043:            continue;
                   1044: 
                   1045:        /* Skip optional "export " */
                   1046:        if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) {
                   1047:            var += 7;
                   1048:            while (isspace((unsigned char) *var)) {
                   1049:                var++;
                   1050:            }
                   1051:        }
                   1052: 
                   1053:        /* Must be of the form name=["']value['"] */
                   1054:        for (val = var; *val != '\0' && *val != '='; val++)
                   1055:            ;
                   1056:        if (var == val || *val != '=')
                   1057:            continue;
                   1058:        var_len = (size_t)(val - var);
                   1059:        val_len = strlen(++val);
                   1060: 
                   1061:        /* Strip leading and trailing single/double quotes */
                   1062:        if ((val[0] == '\'' || val[0] == '\"') && val[0] == val[val_len - 1]) {
                   1063:            val[val_len - 1] = '\0';
                   1064:            val++;
                   1065:            val_len -= 2;
                   1066:        }
                   1067: 
                   1068:        cp = emalloc(var_len + 1 + val_len + 1);
                   1069:        memcpy(cp, var, var_len + 1); /* includes '=' */
                   1070:        memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */
                   1071: 
1.1.1.2   misho    1072:        sudo_putenv(cp, true, overwrite);
1.1       misho    1073:     }
1.1.1.4   misho    1074:     free(line);
1.1       misho    1075:     fclose(fp);
                   1076: }
                   1077: 
                   1078: void
                   1079: init_envtables(void)
                   1080: {
                   1081:     struct list_member *cur;
                   1082:     const char **p;
                   1083: 
                   1084:     /* Fill in the "env_delete" list. */
                   1085:     for (p = initial_badenv_table; *p; p++) {
1.1.1.2   misho    1086:        cur = ecalloc(1, sizeof(struct list_member));
1.1       misho    1087:        cur->value = estrdup(*p);
1.1.1.6 ! misho    1088:        SLIST_INSERT_HEAD(&def_env_delete, cur, entries);
1.1       misho    1089:     }
                   1090: 
                   1091:     /* Fill in the "env_check" list. */
                   1092:     for (p = initial_checkenv_table; *p; p++) {
1.1.1.2   misho    1093:        cur = ecalloc(1, sizeof(struct list_member));
1.1       misho    1094:        cur->value = estrdup(*p);
1.1.1.6 ! misho    1095:        SLIST_INSERT_HEAD(&def_env_check, cur, entries);
1.1       misho    1096:     }
                   1097: 
                   1098:     /* Fill in the "env_keep" list. */
                   1099:     for (p = initial_keepenv_table; *p; p++) {
1.1.1.2   misho    1100:        cur = ecalloc(1, sizeof(struct list_member));
1.1       misho    1101:        cur->value = estrdup(*p);
1.1.1.6 ! misho    1102:        SLIST_INSERT_HEAD(&def_env_keep, cur, entries);
1.1       misho    1103:     }
                   1104: }
1.1.1.2   misho    1105: 
                   1106: int
                   1107: sudoers_hook_getenv(const char *name, char **value, void *closure)
                   1108: {
                   1109:     static bool in_progress = false; /* avoid recursion */
                   1110: 
                   1111:     if (in_progress || env.envp == NULL)
                   1112:        return SUDO_HOOK_RET_NEXT;
                   1113: 
                   1114:     in_progress = true;
1.1.1.4   misho    1115: 
                   1116:     /* Hack to make GNU gettext() find the sudoers locale when needed. */
                   1117:     if (*name == 'L' && sudoers_getlocale() == SUDOERS_LOCALE_SUDOERS) {
                   1118:        if (strcmp(name, "LANGUAGE") == 0 || strcmp(name, "LANG") == 0) {
                   1119:            *value = NULL;
                   1120:            goto done;
                   1121:        }
                   1122:        if (strcmp(name, "LC_ALL") == 0 || strcmp(name, "LC_MESSAGES") == 0) {
                   1123:            *value = def_sudoers_locale;
                   1124:            goto done;
                   1125:        }
                   1126:     }
                   1127: 
1.1.1.2   misho    1128:     *value = sudo_getenv_nodebug(name);
1.1.1.4   misho    1129: done:
1.1.1.2   misho    1130:     in_progress = false;
                   1131:     return SUDO_HOOK_RET_STOP;
                   1132: }
                   1133: 
                   1134: int
                   1135: sudoers_hook_putenv(char *string, void *closure)
                   1136: {
                   1137:     static bool in_progress = false; /* avoid recursion */
                   1138: 
                   1139:     if (in_progress || env.envp == NULL)
                   1140:        return SUDO_HOOK_RET_NEXT;
                   1141: 
                   1142:     in_progress = true;
                   1143:     sudo_putenv_nodebug(string, true, true);
                   1144:     in_progress = false;
                   1145:     return SUDO_HOOK_RET_STOP;
                   1146: }
                   1147: 
                   1148: int
                   1149: sudoers_hook_setenv(const char *name, const char *value, int overwrite, void *closure)
                   1150: {
                   1151:     static bool in_progress = false; /* avoid recursion */
                   1152: 
                   1153:     if (in_progress || env.envp == NULL)
                   1154:        return SUDO_HOOK_RET_NEXT;
                   1155: 
                   1156:     in_progress = true;
                   1157:     sudo_setenv_nodebug(name, value, overwrite);
                   1158:     in_progress = false;
                   1159:     return SUDO_HOOK_RET_STOP;
                   1160: }
                   1161: 
                   1162: int
                   1163: sudoers_hook_unsetenv(const char *name, void *closure)
                   1164: {
                   1165:     static bool in_progress = false; /* avoid recursion */
                   1166: 
                   1167:     if (in_progress || env.envp == NULL)
                   1168:        return SUDO_HOOK_RET_NEXT;
                   1169: 
                   1170:     in_progress = true;
                   1171:     sudo_unsetenv_nodebug(name);
                   1172:     in_progress = false;
                   1173:     return SUDO_HOOK_RET_STOP;
                   1174: }

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