From: Todd C. Miller Date: Fri, 30 Mar 2012 17:34:19 +0000 (-0400) Subject: When initializing the environment for env_reset, start out with the X-Git-Tag: SUDO_1_7_9p1~18 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=16e9aeb513fd4198661e7f231f14a0c8559d3a13;p=sudo When initializing the environment for env_reset, start out with the contents of /etc/environment on AIX and login.conf on BSD. Also apply environment in login.conf for "sudo -i". --HG-- branch : 1.7 --- diff --git a/env.c b/env.c index 962ade147..9e5a9fd89 100644 --- a/env.c +++ b/env.c @@ -42,6 +42,12 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ +#ifdef HAVE_LOGIN_CAP_H +# include +# ifndef LOGIN_SETENV +# define LOGIN_SETENV 0 +# endif +#endif /* HAVE_LOGIN_CAP_H */ #include #include #include @@ -205,9 +211,6 @@ static const char *initial_keepenv_table[] = { "TZ", "XAUTHORITY", "XAUTHORIZATION", -#ifdef _AIX - "ODMDIR", -#endif NULL }; @@ -510,7 +513,7 @@ env_merge(char * const envp[], int overwrite) /* * Check the env_delete blacklist. - * Returns TRUE if the variable was found, else false. + * Returns TRUE if the variable was found, else FALSE. */ static int matches_env_delete(var) @@ -601,6 +604,43 @@ matches_env_keep(var) return keepit; } +static void +env_update_didvar(const char *ep, unsigned int *didvar) +{ + switch (*ep) { + case 'H': + if (strncmp(ep, "HOME=", 5) == 0) + SET(*didvar, DID_HOME); + break; + case 'L': + if (strncmp(ep, "LOGNAME=", 8) == 0) + SET(*didvar, DID_LOGNAME); + break; + case 'M': + if (strncmp(ep, "MAIL=", 5) == 0) + SET(*didvar, DID_MAIL); + break; + case 'P': + if (strncmp(ep, "PATH=", 5) == 0) + SET(*didvar, DID_PATH); + break; + case 'S': + if (strncmp(ep, "SHELL=", 6) == 0) + SET(*didvar, DID_SHELL); + break; + case 'T': + if (strncmp(ep, "TERM=", 5) == 0) + SET(*didvar, DID_TERM); + break; + case 'U': + if (strncmp(ep, "USER=", 5) == 0) + SET(*didvar, DID_USER); + if (strncmp(ep, "USERNAME=", 5) == 0) + SET(*didvar, DID_USERNAME); + break; + } +} + /* * Build a new environment and ether clear potentially dangerous * variables from the old one or start with a clean slate. @@ -626,6 +666,8 @@ rebuild_env(noexec) env.envp = emalloc2(env.env_size, sizeof(char *)); #ifdef ENV_DEBUG memset(env.envp, 0, env.env_size * sizeof(char *)); +#else + env.envp[0] = NULL; #endif /* Reset HOME based on target user if configured to. */ @@ -637,6 +679,32 @@ rebuild_env(noexec) } if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) { + /* + * If starting with a fresh environment, initialize it based on + * /etc/environment or login.conf. For "sudo -i" we want those + * variables to override the invoking user's environment, so we + * defer reading them until later. + */ + if (!ISSET(sudo_mode, MODE_LOGIN_SHELL)) { +#ifdef HAVE_LOGIN_CAP_H + /* Insert login class environment variables. */ + if (login_class) { + login_cap_t *lc = login_getclass(login_class); + if (lc != NULL) { + setusercontext(lc, runas_pw, runas_pw->pw_uid, + LOGIN_SETPATH|LOGIN_SETENV); + login_close(lc); + } + } +#endif /* HAVE_LOGIN_CAP_H */ +#if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM)) + /* Insert system-wide environment variables. */ + read_env_file(_PATH_ENVIRONMENT, TRUE); +#endif + for (ep = env.envp; *ep; ep++) + env_update_didvar(*ep, &didvar); + } + /* Pull in vars we want to keep from the old environment. */ for (ep = old_envp; *ep; ep++) { int keepit; @@ -662,38 +730,7 @@ rebuild_env(noexec) if (keepit) { /* Preserve variable. */ - switch (**ep) { - case 'H': - if (strncmp(*ep, "HOME=", 5) == 0) - SET(didvar, DID_HOME); - break; - case 'L': - if (strncmp(*ep, "LOGNAME=", 8) == 0) - SET(didvar, DID_LOGNAME); - break; - case 'M': - if (strncmp(*ep, "MAIL=", 5) == 0) - SET(didvar, DID_MAIL); - break; - case 'P': - if (strncmp(*ep, "PATH=", 5) == 0) - SET(didvar, DID_PATH); - break; - case 'S': - if (strncmp(*ep, "SHELL=", 6) == 0) - SET(didvar, DID_SHELL); - break; - case 'T': - if (strncmp(*ep, "TERM=", 5) == 0) - SET(didvar, DID_TERM); - break; - case 'U': - if (strncmp(*ep, "USER=", 5) == 0) - SET(didvar, DID_USER); - if (strncmp(*ep, "USERNAME=", 5) == 0) - SET(didvar, DID_USERNAME); - break; - } + env_update_didvar(*ep, &didvar); sudo_putenv(*ep, FALSE, FALSE); } } diff --git a/sudo.c b/sudo.c index a384743e7..3cdc3b708 100644 --- a/sudo.c +++ b/sudo.c @@ -87,6 +87,9 @@ # ifndef LOGIN_DEFROOTCLASS # define LOGIN_DEFROOTCLASS "daemon" # endif +# ifndef LOGIN_SETENV +# define LOGIN_SETENV 0 +# endif #endif #ifdef HAVE_MBR_CHECK_MEMBERSHIP # include @@ -540,6 +543,17 @@ main(argc, argv, envp) /* Insert system-wide environment variables. */ read_env_file(_PATH_ENVIRONMENT, TRUE); #endif +#ifdef HAVE_LOGIN_CAP_H + /* Set environment based on login class. */ + if (login_class) { + login_cap_t *lc = login_getclass(login_class); + if (lc != NULL) { + setusercontext(lc, runas_pw, runas_pw->pw_uid, + LOGIN_SETPATH|LOGIN_SETENV); + login_close(lc); + } + } +#endif /* HAVE_LOGIN_CAP_H */ } if (ISSET(sudo_mode, MODE_RUN)) { diff --git a/sudo.pod b/sudo.pod index 76755d004..1e6850876 100644 --- a/sudo.pod +++ b/sudo.pod @@ -428,12 +428,16 @@ B tries to be safe when executing external commands. There are two distinct ways to deal with environment variables. By default, the I I option is enabled. This causes -commands to be executed with a minimal environment containing the -C, C, C, C, C, C, C, -C and C variables in addition to variables from -the invoking process permitted by the I and I -I options. This is effectively a whitelist for environment -variables. +commands to be executed with a new, minimal environment containing. +On AIX (and Linux systems without PAM), the environment is initialized +with the contents of the F file. On BSD systems, +if the I option is enabled, the environment is +initialized based on the I and I settings in +F. The new environment contains the C, +C, C, C, C, C, C, C +and C variables in addition to variables from the invoking +process permitted by the I and I options. This +is effectively a whitelist for environment variables. If, however, the I option is disabled in I, any variables not explicitly denied by the I and I @@ -602,7 +606,7 @@ Directory containing time stamps =item F -Initial environment for B<-i> mode on Linux and AIX +Initial environment for B<-i> mode on AIX Linux systems =back