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