Merge tag 'debian/1.8.5p2-1' into squeeze
[debian/sudo] / plugins / sudoers / env.c
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 #ifdef HAVE_LOGIN_CAP_H
46 # include <login_cap.h>
47 # ifndef LOGIN_SETENV
48 #  define LOGIN_SETENV  0
49 # endif
50 #endif /* HAVE_LOGIN_CAP_H */
51 #include <ctype.h>
52 #include <errno.h>
53 #include <pwd.h>
54
55 #include "sudoers.h"
56
57 /*
58  * Flags used in rebuild_env()
59  */
60 #undef DID_TERM
61 #define DID_TERM        0x0001
62 #undef DID_PATH
63 #define DID_PATH        0x0002
64 #undef DID_HOME
65 #define DID_HOME        0x0004
66 #undef DID_SHELL
67 #define DID_SHELL       0x0008
68 #undef DID_LOGNAME
69 #define DID_LOGNAME     0x0010
70 #undef DID_USER
71 #define DID_USER        0x0020
72 #undef DID_USERNAME
73 #define DID_USERNAME    0x0040
74 #undef DID_MAIL
75 #define DID_MAIL        0x0080
76 #undef DID_MAX
77 #define DID_MAX         0x00ff
78
79 #undef KEPT_TERM
80 #define KEPT_TERM       0x0100
81 #undef KEPT_PATH
82 #define KEPT_PATH       0x0200
83 #undef KEPT_HOME
84 #define KEPT_HOME       0x0400
85 #undef KEPT_SHELL
86 #define KEPT_SHELL      0x0800
87 #undef KEPT_LOGNAME
88 #define KEPT_LOGNAME    0x1000
89 #undef KEPT_USER
90 #define KEPT_USER       0x2000
91 #undef KEPT_USERNAME
92 #define KEPT_USERNAME   0x4000
93 #undef KEPT_MAIL
94 #define KEPT_MAIL       0x8000
95 #undef KEPT_MAX
96 #define KEPT_MAX        0xff00
97
98 struct environment {
99     char * const *old_envp;     /* pointer the environment we passed back */
100     char **envp;                /* pointer to the new environment */
101     size_t env_size;            /* size of new_environ in char **'s */
102     size_t env_len;             /* number of slots used, not counting NULL */
103 };
104
105 /*
106  * Copy of the sudo-managed environment.
107  */
108 static struct environment env;
109
110 /*
111  * Default table of "bad" variables to remove from the environment.
112  * XXX - how to omit TERMCAP if it starts with '/'?
113  */
114 static const char *initial_badenv_table[] = {
115     "IFS",
116     "CDPATH",
117     "LOCALDOMAIN",
118     "RES_OPTIONS",
119     "HOSTALIASES",
120     "NLSPATH",
121     "PATH_LOCALE",
122     "LD_*",
123     "_RLD*",
124 #ifdef __hpux
125     "SHLIB_PATH",
126 #endif /* __hpux */
127 #ifdef _AIX
128     "LDR_*",
129     "LIBPATH",
130     "AUTHSTATE",
131 #endif
132 #ifdef __APPLE__
133     "DYLD_*",
134 #endif
135 #ifdef HAVE_KERB5
136     "KRB5_CONFIG*",
137     "KRB5_KTNAME",
138 #endif /* HAVE_KERB5 */
139 #ifdef HAVE_SECURID
140     "VAR_ACE",
141     "USR_ACE",
142     "DLC_ACE",
143 #endif /* HAVE_SECURID */
144     "TERMINFO",                 /* terminfo, exclusive path to terminfo files */
145     "TERMINFO_DIRS",            /* terminfo, path(s) to terminfo files */
146     "TERMPATH",                 /* termcap, path(s) to termcap files */
147     "TERMCAP",                  /* XXX - only if it starts with '/' */
148     "ENV",                      /* ksh, file to source before script runs */
149     "BASH_ENV",                 /* bash, file to source before script runs */
150     "PS4",                      /* bash, prefix for lines in xtrace mode */
151     "GLOBIGNORE",               /* bash, globbing patterns to ignore */
152     "SHELLOPTS",                /* bash, extra command line options */
153     "JAVA_TOOL_OPTIONS",        /* java, extra command line options */
154     "PERLIO_DEBUG ",            /* perl, debugging output file */
155     "PERLLIB",                  /* perl, search path for modules/includes */
156     "PERL5LIB",                 /* perl 5, search path for modules/includes */
157     "PERL5OPT",                 /* perl 5, extra command line options */
158     "PERL5DB",                  /* perl 5, command used to load debugger */
159     "FPATH",                    /* ksh, search path for functions */
160     "NULLCMD",                  /* zsh, command for null file redirection */
161     "READNULLCMD",              /* zsh, command for null file redirection */
162     "ZDOTDIR",                  /* zsh, search path for dot files */
163     "TMPPREFIX",                /* zsh, prefix for temporary files */
164     "PYTHONHOME",               /* python, module search path */
165     "PYTHONPATH",               /* python, search path */
166     "PYTHONINSPECT",            /* python, allow inspection */
167     "PYTHONUSERBASE",           /* python, per user site-packages directory */
168     "RUBYLIB",                  /* ruby, library load path */
169     "RUBYOPT",                  /* ruby, extra command line options */
170     NULL
171 };
172
173 /*
174  * Default table of variables to check for '%' and '/' characters.
175  */
176 static const char *initial_checkenv_table[] = {
177     "COLORTERM",
178     "LANG",
179     "LANGUAGE",
180     "LC_*",
181     "LINGUAS",
182     "TERM",
183     NULL
184 };
185
186 /*
187  * Default table of variables to preserve in the environment.
188  */
189 static const char *initial_keepenv_table[] = {
190     "COLORS",
191     "DISPLAY",
192     "HOSTNAME",
193     "KRB5CCNAME",
194     "LS_COLORS",
195     "PATH",
196     "PS1",
197     "PS2",
198     "TZ",
199     "XAUTHORITY",
200     "XAUTHORIZATION",
201     NULL
202 };
203
204 /*
205  * Initialize env based on envp.
206  */
207 void
208 env_init(char * const envp[])
209 {
210     char * const *ep;
211     size_t len;
212     debug_decl(env_init, SUDO_DEBUG_ENV)
213
214     if (envp == NULL) {
215         /* Reset to initial state but keep a pointer to what we allocated. */
216         envp = env.envp;
217         memset(&env, 0, sizeof(env));
218         env.old_envp = envp;
219     } else {
220         /* Make private copy of envp. */
221         for (ep = envp; *ep != NULL; ep++)
222             continue;
223         len = (size_t)(ep - envp);
224
225         env.env_len = len;
226         env.env_size = len + 1 + 128;
227         env.envp = emalloc2(env.env_size, sizeof(char *));
228 #ifdef ENV_DEBUG
229         memset(env.envp, 0, env.env_size * sizeof(char *));
230 #endif
231         memcpy(env.envp, envp, len * sizeof(char *));
232         env.envp[len] = '\0';
233
234         /* Free the old envp we allocated, if any. */
235         if (env.old_envp != NULL)
236             efree((void *)env.old_envp);
237     }
238
239     debug_return;
240 }
241
242 /*
243  * Getter for private copy of the environment.
244  */
245 char **
246 env_get(void)
247 {
248     return env.envp;
249 }
250
251 /*
252  * Similar to putenv(3) but operates on sudo's private copy of the
253  * environment (not environ) and it always overwrites.  The dupcheck param
254  * determines whether we need to verify that the variable is not already set.
255  * Will only overwrite an existing variable if overwrite is set.
256  * Does not include warnings or debugging to avoid recursive calls.
257  */
258 static int
259 sudo_putenv_nodebug(char *str, bool dupcheck, bool overwrite)
260 {
261     char **ep;
262     size_t len;
263     bool found = false;
264
265     /* Make sure there is room for the new entry plus a NULL. */
266     if (env.env_len + 2 > env.env_size) {
267         char **nenvp;
268         size_t nsize = env.env_size + 128;
269         nenvp = env.envp ? realloc(env.envp, nsize * sizeof(char *)) :
270             malloc(nsize * sizeof(char *));
271         if (nenvp == NULL) {
272             errno = ENOMEM;
273             return -1;
274         }
275         env.envp = nenvp;
276         env.env_size = nsize;
277 #ifdef ENV_DEBUG
278         memset(env.envp + env.env_len, 0,
279             (env.env_size - env.env_len) * sizeof(char *));
280 #endif
281     }
282
283 #ifdef ENV_DEBUG
284     if (env.envp[env.env_len] != NULL) {
285         errno = EINVAL;
286         return -1;
287     }
288 #endif
289
290     if (dupcheck) {
291         len = (strchr(str, '=') - str) + 1;
292         for (ep = env.envp; !found && *ep != NULL; ep++) {
293             if (strncmp(str, *ep, len) == 0) {
294                 if (overwrite)
295                     *ep = str;
296                 found = true;
297             }
298         }
299         /* Prune out duplicate variables. */
300         if (found && overwrite) {
301             while (*ep != NULL) {
302                 if (strncmp(str, *ep, len) == 0) {
303                     char **cur = ep;
304                     while ((*cur = *(cur + 1)) != NULL)
305                         cur++;
306                 } else {
307                     ep++;
308                 }
309             }
310             env.env_len = ep - env.envp;
311         }
312     }
313
314     if (!found) {
315         ep = env.envp + env.env_len;
316         env.env_len++;
317         *ep++ = str;
318         *ep = NULL;
319     }
320     return 0;
321 }
322
323 /*
324  * Similar to putenv(3) but operates on sudo's private copy of the
325  * environment (not environ) and it always overwrites.  The dupcheck param
326  * determines whether we need to verify that the variable is not already set.
327  * Will only overwrite an existing variable if overwrite is set.
328  */
329 static int
330 sudo_putenv(char *str, bool dupcheck, bool overwrite)
331 {
332     int rval;
333     debug_decl(sudo_putenv, SUDO_DEBUG_ENV)
334
335     rval = sudo_putenv_nodebug(str, dupcheck, overwrite);
336     if (rval == -1) {
337 #ifdef ENV_DEBUG
338         if (env.envp[env.env_len] != NULL)
339             errorx(1, _("sudo_putenv: corrupted envp, length mismatch"));
340 #endif
341         errorx(1, _("unable to allocate memory"));
342     }
343     debug_return_int(rval);
344 }
345
346 /*
347  * Similar to setenv(3) but operates on a private copy of the environment.
348  * The dupcheck param determines whether we need to verify that the variable
349  * is not already set.
350  */
351 static int
352 sudo_setenv2(const char *var, const char *val, bool dupcheck, bool overwrite)
353 {
354     char *estring;
355     size_t esize;
356     debug_decl(sudo_setenv2, SUDO_DEBUG_ENV)
357
358     esize = strlen(var) + 1 + strlen(val) + 1;
359     estring = emalloc(esize);
360
361     /* Build environment string and insert it. */
362     if (strlcpy(estring, var, esize) >= esize ||
363         strlcat(estring, "=", esize) >= esize ||
364         strlcat(estring, val, esize) >= esize) {
365
366         errorx(1, _("internal error, sudo_setenv2() overflow"));
367     }
368     debug_return_int(sudo_putenv(estring, dupcheck, overwrite));
369 }
370
371 /*
372  * Similar to setenv(3) but operates on a private copy of the environment.
373  * Does not include warnings or debugging to avoid recursive calls.
374  */
375 static int
376 sudo_setenv_nodebug(const char *var, const char *val, int overwrite)
377 {
378     char *estring;
379     size_t esize;
380
381     esize = strlen(var) + 1 + strlen(val) + 1;
382     if ((estring = malloc(esize)) == NULL) {
383         errno = ENOMEM;
384         return -1;
385     }
386
387     /* Build environment string and insert it. */
388     if (strlcpy(estring, var, esize) >= esize ||
389         strlcat(estring, "=", esize) >= esize ||
390         strlcat(estring, val, esize) >= esize) {
391
392         errno = EINVAL;
393         return -1;
394     }
395     return sudo_putenv_nodebug(estring, true, overwrite);
396 }
397
398 /*
399  * Similar to setenv(3) but operates on a private copy of the environment.
400  */
401 int
402 sudo_setenv(const char *var, const char *val, int overwrite)
403 {
404     int rval;
405     debug_decl(sudo_setenv, SUDO_DEBUG_ENV)
406
407     rval = sudo_setenv_nodebug(var, val, overwrite);
408     if (rval == -1) {
409         if (errno == EINVAL)
410             errorx(1, _("internal error, sudo_setenv() overflow"));
411         errorx(1, _("unable to allocate memory"));
412     }
413     debug_return_int(rval);
414 }
415
416 /*
417  * Similar to unsetenv(3) but operates on a private copy of the environment.
418  * Does not include warnings or debugging to avoid recursive calls.
419  */
420 static int
421 sudo_unsetenv_nodebug(const char *var)
422 {
423     char **ep = env.envp;
424     size_t len;
425
426     if (ep == NULL || var == NULL || *var == '\0' || strchr(var, '=') != NULL) {
427         errno = EINVAL;
428         return -1;
429     }
430
431     len = strlen(var);
432     while (*ep != NULL) {
433         if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') {
434             /* Found it; shift remainder + NULL over by one. */
435             char **cur = ep;
436             while ((*cur = *(cur + 1)) != NULL)
437                 cur++;
438             /* Keep going, could be multiple instances of the var. */
439         } else {
440             ep++;
441         }
442     }
443     return 0;
444 }
445
446 /*
447  * Similar to unsetenv(3) but operates on a private copy of the environment.
448  */
449 int
450 sudo_unsetenv(const char *name)
451 {
452     int rval;
453     debug_decl(sudo_unsetenv, SUDO_DEBUG_ENV)
454
455     rval = sudo_unsetenv_nodebug(name);
456
457     debug_return_int(rval);
458 }
459
460 /*
461  * Similar to getenv(3) but operates on a private copy of the environment.
462  * Does not include warnings or debugging to avoid recursive calls.
463  */
464 static char *
465 sudo_getenv_nodebug(const char *name)
466 {
467     char **ep, *val = NULL;
468     size_t namelen = 0;
469
470     if (env.env_len != 0) {
471         /* For BSD compatibility, treat '=' in name like end of string. */
472         while (name[namelen] != '\0' && name[namelen] != '=')
473             namelen++;
474         for (ep = env.envp; *ep != NULL; ep++) {
475             if (strncmp(*ep, name, namelen) == 0 && (*ep)[namelen] == '=') {
476                 val = *ep + namelen + 1;
477                 break;
478             }
479         }
480     }
481     return val;
482 }
483
484 /*
485  * Similar to getenv(3) but operates on a private copy of the environment.
486  */
487 char *
488 sudo_getenv(const char *name)
489 {
490     char *val;
491     debug_decl(sudo_getenv, SUDO_DEBUG_ENV)
492
493     val = sudo_getenv_nodebug(name);
494
495     debug_return_str(val);
496 }
497
498 /*
499  * Merge another environment with our private copy.
500  */
501 void
502 env_merge(char * const envp[], bool overwrite)
503 {
504     char * const *ep;
505     debug_decl(env_merge, SUDO_DEBUG_ENV)
506
507     for (ep = envp; *ep != NULL; ep++)
508         sudo_putenv(*ep, true, overwrite);
509
510     debug_return;
511 }
512
513 /*
514  * Check the env_delete blacklist.
515  * Returns true if the variable was found, else false.
516  */
517 static bool
518 matches_env_delete(const char *var)
519 {
520     struct list_member *cur;
521     size_t len;
522     bool iswild;
523     bool match = false;
524     debug_decl(matches_env_delete, SUDO_DEBUG_ENV)
525
526     /* Skip anything listed in env_delete. */
527     for (cur = def_env_delete; cur; cur = cur->next) {
528         len = strlen(cur->value);
529         /* Deal with '*' wildcard */
530         if (cur->value[len - 1] == '*') {
531             len--;
532             iswild = true;
533         } else
534             iswild = false;
535         if (strncmp(cur->value, var, len) == 0 &&
536             (iswild || var[len] == '=')) {
537             match = true;
538             break;
539         }
540     }
541     debug_return_bool(match);
542 }
543
544 /*
545  * Apply the env_check list.
546  * Returns true if the variable is allowed, false if denied
547  * or -1 if no match.
548  */
549 static int
550 matches_env_check(const char *var)
551 {
552     struct list_member *cur;
553     size_t len;
554     bool iswild;
555     int keepit = -1;
556     debug_decl(matches_env_check, SUDO_DEBUG_ENV)
557
558     for (cur = def_env_check; cur; cur = cur->next) {
559         len = strlen(cur->value);
560         /* Deal with '*' wildcard */
561         if (cur->value[len - 1] == '*') {
562             len--;
563             iswild = true;
564         } else
565             iswild = false;
566         if (strncmp(cur->value, var, len) == 0 &&
567             (iswild || var[len] == '=')) {
568             keepit = !strpbrk(var, "/%");
569             break;
570         }
571     }
572     debug_return_bool(keepit);
573 }
574
575 /*
576  * Check the env_keep list.
577  * Returns true if the variable is allowed else false.
578  */
579 static bool
580 matches_env_keep(const char *var)
581 {
582     struct list_member *cur;
583     size_t len;
584     bool iswild, keepit = false;
585     debug_decl(matches_env_keep, SUDO_DEBUG_ENV)
586
587     /* Preserve SHELL variable for "sudo -s". */
588     if (ISSET(sudo_mode, MODE_SHELL) && strncmp(var, "SHELL=", 6) == 0) {
589         keepit = true;
590         goto done;
591     }
592
593     for (cur = def_env_keep; cur; cur = cur->next) {
594         len = strlen(cur->value);
595         /* Deal with '*' wildcard */
596         if (cur->value[len - 1] == '*') {
597             len--;
598             iswild = true;
599         } else
600             iswild = false;
601         if (strncmp(cur->value, var, len) == 0 &&
602             (iswild || var[len] == '=')) {
603             keepit = true;
604             break;
605         }
606     }
607 done:
608     debug_return_bool(keepit);
609 }
610
611 /*
612  * Look up var in the env_delete and env_check.
613  * Returns true if we should delete the variable, else false.
614  */
615 static bool
616 env_should_delete(const char *var)
617 {
618     int delete_it;
619     debug_decl(env_should_delete, SUDO_DEBUG_ENV);
620
621     delete_it = matches_env_delete(var);
622     if (!delete_it)
623         delete_it = matches_env_check(var) == false;
624     debug_return_bool(delete_it);
625 }
626
627 /*
628  * Lookup var in the env_check and env_keep lists.
629  * Returns true if the variable is allowed else false.
630  */
631 static bool
632 env_should_keep(const char *var)
633 {
634     int keepit;
635     debug_decl(env_should_keep, SUDO_DEBUG_ENV)
636
637     keepit = matches_env_check(var);
638     if (keepit == -1)
639         keepit = matches_env_keep(var);
640
641     debug_return_bool(keepit == true);
642 }
643
644 static void
645 env_update_didvar(const char *ep, unsigned int *didvar)
646 {
647     switch (*ep) {
648         case 'H':
649             if (strncmp(ep, "HOME=", 5) == 0)
650                 SET(*didvar, DID_HOME);
651             break;
652         case 'L':
653             if (strncmp(ep, "LOGNAME=", 8) == 0)
654                 SET(*didvar, DID_LOGNAME);
655             break;
656         case 'M':
657             if (strncmp(ep, "MAIL=", 5) == 0)
658                 SET(*didvar, DID_MAIL);
659             break;
660         case 'P':
661             if (strncmp(ep, "PATH=", 5) == 0)
662                 SET(*didvar, DID_PATH);
663             break;
664         case 'S':
665             if (strncmp(ep, "SHELL=", 6) == 0)
666                 SET(*didvar, DID_SHELL);
667             break;
668         case 'T':
669             if (strncmp(ep, "TERM=", 5) == 0)
670                 SET(*didvar, DID_TERM);
671             break;
672         case 'U':
673             if (strncmp(ep, "USER=", 5) == 0)
674                 SET(*didvar, DID_USER);
675             if (strncmp(ep, "USERNAME=", 5) == 0)
676                 SET(*didvar, DID_USERNAME);
677             break;
678     }
679 }
680
681 /*
682  * Build a new environment and ether clear potentially dangerous
683  * variables from the old one or start with a clean slate.
684  * Also adds sudo-specific variables (SUDO_*).
685  */
686 void
687 rebuild_env(void)
688 {
689     char **old_envp, **ep, *cp, *ps1;
690     char idbuf[MAX_UID_T_LEN];
691     unsigned int didvar;
692     bool reset_home = false;
693
694     /*
695      * Either clean out the environment or reset to a safe default.
696      */
697     ps1 = NULL;
698     didvar = 0;
699     env.env_len = 0;
700     env.env_size = 128;
701     old_envp = env.envp;
702     env.envp = emalloc2(env.env_size, sizeof(char *));
703 #ifdef ENV_DEBUG
704     memset(env.envp, 0, env.env_size * sizeof(char *));
705 #else
706     env.envp[0] = NULL;
707 #endif
708
709     /* Reset HOME based on target user if configured to. */
710     if (ISSET(sudo_mode, MODE_RUN)) {
711         if (def_always_set_home ||
712             ISSET(sudo_mode, MODE_RESET_HOME | MODE_LOGIN_SHELL) || 
713             (ISSET(sudo_mode, MODE_SHELL) && def_set_home))
714             reset_home = true;
715     }
716
717     if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
718         /*
719          * If starting with a fresh environment, initialize it based on
720          * /etc/environment or login.conf.  For "sudo -i" we want those
721          * variables to override the invoking user's environment, so we
722          * defer reading them until later.
723          */
724         if (!ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
725 #ifdef HAVE_LOGIN_CAP_H
726             /* Insert login class environment variables. */
727             if (login_class) {
728                 login_cap_t *lc = login_getclass(login_class);
729                 if (lc != NULL) {
730                     setusercontext(lc, runas_pw, runas_pw->pw_uid,
731                         LOGIN_SETPATH|LOGIN_SETENV);
732                     login_close(lc);
733                 }
734             }
735 #endif /* HAVE_LOGIN_CAP_H */
736 #if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM))
737             /* Insert system-wide environment variables. */
738             read_env_file(_PATH_ENVIRONMENT, true);
739 #endif
740             for (ep = env.envp; *ep; ep++)
741                 env_update_didvar(*ep, &didvar);
742         }
743
744     /* Reset HOME based on target user if configured to. */
745     if (ISSET(sudo_mode, MODE_RUN)) {
746         if (def_always_set_home ||
747             ISSET(sudo_mode, MODE_RESET_HOME | MODE_LOGIN_SHELL) || 
748             (ISSET(sudo_mode, MODE_SHELL) && def_set_home))
749             reset_home = TRUE;
750     }
751
752     if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
753         /* Pull in vars we want to keep from the old environment. */
754         for (ep = old_envp; *ep; ep++) {
755             bool keepit;
756
757             /* Skip variables with values beginning with () (bash functions) */
758             if ((cp = strchr(*ep, '=')) != NULL) {
759                 if (strncmp(cp, "=() ", 3) == 0)
760                     continue;
761             }
762
763             /*
764              * Look up the variable in the env_check and env_keep lists.
765              */
766             keepit = env_should_keep(*ep);
767
768             /*
769              * Do SUDO_PS1 -> PS1 conversion.
770              * This must happen *after* env_should_keep() is called.
771              */
772             if (strncmp(*ep, "SUDO_PS1=", 8) == 0)
773                 ps1 = *ep + 5;
774
775             if (keepit) {
776                 /* Preserve variable. */
777                 sudo_putenv(*ep, false, false);
778                 env_update_didvar(*ep, &didvar);
779             }
780         }
781         didvar |= didvar << 8;          /* convert DID_* to KEPT_* */
782
783         /*
784          * Add in defaults.  In -i mode these come from the runas user,
785          * otherwise they may be from the user's environment (depends
786          * on sudoers options).
787          */
788         if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
789             sudo_setenv2("SHELL", runas_pw->pw_shell,
790                 ISSET(didvar, DID_SHELL), true);
791             sudo_setenv2("LOGNAME", runas_pw->pw_name,
792                 ISSET(didvar, DID_LOGNAME), true);
793             sudo_setenv2("USER", runas_pw->pw_name,
794                 ISSET(didvar, DID_USER), true);
795             sudo_setenv2("USERNAME", runas_pw->pw_name,
796                 ISSET(didvar, DID_USERNAME), true);
797         } else {
798             if (!ISSET(didvar, DID_SHELL))
799                 sudo_setenv2("SHELL", sudo_user.pw->pw_shell, false, true);
800             if (!ISSET(didvar, DID_LOGNAME))
801                 sudo_setenv2("LOGNAME", user_name, false, true);
802             if (!ISSET(didvar, DID_USER))
803                 sudo_setenv2("USER", user_name, false, true);
804             if (!ISSET(didvar, DID_USERNAME))
805                 sudo_setenv2("USERNAME", user_name, false, true);
806         }
807
808         /* If we didn't keep HOME, reset it based on target user. */
809         if (!ISSET(didvar, KEPT_HOME))
810             reset_home = true;
811
812         /*
813          * Set MAIL to target user in -i mode or if MAIL is not preserved
814          * from user's environment.
815          */
816         if (ISSET(sudo_mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) {
817             cp = _PATH_MAILDIR;
818             if (cp[sizeof(_PATH_MAILDIR) - 2] == '/')
819                 easprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name);
820             else
821                 easprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name);
822             sudo_putenv(cp, ISSET(didvar, DID_MAIL), true);
823         }
824     } else {
825         /*
826          * Copy environ entries as long as they don't match env_delete or
827          * env_check.
828          */
829         for (ep = old_envp; *ep; ep++) {
830             /* Skip variables with values beginning with () (bash functions) */
831             if ((cp = strchr(*ep, '=')) != NULL) {
832                 if (strncmp(cp, "=() ", 3) == 0)
833                     continue;
834             }
835
836             /* Add variable unless it matches a black list. */
837             if (!env_should_delete(*ep)) {
838                 if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
839                     ps1 = *ep + 5;
840                 else if (strncmp(*ep, "PATH=", 5) == 0)
841                     SET(didvar, DID_PATH);
842                 else if (strncmp(*ep, "TERM=", 5) == 0)
843                     SET(didvar, DID_TERM);
844                 sudo_putenv(*ep, false, false);
845             }
846         }
847     }
848     /* Replace the PATH envariable with a secure one? */
849     if (def_secure_path && !user_is_exempt()) {
850         sudo_setenv2("PATH", def_secure_path, true, true);
851         SET(didvar, DID_PATH);
852     }
853
854     /*
855      * Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is not
856      * disabled.  We skip this if we are running a login shell (because
857      * they have already been set them) or sudoedit (because we want the
858      * editor to find the user's startup files).
859      */
860     if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL|MODE_EDIT)) {
861         if (!ISSET(didvar, KEPT_LOGNAME))
862             sudo_setenv2("LOGNAME", runas_pw->pw_name, true, true);
863         if (!ISSET(didvar, KEPT_USER))
864             sudo_setenv2("USER", runas_pw->pw_name, true, true);
865         if (!ISSET(didvar, KEPT_USERNAME))
866             sudo_setenv2("USERNAME", runas_pw->pw_name, true, true);
867     }
868
869     /* Set $HOME to target user if not preserving user's value. */
870     if (reset_home)
871         sudo_setenv2("HOME", runas_pw->pw_dir, true, true);
872
873     /* Provide default values for $TERM and $PATH if they are not set. */
874     if (!ISSET(didvar, DID_TERM))
875         sudo_putenv("TERM=unknown", false, false);
876     if (!ISSET(didvar, DID_PATH))
877         sudo_setenv2("PATH", _PATH_STDPATH, false, true);
878
879     /* Set PS1 if SUDO_PS1 is set. */
880     if (ps1 != NULL)
881         sudo_putenv(ps1, true, true);
882
883     /* Add the SUDO_COMMAND envariable (cmnd + args). */
884     if (user_args) {
885         easprintf(&cp, "%s %s", user_cmnd, user_args);
886         sudo_setenv2("SUDO_COMMAND", cp, true, true);
887         efree(cp);
888     } else {
889         sudo_setenv2("SUDO_COMMAND", user_cmnd, true, true);
890     }
891
892     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
893     sudo_setenv2("SUDO_USER", user_name, true, true);
894     snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_uid);
895     sudo_setenv2("SUDO_UID", idbuf, true, true);
896     snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_gid);
897     sudo_setenv2("SUDO_GID", idbuf, true, true);
898
899     /* Free old environment. */
900     efree(old_envp);
901 }
902
903 void
904 insert_env_vars(char * const envp[])
905 {
906     char * const *ep;
907
908     if (envp == NULL)
909         return;
910
911     /* Add user-specified environment variables. */
912     for (ep = envp; *ep != NULL; ep++)
913         sudo_putenv(*ep, true, true);
914 }
915
916 /*
917  * Validate the list of environment variables passed in on the command
918  * line against env_delete, env_check, and env_keep.
919  * Calls log_fatal() if any specified variables are not allowed.
920  */
921 void
922 validate_env_vars(char * const env_vars[])
923 {
924     char * const *ep;
925     char *eq, *bad = NULL;
926     size_t len, blen = 0, bsize = 0;
927     bool okvar;
928
929     if (env_vars == NULL)
930         return;
931
932     /* Add user-specified environment variables. */
933     for (ep = env_vars; *ep != NULL; ep++) {
934         if (def_secure_path && !user_is_exempt() &&
935             strncmp(*ep, "PATH=", 5) == 0) {
936             okvar = false;
937         } else if (def_env_reset) {
938             okvar = env_should_keep(*ep);
939         } else {
940             okvar = !env_should_delete(*ep);
941         }
942         if (okvar == false) {
943             /* Not allowed, add to error string, allocating as needed. */
944             if ((eq = strchr(*ep, '=')) != NULL)
945                 *eq = '\0';
946             len = strlen(*ep) + 2;
947             if (blen + len >= bsize) {
948                 do {
949                     bsize += 1024;
950                 } while (blen + len >= bsize);
951                 bad = erealloc(bad, bsize);
952                 bad[blen] = '\0';
953             }
954             strlcat(bad, *ep, bsize);
955             strlcat(bad, ", ", bsize);
956             blen += len;
957             if (eq != NULL)
958                 *eq = '=';
959         }
960     }
961     if (bad != NULL) {
962         bad[blen - 2] = '\0';           /* remove trailing ", " */
963         log_fatal(NO_MAIL,
964             _("sorry, you are not allowed to set the following environment variables: %s"), bad);
965         /* NOTREACHED */
966         efree(bad);
967     }
968 }
969
970 /*
971  * Read in /etc/environment ala AIX and Linux.
972  * Lines may be in either of three formats:
973  *  NAME=VALUE
974  *  NAME="VALUE"
975  *  NAME='VALUE'
976  * with an optional "export" prefix so the shell can source the file.
977  * Invalid lines, blank lines, or lines consisting solely of a comment
978  * character are skipped.
979  */
980 void
981 read_env_file(const char *path, int overwrite)
982 {
983     FILE *fp;
984     char *cp, *var, *val;
985     size_t var_len, val_len;
986
987     if ((fp = fopen(path, "r")) == NULL)
988         return;
989
990     while ((var = sudo_parseln(fp)) != NULL) {
991         /* Skip blank or comment lines */
992         if (*var == '\0')
993             continue;
994
995         /* Skip optional "export " */
996         if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) {
997             var += 7;
998             while (isspace((unsigned char) *var)) {
999                 var++;
1000             }
1001         }
1002
1003         /* Must be of the form name=["']value['"] */
1004         for (val = var; *val != '\0' && *val != '='; val++)
1005             ;
1006         if (var == val || *val != '=')
1007             continue;
1008         var_len = (size_t)(val - var);
1009         val_len = strlen(++val);
1010
1011         /* Strip leading and trailing single/double quotes */
1012         if ((val[0] == '\'' || val[0] == '\"') && val[0] == val[val_len - 1]) {
1013             val[val_len - 1] = '\0';
1014             val++;
1015             val_len -= 2;
1016         }
1017
1018         cp = emalloc(var_len + 1 + val_len + 1);
1019         memcpy(cp, var, var_len + 1); /* includes '=' */
1020         memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */
1021
1022         sudo_putenv(cp, true, overwrite);
1023     }
1024     fclose(fp);
1025 }
1026
1027 void
1028 init_envtables(void)
1029 {
1030     struct list_member *cur;
1031     const char **p;
1032
1033     /* Fill in the "env_delete" list. */
1034     for (p = initial_badenv_table; *p; p++) {
1035         cur = ecalloc(1, sizeof(struct list_member));
1036         cur->value = estrdup(*p);
1037         cur->next = def_env_delete;
1038         def_env_delete = cur;
1039     }
1040
1041     /* Fill in the "env_check" list. */
1042     for (p = initial_checkenv_table; *p; p++) {
1043         cur = ecalloc(1, sizeof(struct list_member));
1044         cur->value = estrdup(*p);
1045         cur->next = def_env_check;
1046         def_env_check = cur;
1047     }
1048
1049     /* Fill in the "env_keep" list. */
1050     for (p = initial_keepenv_table; *p; p++) {
1051         cur = ecalloc(1, sizeof(struct list_member));
1052         cur->value = estrdup(*p);
1053         cur->next = def_env_keep;
1054         def_env_keep = cur;
1055     }
1056 }
1057
1058 int
1059 sudoers_hook_getenv(const char *name, char **value, void *closure)
1060 {
1061     static bool in_progress = false; /* avoid recursion */
1062
1063     if (in_progress || env.envp == NULL)
1064         return SUDO_HOOK_RET_NEXT;
1065
1066     in_progress = true;
1067     *value = sudo_getenv_nodebug(name);
1068     in_progress = false;
1069     return SUDO_HOOK_RET_STOP;
1070 }
1071
1072 int
1073 sudoers_hook_putenv(char *string, void *closure)
1074 {
1075     static bool in_progress = false; /* avoid recursion */
1076
1077     if (in_progress || env.envp == NULL)
1078         return SUDO_HOOK_RET_NEXT;
1079
1080     in_progress = true;
1081     sudo_putenv_nodebug(string, true, true);
1082     in_progress = false;
1083     return SUDO_HOOK_RET_STOP;
1084 }
1085
1086 int
1087 sudoers_hook_setenv(const char *name, const char *value, int overwrite, void *closure)
1088 {
1089     static bool in_progress = false; /* avoid recursion */
1090
1091     if (in_progress || env.envp == NULL)
1092         return SUDO_HOOK_RET_NEXT;
1093
1094     in_progress = true;
1095     sudo_setenv_nodebug(name, value, overwrite);
1096     in_progress = false;
1097     return SUDO_HOOK_RET_STOP;
1098 }
1099
1100 int
1101 sudoers_hook_unsetenv(const char *name, void *closure)
1102 {
1103     static bool in_progress = false; /* avoid recursion */
1104
1105     if (in_progress || env.envp == NULL)
1106         return SUDO_HOOK_RET_NEXT;
1107
1108     in_progress = true;
1109     sudo_unsetenv_nodebug(name);
1110     in_progress = false;
1111     return SUDO_HOOK_RET_STOP;
1112 }