add doc about interaction with RAMRUN to README.Debian in response to #581393
[debian/sudo] / env.c
1 /*
2  * Copyright (c) 2000-2005, 2007-2009
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 #else
39 # ifdef HAVE_STRINGS_H
40 #  include <strings.h>
41 # endif
42 #endif /* HAVE_STRING_H */
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif /* HAVE_UNISTD_H */
46 #include <ctype.h>
47 #include <errno.h>
48 #include <pwd.h>
49
50 #include "sudo.h"
51
52 /*
53  * Flags used in rebuild_env()
54  */
55 #undef DID_TERM
56 #define DID_TERM        0x0001
57 #undef DID_PATH
58 #define DID_PATH        0x0002
59 #undef DID_HOME
60 #define DID_HOME        0x0004
61 #undef DID_SHELL
62 #define DID_SHELL       0x0008
63 #undef DID_LOGNAME
64 #define DID_LOGNAME     0x0010
65 #undef DID_USER
66 #define DID_USER        0x0020
67 #undef DID_USERNAME
68 #define DID_USERNAME    0x0040
69 #undef DID_MAX
70 #define DID_MAX         0x00ff
71
72 #undef KEPT_TERM
73 #define KEPT_TERM       0x0100
74 #undef KEPT_PATH
75 #define KEPT_PATH       0x0200
76 #undef KEPT_HOME
77 #define KEPT_HOME       0x0400
78 #undef KEPT_SHELL
79 #define KEPT_SHELL      0x0800
80 #undef KEPT_LOGNAME
81 #define KEPT_LOGNAME    0x1000
82 #undef KEPT_USER
83 #define KEPT_USER       0x2000
84 #undef KEPT_USERNAME
85 #define KEPT_USERNAME   0x4000
86 #undef KEPT_MAX
87 #define KEPT_MAX        0xff00
88
89 #undef VNULL
90 #define VNULL   (void *)NULL
91
92 struct environment {
93     char **envp;                /* pointer to the new environment */
94     size_t env_size;            /* size of new_environ in char **'s */
95     size_t env_len;             /* number of slots used, not counting NULL */
96 };
97
98 /*
99  * Prototypes
100  */
101 void rebuild_env                __P((int, int));
102 static void sudo_setenv         __P((const char *, const char *, int));
103 static void sudo_putenv         __P((char *, int, int));
104
105 extern char **environ;          /* global environment */
106
107 /*
108  * Copy of the sudo-managed environment.
109  */
110 static struct environment env;
111
112 /*
113  * Default table of "bad" variables to remove from the environment.
114  * XXX - how to omit TERMCAP if it starts with '/'?
115  */
116 static const char *initial_badenv_table[] = {
117     "IFS",
118     "CDPATH",
119     "LOCALDOMAIN",
120     "RES_OPTIONS",
121     "HOSTALIASES",
122     "NLSPATH",
123     "PATH_LOCALE",
124     "LD_*",
125     "_RLD*",
126 #ifdef __hpux
127     "SHLIB_PATH",
128 #endif /* __hpux */
129 #ifdef _AIX
130     "LDR_*",
131     "LIBPATH",
132     "AUTHSTATE",
133 #endif
134 #ifdef __APPLE__
135     "DYLD_*",
136 #endif
137 #ifdef HAVE_KERB4
138     "KRB_CONF*",
139     "KRBCONFDIR",
140     "KRBTKFILE",
141 #endif /* HAVE_KERB4 */
142 #ifdef HAVE_KERB5
143     "KRB5_CONFIG*",
144     "KRB5_KTNAME",
145 #endif /* HAVE_KERB5 */
146 #ifdef HAVE_SECURID
147     "VAR_ACE",
148     "USR_ACE",
149     "DLC_ACE",
150 #endif /* HAVE_SECURID */
151     "TERMINFO",                 /* terminfo, exclusive path to terminfo files */
152     "TERMINFO_DIRS",            /* terminfo, path(s) to terminfo files */
153     "TERMPATH",                 /* termcap, path(s) to termcap files */
154     "TERMCAP",                  /* XXX - only if it starts with '/' */
155     "ENV",                      /* ksh, file to source before script runs */
156     "BASH_ENV",                 /* bash, file to source before script runs */
157     "PS4",                      /* bash, prefix for lines in xtrace mode */
158     "GLOBIGNORE",               /* bash, globbing patterns to ignore */
159     "SHELLOPTS",                /* bash, extra command line options */
160     "JAVA_TOOL_OPTIONS",        /* java, extra command line options */
161     "PERLIO_DEBUG ",            /* perl, debugging output file */
162     "PERLLIB",                  /* perl, search path for modules/includes */
163     "PERL5LIB",                 /* perl 5, search path for modules/includes */
164     "PERL5OPT",                 /* perl 5, extra command line options */
165     "PERL5DB",                  /* perl 5, command used to load debugger */
166     "FPATH",                    /* ksh, search path for functions */
167     "NULLCMD",                  /* zsh, command for null file redirection */
168     "READNULLCMD",              /* zsh, command for null file redirection */
169     "ZDOTDIR",                  /* zsh, search path for dot files */
170     "TMPPREFIX",                /* zsh, prefix for temporary files */
171     "PYTHONHOME",               /* python, module search path */
172     "PYTHONPATH",               /* python, search path */
173     "PYTHONINSPECT",            /* python, allow inspection */
174     "RUBYLIB",                  /* ruby, library load path */
175     "RUBYOPT",                  /* ruby, extra command line options */
176     NULL
177 };
178
179 /*
180  * Default table of variables to check for '%' and '/' characters.
181  */
182 static const char *initial_checkenv_table[] = {
183     "COLORTERM",
184     "LANG",
185     "LANGUAGE",
186     "LC_*",
187     "LINGUAS",
188     "TERM",
189     NULL
190 };
191
192 /*
193  * Default table of variables to preserve in the environment.
194  */
195 static const char *initial_keepenv_table[] = {
196     "COLORS",
197     "DISPLAY",
198     "HOME",
199     "HOSTNAME",
200     "KRB5CCNAME",
201     "LS_COLORS",
202     "MAIL",
203     "PATH",
204     "PS1",
205     "PS2",
206     "TZ",
207     "XAUTHORITY",
208     "XAUTHORIZATION",
209     NULL
210 };
211
212 /*
213  * Similar to setenv(3) but operates on sudo's private copy of the environment
214  * (not environ) and it always overwrites.  The dupcheck param determines
215  * whether we need to verify that the variable is not already set.
216  */
217 static void
218 sudo_setenv(var, val, dupcheck)
219     const char *var;
220     const char *val;
221     int dupcheck;
222 {
223     char *estring;
224     size_t esize;
225
226     esize = strlen(var) + 1 + strlen(val) + 1;
227     estring = emalloc(esize);
228
229     /* Build environment string and insert it. */
230     if (strlcpy(estring, var, esize) >= esize ||
231         strlcat(estring, "=", esize) >= esize ||
232         strlcat(estring, val, esize) >= esize) {
233
234         errorx(1, "internal error, sudo_setenv() overflow");
235     }
236     sudo_putenv(estring, dupcheck, TRUE);
237 }
238
239 /*
240  * Version of setenv(3) that uses our own environ pointer.
241  * Will sync with environ as needed.
242  */
243 int
244 setenv(var, val, overwrite)
245     const char *var;
246     const char *val;
247     int overwrite;
248 {
249     char *estring, *ep;
250     const char *cp;
251     size_t esize;
252
253     if (!var || *var == '\0')
254         return(EINVAL);
255
256     /*
257      * POSIX says a var name with '=' is an error but BSD
258      * just ignores the '=' and anything after it.
259      */
260     for (cp = var; *cp && *cp != '='; cp++)
261         ;
262     esize = (size_t)(cp - var) + 2;
263     if (val) {
264         esize += strlen(val);   /* glibc treats a NULL val as "" */
265     }
266
267     /* Allocate and fill in estring. */
268     estring = ep = emalloc(esize);
269     for (cp = var; *cp && *cp != '='; cp++)
270         *ep++ = *cp;
271     *ep++ = '=';
272     if (val) {
273         for (cp = val; *cp; cp++)
274             *ep++ = *cp;
275     }
276     *ep = '\0';
277
278     /* Sync env.envp with environ as needed. */
279     if (env.envp != environ) {
280         char **ep;
281         size_t len;
282
283         for (ep = environ; *ep != NULL; ep++)
284             continue;
285         len = ep - environ;
286         if (len + 2 > env.env_size) {
287             efree(env.envp);
288             env.env_size = len + 2 + 128;
289             env.envp = emalloc2(env.env_size, sizeof(char *));
290 #ifdef ENV_DEBUG
291             memset(env.envp, 0, env.env_size * sizeof(char *));
292 #endif
293         }
294         memcpy(env.envp, environ, len * sizeof(char *));
295         env.envp[len] = NULL;
296         env.env_len = len;
297         environ = env.envp;
298 #ifdef ENV_DEBUG
299     } else {
300         if (env.envp[env.env_len] != NULL)
301             errorx(1, "setenv: corrupted envp, len mismatch");
302 #endif
303     }
304     sudo_putenv(estring, TRUE, overwrite);
305     return(0);
306 }
307
308 /*
309  * Version of unsetenv(3) that uses our own environ pointer.
310  * Will sync with environ as needed.
311  */
312 #ifdef UNSETENV_VOID
313 void
314 #else
315 int
316 #endif
317 unsetenv(var)
318     const char *var;
319 {
320     char **ep;
321     size_t len;
322
323     if (strchr(var, '=') != NULL) {
324         errno = EINVAL;
325 #ifdef UNSETENV_VOID
326         return;
327 #else
328         return(-1);
329 #endif
330     }
331
332     /* Make sure we are operating on the current environment. */
333     /* XXX - this could be optimized to include the search */
334     if (env.envp != environ) {
335         for (ep = environ; *ep != NULL; ep++)
336             continue;
337         len = ep - environ;
338         if (len + 1 > env.env_size) {
339             efree(env.envp);
340             env.env_size = len + 1 + 128;
341             env.envp = emalloc2(env.env_size, sizeof(char *));
342 #ifdef ENV_DEBUG
343             memset(env.envp, 0, env.env_size * sizeof(char *));
344 #endif
345         }
346         memcpy(env.envp, environ, len * sizeof(char *));
347         env.envp[len] = NULL;
348         env.env_len = len;
349         environ = env.envp;
350 #ifdef ENV_DEBUG
351     } else {
352         if (env.envp[env.env_len] != NULL)
353             errorx(1, "unsetenv: corrupted envp, len mismatch");
354 #endif
355     }
356
357     len = strlen(var);
358     for (ep = env.envp; *ep; ep++) {
359         if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') {
360             /* Found it; shift remainder + NULL over by one and update len. */
361             memmove(ep, ep + 1,
362                 (env.env_len - (ep - env.envp)) * sizeof(char *));
363             env.env_len--;
364             break;
365         }
366     }
367 #ifndef UNSETENV_VOID
368     return(0);
369 #endif
370 }
371
372 /*
373  * Version of putenv(3) that uses our own environ pointer.
374  * Will sync with environ as needed.
375  */
376 int
377 #ifdef PUTENV_CONST
378 putenv(const char *string)
379 #else
380 putenv(string)
381     char *string;
382 #endif
383 {
384     if (strchr(string, '=') == NULL) {
385         errno = EINVAL;
386         return(-1);
387     }
388     /* Sync env.envp with environ as needed. */
389     if (env.envp != environ) {
390         char **ep;
391         size_t len;
392
393         for (ep = environ; *ep != NULL; ep++)
394             continue;
395         len = ep - environ;
396         if (len + 2 > env.env_size) {
397             efree(env.envp);
398             env.env_size = len + 2 + 128;
399             env.envp = emalloc2(env.env_size, sizeof(char *));
400 #ifdef ENV_DEBUG
401             memset(env.envp, 0, env.env_size * sizeof(char *));
402 #endif
403         }
404         memcpy(env.envp, environ, len * sizeof(char *));
405         env.envp[len] = NULL;
406         env.env_len = len;
407         environ = env.envp;
408 #ifdef ENV_DEBUG
409     } else {
410         if (env.envp[env.env_len] != NULL)
411             errorx(1, "putenv: corrupted envp, len mismatch");
412 #endif
413     }
414     sudo_putenv((char *)string, TRUE, TRUE);
415     return(0);
416 }
417
418 /*
419  * Similar to putenv(3) but operates on sudo's private copy of the
420  * environment (not environ) and it always overwrites.  The dupcheck param
421  * determines whether we need to verify that the variable is not already set.
422  * Will only overwrite an existing variable if overwrite is set.
423  */
424 static void
425 sudo_putenv(str, dupcheck, overwrite)
426     char *str;
427     int dupcheck;
428     int overwrite;
429 {
430     char **ep;
431     size_t len;
432
433     /* Make sure there is room for the new entry plus a NULL. */
434     if (env.env_len + 2 > env.env_size) {
435         env.env_size += 128;
436         env.envp = erealloc3(env.envp, env.env_size, sizeof(char *));
437 #ifdef ENV_DEBUG
438         memset(env.envp + env.env_len, 0,
439             (env.env_size - env.env_len) * sizeof(char *));
440 #endif
441         environ = env.envp;
442     }
443
444 #ifdef ENV_DEBUG
445     if (env.envp[env.env_len] != NULL)
446         errorx(1, "sudo_putenv: corrupted envp, len mismatch");
447 #endif
448
449     if (dupcheck) {
450             len = (strchr(str, '=') - str) + 1;
451             for (ep = env.envp; *ep; ep++) {
452                 if (strncmp(str, *ep, len) == 0) {
453                     if (overwrite)
454                         *ep = str;
455                     return;
456                 }
457             }
458     } else
459         ep = env.envp + env.env_len;
460
461     env.env_len++;
462     *ep++ = str;
463     *ep = NULL;
464 }
465
466 /*
467  * Check the env_delete blacklist.
468  * Returns TRUE if the variable was found, else false.
469  */
470 static int
471 matches_env_delete(var)
472     const char *var;
473 {
474     struct list_member *cur;
475     size_t len;
476     int iswild, match = FALSE;
477
478     /* Skip anything listed in env_delete. */
479     for (cur = def_env_delete; cur; cur = cur->next) {
480         len = strlen(cur->value);
481         /* Deal with '*' wildcard */
482         if (cur->value[len - 1] == '*') {
483             len--;
484             iswild = TRUE;
485         } else
486             iswild = FALSE;
487         if (strncmp(cur->value, var, len) == 0 &&
488             (iswild || var[len] == '=')) {
489             match = TRUE;
490             break;
491         }
492     }
493     return(match);
494 }
495
496 /*
497  * Apply the env_check list.
498  * Returns TRUE if the variable is allowed, FALSE if denied
499  * or -1 if no match.
500  */
501 static int
502 matches_env_check(var)
503     const char *var;
504 {
505     struct list_member *cur;
506     size_t len;
507     int iswild, keepit = -1;
508
509     for (cur = def_env_check; cur; cur = cur->next) {
510         len = strlen(cur->value);
511         /* Deal with '*' wildcard */
512         if (cur->value[len - 1] == '*') {
513             len--;
514             iswild = TRUE;
515         } else
516             iswild = FALSE;
517         if (strncmp(cur->value, var, len) == 0 &&
518             (iswild || var[len] == '=')) {
519             keepit = !strpbrk(var, "/%");
520             break;
521         }
522     }
523     return(keepit);
524 }
525
526 /*
527  * Check the env_keep list.
528  * Returns TRUE if the variable is allowed else FALSE.
529  */
530 static int
531 matches_env_keep(var)
532     const char *var;
533 {
534     struct list_member *cur;
535     size_t len;
536     int iswild, keepit = FALSE;
537
538     for (cur = def_env_keep; cur; cur = cur->next) {
539         len = strlen(cur->value);
540         /* Deal with '*' wildcard */
541         if (cur->value[len - 1] == '*') {
542             len--;
543             iswild = TRUE;
544         } else
545             iswild = FALSE;
546         if (strncmp(cur->value, var, len) == 0 &&
547             (iswild || var[len] == '=')) {
548             keepit = TRUE;
549             break;
550         }
551     }
552     return(keepit);
553 }
554
555 /*
556  * Build a new environment and ether clear potentially dangerous
557  * variables from the old one or start with a clean slate.
558  * Also adds sudo-specific variables (SUDO_*).
559  */
560 void
561 rebuild_env(sudo_mode, noexec)
562     int sudo_mode;
563     int noexec;
564 {
565     char **old_envp, **ep, *cp, *ps1;
566     char idbuf[MAX_UID_T_LEN];
567     unsigned int didvar;
568
569     /*
570      * Either clean out the environment or reset to a safe default.
571      */
572     ps1 = NULL;
573     didvar = 0;
574     env.env_len = 0;
575     env.env_size = 128;
576     old_envp = env.envp;
577     env.envp = emalloc2(env.env_size, sizeof(char *));
578 #ifdef ENV_DEBUG
579     memset(env.envp, 0, env.env_size * sizeof(char *));
580 #endif
581     if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
582         /* Pull in vars we want to keep from the old environment. */
583         for (ep = environ; *ep; ep++) {
584             int keepit;
585
586             /* Skip variables with values beginning with () (bash functions) */
587             if ((cp = strchr(*ep, '=')) != NULL) {
588                 if (strncmp(cp, "=() ", 3) == 0)
589                     continue;
590             }
591
592             /*
593              * First check certain variables for '%' and '/' characters.
594              * If no match there, check the keep list.
595              * If nothing matched, we remove it from the environment.
596              */
597             keepit = matches_env_check(*ep);
598             if (keepit == -1)
599                 keepit = matches_env_keep(*ep);
600
601             /* For SUDO_PS1 -> PS1 conversion. */
602             if (strncmp(*ep, "SUDO_PS1=", 8) == 0)
603                 ps1 = *ep + 5;
604
605             if (keepit) {
606                 /* Preserve variable. */
607                 switch (**ep) {
608                     case 'H':
609                         if (strncmp(*ep, "HOME=", 5) == 0)
610                             SET(didvar, DID_HOME);
611                         break;
612                     case 'L':
613                         if (strncmp(*ep, "LOGNAME=", 8) == 0)
614                             SET(didvar, DID_LOGNAME);
615                         break;
616                     case 'P':
617                         if (strncmp(*ep, "PATH=", 5) == 0)
618                             SET(didvar, DID_PATH);
619                         break;
620                     case 'S':
621                         if (strncmp(*ep, "SHELL=", 6) == 0)
622                             SET(didvar, DID_SHELL);
623                         break;
624                     case 'T':
625                         if (strncmp(*ep, "TERM=", 5) == 0)
626                             SET(didvar, DID_TERM);
627                         break;
628                     case 'U':
629                         if (strncmp(*ep, "USER=", 5) == 0)
630                             SET(didvar, DID_USER);
631                         if (strncmp(*ep, "USERNAME=", 5) == 0)
632                             SET(didvar, DID_USERNAME);
633                         break;
634                 }
635                 sudo_putenv(*ep, FALSE, FALSE);
636             }
637         }
638         didvar |= didvar << 8;          /* convert DID_* to KEPT_* */
639
640         /*
641          * Add in defaults.  In -i mode these come from the runas user,
642          * otherwise they may be from the user's environment (depends
643          * on sudoers options).
644          */
645         if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
646             sudo_setenv("HOME", runas_pw->pw_dir, ISSET(didvar, DID_HOME));
647             sudo_setenv("SHELL", runas_pw->pw_shell, ISSET(didvar, DID_SHELL));
648             sudo_setenv("LOGNAME", runas_pw->pw_name,
649                 ISSET(didvar, DID_LOGNAME));
650             sudo_setenv("USER", runas_pw->pw_name, ISSET(didvar, DID_USER));
651             sudo_setenv("USERNAME", runas_pw->pw_name,
652                 ISSET(didvar, DID_USERNAME));
653         } else {
654             if (!ISSET(didvar, DID_HOME))
655                 sudo_setenv("HOME", user_dir, FALSE);
656             if (!ISSET(didvar, DID_SHELL))
657                 sudo_setenv("SHELL", sudo_user.pw->pw_shell, FALSE);
658             if (!ISSET(didvar, DID_LOGNAME))
659                 sudo_setenv("LOGNAME", user_name, FALSE);
660             if (!ISSET(didvar, DID_USER))
661                 sudo_setenv("USER", user_name, FALSE);
662             if (!ISSET(didvar, DID_USERNAME))
663                 sudo_setenv("USERNAME", user_name, FALSE);
664         }
665     } else {
666         /*
667          * Copy environ entries as long as they don't match env_delete or
668          * env_check.
669          */
670         for (ep = environ; *ep; ep++) {
671             int okvar;
672
673             /* Skip variables with values beginning with () (bash functions) */
674             if ((cp = strchr(*ep, '=')) != NULL) {
675                 if (strncmp(cp, "=() ", 3) == 0)
676                     continue;
677             }
678
679             /*
680              * First check variables against the blacklist in env_delete.
681              * If no match there check for '%' and '/' characters.
682              */
683             okvar = matches_env_delete(*ep) != TRUE;
684             if (okvar)
685                 okvar = matches_env_check(*ep) != FALSE;
686
687             if (okvar) {
688                 if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
689                     ps1 = *ep + 5;
690                 else if (strncmp(*ep, "PATH=", 5) == 0)
691                     SET(didvar, DID_PATH);
692                 else if (strncmp(*ep, "TERM=", 5) == 0)
693                     SET(didvar, DID_TERM);
694                 sudo_putenv(*ep, FALSE, FALSE);
695             }
696         }
697     }
698     /* Replace the PATH envariable with a secure one? */
699     if (def_secure_path && !user_is_exempt()) {
700         sudo_setenv("PATH", def_secure_path, TRUE);
701         SET(didvar, DID_PATH);
702     }
703
704     /* Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is true. */
705     /* XXX - not needed for MODE_LOGIN_SHELL */
706     if (def_set_logname && runas_pw->pw_name) {
707         if (!ISSET(didvar, KEPT_LOGNAME))
708             sudo_setenv("LOGNAME", runas_pw->pw_name, TRUE);
709         if (!ISSET(didvar, KEPT_USER))
710             sudo_setenv("USER", runas_pw->pw_name, TRUE);
711         if (!ISSET(didvar, KEPT_USERNAME))
712             sudo_setenv("USERNAME", runas_pw->pw_name, TRUE);
713     }
714
715     /* Set $HOME for `sudo -H'.  Only valid at PERM_FULL_RUNAS. */
716     /* XXX - not needed for MODE_LOGIN_SHELL */
717     if (runas_pw->pw_dir) {
718         if (ISSET(sudo_mode, MODE_RESET_HOME) ||
719             (ISSET(sudo_mode, MODE_RUN) && (def_always_set_home ||
720             (ISSET(sudo_mode, MODE_SHELL) && def_set_home))))
721             sudo_setenv("HOME", runas_pw->pw_dir, TRUE);
722     }
723
724     /* Provide default values for $TERM and $PATH if they are not set. */
725     if (!ISSET(didvar, DID_TERM))
726         sudo_putenv("TERM=unknown", FALSE, FALSE);
727     if (!ISSET(didvar, DID_PATH))
728         sudo_setenv("PATH", _PATH_DEFPATH, FALSE);
729
730     /*
731      * Preload a noexec file?  For a list of LD_PRELOAD-alikes, see
732      * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
733      * XXX - should prepend to original value, if any
734      */
735     if (noexec && def_noexec_file != NULL) {
736 #if defined(__darwin__) || defined(__APPLE__)
737         sudo_setenv("DYLD_INSERT_LIBRARIES", def_noexec_file, TRUE);
738         sudo_setenv("DYLD_FORCE_FLAT_NAMESPACE", "", TRUE);
739 #else
740 # if defined(__osf__) || defined(__sgi)
741         easprintf(&cp, "%s:DEFAULT", def_noexec_file);
742         sudo_setenv("_RLD_LIST", cp, TRUE);
743         efree(cp);
744 # else
745 #  ifdef _AIX
746         sudo_setenv("LDR_PRELOAD", def_noexec_file, TRUE);
747 #  else
748         sudo_setenv("LD_PRELOAD", def_noexec_file, TRUE);
749 #  endif /* _AIX */
750 # endif /* __osf__ || __sgi */
751 #endif /* __darwin__ || __APPLE__ */
752     }
753
754     /* Set PS1 if SUDO_PS1 is set. */
755     if (ps1 != NULL)
756         sudo_putenv(ps1, TRUE, TRUE);
757
758     /* Add the SUDO_COMMAND envariable (cmnd + args). */
759     if (user_args) {
760         easprintf(&cp, "%s %s", user_cmnd, user_args);
761         sudo_setenv("SUDO_COMMAND", cp, TRUE);
762         efree(cp);
763     } else
764         sudo_setenv("SUDO_COMMAND", user_cmnd, TRUE);
765
766     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
767     sudo_setenv("SUDO_USER", user_name, TRUE);
768     snprintf(idbuf, sizeof(idbuf), "%lu", (unsigned long) user_uid);
769     sudo_setenv("SUDO_UID", idbuf, TRUE);
770     snprintf(idbuf, sizeof(idbuf), "%lu", (unsigned long) user_gid);
771     sudo_setenv("SUDO_GID", idbuf, TRUE);
772
773     /* Install new environment. */
774     environ = env.envp;
775     efree(old_envp);
776 }
777
778 void
779 insert_env_vars(env_vars)
780     struct list_member *env_vars;
781 {
782     struct list_member *cur;
783
784     if (env_vars == NULL)
785         return;
786
787     /* Add user-specified environment variables. */
788     for (cur = env_vars; cur != NULL; cur = cur->next)
789         putenv(cur->value);
790 }
791
792 /*
793  * Validate the list of environment variables passed in on the command
794  * line against env_delete, env_check, and env_keep.
795  * Calls log_error() if any specified variables are not allowed.
796  */
797 void
798 validate_env_vars(env_vars)
799     struct list_member *env_vars;
800 {
801     struct list_member *var;
802     char *eq, *bad = NULL;
803     size_t len, blen = 0, bsize = 0;
804     int okvar;
805
806     for (var = env_vars; var != NULL; var = var->next) {
807         if (def_secure_path && !user_is_exempt() &&
808             strncmp(var->value, "PATH=", 5) == 0) {
809             okvar = FALSE;
810         } else if (def_env_reset) {
811             okvar = matches_env_check(var->value);
812             if (okvar == -1)
813                 okvar = matches_env_keep(var->value);
814         } else {
815             okvar = matches_env_delete(var->value) == FALSE;
816             if (okvar == FALSE)
817                 okvar = matches_env_check(var->value) != FALSE;
818         }
819         if (okvar == FALSE) {
820             /* Not allowed, add to error string, allocating as needed. */
821             if ((eq = strchr(var->value, '=')) != NULL)
822                 *eq = '\0';
823             len = strlen(var->value) + 2;
824             if (blen + len >= bsize) {
825                 do {
826                     bsize += 1024;
827                 } while (blen + len >= bsize);
828                 bad = erealloc(bad, bsize);
829                 bad[blen] = '\0';
830             }
831             strlcat(bad, var->value, bsize);
832             strlcat(bad, ", ", bsize);
833             blen += len;
834             if (eq != NULL)
835                 *eq = '=';
836         }
837     }
838     if (bad != NULL) {
839         bad[blen - 2] = '\0';           /* remove trailing ", " */
840         log_error(NO_MAIL,
841             "sorry, you are not allowed to set the following environment variables: %s", bad);
842         /* NOTREACHED */
843         efree(bad);
844     }
845 }
846
847 /*
848  * Read in /etc/environment ala AIX and Linux.
849  * Lines may be in either of three formats:
850  *  NAME=VALUE
851  *  NAME="VALUE"
852  *  NAME='VALUE'
853  * with an optional "export" prefix so the shell can source the file.
854  * Invalid lines, blank lines, or lines consisting solely of a comment
855  * character are skipped.
856  */
857 void
858 read_env_file(path, overwrite)
859     const char *path;
860     int overwrite;
861 {
862     FILE *fp;
863     char *cp, *var, *val;
864     size_t var_len, val_len;
865
866     if ((fp = fopen(path, "r")) == NULL)
867         return;
868
869     while ((var = sudo_parseln(fp)) != NULL) {
870         /* Skip blank or comment lines */
871         if (*var == '\0')
872             continue;
873
874         /* Skip optional "export " */
875         if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) {
876             var += 7;
877             while (isspace((unsigned char) *var)) {
878                 var++;
879             }
880         }
881
882         /* Must be of the form name=["']value['"] */
883         for (val = var; *val != '\0' && *val != '='; val++)
884             ;
885         if (var == val || *val != '=')
886             continue;
887         var_len = (size_t)(val - var);
888         val_len = strlen(++val);
889
890         /* Strip leading and trailing single/double quotes */
891         if ((val[0] == '\'' || val[0] == '\"') && val[0] == val[val_len - 1]) {
892             val[val_len - 1] = '\0';
893             val++;
894             val_len -= 2;
895         }
896
897         cp = emalloc(var_len + 1 + val_len + 1);
898         memcpy(cp, var, var_len + 1); /* includes '=' */
899         memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */
900
901         sudo_putenv(cp, TRUE, overwrite);
902     }
903     fclose(fp);
904 }
905
906 void
907 init_envtables()
908 {
909     struct list_member *cur;
910     const char **p;
911
912     /* Fill in the "env_delete" list. */
913     for (p = initial_badenv_table; *p; p++) {
914         cur = emalloc(sizeof(struct list_member));
915         cur->value = estrdup(*p);
916         cur->next = def_env_delete;
917         def_env_delete = cur;
918     }
919
920     /* Fill in the "env_check" list. */
921     for (p = initial_checkenv_table; *p; p++) {
922         cur = emalloc(sizeof(struct list_member));
923         cur->value = estrdup(*p);
924         cur->next = def_env_check;
925         def_env_check = cur;
926     }
927
928     /* Fill in the "env_keep" list. */
929     for (p = initial_keepenv_table; *p; p++) {
930         cur = emalloc(sizeof(struct list_member));
931         cur->value = estrdup(*p);
932         cur->next = def_env_keep;
933         def_env_keep = cur;
934     }
935 }