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