[BACK]Return to env.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Diff for /src/usr.bin/sudo/Attic/env.c between version 1.13 and 1.14

version 1.13, 2005/02/06 15:56:27 version 1.14, 2007/07/26 16:10:16
Line 1 
Line 1 
 /*  /*
  * Copyright (c) 2000-2004 Todd C. Miller <Todd.Miller@courtesan.com>   * Copyright (c) 2000-2007 Todd C. Miller <Todd.Miller@courtesan.com>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
Line 18 
Line 18 
  * Materiel Command, USAF, under agreement number F39502-99-1-0512.   * Materiel Command, USAF, under agreement number F39502-99-1-0512.
  */   */
   
 #include "config.h"  #include <config.h>
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/param.h>  #include <sys/param.h>
Line 52 
Line 52 
 #include "sudo.h"  #include "sudo.h"
   
 #ifndef lint  #ifndef lint
 static const char rcsid[] = "$Sudo: env.c,v 1.42 2004/09/08 15:57:49 millert Exp $";  __unused static const char rcsid[] = "$Sudo: env.c,v 1.39.2.15 2007/07/09 19:15:43 millert Exp $";
 #endif /* lint */  #endif /* lint */
   
 /*  /*
  * Flags used in rebuild_env()   * Flags used in rebuild_env()
  */   */
 #undef DID_TERM  #undef DID_TERM
 #define DID_TERM        0x01  #define DID_TERM        0x0001
 #undef DID_PATH  #undef DID_PATH
 #define DID_PATH        0x02  #define DID_PATH        0x0002
 #undef DID_HOME  #undef DID_HOME
 #define DID_HOME        0x04  #define DID_HOME        0x0004
 #undef DID_SHELL  #undef DID_SHELL
 #define DID_SHELL       0x08  #define DID_SHELL       0x0008
 #undef DID_LOGNAME  #undef DID_LOGNAME
 #define DID_LOGNAME     0x10  #define DID_LOGNAME     0x0010
 #undef DID_USER  #undef DID_USER
 #define DID_USER        0x20  #define DID_USER        0x0020
   #undef DID_USERNAME
   #define DID_USERNAME    0x0040
   #undef DID_MAX
   #define DID_MAX         0x00ff
   
   #undef KEPT_TERM
   #define KEPT_TERM       0x0100
   #undef KEPT_PATH
   #define KEPT_PATH       0x0200
   #undef KEPT_HOME
   #define KEPT_HOME       0x0400
   #undef KEPT_SHELL
   #define KEPT_SHELL      0x0800
   #undef KEPT_LOGNAME
   #define KEPT_LOGNAME    0x1000
   #undef KEPT_USER
   #define KEPT_USER       0x2000
   #undef KEPT_USERNAME
   #define KEPT_USERNAME   0x4000
   #undef KEPT_MAX
   #define KEPT_MAX        0xff00
   
 #undef VNULL  #undef VNULL
 #define VNULL   (VOID *)NULL  #define VNULL   (VOID *)NULL
   
   struct environment {
       char **envp;                /* pointer to the new environment */
       size_t env_size;            /* size of new_environ in char **'s */
       size_t env_len;             /* number of slots used, not counting NULL */
   };
   
 /*  /*
  * Prototypes   * Prototypes
  */   */
 char **rebuild_env              __P((char **, int, int));  char **rebuild_env              __P((char **, int, int));
 char **zero_env                 __P((char **));  static void insert_env          __P((char *, struct environment *, int));
 static void insert_env          __P((char *, int));  
 static char *format_env         __P((char *, ...));  static char *format_env         __P((char *, ...));
   
 /*  /*
    * Copy of the sudo-managed environment.
    */
   static struct environment env;
   
   /*
  * Default table of "bad" variables to remove from the environment.   * Default table of "bad" variables to remove from the environment.
  * XXX - how to omit TERMCAP if it starts with '/'?   * XXX - how to omit TERMCAP if it starts with '/'?
  */   */
Line 100 
Line 131 
     "SHLIB_PATH",      "SHLIB_PATH",
 #endif /* __hpux */  #endif /* __hpux */
 #ifdef _AIX  #ifdef _AIX
       "LDR_*",
     "LIBPATH",      "LIBPATH",
 #endif /* _AIX */  #endif
 #ifdef __APPLE__  #ifdef __APPLE__
     "DYLD_*",      "DYLD_*",
 #endif  #endif
