Wed Mar 7 23:41:17 2012 UTC ()
Pull up following revision(s) (requested by dholland in ticket #88):
	external/bsd/cron/dist/crontab.c: revision 1.4
	external/bsd/cron/dist/crontab.c: revision 1.5
PR/46127: Holger Weiss: "crontab <file>" fails for unprivileged users
XXX: Pullup to 6
Fix multiple problems in previous commit:
1.) Correct set-uid check to allow "root" to run "crontab -l" again.
2.) Don't the the last error reported in "errno" in case "crontab" is not
    installed set-uid "root". As no system-call failed "errno" is set
    to zero.


(riz)
diff -r1.3 -r1.3.8.1 src/external/bsd/cron/dist/crontab.c

cvs diff -r1.3 -r1.3.8.1 src/external/bsd/cron/dist/crontab.c (expand / switch to unified diff)

--- src/external/bsd/cron/dist/crontab.c 2010/05/18 21:47:43 1.3
+++ src/external/bsd/cron/dist/crontab.c 2012/03/07 23:41:17 1.3.8.1
@@ -1,41 +1,41 @@ @@ -1,41 +1,41 @@
1/* $NetBSD: crontab.c,v 1.3 2010/05/18 21:47:43 christos Exp $ */ 1/* $NetBSD: crontab.c,v 1.3.8.1 2012/03/07 23:41:17 riz Exp $ */
2 2
3/* Copyright 1988,1990,1993,1994 by Paul Vixie 3/* Copyright 1988,1990,1993,1994 by Paul Vixie
4 * All rights reserved 4 * All rights reserved
5 */ 5 */
6 6
7/* 7/*
8 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 8 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. 9 * Copyright (c) 1997,2000 by Internet Software Consortium, Inc.
10 * 10 *
11 * Permission to use, copy, modify, and distribute this software for any 11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above 12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies. 13 * copyright notice and this permission notice appear in all copies.
14 * 14 *
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */ 22 */
23#include <sys/cdefs.h> 23#include <sys/cdefs.h>
24#if !defined(lint) && !defined(LINT) 24#if !defined(lint) && !defined(LINT)
25#if 0 25#if 0
26static char rcsid[] = "Id: crontab.c,v 1.12 2004/01/23 18:56:42 vixie Exp"; 26static char rcsid[] = "Id: crontab.c,v 1.12 2004/01/23 18:56:42 vixie Exp";
27#else 27#else
28__RCSID("$NetBSD: crontab.c,v 1.3 2010/05/18 21:47:43 christos Exp $"); 28__RCSID("$NetBSD: crontab.c,v 1.3.8.1 2012/03/07 23:41:17 riz Exp $");
29#endif 29#endif
30#endif 30#endif
31 31
32/* crontab - install and manage per-user crontab files 32/* crontab - install and manage per-user crontab files
33 * vix 02may87 [RCS has the rest of the log] 33 * vix 02may87 [RCS has the rest of the log]
34 * vix 26jan87 [original] 34 * vix 26jan87 [original]
35 */ 35 */
36 36
37#define MAIN_PROGRAM 37#define MAIN_PROGRAM
38 38
39#include "cron.h" 39#include "cron.h"
40 40
41#define NHEADER_LINES 3 41#define NHEADER_LINES 3
@@ -56,48 +56,60 @@ static char Filename[MAX_FNAME], TempFi @@ -56,48 +56,60 @@ static char Filename[MAX_FNAME], TempFi
56static FILE *NewCrontab; 56static FILE *NewCrontab;
57static int CheckErrorCount; 57static int CheckErrorCount;
58static enum opt_t Option; 58static enum opt_t Option;
59static struct passwd *pw; 59static struct passwd *pw;
60static void list_cmd(void), 60static void list_cmd(void),
61 delete_cmd(void), 61 delete_cmd(void),
62 edit_cmd(void), 62 edit_cmd(void),
63 poke_daemon(void), 63 poke_daemon(void),
64 check_error(const char *), 64 check_error(const char *),
65 parse_args(int c, char *v[]); 65 parse_args(int c, char *v[]);
66static int replace_cmd(void); 66static int replace_cmd(void);
67static int allowed(const char *, const char *, const char *); 67static int allowed(const char *, const char *, const char *);
68static int in_file(const char *, FILE *, int); 68static int in_file(const char *, FILE *, int);
69static int swap_uids(void); 69static int relinguish_priv(void);
 70static int regain_priv(void);
