Imported Upstream version 1.6.9p16
[debian/sudo] / env.c
1 /*
2  * Copyright (c) 2000-2007 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * Sponsored in part by the Defense Advanced Research Projects
17  * Agency (DARPA) and Air Force Research Laboratory, Air Force
18  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
19  */
20
21 #include <config.h>
22
23 #include <sys/types.h>
24 #include <sys/param.h>
25 #include <sys/stat.h>
26 #include <stdio.h>
27 #ifdef STDC_HEADERS
28 # include <stdlib.h>
29 # include <stddef.h>
30 #else
31 # ifdef HAVE_STDLIB_H
32 #  include <stdlib.h>
33 # endif
34 #endif /* STDC_HEADERS */
35 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #else
38 # ifdef HAVE_STRINGS_H
39 #  include <strings.h>
40 # endif
41 #endif /* HAVE_STRING_H */
42 #ifdef HAVE_UNISTD_H
43 # include <unistd.h>
44 #endif /* HAVE_UNISTD_H */
45 #ifdef HAVE_ERR_H
46 # include <err.h>
47 #else
48 # include "emul/err.h"
49 #endif /* HAVE_ERR_H */
50 #include <pwd.h>
51
52 #include "sudo.h"
53
54 #ifndef lint
55 __unused static const char rcsid[] = "$Sudo: env.c,v 1.39.2.18 2008/03/13 11:34:57 millert Exp $";
56 #endif /* lint */
57
58 /*
59  * Flags used in rebuild_env()
60  */
61 #undef DID_TERM
62 #define DID_TERM        0x0001
63 #undef DID_PATH
64 #define DID_PATH        0x0002
65 #undef DID_HOME
66 #define DID_HOME        0x0004
67 #undef DID_SHELL
68 #define DID_SHELL       0x0008
69 #undef DID_LOGNAME
70 #define DID_LOGNAME     0x0010
71 #undef DID_USER
72 #define DID_USER        0x0020
73 #undef DID_USERNAME
74 #define DID_USERNAME    0x0040
75 #undef DID_MAX
76 #define DID_MAX         0x00ff
77
78 #undef KEPT_TERM
79 #define KEPT_TERM       0x0100
80 #undef KEPT_PATH
81 #define KEPT_PATH       0x0200
82 #undef KEPT_HOME
83 #define KEPT_HOME       0x0400
84 #undef KEPT_SHELL
85 #define KEPT_SHELL      0x0800
86 #undef KEPT_LOGNAME
87 #define KEPT_LOGNAME    0x1000
88 #undef KEPT_USER
89 #define KEPT_USER       0x2000
90 #undef KEPT_USERNAME
91 #define KEPT_USERNAME   0x4000
92 #undef KEPT_MAX
93 #define KEPT_MAX        0xff00
94
95 #undef VNULL
96 #define VNULL   (VOID *)NULL
97
98 struct environment {
99     char **envp;                /* pointer to the new environment */
100     size_t env_size;            /* size of new_environ in char **'s */
101     size_t env_len;             /* number of slots used, not counting NULL */
102 };
103
104 /*
105  * Prototypes
106  */
107 char **rebuild_env              __P((char **, int, int));
108 static void insert_env          __P((char *, struct environment *, int));
109 static char *format_env         __P((char *, ...));
110
111 /*
112  * Copy of the sudo-managed environment.
113  */
114 static struct environment env;
115
116 /*
117  * Default table of "bad" variables to remove from the environment.
118  * XXX - how to omit TERMCAP if it starts with '/'?
119  */
120 static const char *initial_badenv_table[] = {
121     "IFS",
122     "CDPATH",
123     "LOCALDOMAIN",
124     "RES_OPTIONS",
125     "HOSTALIASES",
126     "NLSPATH",
127     "PATH_LOCALE",
128     "LD_*",
129     "_RLD*",
130 #ifdef __hpux
131     "SHLIB_PATH",
132 #endif /* __hpux */
133 #ifdef _AIX
134     "LDR_*",
135     "LIBPATH",
136 #endif
137 #ifdef __APPLE__
138     "DYLD_*",
139 #endif
140 #ifdef HAVE_KERB4
141     "KRB_CONF*",
142     "KRBCONFDIR",
143     "KRBTKFILE",
144 #endif /* HAVE_KERB4 */
145 #ifdef HAVE_KERB5
146     "KRB5_CONFIG*",
147     "KRB5_KTNAME",
148 #endif /* HAVE_KERB5 */
149 #ifdef HAVE_SECURID
150     "VAR_ACE",
151     "USR_ACE",
152     "DLC_ACE",
153 #endif /* HAVE_SECURID */
154     "TERMINFO",                 /* terminfo, exclusive path to terminfo files */
155     "TERMINFO_DIRS",            /* terminfo, path(s) to terminfo files */
156     "TERMPATH",                 /* termcap, path(s) to termcap files */
157     "TERMCAP",                  /* XXX - only if it starts with '/' */
158     "ENV",                      /* ksh, file to source before script runs */
159     "BASH_ENV",                 /* bash, file to source before script runs */
160     "PS4",                      /* bash, prefix for lines in xtrace mode */
161     "GLOBIGNORE",               /* bash, globbing patterns to ignore */
162     "SHELLOPTS",                /* bash, extra command line options */
163     "JAVA_TOOL_OPTIONS",        /* java, extra command line options */
164     "PERLIO_DEBUG ",            /* perl, debugging output file */
165     "PERLLIB",                  /* perl, search path for modules/includes */
166     "PERL5LIB",                 /* perl 5, search path for modules/includes */
167     "PERL5OPT",                 /* perl 5, extra command line options */
168     "PERL5DB",                  /* perl 5, command used to load debugger */
169     "FPATH",                    /* ksh, search path for functions */
170     "NULLCMD",                  /* zsh, command for null file redirection */
171     "READNULLCMD",              /* zsh, command for null file redirection */
172     "ZDOTDIR",                  /* zsh, search path for dot files */
173     "TMPPREFIX",                /* zsh, prefix for temporary files */
174     "PYTHONHOME",               /* python, module search path */
175     "PYTHONPATH",               /* python, search path */
176     "PYTHONINSPECT",            /* python, allow inspection */
177     "RUBYLIB",                  /* ruby, library load path */
178     "RUBYOPT",                  /* ruby, extra command line options */
179     NULL
180 };
181
182 /*
183  * Default table of variables to check for '%' and '/' characters.
184  */
185 static const char *initial_checkenv_table[] = {
186     "COLORTERM",
187     "LANG",
188     "LANGUAGE",
189     "LC_*",
190     "LINGUAS",
191     "TERM",
192     NULL
193 };
194
195 /*
196  * Default table of variables to preserve in the environment.
197  */
198 static const char *initial_keepenv_table[] = {
199     "COLORS",
200     "DISPLAY",
201     "HOME",
202     "HOSTNAME",
203     "KRB5CCNAME",
204     "LS_COLORS",
205     "MAIL",
206     "PATH",
207     "PS1",
208     "PS2",
209     "TZ",
210     "XAUTHORITY",
211     "XAUTHORIZATION",
212     NULL
213 };
214
215 /*
216  * Given a variable and value, allocate and format an environment string.
217  */
218 static char *
219 #ifdef __STDC__
220 format_env(char *var, ...)
221 #else
222 format_env(var, va_alist)
223     char *var;
224     va_dcl
225 #endif
226 {
227     char *estring;
228     char *val;
229     size_t esize;
230     va_list ap;
231
232 #ifdef __STDC__
233     va_start(ap, var);
234 #else
235     va_start(ap);
236 #endif
237     esize = strlen(var) + 2;
238     while ((val = va_arg(ap, char *)) != NULL)
239         esize += strlen(val);
240     va_end(ap);
241     estring = (char *) emalloc(esize);
242
243     /* Store variable name and the '=' separator.  */
244     if (strlcpy(estring, var, esize) >= esize ||
245         strlcat(estring, "=", esize) >= esize) {
246
247         errx(1, "internal error, format_env() overflow");
248     }
249
250     /* Now store the variable's value (if any) */
251 #ifdef __STDC__
252     va_start(ap, var);
253 #else
254     va_start(ap);
255 #endif
256     while ((val = va_arg(ap, char *)) != NULL) {
257         if (strlcat(estring, val, esize) >= esize)
258             errx(1, "internal error, format_env() overflow");
259     }
260     va_end(ap);
261
262     return(estring);
263 }
264
265 /*
266  * Insert str into e->envp, assumes str has an '=' in it.
267  */
268 static void
269 insert_env(str, e, dupcheck)
270     char *str;
271     struct environment *e;
272     int dupcheck;
273 {
274     char **nep;
275     size_t varlen;
276
277     /* Make sure there is room for the new entry plus a NULL. */
278     if (e->env_len + 2 > e->env_size) {
279         e->env_size += 128;
280         e->envp = erealloc3(e->envp, e->env_size, sizeof(char *));
281     }
282
283     if (dupcheck) {
284             varlen = (strchr(str, '=') - str) + 1;
285
286             for (nep = e->envp; *nep; nep++) {
287                 if (strncmp(str, *nep, varlen) == 0) {
288                     *nep = str;
289                     return;
290                 }
291             }
292     } else
293         nep = e->envp + e->env_len;
294
295     e->env_len++;
296     *nep++ = str;
297     *nep = NULL;
298 }
299
300 /*
301  * Check the env_delete blacklist.
302  * Returns TRUE if the variable was found, else false.
303  */
304 static int
305 matches_env_delete(var)
306     const char *var;
307 {
308     struct list_member *cur;
309     size_t len;
310     int iswild, match = FALSE;
311
312     /* Skip anything listed in env_delete. */
313     for (cur = def_env_delete; cur; cur = cur->next) {
314         len = strlen(cur->value);
315         /* Deal with '*' wildcard */
316         if (cur->value[len - 1] == '*') {
317             len--;
318             iswild = TRUE;
319         } else
320             iswild = FALSE;
321         if (strncmp(cur->value, var, len) == 0 &&
322             (iswild || var[len] == '=')) {
323             match = TRUE;
324             break;
325         }
326     }
327     return(match);
328 }
329
330 /*
331  * Apply the env_check list.
332  * Returns TRUE if the variable is allowed, FALSE if denied
333  * or -1 if no match.
334  */
335 static int
336 matches_env_check(var)
337     const char *var;
338 {
339     struct list_member *cur;
340     size_t len;
341     int iswild, keepit = -1;
342
343     for (cur = def_env_check; cur; cur = cur->next) {
344         len = strlen(cur->value);
345         /* Deal with '*' wildcard */
346         if (cur->value[len - 1] == '*') {
347             len--;
348             iswild = TRUE;
349         } else
350             iswild = FALSE;
351         if (strncmp(cur->value, var, len) == 0 &&
352             (iswild || var[len] == '=')) {
353             keepit = !strpbrk(var, "/%");
354             break;
355         }
356     }
357     return(keepit);
358 }
359
360 /*
361  * Check the env_keep list.
362  * Returns TRUE if the variable is allowed else FALSE.
363  */
364 static int
365 matches_env_keep(var)
366     const char *var;
367 {
368     struct list_member *cur;
369     size_t len;
370     int iswild, keepit = FALSE;
371
372     for (cur = def_env_keep; cur; cur = cur->next) {
373         len = strlen(cur->value);
374         /* Deal with '*' wildcard */
375         if (cur->value[len - 1] == '*') {
376             len--;
377             iswild = TRUE;
378         } else
379             iswild = FALSE;
380         if (strncmp(cur->value, var, len) == 0 &&
381             (iswild || var[len] == '=')) {
382             keepit = TRUE;
383             break;
384         }
385     }
386     return(keepit);
387 }
388
389 /*
390  * Build a new environment and ether clear potentially dangerous
391  * variables from the old one or start with a clean slate.
392  * Also adds sudo-specific variables (SUDO_*).
393  */
394 char **
395 rebuild_env(envp, sudo_mode, noexec)
396     char **envp;
397     int sudo_mode;
398     int noexec;
399 {
400     char **ep, *cp, *ps1;
401     unsigned int didvar;
402
403     /*
404      * Either clean out the environment or reset to a safe default.
405      */
406     ps1 = NULL;
407     didvar = 0;
408     memset(&env, 0, sizeof(env));
409     if (def_env_reset) {
410         /* Pull in vars we want to keep from the old environment. */
411         for (ep = envp; *ep; ep++) {
412             int keepit;
413
414             /* Skip variables with values beginning with () (bash functions) */
415             if ((cp = strchr(*ep, '=')) != NULL) {
416                 if (strncmp(cp, "=() ", 3) == 0)
417                     continue;
418             }
419
420             /*
421              * First check certain variables for '%' and '/' characters.
422              * If no match there, check the keep list.
423              * If nothing matched, we remove it from the environment.
424              */
425             keepit = matches_env_check(*ep);
426             if (keepit == -1)
427                 keepit = matches_env_keep(*ep);
428
429             /* For SUDO_PS1 -> PS1 conversion. */
430             if (strncmp(*ep, "SUDO_PS1=", 8) == 0)
431                 ps1 = *ep + 5;
432
433             if (keepit) {
434                 /* Preserve variable. */
435                 switch (**ep) {
436                     case 'H':
437                         if (strncmp(*ep, "HOME=", 5) == 0)
438                             SET(didvar, DID_HOME);
439                         break;
440                     case 'L':
441                         if (strncmp(*ep, "LOGNAME=", 8) == 0)
442                             SET(didvar, DID_LOGNAME);
443                         break;
444                     case 'P':
445                         if (strncmp(*ep, "PATH=", 5) == 0)
446                             SET(didvar, DID_PATH);
447                         break;
448                     case 'S':
449                         if (strncmp(*ep, "SHELL=", 6) == 0)
450                             SET(didvar, DID_SHELL);
451                         break;
452                     case 'T':
453                         if (strncmp(*ep, "TERM=", 5) == 0)
454                             SET(didvar, DID_TERM);
455                         break;
456                     case 'U':
457                         if (strncmp(*ep, "USER=", 5) == 0)
458                             SET(didvar, DID_USER);
459                         if (strncmp(*ep, "USERNAME=", 5) == 0)
460                             SET(didvar, DID_USERNAME);
461                         break;
462                 }
463                 insert_env(*ep, &env, 0);
464             }
465         }
466         didvar |= didvar << 8;          /* convert DID_* to KEPT_* */
467
468         /*
469          * Add in defaults.  In -i mode these come from the runas user,
470          * otherwise they may be from the user's environment (depends
471          * on sudoers options).
472          */
473         if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) {
474             insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), &env,
475                 ISSET(didvar, DID_HOME));
476             insert_env(format_env("SHELL", runas_pw->pw_shell, VNULL), &env,
477                 ISSET(didvar, DID_SHELL));
478             insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), &env,
479                 ISSET(didvar, DID_LOGNAME));
480             insert_env(format_env("USER", runas_pw->pw_name, VNULL), &env,
481                 ISSET(didvar, DID_USER));
482             insert_env(format_env("USERNAME", runas_pw->pw_name, VNULL), &env,
483                 ISSET(didvar, DID_USERNAME));
484         } else {
485             if (!ISSET(didvar, DID_HOME))
486                 insert_env(format_env("HOME", user_dir, VNULL), &env, 0);
487             if (!ISSET(didvar, DID_SHELL))
488                 insert_env(format_env("SHELL", sudo_user.pw->pw_shell, VNULL),
489                     &env, 0);
490             if (!ISSET(didvar, DID_LOGNAME))
491                 insert_env(format_env("LOGNAME", user_name, VNULL), &env, 0);
492             if (!ISSET(didvar, DID_USER))
493                 insert_env(format_env("USER", user_name, VNULL), &env, 0);
494             if (!ISSET(didvar, DID_USERNAME))
495                 insert_env(format_env("USERNAME", user_name, VNULL), &env, 0);
496         }
497     } else {
498         /*
499          * Copy envp entries as long as they don't match env_delete or
500          * env_check.
501          */
502         for (ep = envp; *ep; ep++) {
503             int okvar;
504
505             /* Skip variables with values beginning with () (bash functions) */
506             if ((cp = strchr(*ep, '=')) != NULL) {
507                 if (strncmp(cp, "=() ", 3) == 0)
508                     continue;
509             }
510
511             /*
512              * First check variables against the blacklist in env_delete.
513              * If no match there check for '%' and '/' characters.
514              */
515             okvar = matches_env_delete(*ep) != TRUE;
516             if (okvar)
517                 okvar = matches_env_check(*ep) != FALSE;
518
519             if (okvar) {
520                 if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
521                     ps1 = *ep + 5;
522                 else if (strncmp(*ep, "PATH=", 5) == 0)
523                     SET(didvar, DID_PATH);
524                 else if (strncmp(*ep, "TERM=", 5) == 0)
525                     SET(didvar, DID_TERM);
526                 insert_env(*ep, &env, 0);
527             }
528         }
529     }
530
531 #ifdef SECURE_PATH
532     /* Replace the PATH envariable with a secure one. */
533     if (!user_is_exempt()) {
534         insert_env(format_env("PATH", SECURE_PATH, VNULL), &env, 1);
535         SET(didvar, DID_PATH);
536     }
537 #endif
538
539     /* Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is true. */
540     if (def_set_logname && runas_pw->pw_name) {
541         if (!ISSET(didvar, KEPT_LOGNAME))
542             insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), &env, 1);
543         if (!ISSET(didvar, KEPT_USER))
544             insert_env(format_env("USER", runas_pw->pw_name, VNULL), &env, 1);
545         if (!ISSET(didvar, KEPT_USERNAME))
546             insert_env(format_env("USERNAME", runas_pw->pw_name, VNULL), &env, 1);
547     }
548
549     /* Set $HOME for `sudo -H'.  Only valid at PERM_FULL_RUNAS. */
550     if (runas_pw->pw_dir) {
551         if (ISSET(sudo_mode, MODE_RESET_HOME) ||
552             (ISSET(sudo_mode, MODE_RUN) && (def_always_set_home ||
553             (ISSET(sudo_mode, MODE_SHELL) && def_set_home))))
554             insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), &env, 1);
555     }
556
557     /* Provide default values for $TERM and $PATH if they are not set. */
558     if (!ISSET(didvar, DID_TERM))
559         insert_env("TERM=unknown", &env, 0);
560     if (!ISSET(didvar, DID_PATH))
561         insert_env(format_env("PATH", _PATH_DEFPATH, VNULL), &env, 0);
562
563     /*
564      * Preload a noexec file?  For a list of LD_PRELOAD-alikes, see
565      * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
566      * XXX - should prepend to original value, if any
567      */
568     if (noexec && def_noexec_file != NULL) {
569 #if defined(__darwin__) || defined(__APPLE__)
570         insert_env(format_env("DYLD_INSERT_LIBRARIES", def_noexec_file, VNULL),
571             &env, 1);
572         insert_env(format_env("DYLD_FORCE_FLAT_NAMESPACE", VNULL), &env, 1);
573 #else
574 # if defined(__osf__) || defined(__sgi)
575         insert_env(format_env("_RLD_LIST", def_noexec_file, ":DEFAULT", VNULL),
576             &env, 1);
577 # else
578 #  ifdef _AIX
579         insert_env(format_env("LDR_PRELOAD", def_noexec_file, VNULL), &env, 1);
580 #  else
581         insert_env(format_env("LD_PRELOAD", def_noexec_file, VNULL), &env, 1);
582 #  endif /* _AIX */
583 # endif /* __osf__ || __sgi */
584 #endif /* __darwin__ || __APPLE__ */
585     }
586
587     /* Set PS1 if SUDO_PS1 is set. */
588     if (ps1)
589         insert_env(ps1, &env, 1);
590
591     /* Add the SUDO_COMMAND envariable (cmnd + args). */
592     if (user_args)
593         insert_env(format_env("SUDO_COMMAND", user_cmnd, " ", user_args, VNULL),
594             &env, 1);
595     else
596         insert_env(format_env("SUDO_COMMAND", user_cmnd, VNULL), &env, 1);
597
598     /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
599     insert_env(format_env("SUDO_USER", user_name, VNULL), &env, 1);
600     easprintf(&cp, "SUDO_UID=%lu", (unsigned long) user_uid);
601     insert_env(cp, &env, 1);
602     easprintf(&cp, "SUDO_GID=%lu", (unsigned long) user_gid);
603     insert_env(cp, &env, 1);
604
605     return(env.envp);
606 }
607
608 char **
609 insert_env_vars(envp, env_vars)
610     char **envp;
611     struct list_member *env_vars;
612 {
613     struct list_member *cur;
614
615     if (env_vars == NULL)
616         return (envp);
617
618     /*
619      * Make sure we still own the environment and steal it back if not.
620      */
621     if (env.envp != envp) {
622         size_t evlen;
623         char **ep;
624
625         for (ep = envp; *ep != NULL; ep++)
626             continue;
627         evlen = ep - envp;
628         if (evlen + 1 > env.env_size) {
629             efree(env.envp);
630             env.env_size = evlen + 1 + 128;
631             env.envp = emalloc2(env.env_size, sizeof(char *));
632         }
633         memcpy(env.envp, envp, (evlen + 1) * sizeof(char *));
634         env.env_len = evlen;
635     }
636
637     /* Add user-specified environment variables. */
638     for (cur = env_vars; cur != NULL; cur = cur->next)
639         insert_env(cur->value, &env, 1);
640
641     return(env.envp);
642 }
643
644 /*
645  * Validate the list of environment variables passed in on the command
646  * line against env_delete, env_check, and env_keep.
647  * Calls log_error() if any specified variables are not allowed.
648  */
649 void
650 validate_env_vars(env_vars)
651     struct list_member *env_vars;
652 {
653     struct list_member *var;
654     char *eq, *bad = NULL;
655     size_t len, blen = 0, bsize = 0;
656     int okvar;
657
658     for (var = env_vars; var != NULL; var = var->next) {
659 #ifdef SECURE_PATH
660         if (!user_is_exempt() && strncmp(var->value, "PATH=", 5) == 0) {
661             okvar = FALSE;
662         } else
663 #endif
664         if (def_env_reset) {
665             okvar = matches_env_check(var->value);
666             if (okvar == -1)
667                 okvar = matches_env_keep(var->value);
668         } else {
669             okvar = matches_env_delete(var->value) == FALSE;
670             if (okvar == FALSE)
671                 okvar = matches_env_check(var->value) != FALSE;
672         }
673         if (okvar == FALSE) {
674             /* Not allowed, add to error string, allocating as needed. */
675             if ((eq = strchr(var->value, '=')) != NULL)
676                 *eq = '\0';
677             len = strlen(var->value) + 2;
678             if (blen + len >= bsize) {
679                 do {
680                     bsize += 1024;
681                 } while (blen + len >= bsize);
682                 bad = erealloc(bad, bsize);
683                 bad[blen] = '\0';
684             }
685             strlcat(bad, var->value, bsize);
686             strlcat(bad, ", ", bsize);
687             blen += len;
688             if (eq != NULL)
689                 *eq = '=';
690         }
691     }
692     if (bad != NULL) {
693         bad[blen - 2] = '\0';           /* remove trailing ", " */
694         log_error(NO_MAIL,
695             "sorry, you are not allowed to set the following environment variables: %s", bad);
696         /* NOTREACHED */
697         efree(bad);
698     }
699 }
700
701 void
702 init_envtables()
703 {
704     struct list_member *cur;
705     const char **p;
706
707     /* Fill in the "env_delete" list. */
708     for (p = initial_badenv_table; *p; p++) {
709         cur = emalloc(sizeof(struct list_member));
710         cur->value = estrdup(*p);
711         cur->next = def_env_delete;
712         def_env_delete = cur;
713     }
714
715     /* Fill in the "env_check" list. */
716     for (p = initial_checkenv_table; *p; p++) {
717         cur = emalloc(sizeof(struct list_member));
718         cur->value = estrdup(*p);
719         cur->next = def_env_check;
720         def_env_check = cur;
721     }
722
723     /* Fill in the "env_keep" list. */
724     for (p = initial_keepenv_table; *p; p++) {
725         cur = emalloc(sizeof(struct list_member));
726         cur->value = estrdup(*p);
727         cur->next = def_env_keep;
728         def_env_keep = cur;
729     }
730 }