-/* $OpenBSD: at.c,v 1.79 2017/03/18 02:58:54 deraadt Exp $ */
+/* $OpenBSD: at.c,v 1.80 2017/06/07 23:36:43 millert Exp $ */
/*
* at.c : Put file into atrun queue
if ((fd = newjob(runtimer, queue)) == -1)
fatal("unable to create atjob file");
- if (fchown(fd, -1, user_gid) != 0)
- fatal("fchown");
-
/*
* We've successfully created the file; let's set the flag so it
* gets removed in case of an interrupt or error.
}
(void)fprintf(fp, "#!/bin/sh\n# atrun uid=%lu gid=%lu\n# mail %*s %d\n",
- (unsigned long)user_uid, (unsigned long)user_gid,
+ (unsigned long)user_uid, (unsigned long)spool_gid,
MAX_UNAME, mailname, send_mail);
/* Write out the umask at the time of invocation */
-/* $OpenBSD: atrun.c,v 1.44 2017/06/07 17:59:36 millert Exp $ */
+/* $OpenBSD: atrun.c,v 1.45 2017/06/07 23:36:43 millert Exp $ */
/*
* Copyright (c) 2002-2003 Todd C. Miller <Todd.Miller@courtesan.com>
atfile);
_exit(EXIT_FAILURE);
}
+ if (sb.st_gid != cron_gid) {
+ syslog(LOG_WARNING, "(%s) WRONG FILE GROUP (%s)", pw->pw_name,
+ atfile);
+ _exit(EXIT_FAILURE);
+ }
if (sb.st_nlink > 1) {
syslog(LOG_WARNING, "(%s) BAD LINK COUNT (%s)", pw->pw_name,
atfile);
-/* $OpenBSD: cron.c,v 1.75 2017/06/05 01:42:45 millert Exp $ */
+/* $OpenBSD: cron.c,v 1.76 2017/06/07 23:36:43 millert Exp $ */
/* Copyright 1988,1990,1993,1994 by Paul Vixie
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
static double batch_maxload = BATCH_MAXLOAD;
static int NoFork;
static time_t StartTime;
+ gid_t cron_gid;
static void
usage(void)
{
struct sigaction sact;
sigset_t blocked, omask;
+ struct group *grp;
setlocale(LC_ALL, "");
exit(EXIT_FAILURE);
}
+ if ((grp = getgrnam(CRON_GROUP)) == NULL) {
+ warnx("can't find cron group %s", CRON_GROUP);
+ syslog(LOG_ERR, "(CRON) DEATH (can't find cron group)");
+ exit(EXIT_FAILURE);
+ }
+ cron_gid = grp->gr_gid;
+
cronSock = open_socket();
if (putenv("PATH="_PATH_DEFPATH) < 0) {
{
int sock, rc;
mode_t omask;
- struct group *grp;
struct sockaddr_un s_un;
- if ((grp = getgrnam(CRON_GROUP)) == NULL)
- syslog(LOG_WARNING, "(CRON) STARTUP (can't find cron group)");
-
sock = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (sock == -1) {
warn("socket");
syslog(LOG_ERR, "(CRON) DEATH (can't listen on socket)");
exit(EXIT_FAILURE);
}
- 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());
- }
+
+ /* pledge won't let us change files to a foreign group. */
+ if (setegid(cron_gid) == 0) {
+ chown(s_un.sun_path, -1, cron_gid);
+ (void)setegid(getgid());
}
chmod(s_un.sun_path, 0660);
-/* $OpenBSD: database.c,v 1.34 2016/01/11 14:23:50 millert Exp $ */
+/* $OpenBSD: database.c,v 1.35 2017/06/07 23:36:43 millert Exp $ */
/* Copyright 1988,1990,1993,1994 by Paul Vixie
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
#include <unistd.h>
#include "pathnames.h"
+#include "globals.h"
#include "macros.h"
#include "structs.h"
#include "funcs.h"
{
struct passwd *pw = NULL;
int crontab_fd = -1;
- user *u;
+ user *u, *new_u;
+ mode_t tabmask, tabperm;
/* Note: pw must remain NULL for system crontab (see below). */
if (fname[0] != '/' && (pw = getpwnam(uname)) == NULL) {
syslog(LOG_WARNING, "(%s) NOT REGULAR (%s)", uname, fname);
goto next_crontab;
}
- if (pw != NULL) {
- /* Looser permissions on system crontab. */
- if ((statbuf->st_mode & 077) != 0) {
- syslog(LOG_WARNING, "(%s) BAD FILE MODE (%s)",
- uname, fname);
- goto next_crontab;
- }
+ /* Looser permissions on system crontab. */
+ tabmask = pw ? ALLPERMS : (ALLPERMS & ~(S_IWUSR|S_IRGRP|S_IROTH));
+ tabperm = pw ? (S_IRUSR|S_IWUSR) : S_IRUSR;
+ if ((statbuf->st_mode & tabmask) != tabperm) {
+ syslog(LOG_WARNING, "(%s) BAD FILE MODE (%s)", uname, fname);
+ goto next_crontab;
}
if (statbuf->st_uid != 0 && (pw == NULL ||
statbuf->st_uid != pw->pw_uid || strcmp(uname, pw->pw_name) != 0)) {
syslog(LOG_WARNING, "(%s) WRONG FILE OWNER (%s)", uname, fname);
goto next_crontab;
}
+ if (pw != NULL && statbuf->st_gid != cron_gid) {
+ syslog(LOG_WARNING, "(%s) WRONG FILE GROUP (%s)", uname, fname);
+ goto next_crontab;
+ }
if (pw != NULL && statbuf->st_nlink != 1) {
syslog(LOG_WARNING, "(%s) BAD LINK COUNT (%s)", uname, fname);
goto next_crontab;
TAILQ_INSERT_TAIL(&new_db->users, u, entries);
goto next_crontab;
}
-
- /* before we fall through to the code that will reload
- * the user, let's deallocate and unlink the user in
- * the old database. This is more a point of memory
- * efficiency than anything else, since all leftover
- * users will be deleted from the old database when
- * we finish with the crontab...
- */
- TAILQ_REMOVE(&old_db->users, u, entries);
- free_user(u);
syslog(LOG_INFO, "(%s) RELOAD (%s)", uname, fname);
}
- u = load_user(crontab_fd, pw, fname);
- if (u != NULL) {
- u->mtime = statbuf->st_mtim;
+
+ new_u = load_user(crontab_fd, pw, fname);
+ if (new_u != NULL) {
+ /* Insert user into the new database and remove from old. */
+ new_u->mtime = statbuf->st_mtim;
+ TAILQ_INSERT_TAIL(&new_db->users, new_u, entries);
+ if (u != NULL) {
+ TAILQ_REMOVE(&old_db->users, u, entries);
+ free_user(u);
+ }
+ } else if (u != NULL) {
+ /* New user crontab failed to load, preserve the old one. */
+ TAILQ_REMOVE(&old_db->users, u, entries);
TAILQ_INSERT_TAIL(&new_db->users, u, entries);
}
-/* $OpenBSD: env.c,v 1.32 2015/11/04 20:28:17 millert Exp $ */
+/* $OpenBSD: env.c,v 1.33 2017/06/07 23:36:43 millert Exp $ */
/* Copyright 1988,1990,1993,1994 by Paul Vixie
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
break;
}
}
- if (state != FINI && !(state == VALUE && !quotechar)) {
- fseek(f, filepos, SEEK_SET);
- Set_LineNum(fileline);
- return (FALSE);
- }
+ if (state != FINI && !(state == VALUE && !quotechar))
+ goto not_env;
if (state == VALUE) {
/* End of unquoted value: trim trailing whitespace */
c = val + strlen(val);
* name and val fields. Still, it doesn't hurt to be careful...
*/
if (snprintf(envstr, MAX_ENVSTR, "%s=%s", name, val) >= MAX_ENVSTR)
- return (FALSE);
+ goto not_env;
return (TRUE);
+ not_env:
+ fseek(f, filepos, SEEK_SET);
+ Set_LineNum(fileline);
+ return (FALSE);
}
-/* $OpenBSD: globals.h,v 1.13 2015/11/06 23:47:42 millert Exp $ */
+/* $OpenBSD: globals.h,v 1.14 2017/06/07 23:36:43 millert Exp $ */
/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+extern gid_t cron_gid;
extern int LineNumber;
extern char *__progname;
-/* $OpenBSD: user.c,v 1.19 2016/08/30 14:08:16 millert Exp $ */
+/* $OpenBSD: user.c,v 1.20 2017/06/07 23:36:43 millert Exp $ */
/* Copyright 1988,1990,1993,1994 by Paul Vixie
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
#include "macros.h"
#include "structs.h"
#include "funcs.h"
+#include "globals.h"
void
free_user(user *u)
free(u);
}
+static int ParseErrorCount;
+static const char *CrontabFilename;
+
+static void
+parse_error(const char *msg)
+{
+ ParseErrorCount++;
+ syslog(LOG_ERR, "(CRON) %s:%d (%s)", CrontabFilename, LineNumber, msg);
+}
+
user *
load_user(int crontab_fd, struct passwd *pw, const char *name)
{
char **envp = NULL, **tenvp;
if (!(file = fdopen(crontab_fd, "r"))) {
- syslog(LOG_ERR, "(%s) FDOPEN (%m)", pw->pw_name);
+ syslog(LOG_ERR, "(%s) FDOPEN (%m)", name);
return (NULL);
}
+ CrontabFilename = name;
+ LineNumber = 0;
/* file is open. build user entry, then read the crontab file.
*/
/* load the crontab
*/
+ ParseErrorCount = 0;
while ((status = load_env(envstr, file)) >= 0) {
switch (status) {
case FALSE:
/* Not an env variable, parse as crontab entry. */
- e = load_entry(file, NULL, pw, envp);
- if (e)
+ e = load_entry(file, parse_error, pw, envp);
+ if (e == NULL) {
+ /* Parse error, ignore for non-root entries */
+ if (pw != NULL) {
+ save_errno = errno;
+ free_user(u);
+ u = NULL;
+ errno = save_errno;
+ goto done;
+ }
+ } else {
SLIST_INSERT_HEAD(&u->crontab, e, entries);
+ }
break;
case TRUE:
if ((tenvp = env_set(envp, envstr)) == NULL) {