70 71
71static void 72static void
72usage(const char *msg) { 73usage(const char *msg) {
73 (void)fprintf(stderr, "%s: usage error: %s\n", getprogname(), msg); 74 (void)fprintf(stderr, "%s: usage error: %s\n", getprogname(), msg);
74 (void)fprintf(stderr, "usage:\t%s [-u user] file\n", getprogname()); 75 (void)fprintf(stderr, "usage:\t%s [-u user] file\n", getprogname());
75 (void)fprintf(stderr, "\t%s [-u user] [ -e | -l | -r ]\n", getprogname()); 76 (void)fprintf(stderr, "\t%s [-u user] [ -e | -l | -r ]\n", getprogname());
76 (void)fprintf(stderr, "\t\t(default operation is replace, per 1003.2)\n"); 77 (void)fprintf(stderr, "\t\t(default operation is replace, per 1003.2)\n");
77 (void)fprintf(stderr, "\t-e\t(edit user's crontab)\n"); 78 (void)fprintf(stderr, "\t-e\t(edit user's crontab)\n");
78 (void)fprintf(stderr, "\t-l\t(list user's crontab)\n"); 79 (void)fprintf(stderr, "\t-l\t(list user's crontab)\n");
79 (void)fprintf(stderr, "\t-r\t(delete user's crontab)\n"); 80 (void)fprintf(stderr, "\t-r\t(delete user's crontab)\n");
80 exit(ERROR_EXIT); 81 exit(ERROR_EXIT);
81} 82}
82 83
 84static uid_t euid, ruid;
 85static gid_t egid, rgid;
 86
