]> granicus.if.org Git - sudo/commitdiff
When initializing the environment for env_reset, start out with the
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 30 Mar 2012 17:34:19 +0000 (13:34 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 30 Mar 2012 17:34:19 +0000 (13:34 -0400)
contents of /etc/environment on AIX and login.conf on BSD.  Also
apply environment in login.conf for "sudo -i".

--HG--
branch : 1.7

env.c
sudo.c
sudo.pod

diff --git a/env.c b/env.c
index 962ade147a706f44d707f82e63e33bc8efcab795..9e5a9fd89a9315bb78ba9fc751576eeb1e3a3e32 100644 (file)
--- a/env.c
+++ b/env.c
 #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>
@@ -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 a384743e7ff36175f1137a54d9782c840db07a5e..3cdc3b708b7b4843807059837be6941742d72a17 100644 (file)
--- 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 <membership.h>
@@ -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)) {
index 76755d0048ef2da44ab831005ec393e01a34d916..1e685087655a2adb7d4642e7edc80674465f21e9 100644 (file)
--- a/sudo.pod
+++ b/sudo.pod
@@ -428,12 +428,16 @@ B<sudo> tries to be safe when executing external commands.
 
 There are two distinct ways to deal with environment variables.  By
 default, the I<env_reset> I<sudoers> 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>
-I<sudoers> 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</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 in I<sudoers>, any
 variables not explicitly denied by the I<env_check> and I<env_delete>
@@ -602,7 +606,7 @@ Directory containing time stamps
 
 =item F</etc/environment>
 
-Initial environment for B<-i> mode on Linux and AIX
+Initial environment for B<-i> mode on AIX Linux systems
 
 =back