When initializing the environment for env_reset, start out with
the contents of /etc/environment on AIX and login.conf on BSD.
This commit is contained in:
@@ -89,11 +89,16 @@ environment are inherited by the command to be run. There are two
|
||||
distinct ways I<sudoers> can deal with environment variables.
|
||||
|
||||
By default, the I<env_reset> option is enabled. This causes commands
|
||||
to be executed with a minimal environment containing the C<TERM>,
|
||||
C<PATH>, C<HOME>, C<MAIL>, C<SHELL>, C<LOGNAME>, C<USER>, C<USERNAME>
|
||||
and C<SUDO_*> variables in addition to variables from the
|
||||
invoking process permitted by the I<env_check> and I<env_keep>
|
||||
options. This is effectively a whitelist for environment variables.
|
||||
to be executed with a new, minimal environment. On AIX (and Linux
|
||||
systems without PAM), the environment is initialized with the
|
||||
contents of the F</etc/environment> file. On BSD systems, if the
|
||||
I<use_loginclass> option is enabled, the environment is initialized
|
||||
based on the I<path> and I<setenv> settings in F</etc/login.conf>.
|
||||
The new environment contains the C<TERM>, C<PATH>, C<HOME>, C<MAIL>,
|
||||
C<SHELL>, C<LOGNAME>, C<USER>, C<USERNAME> and C<SUDO_*> variables
|
||||
in addition to variables from the invoking process permitted by the
|
||||
I<env_check> and I<env_keep> options. This is effectively a whitelist
|
||||
for environment variables.
|
||||
|
||||
If, however, the I<env_reset> option is disabled, any variables not
|
||||
explicitly denied by the I<env_check> and I<env_delete> options are
|
||||
@@ -119,12 +124,15 @@ As a special case, if B<sudo>'s B<-i> option (initial login) is
|
||||
specified, I<sudoers> will initialize the environment regardless
|
||||
of the value of I<env_reset>. The I<DISPLAY>, I<PATH> and I<TERM>
|
||||
variables remain unchanged; I<HOME>, I<MAIL>, I<SHELL>, I<USER>,
|
||||
and I<LOGNAME> are set based on the target user. On Linux and AIX
|
||||
systems the contents of F</etc/environment> are also included. All
|
||||
other environment variables are removed.
|
||||
and I<LOGNAME> are set based on the target user. On AIX (and Linux
|
||||
systems without PAM), the contents of F</etc/environment> are also
|
||||
included. On BSD systems, if the I<use_loginclass> option is
|
||||
enabled, the I<path> and I<setenv> variables in F</etc/login.conf>
|
||||
are also applied. All other environment variables are removed.
|
||||
|
||||
Lastly, if the I<env_file> option is defined, any variables present
|
||||
in that file will be set to their specified values.
|
||||
Finally, if the I<env_file> option is defined, any variables present
|
||||
in that file will be set to their specified values as long as they
|
||||
would not conflict with an existing environment variable.
|
||||
|
||||
=head1 SUDOERS FILE FORMAT
|
||||
|
||||
@@ -1776,7 +1784,7 @@ Directory containing time stamps for the I<sudoers> security policy
|
||||
|
||||
=item F</etc/environment>
|
||||
|
||||
Initial environment for B<-i> mode on Linux and AIX
|
||||
Initial environment for B<-i> mode on AIX and Linux systems
|
||||
|
||||
=back
|
||||
|
||||
|
@@ -42,6 +42,12 @@
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#ifdef HAVE_LOGIN_CAP_H
|
||||
# include <login_cap.h>
|
||||
# ifndef LOGIN_SETENV
|
||||
# define LOGIN_SETENV 0
|
||||
# endif
|
||||
#endif /* HAVE_LOGIN_CAP_H */
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
@@ -638,6 +644,43 @@ env_should_keep(const char *var)
|
||||
debug_return_bool(keepit == true);
|
||||
}
|
||||
|
||||
static void
|
||||
env_update_didvar(const char *ep, 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.
|
||||
@@ -662,6 +705,8 @@ rebuild_env(void)
|
||||
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. */
|
||||
@@ -673,6 +718,32 @@ rebuild_env(void)
|
||||
}
|
||||
|
||||
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++) {
|
||||
bool keepit;
|
||||
@@ -697,39 +768,8 @@ rebuild_env(void)
|
||||
|
||||
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;
|
||||
}
|
||||
sudo_putenv(*ep, false, false);
|
||||
env_update_didvar(*ep, &didvar);
|
||||
}
|
||||
}
|
||||
didvar |= didvar << 8; /* convert DID_* to KEPT_* */
|
||||
|
Reference in New Issue
Block a user