Merge lp:~ubuntu-branches/ubuntu/oneiric/sudo/oneiric-201105230807 into lp:ubuntu/oneiric/sudo

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
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+61926@code.launchpad.net

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(&timestampdir, &timestampfile);
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(&timestampdir, &timestampfile);
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,

Subscribers

People subscribed via source and target branches

to all changes: