| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: calendar.c,v 1.50 2013/11/09 15:57:15 christos Exp $ */ | | 1 | /* $NetBSD: calendar.c,v 1.50.4.1 2015/07/01 07:26:42 bouyer Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1989, 1993, 1994 | | 4 | * Copyright (c) 1989, 1993, 1994 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -29,35 +29,36 @@ | | | @@ -29,35 +29,36 @@ |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | #ifndef lint | | 33 | #ifndef lint |
34 | __COPYRIGHT("@(#) Copyright (c) 1989, 1993\ | | 34 | __COPYRIGHT("@(#) Copyright (c) 1989, 1993\ |
35 | The Regents of the University of California. All rights reserved."); | | 35 | The Regents of the University of California. All rights reserved."); |
36 | #endif /* not lint */ | | 36 | #endif /* not lint */ |
37 | | | 37 | |
38 | #ifndef lint | | 38 | #ifndef lint |
39 | #if 0 | | 39 | #if 0 |
40 | static char sccsid[] = "@(#)calendar.c 8.4 (Berkeley) 1/7/95"; | | 40 | static char sccsid[] = "@(#)calendar.c 8.4 (Berkeley) 1/7/95"; |
41 | #endif | | 41 | #endif |
42 | __RCSID("$NetBSD: calendar.c,v 1.50 2013/11/09 15:57:15 christos Exp $"); | | 42 | __RCSID("$NetBSD: calendar.c,v 1.50.4.1 2015/07/01 07:26:42 bouyer Exp $"); |
43 | #endif /* not lint */ | | 43 | #endif /* not lint */ |
44 | | | 44 | |
45 | #include <sys/param.h> | | 45 | #include <sys/param.h> |
46 | #include <sys/time.h> | | 46 | #include <sys/time.h> |
47 | #include <sys/stat.h> | | 47 | #include <sys/stat.h> |
48 | #include <sys/uio.h> | | 48 | #include <sys/uio.h> |
49 | #include <sys/wait.h> | | 49 | #include <sys/wait.h> |
50 | | | 50 | |
| | | 51 | #include <assert.h> |
51 | #include <ctype.h> | | 52 | #include <ctype.h> |
52 | #include <err.h> | | 53 | #include <err.h> |
53 | #include <errno.h> | | 54 | #include <errno.h> |
54 | #include <fcntl.h> | | 55 | #include <fcntl.h> |
55 | #include <pwd.h> | | 56 | #include <pwd.h> |
56 | #include <stdbool.h> | | 57 | #include <stdbool.h> |
57 | #include <stdio.h> | | 58 | #include <stdio.h> |
58 | #include <stdlib.h> | | 59 | #include <stdlib.h> |
59 | #include <string.h> | | 60 | #include <string.h> |
60 | #include <time.h> | | 61 | #include <time.h> |
61 | #include <tzfile.h> | | 62 | #include <tzfile.h> |
62 | #include <unistd.h> | | 63 | #include <unistd.h> |
63 | | | 64 | |
| @@ -102,26 +103,27 @@ static struct iovec header[] = { | | | @@ -102,26 +103,27 @@ static struct iovec header[] = { |
102 | | | 103 | |
103 | static const char *days[] = { | | 104 | static const char *days[] = { |
104 | "sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL, | | 105 | "sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL, |
105 | }; | | 106 | }; |
106 | | | 107 | |
107 | static const char *months[] = { | | 108 | static const char *months[] = { |
108 | "jan", "feb", "mar", "apr", "may", "jun", | | 109 | "jan", "feb", "mar", "apr", "may", "jun", |
109 | "jul", "aug", "sep", "oct", "nov", "dec", NULL, | | 110 | "jul", "aug", "sep", "oct", "nov", "dec", NULL, |
110 | }; | | 111 | }; |
111 | | | 112 | |
112 | static void atodays(int, char *, unsigned short *); | | 113 | static void atodays(int, char *, unsigned short *); |
113 | static void cal(void); | | 114 | static void cal(void); |
114 | static void closecal(FILE *); | | 115 | static void closecal(FILE *); |
| | | 116 | static void changeuser(void); |
115 | static int getday(char *); | | 117 | static int getday(char *); |
116 | static int getfield(char *, char **, int *); | | 118 | static int getfield(char *, char **, int *); |
117 | static void getmmdd(struct tm *, char *); | | 119 | static void getmmdd(struct tm *, char *); |
118 | static int getmonth(char *); | | 120 | static int getmonth(char *); |
119 | static bool isnow(char *); | | 121 | static bool isnow(char *); |
120 | static FILE *opencal(FILE **); | | 122 | static FILE *opencal(FILE **); |
121 | static void settime(void); | | 123 | static void settime(void); |
122 | static void usage(void) __dead; | | 124 | static void usage(void) __dead; |
123 | | | 125 | |
124 | int | | 126 | int |
125 | main(int argc, char **argv) | | 127 | main(int argc, char **argv) |
126 | { | | 128 | { |
127 | int ch; | | 129 | int ch; |
| @@ -161,32 +163,44 @@ main(int argc, char **argv) | | | @@ -161,32 +163,44 @@ main(int argc, char **argv) |
161 | } | | 163 | } |
162 | argc -= optind; | | 164 | argc -= optind; |
163 | argv += optind; | | 165 | argv += optind; |
164 | | | 166 | |
165 | if (argc) | | 167 | if (argc) |
166 | usage(); | | 168 | usage(); |
167 | | | 169 | |
168 | settime(); | | 170 | settime(); |
169 | if (doall) { | | 171 | if (doall) { |
170 | /* | | 172 | /* |
171 | * XXX - This ignores the user's CALENDAR_DIR variable. | | 173 | * XXX - This ignores the user's CALENDAR_DIR variable. |
172 | * Run under user's login shell? | | 174 | * Run under user's login shell? |
173 | */ | | 175 | */ |
| | | 176 | if (setgroups(0, NULL) == -1) { |
| | | 177 | err(EXIT_FAILURE, "setgroups"); |
| | | 178 | } |
174 | while ((pw = getpwent()) != NULL) { | | 179 | while ((pw = getpwent()) != NULL) { |
175 | (void)setegid(pw->pw_gid); | | 180 | if (setegid(pw->pw_gid) == -1) { |
176 | (void)seteuid(pw->pw_uid); | | 181 | warn("%s: setegid", pw->pw_name); |
177 | if (chdir(pw->pw_dir) != -1) | | 182 | continue; |
| | | 183 | } |
| | | 184 | if (seteuid(pw->pw_uid) == -1) { |
| | | 185 | warn("%s: seteuid", pw->pw_name); |
| | | 186 | continue; |
| | | 187 | } |
| | | 188 | if (chdir(pw->pw_dir) != -1) { |
178 | cal(); | | 189 | cal(); |
179 | (void)seteuid(0); | | 190 | } |
| | | 191 | if (seteuid(0) == -1) { |
| | | 192 | warn("%s: seteuid back to 0", pw->pw_name); |
| | | 193 | } |
180 | } | | 194 | } |
181 | } else if ((caldir = getenv("CALENDAR_DIR")) != NULL) { | | 195 | } else if ((caldir = getenv("CALENDAR_DIR")) != NULL) { |
182 | if (chdir(caldir) != -1) | | 196 | if (chdir(caldir) != -1) |
183 | cal(); | | 197 | cal(); |
184 | } else if ((pw = getpwuid(geteuid())) != NULL) { | | 198 | } else if ((pw = getpwuid(geteuid())) != NULL) { |
185 | if (chdir(pw->pw_dir) != -1) | | 199 | if (chdir(pw->pw_dir) != -1) |
186 | cal(); | | 200 | cal(); |
187 | } | | 201 | } |
188 | return 0; | | 202 | return 0; |
189 | } | | 203 | } |
190 | | | 204 | |
191 | static void | | 205 | static void |
192 | cal(void) | | 206 | cal(void) |
| @@ -419,26 +433,30 @@ opencal(FILE **in) | | | @@ -419,26 +433,30 @@ opencal(FILE **in) |
419 | case 0: | | 433 | case 0: |
420 | /* child */ | | 434 | /* child */ |
421 | /* set stdin to calendar file */ | | 435 | /* set stdin to calendar file */ |
422 | if (fd != STDIN_FILENO) { | | 436 | if (fd != STDIN_FILENO) { |
423 | (void)dup2(fd, STDIN_FILENO); | | 437 | (void)dup2(fd, STDIN_FILENO); |
424 | (void)close(fd); | | 438 | (void)close(fd); |
425 | } | | 439 | } |
426 | /* set stdout to pipe input */ | | 440 | /* set stdout to pipe input */ |
427 | if (pdes[1] != STDOUT_FILENO) { | | 441 | if (pdes[1] != STDOUT_FILENO) { |
428 | (void)dup2(pdes[1], STDOUT_FILENO); | | 442 | (void)dup2(pdes[1], STDOUT_FILENO); |
429 | (void)close(pdes[1]); | | 443 | (void)close(pdes[1]); |
430 | } | | 444 | } |
431 | (void)close(pdes[0]); | | 445 | (void)close(pdes[0]); |
| | | 446 | if (doall) { |
| | | 447 | /* become the user properly */ |
| | | 448 | changeuser(); |
| | | 449 | } |
432 | /* tell CPP to only open regular files */ | | 450 | /* tell CPP to only open regular files */ |
433 | if(!cpp_restricted && setenv("CPP_RESTRICTED", "", 1) == -1) | | 451 | if(!cpp_restricted && setenv("CPP_RESTRICTED", "", 1) == -1) |
434 | err(EXIT_FAILURE, "Cannot restrict cpp"); | | 452 | err(EXIT_FAILURE, "Cannot restrict cpp"); |
435 | cpp_restricted = true; | | 453 | cpp_restricted = true; |
436 | | | 454 | |
437 | (void)execl(_PATH_CPP, "cpp", "-traditional", "-P", "-I.", | | 455 | (void)execl(_PATH_CPP, "cpp", "-traditional", "-P", "-I.", |
438 | "-I" _PATH_CALENDARS, NULL); | | 456 | "-I" _PATH_CALENDARS, NULL); |
439 | err(EXIT_FAILURE, "Cannot exec `%s'", _PATH_CPP); | | 457 | err(EXIT_FAILURE, "Cannot exec `%s'", _PATH_CPP); |
440 | /*NOTREACHED*/ | | 458 | /*NOTREACHED*/ |
441 | default: | | 459 | default: |
442 | /* parent -- fdopen *in to pipe output */ | | 460 | /* parent -- fdopen *in to pipe output */ |
443 | *in = fdopen(pdes[0], "r"); | | 461 | *in = fdopen(pdes[0], "r"); |
444 | (void)close(pdes[1]); | | 462 | (void)close(pdes[1]); |
| @@ -485,49 +503,81 @@ closecal(FILE *fp) | | | @@ -485,49 +503,81 @@ closecal(FILE *fp) |
485 | switch (fork()) { | | 503 | switch (fork()) { |
486 | case -1: | | 504 | case -1: |
487 | /* error */ | | 505 | /* error */ |
488 | (void)close(pdes[0]); | | 506 | (void)close(pdes[0]); |
489 | (void)close(pdes[1]); | | 507 | (void)close(pdes[1]); |
490 | break; | | 508 | break; |
491 | case 0: | | 509 | case 0: |
492 | /* child -- set stdin to pipe output */ | | 510 | /* child -- set stdin to pipe output */ |
493 | if (pdes[0] != STDIN_FILENO) { | | 511 | if (pdes[0] != STDIN_FILENO) { |
494 | (void)dup2(pdes[0], STDIN_FILENO); | | 512 | (void)dup2(pdes[0], STDIN_FILENO); |
495 | (void)close(pdes[0]); | | 513 | (void)close(pdes[0]); |
496 | } | | 514 | } |
497 | (void)close(pdes[1]); | | 515 | (void)close(pdes[1]); |
| | | 516 | if (doall) { |
| | | 517 | /* become the user properly */ |
| | | 518 | changeuser(); |
| | | 519 | } |
498 | (void)execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F", | | 520 | (void)execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F", |
499 | "\"Reminder Service\"", "-f", "root", NULL); | | 521 | "\"Reminder Service\"", "-f", "root", NULL); |
500 | err(EXIT_FAILURE, "Cannot exec `%s'", _PATH_SENDMAIL); | | 522 | err(EXIT_FAILURE, "Cannot exec `%s'", _PATH_SENDMAIL); |
501 | /*NOTREACHED*/ | | 523 | /*NOTREACHED*/ |
502 | default: | | 524 | default: |
503 | /* parent -- write to pipe input */ | | 525 | /* parent -- write to pipe input */ |
504 | (void)close(pdes[0]); | | 526 | (void)close(pdes[0]); |
505 | | | 527 | |
506 | header[1].iov_base = header[3].iov_base = (void *)pw->pw_name; | | 528 | header[1].iov_base = header[3].iov_base = (void *)pw->pw_name; |
507 | header[1].iov_len = header[3].iov_len = strlen(pw->pw_name); | | 529 | header[1].iov_len = header[3].iov_len = strlen(pw->pw_name); |
508 | (void)writev(pdes[1], header, 7); | | 530 | (void)writev(pdes[1], header, 7); |
509 | while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0) | | 531 | while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0) |
510 | (void)write(pdes[1], buf, (size_t)nread); | | 532 | (void)write(pdes[1], buf, (size_t)nread); |
511 | (void)close(pdes[1]); | | 533 | (void)close(pdes[1]); |
512 | break; | | 534 | break; |
513 | } | | 535 | } |
514 | | | 536 | |
515 | done: (void)fclose(fp); | | 537 | done: (void)fclose(fp); |
516 | (void)unlink(path); | | 538 | (void)unlink(path); |
517 | while (wait(&status) != -1) | | 539 | while (wait(&status) != -1) |
518 | continue; | | 540 | continue; |
519 | } | | 541 | } |
520 | | | 542 | |
| | | 543 | static void |
| | | 544 | changeuser(void) |
| | | 545 | { |
| | | 546 | uid_t uid; |
| | | 547 | gid_t gid; |
| | | 548 | |
| | | 549 | uid = geteuid(); |
| | | 550 | gid = getegid(); |
| | | 551 | assert(uid == pw->pw_uid); |
| | | 552 | assert(gid == pw->pw_gid); |
| | | 553 | |
| | | 554 | if (seteuid(0) == -1) { |
| | | 555 | err(EXIT_FAILURE, "%s: changing user: cannot reassert uid 0", |
| | | 556 | pw->pw_name); |
| | | 557 | } |
| | | 558 | if (setgid(gid) == -1) { |
| | | 559 | err(EXIT_FAILURE, "%s: cannot assume gid %d", |
| | | 560 | pw->pw_name, (int)gid); |
| | | 561 | } |
| | | 562 | if (initgroups(pw->pw_name, gid) == -1) { |
| | | 563 | err(EXIT_FAILURE, "%s: cannot initgroups", pw->pw_name); |
| | | 564 | } |
| | | 565 | if (setuid(uid) == -1) { |
| | | 566 | err(EXIT_FAILURE, "%s: cannot assume uid %d", |
| | | 567 | pw->pw_name, (int)uid); |
| | | 568 | } |
| | | 569 | } |
| | | 570 | |
521 | static int | | 571 | static int |
522 | getmonth(char *s) | | 572 | getmonth(char *s) |
523 | { | | 573 | { |
524 | const char **p; | | 574 | const char **p; |
525 | | | 575 | |
526 | for (p = months; *p; ++p) | | 576 | for (p = months; *p; ++p) |
527 | if (strncasecmp(s, *p, 3) == 0) | | 577 | if (strncasecmp(s, *p, 3) == 0) |
528 | return (int)(p - months) + 1; | | 578 | return (int)(p - months) + 1; |
529 | return 0; | | 579 | return 0; |
530 | } | | 580 | } |
531 | | | 581 | |
532 | static int | | 582 | static int |
533 | getday(char *s) | | 583 | getday(char *s) |