| @@ -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 |
26 | static char rcsid[] = "Id: crontab.c,v 1.12 2004/01/23 18:56:42 vixie Exp"; | | 26 | static 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 |
56 | static FILE *NewCrontab; | | 56 | static FILE *NewCrontab; |
57 | static int CheckErrorCount; | | 57 | static int CheckErrorCount; |
58 | static enum opt_t Option; | | 58 | static enum opt_t Option; |
59 | static struct passwd *pw; | | 59 | static struct passwd *pw; |
60 | static void list_cmd(void), | | 60 | static 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[]); |
66 | static int replace_cmd(void); | | 66 | static int replace_cmd(void); |
67 | static int allowed(const char *, const char *, const char *); | | 67 | static int allowed(const char *, const char *, const char *); |
68 | static int in_file(const char *, FILE *, int); | | 68 | static int in_file(const char *, FILE *, int); |
69 | static int swap_uids(void); | | 69 | static int relinguish_priv(void); |
| | | 70 | static int regain_priv(void); |
70 | | | 71 | |
71 | static void | | 72 | static void |
72 | usage(const char *msg) { | | 73 | usage(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 | |
| | | 84 | static uid_t euid, ruid; |
| | | 85 | static gid_t egid, rgid; |
| | | 86 | |
83 | int | | 87 | int |
84 | main(int argc, char *argv[]) { | | 88 | main(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 | |
230 | static void | | 242 | static void |
231 | skip_header(int *pch, FILE *f) | | 243 | skip_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 | |
775 | static int swap_uids(void) { | | 787 | static 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 | |
779 | static int swap_uids_back(void) { | | 791 | static 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 | |
786 | static int swap_uids(void) { | | 797 | static 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 | | 801 | static int regain_priv(void) { |
792 | static 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*/ |