83int 87int
84main(int argc, char *argv[]) { 88main(int argc, char *argv[]) {
85 int exitstatus; 89 int exitstatus;
86 90
87 setprogname(argv[0]); 91 setprogname(argv[0]);
88 Pid = getpid(); 92 Pid = getpid();
89 (void)setlocale(LC_ALL, ""); 93 (void)setlocale(LC_ALL, "");
90 94
 95 euid = geteuid();
 96 egid = getegid();
 97 ruid = getuid();
 98 rgid = getgid();
 99
 100 if (euid == ruid && ruid != 0)
 101 errx(ERROR_EXIT, "Not installed setuid root");
 102
91 (void)setvbuf(stderr, NULL, _IOLBF, 0); 103 (void)setvbuf(stderr, NULL, _IOLBF, 0);
92 parse_args(argc, argv); /* sets many globals, opens a file */ 104 parse_args(argc, argv); /* sets many globals, opens a file */
93 set_cron_cwd(); 105 set_cron_cwd();
94 if (!allowed(RealUser, CRON_ALLOW, CRON_DENY)) { 106 if (!allowed(RealUser, CRON_ALLOW, CRON_DENY)) {
95 (void)fprintf(stderr, 107 (void)fprintf(stderr,
96 "You `%s' are not allowed to use this program `%s'\n", 108 "You `%s' are not allowed to use this program `%s'\n",
97 User, getprogname()); 109 User, getprogname());
98 (void)fprintf(stderr, "See crontab(1) for more information\n"); 110 (void)fprintf(stderr, "See crontab(1) for more information\n");
99 log_it(RealUser, Pid, "AUTH", "crontab command not allowed"); 111 log_it(RealUser, Pid, "AUTH", "crontab command not allowed");
100 exit(ERROR_EXIT); 112 exit(ERROR_EXIT);
101 } 113 }
102 exitstatus = OK_EXIT; 114 exitstatus = OK_EXIT;
103 switch (Option) { 115 switch (Option) {
@@ -201,33 +213,33 @@ parse_args(int argc, char *argv[]) { @@ -201,33 +213,33 @@ parse_args(int argc, char *argv[]) {
201 * reading the file. 213 * reading the file.
202 */ 214 */
203 if (!strcmp(Filename, "-")) 215 if (!strcmp(Filename, "-"))
204 NewCrontab = stdin; 216 NewCrontab = stdin;
205 else { 217 else {
206 /* relinquish the setuid status of the binary during 218 /* relinquish the setuid status of the binary during
207 * the open, lest nonroot users read files they should 219 * the open, lest nonroot users read files they should
208 * not be able to read. we can't use access() here 220 * not be able to read. we can't use access() here
209 * since there's a race condition. thanks go out to 221 * since there's a race condition. thanks go out to
210 * Arnt Gulbrandsen <agulbra@pvv.unit.no> for spotting 222 * Arnt Gulbrandsen <agulbra@pvv.unit.no> for spotting
211 * the race. 223 * the race.
212 */ 224 */
213 225
214 if (swap_uids() < OK) { 226 if (relinguish_priv() < OK) {
215 err(ERROR_EXIT, "swapping uids"); 227 err(ERROR_EXIT, "swapping uids");
216 } 228 }
217 if (!(NewCrontab = fopen(Filename, "r"))) { 229 if (!(NewCrontab = fopen(Filename, "r"))) {
218 err(ERROR_EXIT, "cannot open `%s'", Filename); 230 err(ERROR_EXIT, "cannot open `%s'", Filename);
219 } 231 }
220 if (swap_uids() < OK) { 232 if (regain_priv() < OK) {
221 err(ERROR_EXIT, "swapping uids back"); 233 err(ERROR_EXIT, "swapping uids back");
222 } 234 }
223 } 235 }
224 } 236 }
225 237
226 Debug(DMISC, ("user=%s, file=%s, option=%s\n", 238 Debug(DMISC, ("user=%s, file=%s, option=%s\n",
227 User, Filename, Options[(int)Option])); 239 User, Filename, Options[(int)Option]));
228} 240}
229 241
230static void 242static void
231skip_header(int *pch, FILE *f) 243skip_header(int *pch, FILE *f)
232{ 244{
233 int ch; 245 int ch;
@@ -577,27 +589,27 @@ replace_cmd(void) { @@ -577,27 +589,27 @@ replace_cmd(void) {
577 if ((uintmax_t)statbuf.st_size > (uintmax_t)maxtabsize) { 589 if ((uintmax_t)statbuf.st_size > (uintmax_t)maxtabsize) {
578 warnx("%ld bytes is larger than the maximum size of %ld bytes", 590 warnx("%ld bytes is larger than the maximum size of %ld bytes",
579 (long) statbuf.st_size, (long) maxtabsize); 591 (long) statbuf.st_size, (long) maxtabsize);
580 error = -2; 592 error = -2;
581 goto done; 593 goto done;
582 } 594 }
583 595
584 /* write a signature at the top of the file. 596 /* write a signature at the top of the file.
585 * 597 *
586 * VERY IMPORTANT: make sure NHEADER_LINES agrees with this code. 598 * VERY IMPORTANT: make sure NHEADER_LINES agrees with this code.
587 */ 599 */
588 (void)fprintf(tmp, "# DO NOT EDIT THIS FILE - edit the master and reinstall.\n"); 600 (void)fprintf(tmp, "# DO NOT EDIT THIS FILE - edit the master and reinstall.\n");
589 (void)fprintf(tmp, "# (%s installed on %-24.24s)\n", Filename, ctime(&now)); 601 (void)fprintf(tmp, "# (%s installed on %-24.24s)\n", Filename, ctime(&now));
590 (void)fprintf(tmp, "# (Cron version %s -- %s)\n", CRON_VERSION, "$NetBSD: crontab.c,v 1.3 2010/05/18 21:47:43 christos Exp $"); 602 (void)fprintf(tmp, "# (Cron version %s -- %s)\n", CRON_VERSION, "$NetBSD: crontab.c,v 1.3.8.1 2012/03/07 23:41:17 riz Exp $");
591 603
592 /* copy the crontab to the tmp 604 /* copy the crontab to the tmp
593 */ 605 */
594 (void)rewind(NewCrontab); 606 (void)rewind(NewCrontab);
595 Set_LineNum(1); 607 Set_LineNum(1);
596 lastch = EOF; 608 lastch = EOF;
597 while (EOF != (ch = get_char(NewCrontab))) 609 while (EOF != (ch = get_char(NewCrontab)))
598 (void)putc(lastch = ch, tmp); 610 (void)putc(lastch = ch, tmp);
599 611
600 if (lastch != (char)EOF && lastch != '\n') { 612 if (lastch != (char)EOF && lastch != '\n') {
601 warnx("missing trailing newline in `%s'", Filename); 613 warnx("missing trailing newline in `%s'", Filename);
602 error = -1; 614 error = -1;
603 goto done; 615 goto done;
@@ -762,35 +774,31 @@ in_file(const char *string, FILE *file,  @@ -762,35 +774,31 @@ in_file(const char *string, FILE *file,
762 return (error); 774 return (error);
763 *endp = '\0'; 775 *endp = '\0';
764 if (0 == strcmp(line, string)) 776 if (0 == strcmp(line, string))
765 return (TRUE); 777 return (TRUE);
766 } 778 }
767 } 779 }
768 if (ferror(file)) 780 if (ferror(file))
769 return (error); 781 return (error);
770 return (FALSE); 782 return (FALSE);
771} 783}
772 784
773#ifdef HAVE_SAVED_UIDS 785#ifdef HAVE_SAVED_UIDS
774 786
775static int swap_uids(void) { 787static int relinguish_priv(void) {
776 return ((setegid(getgid()) || seteuid(getuid())) ? -1 : 0); 788 return (setegid(rgid) || seteuid(ruid)) ? -1 : 0;
777} 789}
778#if 0 790
779static int swap_uids_back(void) { 791static int regain_priv(void) {
780 return ((setegid(getgid()) || seteuid(getuid())) ? -1 : 0); 792 return (setegid(egid) || seteuid(euid)) ? -1 : 0;
781} 793}
782#endif 
783 794
784#else /*HAVE_SAVED_UIDS*/ 795#else /*HAVE_SAVED_UIDS*/
785 796
786static int swap_uids(void) { 797static int relinguish_priv(void) {
787 return ((setregid(getegid(), getgid()) || setreuid(geteuid(), getuid())) 798 return (setregid(egid, rgid) || setreuid(euid, ruid)) ? -1 : 0;
788 ? -1 : 0); 
789} 799}
790 800
791#if 0 801static int regain_priv(void) {
792static int swap_uids_back(void) { 802 return (setregid(rgid, egid) || setreuid(ruid, euid)) ? -1 : 0;
793 return (swap_uids()); 
794} 803}
795#endif 
796#endif /*HAVE_SAVED_UIDS*/ 804#endif /*HAVE_SAVED_UIDS*/