Line 112 
Line 144 
 #endif /* HAVE_KERB4 */  #endif /* HAVE_KERB4 */
 #ifdef HAVE_KERB5  #ifdef HAVE_KERB5
     "KRB5_CONFIG*",      "KRB5_CONFIG*",
       "KRB5_KTNAME",
 #endif /* HAVE_KERB5 */  #endif /* HAVE_KERB5 */
 #ifdef HAVE_SECURID  #ifdef HAVE_SECURID
     "VAR_ACE",      "VAR_ACE",
     "USR_ACE",      "USR_ACE",
     "DLC_ACE",      "DLC_ACE",
 #endif /* HAVE_SECURID */  #endif /* HAVE_SECURID */
     "TERMINFO",      "TERMINFO",                 /* terminfo, exclusive path to terminfo files */
     "TERMINFO_DIRS",      "TERMINFO_DIRS",            /* terminfo, path(s) to terminfo files */
     "TERMPATH",      "TERMPATH",                 /* termcap, path(s) to termcap files */
     "TERMCAP",                  /* XXX - only if it starts with '/' */      "TERMCAP",                  /* XXX - only if it starts with '/' */
     "ENV",      "ENV",                      /* ksh, file to source before script runs */
     "BASH_ENV",      "BASH_ENV",                 /* bash, file to source before script runs */
       "PS4",                      /* bash, prefix for lines in xtrace mode */
       "GLOBIGNORE",               /* bash, globbing patterns to ignore */
       "SHELLOPTS",                /* bash, extra command line options */
       "JAVA_TOOL_OPTIONS",        /* java, extra command line options */
       "PERLIO_DEBUG ",            /* perl, debugging output file */
       "PERLLIB",                  /* perl, search path for modules/includes */
       "PERL5LIB",                 /* perl 5, search path for modules/includes */
       "PERL5OPT",                 /* perl 5, extra command line options */
       "PERL5DB",                  /* perl 5, command used to load debugger */
       "FPATH",                    /* ksh, search path for functions */
       "NULLCMD",                  /* zsh, command for null file redirection */
       "READNULLCMD",              /* zsh, command for null file redirection */
       "ZDOTDIR",                  /* zsh, search path for dot files */
       "TMPPREFIX",                /* zsh, prefix for temporary files */
       "PYTHONHOME",               /* python, module search path */
       "PYTHONPATH",               /* python, search path */
       "PYTHONINSPEC",             /* python, allow inspection */
       "RUBYLIB",                  /* ruby, library load path */
       "RUBYOPT",                  /* ruby, extra command line options */
     NULL      NULL
 };  };
   
