diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2015-11-12 21:12:06 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2015-11-12 21:12:06 +0000 |
commit | 8bcf8c8455a4408e205eba1acbf21a4428d3192c (patch) | |
tree | 13a479f6705664ec825a6ec1f690df9c499a5a8d | |
parent | 258b48ab5f61b14c05f456acc16073292ce3670e (diff) |
Use absolute paths in pathnames.h. There is no longer a need to
chdir(2) to the cron dir and cron(8) now changes to / via daemon(3).
We no longer try to create/chmod the spool directories as they
should be set correctly at install time. The setegid(crontab)
has been moved to open_socket() so it is closer to the chmod(2)
call that needs it. OK deraadt@ tedu@
-rw-r--r-- | usr.bin/at/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/at/at.c | 45 | ||||
-rw-r--r-- | usr.bin/crontab/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/cron/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/cron/atrun.c | 37 | ||||
-rw-r--r-- | usr.sbin/cron/client.c | 10 | ||||
-rw-r--r-- | usr.sbin/cron/common.c | 136 | ||||
-rw-r--r-- | usr.sbin/cron/cron.c | 23 | ||||
-rw-r--r-- | usr.sbin/cron/crontab.c | 45 | ||||
-rw-r--r-- | usr.sbin/cron/database.c | 66 | ||||
-rw-r--r-- | usr.sbin/cron/funcs.h | 9 | ||||
-rw-r--r-- | usr.sbin/cron/macros.h | 3 | ||||
-rw-r--r-- | usr.sbin/cron/pathnames.h | 62 |
13 files changed, 143 insertions, 305 deletions
diff --git a/usr.bin/at/Makefile b/usr.bin/at/Makefile index 74ba676627a..b2167d8bf30 100644 --- a/usr.bin/at/Makefile +++ b/usr.bin/at/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.10 2015/10/31 12:19:41 millert Exp $ +# $OpenBSD: Makefile,v 1.11 2015/11/12 21:12:05 millert Exp $ PROG= at -SRCS= at.c client.c common.c parsetime.c +SRCS= at.c client.c parsetime.c CRONDIR=${.CURDIR}/../../usr.sbin/cron CFLAGS+=-I${CRONDIR} MAN= at.1 atrm.1 atq.1 diff --git a/usr.bin/at/at.c b/usr.bin/at/at.c index 3b0510fecfa..9b519111bbe 100644 --- a/usr.bin/at/at.c +++ b/usr.bin/at/at.c @@ -1,4 +1,4 @@ -/* $OpenBSD: at.c,v 1.73 2015/11/11 21:53:51 millert Exp $ */ +/* $OpenBSD: at.c,v 1.74 2015/11/12 21:12:05 millert Exp $ */ /* * at.c : Put file into atrun queue @@ -70,7 +70,7 @@ char *no_export[] = }; int program = AT; /* default program mode */ -char atfile[MAX_FNAME]; /* path to the at spool file */ +char atfile[PATH_MAX]; /* path to the at spool file */ int fcreated; /* whether or not we created the file yet */ char atqueue = 0; /* which queue to examine for jobs (atq) */ char vflag = 0; /* show completed but unremoved jobs (atq) */ @@ -142,6 +142,21 @@ sigc(int signo) } static int +strtot(const char *nptr, char **endptr, time_t *tp) +{ + long long ll; + + errno = 0; + ll = strtoll(nptr, endptr, 10); + if (*endptr == nptr) + return (-1); + if (ll < 0 || (errno == ERANGE && ll == LLONG_MAX) || (time_t)ll != ll) + return (-1); + *tp = (time_t)ll; + return (0); +} + +static int newjob(time_t runtimer, int queue) { int fd, i; @@ -152,7 +167,7 @@ newjob(time_t runtimer, int queue) * queues instead... */ for (i = 0; i < 120; i++) { - snprintf(atfile, sizeof(atfile), "%s/%lld.%c", AT_SPOOL, + snprintf(atfile, sizeof(atfile), "%s/%lld.%c", _PATH_AT_SPOOL, (long long)runtimer, queue); fd = open(atfile, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR); if (fd >= 0) @@ -351,12 +366,12 @@ writefile(const char *cwd, time_t runtimer, char queue) (void)fclose(fp); /* Poke cron so it knows to reload the at spool. */ - poke_daemon(AT_SPOOL, RELOAD_AT); + poke_daemon(RELOAD_AT); runtime = *localtime(&runtimer); strftime(timestr, TIMESIZE, "%a %b %e %T %Y", &runtime); (void)fprintf(stderr, "commands will be executed using %s\n", shell); - (void)fprintf(stderr, "job %s at %s\n", &atfile[sizeof(AT_SPOOL)], + (void)fprintf(stderr, "job %s at %s\n", &atfile[sizeof(_PATH_AT_SPOOL)], timestr); } @@ -414,7 +429,7 @@ print_job(struct atjob *job, int n, int shortformat) /* * List all of a user's jobs in the queue, by looping through - * AT_SPOOL, or all jobs if we are root. If argc is > 0, argv + * _PATH_AT_SPOOL, or all jobs if we are root. If argc is > 0, argv * contains the list of users whose jobs shall be displayed. By * default, the list is sorted by execution date and queue. If * csort is non-zero jobs will be sorted by creation/submission date. @@ -449,12 +464,12 @@ list_jobs(int argc, char **argv, int count_only, int csort) shortformat = strcmp(__progname, "at") == 0; - if ((dfd = open(AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1 || + if ((dfd = open(_PATH_AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1 || (spool = fdopendir(dfd)) == NULL) - fatal(AT_SPOOL); + fatal(_PATH_AT_SPOOL); if (fstat(dfd, &stbuf) != 0) - fatal(AT_SPOOL); + fatal(_PATH_AT_SPOOL); /* * The directory's link count should give us a good idea @@ -564,7 +579,7 @@ rmok(long long job) } /* - * Loop through all jobs in AT_SPOOL and display or delete ones + * Loop through all jobs in _PATH_AT_SPOOL and display or delete ones * that match argv (may be job or username), or all if argc == 0. * Only the superuser may display/delete other people's jobs. */ @@ -583,9 +598,9 @@ process_jobs(int argc, char **argv, int what) int job_matches, jobs_len, uids_len; int error, i, ch, changed, dfd; - if ((dfd = open(AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1 || + if ((dfd = open(_PATH_AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1 || (spool = fdopendir(dfd)) == NULL) - fatal(AT_SPOOL); + fatal(_PATH_AT_SPOOL); /* Convert argv into a list of jobs and uids. */ jobs = NULL; @@ -696,7 +711,7 @@ process_jobs(int argc, char **argv, int what) /* If we modied the spool, poke cron so it knows to reload. */ if (changed) - poke_daemon(AT_SPOOL, RELOAD_AT); + poke_daemon(RELOAD_AT); return (error); } @@ -792,7 +807,7 @@ check_permission(void) if ((pw = getpwuid(user_uid)) == NULL) fatalx("unknown uid %u", user_uid); - return (allowed(pw->pw_name, AT_ALLOW, AT_DENY)); + return (allowed(pw->pw_name, _PATH_AT_ALLOW, _PATH_AT_DENY)); } static __dead void @@ -964,8 +979,6 @@ main(int argc, char **argv) if (getcwd(cwd, sizeof(cwd)) == NULL) fatal("unable to get current working directory"); - set_cron_cwd(); - if (!check_permission()) fatalx("you do not have permission to use at."); diff --git a/usr.bin/crontab/Makefile b/usr.bin/crontab/Makefile index 5fc8d3ecae8..ad68bea530c 100644 --- a/usr.bin/crontab/Makefile +++ b/usr.bin/crontab/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.7 2015/10/31 12:19:41 millert Exp $ +# $OpenBSD: Makefile,v 1.8 2015/11/12 21:12:05 millert Exp $ PROG= crontab -SRCS= crontab.c entry.c env.c client.c common.c misc.c +SRCS= crontab.c entry.c env.c client.c misc.c CFLAGS+=-I${.CURDIR} -I${.CURDIR}/../../usr.sbin/cron BINGRP =crontab BINMODE=2555 diff --git a/usr.sbin/cron/Makefile b/usr.sbin/cron/Makefile index 377c9c3be7d..56d50a2e3a8 100644 --- a/usr.sbin/cron/Makefile +++ b/usr.sbin/cron/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.5 2015/10/31 12:19:41 millert Exp $ +# $OpenBSD: Makefile,v 1.6 2015/11/12 21:12:05 millert Exp $ PROG= cron SRCS= cron.c database.c user.c entry.c job.c do_command.c \ - misc.c env.c popen.c atrun.c common.c + misc.c env.c popen.c atrun.c CFLAGS+=-I${.CURDIR} MAN= cron.8 diff --git a/usr.sbin/cron/atrun.c b/usr.sbin/cron/atrun.c index 132ea1c500b..7e6846b15be 100644 --- a/usr.sbin/cron/atrun.c +++ b/usr.sbin/cron/atrun.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atrun.c,v 1.38 2015/11/09 16:37:07 millert Exp $ */ +/* $OpenBSD: atrun.c,v 1.39 2015/11/12 21:12:05 millert Exp $ */ /* * Copyright (c) 2002-2003 Todd C. Miller <Todd.Miller@courtesan.com> @@ -50,6 +50,21 @@ static void run_job(atjob *, char *); +static int +strtot(const char *nptr, char **endptr, time_t *tp) +{ + long long ll; + + errno = 0; + ll = strtoll(nptr, endptr, 10); + if (*endptr == nptr) + return (-1); + if (ll < 0 || (errno == ERANGE && ll == LLONG_MAX) || (time_t)ll != ll) + return (-1); + *tp = (time_t)ll; + return (0); +} + /* * Scan the at jobs dir and build up a list of jobs found. */ @@ -65,12 +80,12 @@ scan_atjobs(at_db **db, struct timespec *ts) struct dirent *file; struct stat sb; - if ((dfd = open(AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1) { - log_it("CRON", "OPEN FAILED", AT_SPOOL); + if ((dfd = open(_PATH_AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1) { + log_it("CRON", "OPEN FAILED", _PATH_AT_SPOOL); return (0); } if (fstat(dfd, &sb) != 0) { - log_it("CRON", "FSTAT FAILED", AT_SPOOL); + log_it("CRON", "FSTAT FAILED", _PATH_AT_SPOOL); close(dfd); return (0); } @@ -80,7 +95,7 @@ scan_atjobs(at_db **db, struct timespec *ts) } if ((atdir = fdopendir(dfd)) == NULL) { - log_it("CRON", "OPENDIR FAILED", AT_SPOOL); + log_it("CRON", "OPENDIR FAILED", _PATH_AT_SPOOL); close(dfd); return (0); } @@ -148,7 +163,7 @@ scan_atjobs(at_db **db, struct timespec *ts) void atrun(at_db *db, double batch_maxload, time_t now) { - char atfile[MAX_FNAME]; + char atfile[PATH_MAX]; struct stat sb; double la; atjob *job, *tjob, *batch = NULL; @@ -161,7 +176,7 @@ atrun(at_db *db, double batch_maxload, time_t now) if (job->run_time > now) continue; - snprintf(atfile, sizeof(atfile), "%s/%lld.%c", AT_SPOOL, + snprintf(atfile, sizeof(atfile), "%s/%lld.%c", _PATH_AT_SPOOL, (long long)job->run_time, job->queue); if (lstat(atfile, &sb) != 0 || !S_ISREG(sb.st_mode)) { @@ -194,7 +209,7 @@ atrun(at_db *db, double batch_maxload, time_t now) && (batch_maxload == 0.0 || ((getloadavg(&la, 1) == 1) && la <= batch_maxload)) ) { - snprintf(atfile, sizeof(atfile), "%s/%lld.%c", AT_SPOOL, + snprintf(atfile, sizeof(atfile), "%s/%lld.%c", _PATH_AT_SPOOL, (long long)batch->run_time, batch->queue); run_job(batch, atfile); TAILQ_REMOVE(&db->jobs, batch, entries); @@ -420,8 +435,6 @@ run_job(atjob *job, char *atfile) login_close(lc); } - chdir("/"); /* at job will chdir to correct place */ - /* If this is a low priority job, nice ourself. */ if (job->queue > 'b') (void)setpriority(PRIO_PROCESS, 0, job->queue - 'b'); @@ -480,8 +493,8 @@ run_job(atjob *job, char *atfile) fprintf(mail, "To: %s\n", mailto); fprintf(mail, "Subject: Output from \"at\" job\n"); fprintf(mail, "Auto-Submitted: auto-generated\n"); - fprintf(mail, "\nYour \"at\" job on %s\n\"%s/%s/%s\"\n", - hostname, CRONDIR, AT_SPOOL, atfile); + fprintf(mail, "\nYour \"at\" job on %s\n\"%s/%s\"\n", + hostname, _PATH_AT_SPOOL, atfile); fprintf(mail, "\nproduced the following output:\n\n"); /* Pipe the job's output to sendmail. */ diff --git a/usr.sbin/cron/client.c b/usr.sbin/cron/client.c index 4ef6a2f4c9e..a0ad3caad91 100644 --- a/usr.sbin/cron/client.c +++ b/usr.sbin/cron/client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.7 2015/11/12 13:42:42 millert Exp $ */ +/* $OpenBSD: client.c,v 1.8 2015/11/12 21:12:05 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -88,19 +88,19 @@ allowed(const char *username, const char *allow_file, const char *deny_file) return (isallowed); } -/* void poke_daemon(const char *spool_dir, unsigned char cookie) +/* void poke_daemon(unsigned char cookie) * touches spool_dir and sends a poke to the cron daemon if running. */ void -poke_daemon(const char *spool_dir, unsigned char cookie) +poke_daemon(unsigned char cookie) { int sock = -1; - const char *cronsock = CRONSOCK; + const char *cronsock = _PATH_CRON_SOCK; struct stat sb; struct sockaddr_un s_un; if (stat(cronsock, &sb) != 0) - cronsock = CRONSOCK_OLD; /* backwards compatibility */ + cronsock = _PATH_CRON_SOCK_OLD; /* backwards compatibility */ bzero(&s_un, sizeof(s_un)); if (strlcpy(s_un.sun_path, cronsock, sizeof(s_un.sun_path)) >= diff --git a/usr.sbin/cron/common.c b/usr.sbin/cron/common.c deleted file mode 100644 index 381d309a660..00000000000 --- a/usr.sbin/cron/common.c +++ /dev/null @@ -1,136 +0,0 @@ -/* $OpenBSD: common.c,v 1.5 2015/11/12 13:42:42 millert Exp $ */ - -/* Copyright 1988,1990,1993,1994 by Paul Vixie - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/types.h> -#include <sys/stat.h> - -#include <bitstring.h> /* for structs.h */ -#include <errno.h> -#include <grp.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#include "config.h" -#include "pathnames.h" -#include "macros.h" -#include "structs.h" -#include "funcs.h" -#include "globals.h" - -void -set_cron_cwd(void) -{ - struct stat sb; - struct group *grp = NULL; - - grp = getgrnam(CRON_GROUP); - /* first check for CRONDIR ("/var/cron" or some such) - */ - if (stat(CRONDIR, &sb) < 0 && errno == ENOENT) { - perror(CRONDIR); - if (0 == mkdir(CRONDIR, 0710)) { - fprintf(stderr, "%s: created\n", CRONDIR); - stat(CRONDIR, &sb); - } else { - fprintf(stderr, "%s: ", CRONDIR); - perror("mkdir"); - exit(EXIT_FAILURE); - } - } - if (!S_ISDIR(sb.st_mode)) { - fprintf(stderr, "'%s' is not a directory, bailing out.\n", - CRONDIR); - exit(EXIT_FAILURE); - } - if (chdir(CRONDIR) < 0) { - fprintf(stderr, "cannot chdir(%s), bailing out.\n", CRONDIR); - perror(CRONDIR); - exit(EXIT_FAILURE); - } - - /* CRONDIR okay (now==CWD), now look at CRON_SPOOL ("tabs" or some such) - */ - if (stat(CRON_SPOOL, &sb) < 0 && errno == ENOENT) { - perror(CRON_SPOOL); - if (0 == mkdir(CRON_SPOOL, 0700)) { - fprintf(stderr, "%s: created\n", CRON_SPOOL); - stat(CRON_SPOOL, &sb); - } else { - fprintf(stderr, "%s: ", CRON_SPOOL); - perror("mkdir"); - exit(EXIT_FAILURE); - } - } - if (!S_ISDIR(sb.st_mode)) { - fprintf(stderr, "'%s' is not a directory, bailing out.\n", - CRON_SPOOL); - exit(EXIT_FAILURE); - } - if (grp != NULL) { - if (sb.st_gid != grp->gr_gid) - chown(CRON_SPOOL, -1, grp->gr_gid); - if ((sb.st_mode & ALLPERMS) != 01730) - chmod(CRON_SPOOL, 01730); - } - - /* finally, look at AT_SPOOL ("atjobs" or some such) - */ - if (stat(AT_SPOOL, &sb) < 0 && errno == ENOENT) { - perror(AT_SPOOL); - if (0 == mkdir(AT_SPOOL, 0700)) { - fprintf(stderr, "%s: created\n", AT_SPOOL); - stat(AT_SPOOL, &sb); - } else { - fprintf(stderr, "%s: ", AT_SPOOL); - perror("mkdir"); - exit(EXIT_FAILURE); - } - } - if (!S_ISDIR(sb.st_mode)) { - fprintf(stderr, "'%s' is not a directory, bailing out.\n", - AT_SPOOL); - exit(EXIT_FAILURE); - } - if (grp != NULL) { - setegid(grp->gr_gid); - if (sb.st_gid != grp->gr_gid) - chown(AT_SPOOL, -1, grp->gr_gid); - if ((sb.st_mode & ALLPERMS) != 01770) - chmod(AT_SPOOL, 01770); - } -} - -int -strtot(const char *nptr, char **endptr, time_t *tp) -{ - long long ll; - - errno = 0; - ll = strtoll(nptr, endptr, 10); - if (*endptr == nptr) - return (-1); - if (ll < 0 || (errno == ERANGE && ll == LLONG_MAX) || (time_t)ll != ll) - return (-1); - *tp = (time_t)ll; - return (0); -} diff --git a/usr.sbin/cron/cron.c b/usr.sbin/cron/cron.c index 00e80f722bc..50eba6a864f 100644 --- a/usr.sbin/cron/cron.c +++ b/usr.sbin/cron/cron.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cron.c,v 1.69 2015/11/12 13:42:42 millert Exp $ */ +/* $OpenBSD: cron.c,v 1.70 2015/11/12 21:12:05 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -25,6 +25,7 @@ #include <bitstring.h> #include <errno.h> +#include <grp.h> #include <locale.h> #include <poll.h> #include <signal.h> @@ -97,8 +98,6 @@ main(int argc, char *argv[]) sact.sa_handler = SIG_IGN; (void) sigaction(SIGPIPE, &sact, NULL); - set_cron_cwd(); - if (pledge("stdio rpath wpath cpath fattr getpw unix id dns proc exec", NULL) == -1) { log_it("CRON", "pledge", strerror(errno)); @@ -113,7 +112,7 @@ main(int argc, char *argv[]) } if (NoFork == 0) { - if (daemon(1, 0) == -1) { + if (daemon(0, 0) == -1) { log_it("CRON", "DEATH", "can't fork"); exit(EXIT_FAILURE); } @@ -421,8 +420,12 @@ open_socket(void) { int sock, rc; mode_t omask; + struct group *grp; struct sockaddr_un s_un; + if ((grp = getgrnam(CRON_GROUP)) == NULL) + log_it("CRON", "STARTUP", "can't find cron group"); + sock = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (sock == -1) { fprintf(stderr, "%s: can't create socket: %s\n", @@ -431,9 +434,9 @@ open_socket(void) exit(EXIT_FAILURE); } bzero(&s_un, sizeof(s_un)); - if (strlcpy(s_un.sun_path, CRONSOCK, sizeof(s_un.sun_path)) + if (strlcpy(s_un.sun_path, _PATH_CRON_SOCK, sizeof(s_un.sun_path)) >= sizeof(s_un.sun_path)) { - fprintf(stderr, "%s: path too long\n", CRONSOCK); + fprintf(stderr, "%s: path too long\n", _PATH_CRON_SOCK); log_it("CRON", "DEATH", "path too long"); exit(EXIT_FAILURE); } @@ -463,7 +466,13 @@ open_socket(void) exit(EXIT_FAILURE); } chmod(s_un.sun_path, 0660); - chown(s_un.sun_path, -1, getegid()); + if (grp != NULL) { + /* pledge won't let us change files to a foreign group. */ + if (setegid(grp->gr_gid) == 0) { + chown(s_un.sun_path, -1, grp->gr_gid); + (void)setegid(getgid()); + } + } return(sock); } diff --git a/usr.sbin/cron/crontab.c b/usr.sbin/cron/crontab.c index 804c61b5b52..55a51076849 100644 --- a/usr.sbin/cron/crontab.c +++ b/usr.sbin/cron/crontab.c @@ -1,4 +1,4 @@ -/* $OpenBSD: crontab.c,v 1.88 2015/11/11 21:20:51 millert Exp $ */ +/* $OpenBSD: crontab.c,v 1.89 2015/11/12 21:12:05 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -24,6 +24,7 @@ #include <bitstring.h> /* for structs.h */ #include <err.h> #include <errno.h> +#include <limits.h> #include <locale.h> #include <pwd.h> #include <signal.h> @@ -46,7 +47,7 @@ enum opt_t { opt_unknown, opt_list, opt_delete, opt_edit, opt_replace }; static gid_t crontab_gid; static gid_t user_gid; static char User[MAX_UNAME], RealUser[MAX_UNAME]; -static char Filename[MAX_FNAME], TempFilename[MAX_FNAME]; +static char Filename[PATH_MAX], TempFilename[PATH_MAX]; static FILE *NewCrontab; static int CheckErrorCount; static enum opt_t Option; @@ -93,8 +94,7 @@ main(int argc, char *argv[]) setvbuf(stderr, NULL, _IOLBF, 0); parse_args(argc, argv); /* sets many globals, opens a file */ - set_cron_cwd(); - if (!allowed(RealUser, CRON_ALLOW, CRON_DENY)) { + if (!allowed(RealUser, _PATH_CRON_ALLOW, _PATH_CRON_DENY)) { fprintf(stderr, "You do not have permission to use crontab\n"); fprintf(stderr, "See crontab(1) for more information\n"); log_it(RealUser, "AUTH", "crontab command not allowed"); @@ -183,10 +183,7 @@ parse_args(int argc, char *argv[]) } if (Option == opt_replace) { - /* we have to open the file here because we're going to - * chdir(2) into /var/cron before we get around to - * reading the file. - */ + /* XXX - no longer need to open the file early, move this. */ if (!strcmp(Filename, "-")) NewCrontab = stdin; else { @@ -211,12 +208,12 @@ parse_args(int argc, char *argv[]) static void list_cmd(void) { - char n[MAX_FNAME]; + char n[PATH_MAX]; FILE *f; log_it(RealUser, "LIST", User); - if (snprintf(n, sizeof n, "%s/%s", CRON_SPOOL, User) >= sizeof(n)) - errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", CRON_SPOOL, User); + if (snprintf(n, sizeof n, "%s/%s", _PATH_CRON_SPOOL, User) >= sizeof(n)) + errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", _PATH_CRON_SPOOL, User); if (!(f = fopen(n, "r"))) { if (errno == ENOENT) warnx("no crontab for %s", User); @@ -236,11 +233,11 @@ list_cmd(void) static void delete_cmd(void) { - char n[MAX_FNAME]; + char n[PATH_MAX]; log_it(RealUser, "DELETE", User); - if (snprintf(n, sizeof n, "%s/%s", CRON_SPOOL, User) >= sizeof(n)) - errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", CRON_SPOOL, User); + if (snprintf(n, sizeof n, "%s/%s", _PATH_CRON_SPOOL, User) >= sizeof(n)) + errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", _PATH_CRON_SPOOL, User); if (unlink(n) != 0) { if (errno == ENOENT) warnx("no crontab for %s", User); @@ -248,7 +245,7 @@ delete_cmd(void) warn("%s", n); exit(EXIT_FAILURE); } - poke_daemon(CRON_SPOOL, RELOAD_CRON); + poke_daemon(RELOAD_CRON); } static void @@ -261,15 +258,15 @@ check_error(const char *msg) static void edit_cmd(void) { - char n[MAX_FNAME], q[MAX_TEMPSTR]; + char n[PATH_MAX], q[MAX_TEMPSTR]; FILE *f; int t; struct stat statbuf, xstatbuf; struct timespec ts[2]; log_it(RealUser, "BEGIN EDIT", User); - if (snprintf(n, sizeof n, "%s/%s", CRON_SPOOL, User) >= sizeof(n)) - errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", CRON_SPOOL, User); + if (snprintf(n, sizeof n, "%s/%s", _PATH_CRON_SPOOL, User) >= sizeof(n)) + errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", _PATH_CRON_SPOOL, User); if (!(f = fopen(n, "r"))) { if (errno != ENOENT) err(EXIT_FAILURE, "%s", n); @@ -393,7 +390,7 @@ edit_cmd(void) static int replace_cmd(void) { - char n[MAX_FNAME], envstr[MAX_ENVSTR]; + char n[PATH_MAX], envstr[MAX_ENVSTR]; FILE *tmp; int ch, eof, fd; int error = 0; @@ -407,9 +404,9 @@ replace_cmd(void) return (-2); } if (snprintf(TempFilename, sizeof TempFilename, "%s/tmp.XXXXXXXXX", - CRON_SPOOL) >= sizeof(TempFilename)) { + _PATH_CRON_SPOOL) >= sizeof(TempFilename)) { TempFilename[0] = '\0'; - warnc(ENAMETOOLONG, "%s/tmp.XXXXXXXXX", CRON_SPOOL); + warnc(ENAMETOOLONG, "%s/tmp.XXXXXXXXX", _PATH_CRON_SPOOL); return (-2); } if (euid != pw->pw_uid) { @@ -505,8 +502,8 @@ replace_cmd(void) goto done; } - if (snprintf(n, sizeof n, "%s/%s", CRON_SPOOL, User) >= sizeof(n)) { - warnc(ENAMETOOLONG, "%s/%s", CRON_SPOOL, User); + if (snprintf(n, sizeof n, "%s/%s", _PATH_CRON_SPOOL, User) >= sizeof(n)) { + warnc(ENAMETOOLONG, "%s/%s", _PATH_CRON_SPOOL, User); error = -2; goto done; } @@ -518,7 +515,7 @@ replace_cmd(void) TempFilename[0] = '\0'; log_it(RealUser, "REPLACE", User); - poke_daemon(CRON_SPOOL, RELOAD_CRON); + poke_daemon(RELOAD_CRON); done: (void) signal(SIGHUP, SIG_DFL); diff --git a/usr.sbin/cron/database.c b/usr.sbin/cron/database.c index 332ead7ad1f..adf01e6e0f1 100644 --- a/usr.sbin/cron/database.c +++ b/usr.sbin/cron/database.c @@ -1,4 +1,4 @@ -/* $OpenBSD: database.c,v 1.31 2015/11/09 16:37:07 millert Exp $ */ +/* $OpenBSD: database.c,v 1.32 2015/11/12 21:12:05 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -38,9 +38,8 @@ #define HASH(a,b) ((a)+(b)) -static void process_crontab(const char *, const char *, - const char *, struct stat *, - cron_db *, cron_db *); +static void process_crontab(int, const char *, const char *, + struct stat *, cron_db *, cron_db *); void load_database(cron_db **db) @@ -51,18 +50,18 @@ load_database(cron_db **db) DIR *dir; user *u; - /* before we start loading any data, do a stat on CRON_SPOOL + /* before we start loading any data, do a stat on _PATH_CRON_SPOOL * so that if anything changes as of this moment (i.e., before we've * cached any of the database), we'll see the changes next time. */ - if (stat(CRON_SPOOL, &statbuf) < 0) { - log_it("CRON", "STAT FAILED", CRON_SPOOL); + if (stat(_PATH_CRON_SPOOL, &statbuf) < 0) { + log_it("CRON", "STAT FAILED", _PATH_CRON_SPOOL); return; } /* track system crontab file */ - if (stat(SYSCRONTAB, &syscron_stat) < 0) + if (stat(_PATH_SYS_CRONTAB, &syscron_stat) < 0) syscron_stat.st_mtime = 0; /* if spooldir's mtime has not changed, we don't need to fiddle with @@ -84,16 +83,16 @@ load_database(cron_db **db) TAILQ_INIT(&new_db->users); if (syscron_stat.st_mtime) { - process_crontab("root", NULL, SYSCRONTAB, &syscron_stat, - new_db, old_db); + process_crontab(AT_FDCWD, "*system*", _PATH_SYS_CRONTAB, + &syscron_stat, new_db, old_db); } /* we used to keep this dir open all the time, for the sake of * efficiency. however, we need to close it in every fork, and * we fork a lot more often than the mtime of the dir changes. */ - if (!(dir = opendir(CRON_SPOOL))) { - log_it("CRON", "OPENDIR FAILED", CRON_SPOOL); + if (!(dir = opendir(_PATH_CRON_SPOOL))) { + log_it("CRON", "OPENDIR FAILED", _PATH_CRON_SPOOL); /* Restore system crontab entry as needed. */ if (!TAILQ_EMPTY(&new_db->users) && (u = TAILQ_FIRST(&old_db->users))) { @@ -109,8 +108,6 @@ load_database(cron_db **db) } while (NULL != (dp = readdir(dir))) { - char fname[NAME_MAX+1], tabname[MAX_FNAME]; - /* avoid file names beginning with ".". this is good * because we would otherwise waste two guaranteed calls * to getpwnam() for . and .., and also because user names @@ -119,14 +116,7 @@ load_database(cron_db **db) if (dp->d_name[0] == '.') continue; - if (strlcpy(fname, dp->d_name, sizeof fname) >= sizeof fname) - continue; /* XXX log? */ - - if (snprintf(tabname, sizeof tabname, "%s/%s", CRON_SPOOL, fname) >= - sizeof(tabname)) - continue; /* XXX log? */ - - process_crontab(fname, fname, tabname, + process_crontab(dirfd(dir), dp->d_name, dp->d_name, &statbuf, new_db, old_db); } closedir(dir); @@ -167,53 +157,51 @@ find_user(cron_db *db, const char *name) } static void -process_crontab(const char *uname, const char *fname, const char *tabname, +process_crontab(int dfd, const char *uname, const char *fname, struct stat *statbuf, cron_db *new_db, cron_db *old_db) { struct passwd *pw = NULL; int crontab_fd = -1; user *u; - if (fname == NULL) { - /* must be set to something for logging purposes. - */ - fname = "*system*"; - } else if ((pw = getpwnam(uname)) == NULL) { + /* Note: pw must remain NULL for system crontab (see below). */ + if (fname[0] != '/' && (pw = getpwnam(uname)) == NULL) { /* file doesn't have a user in passwd file. */ - log_it(fname, "ORPHAN", "no passwd entry"); + log_it(uname, "ORPHAN", "no passwd entry"); goto next_crontab; } - if ((crontab_fd = open(tabname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) { + crontab_fd = openat(dfd, fname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW); + if (crontab_fd < 0) { /* crontab not accessible? */ - log_it(fname, "CAN'T OPEN", tabname); + log_it(uname, "CAN'T OPEN", fname); goto next_crontab; } if (fstat(crontab_fd, statbuf) < 0) { - log_it(fname, "FSTAT FAILED", tabname); + log_it(uname, "FSTAT FAILED", fname); goto next_crontab; } if (!S_ISREG(statbuf->st_mode)) { - log_it(fname, "NOT REGULAR", tabname); + log_it(uname, "NOT REGULAR", fname); goto next_crontab; } - if ((statbuf->st_mode & 07577) != 0400) { + if (pw != NULL) { /* Looser permissions on system crontab. */ - if (pw != NULL || (statbuf->st_mode & 022) != 0) { - log_it(fname, "BAD FILE MODE", tabname); + if ((statbuf->st_mode & 077) != 0) { + log_it(uname, "BAD FILE MODE", fname); goto next_crontab; } } if (statbuf->st_uid != 0 && (pw == NULL || statbuf->st_uid != pw->pw_uid || strcmp(uname, pw->pw_name) != 0)) { - log_it(fname, "WRONG FILE OWNER", tabname); + log_it(uname, "WRONG FILE OWNER", fname); goto next_crontab; } if (pw != NULL && statbuf->st_nlink != 1) { - log_it(fname, "BAD LINK COUNT", tabname); + log_it(uname, "BAD LINK COUNT", fname); goto next_crontab; } @@ -237,7 +225,7 @@ process_crontab(const char *uname, const char *fname, const char *tabname, */ TAILQ_REMOVE(&old_db->users, u, entries); free_user(u); - log_it(fname, "RELOAD", tabname); + log_it(uname, "RELOAD", fname); } u = load_user(crontab_fd, pw, fname); if (u != NULL) { diff --git a/usr.sbin/cron/funcs.h b/usr.sbin/cron/funcs.h index 82bb7c6833c..27222960200 100644 --- a/usr.sbin/cron/funcs.h +++ b/usr.sbin/cron/funcs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: funcs.h,v 1.26 2015/11/09 16:37:07 millert Exp $ */ +/* $OpenBSD: funcs.h,v 1.27 2015/11/12 21:12:05 millert Exp $ */ /* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -22,8 +22,7 @@ * We should reorg this into sections by module. */ -void set_cron_cwd(void), - load_database(cron_db **), +void load_database(cron_db **), job_add(entry *, user *), do_command(entry *, user *), free_user(user *), @@ -33,7 +32,7 @@ void set_cron_cwd(void), skip_comments(FILE *), log_it(const char *, const char *, const char *), log_close(void), - poke_daemon(const char *, unsigned char), + poke_daemon(unsigned char), atrun(at_db *, double, time_t); int job_runqueue(void), @@ -45,8 +44,6 @@ int job_runqueue(void), safe_p(const char *, const char *), scan_atjobs(at_db **, struct timespec *); -int strtot(const char *nptr, char **endptr, time_t *tp); - char *env_get(char *, char **), *first_word(char *, char *), **env_init(void), diff --git a/usr.sbin/cron/macros.h b/usr.sbin/cron/macros.h index 585f788096b..c1cc8f84a6f 100644 --- a/usr.sbin/cron/macros.h +++ b/usr.sbin/cron/macros.h @@ -1,4 +1,4 @@ -/* $OpenBSD: macros.h,v 1.14 2015/11/04 20:28:17 millert Exp $ */ +/* $OpenBSD: macros.h,v 1.15 2015/11/12 21:12:05 millert Exp $ */ /* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -24,7 +24,6 @@ #define READ_PIPE 0 /* which end of a pipe pair do you read? */ #define WRITE_PIPE 1 /* or write to? */ -#define MAX_FNAME 100 /* max length of internally generated fn */ #define MAX_COMMAND 1000 /* max length of internally generated cmd */ #define MAX_ENVSTR 1000 /* max length of envvar=value\0 strings */ #define MAX_TEMPSTR 100 /* obvious */ diff --git a/usr.sbin/cron/pathnames.h b/usr.sbin/cron/pathnames.h index 99d3a7efec1..b7454192e3f 100644 --- a/usr.sbin/cron/pathnames.h +++ b/usr.sbin/cron/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.21 2015/11/12 13:42:42 millert Exp $ */ +/* $OpenBSD: pathnames.h,v 1.22 2015/11/12 21:12:05 millert Exp $ */ /* Copyright 1993,1994 by Paul Vixie * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -22,56 +22,14 @@ #include <paths.h> - /* CRONDIR is where cron(8), crontab(1) and at(1) - * chdir to; CRON_SPOOL, CRON_ALLOW, CRON_DENY, - * AT_SPOOL, AT_ALLOW and AT_DENY are all relative - * to this directory. - */ -#define CRONDIR "/var/cron" - - /* SPOOLDIR is where the crontabs live. - * This directory will have its modtime updated - * whenever crontab(1) changes a crontab; this is - * the signal for cron(8) to look at each individual - * crontab file and reload those whose modtimes are - * newer than they were last time around (or which - * didn't exist last time around...) - */ -#define CRON_SPOOL "tabs" - - /* AT_SPOOL is where the at jobs live (relative to - * CRONDIR). This directory will have its modtime - * updated whenever at(1) changes a crontab; this is - * the signal for cron(8) to look for changes in the - * jobs directory (new, changed or jobs). - */ -#define AT_SPOOL "atjobs" - - /* CRONSOCK is the name of the socket used by at and - * crontab to poke cron to re-read the at and cron - * spool files while cron is asleep. - */ -#define CRONSOCK "/var/run/cron.sock" -#define CRONSOCK_OLD CRON_SPOOL "/.sock" - - /* cron allow/deny file. At least cron.deny must - * exist for ordinary users to run crontab. - */ -#define CRON_ALLOW "cron.allow" -#define CRON_DENY "cron.deny" - - /* at allow/deny file. At least at.deny must - * exist for ordinary users to run at. - */ -#define AT_ALLOW "at.allow" -#define AT_DENY "at.deny" - - /* 4.3BSD-style crontab */ -#define SYSCRONTAB "/etc/crontab" - - /* what editor to use if no EDITOR or VISUAL - * environment variable specified. - */ -#define EDITOR _PATH_VI +#define _PATH_AT_ALLOW "/var/cron/at.allow" +#define _PATH_AT_DENY "/var/cron/at.deny" +#define _PATH_AT_SPOOL "/var/cron/atjobs" +#define _PATH_CRON_ALLOW "/var/cron/cron.allow" +#define _PATH_CRON_DENY "/var/cron/cron.deny" +#define _PATH_CRON_SOCK "/var/run/cron.sock" +#define _PATH_CRON_SOCK_OLD "/var/cron/tabs/.sock" +#define _PATH_CRON_SPOOL "/var/cron/tabs" +#define _PATH_SYS_CRONTAB "/etc/crontab" #endif /* _PATHNAMES_H_ */ |