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

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.4 ! misho     288:            fatalx_nodebug(_("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.4 ! misho     293:            fatalx_nodebug(_("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.4 ! misho     367:            fatalx(_("sudo_putenv: corrupted envp, length mismatch"));
1.1.1.2   misho     368: #endif
1.1.1.4 ! misho     369:        fatalx(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.4 ! misho     395:        fatalx(_("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:  * Merge another environment with our private copy.
                    549:  */
                    550: void
                    551: env_merge(char * const envp[], bool overwrite)
                    552: {
                    553:     char * const *ep;
                    554:     debug_decl(env_merge, SUDO_DEBUG_ENV)
                    555: 
                    556:     for (ep = envp; *ep != NULL; ep++)
                    557:        sudo_putenv(*ep, true, overwrite);
                    558: 
                    559:     debug_return;
                    560: }
                    561: 
                    562: /*
                    563:  * Check the env_delete blacklist.
                    564:  * Returns true if the variable was found, else false.
                    565:  */
                    566: static bool
1.1       misho     567: matches_env_delete(const char *var)
                    568: {
                    569:     struct list_member *cur;
                    570:     size_t len;
1.1.1.2   misho     571:     bool iswild;
                    572:     bool match = false;
                    573:     debug_decl(matches_env_delete, SUDO_DEBUG_ENV)
1.1       misho     574: 
                    575:     /* Skip anything listed in env_delete. */
                    576:     for (cur = def_env_delete; cur; cur = cur->next) {
                    577:        len = strlen(cur->value);
                    578:        /* Deal with '*' wildcard */
                    579:        if (cur->value[len - 1] == '*') {
                    580:            len--;
1.1.1.2   misho     581:            iswild = true;
1.1       misho     582:        } else
1.1.1.2   misho     583:            iswild = false;
1.1       misho     584:        if (strncmp(cur->value, var, len) == 0 &&
                    585:            (iswild || var[len] == '=')) {
1.1.1.2   misho     586:            match = true;
1.1       misho     587:            break;
                    588:        }
                    589:     }
1.1.1.2   misho     590:     debug_return_bool(match);
1.1       misho     591: }
                    592: 
                    593: /*
                    594:  * Apply the env_check list.
1.1.1.2   misho     595:  * Returns true if the variable is allowed, false if denied
1.1       misho     596:  * or -1 if no match.
                    597:  */
                    598: static int
                    599: matches_env_check(const char *var)
                    600: {
                    601:     struct list_member *cur;
                    602:     size_t len;
1.1.1.2   misho     603:     bool iswild;
                    604:     int keepit = -1;
                    605:     debug_decl(matches_env_check, SUDO_DEBUG_ENV)
1.1       misho     606: 
                    607:     for (cur = def_env_check; cur; cur = cur->next) {
                    608:        len = strlen(cur->value);
                    609:        /* Deal with '*' wildcard */
                    610:        if (cur->value[len - 1] == '*') {
                    611:            len--;
1.1.1.2   misho     612:            iswild = true;
1.1       misho     613:        } else
1.1.1.2   misho     614:            iswild = false;
1.1       misho     615:        if (strncmp(cur->value, var, len) == 0 &&
                    616:            (iswild || var[len] == '=')) {
                    617:            keepit = !strpbrk(var, "/%");
                    618:            break;
                    619:        }
                    620:     }
1.1.1.2   misho     621:     debug_return_bool(keepit);
1.1       misho     622: }
                    623: 
                    624: /*
                    625:  * Check the env_keep list.
1.1.1.2   misho     626:  * Returns true if the variable is allowed else false.
1.1       misho     627:  */
1.1.1.2   misho     628: static bool
1.1       misho     629: matches_env_keep(const char *var)
                    630: {
                    631:     struct list_member *cur;
                    632:     size_t len;
1.1.1.2   misho     633:     bool iswild, keepit = false;
                    634:     debug_decl(matches_env_keep, SUDO_DEBUG_ENV)
1.1       misho     635: 
                    636:     /* Preserve SHELL variable for "sudo -s". */
1.1.1.2   misho     637:     if (ISSET(sudo_mode, MODE_SHELL) && strncmp(var, "SHELL=", 6) == 0) {
                    638:        keepit = true;
                    639:        goto done;
                    640:     }
1.1       misho     641: 
                    642:     for (cur = def_env_keep; cur; cur = cur->next) {
                    643:        len = strlen(cur->value);
                    644:        /* Deal with '*' wildcard */
                    645:        if (cur->value[len - 1] == '*') {
                    646:            len--;
1.1.1.2   misho     647:            iswild = true;
1.1       misho     648:        } else
1.1.1.2   misho     649:            iswild = false;
1.1       misho     650:        if (strncmp(cur->value, var, len) == 0 &&
                    651:            (iswild || var[len] == '=')) {
1.1.1.2   misho     652:            keepit = true;
1.1       misho     653:            break;
                    654:        }
                    655:     }
1.1.1.2   misho     656: done:
                    657:     debug_return_bool(keepit);
                    658: }
                    659: 
                    660: /*
                    661:  * Look up var in the env_delete and env_check.
                    662:  * Returns true if we should delete the variable, else false.
                    663:  */
                    664: static bool
                    665: env_should_delete(const char *var)
                    666: {
                    667:     int delete_it;
                    668:     debug_decl(env_should_delete, SUDO_DEBUG_ENV);
                    669: 
                    670:     delete_it = matches_env_delete(var);
                    671:     if (!delete_it)
                    672:        delete_it = matches_env_check(var) == false;
1.1.1.3   misho     673: 
                    674:     sudo_debug_printf(SUDO_DEBUG_INFO, "delete %s: %s",
                    675:        var, delete_it ? "YES" : "NO");
1.1.1.2   misho     676:     debug_return_bool(delete_it);
                    677: }
                    678: 
                    679: /*
                    680:  * Lookup var in the env_check and env_keep lists.
                    681:  * Returns true if the variable is allowed else false.
                    682:  */
                    683: static bool
                    684: env_should_keep(const char *var)
                    685: {
                    686:     int keepit;
                    687:     debug_decl(env_should_keep, SUDO_DEBUG_ENV)
                    688: 
                    689:     keepit = matches_env_check(var);
                    690:     if (keepit == -1)
                    691:        keepit = matches_env_keep(var);
                    692: 
1.1.1.3   misho     693:     sudo_debug_printf(SUDO_DEBUG_INFO, "keep %s: %s",
                    694:        var, keepit ? "YES" : "NO");
1.1.1.2   misho     695:     debug_return_bool(keepit == true);
                    696: }
                    697: 
                    698: static void
                    699: env_update_didvar(const char *ep, unsigned int *didvar)
                    700: {
                    701:     switch (*ep) {
                    702:        case 'H':
                    703:            if (strncmp(ep, "HOME=", 5) == 0)
                    704:                SET(*didvar, DID_HOME);
                    705:            break;
                    706:        case 'L':
                    707:            if (strncmp(ep, "LOGNAME=", 8) == 0)
                    708:                SET(*didvar, DID_LOGNAME);
                    709:            break;
                    710:        case 'M':
                    711:            if (strncmp(ep, "MAIL=", 5) == 0)
                    712:                SET(*didvar, DID_MAIL);
                    713:            break;
                    714:        case 'P':
                    715:            if (strncmp(ep, "PATH=", 5) == 0)
                    716:                SET(*didvar, DID_PATH);
                    717:            break;
                    718:        case 'S':
                    719:            if (strncmp(ep, "SHELL=", 6) == 0)
                    720:                SET(*didvar, DID_SHELL);
                    721:            break;
                    722:        case 'T':
                    723:            if (strncmp(ep, "TERM=", 5) == 0)
                    724:                SET(*didvar, DID_TERM);
                    725:            break;
                    726:        case 'U':
                    727:            if (strncmp(ep, "USER=", 5) == 0)
                    728:                SET(*didvar, DID_USER);
                    729:            if (strncmp(ep, "USERNAME=", 5) == 0)
                    730:                SET(*didvar, DID_USERNAME);
                    731:            break;
                    732:     }
1.1       misho     733: }
                    734: 
                    735: /*
                    736:  * Build a new environment and ether clear potentially dangerous
                    737:  * variables from the old one or start with a clean slate.
                    738:  * Also adds sudo-specific variables (SUDO_*).
                    739:  */
                    740: void
                    741: rebuild_env(void)
                    742: {
                    743:     char **old_envp, **ep, *cp, *ps1;
1.1.1.3   misho     744:     char idbuf[MAX_UID_T_LEN + 1];
1.1       misho     745:     unsigned int didvar;
1.1.1.2   misho     746:     bool reset_home = false;
1.1       misho     747: 
                    748:     /*
                    749:      * Either clean out the environment or reset to a safe default.
                    750:      */
                    751:     ps1 = NULL;
                    752:     didvar = 0;
                    753:     env.env_len = 0;
                    754:     env.env_size = 128;
                    755:     old_envp = env.envp;
                    756:     env.envp = emalloc2(env.env_size, sizeof(char *));
                    757: #ifdef ENV_DEBUG
                    758:     memset(env.envp, 0, env.env_size * sizeof(char *));
1.1.1.2   misho     759: #else
                    760:     env.envp[0] = NULL;
1.1       misho     761: #endif
                    762: 
                    763:     /* Reset HOME based on target user if configured to. */
                    764:     if (ISSET(sudo_mode, MODE_RUN)) {
                    765:        if (def_always_set_home ||
                    766:            ISSET(sudo_mode, MODE_RESET_HOME | MODE_LOGIN_SHELL) || 
                    767:            (ISSET(sudo_mode, MODE_SHELL) && def_set_home))
1.1.1.2   misho     768:            reset_home = true;
1.1       misho     769:     }
                    770: 
                    771:     if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
1.1.1.2   misho     772:        /*
                    773:         * If starting with a fresh environment, initialize it based on
                    774:         * /etc/environment or login.conf.  For "sudo -i" we want those
                    775:         * variables to override the invoking user's environment, so we
                    776:         * defer reading them until later.
                    777:         */
                    778:        if (!ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
                    779: #ifdef HAVE_LOGIN_CAP_H
                    780:            /* Insert login class environment variables. */
                    781:            if (login_class) {
                    782:                login_cap_t *lc = login_getclass(login_class);
                    783:                if (lc != NULL) {
                    784:                    setusercontext(lc, runas_pw, runas_pw->pw_uid,
                    785:                        LOGIN_SETPATH|LOGIN_SETENV);
                    786:                    login_close(lc);
                    787:                }
                    788:            }
                    789: #endif /* HAVE_LOGIN_CAP_H */
                    790: #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM))
                    791:            /* Insert system-wide environment variables. */
                    792:            read_env_file(_PATH_ENVIRONMENT, true);
                    793: #endif
                    794:            for (ep = env.envp; *ep; ep++)
                    795:                env_update_didvar(*ep, &didvar);
                    796:        }
                    797: 
1.1       misho     798:        /* Pull in vars we want to keep from the old environment. */
                    799:        for (ep = old_envp; *ep; ep++) {
1.1.1.2   misho     800:            bool keepit;
1.1       misho     801: 
                    802:            /* Skip variables with values beginning with () (bash functions) */
                    803:            if ((cp = strchr(*ep, '=')) != NULL) {
                    804:                if (strncmp(cp, "=() ", 3) == 0)
                    805:                    continue;
                    806:            }
                    807: 
                    808:            /*
1.1.1.2   misho     809:             * Look up the variable in the env_check and env_keep lists.
1.1       misho     810:             */
1.1.1.2   misho     811:            keepit = env_should_keep(*ep);
1.1       misho     812: 
1.1.1.2   misho     813:            /*
                    814:             * Do SUDO_PS1 -> PS1 conversion.
                    815:             * This must happen *after* env_should_keep() is called.
                    816:             */
1.1       misho     817:            if (strncmp(*ep, "SUDO_PS1=", 8) == 0)
                    818:                ps1 = *ep + 5;
                    819: 
                    820:            if (keepit) {
                    821:                /* Preserve variable. */
1.1.1.2   misho     822:                sudo_putenv(*ep, false, false);
                    823:                env_update_didvar(*ep, &didvar);
1.1       misho     824:            }
                    825:        }
                    826:        didvar |= didvar << 8;          /* convert DID_* to KEPT_* */
                    827: 
                    828:        /*
                    829:         * Add in defaults.  In -i mode these come from the runas user,
                    830:         * otherwise they may be from the user's environment (depends
                    831:         * on sudoers options).
                    832:         */
                    833:        if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
1.1.1.2   misho     834:            sudo_setenv2("SHELL", runas_pw->pw_shell,
                    835:                ISSET(didvar, DID_SHELL), true);
                    836:            sudo_setenv2("LOGNAME", runas_pw->pw_name,
                    837:                ISSET(didvar, DID_LOGNAME), true);
                    838:            sudo_setenv2("USER", runas_pw->pw_name,
                    839:                ISSET(didvar, DID_USER), true);
                    840:            sudo_setenv2("USERNAME", runas_pw->pw_name,
                    841:                ISSET(didvar, DID_USERNAME), true);
1.1       misho     842:        } else {
                    843:            if (!ISSET(didvar, DID_SHELL))
1.1.1.2   misho     844:                sudo_setenv2("SHELL", sudo_user.pw->pw_shell, false, true);
1.1.1.3   misho     845:            /* We will set LOGNAME later in the !def_set_logname case. */
                    846:            if (!def_set_logname) {
                    847:                if (!ISSET(didvar, DID_LOGNAME))
                    848:                    sudo_setenv2("LOGNAME", user_name, false, true);
                    849:                if (!ISSET(didvar, DID_USER))
                    850:                    sudo_setenv2("USER", user_name, false, true);
                    851:                if (!ISSET(didvar, DID_USERNAME))
                    852:                    sudo_setenv2("USERNAME", user_name, false, true);
                    853:            }
1.1       misho     854:        }
                    855: 
                    856:        /* If we didn't keep HOME, reset it based on target user. */
                    857:        if (!ISSET(didvar, KEPT_HOME))
1.1.1.2   misho     858:            reset_home = true;
1.1       misho     859: 
                    860:        /*
                    861:         * Set MAIL to target user in -i mode or if MAIL is not preserved
                    862:         * from user's environment.
                    863:         */
                    864:        if (ISSET(sudo_mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) {
                    865:            cp = _PATH_MAILDIR;
                    866:            if (cp[sizeof(_PATH_MAILDIR) - 2] == '/')
                    867:                easprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name);
                    868:            else
                    869:                easprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name);
1.1.1.2   misho     870:            sudo_putenv(cp, ISSET(didvar, DID_MAIL), true);
1.1       misho     871:        }
                    872:     } else {
                    873:        /*
                    874:         * Copy environ entries as long as they don't match env_delete or
                    875:         * env_check.
                    876:         */
                    877:        for (ep = old_envp; *ep; ep++) {
                    878:            /* Skip variables with values beginning with () (bash functions) */
                    879:            if ((cp = strchr(*ep, '=')) != NULL) {
                    880:                if (strncmp(cp, "=() ", 3) == 0)
                    881:                    continue;
                    882:            }
                    883: 
1.1.1.2   misho     884:            /* Add variable unless it matches a black list. */
                    885:            if (!env_should_delete(*ep)) {
1.1       misho     886:                if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
                    887:                    ps1 = *ep + 5;
                    888:                else if (strncmp(*ep, "PATH=", 5) == 0)
                    889:                    SET(didvar, DID_PATH);
                    890:                else if (strncmp(*ep, "TERM=", 5) == 0)
                    891:                    SET(didvar, DID_TERM);
1.1.1.2   misho     892:                sudo_putenv(*ep, false, false);
1.1       misho     893:            }
                    894:        }
                    895:     }
                    896:     /* Replace the PATH envariable with a secure one? */
                    897:     if (def_secure_path && !user_is_exempt()) {
1.1.1.2   misho     898:        sudo_setenv2("PATH", def_secure_path, true, true);
1.1       misho     899:        SET(didvar, DID_PATH);
                    900:     }
                    901: 
                    902:     /*
                    903:      * Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is not
                    904:      * disabled.  We skip this if we are running a login shell (because
1.1.1.3   misho     905:      * they have already been set) or sudoedit (because we want the editor
                    906:      * to find the invoking user's startup files).
1.1       misho     907:      */
                    908:     if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL|MODE_EDIT)) {
                    909:        if (!ISSET(didvar, KEPT_LOGNAME))
1.1.1.2   misho     910:            sudo_setenv2("LOGNAME", runas_pw->pw_name, true, true);
1.1       misho     911:        if (!ISSET(didvar, KEPT_USER))
1.1.1.2   misho     912:            sudo_setenv2("USER", runas_pw->pw_name, true, true);
1.1       misho     913:        if (!ISSET(didvar, KEPT_USERNAME))
1.1.1.2   misho     914:            sudo_setenv2("USERNAME", runas_pw->pw_name, true, true);
1.1       misho     915:     }
                    916: 
                    917:     /* Set $HOME to target user if not preserving user's value. */
                    918:     if (reset_home)
1.1.1.2   misho     919:        sudo_setenv2("HOME", runas_pw->pw_dir, true, true);
1.1       misho     920: 
                    921:     /* Provide default values for $TERM and $PATH if they are not set. */
                    922:     if (!ISSET(didvar, DID_TERM))
1.1.1.2   misho     923:        sudo_putenv("TERM=unknown", false, false);
1.1       misho     924:     if (!ISSET(didvar, DID_PATH))
1.1.1.2   misho     925:        sudo_setenv2("PATH", _PATH_STDPATH, false, true);
1.1       misho     926: 
                    927:     /* Set PS1 if SUDO_PS1 is set. */
                    928:     if (ps1 != NULL)
1.1.1.2   misho     929:        sudo_putenv(ps1, true, true);
1.1       misho     930: 
                    931:     /* Add the SUDO_COMMAND envariable (cmnd + args). */
                    932:     if (user_args) {
                    933:        easprintf(&cp, "%s %s", user_cmnd, user_args);
1.1.1.2   misho     934:        sudo_setenv2("SUDO_COMMAND", cp, true, true);
1.1       misho     935:        efree(cp);
                    936:     } else {
1.1.1.2   misho     937:        sudo_setenv2("SUDO_COMMAND", user_cmnd, true, true);
1.1       misho     938:     }
                    939: 
                    940:     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
1.1.1.2   misho     941:     sudo_setenv2("SUDO_USER", user_name, true, true);
1.1       misho     942:     snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_uid);
1.1.1.2   misho     943:     sudo_setenv2("SUDO_UID", idbuf, true, true);
1.1       misho     944:     snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_gid);
1.1.1.2   misho     945:     sudo_setenv2("SUDO_GID", idbuf, true, true);
1.1       misho     946: 
                    947:     /* Free old environment. */
                    948:     efree(old_envp);
                    949: }
                    950: 
                    951: void
                    952: insert_env_vars(char * const envp[])
                    953: {
                    954:     char * const *ep;
                    955: 
                    956:     if (envp == NULL)
                    957:        return;
                    958: 
                    959:     /* Add user-specified environment variables. */
                    960:     for (ep = envp; *ep != NULL; ep++)
1.1.1.2   misho     961:        sudo_putenv(*ep, true, true);
1.1       misho     962: }
                    963: 
                    964: /*
                    965:  * Validate the list of environment variables passed in on the command
                    966:  * line against env_delete, env_check, and env_keep.
1.1.1.2   misho     967:  * Calls log_fatal() if any specified variables are not allowed.
1.1       misho     968:  */
                    969: void
                    970: validate_env_vars(char * const env_vars[])
                    971: {
                    972:     char * const *ep;
                    973:     char *eq, *bad = NULL;
                    974:     size_t len, blen = 0, bsize = 0;
1.1.1.2   misho     975:     bool okvar;
1.1       misho     976: 
                    977:     if (env_vars == NULL)
                    978:        return;
                    979: 
                    980:     /* Add user-specified environment variables. */
                    981:     for (ep = env_vars; *ep != NULL; ep++) {
                    982:        if (def_secure_path && !user_is_exempt() &&
                    983:            strncmp(*ep, "PATH=", 5) == 0) {
1.1.1.2   misho     984:            okvar = false;
1.1       misho     985:        } else if (def_env_reset) {
1.1.1.2   misho     986:            okvar = env_should_keep(*ep);
1.1       misho     987:        } else {
1.1.1.2   misho     988:            okvar = !env_should_delete(*ep);
1.1       misho     989:        }
1.1.1.2   misho     990:        if (okvar == false) {
1.1       misho     991:            /* Not allowed, add to error string, allocating as needed. */
                    992:            if ((eq = strchr(*ep, '=')) != NULL)
                    993:                *eq = '\0';
                    994:            len = strlen(*ep) + 2;
                    995:            if (blen + len >= bsize) {
                    996:                do {
                    997:                    bsize += 1024;
                    998:                } while (blen + len >= bsize);
                    999:                bad = erealloc(bad, bsize);
                   1000:                bad[blen] = '\0';
                   1001:            }
                   1002:            strlcat(bad, *ep, bsize);
                   1003:            strlcat(bad, ", ", bsize);
                   1004:            blen += len;
                   1005:            if (eq != NULL)
                   1006:                *eq = '=';
                   1007:        }
                   1008:     }
                   1009:     if (bad != NULL) {
                   1010:        bad[blen - 2] = '\0';           /* remove trailing ", " */
1.1.1.2   misho    1011:        log_fatal(NO_MAIL,
1.1.1.4 ! misho    1012:            N_("sorry, you are not allowed to set the following environment variables: %s"), bad);
1.1       misho    1013:        /* NOTREACHED */
                   1014:        efree(bad);
                   1015:     }
                   1016: }
                   1017: 
                   1018: /*
                   1019:  * Read in /etc/environment ala AIX and Linux.
                   1020:  * Lines may be in either of three formats:
                   1021:  *  NAME=VALUE
                   1022:  *  NAME="VALUE"
                   1023:  *  NAME='VALUE'
                   1024:  * with an optional "export" prefix so the shell can source the file.
                   1025:  * Invalid lines, blank lines, or lines consisting solely of a comment
                   1026:  * character are skipped.
                   1027:  */
                   1028: void
                   1029: read_env_file(const char *path, int overwrite)
                   1030: {
                   1031:     FILE *fp;
1.1.1.4 ! misho    1032:     char *cp, *var, *val, *line = NULL;
        !          1033:     size_t var_len, val_len, linesize = 0;
1.1       misho    1034: 
                   1035:     if ((fp = fopen(path, "r")) == NULL)
                   1036:        return;
                   1037: 
1.1.1.4 ! misho    1038:     while (sudo_parseln(&line, &linesize, NULL, fp) != -1) {
1.1       misho    1039:        /* Skip blank or comment lines */
1.1.1.4 ! misho    1040:        if (*(var = line) == '\0')
1.1       misho    1041:            continue;
                   1042: 
                   1043:        /* Skip optional "export " */
                   1044:        if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) {
                   1045:            var += 7;
                   1046:            while (isspace((unsigned char) *var)) {
                   1047:                var++;
                   1048:            }
                   1049:        }
                   1050: 
                   1051:        /* Must be of the form name=["']value['"] */
                   1052:        for (val = var; *val != '\0' && *val != '='; val++)
                   1053:            ;
                   1054:        if (var == val || *val != '=')
                   1055:            continue;
                   1056:        var_len = (size_t)(val - var);
                   1057:        val_len = strlen(++val);
                   1058: 
                   1059:        /* Strip leading and trailing single/double quotes */
                   1060:        if ((val[0] == '\'' || val[0] == '\"') && val[0] == val[val_len - 1]) {
                   1061:            val[val_len - 1] = '\0';
                   1062:            val++;
                   1063:            val_len -= 2;
                   1064:        }
                   1065: 
                   1066:        cp = emalloc(var_len + 1 + val_len + 1);
                   1067:        memcpy(cp, var, var_len + 1); /* includes '=' */
                   1068:        memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */
                   1069: 
1.1.1.2   misho    1070:        sudo_putenv(cp, true, overwrite);
1.1       misho    1071:     }
1.1.1.4 ! misho    1072:     free(line);
1.1       misho    1073:     fclose(fp);
                   1074: }
                   1075: 
                   1076: void
                   1077: init_envtables(void)
                   1078: {
                   1079:     struct list_member *cur;
                   1080:     const char **p;
                   1081: 
                   1082:     /* Fill in the "env_delete" list. */
                   1083:     for (p = initial_badenv_table; *p; p++) {
1.1.1.2   misho    1084:        cur = ecalloc(1, sizeof(struct list_member));
1.1       misho    1085:        cur->value = estrdup(*p);
                   1086:        cur->next = def_env_delete;
                   1087:        def_env_delete = cur;
                   1088:     }
                   1089: 
                   1090:     /* Fill in the "env_check" list. */
                   1091:     for (p = initial_checkenv_table; *p; p++) {
1.1.1.2   misho    1092:        cur = ecalloc(1, sizeof(struct list_member));
1.1       misho    1093:        cur->value = estrdup(*p);
                   1094:        cur->next = def_env_check;
                   1095:        def_env_check = cur;
                   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);
                   1102:        cur->next = def_env_keep;
                   1103:        def_env_keep = cur;
                   1104:     }
                   1105: }