Line 131 
Line 183 
  * Default table of variables to check for '%' and '/' characters.   * Default table of variables to check for '%' and '/' characters.
  */   */
 static const char *initial_checkenv_table[] = {  static const char *initial_checkenv_table[] = {
     "LC_*",      "COLORTERM",
     "LANG",      "LANG",
     "LANGUAGE",      "LANGUAGE",
       "LC_*",
       "LINGUAS",
       "TERM",
     NULL      NULL
 };  };
   
 static char **new_environ;      /* Modified copy of the environment */  
 static size_t env_size;         /* size of new_environ in char **'s */  
 static size_t env_len;          /* number of slots used, not counting NULL */  
   
 /*  /*
  * Zero out environment and replace with a minimal set of KRB5CCNAME   * Default table of variables to preserve in the environment.
  * USER, LOGNAME, HOME, TZ, PATH (XXX - should just set path to default)  
  * May set user_path, user_shell, and/or user_prompt as side effects.  
  */   */
 char **  static const char *initial_keepenv_table[] = {
 zero_env(envp)      "COLORS",
     char **envp;      "DISPLAY",
 {      "HOSTNAME",
     static char *newenv[9];      "KRB5CCNAME",
     char **ep, **nep = newenv;      "LS_COLORS",
     char **ne_last = &newenv[(sizeof(newenv) / sizeof(newenv[0])) - 1];      "MAIL",
     extern char *prev_user;      "PATH",
       "PS1",
       "PS2",
       "TZ",
       "XAUTHORITY",
       "XAUTHORIZATION",
       NULL
   };
   
     for (ep = envp; *ep; ep++) {  
         switch (**ep) {  
             case 'H':  
                 if (strncmp("HOME=", *ep, 5) == 0)  
                     break;  
                 continue;  
             case 'K':  
                 if (strncmp("KRB5CCNAME=", *ep, 11) == 0)  
                     break;  
                 continue;  
             case 'L':  
                 if (strncmp("LOGNAME=", *ep, 8) == 0)  
                     break;  
                 continue;  
             case 'P':  
                 if (strncmp("PATH=", *ep, 5) == 0) {  
                     user_path = *ep + 5;  
                     /* XXX - set to sane default instead of user's? */  
                     break;  
                 }  
                 continue;  
             case 'S':  
                 if (strncmp("SHELL=", *ep, 6) == 0)  
                     user_shell = *ep + 6;  
                 else if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0)  
                     user_prompt = *ep + 12;  
                 else if (strncmp("SUDO_USER=", *ep, 10) == 0)  
                     prev_user = *ep + 10;  
                 continue;  
             case 'T':  
                 if (strncmp("TZ=", *ep, 3) == 0)  
                     break;  
                 continue;  
             case 'U':  
                 if (strncmp("USER=", *ep, 5) == 0)  
                     break;  
                 continue;  
             default:  
                 continue;  
         }  
   
         /* Deal with multiply defined variables (take first instance) */  
         for (nep = newenv; *nep; nep++) {  
             if (**nep == **ep)  
                 break;  
         }  
         if (*nep == NULL) {  
             if (nep < ne_last)  
                 *nep++ = *ep;  
             else  
                 errx(1, "internal error, attempt to write outside newenv");  
         }  
     }  
   
 #ifdef HAVE_LDAP  
     /*  
      * Prevent OpenLDAP from reading any user dotfiles  
      * or files in the current directory.  
      *  
      */  
     if (nep < ne_last)  
         *nep++ = "LDAPNOINIT=1";  
     else  
         errx(1, "internal error, attempt to write outside newenv");  
 #endif  
   
     return(&newenv[0]);  
 }  
   
 /*  /*
  * Given a variable and value, allocate and format an environment string.   * Given a variable and value, allocate and format an environment string.
  */   */
