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

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

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