1.1.1.2   misho    1106: 
                   1107: int
                   1108: sudoers_hook_getenv(const char *name, char **value, void *closure)
                   1109: {
                   1110:     static bool in_progress = false; /* avoid recursion */
                   1111: 
                   1112:     if (in_progress || env.envp == NULL)
                   1113:        return SUDO_HOOK_RET_NEXT;
                   1114: 
                   1115:     in_progress = true;
1.1.1.4 ! misho    1116: 
        !          1117:     /* Hack to make GNU gettext() find the sudoers locale when needed. */
        !          1118:     if (*name == 'L' && sudoers_getlocale() == SUDOERS_LOCALE_SUDOERS) {
        !          1119:        if (strcmp(name, "LANGUAGE") == 0 || strcmp(name, "LANG") == 0) {
        !          1120:            *value = NULL;
        !          1121:            goto done;
        !          1122:        }
        !          1123:        if (strcmp(name, "LC_ALL") == 0 || strcmp(name, "LC_MESSAGES") == 0) {
        !          1124:            *value = def_sudoers_locale;
        !          1125:            goto done;
        !          1126:        }
        !          1127:     }
        !          1128: 
1.1.1.2   misho    1129:     *value = sudo_getenv_nodebug(name);
1.1.1.4 ! misho    1130: done:
1.1.1.2   misho    1131:     in_progress = false;
                   1132:     return SUDO_HOOK_RET_STOP;
                   1133: }
                   1134: 
                   1135: int
                   1136: sudoers_hook_putenv(char *string, void *closure)
                   1137: {
                   1138:     static bool in_progress = false; /* avoid recursion */
                   1139: 
                   1140:     if (in_progress || env.envp == NULL)
                   1141:        return SUDO_HOOK_RET_NEXT;
                   1142: 
                   1143:     in_progress = true;
                   1144:     sudo_putenv_nodebug(string, true, true);
                   1145:     in_progress = false;
                   1146:     return SUDO_HOOK_RET_STOP;
                   1147: }
                   1148: 
                   1149: int
                   1150: sudoers_hook_setenv(const char *name, const char *value, int overwrite, void *closure)
                   1151: {
                   1152:     static bool in_progress = false; /* avoid recursion */
                   1153: 
                   1154:     if (in_progress || env.envp == NULL)
                   1155:        return SUDO_HOOK_RET_NEXT;
                   1156: 
                   1157:     in_progress = true;
                   1158:     sudo_setenv_nodebug(name, value, overwrite);
                   1159:     in_progress = false;
                   1160:     return SUDO_HOOK_RET_STOP;
                   1161: }
                   1162: 
                   1163: int
                   1164: sudoers_hook_unsetenv(const char *name, void *closure)
                   1165: {
                   1166:     static bool in_progress = false; /* avoid recursion */
                   1167: 
                   1168:     if (in_progress || env.envp == NULL)
                   1169:        return SUDO_HOOK_RET_NEXT;
                   1170: 
                   1171:     in_progress = true;
                   1172:     sudo_unsetenv_nodebug(name);
                   1173:     in_progress = false;
                   1174:     return SUDO_HOOK_RET_STOP;
                   1175: }

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