Line 275 
Line 262 
 }  }
   
 /*  /*
  * Insert str into new_environ, assumes str has an '=' in it.   * Insert str into e->envp, assumes str has an '=' in it.
  * NOTE: no other routines may modify new_environ, env_size, or env_len.  
  */   */
 static void  static void
 insert_env(str, dupcheck)  insert_env(str, e, dupcheck)
     char *str;      char *str;
       struct environment *e;
     int dupcheck;      int dupcheck;
 {  {
     char **nep;      char **nep;
     size_t varlen;      size_t varlen;
   
     /* Make sure there is room for the new entry plus a NULL. */      /* Make sure there is room for the new entry plus a NULL. */
     if (env_len + 2 > env_size) {      if (e->env_len + 2 > e->env_size) {
         env_size += 128;          e->env_size += 128;
         new_environ = erealloc3(new_environ, env_size, sizeof(char *));          e->envp = erealloc3(e->envp, e->env_size, sizeof(char *));
     }      }
   
     if (dupcheck) {      if (dupcheck) {
             varlen = (strchr(str, '=') - str) + 1;              varlen = (strchr(str, '=') - str) + 1;
   
             for (nep = new_environ; *nep; nep++) {              for (nep = e->envp; *nep; nep++) {
                 if (strncmp(str, *nep, varlen) == 0) {                  if (strncmp(str, *nep, varlen) == 0) {
                     *nep = str;                      *nep = str;
                     return;                      return;
                 }                  }
             }              }
     } else      } else
         nep = &new_environ[env_len];          nep = e->envp + e->env_len;
   
     env_len++;      e->env_len++;
     *nep++ = str;      *nep++ = str;
     *nep = NULL;      *nep = NULL;
 }  }
   
 /*  /*
    * Check the env_delete blacklist.
    * Returns TRUE if the variable was found, else false.
    */
   static int
   matches_env_delete(var)
       const char *var;
   {
       struct list_member *cur;
       size_t len;
       int iswild, match = FALSE;
   
       /* Skip anything listed in env_delete. */
       for (cur = def_env_delete; cur; cur = cur->next) {
           len = strlen(cur->value);
           /* Deal with '*' wildcard */
           if (cur->value[len - 1] == '*') {
               len--;
               iswild = TRUE;
           } else
               iswild = FALSE;
           if (strncmp(cur->value, var, len) == 0 &&
               (iswild || var[len] == '=')) {
               match = TRUE;
               break;
           }
       }
       return(match);
   }
   
   /*
    * Apply the env_check list.
    * Returns TRUE if the variable is allowed, FALSE if denied
    * or -1 if no match.
    */
   static int
   matches_env_check(var)
       const char *var;
   {
       struct list_member *cur;
       size_t len;
       int iswild, keepit = -1;
   
       for (cur = def_env_check; cur; cur = cur->next) {
           len = strlen(cur->value);
           /* Deal with '*' wildcard */
           if (cur->value[len - 1] == '*') {
               len--;
               iswild = TRUE;
           } else
               iswild = FALSE;
           if (strncmp(cur->value, var, len) == 0 &&
               (iswild || var[len] == '=')) {
               keepit = !strpbrk(var, "/%");
               break;
           }
       }
       return(keepit);
   }
   
   /*
    * Check the env_keep list.
    * Returns TRUE if the variable is allowed else FALSE.
    */
   static int
   matches_env_keep(var)
       const char *var;
   {
       struct list_member *cur;
       size_t len;
       int iswild, keepit = FALSE;
   
       for (cur = def_env_keep; cur; cur = cur->next) {
           len = strlen(cur->value);
           /* Deal with '*' wildcard */
           if (cur->value[len - 1] == '*') {
               len--;
               iswild = TRUE;
           } else
               iswild = FALSE;
           if (strncmp(cur->value, var, len) == 0 &&
               (iswild || var[len] == '=')) {
               keepit = TRUE;
               break;
           }
       }
       return(keepit);
   }
   
   /*
  * Build a new environment and ether clear potentially dangerous   * Build a new environment and ether clear potentially dangerous
  * variables from the old one or start with a clean slate.   * variables from the old one or start with a clean slate.
  * Also adds sudo-specific variables (SUDO_*).   * Also adds sudo-specific variables (SUDO_*).
Line 321 
Line 397 
     int noexec;      int noexec;
 {  {
     char **ep, *cp, *ps1;      char **ep, *cp, *ps1;
     int okvar, iswild, didvar;      unsigned int didvar;
     size_t len;  
     struct list_member *cur;  
   
     /*      /*
      * Either clean out the environment or reset to a safe default.       * Either clean out the environment or reset to a safe default.
      */       */
     ps1 = NULL;      ps1 = NULL;
     didvar = 0;      didvar = 0;
       memset(&env, 0, sizeof(env));
     if (def_env_reset) {      if (def_env_reset) {
         int keepit;  
   
         /* Pull in vars we want to keep from the old environment. */          /* Pull in vars we want to keep from the old environment. */
         for (ep = envp; *ep; ep++) {          for (ep = envp; *ep; ep++) {
             keepit = 0;              int keepit;
   
             /* Skip variables with values beginning with () (bash functions) */              /* Skip variables with values beginning with () (bash functions) */
             if ((cp = strchr(*ep, '=')) != NULL) {              if ((cp = strchr(*ep, '=')) != NULL) {
Line 343 
Line 416 
                     continue;                      continue;
             }              }
   
             for (cur = def_env_keep; cur; cur = cur->next) {              /*
                 len = strlen(cur->value);               * First check certain variables for '%' and '/' characters.
                 /* Deal with '*' wildcard */               * If no match there, check the keep list.
                 if (cur->value[len - 1] == '*') {               * If nothing matched, we remove it from the environment.
                     len--;               */
                     iswild = 1;              keepit = matches_env_check(*ep);
                 } else              if (keepit == -1)
                     iswild = 0;                  keepit = matches_env_keep(*ep);
                 if (strncmp(cur->value, *ep, len) == 0 &&  
                     (iswild || (*ep)[len] == '=')) {  
                     /* We always preserve TERM, no special treatment needed. */  
                     if (strncmp(*ep, "TERM=", 5) != 0)  
                         keepit = 1;  
                     break;  
                 }  
             }  
   
             /* For SUDO_PS1 -> PS1 conversion. */              /* For SUDO_PS1 -> PS1 conversion. */
             if (strncmp(*ep, "SUDO_PS1=", 8) == 0)              if (strncmp(*ep, "SUDO_PS1=", 8) == 0)
Line 371 
Line 436 
                         if (strncmp(*ep, "HOME=", 5) == 0)                          if (strncmp(*ep, "HOME=", 5) == 0)
                             SET(didvar, DID_HOME);                              SET(didvar, DID_HOME);
                         break;                          break;
                       case 'L':
                           if (strncmp(*ep, "LOGNAME=", 8) == 0)
                               SET(didvar, DID_LOGNAME);
                           break;
                       case 'P':
                           if (strncmp(*ep, "PATH=", 5) == 0)
                               SET(didvar, DID_PATH);
                           break;
                     case 'S':                      case 'S':
                         if (strncmp(*ep, "SHELL=", 6) == 0)                          if (strncmp(*ep, "SHELL=", 6) == 0)
                             SET(didvar, DID_SHELL);                              SET(didvar, DID_SHELL);
                         break;                          break;
                     case 'L':                      case 'T':
                         if (strncmp(*ep, "LOGNAME=", 8) == 0)                          if (strncmp(*ep, "TERM=", 5) == 0)
                             SET(didvar, DID_LOGNAME);                              SET(didvar, DID_TERM);
                         break;                          break;
                     case 'U':                      case 'U':
                         if (strncmp(*ep, "USER=", 5) == 0)                          if (strncmp(*ep, "USER=", 5) == 0)
                             SET(didvar, DID_USER);                              SET(didvar, DID_USER);
                           if (strncmp(*ep, "USERNAME=", 5) == 0)
                               SET(didvar, DID_USERNAME);
                         break;                          break;
                 }                  }
                 insert_env(*ep, 0);                  insert_env(*ep, &env, 0);
             } else {  
                 /* Preserve TERM and PATH, ignore anything else. */  
                 if (!ISSET(didvar, DID_TERM) && strncmp(*ep, "TERM=", 5) == 0) {  
                     insert_env(*ep, 0);  
                     SET(didvar, DID_TERM);  
                 } else if (!ISSET(didvar, DID_PATH) && strncmp(*ep, "PATH=", 5) == 0) {  
                     insert_env(*ep, 0);  
                     SET(didvar, DID_PATH);  
                 }  
             }              }
         }          }
           didvar |= didvar << 8;          /* convert DID_* to KEPT_* */
   
         /*          /*
          * Add in defaults.  In -i mode these come from the runas user,           * Add in defaults.  In -i mode these come from the runas user,
Line 403 
Line 470 
          * on sudoers options).           * on sudoers options).
          */           */
         if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {          if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
             insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), 0);              insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), &env,
             insert_env(format_env("SHELL", runas_pw->pw_shell, VNULL), 0);                  ISSET(didvar, DID_HOME));
             insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), 0);              insert_env(format_env("SHELL", runas_pw->pw_shell, VNULL), &env,
             insert_env(format_env("USER", runas_pw->pw_name, VNULL), 0);                  ISSET(didvar, DID_SHELL));
               insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), &env,
                   ISSET(didvar, DID_LOGNAME));
               insert_env(format_env("USER", runas_pw->pw_name, VNULL), &env,
                   ISSET(didvar, DID_USER));
               insert_env(format_env("USERNAME", runas_pw->pw_name, VNULL), &env,
                   ISSET(didvar, DID_USERNAME));
         } else {          } else {
             if (!ISSET(didvar, DID_HOME))              if (!ISSET(didvar, DID_HOME))
                 insert_env(format_env("HOME", user_dir, VNULL), 0);                  insert_env(format_env("HOME", user_dir, VNULL), &env, 0);
             if (!ISSET(didvar, DID_SHELL))              if (!ISSET(didvar, DID_SHELL))
                 insert_env(format_env("SHELL", sudo_user.pw->pw_shell, VNULL), 0);                  insert_env(format_env("SHELL", sudo_user.pw->pw_shell, VNULL),
                       &env, 0);
             if (!ISSET(didvar, DID_LOGNAME))              if (!ISSET(didvar, DID_LOGNAME))
                 insert_env(format_env("LOGNAME", user_name, VNULL), 0);                  insert_env(format_env("LOGNAME", user_name, VNULL), &env, 0);
             if (!ISSET(didvar, DID_USER))              if (!ISSET(didvar, DID_USER))
                 insert_env(format_env("USER", user_name, VNULL), 0);                  insert_env(format_env("USER", user_name, VNULL), &env, 0);
               if (!ISSET(didvar, DID_USERNAME))
                   insert_env(format_env("USERNAME", user_name, VNULL), &env, 0);
         }          }
     } else {      } else {
         /*          /*
Line 423 
Line 499 
          * env_check.           * env_check.
          */           */
         for (ep = envp; *ep; ep++) {          for (ep = envp; *ep; ep++) {
             okvar = 1;              int okvar;
   
             /* Skip variables with values beginning with () (bash functions) */              /* Skip variables with values beginning with () (bash functions) */
             if ((cp = strchr(*ep, '=')) != NULL) {              if ((cp = strchr(*ep, '=')) != NULL) {
Line 431 
Line 507 
                     continue;                      continue;
             }              }
   
             /* Skip anything listed in env_delete. */              /*
             for (cur = def_env_delete; cur && okvar; cur = cur->next) {               * First check variables against the blacklist in env_delete.
                 len = strlen(cur->value);               * If no match there check for '%' and '/' characters.
                 /* Deal with '*' wildcard */               */
                 if (cur->value[len - 1] == '*') {              okvar = matches_env_delete(*ep) != TRUE;
                     len--;              if (okvar)
                     iswild = 1;                  okvar = matches_env_check(*ep) != FALSE;
                 } else  
                     iswild = 0;  
                 if (strncmp(cur->value, *ep, len) == 0 &&  
                     (iswild || (*ep)[len] == '=')) {  
                     okvar = 0;  
                 }  
             }  
   
             /* Check certain variables for '%' and '/' characters. */  
             for (cur = def_env_check; cur && okvar; cur = cur->next) {  
                 len = strlen(cur->value);  
                 /* Deal with '*' wildcard */  
                 if (cur->value[len - 1] == '*') {  
                     len--;  
                     iswild = 1;  
                 } else  
                     iswild = 0;  
                 if (strncmp(cur->value, *ep, len) == 0 &&  
                     (iswild || (*ep)[len] == '=') &&  
                     strpbrk(*ep, "/%")) {  
                     okvar = 0;  
                 }  
             }  
   
             if (okvar) {              if (okvar) {
                 if (strncmp(*ep, "SUDO_PS1=", 9) == 0)                  if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
                     ps1 = *ep + 5;                      ps1 = *ep + 5;
Line 469 
Line 522 
                     SET(didvar, DID_PATH);                      SET(didvar, DID_PATH);
                 else if (strncmp(*ep, "TERM=", 5) == 0)                  else if (strncmp(*ep, "TERM=", 5) == 0)
                     SET(didvar, DID_TERM);                      SET(didvar, DID_TERM);
                 insert_env(*ep, 0);                  insert_env(*ep, &env, 0);
             }              }
         }          }
     }      }
     /* Provide default values for $TERM and $PATH if they are not set. */  
     if (!ISSET(didvar, DID_TERM))  
         insert_env("TERM=unknown", 0);  
     if (!ISSET(didvar, DID_PATH))  
         insert_env(format_env("PATH", _PATH_DEFPATH, VNULL), 0);  
   
 #ifdef SECURE_PATH  #ifdef SECURE_PATH
     /* Replace the PATH envariable with a secure one. */      /* Replace the PATH envariable with a secure one. */
     insert_env(format_env("PATH", SECURE_PATH, VNULL), 1);      if (!user_is_exempt()) {
           insert_env(format_env("PATH", SECURE_PATH, VNULL), &env, 1);
           SET(didvar, DID_PATH);
       }
 #endif  #endif
   
     /* Set $USER and $LOGNAME to target if "set_logname" is true. */      /* Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is true. */
     if (def_set_logname && runas_pw->pw_name) {      if (def_set_logname && runas_pw->pw_name) {
         insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), 1);          if (!ISSET(didvar, KEPT_LOGNAME))
         insert_env(format_env("USER", runas_pw->pw_name, VNULL), 1);              insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), &env, 1);
           if (!ISSET(didvar, KEPT_USER))
               insert_env(format_env("USER", runas_pw->pw_name, VNULL), &env, 1);
           if (!ISSET(didvar, KEPT_USERNAME))
               insert_env(format_env("USERNAME", runas_pw->pw_name, VNULL), &env, 1);
     }      }
   
     /* Set $HOME for `sudo -H'.  Only valid at PERM_FULL_RUNAS. */      /* Set $HOME for `sudo -H'.  Only valid at PERM_FULL_RUNAS. */
     if (ISSET(sudo_mode, MODE_RESET_HOME) && runas_pw->pw_dir)      if (runas_pw->pw_dir) {
         insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), 1);          if (ISSET(sudo_mode, MODE_RESET_HOME) ||
               (ISSET(sudo_mode, MODE_RUN) && (def_always_set_home ||
               (ISSET(sudo_mode, MODE_SHELL) && def_set_home))))
               insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), &env, 1);
       }
   
       /* Provide default values for $TERM and $PATH if they are not set. */
       if (!ISSET(didvar, DID_TERM))
           insert_env("TERM=unknown", &env, 0);
       if (!ISSET(didvar, DID_PATH))
           insert_env(format_env("PATH", _PATH_DEFPATH, VNULL), &env, 0);
   
     /*      /*
      * Preload a noexec file?  For a list of LD_PRELOAD-alikes, see       * Preload a noexec file?  For a list of LD_PRELOAD-alikes, see
      * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html       * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
Line 501 
Line 566 
      */       */
     if (noexec && def_noexec_file != NULL) {      if (noexec && def_noexec_file != NULL) {
 #if defined(__darwin__) || defined(__APPLE__)  #if defined(__darwin__) || defined(__APPLE__)
         insert_env(format_env("DYLD_INSERT_LIBRARIES", def_noexec_file, VNULL), 1);          insert_env(format_env("DYLD_INSERT_LIBRARIES", def_noexec_file, VNULL),
         insert_env(format_env("DYLD_FORCE_FLAT_NAMESPACE", VNULL), 1);              &env, 1);
           insert_env(format_env("DYLD_FORCE_FLAT_NAMESPACE", VNULL), &env, 1);
 #else  #else
 # if defined(__osf__) || defined(__sgi)  # if defined(__osf__) || defined(__sgi)
         insert_env(format_env("_RLD_LIST", def_noexec_file, ":DEFAULT", VNULL), 1);          insert_env(format_env("_RLD_LIST", def_noexec_file, ":DEFAULT", VNULL),
               &env, 1);
 # else  # else
         insert_env(format_env("LD_PRELOAD", def_noexec_file, VNULL), 1);  #  ifdef _AIX
 # endif          insert_env(format_env("LDR_PRELOAD", def_noexec_file, VNULL), &env, 1);
 #endif  #  else
           insert_env(format_env("LD_PRELOAD", def_noexec_file, VNULL), &env, 1);
   #  endif /* _AIX */
   # endif /* __osf__ || __sgi */
   #endif /* __darwin__ || __APPLE__ */
     }      }
   
     /* Set PS1 if SUDO_PS1 is set. */      /* Set PS1 if SUDO_PS1 is set. */
     if (ps1)      if (ps1)
         insert_env(ps1, 1);          insert_env(ps1, &env, 1);
   
     /* Add the SUDO_COMMAND envariable (cmnd + args). */      /* Add the SUDO_COMMAND envariable (cmnd + args). */
     if (user_args)      if (user_args)
         insert_env(format_env("SUDO_COMMAND", user_cmnd, " ", user_args, VNULL), 1);          insert_env(format_env("SUDO_COMMAND", user_cmnd, " ", user_args, VNULL),
               &env, 1);
     else      else
         insert_env(format_env("SUDO_COMMAND", user_cmnd, VNULL), 1);          insert_env(format_env("SUDO_COMMAND", user_cmnd, VNULL), &env, 1);
   
     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */      /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
     insert_env(format_env("SUDO_USER", user_name, VNULL), 1);      insert_env(format_env("SUDO_USER", user_name, VNULL), &env, 1);
     easprintf(&cp, "SUDO_UID=%lu", (unsigned long) user_uid);      easprintf(&cp, "SUDO_UID=%lu", (unsigned long) user_uid);
     insert_env(cp, 1);      insert_env(cp, &env, 1);
     easprintf(&cp, "SUDO_GID=%lu", (unsigned long) user_gid);      easprintf(&cp, "SUDO_GID=%lu", (unsigned long) user_gid);
     insert_env(cp, 1);      insert_env(cp, &env, 1);
   
     return(new_environ);      return(env.envp);
 }  }
   
   char **
   insert_env_vars(envp, env_vars)
       char **envp;
       struct list_member *env_vars;
   {
       struct list_member *cur;
   
       if (env_vars == NULL)
           return (envp);
   
       /*
        * Make sure we still own the environment and steal it back if not.
        */
       if (env.envp != envp) {
           size_t evlen;
           char **ep;
   
           for (ep = envp; *ep != NULL; ep++)
               continue;
           evlen = ep - envp;
           if (evlen + 1 > env.env_size) {
               efree(env.envp);
               env.env_size = evlen + 1 + 128;
               env.envp = emalloc2(env.env_size, sizeof(char *));
           }
           memcpy(env.envp, envp, evlen + 1);
           env.env_len = evlen;
       }
   
       /* Add user-specified environment variables. */
       for (cur = env_vars; cur != NULL; cur = cur->next)
           insert_env(cur->value, &env, 1);
   
       return(env.envp);
   }
   
   /*
    * Validate the list of environment variables passed in on the command
    * line against env_delete, env_check, and env_keep.
    * Calls log_error() if any specified variables are not allowed.
    */
 void  void
   validate_env_vars(env_vars)
       struct list_member *env_vars;
   {
       struct list_member *var;
       char *eq, *bad = NULL;
       size_t len, blen = 0, bsize = 0;
       int okvar;
   
       for (var = env_vars; var != NULL; var = var->next) {
   #ifdef SECURE_PATH
           if (!user_is_exempt() && strncmp(var->value, "PATH=", 5) == 0) {
               okvar = FALSE;
           } else
   #endif
           if (def_env_reset) {
               okvar = matches_env_check(var->value);
               if (okvar == -1)
                   okvar = matches_env_keep(var->value);
           } else {
               okvar = matches_env_delete(var->value) == FALSE;
               if (okvar == FALSE)
                   okvar = matches_env_check(var->value) != FALSE;
           }
           if (okvar == FALSE) {
               /* Not allowed, add to error string, allocating as needed. */
               if ((eq = strchr(var->value, '=')) != NULL)
                   *eq = '\0';
               len = strlen(var->value) + 2;
               if (blen + len >= bsize) {
                   do {
                       bsize += 1024;
                   } while (blen + len >= bsize);
                   bad = erealloc(bad, bsize);
                   bad[blen] = '\0';
               }
               strlcat(bad, var->value, bsize);
               strlcat(bad, ", ", bsize);
               blen += len;
               if (eq != NULL)
                   *eq = '=';
           }
       }
       if (bad != NULL) {
           bad[blen - 2] = '\0';           /* remove trailing ", " */
           log_error(NO_MAIL,
               "sorry, you are not allowed to set the following environment variables: %s", bad);
           /* NOTREACHED */
           efree(bad);
       }
   }
   
   void
 init_envtables()  init_envtables()
 {  {
     struct list_member *cur;      struct list_member *cur;
     const char **p;      const char **p;
   
     /* Fill in "env_delete" variable. */      /* Fill in the "env_delete" list. */
     for (p = initial_badenv_table; *p; p++) {      for (p = initial_badenv_table; *p; p++) {
         cur = emalloc(sizeof(struct list_member));          cur = emalloc(sizeof(struct list_member));
         cur->value = estrdup(*p);          cur->value = estrdup(*p);
Line 546 
Line 711 
         def_env_delete = cur;          def_env_delete = cur;
     }      }
   
     /* Fill in "env_check" variable. */      /* Fill in the "env_check" list. */
     for (p = initial_checkenv_table; *p; p++) {      for (p = initial_checkenv_table; *p; p++) {
         cur = emalloc(sizeof(struct list_member));          cur = emalloc(sizeof(struct list_member));
         cur->value = estrdup(*p);          cur->value = estrdup(*p);
         cur->next = def_env_check;          cur->next = def_env_check;
         def_env_check = cur;          def_env_check = cur;
       }
   
       /* Fill in the "env_keep" list. */
       for (p = initial_keepenv_table; *p; p++) {
           cur = emalloc(sizeof(struct list_member));
           cur->value = estrdup(*p);
           cur->next = def_env_keep;
           def_env_keep = cur;
     }      }
 }  }

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.14