~ubuntu-branches/ubuntu/oneiric/sudo/oneiric-updates

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