update control to reflect move of primary repo to collab-maint
[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         /* Pull in vars we want to keep from the old environment. */
745         for (ep = old_envp; *ep; ep++) {
746             bool keepit;
747
748             /* Skip variables with values beginning with () (bash functions) */
749             if ((cp = strchr(*ep, '=')) != NULL) {
750                 if (strncmp(cp, "=() ", 3) == 0)
751                     continue;
752             }
753
754             /*
755              * Look up the variable in the env_check and env_keep lists.
756              */
757             keepit = env_should_keep(*ep);
758
759             /*
760              * Do SUDO_PS1 -> PS1 conversion.
761              * This must happen *after* env_should_keep() is called.
762              */
763             if (strncmp(*ep, "SUDO_PS1=", 8) == 0)
764                 ps1 = *ep + 5;
765
766             if (keepit) {
767                 /* Preserve variable. */
768                 sudo_putenv(*ep, false, false);
769                 env_update_didvar(*ep, &didvar);
770             }
771         }
772         didvar |= didvar << 8;          /* convert DID_* to KEPT_* */
773
774         /*
775          * Add in defaults.  In -i mode these come from the runas user,
776          * otherwise they may be from the user's environment (depends
777          * on sudoers options).
778          */
779         if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
780             sudo_setenv2("SHELL", runas_pw->pw_shell,
781                 ISSET(didvar, DID_SHELL), true);
782             sudo_setenv2("LOGNAME", runas_pw->pw_name,
783                 ISSET(didvar, DID_LOGNAME), true);
784             sudo_setenv2("USER", runas_pw->pw_name,
785                 ISSET(didvar, DID_USER), true);
786             sudo_setenv2("USERNAME", runas_pw->pw_name,
787                 ISSET(didvar, DID_USERNAME), true);
788         } else {
789             if (!ISSET(didvar, DID_SHELL))
790                 sudo_setenv2("SHELL", sudo_user.pw->pw_shell, false, true);
791             if (!ISSET(didvar, DID_LOGNAME))
792                 sudo_setenv2("LOGNAME", user_name, false, true);
793             if (!ISSET(didvar, DID_USER))
794                 sudo_setenv2("USER", user_name, false, true);
795             if (!ISSET(didvar, DID_USERNAME))
796                 sudo_setenv2("USERNAME", user_name, false, true);
797         }
798
799         /* If we didn't keep HOME, reset it based on target user. */
800         if (!ISSET(didvar, KEPT_HOME))
801             reset_home = true;
802
803         /*
804          * Set MAIL to target user in -i mode or if MAIL is not preserved
805          * from user's environment.
806          */
807         if (ISSET(sudo_mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) {
808             cp = _PATH_MAILDIR;
809             if (cp[sizeof(_PATH_MAILDIR) - 2] == '/')
810                 easprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name);
811             else
812                 easprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name);
813             sudo_putenv(cp, ISSET(didvar, DID_MAIL), true);
814         }
815     } else {
816         /*
817          * Copy environ entries as long as they don't match env_delete or
818          * env_check.
819          */
820         for (ep = old_envp; *ep; ep++) {
821             /* Skip variables with values beginning with () (bash functions) */
822             if ((cp = strchr(*ep, '=')) != NULL) {
823                 if (strncmp(cp, "=() ", 3) == 0)
824                     continue;
825             }
826
827             /* Add variable unless it matches a black list. */
828             if (!env_should_delete(*ep)) {
829                 if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
830                     ps1 = *ep + 5;
831                 else if (strncmp(*ep, "PATH=", 5) == 0)
832                     SET(didvar, DID_PATH);
833                 else if (strncmp(*ep, "TERM=", 5) == 0)
834                     SET(didvar, DID_TERM);
835                 sudo_putenv(*ep, false, false);
836             }
837         }
838     }
839     /* Replace the PATH envariable with a secure one? */
840     if (def_secure_path && !user_is_exempt()) {
841         sudo_setenv2("PATH", def_secure_path, true, true);
842         SET(didvar, DID_PATH);
843     }
844
845     /*
846      * Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is not
847      * disabled.  We skip this if we are running a login shell (because
848      * they have already been set them) or sudoedit (because we want the
849      * editor to find the user's startup files).
850      */
851     if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL|MODE_EDIT)) {
852         if (!ISSET(didvar, KEPT_LOGNAME))
853             sudo_setenv2("LOGNAME", runas_pw->pw_name, true, true);
854         if (!ISSET(didvar, KEPT_USER))
855             sudo_setenv2("USER", runas_pw->pw_name, true, true);
856         if (!ISSET(didvar, KEPT_USERNAME))
857             sudo_setenv2("USERNAME", runas_pw->pw_name, true, true);
858     }
859
860     /* Set $HOME to target user if not preserving user's value. */
861     if (reset_home)
862         sudo_setenv2("HOME", runas_pw->pw_dir, true, true);
863
864     /* Provide default values for $TERM and $PATH if they are not set. */
865     if (!ISSET(didvar, DID_TERM))
866         sudo_putenv("TERM=unknown", false, false);
867     if (!ISSET(didvar, DID_PATH))
868         sudo_setenv2("PATH", _PATH_STDPATH, false, true);
869
870     /* Set PS1 if SUDO_PS1 is set. */
871     if (ps1 != NULL)
872         sudo_putenv(ps1, true, true);
873
874     /* Add the SUDO_COMMAND envariable (cmnd + args). */
875     if (user_args) {
876         easprintf(&cp, "%s %s", user_cmnd, user_args);
877         sudo_setenv2("SUDO_COMMAND", cp, true, true);
878         efree(cp);
879     } else {
880         sudo_setenv2("SUDO_COMMAND", user_cmnd, true, true);
881     }
882
883     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
884     sudo_setenv2("SUDO_USER", user_name, true, true);
885     snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_uid);
886     sudo_setenv2("SUDO_UID", idbuf, true, true);
887     snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_gid);
888     sudo_setenv2("SUDO_GID", idbuf, true, true);
889
890     /* Free old environment. */
891     efree(old_envp);
892 }
893
894 void
895 insert_env_vars(char * const envp[])
896 {
897     char * const *ep;
898
899     if (envp == NULL)
900         return;
901
902     /* Add user-specified environment variables. */
903     for (ep = envp; *ep != NULL; ep++)
904         sudo_putenv(*ep, true, true);
905 }
906
907 /*
908  * Validate the list of environment variables passed in on the command
909  * line against env_delete, env_check, and env_keep.
910  * Calls log_fatal() if any specified variables are not allowed.
911  */
912 void
913 validate_env_vars(char * const env_vars[])
914 {
915     char * const *ep;
916     char *eq, *bad = NULL;
917     size_t len, blen = 0, bsize = 0;
918     bool okvar;
919
920     if (env_vars == NULL)
921         return;
922
923     /* Add user-specified environment variables. */
924     for (ep = env_vars; *ep != NULL; ep++) {
925         if (def_secure_path && !user_is_exempt() &&
926             strncmp(*ep, "PATH=", 5) == 0) {
927             okvar = false;
928         } else if (def_env_reset) {
929             okvar = env_should_keep(*ep);
930         } else {
931             okvar = !env_should_delete(*ep);
932         }
933         if (okvar == false) {
934             /* Not allowed, add to error string, allocating as needed. */
935             if ((eq = strchr(*ep, '=')) != NULL)
936                 *eq = '\0';
937             len = strlen(*ep) + 2;
938             if (blen + len >= bsize) {
939                 do {
940                     bsize += 1024;
941                 } while (blen + len >= bsize);
942                 bad = erealloc(bad, bsize);
943                 bad[blen] = '\0';
944             }
945             strlcat(bad, *ep, bsize);
946             strlcat(bad, ", ", bsize);
947             blen += len;
948             if (eq != NULL)
949                 *eq = '=';
950         }
951     }
952     if (bad != NULL) {
953         bad[blen - 2] = '\0';           /* remove trailing ", " */
954         log_fatal(NO_MAIL,
955             _("sorry, you are not allowed to set the following environment variables: %s"), bad);
956         /* NOTREACHED */
957         efree(bad);
958     }
959 }
960
961 /*
962  * Read in /etc/environment ala AIX and Linux.
963  * Lines may be in either of three formats:
964  *  NAME=VALUE
965  *  NAME="VALUE"
966  *  NAME='VALUE'
967  * with an optional "export" prefix so the shell can source the file.
968  * Invalid lines, blank lines, or lines consisting solely of a comment
969  * character are skipped.
970  */
971 void
972 read_env_file(const char *path, int overwrite)
973 {
974     FILE *fp;
975     char *cp, *var, *val;
976     size_t var_len, val_len;
977
978     if ((fp = fopen(path, "r")) == NULL)
979         return;
980
981     while ((var = sudo_parseln(fp)) != NULL) {
982         /* Skip blank or comment lines */
983         if (*var == '\0')
984             continue;
985
986         /* Skip optional "export " */
987         if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) {
988             var += 7;
989             while (isspace((unsigned char) *var)) {
990                 var++;
991             }
992         }
993
994         /* Must be of the form name=["']value['"] */
995         for (val = var; *val != '\0' && *val != '='; val++)
996             ;
997         if (var == val || *val != '=')
998             continue;
999         var_len = (size_t)(val - var);
1000         val_len = strlen(++val);
1001
1002         /* Strip leading and trailing single/double quotes */
1003         if ((val[0] == '\'' || val[0] == '\"') && val[0] == val[val_len - 1]) {
1004             val[val_len - 1] = '\0';
1005             val++;
1006             val_len -= 2;
1007         }
1008
1009         cp = emalloc(var_len + 1 + val_len + 1);
1010         memcpy(cp, var, var_len + 1); /* includes '=' */
1011         memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */
1012
1013         sudo_putenv(cp, true, overwrite);
1014     }
1015     fclose(fp);
1016 }
1017
1018 void
1019 init_envtables(void)
1020 {
1021     struct list_member *cur;
1022     const char **p;
1023
1024     /* Fill in the "env_delete" list. */
1025     for (p = initial_badenv_table; *p; p++) {
1026         cur = ecalloc(1, sizeof(struct list_member));
1027         cur->value = estrdup(*p);
1028         cur->next = def_env_delete;
1029         def_env_delete = cur;
1030     }
1031
1032     /* Fill in the "env_check" list. */
1033     for (p = initial_checkenv_table; *p; p++) {
1034         cur = ecalloc(1, sizeof(struct list_member));
1035         cur->value = estrdup(*p);
1036         cur->next = def_env_check;
1037         def_env_check = cur;
1038     }
1039
1040     /* Fill in the "env_keep" list. */
1041     for (p = initial_keepenv_table; *p; p++) {
1042         cur = ecalloc(1, sizeof(struct list_member));
1043         cur->value = estrdup(*p);
1044         cur->next = def_env_keep;
1045         def_env_keep = cur;
1046     }
1047 }
1048
1049 int
1050 sudoers_hook_getenv(const char *name, char **value, void *closure)
1051 {
1052     static bool in_progress = false; /* avoid recursion */
1053
1054     if (in_progress || env.envp == NULL)
1055         return SUDO_HOOK_RET_NEXT;
1056
1057     in_progress = true;
1058     *value = sudo_getenv_nodebug(name);
1059     in_progress = false;
1060     return SUDO_HOOK_RET_STOP;
1061 }
1062
1063 int
1064 sudoers_hook_putenv(char *string, void *closure)
1065 {
1066     static bool in_progress = false; /* avoid recursion */
1067
1068     if (in_progress || env.envp == NULL)
1069         return SUDO_HOOK_RET_NEXT;
1070
1071     in_progress = true;
1072     sudo_putenv_nodebug(string, true, true);
1073     in_progress = false;
1074     return SUDO_HOOK_RET_STOP;
1075 }
1076
1077 int
1078 sudoers_hook_setenv(const char *name, const char *value, int overwrite, void *closure)
1079 {
1080     static bool in_progress = false; /* avoid recursion */
1081
1082     if (in_progress || env.envp == NULL)
1083         return SUDO_HOOK_RET_NEXT;
1084
1085     in_progress = true;
1086     sudo_setenv_nodebug(name, value, overwrite);
1087     in_progress = false;
1088     return SUDO_HOOK_RET_STOP;
1089 }
1090
1091 int
1092 sudoers_hook_unsetenv(const char *name, void *closure)
1093 {
1094     static bool in_progress = false; /* avoid recursion */
1095
1096     if (in_progress || env.envp == NULL)
1097         return SUDO_HOOK_RET_NEXT;
1098
1099     in_progress = true;
1100     sudo_unsetenv_nodebug(name);
1101     in_progress = false;
1102     return SUDO_HOOK_RET_STOP;
1103 }