Merge lp:~ubuntu-branches/ubuntu/oneiric/sudo/oneiric-201105230807 into lp:ubuntu/oneiric/sudo
- Oneiric (11.10)
- oneiric-201105230807
- Merge into oneiric
Proposed by
James Westby
Status: | Rejected |
---|---|
Rejected by: | James Westby |
Proposed branch: | lp:~ubuntu-branches/ubuntu/oneiric/sudo/oneiric-201105230807 |
Merge into: | lp:ubuntu/oneiric/sudo |
Diff against target: |
2856 lines (+2801/-0) (has conflicts) 5 files modified
.pc/CVE-2011-0010.patch/check.c (+694/-0) .pc/applied-patches (+6/-0) .pc/debian-changes-1.7.4p6-1/env.c (+996/-0) .pc/keep_home_by_default.patch/env.c (+1000/-0) debian/changelog (+105/-0) Text conflict in .pc/applied-patches Text conflict in .pc/debian-changes-1.7.4p6-1/env.c Text conflict in .pc/keep_home_by_default.patch/env.c Text conflict in debian/changelog |
To merge this branch: | bzr merge lp:~ubuntu-branches/ubuntu/oneiric/sudo/oneiric-201105230807 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+61926@code.launchpad.net |
Commit message
Description of the change
The package history in the archive and the history in the bzr branch differ. As the archive is authoritative the history of lp:ubuntu/oneiric/sudo now reflects that and the old bzr branch has been pushed to lp:~ubuntu-branches/ubuntu/oneiric/sudo/oneiric-201105230807. A merge should be performed if necessary.
To post a comment you must log in.
Unmerged revisions
- 50. By Michael Vogt
-
merged from lp:debian/sudo and resolved conflicts
- 49. By Michael Vogt
-
* debian/
sudo.preinst:
- if well-known ec2 vmbuilder file is found, write a file in
sudoers.d for the 'ubuntu' user (LP: #768625)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory '.pc/CVE-2011-0010.patch' |
2 | === added file '.pc/CVE-2011-0010.patch/check.c' |
3 | --- .pc/CVE-2011-0010.patch/check.c 1970-01-01 00:00:00 +0000 |
4 | +++ .pc/CVE-2011-0010.patch/check.c 2011-05-23 08:12:57 +0000 |
5 | @@ -0,0 +1,694 @@ |
6 | +/* |
7 | + * Copyright (c) 1993-1996,1998-2005, 2007-2010 |
8 | + * Todd C. Miller <Todd.Miller@courtesan.com> |
9 | + * |
10 | + * Permission to use, copy, modify, and distribute this software for any |
11 | + * purpose with or without fee is hereby granted, provided that the above |
12 | + * copyright notice and this permission notice appear in all copies. |
13 | + * |
14 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
15 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
16 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
17 | + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
18 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
19 | + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
20 | + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
21 | + * |
22 | + * Sponsored in part by the Defense Advanced Research Projects |
23 | + * Agency (DARPA) and Air Force Research Laboratory, Air Force |
24 | + * Materiel Command, USAF, under agreement number F39502-99-1-0512. |
25 | + */ |
26 | + |
27 | +#include <config.h> |
28 | + |
29 | +#include <sys/types.h> |
30 | +#include <sys/param.h> |
31 | +#include <sys/time.h> |
32 | +#include <sys/stat.h> |
33 | +#ifdef __linux__ |
34 | +# include <sys/vfs.h> |
35 | +#endif |
36 | +#if defined(__sun) && defined(__SVR4) |
37 | +# include <sys/statvfs.h> |
38 | +#endif |
39 | +#ifndef __TANDEM |
40 | +# include <sys/file.h> |
41 | +#endif |
42 | +#include <stdio.h> |
43 | +#ifdef STDC_HEADERS |
44 | +# include <stdlib.h> |
45 | +# include <stddef.h> |
46 | +#else |
47 | +# ifdef HAVE_STDLIB_H |
48 | +# include <stdlib.h> |
49 | +# endif |
50 | +#endif /* STDC_HEADERS */ |
51 | +#ifdef HAVE_STRING_H |
52 | +# include <string.h> |
53 | +#endif /* HAVE_STRING_H */ |
54 | +#ifdef HAVE_STRINGS_H |
55 | +# include <strings.h> |
56 | +#endif /* HAVE_STRINGS_H */ |
57 | +#ifdef HAVE_UNISTD_H |
58 | +# include <unistd.h> |
59 | +#endif /* HAVE_UNISTD_H */ |
60 | +#if TIME_WITH_SYS_TIME |
61 | +# include <time.h> |
62 | +#endif |
63 | +#include <errno.h> |
64 | +#include <fcntl.h> |
65 | +#include <signal.h> |
66 | +#include <pwd.h> |
67 | +#include <grp.h> |
68 | + |
69 | +#include "sudo.h" |
70 | + |
71 | +/* Status codes for timestamp_status() */ |
72 | +#define TS_CURRENT 0 |
73 | +#define TS_OLD 1 |
74 | +#define TS_MISSING 2 |
75 | +#define TS_NOFILE 3 |
76 | +#define TS_ERROR 4 |
77 | + |
78 | +/* Flags for timestamp_status() */ |
79 | +#define TS_MAKE_DIRS 1 |
80 | +#define TS_REMOVE 2 |
81 | + |
82 | +/* |
83 | + * Info stored in tty ticket from stat(2) to help with tty matching. |
84 | + */ |
85 | +static struct tty_info { |
86 | + dev_t dev; /* ID of device tty resides on */ |
87 | + dev_t rdev; /* tty device ID */ |
88 | + ino_t ino; /* tty inode number */ |
89 | + struct timeval ctime; /* tty inode change time */ |
90 | +} tty_info; |
91 | + |
92 | +static void build_timestamp __P((char **, char **)); |
93 | +static int timestamp_status __P((char *, char *, char *, int)); |
94 | +static char *expand_prompt __P((char *, char *, char *)); |
95 | +static void lecture __P((int)); |
96 | +static void update_timestamp __P((char *, char *)); |
97 | +static int tty_is_devpts __P((const char *)); |
98 | + |
99 | +/* |
100 | + * This function only returns if the user can successfully |
101 | + * verify who he/she is. |
102 | + */ |
103 | +void |
104 | +check_user(validated, mode) |
105 | + int validated; |
106 | + int mode; |
107 | +{ |
108 | + char *timestampdir = NULL; |
109 | + char *timestampfile = NULL; |
110 | + char *prompt; |
111 | + struct stat sb; |
112 | + int status; |
113 | + |
114 | + /* Stash the tty's ctime for tty ticket comparison. */ |
115 | + if (def_tty_tickets && user_ttypath && stat(user_ttypath, &sb) == 0) { |
116 | + tty_info.dev = sb.st_dev; |
117 | + tty_info.ino = sb.st_ino; |
118 | + tty_info.rdev = sb.st_rdev; |
119 | + if (tty_is_devpts(user_ttypath)) |
120 | + ctim_get(&sb, &tty_info.ctime); |
121 | + } |
122 | + |
123 | + /* Always prompt for a password when -k was specified with the command. */ |
124 | + if (ISSET(mode, MODE_INVALIDATE)) { |
125 | + SET(validated, FLAG_CHECK_USER); |
126 | + } else { |
127 | + if (user_uid == 0 || user_uid == runas_pw->pw_uid || user_is_exempt()) |
128 | + return; |
129 | + } |
130 | + |
131 | + build_timestamp(×tampdir, ×tampfile); |
132 | + status = timestamp_status(timestampdir, timestampfile, user_name, |
133 | + TS_MAKE_DIRS); |
134 | + |
135 | + if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) { |
136 | + /* Bail out if we are non-interactive and a password is required */ |
137 | + if (ISSET(mode, MODE_NONINTERACTIVE)) |
138 | + errorx(1, "sorry, a password is required to run %s", getprogname()); |
139 | + |
140 | + /* If user specified -A, make sure we have an askpass helper. */ |
141 | + if (ISSET(tgetpass_flags, TGP_ASKPASS)) { |
142 | + if (user_askpass == NULL) |
143 | + log_error(NO_MAIL, |
144 | + "no askpass program specified, try setting SUDO_ASKPASS"); |
145 | + } else if (!ISSET(tgetpass_flags, TGP_STDIN)) { |
146 | + /* If no tty but DISPLAY is set, use askpass if we have it. */ |
147 | + if (!user_ttypath && !tty_present()) { |
148 | + if (user_askpass && user_display && *user_display != '\0') { |
149 | + SET(tgetpass_flags, TGP_ASKPASS); |
150 | + } else if (!def_visiblepw) { |
151 | + log_error(NO_MAIL, |
152 | + "no tty present and no askpass program specified"); |
153 | + } |
154 | + } |
155 | + } |
156 | + |
157 | + if (!ISSET(tgetpass_flags, TGP_ASKPASS)) |
158 | + lecture(status); |
159 | + |
160 | + /* Expand any escapes in the prompt. */ |
161 | + prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt, |
162 | + user_name, user_shost); |
163 | + |
164 | + verify_user(auth_pw, prompt); |
165 | + } |
166 | + /* Only update timestamp if user was validated. */ |
167 | + if (ISSET(validated, VALIDATE_OK) && !ISSET(mode, MODE_INVALIDATE) && status != TS_ERROR) |
168 | + update_timestamp(timestampdir, timestampfile); |
169 | + efree(timestampdir); |
170 | + efree(timestampfile); |
171 | +} |
172 | + |
173 | +/* |
174 | + * Standard sudo lecture. |
175 | + */ |
176 | +static void |
177 | +lecture(status) |
178 | + int status; |
179 | +{ |
180 | + FILE *fp; |
181 | + char buf[BUFSIZ]; |
182 | + ssize_t nread; |
183 | + |
184 | + if (def_lecture == never || |
185 | + (def_lecture == once && status != TS_MISSING && status != TS_ERROR)) |
186 | + return; |
187 | + |
188 | + if (def_lecture_file && (fp = fopen(def_lecture_file, "r")) != NULL) { |
189 | + while ((nread = fread(buf, sizeof(char), sizeof(buf), fp)) != 0) |
190 | + fwrite(buf, nread, 1, stderr); |
191 | + fclose(fp); |
192 | + } else { |
193 | + (void) fputs("\n\ |
194 | +We trust you have received the usual lecture from the local System\n\ |
195 | +Administrator. It usually boils down to these three things:\n\ |
196 | +\n\ |
197 | + #1) Respect the privacy of others.\n\ |
198 | + #2) Think before you type.\n\ |
199 | + #3) With great power comes great responsibility.\n\n", |
200 | + stderr); |
201 | + } |
202 | +} |
203 | + |
204 | +/* |
205 | + * Update the time on the timestamp file/dir or create it if necessary. |
206 | + */ |
207 | +static void |
208 | +update_timestamp(timestampdir, timestampfile) |
209 | + char *timestampdir; |
210 | + char *timestampfile; |
211 | +{ |
212 | + /* If using tty timestamps but we have no tty there is nothing to do. */ |
213 | + if (def_tty_tickets && !user_ttypath) |
214 | + return; |
215 | + |
216 | + if (timestamp_uid != 0) |
217 | + set_perms(PERM_TIMESTAMP); |
218 | + if (timestampfile) { |
219 | + /* |
220 | + * Store tty info in timestamp file |
221 | + */ |
222 | + int fd = open(timestampfile, O_WRONLY|O_CREAT, 0600); |
223 | + if (fd == -1) |
224 | + log_error(NO_EXIT|USE_ERRNO, "Can't open %s", timestampfile); |
225 | + else { |
226 | + lock_file(fd, SUDO_LOCK); |
227 | + write(fd, &tty_info, sizeof(tty_info)); |
228 | + close(fd); |
229 | + } |
230 | + } else { |
231 | + if (touch(-1, timestampdir, NULL) == -1) { |
232 | + if (mkdir(timestampdir, 0700) == -1) |
233 | + log_error(NO_EXIT|USE_ERRNO, "Can't mkdir %s", timestampdir); |
234 | + } |
235 | + } |
236 | + if (timestamp_uid != 0) |
237 | + set_perms(PERM_ROOT); |
238 | +} |
239 | + |
240 | +/* |
241 | + * Expand %h and %u escapes in the prompt and pass back the dynamically |
242 | + * allocated result. Returns the same string if there are no escapes. |
243 | + */ |
244 | +static char * |
245 | +expand_prompt(old_prompt, user, host) |
246 | + char *old_prompt; |
247 | + char *user; |
248 | + char *host; |
249 | +{ |
250 | + size_t len, n; |
251 | + int subst; |
252 | + char *p, *np, *new_prompt, *endp; |
253 | + |
254 | + /* How much space do we need to malloc for the prompt? */ |
255 | + subst = 0; |
256 | + for (p = old_prompt, len = strlen(old_prompt); *p; p++) { |
257 | + if (p[0] =='%') { |
258 | + switch (p[1]) { |
259 | + case 'h': |
260 | + p++; |
261 | + len += strlen(user_shost) - 2; |
262 | + subst = 1; |
263 | + break; |
264 | + case 'H': |
265 | + p++; |
266 | + len += strlen(user_host) - 2; |
267 | + subst = 1; |
268 | + break; |
269 | + case 'p': |
270 | + p++; |
271 | + if (def_rootpw) |
272 | + len += 2; |
273 | + else if (def_targetpw || def_runaspw) |
274 | + len += strlen(runas_pw->pw_name) - 2; |
275 | + else |
276 | + len += strlen(user_name) - 2; |
277 | + subst = 1; |
278 | + break; |
279 | + case 'u': |
280 | + p++; |
281 | + len += strlen(user_name) - 2; |
282 | + subst = 1; |
283 | + break; |
284 | + case 'U': |
285 | + p++; |
286 | + len += strlen(runas_pw->pw_name) - 2; |
287 | + subst = 1; |
288 | + break; |
289 | + case '%': |
290 | + p++; |
291 | + len--; |
292 | + subst = 1; |
293 | + break; |
294 | + default: |
295 | + break; |
296 | + } |
297 | + } |
298 | + } |
299 | + |
300 | + if (subst) { |
301 | + new_prompt = (char *) emalloc(++len); |
302 | + endp = new_prompt + len; |
303 | + for (p = old_prompt, np = new_prompt; *p; p++) { |
304 | + if (p[0] =='%') { |
305 | + switch (p[1]) { |
306 | + case 'h': |
307 | + p++; |
308 | + n = strlcpy(np, user_shost, np - endp); |
309 | + if (n >= np - endp) |
310 | + goto oflow; |
311 | + np += n; |
312 | + continue; |
313 | + case 'H': |
314 | + p++; |
315 | + n = strlcpy(np, user_host, np - endp); |
316 | + if (n >= np - endp) |
317 | + goto oflow; |
318 | + np += n; |
319 | + continue; |
320 | + case 'p': |
321 | + p++; |
322 | + if (def_rootpw) |
323 | + n = strlcpy(np, "root", np - endp); |
324 | + else if (def_targetpw || def_runaspw) |
325 | + n = strlcpy(np, runas_pw->pw_name, np - endp); |
326 | + else |
327 | + n = strlcpy(np, user_name, np - endp); |
328 | + if (n >= np - endp) |
329 | + goto oflow; |
330 | + np += n; |
331 | + continue; |
332 | + case 'u': |
333 | + p++; |
334 | + n = strlcpy(np, user_name, np - endp); |
335 | + if (n >= np - endp) |
336 | + goto oflow; |
337 | + np += n; |
338 | + continue; |
339 | + case 'U': |
340 | + p++; |
341 | + n = strlcpy(np, runas_pw->pw_name, np - endp); |
342 | + if (n >= np - endp) |
343 | + goto oflow; |
344 | + np += n; |
345 | + continue; |
346 | + case '%': |
347 | + /* convert %% -> % */ |
348 | + p++; |
349 | + break; |
350 | + default: |
351 | + /* no conversion */ |
352 | + break; |
353 | + } |
354 | + } |
355 | + *np++ = *p; |
356 | + if (np >= endp) |
357 | + goto oflow; |
358 | + } |
359 | + *np = '\0'; |
360 | + } else |
361 | + new_prompt = old_prompt; |
362 | + |
363 | + return(new_prompt); |
364 | + |
365 | +oflow: |
366 | + /* We pre-allocate enough space, so this should never happen. */ |
367 | + errorx(1, "internal error, expand_prompt() overflow"); |
368 | +} |
369 | + |
370 | +/* |
371 | + * Checks if the user is exempt from supplying a password. |
372 | + */ |
373 | +int |
374 | +user_is_exempt() |
375 | +{ |
376 | + if (!def_exempt_group) |
377 | + return(FALSE); |
378 | + return(user_in_group(sudo_user.pw, def_exempt_group)); |
379 | +} |
380 | + |
381 | +/* |
382 | + * Fills in timestampdir as well as timestampfile if using tty tickets. |
383 | + */ |
384 | +static void |
385 | +build_timestamp(timestampdir, timestampfile) |
386 | + char **timestampdir; |
387 | + char **timestampfile; |
388 | +{ |
389 | + char *dirparent; |
390 | + int len; |
391 | + |
392 | + dirparent = def_timestampdir; |
393 | + len = easprintf(timestampdir, "%s/%s", dirparent, user_name); |
394 | + if (len >= PATH_MAX) |
395 | + log_error(0, "timestamp path too long: %s", *timestampdir); |
396 | + |
397 | + /* |
398 | + * Timestamp file may be a file in the directory or NUL to use |
399 | + * the directory as the timestamp. |
400 | + */ |
401 | + if (def_tty_tickets) { |
402 | + char *p; |
403 | + |
404 | + if ((p = strrchr(user_tty, '/'))) |
405 | + p++; |
406 | + else |
407 | + p = user_tty; |
408 | + if (def_targetpw) |
409 | + len = easprintf(timestampfile, "%s/%s/%s:%s", dirparent, user_name, |
410 | + p, runas_pw->pw_name); |
411 | + else |
412 | + len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, p); |
413 | + if (len >= PATH_MAX) |
414 | + log_error(0, "timestamp path too long: %s", *timestampfile); |
415 | + } else if (def_targetpw) { |
416 | + len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, |
417 | + runas_pw->pw_name); |
418 | + if (len >= PATH_MAX) |
419 | + log_error(0, "timestamp path too long: %s", *timestampfile); |
420 | + } else |
421 | + *timestampfile = NULL; |
422 | +} |
423 | + |
424 | +/* |
425 | + * Check the timestamp file and directory and return their status. |
426 | + */ |
427 | +static int |
428 | +timestamp_status(timestampdir, timestampfile, user, flags) |
429 | + char *timestampdir; |
430 | + char *timestampfile; |
431 | + char *user; |
432 | + int flags; |
433 | +{ |
434 | + struct stat sb; |
435 | + struct timeval boottime, mtime; |
436 | + time_t now; |
437 | + char *dirparent = def_timestampdir; |
438 | + int status = TS_ERROR; /* assume the worst */ |
439 | + |
440 | + if (timestamp_uid != 0) |
441 | + set_perms(PERM_TIMESTAMP); |
442 | + |
443 | + /* |
444 | + * Sanity check dirparent and make it if it doesn't already exist. |
445 | + * We start out assuming the worst (that the dir is not sane) and |
446 | + * if it is ok upgrade the status to ``no timestamp file''. |
447 | + * Note that we don't check the parent(s) of dirparent for |
448 | + * sanity since the sudo dir is often just located in /tmp. |
449 | + */ |
450 | + if (lstat(dirparent, &sb) == 0) { |
451 | + if (!S_ISDIR(sb.st_mode)) |
452 | + log_error(NO_EXIT, "%s exists but is not a directory (0%o)", |
453 | + dirparent, (unsigned int) sb.st_mode); |
454 | + else if (sb.st_uid != timestamp_uid) |
455 | + log_error(NO_EXIT, "%s owned by uid %lu, should be uid %lu", |
456 | + dirparent, (unsigned long) sb.st_uid, |
457 | + (unsigned long) timestamp_uid); |
458 | + else if ((sb.st_mode & 0000022)) |
459 | + log_error(NO_EXIT, |
460 | + "%s writable by non-owner (0%o), should be mode 0700", |
461 | + dirparent, (unsigned int) sb.st_mode); |
462 | + else { |
463 | + if ((sb.st_mode & 0000777) != 0700) |
464 | + (void) chmod(dirparent, 0700); |
465 | + status = TS_MISSING; |
466 | + } |
467 | + } else if (errno != ENOENT) { |
468 | + log_error(NO_EXIT|USE_ERRNO, "can't stat %s", dirparent); |
469 | + } else { |
470 | + /* No dirparent, try to make one. */ |
471 | + if (ISSET(flags, TS_MAKE_DIRS)) { |
472 | + if (mkdir(dirparent, S_IRWXU)) |
473 | + log_error(NO_EXIT|USE_ERRNO, "can't mkdir %s", |
474 | + dirparent); |
475 | + else |
476 | + status = TS_MISSING; |
477 | + } |
478 | + } |
479 | + if (status == TS_ERROR) { |
480 | + if (timestamp_uid != 0) |
481 | + set_perms(PERM_ROOT); |
482 | + return(status); |
483 | + } |
484 | + |
485 | + /* |
486 | + * Sanity check the user's ticket dir. We start by downgrading |
487 | + * the status to TS_ERROR. If the ticket dir exists and is sane |
488 | + * this will be upgraded to TS_OLD. If the dir does not exist, |
489 | + * it will be upgraded to TS_MISSING. |
490 | + */ |
491 | + status = TS_ERROR; /* downgrade status again */ |
492 | + if (lstat(timestampdir, &sb) == 0) { |
493 | + if (!S_ISDIR(sb.st_mode)) { |
494 | + if (S_ISREG(sb.st_mode)) { |
495 | + /* convert from old style */ |
496 | + if (unlink(timestampdir) == 0) |
497 | + status = TS_MISSING; |
498 | + } else |
499 | + log_error(NO_EXIT, "%s exists but is not a directory (0%o)", |
500 | + timestampdir, (unsigned int) sb.st_mode); |
501 | + } else if (sb.st_uid != timestamp_uid) |
502 | + log_error(NO_EXIT, "%s owned by uid %lu, should be uid %lu", |
503 | + timestampdir, (unsigned long) sb.st_uid, |
504 | + (unsigned long) timestamp_uid); |
505 | + else if ((sb.st_mode & 0000022)) |
506 | + log_error(NO_EXIT, |
507 | + "%s writable by non-owner (0%o), should be mode 0700", |
508 | + timestampdir, (unsigned int) sb.st_mode); |
509 | + else { |
510 | + if ((sb.st_mode & 0000777) != 0700) |
511 | + (void) chmod(timestampdir, 0700); |
512 | + status = TS_OLD; /* do date check later */ |
513 | + } |
514 | + } else if (errno != ENOENT) { |
515 | + log_error(NO_EXIT|USE_ERRNO, "can't stat %s", timestampdir); |
516 | + } else |
517 | + status = TS_MISSING; |
518 | + |
519 | + /* |
520 | + * If there is no user ticket dir, AND we are in tty ticket mode, |
521 | + * AND the TS_MAKE_DIRS flag is set, create the user ticket dir. |
522 | + */ |
523 | + if (status == TS_MISSING && timestampfile && ISSET(flags, TS_MAKE_DIRS)) { |
524 | + if (mkdir(timestampdir, S_IRWXU) == -1) { |
525 | + status = TS_ERROR; |
526 | + log_error(NO_EXIT|USE_ERRNO, "can't mkdir %s", timestampdir); |
527 | + } |
528 | + } |
529 | + |
530 | + /* |
531 | + * Sanity check the tty ticket file if it exists. |
532 | + */ |
533 | + if (timestampfile && status != TS_ERROR) { |
534 | + if (status != TS_MISSING) |
535 | + status = TS_NOFILE; /* dir there, file missing */ |
536 | + if (def_tty_tickets && !user_ttypath) |
537 | + goto done; /* no tty, always prompt */ |
538 | + if (lstat(timestampfile, &sb) == 0) { |
539 | + if (!S_ISREG(sb.st_mode)) { |
540 | + status = TS_ERROR; |
541 | + log_error(NO_EXIT, "%s exists but is not a regular file (0%o)", |
542 | + timestampfile, (unsigned int) sb.st_mode); |
543 | + } else { |
544 | + /* If bad uid or file mode, complain and kill the bogus file. */ |
545 | + if (sb.st_uid != timestamp_uid) { |
546 | + log_error(NO_EXIT, |
547 | + "%s owned by uid %lu, should be uid %lu", |
548 | + timestampfile, (unsigned long) sb.st_uid, |
549 | + (unsigned long) timestamp_uid); |
550 | + (void) unlink(timestampfile); |
551 | + } else if ((sb.st_mode & 0000022)) { |
552 | + log_error(NO_EXIT, |
553 | + "%s writable by non-owner (0%o), should be mode 0600", |
554 | + timestampfile, (unsigned int) sb.st_mode); |
555 | + (void) unlink(timestampfile); |
556 | + } else { |
557 | + /* If not mode 0600, fix it. */ |
558 | + if ((sb.st_mode & 0000777) != 0600) |
559 | + (void) chmod(timestampfile, 0600); |
560 | + |
561 | + /* |
562 | + * Check for stored tty info. If the file is zero-sized |
563 | + * it is an old-style timestamp with no tty info in it. |
564 | + * If removing, we don't care about the contents. |
565 | + * The actual mtime check is done later. |
566 | + */ |
567 | + if (ISSET(flags, TS_REMOVE)) { |
568 | + status = TS_OLD; |
569 | + } else if (sb.st_size != 0) { |
570 | + struct tty_info info; |
571 | + int fd = open(timestampfile, O_RDONLY, 0644); |
572 | + if (fd != -1) { |
573 | + if (read(fd, &info, sizeof(info)) == sizeof(info) && |
574 | + memcmp(&info, &tty_info, sizeof(info)) == 0) { |
575 | + status = TS_OLD; |
576 | + } |
577 | + close(fd); |
578 | + } |
579 | + } |
580 | + } |
581 | + } |
582 | + } else if (errno != ENOENT) { |
583 | + log_error(NO_EXIT|USE_ERRNO, "can't stat %s", timestampfile); |
584 | + status = TS_ERROR; |
585 | + } |
586 | + } |
587 | + |
588 | + /* |
589 | + * If the file/dir exists and we are not removing it, check its mtime. |
590 | + */ |
591 | + if (status == TS_OLD && !ISSET(flags, TS_REMOVE)) { |
592 | + mtim_get(&sb, &mtime); |
593 | + /* Negative timeouts only expire manually (sudo -k). */ |
594 | + if (def_timestamp_timeout < 0 && mtime.tv_sec != 0) |
595 | + status = TS_CURRENT; |
596 | + else { |
597 | + now = time(NULL); |
598 | + if (def_timestamp_timeout && |
599 | + now - mtime.tv_sec < 60 * def_timestamp_timeout) { |
600 | + /* |
601 | + * Check for bogus time on the stampfile. The clock may |
602 | + * have been set back or someone could be trying to spoof us. |
603 | + */ |
604 | + if (mtime.tv_sec > now + 60 * def_timestamp_timeout * 2) { |
605 | + time_t tv_sec = (time_t)mtime.tv_sec; |
606 | + log_error(NO_EXIT, |
607 | + "timestamp too far in the future: %20.20s", |
608 | + 4 + ctime(&tv_sec)); |
609 | + if (timestampfile) |
610 | + (void) unlink(timestampfile); |
611 | + else |
612 | + (void) rmdir(timestampdir); |
613 | + status = TS_MISSING; |
614 | + } else if (get_boottime(&boottime) && timevalcmp(&mtime, &boottime, <)) { |
615 | + status = TS_OLD; |
616 | + } else { |
617 | + status = TS_CURRENT; |
618 | + } |
619 | + } |
620 | + } |
621 | + } |
622 | + |
623 | +done: |
624 | + if (timestamp_uid != 0) |
625 | + set_perms(PERM_ROOT); |
626 | + return(status); |
627 | +} |
628 | + |
629 | +/* |
630 | + * Remove the timestamp ticket file/dir. |
631 | + */ |
632 | +void |
633 | +remove_timestamp(remove) |
634 | + int remove; |
635 | +{ |
636 | + struct timeval tv; |
637 | + char *timestampdir, *timestampfile, *path; |
638 | + int status; |
639 | + |
640 | + build_timestamp(×tampdir, ×tampfile); |
641 | + status = timestamp_status(timestampdir, timestampfile, user_name, |
642 | + TS_REMOVE); |
643 | + if (status == TS_OLD || status == TS_CURRENT) { |
644 | + path = timestampfile ? timestampfile : timestampdir; |
645 | + if (remove) { |
646 | + if (timestampfile) |
647 | + status = unlink(timestampfile); |
648 | + else |
649 | + status = rmdir(timestampdir); |
650 | + if (status == -1 && errno != ENOENT) { |
651 | + log_error(NO_EXIT, "can't remove %s (%s), will reset to Epoch", |
652 | + path, strerror(errno)); |
653 | + remove = FALSE; |
654 | + } |
655 | + } else { |
656 | + timevalclear(&tv); |
657 | + if (touch(-1, path, &tv) == -1 && errno != ENOENT) |
658 | + error(1, "can't reset %s to Epoch", path); |
659 | + } |
660 | + } |
661 | + |
662 | + efree(timestampdir); |
663 | + efree(timestampfile); |
664 | +} |
665 | + |
666 | +/* |
667 | + * Returns TRUE if tty lives on a devpts or /devices filesystem, else FALSE. |
668 | + * Unlike most filesystems, the ctime of devpts nodes is not updated when |
669 | + * the device node is written to, only when the inode's status changes, |
670 | + * typically via the chmod, chown, link, rename, or utimes system calls. |
671 | + * Since the ctime is "stable" in this case, we can stash it the tty ticket |
672 | + * file and use it to determine whether the tty ticket file is stale. |
673 | + */ |
674 | +static int |
675 | +tty_is_devpts(tty) |
676 | + const char *tty; |
677 | +{ |
678 | + int retval = FALSE; |
679 | +#ifdef __linux__ |
680 | + struct statfs sfs; |
681 | + |
682 | +#ifndef DEVPTS_SUPER_MAGIC |
683 | +# define DEVPTS_SUPER_MAGIC 0x1cd1 |
684 | +#endif |
685 | + |
686 | + if (statfs(tty, &sfs) == 0) { |
687 | + if (sfs.f_type == DEVPTS_SUPER_MAGIC) |
688 | + retval = TRUE; |
689 | + } |
690 | +#elif defined(__sun) && defined(__SVR4) |
691 | + struct statvfs sfs; |
692 | + |
693 | + if (statvfs(tty, &sfs) == 0) { |
694 | + if (strcmp(sfs.f_fstr, "devices") == 0) |
695 | + retval = TRUE; |
696 | + } |
697 | +#endif /* __linux__ */ |
698 | + return retval; |
699 | +} |
700 | |
701 | === modified file '.pc/applied-patches' |
702 | --- .pc/applied-patches 2011-05-23 09:50:37 +0000 |
703 | +++ .pc/applied-patches 2011-05-23 08:12:57 +0000 |
704 | @@ -1,6 +1,12 @@ |
705 | typo-in-classic-insults.diff |
706 | env.c-safety.diff |
707 | paths-in-samples.diff |
708 | +<<<<<<< TREE |
709 | keep_home_by_default.patch |
710 | hurd-have-getutid.diff |
711 | debian-changes-1.7.4p6-1 |
712 | +======= |
713 | +debian-changes-1.7.4p4-5 |
714 | +CVE-2011-0010.patch |
715 | +keep_home_by_default.patch |
716 | +>>>>>>> MERGE-SOURCE |
717 | |
718 | === modified file '.pc/debian-changes-1.7.4p6-1/env.c' |
719 | --- .pc/debian-changes-1.7.4p6-1/env.c 2011-05-23 09:50:37 +0000 |
720 | +++ .pc/debian-changes-1.7.4p6-1/env.c 2011-05-23 08:12:57 +0000 |
721 | @@ -1,3 +1,4 @@ |
722 | +<<<<<<< TREE |
723 | /* |
724 | * Copyright (c) 2000-2005, 2007-2010 |
725 | * Todd C. Miller <Todd.Miller@courtesan.com> |
726 | @@ -992,3 +993,998 @@ |
727 | def_env_keep = cur; |
728 | } |
729 | } |
730 | +======= |
731 | +/* |
732 | + * Copyright (c) 2000-2005, 2007-2010 |
733 | + * Todd C. Miller <Todd.Miller@courtesan.com> |
734 | + * |
735 | + * Permission to use, copy, modify, and distribute this software for any |
736 | + * purpose with or without fee is hereby granted, provided that the above |
737 | + * copyright notice and this permission notice appear in all copies. |
738 | + * |
739 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
740 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
741 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
742 | + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
743 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
744 | + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
745 | + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
746 | + * |
747 | + * Sponsored in part by the Defense Advanced Research Projects |
748 | + * Agency (DARPA) and Air Force Research Laboratory, Air Force |
749 | + * Materiel Command, USAF, under agreement number F39502-99-1-0512. |
750 | + */ |
751 | + |
752 | +#include <config.h> |
753 | + |
754 | +#include <sys/types.h> |
755 | +#include <sys/param.h> |
756 | +#include <sys/stat.h> |
757 | +#include <stdio.h> |
758 | +#ifdef STDC_HEADERS |
759 | +# include <stdlib.h> |
760 | +# include <stddef.h> |
761 | +#else |
762 | +# ifdef HAVE_STDLIB_H |
763 | +# include <stdlib.h> |
764 | +# endif |
765 | +#endif /* STDC_HEADERS */ |
766 | +#ifdef HAVE_STRING_H |
767 | +# include <string.h> |
768 | +#endif /* HAVE_STRING_H */ |
769 | +#ifdef HAVE_STRINGS_H |
770 | +# include <strings.h> |
771 | +#endif /* HAVE_STRINGS_H */ |
772 | +#ifdef HAVE_UNISTD_H |
773 | +# include <unistd.h> |
774 | +#endif /* HAVE_UNISTD_H */ |
775 | +#include <ctype.h> |
776 | +#include <errno.h> |
777 | +#include <pwd.h> |
778 | + |
779 | +#include "sudo.h" |
780 | + |
781 | +/* |
782 | + * Flags used in rebuild_env() |
783 | + */ |
784 | +#undef DID_TERM |
785 | +#define DID_TERM 0x0001 |
786 | +#undef DID_PATH |
787 | +#define DID_PATH 0x0002 |
788 | +#undef DID_HOME |
789 | +#define DID_HOME 0x0004 |
790 | +#undef DID_SHELL |
791 | +#define DID_SHELL 0x0008 |
792 | +#undef DID_LOGNAME |
793 | +#define DID_LOGNAME 0x0010 |
794 | +#undef DID_USER |
795 | +#define DID_USER 0x0020 |
796 | +#undef DID_USERNAME |
797 | +#define DID_USERNAME 0x0040 |
798 | +#undef DID_MAIL |
799 | +#define DID_MAIL 0x0080 |
800 | +#undef DID_MAX |
801 | +#define DID_MAX 0x00ff |
802 | + |
803 | +#undef KEPT_TERM |
804 | +#define KEPT_TERM 0x0100 |
805 | +#undef KEPT_PATH |
806 | +#define KEPT_PATH 0x0200 |
807 | +#undef KEPT_HOME |
808 | +#define KEPT_HOME 0x0400 |
809 | +#undef KEPT_SHELL |
810 | +#define KEPT_SHELL 0x0800 |
811 | +#undef KEPT_LOGNAME |
812 | +#define KEPT_LOGNAME 0x1000 |
813 | +#undef KEPT_USER |
814 | +#define KEPT_USER 0x2000 |
815 | +#undef KEPT_USERNAME |
816 | +#define KEPT_USERNAME 0x4000 |
817 | +#undef KEPT_MAIL |
818 | +#define KEPT_MAIL 0x8000 |
819 | +#undef KEPT_MAX |
820 | +#define KEPT_MAX 0xff00 |
821 | + |
822 | +struct environment { |
823 | + char **envp; /* pointer to the new environment */ |
824 | + size_t env_size; /* size of new_environ in char **'s */ |
825 | + size_t env_len; /* number of slots used, not counting NULL */ |
826 | + int owned; /* do we own envp or is it the system's? */ |
827 | +}; |
828 | + |
829 | +/* |
830 | + * Prototypes |
831 | + */ |
832 | +static void sudo_setenv __P((const char *, const char *, int)); |
833 | +static void sudo_putenv __P((char *, int, int)); |
834 | + |
835 | +extern char **environ; /* global environment */ |
836 | + |
837 | +/* |
838 | + * Copy of the sudo-managed environment. |
839 | + */ |
840 | +static struct environment env; |
841 | + |
842 | +/* |
843 | + * Default table of "bad" variables to remove from the environment. |
844 | + * XXX - how to omit TERMCAP if it starts with '/'? |
845 | + */ |
846 | +static const char *initial_badenv_table[] = { |
847 | + "IFS", |
848 | + "CDPATH", |
849 | + "SHELLOPTS", |
850 | + "PS4", |
851 | + "LOCALDOMAIN", |
852 | + "RES_OPTIONS", |
853 | + "HOSTALIASES", |
854 | + "NLSPATH", |
855 | + "PATH_LOCALE", |
856 | + "LD_*", |
857 | + "_RLD*", |
858 | +#ifdef __hpux |
859 | + "SHLIB_PATH", |
860 | +#endif /* __hpux */ |
861 | +#ifdef _AIX |
862 | + "LDR_*", |
863 | + "LIBPATH", |
864 | + "AUTHSTATE", |
865 | +#endif |
866 | +#ifdef __APPLE__ |
867 | + "DYLD_*", |
868 | +#endif |
869 | +#ifdef HAVE_KERB4 |
870 | + "KRB_CONF*", |
871 | + "KRBCONFDIR", |
872 | + "KRBTKFILE", |
873 | +#endif /* HAVE_KERB4 */ |
874 | +#ifdef HAVE_KERB5 |
875 | + "KRB5_CONFIG*", |
876 | + "KRB5_KTNAME", |
877 | +#endif /* HAVE_KERB5 */ |
878 | +#ifdef HAVE_SECURID |
879 | + "VAR_ACE", |
880 | + "USR_ACE", |
881 | + "DLC_ACE", |
882 | +#endif /* HAVE_SECURID */ |
883 | + "TERMINFO", /* terminfo, exclusive path to terminfo files */ |
884 | + "TERMINFO_DIRS", /* terminfo, path(s) to terminfo files */ |
885 | + "TERMPATH", /* termcap, path(s) to termcap files */ |
886 | + "TERMCAP", /* XXX - only if it starts with '/' */ |
887 | + "ENV", /* ksh, file to source before script runs */ |
888 | + "BASH_ENV", /* bash, file to source before script runs */ |
889 | + "PS4", /* bash, prefix for lines in xtrace mode */ |
890 | + "GLOBIGNORE", /* bash, globbing patterns to ignore */ |
891 | + "SHELLOPTS", /* bash, extra command line options */ |
892 | + "JAVA_TOOL_OPTIONS", /* java, extra command line options */ |
893 | + "PERLIO_DEBUG ", /* perl, debugging output file */ |
894 | + "PERLLIB", /* perl, search path for modules/includes */ |
895 | + "PERL5LIB", /* perl 5, search path for modules/includes */ |
896 | + "PERL5OPT", /* perl 5, extra command line options */ |
897 | + "PERL5DB", /* perl 5, command used to load debugger */ |
898 | + "FPATH", /* ksh, search path for functions */ |
899 | + "NULLCMD", /* zsh, command for null file redirection */ |
900 | + "READNULLCMD", /* zsh, command for null file redirection */ |
901 | + "ZDOTDIR", /* zsh, search path for dot files */ |
902 | + "TMPPREFIX", /* zsh, prefix for temporary files */ |
903 | + "PYTHONHOME", /* python, module search path */ |
904 | + "PYTHONPATH", /* python, search path */ |
905 | + "PYTHONINSPECT", /* python, allow inspection */ |
906 | + "PYTHONUSERBASE", /* python, per user site-packages directory */ |
907 | + "RUBYLIB", /* ruby, library load path */ |
908 | + "RUBYOPT", /* ruby, extra command line options */ |
909 | + NULL |
910 | +}; |
911 | + |
912 | +/* |
913 | + * Default table of variables to check for '%' and '/' characters. |
914 | + */ |
915 | +static const char *initial_checkenv_table[] = { |
916 | + "COLORTERM", |
917 | + "LANG", |
918 | + "LANGUAGE", |
919 | + "LC_*", |
920 | + "LINGUAS", |
921 | + "TERM", |
922 | + NULL |
923 | +}; |
924 | + |
925 | +/* |
926 | + * Default table of variables to preserve in the environment. |
927 | + */ |
928 | +static const char *initial_keepenv_table[] = { |
929 | + "COLORS", |
930 | + "DISPLAY", |
931 | + "HOSTNAME", |
932 | + "KRB5CCNAME", |
933 | + "LS_COLORS", |
934 | + "PATH", |
935 | + "PS1", |
936 | + "PS2", |
937 | + "TZ", |
938 | + "XAUTHORITY", |
939 | + "XAUTHORIZATION", |
940 | + NULL |
941 | +}; |
942 | + |
943 | +/* |
944 | + * Initialize env based on envp. |
945 | + */ |
946 | +void |
947 | +env_init(lazy) |
948 | + int lazy; |
949 | +{ |
950 | + char * const *ep; |
951 | + size_t len; |
952 | + |
953 | + for (ep = environ; *ep != NULL; ep++) |
954 | + continue; |
955 | + len = (size_t)(ep - environ); |
956 | + |
957 | + if (lazy) { |
958 | + /* |
959 | + * If we are already initialized due to lazy init (usualy via getenv()) |
960 | + * we need to avoid calling malloc() as it may call getenv() itself. |
961 | + */ |
962 | + env.envp = environ; |
963 | + env.env_len = len; |
964 | + env.env_size = len; |
965 | + } else if (!env.owned) { |
966 | + env.env_len = len; |
967 | + env.env_size = len + 1 + 128; |
968 | + env.envp = emalloc2(env.env_size, sizeof(char *)); |
969 | +#ifdef ENV_DEBUG |
970 | + memset(env.envp, 0, env.env_size * sizeof(char *)); |
971 | +#endif |
972 | + memcpy(env.envp, environ, len * sizeof(char *)); |
973 | + env.envp[len] = '\0'; |
974 | + env.owned = TRUE; |
975 | + } |
976 | +} |
977 | + |
978 | +char ** |
979 | +env_get() |
980 | +{ |
981 | + return env.envp; |
982 | +} |
983 | + |
984 | +/* |
985 | + * Similar to setenv(3) but operates on sudo's private copy of the environment |
986 | + * (not environ) and it always overwrites. The dupcheck param determines |
987 | + * whether we need to verify that the variable is not already set. |
988 | + */ |
989 | +static void |
990 | +sudo_setenv(var, val, dupcheck) |
991 | + const char *var; |
992 | + const char *val; |
993 | + int dupcheck; |
994 | +{ |
995 | + char *estring; |
996 | + size_t esize; |
997 | + |
998 | + esize = strlen(var) + 1 + strlen(val) + 1; |
999 | + estring = emalloc(esize); |
1000 | + |
1001 | + /* Build environment string and insert it. */ |
1002 | + if (strlcpy(estring, var, esize) >= esize || |
1003 | + strlcat(estring, "=", esize) >= esize || |
1004 | + strlcat(estring, val, esize) >= esize) { |
1005 | + |
1006 | + errorx(1, "internal error, sudo_setenv() overflow"); |
1007 | + } |
1008 | + sudo_putenv(estring, dupcheck, TRUE); |
1009 | +} |
1010 | + |
1011 | +/* |
1012 | + * Version of getenv(3) that uses our own environ pointer. |
1013 | + */ |
1014 | +char * |
1015 | +getenv(var) |
1016 | + const char *var; |
1017 | +{ |
1018 | + char *cp, **ev; |
1019 | + size_t vlen = strlen(var); |
1020 | + |
1021 | + if (env.envp == NULL) |
1022 | + env_init(TRUE); |
1023 | + |
1024 | + for (ev = env.envp; (cp = *ev) != NULL; ev++) { |
1025 | + if (strncmp(var, cp, vlen) == 0 && cp[vlen] == '=') |
1026 | + return cp + vlen + 1; |
1027 | + } |
1028 | + return NULL; |
1029 | +} |
1030 | + |
1031 | +/* |
1032 | + * Version of setenv(3) that uses our own environ pointer. |
1033 | + */ |
1034 | +int |
1035 | +setenv(var, val, overwrite) |
1036 | + const char *var; |
1037 | + const char *val; |
1038 | + int overwrite; |
1039 | +{ |
1040 | + char *estring, *ep; |
1041 | + const char *cp; |
1042 | + size_t esize; |
1043 | + |
1044 | + if (!var || *var == '\0') { |
1045 | + errno = EINVAL; |
1046 | + return(-1); |
1047 | + } |
1048 | + |
1049 | + if (env.envp == NULL) |
1050 | + env_init(TRUE); |
1051 | + |
1052 | + /* |
1053 | + * POSIX says a var name with '=' is an error but BSD |
1054 | + * just ignores the '=' and anything after it. |
1055 | + */ |
1056 | + for (cp = var; *cp && *cp != '='; cp++) |
1057 | + ; |
1058 | + esize = (size_t)(cp - var) + 2; |
1059 | + if (val) { |
1060 | + esize += strlen(val); /* glibc treats a NULL val as "" */ |
1061 | + } |
1062 | + |
1063 | + /* Allocate and fill in estring. */ |
1064 | + estring = ep = emalloc(esize); |
1065 | + for (cp = var; *cp && *cp != '='; cp++) |
1066 | + *ep++ = *cp; |
1067 | + *ep++ = '='; |
1068 | + if (val) { |
1069 | + for (cp = val; *cp; cp++) |
1070 | + *ep++ = *cp; |
1071 | + } |
1072 | + *ep = '\0'; |
1073 | + |
1074 | +#ifdef ENV_DEBUG |
1075 | + if (env.envp[env.env_len] != NULL) |
1076 | + errorx(1, "setenv: corrupted envp, len mismatch"); |
1077 | +#endif |
1078 | + sudo_putenv(estring, TRUE, overwrite); |
1079 | + return(0); |
1080 | +} |
1081 | + |
1082 | +/* |
1083 | + * Version of unsetenv(3) that uses our own environ pointer. |
1084 | + */ |
1085 | +#ifdef UNSETENV_VOID |
1086 | +void |
1087 | +#else |
1088 | +int |
1089 | +#endif |
1090 | +unsetenv(var) |
1091 | + const char *var; |
1092 | +{ |
1093 | + char **ep; |
1094 | + size_t len; |
1095 | + |
1096 | + if (var == NULL || *var == '\0' || strchr(var, '=') != NULL) { |
1097 | + errno = EINVAL; |
1098 | +#ifdef UNSETENV_VOID |
1099 | + return; |
1100 | +#else |
1101 | + return(-1); |
1102 | +#endif |
1103 | + } |
1104 | + |
1105 | + if (env.envp == NULL) |
1106 | + env_init(TRUE); |
1107 | + |
1108 | +#ifdef ENV_DEBUG |
1109 | + if (env.envp[env.env_len] != NULL) |
1110 | + errorx(1, "unsetenv: corrupted envp, len mismatch"); |
1111 | +#endif |
1112 | + |
1113 | + len = strlen(var); |
1114 | + for (ep = env.envp; *ep != NULL;) { |
1115 | + if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') { |
1116 | + /* Found it; shift remainder + NULL over by one. */ |
1117 | + char **cur = ep; |
1118 | + while ((*cur = *(cur + 1)) != NULL) |
1119 | + cur++; |
1120 | + /* Keep going, could be multiple instances of the var. */ |
1121 | + } else { |
1122 | + ep++; |
1123 | + } |
1124 | + } |
1125 | + env.env_len = ep - env.envp; |
1126 | +#ifndef UNSETENV_VOID |
1127 | + return(0); |
1128 | +#endif |
1129 | +} |
1130 | + |
1131 | +/* |
1132 | + * Version of putenv(3) that uses our own environ pointer. |
1133 | + */ |
1134 | +int |
1135 | +#ifdef PUTENV_CONST |
1136 | +putenv(const char *string) |
1137 | +#else |
1138 | +putenv(string) |
1139 | + char *string; |
1140 | +#endif |
1141 | +{ |
1142 | + if (env.envp == NULL) |
1143 | + env_init(TRUE); |
1144 | + |
1145 | + if (strchr(string, '=') == NULL) { |
1146 | + errno = EINVAL; |
1147 | + return(-1); |
1148 | + } |
1149 | +#ifdef ENV_DEBUG |
1150 | + if (env.envp[env.env_len] != NULL) |
1151 | + errorx(1, "putenv: corrupted envp, len mismatch"); |
1152 | +#endif |
1153 | + sudo_putenv((char *)string, TRUE, TRUE); |
1154 | + return(0); |
1155 | +} |
1156 | + |
1157 | +/* |
1158 | + * Similar to putenv(3) but operates on sudo's private copy of the |
1159 | + * environment (not environ) and it always overwrites. The dupcheck param |
1160 | + * determines whether we need to verify that the variable is not already set. |
1161 | + * Will only overwrite an existing variable if overwrite is set. |
1162 | + */ |
1163 | +static void |
1164 | +sudo_putenv(str, dupcheck, overwrite) |
1165 | + char *str; |
1166 | + int dupcheck; |
1167 | + int overwrite; |
1168 | +{ |
1169 | + char **ep; |
1170 | + size_t len; |
1171 | + int found = FALSE; |
1172 | + |
1173 | + /* Make sure there is room for the new entry plus a NULL. */ |
1174 | + if (env.env_len + 2 > env.env_size) { |
1175 | + env.env_size += 128; |
1176 | + if (env.owned) { |
1177 | + env.envp = erealloc3(env.envp, env.env_size, sizeof(char *)); |
1178 | + } else { |
1179 | + /* We don't own env.envp, allocate a new one. */ |
1180 | + ep = emalloc2(env.env_size, sizeof(char *)); |
1181 | + memcpy(ep, env.envp, env.env_size * sizeof(char *)); |
1182 | + env.envp = ep; |
1183 | + env.owned = TRUE; |
1184 | + } |
1185 | +#ifdef ENV_DEBUG |
1186 | + memset(env.envp + env.env_len, 0, |
1187 | + (env.env_size - env.env_len) * sizeof(char *)); |
1188 | +#endif |
1189 | + } |
1190 | + |
1191 | +#ifdef ENV_DEBUG |
1192 | + if (env.envp[env.env_len] != NULL) |
1193 | + errorx(1, "sudo_putenv: corrupted envp, len mismatch"); |
1194 | +#endif |
1195 | + |
1196 | + if (dupcheck) { |
1197 | + len = (strchr(str, '=') - str) + 1; |
1198 | + for (ep = env.envp; !found && *ep != NULL; ep++) { |
1199 | + if (strncmp(str, *ep, len) == 0) { |
1200 | + if (overwrite) |
1201 | + *ep = str; |
1202 | + found = TRUE; |
1203 | + } |
1204 | + } |
1205 | + /* Prune out duplicate variables. */ |
1206 | + if (found && overwrite) { |
1207 | + while (*ep != NULL) { |
1208 | + if (strncmp(str, *ep, len) == 0) { |
1209 | + char **cur = ep; |
1210 | + while ((*cur = *(cur + 1)) != NULL) |
1211 | + cur++; |
1212 | + } else { |
1213 | + ep++; |
1214 | + } |
1215 | + } |
1216 | + env.env_len = ep - env.envp; |
1217 | + } |
1218 | + } |
1219 | + |
1220 | + if (!found) { |
1221 | + ep = env.envp + env.env_len; |
1222 | + env.env_len++; |
1223 | + *ep++ = str; |
1224 | + *ep = NULL; |
1225 | + } |
1226 | +} |
1227 | + |
1228 | +/* |
1229 | + * Check the env_delete blacklist. |
1230 | + * Returns TRUE if the variable was found, else false. |
1231 | + */ |
1232 | +static int |
1233 | +matches_env_delete(var) |
1234 | + const char *var; |
1235 | +{ |
1236 | + struct list_member *cur; |
1237 | + size_t len; |
1238 | + int iswild, match = FALSE; |
1239 | + |
1240 | + /* Skip anything listed in env_delete. */ |
1241 | + for (cur = def_env_delete; cur; cur = cur->next) { |
1242 | + len = strlen(cur->value); |
1243 | + /* Deal with '*' wildcard */ |
1244 | + if (cur->value[len - 1] == '*') { |
1245 | + len--; |
1246 | + iswild = TRUE; |
1247 | + } else |
1248 | + iswild = FALSE; |
1249 | + if (strncmp(cur->value, var, len) == 0 && |
1250 | + (iswild || var[len] == '=')) { |
1251 | + match = TRUE; |
1252 | + break; |
1253 | + } |
1254 | + } |
1255 | + return(match); |
1256 | +} |
1257 | + |
1258 | +/* |
1259 | + * Apply the env_check list. |
1260 | + * Returns TRUE if the variable is allowed, FALSE if denied |
1261 | + * or -1 if no match. |
1262 | + */ |
1263 | +static int |
1264 | +matches_env_check(var) |
1265 | + const char *var; |
1266 | +{ |
1267 | + struct list_member *cur; |
1268 | + size_t len; |
1269 | + int iswild, keepit = -1; |
1270 | + |
1271 | + for (cur = def_env_check; cur; cur = cur->next) { |
1272 | + len = strlen(cur->value); |
1273 | + /* Deal with '*' wildcard */ |
1274 | + if (cur->value[len - 1] == '*') { |
1275 | + len--; |
1276 | + iswild = TRUE; |
1277 | + } else |
1278 | + iswild = FALSE; |
1279 | + if (strncmp(cur->value, var, len) == 0 && |
1280 | + (iswild || var[len] == '=')) { |
1281 | + keepit = !strpbrk(var, "/%"); |
1282 | + break; |
1283 | + } |
1284 | + } |
1285 | + return(keepit); |
1286 | +} |
1287 | + |
1288 | +/* |
1289 | + * Check the env_keep list. |
1290 | + * Returns TRUE if the variable is allowed else FALSE. |
1291 | + */ |
1292 | +static int |
1293 | +matches_env_keep(var) |
1294 | + const char *var; |
1295 | +{ |
1296 | + struct list_member *cur; |
1297 | + size_t len; |
1298 | + int iswild, keepit = FALSE; |
1299 | + |
1300 | + for (cur = def_env_keep; cur; cur = cur->next) { |
1301 | + len = strlen(cur->value); |
1302 | + /* Deal with '*' wildcard */ |
1303 | + if (cur->value[len - 1] == '*') { |
1304 | + len--; |
1305 | + iswild = TRUE; |
1306 | + } else |
1307 | + iswild = FALSE; |
1308 | + if (strncmp(cur->value, var, len) == 0 && |
1309 | + (iswild || var[len] == '=')) { |
1310 | + keepit = TRUE; |
1311 | + break; |
1312 | + } |
1313 | + } |
1314 | + return(keepit); |
1315 | +} |
1316 | + |
1317 | +/* |
1318 | + * Build a new environment and ether clear potentially dangerous |
1319 | + * variables from the old one or start with a clean slate. |
1320 | + * Also adds sudo-specific variables (SUDO_*). |
1321 | + */ |
1322 | +void |
1323 | +rebuild_env(noexec) |
1324 | + int noexec; |
1325 | +{ |
1326 | + char **old_envp, **ep, *cp, *ps1; |
1327 | + char idbuf[MAX_UID_T_LEN]; |
1328 | + unsigned int didvar; |
1329 | + int reset_home = FALSE; |
1330 | + |
1331 | + /* |
1332 | + * Either clean out the environment or reset to a safe default. |
1333 | + */ |
1334 | + ps1 = NULL; |
1335 | + didvar = 0; |
1336 | + env.env_len = 0; |
1337 | + env.env_size = 128; |
1338 | + old_envp = env.envp; |
1339 | + env.envp = emalloc2(env.env_size, sizeof(char *)); |
1340 | +#ifdef ENV_DEBUG |
1341 | + memset(env.envp, 0, env.env_size * sizeof(char *)); |
1342 | +#endif |
1343 | + if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) { |
1344 | + /* Reset HOME based on target user unless keeping old value. */ |
1345 | + reset_home = TRUE; |
1346 | + |
1347 | + /* Pull in vars we want to keep from the old environment. */ |
1348 | + for (ep = old_envp; *ep; ep++) { |
1349 | + int keepit; |
1350 | + |
1351 | + /* Skip variables with values beginning with () (bash functions) */ |
1352 | + if ((cp = strchr(*ep, '=')) != NULL) { |
1353 | + if (strncmp(cp, "=() ", 3) == 0) |
1354 | + continue; |
1355 | + } |
1356 | + |
1357 | + /* |
1358 | + * First check certain variables for '%' and '/' characters. |
1359 | + * If no match there, check the keep list. |
1360 | + * If nothing matched, we remove it from the environment. |
1361 | + */ |
1362 | + keepit = matches_env_check(*ep); |
1363 | + if (keepit == -1) |
1364 | + keepit = matches_env_keep(*ep); |
1365 | + |
1366 | + if (!strncmp (*ep, "DISPLAY=",8) |
1367 | + || !strncmp (*ep, "XAUTHORITY=", 11) |
1368 | + || !strncmp (*ep, "XAUTHORIZATION=", 15) |
1369 | + || !strncmp (*ep, "XAPPLRESDIR=", 12) |
1370 | + || !strncmp (*ep, "XFILESEARCHPATH=", 16) |
1371 | + || !strncmp (*ep, "XUSERFILESEARCHPATH=", 20) |
1372 | + || !strncmp (*ep, "LANG=", 5) |
1373 | + || !strncmp (*ep, "LANGUAGE=", 9) |
1374 | + || !strncmp (*ep, "LC_", 3)) |
1375 | + keepit = 1; |
1376 | + |
1377 | + /* For SUDO_PS1 -> PS1 conversion. */ |
1378 | + if (strncmp(*ep, "SUDO_PS1=", 8) == 0) |
1379 | + ps1 = *ep + 5; |
1380 | + |
1381 | + if (keepit) { |
1382 | + /* Preserve variable. */ |
1383 | + switch (**ep) { |
1384 | + case 'H': |
1385 | + if (strncmp(*ep, "HOME=", 5) == 0) |
1386 | + SET(didvar, DID_HOME); |
1387 | + break; |
1388 | + case 'L': |
1389 | + if (strncmp(*ep, "LOGNAME=", 8) == 0) |
1390 | + SET(didvar, DID_LOGNAME); |
1391 | + break; |
1392 | + case 'M': |
1393 | + if (strncmp(*ep, "MAIL=", 5) == 0) |
1394 | + SET(didvar, DID_MAIL); |
1395 | + break; |
1396 | + case 'P': |
1397 | + if (strncmp(*ep, "PATH=", 5) == 0) |
1398 | + SET(didvar, DID_PATH); |
1399 | + break; |
1400 | + case 'S': |
1401 | + if (strncmp(*ep, "SHELL=", 6) == 0) |
1402 | + SET(didvar, DID_SHELL); |
1403 | + break; |
1404 | + case 'T': |
1405 | + if (strncmp(*ep, "TERM=", 5) == 0) |
1406 | + SET(didvar, DID_TERM); |
1407 | + break; |
1408 | + case 'U': |
1409 | + if (strncmp(*ep, "USER=", 5) == 0) |
1410 | + SET(didvar, DID_USER); |
1411 | + if (strncmp(*ep, "USERNAME=", 5) == 0) |
1412 | + SET(didvar, DID_USERNAME); |
1413 | + break; |
1414 | + } |
1415 | + sudo_putenv(*ep, FALSE, FALSE); |
1416 | + } |
1417 | + } |
1418 | + didvar |= didvar << 8; /* convert DID_* to KEPT_* */ |
1419 | + |
1420 | + /* |
1421 | + * Add in defaults. In -i mode these come from the runas user, |
1422 | + * otherwise they may be from the user's environment (depends |
1423 | + * on sudoers options). |
1424 | + */ |
1425 | + if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { |
1426 | + sudo_setenv("SHELL", runas_pw->pw_shell, ISSET(didvar, DID_SHELL)); |
1427 | + sudo_setenv("LOGNAME", runas_pw->pw_name, |
1428 | + ISSET(didvar, DID_LOGNAME)); |
1429 | + sudo_setenv("USER", runas_pw->pw_name, ISSET(didvar, DID_USER)); |
1430 | + sudo_setenv("USERNAME", runas_pw->pw_name, |
1431 | + ISSET(didvar, DID_USERNAME)); |
1432 | + } else { |
1433 | + if (!ISSET(didvar, DID_SHELL)) |
1434 | + sudo_setenv("SHELL", sudo_user.pw->pw_shell, FALSE); |
1435 | + if (!ISSET(didvar, DID_LOGNAME)) |
1436 | + sudo_setenv("LOGNAME", user_name, FALSE); |
1437 | + if (!ISSET(didvar, DID_USER)) |
1438 | + sudo_setenv("USER", user_name, FALSE); |
1439 | + if (!ISSET(didvar, DID_USERNAME)) |
1440 | + sudo_setenv("USERNAME", user_name, FALSE); |
1441 | + } |
1442 | + /* |
1443 | + * Set MAIL to target user in -i mode or if MAIL is not preserved |
1444 | + * from user's environment. |
1445 | + */ |
1446 | + if (ISSET(sudo_mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) { |
1447 | + cp = _PATH_MAILDIR; |
1448 | + if (cp[sizeof(_PATH_MAILDIR) - 2] == '/') |
1449 | + easprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name); |
1450 | + else |
1451 | + easprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name); |
1452 | + sudo_putenv(cp, ISSET(didvar, DID_MAIL), TRUE); |
1453 | + } |
1454 | + } else { |
1455 | + /* Reset HOME based on target user if configured to. */ |
1456 | + if (ISSET(sudo_mode, MODE_RUN)) { |
1457 | + if (def_always_set_home || ISSET(sudo_mode, MODE_RESET_HOME) || |
1458 | + (ISSET(sudo_mode, MODE_SHELL) && def_set_home)) |
1459 | + reset_home = TRUE; |
1460 | + } |
1461 | + |
1462 | + /* |
1463 | + * Copy environ entries as long as they don't match env_delete or |
1464 | + * env_check. |
1465 | + */ |
1466 | + for (ep = old_envp; *ep; ep++) { |
1467 | + int okvar; |
1468 | + |
1469 | + /* Skip variables with values beginning with () (bash functions) */ |
1470 | + if ((cp = strchr(*ep, '=')) != NULL) { |
1471 | + if (strncmp(cp, "=() ", 3) == 0) |
1472 | + continue; |
1473 | + } |
1474 | + |
1475 | + /* |
1476 | + * First check variables against the blacklist in env_delete. |
1477 | + * If no match there check for '%' and '/' characters. |
1478 | + */ |
1479 | + okvar = matches_env_delete(*ep) != TRUE; |
1480 | + if (okvar) |
1481 | + okvar = matches_env_check(*ep) != FALSE; |
1482 | + |
1483 | + if (okvar) { |
1484 | + if (strncmp(*ep, "SUDO_PS1=", 9) == 0) |
1485 | + ps1 = *ep + 5; |
1486 | + else if (strncmp(*ep, "PATH=", 5) == 0) |
1487 | + SET(didvar, DID_PATH); |
1488 | + else if (strncmp(*ep, "TERM=", 5) == 0) |
1489 | + SET(didvar, DID_TERM); |
1490 | + sudo_putenv(*ep, FALSE, FALSE); |
1491 | + } |
1492 | + } |
1493 | + } |
1494 | + /* Replace the PATH envariable with a secure one? */ |
1495 | + if (def_secure_path && !user_is_exempt()) { |
1496 | + sudo_setenv("PATH", def_secure_path, TRUE); |
1497 | + SET(didvar, DID_PATH); |
1498 | + } |
1499 | + |
1500 | + /* Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is true. */ |
1501 | + if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL)) { |
1502 | + if (!ISSET(didvar, KEPT_LOGNAME)) |
1503 | + sudo_setenv("LOGNAME", runas_pw->pw_name, TRUE); |
1504 | + if (!ISSET(didvar, KEPT_USER)) |
1505 | + sudo_setenv("USER", runas_pw->pw_name, TRUE); |
1506 | + if (!ISSET(didvar, KEPT_USERNAME)) |
1507 | + sudo_setenv("USERNAME", runas_pw->pw_name, TRUE); |
1508 | + } |
1509 | + |
1510 | + /* Set $HOME to target user if not preserving user's value. */ |
1511 | + if (reset_home && !ISSET(didvar, KEPT_HOME)) |
1512 | + sudo_setenv("HOME", runas_pw->pw_dir, TRUE); |
1513 | + |
1514 | + /* Provide default values for $TERM and $PATH if they are not set. */ |
1515 | + if (!ISSET(didvar, DID_TERM)) |
1516 | + sudo_putenv("TERM=unknown", FALSE, FALSE); |
1517 | + if (!ISSET(didvar, DID_PATH)) |
1518 | + sudo_setenv("PATH", _PATH_STDPATH, FALSE); |
1519 | + |
1520 | + /* |
1521 | + * Preload a noexec file? For a list of LD_PRELOAD-alikes, see |
1522 | + * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html |
1523 | + * XXX - should prepend to original value, if any |
1524 | + */ |
1525 | + if (noexec && def_noexec_file != NULL) { |
1526 | +#if defined(__darwin__) || defined(__APPLE__) |
1527 | + sudo_setenv("DYLD_INSERT_LIBRARIES", def_noexec_file, TRUE); |
1528 | + sudo_setenv("DYLD_FORCE_FLAT_NAMESPACE", "", TRUE); |
1529 | +#else |
1530 | +# if defined(__osf__) || defined(__sgi) |
1531 | + easprintf(&cp, "%s:DEFAULT", def_noexec_file); |
1532 | + sudo_setenv("_RLD_LIST", cp, TRUE); |
1533 | + efree(cp); |
1534 | +# else |
1535 | +# ifdef _AIX |
1536 | + sudo_setenv("LDR_PRELOAD", def_noexec_file, TRUE); |
1537 | +# else |
1538 | + sudo_setenv("LD_PRELOAD", def_noexec_file, TRUE); |
1539 | +# endif /* _AIX */ |
1540 | +# endif /* __osf__ || __sgi */ |
1541 | +#endif /* __darwin__ || __APPLE__ */ |
1542 | + } |
1543 | + |
1544 | + /* Set PS1 if SUDO_PS1 is set. */ |
1545 | + if (ps1 != NULL) |
1546 | + sudo_putenv(ps1, TRUE, TRUE); |
1547 | + |
1548 | + /* Add the SUDO_COMMAND envariable (cmnd + args). */ |
1549 | + if (user_args) { |
1550 | + easprintf(&cp, "%s %s", user_cmnd, user_args); |
1551 | + sudo_setenv("SUDO_COMMAND", cp, TRUE); |
1552 | + efree(cp); |
1553 | + } else { |
1554 | + sudo_setenv("SUDO_COMMAND", user_cmnd, TRUE); |
1555 | + } |
1556 | + |
1557 | + /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */ |
1558 | + sudo_setenv("SUDO_USER", user_name, TRUE); |
1559 | + snprintf(idbuf, sizeof(idbuf), "%lu", (unsigned long) user_uid); |
1560 | + sudo_setenv("SUDO_UID", idbuf, TRUE); |
1561 | + snprintf(idbuf, sizeof(idbuf), "%lu", (unsigned long) user_gid); |
1562 | + sudo_setenv("SUDO_GID", idbuf, TRUE); |
1563 | + |
1564 | + /* Free old environment. */ |
1565 | + efree(old_envp); |
1566 | +} |
1567 | + |
1568 | +void |
1569 | +insert_env_vars(env_vars) |
1570 | + struct list_member *env_vars; |
1571 | +{ |
1572 | + struct list_member *cur; |
1573 | + |
1574 | + /* Add user-specified environment variables. */ |
1575 | + for (cur = env_vars; cur != NULL; cur = cur->next) |
1576 | + putenv(cur->value); |
1577 | +} |
1578 | + |
1579 | +/* |
1580 | + * Validate the list of environment variables passed in on the command |
1581 | + * line against env_delete, env_check, and env_keep. |
1582 | + * Calls log_error() if any specified variables are not allowed. |
1583 | + */ |
1584 | +void |
1585 | +validate_env_vars(env_vars) |
1586 | + struct list_member *env_vars; |
1587 | +{ |
1588 | + struct list_member *var; |
1589 | + char *eq, *bad = NULL; |
1590 | + size_t len, blen = 0, bsize = 0; |
1591 | + int okvar; |
1592 | + |
1593 | + /* Add user-specified environment variables. */ |
1594 | + for (var = env_vars; var != NULL; var = var->next) { |
1595 | + if (def_secure_path && !user_is_exempt() && |
1596 | + strncmp(var->value, "PATH=", 5) == 0) { |
1597 | + okvar = FALSE; |
1598 | + } else if (def_env_reset) { |
1599 | + okvar = matches_env_check(var->value); |
1600 | + if (okvar == -1) |
1601 | + okvar = matches_env_keep(var->value); |
1602 | + } else { |
1603 | + okvar = matches_env_delete(var->value) == FALSE; |
1604 | + if (okvar == FALSE) |
1605 | + okvar = matches_env_check(var->value) != FALSE; |
1606 | + } |
1607 | + if (okvar == FALSE) { |
1608 | + /* Not allowed, add to error string, allocating as needed. */ |
1609 | + if ((eq = strchr(var->value, '=')) != NULL) |
1610 | + *eq = '\0'; |
1611 | + len = strlen(var->value) + 2; |
1612 | + if (blen + len >= bsize) { |
1613 | + do { |
1614 | + bsize += 1024; |
1615 | + } while (blen + len >= bsize); |
1616 | + bad = erealloc(bad, bsize); |
1617 | + bad[blen] = '\0'; |
1618 | + } |
1619 | + strlcat(bad, var->value, bsize); |
1620 | + strlcat(bad, ", ", bsize); |
1621 | + blen += len; |
1622 | + if (eq != NULL) |
1623 | + *eq = '='; |
1624 | + } |
1625 | + } |
1626 | + if (bad != NULL) { |
1627 | + bad[blen - 2] = '\0'; /* remove trailing ", " */ |
1628 | + log_error(NO_MAIL, |
1629 | + "sorry, you are not allowed to set the following environment variables: %s", bad); |
1630 | + /* NOTREACHED */ |
1631 | + efree(bad); |
1632 | + } |
1633 | +} |
1634 | + |
1635 | +/* |
1636 | + * Read in /etc/environment ala AIX and Linux. |
1637 | + * Lines may be in either of three formats: |
1638 | + * NAME=VALUE |
1639 | + * NAME="VALUE" |
1640 | + * NAME='VALUE' |
1641 | + * with an optional "export" prefix so the shell can source the file. |
1642 | + * Invalid lines, blank lines, or lines consisting solely of a comment |
1643 | + * character are skipped. |
1644 | + */ |
1645 | +void |
1646 | +read_env_file(path, overwrite) |
1647 | + const char *path; |
1648 | + int overwrite; |
1649 | +{ |
1650 | + FILE *fp; |
1651 | + char *cp, *var, *val; |
1652 | + size_t var_len, val_len; |
1653 | + |
1654 | + if ((fp = fopen(path, "r")) == NULL) |
1655 | + return; |
1656 | + |
1657 | + while ((var = sudo_parseln(fp)) != NULL) { |
1658 | + /* Skip blank or comment lines */ |
1659 | + if (*var == '\0') |
1660 | + continue; |
1661 | + |
1662 | + /* Skip optional "export " */ |
1663 | + if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) { |
1664 | + var += 7; |
1665 | + while (isspace((unsigned char) *var)) { |
1666 | + var++; |
1667 | + } |
1668 | + } |
1669 | + |
1670 | + /* Must be of the form name=["']value['"] */ |
1671 | + for (val = var; *val != '\0' && *val != '='; val++) |
1672 | + ; |
1673 | + if (var == val || *val != '=') |
1674 | + continue; |
1675 | + var_len = (size_t)(val - var); |
1676 | + val_len = strlen(++val); |
1677 | + |
1678 | + /* Strip leading and trailing single/double quotes */ |
1679 | + if ((val[0] == '\'' || val[0] == '\"') && val[0] == val[val_len - 1]) { |
1680 | + val[val_len - 1] = '\0'; |
1681 | + val++; |
1682 | + val_len -= 2; |
1683 | + } |
1684 | + |
1685 | + cp = emalloc(var_len + 1 + val_len + 1); |
1686 | + memcpy(cp, var, var_len + 1); /* includes '=' */ |
1687 | + memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */ |
1688 | + |
1689 | + sudo_putenv(cp, TRUE, overwrite); |
1690 | + } |
1691 | + fclose(fp); |
1692 | +} |
1693 | + |
1694 | +void |
1695 | +init_envtables() |
1696 | +{ |
1697 | + struct list_member *cur; |
1698 | + const char **p; |
1699 | + |
1700 | + /* Fill in the "env_delete" list. */ |
1701 | + for (p = initial_badenv_table; *p; p++) { |
1702 | + cur = emalloc(sizeof(struct list_member)); |
1703 | + cur->value = estrdup(*p); |
1704 | + cur->next = def_env_delete; |
1705 | + def_env_delete = cur; |
1706 | + } |
1707 | + |
1708 | + /* Fill in the "env_check" list. */ |
1709 | + for (p = initial_checkenv_table; *p; p++) { |
1710 | + cur = emalloc(sizeof(struct list_member)); |
1711 | + cur->value = estrdup(*p); |
1712 | + cur->next = def_env_check; |
1713 | + def_env_check = cur; |
1714 | + } |
1715 | + |
1716 | + /* Fill in the "env_keep" list. */ |
1717 | + for (p = initial_keepenv_table; *p; p++) { |
1718 | + cur = emalloc(sizeof(struct list_member)); |
1719 | + cur->value = estrdup(*p); |
1720 | + cur->next = def_env_keep; |
1721 | + def_env_keep = cur; |
1722 | + } |
1723 | +} |
1724 | +>>>>>>> MERGE-SOURCE |
1725 | |
1726 | === modified file '.pc/keep_home_by_default.patch/env.c' |
1727 | --- .pc/keep_home_by_default.patch/env.c 2011-05-23 09:50:37 +0000 |
1728 | +++ .pc/keep_home_by_default.patch/env.c 2011-05-23 08:12:57 +0000 |
1729 | @@ -1,3 +1,4 @@ |
1730 | +<<<<<<< TREE |
1731 | /* |
1732 | * Copyright (c) 2000-2005, 2007-2010 |
1733 | * Todd C. Miller <Todd.Miller@courtesan.com> |
1734 | @@ -991,3 +992,1002 @@ |
1735 | def_env_keep = cur; |
1736 | } |
1737 | } |
1738 | +======= |
1739 | +/* |
1740 | + * Copyright (c) 2000-2005, 2007-2010 |
1741 | + * Todd C. Miller <Todd.Miller@courtesan.com> |
1742 | + * |
1743 | + * Permission to use, copy, modify, and distribute this software for any |
1744 | + * purpose with or without fee is hereby granted, provided that the above |
1745 | + * copyright notice and this permission notice appear in all copies. |
1746 | + * |
1747 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
1748 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
1749 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
1750 | + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
1751 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
1752 | + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
1753 | + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
1754 | + * |
1755 | + * Sponsored in part by the Defense Advanced Research Projects |
1756 | + * Agency (DARPA) and Air Force Research Laboratory, Air Force |
1757 | + * Materiel Command, USAF, under agreement number F39502-99-1-0512. |
1758 | + */ |
1759 | + |
1760 | +#include <config.h> |
1761 | + |
1762 | +#include <sys/types.h> |
1763 | +#include <sys/param.h> |
1764 | +#include <sys/stat.h> |
1765 | +#include <stdio.h> |
1766 | +#ifdef STDC_HEADERS |
1767 | +# include <stdlib.h> |
1768 | +# include <stddef.h> |
1769 | +#else |
1770 | +# ifdef HAVE_STDLIB_H |
1771 | +# include <stdlib.h> |
1772 | +# endif |
1773 | +#endif /* STDC_HEADERS */ |
1774 | +#ifdef HAVE_STRING_H |
1775 | +# include <string.h> |
1776 | +#endif /* HAVE_STRING_H */ |
1777 | +#ifdef HAVE_STRINGS_H |
1778 | +# include <strings.h> |
1779 | +#endif /* HAVE_STRINGS_H */ |
1780 | +#ifdef HAVE_UNISTD_H |
1781 | +# include <unistd.h> |
1782 | +#endif /* HAVE_UNISTD_H */ |
1783 | +#include <ctype.h> |
1784 | +#include <errno.h> |
1785 | +#include <pwd.h> |
1786 | + |
1787 | +#include "sudo.h" |
1788 | + |
1789 | +/* |
1790 | + * Flags used in rebuild_env() |
1791 | + */ |
1792 | +#undef DID_TERM |
1793 | +#define DID_TERM 0x0001 |
1794 | +#undef DID_PATH |
1795 | +#define DID_PATH 0x0002 |
1796 | +#undef DID_HOME |
1797 | +#define DID_HOME 0x0004 |
1798 | +#undef DID_SHELL |
1799 | +#define DID_SHELL 0x0008 |
1800 | +#undef DID_LOGNAME |
1801 | +#define DID_LOGNAME 0x0010 |
1802 | +#undef DID_USER |
1803 | +#define DID_USER 0x0020 |
1804 | +#undef DID_USERNAME |
1805 | +#define DID_USERNAME 0x0040 |
1806 | +#undef DID_MAIL |
1807 | +#define DID_MAIL 0x0080 |
1808 | +#undef DID_MAX |
1809 | +#define DID_MAX 0x00ff |
1810 | + |
1811 | +#undef KEPT_TERM |
1812 | +#define KEPT_TERM 0x0100 |
1813 | +#undef KEPT_PATH |
1814 | +#define KEPT_PATH 0x0200 |
1815 | +#undef KEPT_HOME |
1816 | +#define KEPT_HOME 0x0400 |
1817 | +#undef KEPT_SHELL |
1818 | +#define KEPT_SHELL 0x0800 |
1819 | +#undef KEPT_LOGNAME |
1820 | +#define KEPT_LOGNAME 0x1000 |
1821 | +#undef KEPT_USER |
1822 | +#define KEPT_USER 0x2000 |
1823 | +#undef KEPT_USERNAME |
1824 | +#define KEPT_USERNAME 0x4000 |
1825 | +#undef KEPT_MAIL |
1826 | +#define KEPT_MAIL 0x8000 |
1827 | +#undef KEPT_MAX |
1828 | +#define KEPT_MAX 0xff00 |
1829 | + |
1830 | +struct environment { |
1831 | + char **envp; /* pointer to the new environment */ |
1832 | + size_t env_size; /* size of new_environ in char **'s */ |
1833 | + size_t env_len; /* number of slots used, not counting NULL */ |
1834 | + int owned; /* do we own envp or is it the system's? */ |
1835 | +}; |
1836 | + |
1837 | +/* |
1838 | + * Prototypes |
1839 | + */ |
1840 | +static void sudo_setenv __P((const char *, const char *, int)); |
1841 | +static void sudo_putenv __P((char *, int, int)); |
1842 | + |
1843 | +extern char **environ; /* global environment */ |
1844 | + |
1845 | +/* |
1846 | + * Copy of the sudo-managed environment. |
1847 | + */ |
1848 | +static struct environment env; |
1849 | + |
1850 | +/* |
1851 | + * Default table of "bad" variables to remove from the environment. |
1852 | + * XXX - how to omit TERMCAP if it starts with '/'? |
1853 | + */ |
1854 | +static const char *initial_badenv_table[] = { |
1855 | + "IFS", |
1856 | + "CDPATH", |
1857 | + "SHELLOPTS", |
1858 | + "PS4", |
1859 | + "LOCALDOMAIN", |
1860 | + "RES_OPTIONS", |
1861 | + "HOSTALIASES", |
1862 | + "NLSPATH", |
1863 | + "PATH_LOCALE", |
1864 | + "LD_*", |
1865 | + "_RLD*", |
1866 | +#ifdef __hpux |
1867 | + "SHLIB_PATH", |
1868 | +#endif /* __hpux */ |
1869 | +#ifdef _AIX |
1870 | + "LDR_*", |
1871 | + "LIBPATH", |
1872 | + "AUTHSTATE", |
1873 | +#endif |
1874 | +#ifdef __APPLE__ |
1875 | + "DYLD_*", |
1876 | +#endif |
1877 | +#ifdef HAVE_KERB4 |
1878 | + "KRB_CONF*", |
1879 | + "KRBCONFDIR", |
1880 | + "KRBTKFILE", |
1881 | +#endif /* HAVE_KERB4 */ |
1882 | +#ifdef HAVE_KERB5 |
1883 | + "KRB5_CONFIG*", |
1884 | + "KRB5_KTNAME", |
1885 | +#endif /* HAVE_KERB5 */ |
1886 | +#ifdef HAVE_SECURID |
1887 | + "VAR_ACE", |
1888 | + "USR_ACE", |
1889 | + "DLC_ACE", |
1890 | +#endif /* HAVE_SECURID */ |
1891 | + "TERMINFO", /* terminfo, exclusive path to terminfo files */ |
1892 | + "TERMINFO_DIRS", /* terminfo, path(s) to terminfo files */ |
1893 | + "TERMPATH", /* termcap, path(s) to termcap files */ |
1894 | + "TERMCAP", /* XXX - only if it starts with '/' */ |
1895 | + "ENV", /* ksh, file to source before script runs */ |
1896 | + "BASH_ENV", /* bash, file to source before script runs */ |
1897 | + "PS4", /* bash, prefix for lines in xtrace mode */ |
1898 | + "GLOBIGNORE", /* bash, globbing patterns to ignore */ |
1899 | + "SHELLOPTS", /* bash, extra command line options */ |
1900 | + "JAVA_TOOL_OPTIONS", /* java, extra command line options */ |
1901 | + "PERLIO_DEBUG ", /* perl, debugging output file */ |
1902 | + "PERLLIB", /* perl, search path for modules/includes */ |
1903 | + "PERL5LIB", /* perl 5, search path for modules/includes */ |
1904 | + "PERL5OPT", /* perl 5, extra command line options */ |
1905 | + "PERL5DB", /* perl 5, command used to load debugger */ |
1906 | + "FPATH", /* ksh, search path for functions */ |
1907 | + "NULLCMD", /* zsh, command for null file redirection */ |
1908 | + "READNULLCMD", /* zsh, command for null file redirection */ |
1909 | + "ZDOTDIR", /* zsh, search path for dot files */ |
1910 | + "TMPPREFIX", /* zsh, prefix for temporary files */ |
1911 | + "PYTHONHOME", /* python, module search path */ |
1912 | + "PYTHONPATH", /* python, search path */ |
1913 | + "PYTHONINSPECT", /* python, allow inspection */ |
1914 | + "PYTHONUSERBASE", /* python, per user site-packages directory */ |
1915 | + "RUBYLIB", /* ruby, library load path */ |
1916 | + "RUBYOPT", /* ruby, extra command line options */ |
1917 | + NULL |
1918 | +}; |
1919 | + |
1920 | +/* |
1921 | + * Default table of variables to check for '%' and '/' characters. |
1922 | + */ |
1923 | +static const char *initial_checkenv_table[] = { |
1924 | + "COLORTERM", |
1925 | + "LANG", |
1926 | + "LANGUAGE", |
1927 | + "LC_*", |
1928 | + "LINGUAS", |
1929 | + "TERM", |
1930 | + NULL |
1931 | +}; |
1932 | + |
1933 | +/* |
1934 | + * Default table of variables to preserve in the environment. |
1935 | + */ |
1936 | +static const char *initial_keepenv_table[] = { |
1937 | + "COLORS", |
1938 | + "DISPLAY", |
1939 | + "HOSTNAME", |
1940 | + "KRB5CCNAME", |
1941 | + "LS_COLORS", |
1942 | + "PATH", |
1943 | + "PS1", |
1944 | + "PS2", |
1945 | + "TZ", |
1946 | + "XAUTHORITY", |
1947 | + "XAUTHORIZATION", |
1948 | + NULL |
1949 | +}; |
1950 | + |
1951 | +/* |
1952 | + * Initialize env based on envp. |
1953 | + */ |
1954 | +void |
1955 | +env_init(lazy) |
1956 | + int lazy; |
1957 | +{ |
1958 | + char * const *ep; |
1959 | + size_t len; |
1960 | + |
1961 | + for (ep = environ; *ep != NULL; ep++) |
1962 | + continue; |
1963 | + len = (size_t)(ep - environ); |
1964 | + |
1965 | + if (lazy) { |
1966 | + /* |
1967 | + * If we are already initialized due to lazy init (usualy via getenv()) |
1968 | + * we need to avoid calling malloc() as it may call getenv() itself. |
1969 | + */ |
1970 | + env.envp = environ; |
1971 | + env.env_len = len; |
1972 | + env.env_size = len; |
1973 | + } else if (!env.owned) { |
1974 | + env.env_len = len; |
1975 | + env.env_size = len + 1 + 128; |
1976 | + env.envp = emalloc2(env.env_size, sizeof(char *)); |
1977 | +#ifdef ENV_DEBUG |
1978 | + memset(env.envp, 0, env.env_size * sizeof(char *)); |
1979 | +#endif |
1980 | + memcpy(env.envp, environ, len * sizeof(char *)); |
1981 | + env.envp[len] = '\0'; |
1982 | + env.owned = TRUE; |
1983 | + } |
1984 | +} |
1985 | + |
1986 | +char ** |
1987 | +env_get() |
1988 | +{ |
1989 | + return env.envp; |
1990 | +} |
1991 | + |
1992 | +/* |
1993 | + * Similar to setenv(3) but operates on sudo's private copy of the environment |
1994 | + * (not environ) and it always overwrites. The dupcheck param determines |
1995 | + * whether we need to verify that the variable is not already set. |
1996 | + */ |
1997 | +static void |
1998 | +sudo_setenv(var, val, dupcheck) |
1999 | + const char *var; |
2000 | + const char *val; |
2001 | + int dupcheck; |
2002 | +{ |
2003 | + char *estring; |
2004 | + size_t esize; |
2005 | + |
2006 | + esize = strlen(var) + 1 + strlen(val) + 1; |
2007 | + estring = emalloc(esize); |
2008 | + |
2009 | + /* Build environment string and insert it. */ |
2010 | + if (strlcpy(estring, var, esize) >= esize || |
2011 | + strlcat(estring, "=", esize) >= esize || |
2012 | + strlcat(estring, val, esize) >= esize) { |
2013 | + |
2014 | + errorx(1, "internal error, sudo_setenv() overflow"); |
2015 | + } |
2016 | + sudo_putenv(estring, dupcheck, TRUE); |
2017 | +} |
2018 | + |
2019 | +/* |
2020 | + * Version of getenv(3) that uses our own environ pointer. |
2021 | + */ |
2022 | +char * |
2023 | +getenv(var) |
2024 | + const char *var; |
2025 | +{ |
2026 | + char *cp, **ev; |
2027 | + size_t vlen = strlen(var); |
2028 | + |
2029 | + if (env.envp == NULL) |
2030 | + env_init(TRUE); |
2031 | + |
2032 | + for (ev = env.envp; (cp = *ev) != NULL; ev++) { |
2033 | + if (strncmp(var, cp, vlen) == 0 && cp[vlen] == '=') |
2034 | + return cp + vlen + 1; |
2035 | + } |
2036 | + return NULL; |
2037 | +} |
2038 | + |
2039 | +/* |
2040 | + * Version of setenv(3) that uses our own environ pointer. |
2041 | + */ |
2042 | +int |
2043 | +setenv(var, val, overwrite) |
2044 | + const char *var; |
2045 | + const char *val; |
2046 | + int overwrite; |
2047 | +{ |
2048 | + char *estring, *ep; |
2049 | + const char *cp; |
2050 | + size_t esize; |
2051 | + |
2052 | + if (!var || *var == '\0') { |
2053 | + errno = EINVAL; |
2054 | + return(-1); |
2055 | + } |
2056 | + |
2057 | + if (env.envp == NULL) |
2058 | + env_init(TRUE); |
2059 | + |
2060 | + /* |
2061 | + * POSIX says a var name with '=' is an error but BSD |
2062 | + * just ignores the '=' and anything after it. |
2063 | + */ |
2064 | + for (cp = var; *cp && *cp != '='; cp++) |
2065 | + ; |
2066 | + esize = (size_t)(cp - var) + 2; |
2067 | + if (val) { |
2068 | + esize += strlen(val); /* glibc treats a NULL val as "" */ |
2069 | + } |
2070 | + |
2071 | + /* Allocate and fill in estring. */ |
2072 | + estring = ep = emalloc(esize); |
2073 | + for (cp = var; *cp && *cp != '='; cp++) |
2074 | + *ep++ = *cp; |
2075 | + *ep++ = '='; |
2076 | + if (val) { |
2077 | + for (cp = val; *cp; cp++) |
2078 | + *ep++ = *cp; |
2079 | + } |
2080 | + *ep = '\0'; |
2081 | + |
2082 | +#ifdef ENV_DEBUG |
2083 | + if (env.envp[env.env_len] != NULL) |
2084 | + errorx(1, "setenv: corrupted envp, len mismatch"); |
2085 | +#endif |
2086 | + sudo_putenv(estring, TRUE, overwrite); |
2087 | + return(0); |
2088 | +} |
2089 | + |
2090 | +/* |
2091 | + * Version of unsetenv(3) that uses our own environ pointer. |
2092 | + */ |
2093 | +#ifdef UNSETENV_VOID |
2094 | +void |
2095 | +#else |
2096 | +int |
2097 | +#endif |
2098 | +unsetenv(var) |
2099 | + const char *var; |
2100 | +{ |
2101 | + char **ep; |
2102 | + size_t len; |
2103 | + |
2104 | + if (var == NULL || *var == '\0' || strchr(var, '=') != NULL) { |
2105 | + errno = EINVAL; |
2106 | +#ifdef UNSETENV_VOID |
2107 | + return; |
2108 | +#else |
2109 | + return(-1); |
2110 | +#endif |
2111 | + } |
2112 | + |
2113 | + if (env.envp == NULL) |
2114 | + env_init(TRUE); |
2115 | + |
2116 | +#ifdef ENV_DEBUG |
2117 | + if (env.envp[env.env_len] != NULL) |
2118 | + errorx(1, "unsetenv: corrupted envp, len mismatch"); |
2119 | +#endif |
2120 | + |
2121 | + len = strlen(var); |
2122 | + for (ep = env.envp; *ep != NULL;) { |
2123 | + if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') { |
2124 | + /* Found it; shift remainder + NULL over by one. */ |
2125 | + char **cur = ep; |
2126 | + while ((*cur = *(cur + 1)) != NULL) |
2127 | + cur++; |
2128 | + /* Keep going, could be multiple instances of the var. */ |
2129 | + } else { |
2130 | + ep++; |
2131 | + } |
2132 | + } |
2133 | + env.env_len = ep - env.envp; |
2134 | +#ifndef UNSETENV_VOID |
2135 | + return(0); |
2136 | +#endif |
2137 | +} |
2138 | + |
2139 | +/* |
2140 | + * Version of putenv(3) that uses our own environ pointer. |
2141 | + */ |
2142 | +int |
2143 | +#ifdef PUTENV_CONST |
2144 | +putenv(const char *string) |
2145 | +#else |
2146 | +putenv(string) |
2147 | + char *string; |
2148 | +#endif |
2149 | +{ |
2150 | + if (env.envp == NULL) |
2151 | + env_init(TRUE); |
2152 | + |
2153 | + if (strchr(string, '=') == NULL) { |
2154 | + errno = EINVAL; |
2155 | + return(-1); |
2156 | + } |
2157 | +#ifdef ENV_DEBUG |
2158 | + if (env.envp[env.env_len] != NULL) |
2159 | + errorx(1, "putenv: corrupted envp, len mismatch"); |
2160 | +#endif |
2161 | + sudo_putenv((char *)string, TRUE, TRUE); |
2162 | + return(0); |
2163 | +} |
2164 | + |
2165 | +/* |
2166 | + * Similar to putenv(3) but operates on sudo's private copy of the |
2167 | + * environment (not environ) and it always overwrites. The dupcheck param |
2168 | + * determines whether we need to verify that the variable is not already set. |
2169 | + * Will only overwrite an existing variable if overwrite is set. |
2170 | + */ |
2171 | +static void |
2172 | +sudo_putenv(str, dupcheck, overwrite) |
2173 | + char *str; |
2174 | + int dupcheck; |
2175 | + int overwrite; |
2176 | +{ |
2177 | + char **ep; |
2178 | + size_t len; |
2179 | + int found = FALSE; |
2180 | + |
2181 | + /* Make sure there is room for the new entry plus a NULL. */ |
2182 | + if (env.env_len + 2 > env.env_size) { |
2183 | + env.env_size += 128; |
2184 | + if (env.owned) { |
2185 | + env.envp = erealloc3(env.envp, env.env_size, sizeof(char *)); |
2186 | + } else { |
2187 | + /* We don't own env.envp, allocate a new one. */ |
2188 | + ep = emalloc2(env.env_size, sizeof(char *)); |
2189 | + memcpy(ep, env.envp, env.env_size * sizeof(char *)); |
2190 | + env.envp = ep; |
2191 | + env.owned = TRUE; |
2192 | + } |
2193 | +#ifdef ENV_DEBUG |
2194 | + memset(env.envp + env.env_len, 0, |
2195 | + (env.env_size - env.env_len) * sizeof(char *)); |
2196 | +#endif |
2197 | + } |
2198 | + |
2199 | +#ifdef ENV_DEBUG |
2200 | + if (env.envp[env.env_len] != NULL) |
2201 | + errorx(1, "sudo_putenv: corrupted envp, len mismatch"); |
2202 | +#endif |
2203 | + |
2204 | + if (dupcheck) { |
2205 | + len = (strchr(str, '=') - str) + 1; |
2206 | + for (ep = env.envp; !found && *ep != NULL; ep++) { |
2207 | + if (strncmp(str, *ep, len) == 0) { |
2208 | + if (overwrite) |
2209 | + *ep = str; |
2210 | + found = TRUE; |
2211 | + } |
2212 | + } |
2213 | + /* Prune out duplicate variables. */ |
2214 | + if (found && overwrite) { |
2215 | + while (*ep != NULL) { |
2216 | + if (strncmp(str, *ep, len) == 0) { |
2217 | + char **cur = ep; |
2218 | + while ((*cur = *(cur + 1)) != NULL) |
2219 | + cur++; |
2220 | + } else { |
2221 | + ep++; |
2222 | + } |
2223 | + } |
2224 | + env.env_len = ep - env.envp; |
2225 | + } |
2226 | + } |
2227 | + |
2228 | + if (!found) { |
2229 | + ep = env.envp + env.env_len; |
2230 | + env.env_len++; |
2231 | + *ep++ = str; |
2232 | + *ep = NULL; |
2233 | + } |
2234 | +} |
2235 | + |
2236 | +/* |
2237 | + * Check the env_delete blacklist. |
2238 | + * Returns TRUE if the variable was found, else false. |
2239 | + */ |
2240 | +static int |
2241 | +matches_env_delete(var) |
2242 | + const char *var; |
2243 | +{ |
2244 | + struct list_member *cur; |
2245 | + size_t len; |
2246 | + int iswild, match = FALSE; |
2247 | + |
2248 | + /* Skip anything listed in env_delete. */ |
2249 | + for (cur = def_env_delete; cur; cur = cur->next) { |
2250 | + len = strlen(cur->value); |
2251 | + /* Deal with '*' wildcard */ |
2252 | + if (cur->value[len - 1] == '*') { |
2253 | + len--; |
2254 | + iswild = TRUE; |
2255 | + } else |
2256 | + iswild = FALSE; |
2257 | + if (strncmp(cur->value, var, len) == 0 && |
2258 | + (iswild || var[len] == '=')) { |
2259 | + match = TRUE; |
2260 | + break; |
2261 | + } |
2262 | + } |
2263 | + return(match); |
2264 | +} |
2265 | + |
2266 | +/* |
2267 | + * Apply the env_check list. |
2268 | + * Returns TRUE if the variable is allowed, FALSE if denied |
2269 | + * or -1 if no match. |
2270 | + */ |
2271 | +static int |
2272 | +matches_env_check(var) |
2273 | + const char *var; |
2274 | +{ |
2275 | + struct list_member *cur; |
2276 | + size_t len; |
2277 | + int iswild, keepit = -1; |
2278 | + |
2279 | + for (cur = def_env_check; cur; cur = cur->next) { |
2280 | + len = strlen(cur->value); |
2281 | + /* Deal with '*' wildcard */ |
2282 | + if (cur->value[len - 1] == '*') { |
2283 | + len--; |
2284 | + iswild = TRUE; |
2285 | + } else |
2286 | + iswild = FALSE; |
2287 | + if (strncmp(cur->value, var, len) == 0 && |
2288 | + (iswild || var[len] == '=')) { |
2289 | + keepit = !strpbrk(var, "/%"); |
2290 | + break; |
2291 | + } |
2292 | + } |
2293 | + return(keepit); |
2294 | +} |
2295 | + |
2296 | +/* |
2297 | + * Check the env_keep list. |
2298 | + * Returns TRUE if the variable is allowed else FALSE. |
2299 | + */ |
2300 | +static int |
2301 | +matches_env_keep(var) |
2302 | + const char *var; |
2303 | +{ |
2304 | + struct list_member *cur; |
2305 | + size_t len; |
2306 | + int iswild, keepit = FALSE; |
2307 | + |
2308 | + for (cur = def_env_keep; cur; cur = cur->next) { |
2309 | + len = strlen(cur->value); |
2310 | + /* Deal with '*' wildcard */ |
2311 | + if (cur->value[len - 1] == '*') { |
2312 | + len--; |
2313 | + iswild = TRUE; |
2314 | + } else |
2315 | + iswild = FALSE; |
2316 | + if (strncmp(cur->value, var, len) == 0 && |
2317 | + (iswild || var[len] == '=')) { |
2318 | + keepit = TRUE; |
2319 | + break; |
2320 | + } |
2321 | + } |
2322 | + return(keepit); |
2323 | +} |
2324 | + |
2325 | +/* |
2326 | + * Build a new environment and ether clear potentially dangerous |
2327 | + * variables from the old one or start with a clean slate. |
2328 | + * Also adds sudo-specific variables (SUDO_*). |
2329 | + */ |
2330 | +void |
2331 | +rebuild_env(noexec) |
2332 | + int noexec; |
2333 | +{ |
2334 | + char **old_envp, **ep, *cp, *ps1; |
2335 | + char idbuf[MAX_UID_T_LEN]; |
2336 | + unsigned int didvar; |
2337 | + int reset_home = FALSE; |
2338 | + |
2339 | + /* |
2340 | + * Either clean out the environment or reset to a safe default. |
2341 | + */ |
2342 | + ps1 = NULL; |
2343 | + didvar = 0; |
2344 | + env.env_len = 0; |
2345 | + env.env_size = 128; |
2346 | + old_envp = env.envp; |
2347 | + env.envp = emalloc2(env.env_size, sizeof(char *)); |
2348 | +#ifdef ENV_DEBUG |
2349 | + memset(env.envp, 0, env.env_size * sizeof(char *)); |
2350 | +#endif |
2351 | + |
2352 | + /* Reset HOME based on target user if configured to. */ |
2353 | + if (ISSET(sudo_mode, MODE_RUN)) { |
2354 | + if (def_always_set_home || |
2355 | + ISSET(sudo_mode, MODE_RESET_HOME | MODE_LOGIN_SHELL) || |
2356 | + (ISSET(sudo_mode, MODE_SHELL) && def_set_home)) |
2357 | + reset_home = TRUE; |
2358 | + } |
2359 | + |
2360 | + if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) { |
2361 | + /* Pull in vars we want to keep from the old environment. */ |
2362 | + for (ep = old_envp; *ep; ep++) { |
2363 | + int keepit; |
2364 | + |
2365 | + /* Skip variables with values beginning with () (bash functions) */ |
2366 | + if ((cp = strchr(*ep, '=')) != NULL) { |
2367 | + if (strncmp(cp, "=() ", 3) == 0) |
2368 | + continue; |
2369 | + } |
2370 | + |
2371 | + /* |
2372 | + * First check certain variables for '%' and '/' characters. |
2373 | + * If no match there, check the keep list. |
2374 | + * If nothing matched, we remove it from the environment. |
2375 | + */ |
2376 | + keepit = matches_env_check(*ep); |
2377 | + if (keepit == -1) |
2378 | + keepit = matches_env_keep(*ep); |
2379 | + |
2380 | + if (!strncmp (*ep, "DISPLAY=",8) |
2381 | + || !strncmp (*ep, "XAUTHORITY=", 11) |
2382 | + || !strncmp (*ep, "XAUTHORIZATION=", 15) |
2383 | + || !strncmp (*ep, "XAPPLRESDIR=", 12) |
2384 | + || !strncmp (*ep, "XFILESEARCHPATH=", 16) |
2385 | + || !strncmp (*ep, "XUSERFILESEARCHPATH=", 20) |
2386 | + || !strncmp (*ep, "LANG=", 5) |
2387 | + || !strncmp (*ep, "LANGUAGE=", 9) |
2388 | + || !strncmp (*ep, "LC_", 3)) |
2389 | + keepit = 1; |
2390 | + |
2391 | + /* For SUDO_PS1 -> PS1 conversion. */ |
2392 | + if (strncmp(*ep, "SUDO_PS1=", 8) == 0) |
2393 | + ps1 = *ep + 5; |
2394 | + |
2395 | + if (keepit) { |
2396 | + /* Preserve variable. */ |
2397 | + switch (**ep) { |
2398 | + case 'H': |
2399 | + if (strncmp(*ep, "HOME=", 5) == 0) |
2400 | + SET(didvar, DID_HOME); |
2401 | + break; |
2402 | + case 'L': |
2403 | + if (strncmp(*ep, "LOGNAME=", 8) == 0) |
2404 | + SET(didvar, DID_LOGNAME); |
2405 | + break; |
2406 | + case 'M': |
2407 | + if (strncmp(*ep, "MAIL=", 5) == 0) |
2408 | + SET(didvar, DID_MAIL); |
2409 | + break; |
2410 | + case 'P': |
2411 | + if (strncmp(*ep, "PATH=", 5) == 0) |
2412 | + SET(didvar, DID_PATH); |
2413 | + break; |
2414 | + case 'S': |
2415 | + if (strncmp(*ep, "SHELL=", 6) == 0) |
2416 | + SET(didvar, DID_SHELL); |
2417 | + break; |
2418 | + case 'T': |
2419 | + if (strncmp(*ep, "TERM=", 5) == 0) |
2420 | + SET(didvar, DID_TERM); |
2421 | + break; |
2422 | + case 'U': |
2423 | + if (strncmp(*ep, "USER=", 5) == 0) |
2424 | + SET(didvar, DID_USER); |
2425 | + if (strncmp(*ep, "USERNAME=", 5) == 0) |
2426 | + SET(didvar, DID_USERNAME); |
2427 | + break; |
2428 | + } |
2429 | + sudo_putenv(*ep, FALSE, FALSE); |
2430 | + } |
2431 | + } |
2432 | + didvar |= didvar << 8; /* convert DID_* to KEPT_* */ |
2433 | + |
2434 | + /* |
2435 | + * Add in defaults. In -i mode these come from the runas user, |
2436 | + * otherwise they may be from the user's environment (depends |
2437 | + * on sudoers options). |
2438 | + */ |
2439 | + if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { |
2440 | + sudo_setenv("SHELL", runas_pw->pw_shell, ISSET(didvar, DID_SHELL)); |
2441 | + sudo_setenv("LOGNAME", runas_pw->pw_name, |
2442 | + ISSET(didvar, DID_LOGNAME)); |
2443 | + sudo_setenv("USER", runas_pw->pw_name, ISSET(didvar, DID_USER)); |
2444 | + sudo_setenv("USERNAME", runas_pw->pw_name, |
2445 | + ISSET(didvar, DID_USERNAME)); |
2446 | + } else { |
2447 | + if (!ISSET(didvar, DID_SHELL)) |
2448 | + sudo_setenv("SHELL", sudo_user.pw->pw_shell, FALSE); |
2449 | + if (!ISSET(didvar, DID_LOGNAME)) |
2450 | + sudo_setenv("LOGNAME", user_name, FALSE); |
2451 | + if (!ISSET(didvar, DID_USER)) |
2452 | + sudo_setenv("USER", user_name, FALSE); |
2453 | + if (!ISSET(didvar, DID_USERNAME)) |
2454 | + sudo_setenv("USERNAME", user_name, FALSE); |
2455 | + } |
2456 | + |
2457 | + /* If we didn't keep HOME, reset it based on target user. */ |
2458 | + if (!ISSET(didvar, KEPT_HOME)) |
2459 | + reset_home = TRUE; |
2460 | + |
2461 | + /* |
2462 | + * Set MAIL to target user in -i mode or if MAIL is not preserved |
2463 | + * from user's environment. |
2464 | + */ |
2465 | + if (ISSET(sudo_mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) { |
2466 | + cp = _PATH_MAILDIR; |
2467 | + if (cp[sizeof(_PATH_MAILDIR) - 2] == '/') |
2468 | + easprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name); |
2469 | + else |
2470 | + easprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name); |
2471 | + sudo_putenv(cp, ISSET(didvar, DID_MAIL), TRUE); |
2472 | + } |
2473 | + } else { |
2474 | + /* |
2475 | + * Copy environ entries as long as they don't match env_delete or |
2476 | + * env_check. |
2477 | + */ |
2478 | + for (ep = old_envp; *ep; ep++) { |
2479 | + int okvar; |
2480 | + |
2481 | + /* Skip variables with values beginning with () (bash functions) */ |
2482 | + if ((cp = strchr(*ep, '=')) != NULL) { |
2483 | + if (strncmp(cp, "=() ", 3) == 0) |
2484 | + continue; |
2485 | + } |
2486 | + |
2487 | + /* |
2488 | + * First check variables against the blacklist in env_delete. |
2489 | + * If no match there check for '%' and '/' characters. |
2490 | + */ |
2491 | + okvar = matches_env_delete(*ep) != TRUE; |
2492 | + if (okvar) |
2493 | + okvar = matches_env_check(*ep) != FALSE; |
2494 | + |
2495 | + if (okvar) { |
2496 | + if (strncmp(*ep, "SUDO_PS1=", 9) == 0) |
2497 | + ps1 = *ep + 5; |
2498 | + else if (strncmp(*ep, "PATH=", 5) == 0) |
2499 | + SET(didvar, DID_PATH); |
2500 | + else if (strncmp(*ep, "TERM=", 5) == 0) |
2501 | + SET(didvar, DID_TERM); |
2502 | + sudo_putenv(*ep, FALSE, FALSE); |
2503 | + } |
2504 | + } |
2505 | + } |
2506 | + /* Replace the PATH envariable with a secure one? */ |
2507 | + if (def_secure_path && !user_is_exempt()) { |
2508 | + sudo_setenv("PATH", def_secure_path, TRUE); |
2509 | + SET(didvar, DID_PATH); |
2510 | + } |
2511 | + |
2512 | + /* Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is true. */ |
2513 | + if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL)) { |
2514 | + if (!ISSET(didvar, KEPT_LOGNAME)) |
2515 | + sudo_setenv("LOGNAME", runas_pw->pw_name, TRUE); |
2516 | + if (!ISSET(didvar, KEPT_USER)) |
2517 | + sudo_setenv("USER", runas_pw->pw_name, TRUE); |
2518 | + if (!ISSET(didvar, KEPT_USERNAME)) |
2519 | + sudo_setenv("USERNAME", runas_pw->pw_name, TRUE); |
2520 | + } |
2521 | + |
2522 | + /* Set $HOME to target user if not preserving user's value. */ |
2523 | + if (reset_home) |
2524 | + sudo_setenv("HOME", runas_pw->pw_dir, TRUE); |
2525 | + |
2526 | + /* Provide default values for $TERM and $PATH if they are not set. */ |
2527 | + if (!ISSET(didvar, DID_TERM)) |
2528 | + sudo_putenv("TERM=unknown", FALSE, FALSE); |
2529 | + if (!ISSET(didvar, DID_PATH)) |
2530 | + sudo_setenv("PATH", _PATH_STDPATH, FALSE); |
2531 | + |
2532 | + /* |
2533 | + * Preload a noexec file? For a list of LD_PRELOAD-alikes, see |
2534 | + * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html |
2535 | + * XXX - should prepend to original value, if any |
2536 | + */ |
2537 | + if (noexec && def_noexec_file != NULL) { |
2538 | +#if defined(__darwin__) || defined(__APPLE__) |
2539 | + sudo_setenv("DYLD_INSERT_LIBRARIES", def_noexec_file, TRUE); |
2540 | + sudo_setenv("DYLD_FORCE_FLAT_NAMESPACE", "", TRUE); |
2541 | +#else |
2542 | +# if defined(__osf__) || defined(__sgi) |
2543 | + easprintf(&cp, "%s:DEFAULT", def_noexec_file); |
2544 | + sudo_setenv("_RLD_LIST", cp, TRUE); |
2545 | + efree(cp); |
2546 | +# else |
2547 | +# ifdef _AIX |
2548 | + sudo_setenv("LDR_PRELOAD", def_noexec_file, TRUE); |
2549 | +# else |
2550 | + sudo_setenv("LD_PRELOAD", def_noexec_file, TRUE); |
2551 | +# endif /* _AIX */ |
2552 | +# endif /* __osf__ || __sgi */ |
2553 | +#endif /* __darwin__ || __APPLE__ */ |
2554 | + } |
2555 | + |
2556 | + /* Set PS1 if SUDO_PS1 is set. */ |
2557 | + if (ps1 != NULL) |
2558 | + sudo_putenv(ps1, TRUE, TRUE); |
2559 | + |
2560 | + /* Add the SUDO_COMMAND envariable (cmnd + args). */ |
2561 | + if (user_args) { |
2562 | + easprintf(&cp, "%s %s", user_cmnd, user_args); |
2563 | + sudo_setenv("SUDO_COMMAND", cp, TRUE); |
2564 | + efree(cp); |
2565 | + } else { |
2566 | + sudo_setenv("SUDO_COMMAND", user_cmnd, TRUE); |
2567 | + } |
2568 | + |
2569 | + /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */ |
2570 | + sudo_setenv("SUDO_USER", user_name, TRUE); |
2571 | + snprintf(idbuf, sizeof(idbuf), "%lu", (unsigned long) user_uid); |
2572 | + sudo_setenv("SUDO_UID", idbuf, TRUE); |
2573 | + snprintf(idbuf, sizeof(idbuf), "%lu", (unsigned long) user_gid); |
2574 | + sudo_setenv("SUDO_GID", idbuf, TRUE); |
2575 | + |
2576 | + /* Free old environment. */ |
2577 | + efree(old_envp); |
2578 | +} |
2579 | + |
2580 | +void |
2581 | +insert_env_vars(env_vars) |
2582 | + struct list_member *env_vars; |
2583 | +{ |
2584 | + struct list_member *cur; |
2585 | + |
2586 | + /* Add user-specified environment variables. */ |
2587 | + for (cur = env_vars; cur != NULL; cur = cur->next) |
2588 | + putenv(cur->value); |
2589 | +} |
2590 | + |
2591 | +/* |
2592 | + * Validate the list of environment variables passed in on the command |
2593 | + * line against env_delete, env_check, and env_keep. |
2594 | + * Calls log_error() if any specified variables are not allowed. |
2595 | + */ |
2596 | +void |
2597 | +validate_env_vars(env_vars) |
2598 | + struct list_member *env_vars; |
2599 | +{ |
2600 | + struct list_member *var; |
2601 | + char *eq, *bad = NULL; |
2602 | + size_t len, blen = 0, bsize = 0; |
2603 | + int okvar; |
2604 | + |
2605 | + /* Add user-specified environment variables. */ |
2606 | + for (var = env_vars; var != NULL; var = var->next) { |
2607 | + if (def_secure_path && !user_is_exempt() && |
2608 | + strncmp(var->value, "PATH=", 5) == 0) { |
2609 | + okvar = FALSE; |
2610 | + } else if (def_env_reset) { |
2611 | + okvar = matches_env_check(var->value); |
2612 | + if (okvar == -1) |
2613 | + okvar = matches_env_keep(var->value); |
2614 | + } else { |
2615 | + okvar = matches_env_delete(var->value) == FALSE; |
2616 | + if (okvar == FALSE) |
2617 | + okvar = matches_env_check(var->value) != FALSE; |
2618 | + } |
2619 | + if (okvar == FALSE) { |
2620 | + /* Not allowed, add to error string, allocating as needed. */ |
2621 | + if ((eq = strchr(var->value, '=')) != NULL) |
2622 | + *eq = '\0'; |
2623 | + len = strlen(var->value) + 2; |
2624 | + if (blen + len >= bsize) { |
2625 | + do { |
2626 | + bsize += 1024; |
2627 | + } while (blen + len >= bsize); |
2628 | + bad = erealloc(bad, bsize); |
2629 | + bad[blen] = '\0'; |
2630 | + } |
2631 | + strlcat(bad, var->value, bsize); |
2632 | + strlcat(bad, ", ", bsize); |
2633 | + blen += len; |
2634 | + if (eq != NULL) |
2635 | + *eq = '='; |
2636 | + } |
2637 | + } |
2638 | + if (bad != NULL) { |
2639 | + bad[blen - 2] = '\0'; /* remove trailing ", " */ |
2640 | + log_error(NO_MAIL, |
2641 | + "sorry, you are not allowed to set the following environment variables: %s", bad); |
2642 | + /* NOTREACHED */ |
2643 | + efree(bad); |
2644 | + } |
2645 | +} |
2646 | + |
2647 | +/* |
2648 | + * Read in /etc/environment ala AIX and Linux. |
2649 | + * Lines may be in either of three formats: |
2650 | + * NAME=VALUE |
2651 | + * NAME="VALUE" |
2652 | + * NAME='VALUE' |
2653 | + * with an optional "export" prefix so the shell can source the file. |
2654 | + * Invalid lines, blank lines, or lines consisting solely of a comment |
2655 | + * character are skipped. |
2656 | + */ |
2657 | +void |
2658 | +read_env_file(path, overwrite) |
2659 | + const char *path; |
2660 | + int overwrite; |
2661 | +{ |
2662 | + FILE *fp; |
2663 | + char *cp, *var, *val; |
2664 | + size_t var_len, val_len; |
2665 | + |
2666 | + if ((fp = fopen(path, "r")) == NULL) |
2667 | + return; |
2668 | + |
2669 | + while ((var = sudo_parseln(fp)) != NULL) { |
2670 | + /* Skip blank or comment lines */ |
2671 | + if (*var == '\0') |
2672 | + continue; |
2673 | + |
2674 | + /* Skip optional "export " */ |
2675 | + if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) { |
2676 | + var += 7; |
2677 | + while (isspace((unsigned char) *var)) { |
2678 | + var++; |
2679 | + } |
2680 | + } |
2681 | + |
2682 | + /* Must be of the form name=["']value['"] */ |
2683 | + for (val = var; *val != '\0' && *val != '='; val++) |
2684 | + ; |
2685 | + if (var == val || *val != '=') |
2686 | + continue; |
2687 | + var_len = (size_t)(val - var); |
2688 | + val_len = strlen(++val); |
2689 | + |
2690 | + /* Strip leading and trailing single/double quotes */ |
2691 | + if ((val[0] == '\'' || val[0] == '\"') && val[0] == val[val_len - 1]) { |
2692 | + val[val_len - 1] = '\0'; |
2693 | + val++; |
2694 | + val_len -= 2; |
2695 | + } |
2696 | + |
2697 | + cp = emalloc(var_len + 1 + val_len + 1); |
2698 | + memcpy(cp, var, var_len + 1); /* includes '=' */ |
2699 | + memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */ |
2700 | + |
2701 | + sudo_putenv(cp, TRUE, overwrite); |
2702 | + } |
2703 | + fclose(fp); |
2704 | +} |
2705 | + |
2706 | +void |
2707 | +init_envtables() |
2708 | +{ |
2709 | + struct list_member *cur; |
2710 | + const char **p; |
2711 | + |
2712 | + /* Fill in the "env_delete" list. */ |
2713 | + for (p = initial_badenv_table; *p; p++) { |
2714 | + cur = emalloc(sizeof(struct list_member)); |
2715 | + cur->value = estrdup(*p); |
2716 | + cur->next = def_env_delete; |
2717 | + def_env_delete = cur; |
2718 | + } |
2719 | + |
2720 | + /* Fill in the "env_check" list. */ |
2721 | + for (p = initial_checkenv_table; *p; p++) { |
2722 | + cur = emalloc(sizeof(struct list_member)); |
2723 | + cur->value = estrdup(*p); |
2724 | + cur->next = def_env_check; |
2725 | + def_env_check = cur; |
2726 | + } |
2727 | + |
2728 | + /* Fill in the "env_keep" list. */ |
2729 | + for (p = initial_keepenv_table; *p; p++) { |
2730 | + cur = emalloc(sizeof(struct list_member)); |
2731 | + cur->value = estrdup(*p); |
2732 | + cur->next = def_env_keep; |
2733 | + def_env_keep = cur; |
2734 | + } |
2735 | +} |
2736 | +>>>>>>> MERGE-SOURCE |
2737 | |
2738 | === modified file 'debian/changelog' |
2739 | --- debian/changelog 2011-05-23 09:50:37 +0000 |
2740 | +++ debian/changelog 2011-05-23 08:12:57 +0000 |
2741 | @@ -1,3 +1,4 @@ |
2742 | +<<<<<<< TREE |
2743 | sudo (1.7.4p6-1ubuntu1) oneiric; urgency=low |
2744 | |
2745 | * Merge from debian/unstable, remaining changes: |
2746 | @@ -102,6 +103,110 @@ |
2747 | |
2748 | -- Lorenzo De Liso <blackz@ubuntu.com> Wed, 15 Dec 2010 21:32:57 +0100 |
2749 | |
2750 | +======= |
2751 | +sudo (1.7.4p6-1ubuntu1) oneiric; urgency=low |
2752 | + |
2753 | + * Merge from debian/unstable, remaining changes: |
2754 | + + debian/patches/keep_home_by_default.patch: Set HOME in |
2755 | + initial_keepenv_table. LP: #760140 |
2756 | + + compile with --without-lecture --with-tty-tickets (Ubuntu specific) |
2757 | + + install man/man8/sudo_root.8 (Ubuntu specific) |
2758 | + + install apport hooks |
2759 | + + debian/sudoers: grant admin group sudo access |
2760 | + - debian/sudo-ldap.dirs, debian/sudo.dirs: add |
2761 | + usr/share/apport/package-hooks |
2762 | + * drop debian/patches/CVE-2011-0010.patch applied upstream now |
2763 | + |
2764 | + -- Michael Vogt <michael.vogt@ubuntu.com> Mon, 23 May 2011 09:25:09 +0200 |
2765 | + |
2766 | +sudo (1.7.4p6-1) unstable; urgency=low |
2767 | + |
2768 | + * new upstream version |
2769 | + * touch the right stamp name after configuring, closes: #611287 |
2770 | + * patch from Svante Signell to fix build problem on Hurd, closes: #611290 |
2771 | + |
2772 | + -- Bdale Garbee <bdale@gag.com> Wed, 09 Feb 2011 11:32:58 -0700 |
2773 | + |
2774 | +sudo (1.7.4p4-6) unstable; urgency=low |
2775 | + |
2776 | + * update /etc/sudoers.d/README now that sudoers is a conffile |
2777 | + * patch from upstream to fix special case in password checking code |
2778 | + when only the gid is changing, closes: #609641 |
2779 | + |
2780 | + -- Bdale Garbee <bdale@gag.com> Tue, 11 Jan 2011 10:22:39 -0700 |
2781 | + |
2782 | +sudo (1.7.4p4-5ubuntu8) oneiric; urgency=low |
2783 | + |
2784 | + * debian/sudo.preinst: |
2785 | + - if well-known ec2 vmbuilder file is found, write a file in |
2786 | + sudoers.d for the 'ubuntu' user (LP: #768625) |
2787 | + |
2788 | + -- Scott Moser <smoser@ubuntu.com> Thu, 21 Apr 2011 18:04:34 -0400 |
2789 | + |
2790 | +sudo (1.7.4p4-5ubuntu7) natty; urgency=low |
2791 | + |
2792 | + * debian/sudo.preinst: |
2793 | + - do not consider the ec2 vmbuilder default sudoers file |
2794 | + verbatim as its actually customized (LP: #761689) |
2795 | + |
2796 | + -- Michael Vogt <michael.vogt@ubuntu.com> Fri, 15 Apr 2011 16:40:10 +0200 |
2797 | + |
2798 | +sudo (1.7.4p4-5ubuntu6) natty; urgency=low |
2799 | + |
2800 | + * debian/patches/keep_home_by_default.patch: Set HOME in |
2801 | + initial_keepenv_table. LP: #760140 |
2802 | + |
2803 | + -- Steve Langasek <steve.langasek@ubuntu.com> Wed, 13 Apr 2011 12:32:25 -0700 |
2804 | + |
2805 | +sudo (1.7.4p4-5ubuntu5) natty; urgency=low |
2806 | + |
2807 | + * debian/sudo.preinst: |
2808 | + - avoid conffile prompt by checking for known default /etc/sudoers |
2809 | + and if found installing the correct default /etc/sudoers file |
2810 | + (LP: #690873) |
2811 | + |
2812 | + -- Michael Vogt <michael.vogt@ubuntu.com> Fri, 25 Mar 2011 09:13:43 +0100 |
2813 | + |
2814 | +sudo (1.7.4p4-5ubuntu4) natty; urgency=low |
2815 | + |
2816 | + * debian/rules: The ubuntu-sudo-as-admin-successful.patch was taken |
2817 | + upstream by Debian however it requires a --enable-admin-flag configure |
2818 | + flag to actually enable it. |
2819 | + (LP: #706045) |
2820 | + |
2821 | + -- Bryce Harrington <bryce@ubuntu.com> Thu, 10 Feb 2011 12:01:53 -0800 |
2822 | + |
2823 | +sudo (1.7.4p4-5ubuntu3) natty; urgency=low |
2824 | + |
2825 | + * SECURITY UPDATE: privilege escalation via -g when using group Runas_List |
2826 | + - debian/patches/CVE-2011-0010.patch: prompt for password when the user is |
2827 | + running sudo as himself but as a different group |
2828 | + - CVE-2011-0010 |
2829 | + |
2830 | + -- Jamie Strandboge <jamie@ubuntu.com> Tue, 18 Jan 2011 16:37:09 -0600 |
2831 | + |
2832 | +sudo (1.7.4p4-5ubuntu2) natty; urgency=low |
2833 | + |
2834 | + * debian/sudoers: temporarily workaround LP #690873 by adding %admin |
2835 | + into the default sudoers file in case people just say "yes" to the |
2836 | + dpkg conffile prompt. |
2837 | + |
2838 | + -- Kees Cook <kees@ubuntu.com> Wed, 15 Dec 2010 15:38:17 -0800 |
2839 | + |
2840 | +sudo (1.7.4p4-5ubuntu1) natty; urgency=low |
2841 | + |
2842 | + * Merge from debian unstable (LP: #689025), remaining changes: |
2843 | + - debian/rules: |
2844 | + + compile with --without-lecture --with-tty-tickets (Ubuntu specific) |
2845 | + + install man/man8/sudo_root.8 (Ubuntu specific) |
2846 | + + install apport hooks |
2847 | + - debian/sudo-ldap.dirs, debian/sudo.dirs: add |
2848 | + usr/share/apport/package-hooks |
2849 | + * This upload also fixes: LP: #609645 |
2850 | + |
2851 | + -- Lorenzo De Liso <blackz@ubuntu.com> Wed, 15 Dec 2010 21:32:57 +0100 |
2852 | + |
2853 | +>>>>>>> MERGE-SOURCE |
2854 | sudo (1.7.4p4-5) unstable; urgency=low |
2855 | |
2856 | * patch from Jakub Wilk to add noopt and nostrip build option support, |