summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2015-11-12 21:12:06 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2015-11-12 21:12:06 +0000
commit8bcf8c8455a4408e205eba1acbf21a4428d3192c (patch)
tree13a479f6705664ec825a6ec1f690df9c499a5a8d
parent258b48ab5f61b14c05f456acc16073292ce3670e (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/Makefile4
-rw-r--r--usr.bin/at/at.c45
-rw-r--r--usr.bin/crontab/Makefile4
-rw-r--r--usr.sbin/cron/Makefile4
-rw-r--r--usr.sbin/cron/atrun.c37
-rw-r--r--usr.sbin/cron/client.c10
-rw-r--r--usr.sbin/cron/common.c136
-rw-r--r--usr.sbin/cron/cron.c23
-rw-r--r--usr.sbin/cron/crontab.c45
-rw-r--r--usr.sbin/cron/database.c66
-rw-r--r--usr.sbin/cron/funcs.h9
-rw-r--r--usr.sbin/cron/macros.h3
-rw-r--r--usr.sbin/cron/pathnames.h62
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_ */