diff options
Diffstat (limited to 'usr.sbin/rdate')
-rw-r--r-- | usr.sbin/rdate/rdate.c | 82 |
1 files changed, 69 insertions, 13 deletions
diff --git a/usr.sbin/rdate/rdate.c b/usr.sbin/rdate/rdate.c index 363fc2a1cb6..5da04a596d6 100644 --- a/usr.sbin/rdate/rdate.c +++ b/usr.sbin/rdate/rdate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rdate.c,v 1.32 2015/02/09 23:00:14 deraadt Exp $ */ +/* $OpenBSD: rdate.c,v 1.33 2015/10/29 03:16:15 deraadt Exp $ */ /* $NetBSD: rdate.c,v 1.4 1996/03/16 12:37:45 pk Exp $ */ /* @@ -40,6 +40,7 @@ #include <sys/socket.h> #include <sys/time.h> +#include <sys/wait.h> #include <stdio.h> #include <stdlib.h> @@ -62,6 +63,12 @@ void ntp_client(const char *, int, struct timeval *, struct timeval *, int); extern char *__progname; __dead void usage(void); +struct { + char message[256]; + struct timeval new; + struct timeval adjust; +} pdata; + __dead void usage(void) { @@ -76,11 +83,9 @@ main(int argc, char **argv) int slidetime = 0, corrleaps = 0; char *hname; extern int optind; - int c; + int c, p[2], pid; int family = PF_UNSPEC; - struct timeval new, adjust; - while ((c = getopt(argc, argv, "46psanocv")) != -1) { switch (c) { case '4': @@ -127,34 +132,85 @@ main(int argc, char **argv) usage(); hname = argv[optind]; - if (ntp) - ntp_client(hname, family, &new, &adjust, corrleaps); - else - rfc868time_client(hname, family, &new, &adjust, corrleaps); + /* + * Privilege separation increases safety, with a slight reduction + * in precision because the time values have to return over a pipe. + */ + if (pipe(p) == -1) + err(1, "pipe"); + switch ((pid = fork())) { + case -1: + err(1, "fork"); + break; + case 0: + if (pledge("stdio inet dns", NULL) == -1) + err(1, "fork"); + + close(p[0]); /* read side of pipe */ + dup2(p[1], STDIN_FILENO); + if (p[1] != STDIN_FILENO) + close(p[1]); + dup2(STDIN_FILENO, STDOUT_FILENO); + dup2(STDOUT_FILENO, STDERR_FILENO); + setvbuf(stdout, NULL, _IOFBF, 0); + setvbuf(stderr, NULL, _IOFBF, 0); + + if (ntp) + ntp_client(hname, family, &pdata.new, + &pdata.adjust, corrleaps); + else + rfc868time_client(hname, family, &pdata.new, + &pdata.adjust, corrleaps); + + if (write(STDOUT_FILENO, &pdata, sizeof pdata) != sizeof pdata) + exit(1); + exit(0); + } + + if (pledge("stdio rpath wpath settime", NULL) == -1) + err(1, "pledge"); + + close(p[1]); /* write side of pipe */ + if (read(p[0], &pdata, sizeof pdata) < 1) + err(1, "child did not collect time"); + if (waitpid(pid, NULL, 0) == -1) + err(1, "waitpid"); + + /* + * A viable timestamp from the child contains no message. + */ + if (pdata.message[0]) { + pdata.message[sizeof(pdata.message)- 1] = '\0'; + write(STDERR_FILENO, pdata.message, strlen(pdata.message)); + exit(1); + } if (!pr) { if (!slidetime) { logwtmp("|", "date", ""); - if (settimeofday(&new, NULL) == -1) + if (settimeofday(&pdata.new, NULL) == -1) err(1, "Could not set time of day"); logwtmp("{", "date", ""); } else { - if (adjtime(&adjust, NULL) == -1) + if (adjtime(&pdata.adjust, NULL) == -1) err(1, "Could not adjust time of day"); } } + if (pledge("stdio rpath", NULL) == -1) + err(1, "pledge"); + if (!silent) { struct tm *ltm; char buf[80]; - time_t tim = new.tv_sec; + time_t tim = pdata.new.tv_sec; double adjsec; ltm = localtime(&tim); (void) strftime(buf, sizeof buf, "%a %b %e %H:%M:%S %Z %Y\n", ltm); (void) fputs(buf, stdout); - adjsec = adjust.tv_sec + adjust.tv_usec / 1.0e6; + adjsec = pdata.adjust.tv_sec + pdata.adjust.tv_usec / 1.0e6; if (slidetime || verbose) { if (ntp) @@ -164,7 +220,7 @@ main(int argc, char **argv) else (void) fprintf(stdout, "%s: adjust local clock by %lld seconds\n", - __progname, (long long)adjust.tv_sec); + __progname, (long long)pdata.adjust.tv_sec); } } |