Hello community, here is the log from the commit of package cronie for openSUSE:Factory checked in at 2019-11-07 23:15:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cronie (Old) and /work/SRC/openSUSE:Factory/.cronie.new.2990 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cronie" Thu Nov 7 23:15:10 2019 rev:75 rq:745503 version:unknown Changes: -------- --- /work/SRC/openSUSE:Factory/cronie/cronie.changes 2019-09-07 11:25:23.930495189 +0200 +++ /work/SRC/openSUSE:Factory/.cronie.new.2990/cronie.changes 2019-11-07 23:15:11.996447597 +0100 @@ -1,0 +2,26 @@ +Fri Nov 1 17:10:22 UTC 2019 - Kristyna Streitova <[email protected]> + +- update to 1.5.5 + * Avoid warning for strncat. + * crontab: fsync to check for full disk + * crontab: Add Y/N to retry prompt + * entries: Explicitly validate upper ranges and steps + * crond: report missing newline before EOF + * do not log carriage return + * skip directories when given as crontabs + * crontab -l colors comment lines in a different color + * getdtablesize() can return very high values in containers + * Power supply name not detected correctly. + * Revert "Avoid creating pid files when crond doesn't fork" + * anacron: fix types in comparisons + * mics: stop using plain integer as NULL pointer + * cron: fix type in comparison and variable shadowing + * cron: mark signal number arguments in signal handlers unused + * Move allowed() and related function to security.c + * cronnext: optionally select jobs by substring + * crond: Do not abort loading crontab prematurely in case of error +- refresh cronie-nheader_lines.diff +- remove cronie-1.5.4-dont_abort_loading_crontab.patch and + cronie-1.5.4-always_create_pid_file.patch (applied upstream) + +------------------------------------------------------------------- Old: ---- cronie-1.5.4-always_create_pid_file.patch cronie-1.5.4-dont_abort_loading_crontab.patch cronie-1.5.4.tar.gz New: ---- cronie-1.5.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cronie.spec ++++++ --- /var/tmp/diff_new_pack.iTVJmd/_old 2019-11-07 23:15:13.056448758 +0100 +++ /var/tmp/diff_new_pack.iTVJmd/_new 2019-11-07 23:15:13.056448758 +0100 @@ -23,7 +23,7 @@ %define cron_configs %{_sysconfdir}/pam.d/crond %{_sysconfdir}/crontab %{_sysconfdir}/cron.deny Name: cronie -Version: 1.5.4 +Version: 1.5.5 Release: 0 Summary: Cron Daemon License: BSD-3-Clause AND GPL-2.0-only AND MIT @@ -51,8 +51,6 @@ # PATCH-FIX-SUSE the first occurance of "/etc/anacrontab" was replaced by "/etc/crontab" # in manpage file because the /etc/crontab is still used in SUSE. Patch13: fix-manpage-replace-anacrontab-with-crontab.patch -Patch14: cronie-1.5.4-dont_abort_loading_crontab.patch -Patch15: cronie-1.5.4-always_create_pid_file.patch BuildRequires: audit-devel BuildRequires: autoconf BuildRequires: automake @@ -113,8 +111,6 @@ cp %{SOURCE7} ./cron_to_cronie.README %patch12 -p1 %patch13 -p1 -%patch14 -p1 -%patch15 -p1 %build # fill macro CRON_VERSION it is used in top three lines of crontab file,should be reworked ++++++ cronie-1.5.4.tar.gz -> cronie-1.5.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/.gitignore new/cronie-cronie-1.5.5/.gitignore --- old/cronie-cronie-1.5.4/.gitignore 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/.gitignore 2019-10-31 17:33:33.000000000 +0100 @@ -1,7 +1,7 @@ Makefile.in Makefile anacron/anacron -anacron/anacron-paths.h +anacron-paths.h anacron/Makefile anacron/Makefile.in aclocal.m4 @@ -26,8 +26,9 @@ src/crond src/crontab src/cronnext -src/cron-paths.h +cron-paths.h *~ *.tar.* *.orig *.patch +.dirstamp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/ChangeLog new/cronie-cronie-1.5.5/ChangeLog --- old/cronie-cronie-1.5.4/ChangeLog 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/ChangeLog 2019-10-31 17:33:33.000000000 +0100 @@ -1,3 +1,107 @@ +2019-10-31 Tomas Mraz <[email protected]> + + * Release new version 1.5.5 + +2019-10-31 Tomas Mraz <[email protected]> + + * Avoid warning for strncat. + +2019-10-29 Christian Kastner <[email protected]> + + * crontab.1: Various fixes and improvements + +2019-10-30 Christian Kastner <[email protected]> + + * crontab: fsync to check for full disk + +2019-10-30 Christian Kastner <[email protected]> + + * crontab: Add Y/N to retry prompt + +2019-10-30 Christian Kastner <[email protected]> + + * entries: Explicitly validate upper ranges and steps + +2019-10-29 Christian Kastner <[email protected]> + + * crond: report missing newline before EOF + +2019-09-09 Christian Hesse <[email protected]> + + * do not log carriage return + +2019-08-22 sgerwk <[email protected]> + + * skip directories when given as crontabs + +2019-07-22 Stephane Blondon <[email protected]> + + * crontab -l colors comment lines in a different color + +2019-07-09 sgerwk <[email protected]> + + * fix compile instruction: configure is generated by autogen.sh + +2019-07-08 Tomas Mraz <[email protected]> + + * getdtablesize() can return very high values in containers + +2019-05-11 John Horne <[email protected]> + + * Power supply name not detected correctly. + +2019-05-07 Tomas Mraz <[email protected]> + + * Revert "Avoid creating pid files when crond doesn't fork" + +2019-04-15 Tomas Mraz <[email protected]> + + * anacron: fix types in comparisons + +2019-03-31 Sami Kerola <[email protected]> + + * mics: stop using plain integer as NULL pointer + +2019-03-31 Sami Kerola <[email protected]> + + * cron: fix type in comparison + +2019-03-31 Sami Kerola <[email protected]> + + * cron: fix variable shadowing + +2019-03-31 Sami Kerola <[email protected]> + + * cron: mark signal number arguments in signal handlers unused + +2019-04-08 Tomáš Mráz <[email protected]> + + * Update readme.md with recent releases + +2019-04-08 Tomas Mraz <[email protected]> + + * Move allowed() and related function to security.c + +2019-03-31 Sami Kerola <[email protected]> + + * build-sys: enable anacron by default + +2019-03-31 Sami Kerola <[email protected]> + + * build-sys: use none-recursive build + +2019-04-02 sgerwk <[email protected]> + + * cronnext: optionally select jobs by substring + +2019-03-18 Tomas Mraz <[email protected]> + + * crond: Do not abort loading crontab prematurely in case of error + +2019-03-18 Tomas Mraz <[email protected]> + + * Release new version 1.5.4 + 2019-03-18 Tomas Mraz <[email protected]> * crond: Fix regression from last release diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/INSTALL new/cronie-cronie-1.5.5/INSTALL --- old/cronie-cronie-1.5.4/INSTALL 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/INSTALL 2019-10-31 17:33:33.000000000 +0100 @@ -6,6 +6,9 @@ make make install +If no "configure" script is present, generate it by: +./autogen.sh + The executable files will be installed in /usr/local/* by default. Configure Options diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/Makefile.am new/cronie-cronie-1.5.5/Makefile.am --- old/cronie-cronie-1.5.4/Makefile.am 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/Makefile.am 2019-10-31 17:33:33.000000000 +0100 @@ -1,9 +1,18 @@ -SUBDIRS = src man anacron +AM_CFLAGS = -I$(top_srcdir) + +BUILT_SOURCES = +CLEANFILES = +EXTRA_DIST = +bin_PROGRAMS = +common_nodist = +sbin_PROGRAMS = dist_noinst_HEADERS = \ cronie_common.h -EXTRA_DIST = \ +EXTRA_DIST += \ + README.anacron \ + COPYING.anacron \ cronie.init \ crond.sysconfig \ contrib/anacrontab \ @@ -19,3 +28,7 @@ else EXTRA_DIST += pam/crond endif + +include anacron/Makemodule.am +include man/Makemodule.am +include src/Makemodule.am diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/NEWS new/cronie-cronie-1.5.5/NEWS --- old/cronie-cronie-1.5.4/NEWS 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/NEWS 2019-10-31 17:33:33.000000000 +0100 @@ -1,10 +1,24 @@ cronie NEWS -- history of user-visible changes. +Release 1.5.5 + +* Explicitly validate upper end of range and step to disallow entries + such as: 1-234/5678 * * * * .... +* crond: Report missing newline before EOF in syslog so the line is not + completely silently ignored. +* crontab -l colors comment lines in a different color. +* crond: Revert "Avoid creating pid files when crond doesn't fork". +* anacron is built by default. +* Use non-recursive build. +* cronnext: Allow to optionally select jobs by substring. + Release 1.5.4 + * crond: Fix regression from previous release. Only first job from a crontab was being run. Release 1.5.3 + * Fix CVE-2019-9704 and CVE-2019-9705 to avoid local DoS of the crond. * crontab: Make crontab without arguments fail. * crond: In PAM configuration include system-auth instead of password-auth. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/README new/cronie-cronie-1.5.5/README --- old/cronie-cronie-1.5.4/README 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/README 2019-10-31 17:33:33.000000000 +0100 @@ -1,11 +1,13 @@ -17. January 2008 mmaslano (at) redhat (dot) com -Rename the fork on cronie. The source code could be found here: -http://mmaslano.fedorapeople.org/cronie/ or git archive here: -git://git.fedorahosted.org/git/cronie.git +Cronie contains the standard UNIX daemon crond that runs specified programs at +scheduled times and related tools. The source is based on the original vixie-cron +and has security and configuration enhancements like the ability to use pam and +SELinux. -3. October 2007 mmaslano (at) redhat (dot) com -This is a clone of 'original' vixie-cron. It was used in Red Hat|Fedora -system and patched for a long time. Now was made clone tagged with -version 4.2. -Changes are mainly in git commit messages, some older changes could be -found in spec changelog (contrib/vixie-cron.spec). +And why cronie? See http://www.urbandictionary.com/define.php?term=cronie + +Contact +------- + +Mailing list: `cronie-devel AT lists.fedorahosted DOT org` + +Bug reports and pull requests can be filled at the Github site. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/anacron/Makefile.am new/cronie-cronie-1.5.5/anacron/Makefile.am --- old/cronie-cronie-1.5.4/anacron/Makefile.am 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/anacron/Makefile.am 1970-01-01 01:00:00.000000000 +0100 @@ -1,31 +0,0 @@ -# Makefile.am - two binaries crond and crontab -if ANACRON -sbin_PROGRAMS = anacron -endif - -anacron_SOURCES = \ - gregor.c lock.c log.c main.c matchrx.c readtab.c runjob.c \ - $(common_src) -common_src = global.h gregor.h matchrx.h -common_nodist = anacron-paths.h -nodist_anacron_SOURCES = $(common_nodist) -BUILT_SOURCES = $(common_nodist) - -AM_CFLAGS = -I$(top_srcdir) - -LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT) - -# This header contains all the paths. -# If they are configurable, they are declared in configure script. -# Depends on this Makefile, because it uses make variables. -anacron-paths.h: Makefile - @echo 'creating $@' - @sed >$@ 's/ *\\$$//' <<\END #\ - /* This file has been automatically generated. Do not edit. */ \ - \ - #ifndef _ANACRON_PATHS_H_ \ - #define _ANACRON_PATHS_H_ \ - #define ANACRON_SPOOL_DIR "$(ANACRON_SPOOL_DIR)" \ - #define ANACRONTAB "$(ANACRONTAB)" \ - #endif /* _ANACRON_PATHS_H_ */ \ - END diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/anacron/Makemodule.am new/cronie-cronie-1.5.5/anacron/Makemodule.am --- old/cronie-cronie-1.5.4/anacron/Makemodule.am 1970-01-01 01:00:00.000000000 +0100 +++ new/cronie-cronie-1.5.5/anacron/Makemodule.am 2019-10-31 17:33:33.000000000 +0100 @@ -0,0 +1,37 @@ +# Makefile.am - two binaries crond and crontab +if ANACRON +sbin_PROGRAMS += anacron/anacron +anacron_anacron_SOURCES = \ + anacron-paths.h \ + anacron/global.h \ + anacron/gregor.c \ + anacron/gregor.h \ + anacron/lock.c \ + anacron/log.c \ + anacron/main.c \ + anacron/matchrx.c \ + anacron/matchrx.h \ + anacron/readtab.c \ + anacron/runjob.c +common_nodist += anacron-paths.h +nodist_anacron_anacron_SOURCES = $(common_nodist) +BUILT_SOURCES += $(common_nodist) + +anacron_anacron_LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT) + +# This header contains all the paths. +# If they are configurable, they are declared in configure script. +# Depends on this Makefile, because it uses make variables. +CLEANFILES += anacron-paths.h +anacron-paths.h: Makefile + @echo 'creating $@' + @sed >$@ 's/ *\\$$//' <<\END #\ + /* This file has been automatically generated. Do not edit. */ \ + \ + #ifndef _ANACRON_PATHS_H_ \ + #define _ANACRON_PATHS_H_ \ + #define ANACRON_SPOOL_DIR "$(ANACRON_SPOOL_DIR)" \ + #define ANACRONTAB "$(ANACRONTAB)" \ + #endif /* _ANACRON_PATHS_H_ */ \ + END +endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/anacron/log.c new/cronie-cronie-1.5.5/anacron/log.c --- old/cronie-cronie-1.5.4/anacron/log.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/anacron/log.c 2019-10-31 17:33:33.000000000 +0100 @@ -79,7 +79,12 @@ /* There's some confusion in the documentation about what vsnprintf * returns when the buffer overflows. Hmmm... */ len = vsnprintf(msg, sizeof(msg), fmt, args); - if (len >= sizeof(msg) - 1) + if (len < 0) { + strncpy(msg, "(vsnprintf failed)", sizeof(msg)); + msg[sizeof(msg) - 1] = '\0'; + return; + } + if ((size_t) len >= sizeof(msg) - 1) strcpy(msg + sizeof(msg) - sizeof(truncated), truncated); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/anacron/matchrx.c new/cronie-cronie-1.5.5/anacron/matchrx.c --- old/cronie-cronie-1.5.4/anacron/matchrx.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/anacron/matchrx.c 2019-10-31 17:33:33.000000000 +0100 @@ -42,11 +42,13 @@ * This is not the most efficient, or elegant way of doing this. */ { - int r, n; + int r; + unsigned int n; regex_t crx; va_list va; char **substring; regmatch_t *sub_offsets; + sub_offsets = malloc(sizeof(regmatch_t) * (n_sub + 1)); if (sub_offsets == NULL) return -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/anacron/runjob.c new/cronie-cronie-1.5.5/anacron/runjob.c --- old/cronie-cronie-1.5.4/anacron/runjob.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/anacron/runjob.c 2019-10-31 17:33:33.000000000 +0100 @@ -53,7 +53,9 @@ dir = P_tmpdir; len = snprintf(template, sizeof(template), "%s/$anacronXXXXXX", dir); - if (len >= sizeof(template)) + if (len < 0) + die_e("snprintf failed"); + else if ((size_t) len >= sizeof(template)) die_e("TMPDIR too long"); fdout = mkstemp(template); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/configure.ac new/cronie-cronie-1.5.5/configure.ac --- old/cronie-cronie-1.5.4/configure.ac 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/configure.ac 2019-10-31 17:33:33.000000000 +0100 @@ -1,8 +1,8 @@ -AC_INIT([cronie],[1.5.4],[[email protected],[email protected]]) +AC_INIT([cronie],[1.5.5],[[email protected],[email protected]]) AC_CONFIG_HEADER([config.h]) AC_PREREQ(2.60) -AM_INIT_AUTOMAKE +AM_INIT_AUTOMAKE([subdir-objects]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [AC_SUBST([AM_DEFAULT_VERBOSITY], [1])]) @@ -253,13 +253,13 @@ CRONIE_CONF_VAR([SYS_CROND_DIR], [the current working directory of the running daemon], [${sysconfdir}/cron.d]) CRONIE_CONF_VAR([SPOOL_DIR], [the directory where all the user cron tabs reside], [${localstatedir}/spool/cron]) -AC_ARG_ENABLE([anacron], [AS_HELP_STRING([--enable-anacron], [Build also anacron.])]) +AC_ARG_ENABLE([anacron], [AS_HELP_STRING([--disable-anacron], [Do not build anacron.])], [], [enable_anacron=yes]) AM_CONDITIONAL([ANACRON], [test "$enable_anacron" = yes]) if test "$enable_anacron" != no; then ANACRON_CONF_VAR([ANACRON_SPOOL_DIR],[The path for anacron locks.],[${localstatedir}/spool/anacron]) ANACRON_CONF_VAR([ANACRONTAB],[The anacron table for regular jobs.],[${sysconfdir}/anacrontab]) fi -AC_CONFIG_FILES([Makefile src/Makefile man/Makefile anacron/Makefile]) +AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/contrib/0anacron new/cronie-cronie-1.5.5/contrib/0anacron --- old/cronie-cronie-1.5.4/contrib/0anacron 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/contrib/0anacron 2019-10-31 17:33:33.000000000 +0100 @@ -9,7 +9,7 @@ # Do not run jobs when on battery power online=1 -for psupply in AC ADP0 ; do +for psupply in AC ADP{0..9} ; do sysfile="/sys/class/power_supply/$psupply/online" if [ -f $sysfile ] ; then diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/man/Makefile.am new/cronie-cronie-1.5.5/man/Makefile.am --- old/cronie-cronie-1.5.4/man/Makefile.am 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/man/Makefile.am 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +0,0 @@ -dist_man_MANS = crontab.1 crontab.5 cron.8 crond.8 cronnext.1 -EXTRA_DIST = anacrontab.5 anacron.8 - -if ANACRON -dist_man_MANS += $(EXTRA_DIST) -endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/man/Makemodule.am new/cronie-cronie-1.5.5/man/Makemodule.am --- old/cronie-cronie-1.5.4/man/Makemodule.am 1970-01-01 01:00:00.000000000 +0100 +++ new/cronie-cronie-1.5.5/man/Makemodule.am 2019-10-31 17:33:33.000000000 +0100 @@ -0,0 +1,16 @@ +dist_man_MANS = \ + man/cron.8 \ + man/crond.8 \ + man/cronnext.1 \ + man/crontab.1 \ + man/crontab.5 + +anacron_man = \ + man/anacrontab.5 \ + man/anacron.8 + +EXTRA_DIST += $(anacron_man) + +if ANACRON +dist_man_MANS += $(anacron_man) +endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/man/cronnext.1 new/cronie-cronie-1.5.5/man/cronnext.1 --- old/cronie-cronie-1.5.4/man/cronnext.1 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/man/cronnext.1 2019-10-31 17:33:33.000000000 +0100 @@ -6,7 +6,7 @@ .B cronnext [\fB-i \fIusers\fR] [\fB-e \fIusers\fR] [\fB-s\fR] [\fB-a\fR] -[\fB-t \fItime\fR] [\fB-q \fItime\fR] +[\fB-t \fItime\fR] [\fB-q \fItime\fR] [\fB-j \fIcommand\fR] [\fB-l\fR] [\fB-c\fR] [\fB-f\fR] [\fB-h\fR] [\fB-V\fR] [file]... .SH DESCRIPTION @@ -52,6 +52,9 @@ Do not check jobs over this time, expressed in the same way as in option .BR -t . .TP +.BI "\-j " command +Only look for jobs that contain \fIcommand\fP as a substring. +.TP .B \-l Print the whole entries of the jobs that are the next to be executed by cron. The default is to only print their next time of execution. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/man/crontab.1 new/cronie-cronie-1.5.5/man/crontab.1 --- old/cronie-cronie-1.5.4/man/crontab.1 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/man/crontab.1 2019-10-31 17:33:33.000000000 +0100 @@ -22,7 +22,7 @@ .\" .\" $Id: crontab.1,v 1.7 2004/01/23 19:03:32 vixie Exp $ .\" -.TH CRONTAB 1 "2012-11-22" "cronie" "User Commands" +.TH CRONTAB 1 "2019-10-29" "cronie" "User Commands" .SH NAME crontab \- maintains crontab files for individual users .SH SYNOPSIS @@ -67,18 +67,21 @@ across a cluster of hosts and specify that only one of the hosts should run the crontab jobs in the particular directory at any one time. You may also use -.BR crontab (1) +.BR crontab from any of these hosts to edit the same shared set of crontab files, and to set and query which host should run the crontab jobs. .PP -Running cron jobs can be allowed or disallowed for different users. For -this purpose, use the +Scheduling cron jobs with +.BR crontab +can be allowed or disallowed for different users. For this purpose, use the .I cron.allow and .I cron.deny files. If the .I cron.allow -file exists, a user must be listed in it to be allowed to use cron If the +file exists, a user must be listed in it to be allowed to use +.BR crontab . +If the .I cron.allow file does not exist but the .I cron.deny @@ -86,12 +89,17 @@ .I not be listed in the .I cron.deny -file in order to use cron. If neither of these files exists, only the -super user is allowed to use cron. Another way to restrict access to -cron is to use PAM authentication in +file in order to use +.BR crontab. +If neither of these files exist, then only the super user is allowed to use +.BR crontab . +.PP +Another way to restrict the scheduling of cron jobs beyond +.BR crontab +is to use PAM authentication in .I /etc/security/access.conf to set up users, which are allowed or disallowed to use -.I crontab +.BR crontab or modify system cron jobs in the .IR /etc/cron.d/ directory. @@ -106,12 +114,12 @@ .B "\-u" Specifies the name of the user whose crontab is to be modified. If this option is not used, -.I crontab +.BR crontab examines "your" crontab, i.e., the crontab of the person executing the command. If no crontab exists for a particular user, it is created for -him the first time the +them the first time the .B crontab -u -command is used under his username. +command is used under their username. .TP .B "\-l" Displays the current crontab on standard output. @@ -178,6 +186,27 @@ .TP .B "\-V" Print version and exit. +.SH CAVEATS +The files +.I cron.allow +and +.I cron.deny +cannot be used to restrict the execution of cron jobs; they only restrict the +use of +.BR crontab . +In particular, restricting access to +.BR crontab +has no effect on an existing +.I crontab +of a user. Its jobs will continue to be executed until the crontab is removed. +.PP +The files +.I cron.allow +and +.I cron.deny +must be readable by the user invoking +.BR crontab . +If this is not the case, then they are treated as non-existent. .SH "SEE ALSO" .BR crontab (5), .BR cron (8) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/man/crontab.5 new/cronie-cronie-1.5.5/man/crontab.5 --- old/cronie-cronie-1.5.4/man/crontab.5 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/man/crontab.5 2019-10-31 17:33:33.000000000 +0100 @@ -326,6 +326,11 @@ in the symlinked crontabs are not automatically noticed by the cron daemon. The cron daemon must receive a SIGHUP signal to reload the crontabs. This is a limitation of the inotify API. +.PP +cron requires that each entry in a crontab end in a newline character. If the +last entry in a crontab is missing a newline (i.e.\& terminated by EOF), +cron will consider the crontab (at least partially) broken. +A warning will be written to syslog. .SH AUTHOR .MT [email protected] Paul Vixie diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/readme.md new/cronie-cronie-1.5.5/readme.md --- old/cronie-cronie-1.5.4/readme.md 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/readme.md 2019-10-31 17:33:33.000000000 +0100 @@ -1,20 +1,38 @@ # Cronie Cronie contains the standard UNIX daemon crond that runs specified programs at -scheduled times and related tools. It is based on the original cron and -has security and configuration enhancements like the ability to use pam and +scheduled times and related tools. The source is based on the original vixie-cron +and has security and configuration enhancements like the ability to use pam and SELinux. And why cronie? [http://www.urbandictionary.com/define.php?term=cronie] # Download -Latest released version is 1.5.2. +Latest released version is 1.5.5. User visible changes: -- crontab: Use temporary file name that is ignored by crond. -- crond: Inherit PATH from the crond environment if -P option is used. -- crond: Remove hardcoded "system_u" SELinux user, use the SELinux user of the running crond. -- anacron: Small cleanups and fixes. -- crond: Fix longstanding race condition on repeated crontab modification. + +Release 1.5.5 +- Explicitly validate upper end of range and step to disallow entries + such as: 1-234/5678 * * * * .... +- crond: Report missing newline before EOF in syslog so the line is not + completely silently ignored. +- crontab -l colors comment lines in a different color. +- crond: Revert "Avoid creating pid files when crond doesn't fork". +- anacron is built by default. +- Use non-recursive build. +- cronnext: Allow to optionally select jobs by substring. + +Release 1.5.4 +- crond: Fix regression from previous release. Only first job from a crontab + was being run. + +Release 1.5.3 +- Fix CVE-2019-9704 and CVE-2019-9705 to avoid local DoS of the crond. +- crontab: Make crontab without arguments fail. +- crond: In PAM configuration include system-auth instead of password-auth. +- crond: In the systemd service file restart crond if it fails. +- crond: Use the role from the crond context for system job contexts. +- Multiple small cleanups and fixes. The source can be downloaded from [https://github.com/cronie-crond/cronie/releases] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/Makefile.am new/cronie-cronie-1.5.5/src/Makefile.am --- old/cronie-cronie-1.5.4/src/Makefile.am 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/Makefile.am 1970-01-01 01:00:00.000000000 +0100 @@ -1,79 +0,0 @@ -# Makefile.am - two binaries crond and crontab - -sbin_PROGRAMS = crond -bin_PROGRAMS = crontab cronnext - -crond_SOURCES = \ - cron.c database.c user.c job.c do_command.c popen.c security.c \ - $(common_src) -crontab_SOURCES = crontab.c security.c $(common_src) -cronnext_SOURCES = \ - cronnext.c database.c user.c job.c \ - $(common_src) -common_src = entry.c env.c misc.c pw_dup.c \ - externs.h funcs.h globals.h macros.h pathnames.h structs.h \ - bitstring.h -common_nodist = cron-paths.h -nodist_crond_SOURCES = $(common_nodist) -nodist_crontab_SOURCES = $(common_nodist) -nodist_cronnext_SOURCES = $(common_nodist) -BUILT_SOURCES = $(common_nodist) - -AM_CFLAGS = -I$(top_srcdir) - -LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT) - -## if DEBUG -## noinst_PROGRAMS = debug -## endif - -# This header contains all the paths. -# If they are configurable, they are declared in configure script. -# Depends on this Makefile, because it uses make variables. -# CCD 2010/09/10 added CRON_HOSTNAME for clustered-cron. -CLEANFILES = cron-paths.h -cron-paths.h: Makefile - @echo 'creating $@' - @sed >$@ 's/ *\\$$//' <<\END #\ - /* This file has been automatically generated. Do not edit. */ \ - \ - #ifndef _CRON_PATHS_H_ \ - #define _CRON_PATHS_H_ \ - \ - /* 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...) \ - * or it will be checked by inotify \ - */ \ - #define SPOOL_DIR "$(SPOOL_DIR)" \ - \ - /* CRON_HOSTNAME is file in SPOOL_DIR which, if it \ - * exists, and does not just contain a line matching \ - * the name returned by gethostname(), causes all \ - * crontabs in SPOOL_DIR to be ignored. This is \ - * intended to be used when clustering hosts sharing \ - * one NFS-mounted SPOOL_DIR, and where only one host \ - * should use the crontab files here at any one time. \ - */ \ - #define CRON_HOSTNAME ".cron.hostname" \ - \ - /* cron allow/deny file. At least cron.deny must \ - * exist for ordinary users to run crontab. \ - */ \ - #define CRON_ALLOW "$(sysconfdir)/cron.allow" \ - #define CRON_DENY "$(sysconfdir)/cron.deny" \ - \ - /* 4.3BSD-style crontab f.e. /etc/crontab */ \ - #define SYSCRONTAB "$(SYSCRONTAB)" \ - \ - /* system crontab dir f.e. /etc/cron.d/ */ \ - #define SYS_CROND_DIR "$(SYS_CROND_DIR)" \ - \ - #define SYSCONFDIR "$(sysconfdir)" \ - \ - #endif /* _CRON_PATHS_H_ */ \ - END diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/Makemodule.am new/cronie-cronie-1.5.5/src/Makemodule.am --- old/cronie-cronie-1.5.4/src/Makemodule.am 1970-01-01 01:00:00.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/Makemodule.am 2019-10-31 17:33:33.000000000 +0100 @@ -0,0 +1,107 @@ +# Makefile.am - two binaries crond and crontab + +sbin_PROGRAMS += \ + src/crond + +bin_PROGRAMS += \ + src/cronnext \ + src/crontab + +src_crond_SOURCES = \ + src/cron.c \ + src/database.c \ + src/do_command.c \ + src/job.c \ + src/popen.c \ + src/security.c \ + src/user.c \ + $(common_src) + +src_crontab_SOURCES = \ + src/crontab.c \ + src/security.c \ + $(common_src) + +src_cronnext_SOURCES = \ + src/cronnext.c \ + src/database.c \ + src/job.c \ + src/user.c \ + $(common_src) + +common_src = \ + src/bitstring.h \ + src/entry.c \ + src/env.c \ + src/externs.h \ + src/funcs.h \ + src/globals.h \ + src/macros.h \ + src/misc.c \ + src/pathnames.h \ + src/pw_dup.c \ + src/structs.h + +common_nodist += cron-paths.h +nodist_src_crond_SOURCES = $(common_nodist) +nodist_src_crontab_SOURCES = $(common_nodist) +nodist_src_cronnext_SOURCES = $(common_nodist) +BUILT_SOURCES += $(common_nodist) + +src_crond_LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT) +src_crontab_LDADD = $(LIBSELINUX) $(LIBPAM) $(LIBAUDIT) + +## if DEBUG +## noinst_PROGRAMS = debug +## endif + +# This header contains all the paths. +# If they are configurable, they are declared in configure script. +# Depends on this Makefile, because it uses make variables. +# CCD 2010/09/10 added CRON_HOSTNAME for clustered-cron. +CLEANFILES += cron-paths.h +cron-paths.h: Makefile + @echo 'creating $@' + @sed >$@ 's/ *\\$$//' <<\END #\ + /* This file has been automatically generated. Do not edit. */ \ + \ + #ifndef _CRON_PATHS_H_ \ + #define _CRON_PATHS_H_ \ + \ + /* 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...) \ + * or it will be checked by inotify \ + */ \ + #define SPOOL_DIR "$(SPOOL_DIR)" \ + \ + /* CRON_HOSTNAME is file in SPOOL_DIR which, if it \ + * exists, and does not just contain a line matching \ + * the name returned by gethostname(), causes all \ + * crontabs in SPOOL_DIR to be ignored. This is \ + * intended to be used when clustering hosts sharing \ + * one NFS-mounted SPOOL_DIR, and where only one host \ + * should use the crontab files here at any one time. \ + */ \ + #define CRON_HOSTNAME ".cron.hostname" \ + \ + /* cron allow/deny file. At least cron.deny must \ + * exist for ordinary users to run crontab. \ + */ \ + #define CRON_ALLOW "$(sysconfdir)/cron.allow" \ + #define CRON_DENY "$(sysconfdir)/cron.deny" \ + \ + /* 4.3BSD-style crontab f.e. /etc/crontab */ \ + #define SYSCRONTAB "$(SYSCRONTAB)" \ + \ + /* system crontab dir f.e. /etc/cron.d/ */ \ + #define SYS_CROND_DIR "$(SYS_CROND_DIR)" \ + \ + #define SYSCONFDIR "$(sysconfdir)" \ + \ + #endif /* _CRON_PATHS_H_ */ \ + END diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/cron.c new/cronie-cronie-1.5.5/src/cron.c --- old/cronie-cronie-1.5.4/src/cron.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/cron.c 2019-10-31 17:33:33.000000000 +0100 @@ -68,8 +68,9 @@ set_time(int), cron_sleep(int, cron_db *), sigchld_handler(int), -sighup_handler(int), -sigchld_reaper(void), sigintterm_handler(int), parse_args(int c, char *v[]); +sighup_handler(int ATTRIBUTE_UNUSED), +sigchld_reaper(void), +sigintterm_handler(int ATTRIBUTE_UNUSED), parse_args(int c, char *v[]); static volatile sig_atomic_t got_sighup, got_sigchld, got_sigintterm; static int timeRunning, virtualTime, clockTime; @@ -261,7 +262,7 @@ */ setlocale(LC_ALL, ""); /* set locale to system defaults or to * that specified by any LC_* env vars */ - if ((cs = nl_langinfo(CODESET)) != 0L) + if ((cs = nl_langinfo(CODESET)) != NULL) strncpy(cron_default_mail_charset, cs, MAX_ENVSTR-1); else strcpy(cron_default_mail_charset, "US-ASCII"); @@ -651,15 +652,15 @@ } } -static void sighup_handler(int x) { +static void sighup_handler(int x ATTRIBUTE_UNUSED) { got_sighup = 1; } -static void sigchld_handler(int x) { +static void sigchld_handler(int x ATTRIBUTE_UNUSED) { got_sigchld = 1; } -static void sigintterm_handler(int x) { +static void sigintterm_handler(int x ATTRIBUTE_UNUSED) { got_sigintterm = 1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/cronnext.c new/cronie-cronie-1.5.5/src/cronnext.c --- old/cronie-cronie-1.5.4/src/cronnext.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/cronnext.c 2019-10-31 17:33:33.000000000 +0100 @@ -25,6 +25,8 @@ #define MAIN_PROGRAM #include <stdlib.h> +#include <unistd.h> +#include <sys/stat.h> #include <string.h> #include <pwd.h> @@ -81,7 +83,7 @@ }; void printflags(char *indent, int flags) { - int f; + size_t f; int first = 1; printf("%s flagnames:", indent); @@ -197,11 +199,11 @@ /* * match a user against a list */ -int matchuser(char *user, char *list) { +int matchuser(char *user_name, char *list) { char *pos; - size_t l = strlen(user); + size_t l = strlen(user_name); - for (pos = list; (pos = strstr(pos, user)) != NULL; pos += l) { + for (pos = list; (pos = strstr(pos, user_name)) != NULL; pos += l) { if ((pos != list) && (*(pos - 1) != ',')) continue; if ((pos[l] != '\0') && (pos[l] != ',')) @@ -216,7 +218,7 @@ */ time_t cronnext(cron_db database, time_t start, time_t end, - char *include, char *exclude, int flags) { + char *include, char *exclude, char *command, int flags) { time_t closest, next; user *u; entry *e; @@ -242,7 +244,9 @@ if (flags & CRONTABS) printcrontab(u); - for (e = u->crontab; e; e = e->next) + for (e = u->crontab; e; e = e->next) { + if (command && strstr(e->cmd, command) == NULL) + continue; for (next = nextmatch(e, start, end); next <= end; next = nextmatch(e, next + 60, end)) { @@ -255,6 +259,7 @@ if (! (flags & ALLJOBS)) break; } + } } return closest; @@ -267,6 +272,7 @@ cron_db db = {NULL, NULL, (time_t) 0}; struct passwd pw; int fd; + struct stat ss; user *u; if (installed) @@ -278,6 +284,12 @@ perror(*additional); continue; } + fstat(fd, &ss); + if (S_ISDIR(ss.st_mode)) { + fprintf(stderr, "%s is a directory - skipping\n", *additional); + close(fd); + continue; + } memset(&pw, 0, sizeof(pw)); pw.pw_name = *additional; pw.pw_passwd = ""; @@ -305,6 +317,7 @@ fprintf(stderr, " -a examine installed crontabs even if files are given\n"); fprintf(stderr, " -t time start from this time (seconds since epoch)\n"); fprintf(stderr, " -q time end check at this time (seconds since epoch)\n"); + fprintf(stderr, " -j cmd only check jobs that contain cmd as a substring\n"); fprintf(stderr, " -l print next jobs to be executed\n"); fprintf(stderr, " -c print next execution of each job\n"); fprintf(stderr, " -f print all jobs executed in the given interval\n"); @@ -317,7 +330,7 @@ */ int main(int argn, char *argv[]) { int opt; - char *include, *exclude; + char *include, *exclude, *command; int flags; time_t start, next, end = 0; int endtime, printjobs; @@ -326,12 +339,13 @@ include = NULL; exclude = NULL; + command = NULL; flags = SYSTEM; endtime = 0; printjobs = 0; start = time(NULL) / 60 * 60; - while (-1 != (opt = getopt(argn, argv, "i:e:ast:q:lcfhV"))) { + while (-1 != (opt = getopt(argn, argv, "i:e:ast:q:j:lcfhV"))) { switch (opt) { case 'i': include = optarg; @@ -352,6 +366,9 @@ end = atoi(optarg) / 60 * 60; endtime = 1; break; + case 'j': + command = optarg; + break; case 'l': printjobs = 1; break; @@ -399,7 +416,7 @@ db = database(installed || argv[optind] == NULL, argv + optind); /* find time of next scheduled command */ - next = cronnext(db, start, end, include, exclude, flags); + next = cronnext(db, start, end, include, exclude, command, flags); /* print time */ if (next == -1) @@ -410,7 +427,7 @@ /* print next jobs */ if (printjobs) { printf("nextjobs:\n"); - cronnext(db, next, next, include, exclude, (flags & SYSTEM) | ENTRIES); + cronnext(db, next, next, include, exclude, command, (flags & SYSTEM) | ENTRIES); } return EXIT_SUCCESS; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/crontab.c new/cronie-cronie-1.5.5/src/crontab.c --- old/cronie-cronie-1.5.4/src/crontab.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/crontab.c 2019-10-31 17:33:33.000000000 +0100 @@ -66,6 +66,9 @@ #define NHEADER_LINES 0 +#define COMMENT_COLOR "\x1B[34m" +#define RESET_COLOR "\033[0m" + enum opt_t {opt_unknown, opt_list, opt_delete, opt_edit, opt_replace, opt_hostset, opt_hostget}; #if DEBUGGING @@ -392,6 +395,8 @@ char n[MAX_FNAME]; FILE *f; int ch; + const int is_tty = isatty(STDOUT); + int new_line = 1; log_it(RealUser, Pid, "LIST", User, 0); if (!glue_strings(n, sizeof n, SPOOL_DIR, User, '/')) { @@ -409,8 +414,18 @@ /* file is open. copy to stdout, close. */ Set_LineNum(1) - while (EOF != (ch = get_char(f))) + while (EOF != (ch = get_char(f))) { + if (is_tty && new_line) { + if (ch == '#') { + fputs(COMMENT_COLOR, stdout); + } + else { + fputs(RESET_COLOR, stdout); + } + } putchar(ch); + new_line = ch == '\n'; + } fclose(f); } @@ -419,7 +434,7 @@ if (PromptOnDelete == 1) { printf("crontab: really delete %s's crontab? ", User); fflush(stdout); - if ((fgets(n, MAX_FNAME - 1, stdin) == 0L) + if ((fgets(n, MAX_FNAME - 1, stdin) == NULL) || ((n[0] != 'Y') && (n[0] != 'y')) ) exit(0); @@ -700,7 +715,7 @@ perror("swapping uids back"); exit(ERROR_EXIT); } - if (NewCrontab == 0L) { + if (NewCrontab == NULL) { perror("fopen"); goto fatal; } @@ -709,10 +724,10 @@ break; case -1: for (;;) { - printf("Do you want to retry the same edit? "); + printf("Do you want to retry the same edit? (Y/N) "); fflush(stdout); q[0] = '\0'; - if (fgets(q, sizeof q, stdin) == 0L) + if (fgets(q, sizeof q, stdin) == NULL) continue; switch (q[0]) { case 'y': @@ -803,15 +818,14 @@ error = -2; goto done; } - fflush(tmp); - rewind(tmp); - if (ferror(tmp)) { + if (ferror(tmp) || fflush(tmp) || fsync(fileno(tmp))) { fprintf(stderr, "%s: error while writing new crontab to %s\n", ProgramName, TempFilename); fclose(tmp); error = -2; goto done; } + rewind(tmp); /* check the syntax of the file being installed. */ @@ -1041,7 +1055,7 @@ } } -static void die(int x) { +static void die(int x ATTRIBUTE_UNUSED) { if (TempFilename[0]) (void) unlink(TempFilename); _exit(ERROR_EXIT); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/database.c new/cronie-cronie-1.5.5/src/database.c --- old/cronie-cronie-1.5.4/src/database.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/database.c 2019-10-31 17:33:33.000000000 +0100 @@ -48,9 +48,6 @@ #include "globals.h" #include "pathnames.h" -#define TMAX(a,b) ((a)>(b)?(a):(b)) -#define TMIN(a,b) ((a)<(b)?(a):(b)) - /* size of the event structure, not counting name */ #define EVENT_SIZE (sizeof (struct inotify_event)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/do_command.c new/cronie-cronie-1.5.5/src/do_command.c --- old/cronie-cronie-1.5.4/src/do_command.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/do_command.c 2019-10-31 17:33:33.000000000 +0100 @@ -46,7 +46,7 @@ void do_command(entry * e, user * u) { pid_t pid = getpid(); int ev; - char **jobenv = 0L; + char **jobenv = NULL; Debug(DPROC, ("[%ld] do_command(%s, (%s,%ld,%ld))\n", (long) pid, e->cmd, u->name, @@ -238,7 +238,7 @@ */ { char *shell = env_get("SHELL", jobenv); - int fd, fdmax = getdtablesize(); + int fd, fdmax = TMIN(getdtablesize(), MAX_CLOSE_FD); /* close all unwanted open file descriptors */ for(fd = STDERR + 1; fd < fdmax; fd++) { @@ -427,8 +427,14 @@ gethostname(hostname, MAXHOSTNAMELEN); if (MailCmd[0] == '\0') { - if (snprintf(mailcmd, sizeof mailcmd, MAILFMT, MAILARG, mailfrom) - >= sizeof mailcmd) { + int len; + + len = snprintf(mailcmd, sizeof mailcmd, MAILFMT, MAILARG, mailfrom); + if (len < 0) { + fprintf(stderr, "mailcmd snprintf failed\n"); + (void) _exit(ERROR_EXIT); + } + if (sizeof mailcmd <= (size_t) len) { fprintf(stderr, "mailcmd too long\n"); (void) _exit(ERROR_EXIT); } @@ -450,7 +456,7 @@ fprintf(mail, "Date: %s\n", arpadate(&StartTime)); #endif /*MAIL_DATE */ fprintf(mail, "MIME-Version: 1.0\n"); - if (content_type == 0L) { + if (content_type == NULL) { fprintf(mail, "Content-Type: text/plain; charset=%s\n", cron_default_mail_charset); } @@ -461,17 +467,17 @@ char *nl = content_type; size_t ctlen = strlen(content_type); while ((*nl != '\0') - && ((nl = strchr(nl, '\n')) != 0L) + && ((nl = strchr(nl, '\n')) != NULL) && (nl < (content_type + ctlen)) ) *nl = ' '; fprintf(mail, "Content-Type: %s\n", content_type); } - if (content_transfer_encoding != 0L) { + if (content_transfer_encoding != NULL) { char *nl = content_transfer_encoding; size_t ctlen = strlen(content_transfer_encoding); while ((*nl != '\0') - && ((nl = strchr(nl, '\n')) != 0L) + && ((nl = strchr(nl, '\n')) != NULL) && (nl < (content_transfer_encoding + ctlen)) ) *nl = ' '; @@ -500,6 +506,8 @@ */ while (EOF != (ch = getc(in))) { + if (ch == '\r') + continue; bytes++; if (mail) putc(ch, mail); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/entry.c new/cronie-cronie-1.5.5/src/entry.c --- old/cronie-cronie-1.5.4/src/entry.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/entry.c 2019-10-31 17:33:33.000000000 +0100 @@ -548,6 +548,13 @@ num3 = 1; } + /* num1 (through i) will be validated by set_element() below, but num2 + * and num3 are merely used as loop condition and increment, and must + * be validated separately. + */ + if (num2 < low || num2 > high || num3 > high) + return (EOF); + /* range. set all elements from num1 to num2, stepping * by num3. (the step is a downward-compatible extension * proposed conceptually by bob@acornrc, syntactically diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/env.c new/cronie-cronie-1.5.5/src/env.c --- old/cronie-cronie-1.5.4/src/env.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/env.c 2019-10-31 17:33:33.000000000 +0100 @@ -23,6 +23,7 @@ #include <ctype.h> #include <errno.h> +#include <stddef.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> @@ -281,7 +282,7 @@ while ((p = *envp++) != NULL) { if (!(q = strchr(p, '='))) continue; - if ((q - p) == len && !strncmp(p, name, len)) + if ((size_t)(q - p) == len && !strncmp(p, name, len)) return (q + 1); } return (NULL); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/macros.h new/cronie-cronie-1.5.5/src/macros.h --- old/cronie-cronie-1.5.4/src/macros.h 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/macros.h 2019-10-31 17:33:33.000000000 +0100 @@ -61,6 +61,7 @@ #define MAX_USER_ENVS 1000 /* maximum environment variables in user's crontab */ #define MAX_USER_ENTRIES 1000 /* maximum crontab entries in user's crontab */ #define MAX_GARBAGE 32768 /* max num of chars of comments and whitespaces between entries */ +#define MAX_CLOSE_FD 10000 /* max fd num to close when spawning a child process */ /* NOTE: these correspond to DebugFlagNames, * defined below. @@ -129,6 +130,9 @@ #define LAST_DOW 7 #define DOW_COUNT (LAST_DOW - FIRST_DOW + 1) +#define TMAX(a,b) ((a)>(b)?(a):(b)) +#define TMIN(a,b) ((a)<(b)?(a):(b)) + /* * Because crontab/at files may be owned by their respective users we * take extreme care in opening them. If the OS lacks the O_NOFOLLOW diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/misc.c new/cronie-cronie-1.5.5/src/misc.c --- old/cronie-cronie-1.5.4/src/misc.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/misc.c 2019-10-31 17:33:33.000000000 +0100 @@ -315,9 +315,6 @@ return; } - if (NoFork == 1) - return; //move along, nothing to do here... - if (fd == -1) { pidfile = _PATH_CRON_PID; /* Initial mode is 0600 to prevent flock() race/DoS. */ @@ -460,76 +457,6 @@ return TRUE; } -/* int in_file(const char *string, FILE *file, int error) - * return TRUE if one of the lines in file matches string exactly, - * FALSE if no lines match, and error on error. - */ -static int in_file(const char *string, FILE * file, int error) { - char line[MAX_TEMPSTR]; - char *endp; - - if (fseek(file, 0L, SEEK_SET)) - return (error); - while (fgets(line, MAX_TEMPSTR, file)) { - if (line[0] != '\0') { - endp = &line[strlen(line) - 1]; - if (*endp != '\n') - return (error); - *endp = '\0'; - if (0 == strcmp(line, string)) - return (TRUE); - } - } - if (ferror(file)) - return (error); - return (FALSE); -} - -/* int allowed(const char *username, const char *allow_file, const char *deny_file) - * returns TRUE if (allow_file exists and user is listed) - * or (deny_file exists and user is NOT listed). - * root is always allowed. - */ -int allowed(const char *username, const char *allow_file, - const char *deny_file) { - FILE *fp; - int isallowed; - char buf[128]; - - if (getuid() == 0) - return TRUE; - isallowed = FALSE; - if ((fp = fopen(allow_file, "r")) != NULL) { - isallowed = in_file(username, fp, FALSE); - fclose(fp); - if ((getuid() == 0) && (!isallowed)) { - snprintf(buf, sizeof (buf), - "root used -u for user %s not in cron.allow", username); - log_it("crontab", getpid(), "warning", buf, 0); - isallowed = TRUE; - } - } - else if ((fp = fopen(deny_file, "r")) != NULL) { - isallowed = !in_file(username, fp, FALSE); - fclose(fp); - if ((getuid() == 0) && (!isallowed)) { - snprintf(buf, sizeof (buf), - "root used -u for user %s in cron.deny", username); - log_it("crontab", getpid(), "warning", buf, 0); - isallowed = TRUE; - } - } -#ifdef WITH_AUDIT - if (isallowed == FALSE) { - int audit_fd = audit_open(); - audit_log_user_message(audit_fd, AUDIT_USER_START, "cron deny", - NULL, NULL, NULL, 0); - close(audit_fd); - } -#endif - return (isallowed); -} - void log_it(const char *username, PID_T xpid, const char *event, const char *detail, int err) { #if defined(LOG_FILE) || DEBUGGING diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/popen.c new/cronie-cronie-1.5.5/src/popen.c --- old/cronie-cronie-1.5.4/src/popen.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/popen.c 2019-10-31 17:33:33.000000000 +0100 @@ -81,12 +81,19 @@ if (!pids) { if ((fds = getdtablesize()) <= 0) return (NULL); + if (fds > MAX_CLOSE_FD) + fds = MAX_CLOSE_FD; /* avoid allocating too much memory */ if (!(pids = (PID_T *) malloc((u_int) ((size_t)fds * sizeof (PID_T))))) return (NULL); memset((char *) pids, 0, (size_t)fds * sizeof (PID_T)); } if (pipe(pdes) < 0) return (NULL); + if (pdes[0] >= fds || pdes[1] >= fds) { + (void) close(pdes[0]); + (void) close(pdes[1]); + return NULL; + } /* break up string into pieces */ for (argc = 0, cp = program; argc < MAX_ARGS; cp = NULL) @@ -145,14 +152,16 @@ } /* parent; assume fdopen can't fail... */ if (*type == 'r') { + fd = pdes[0]; iop = fdopen(pdes[0], type); (void) close(pdes[1]); } else { + fd = pdes[1]; iop = fdopen(pdes[1], type); (void) close(pdes[0]); } - pids[fileno(iop)] = pid; + pids[fd] = pid; pfree: return (iop); @@ -168,7 +177,8 @@ * pclose returns -1 if stream is not associated with a * `popened' command, or, if already `pclosed'. */ - if (pids == 0 || pids[fdes = fileno(iop)] == 0) + fdes = fileno(iop); + if (pids == NULL || fdes >= fds || pids[fdes] == 0L) return (-1); (void) fclose(iop); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/security.c new/cronie-cronie-1.5.5/src/security.c --- old/cronie-cronie-1.5.4/src/security.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/security.c 2019-10-31 17:33:33.000000000 +0100 @@ -120,7 +120,7 @@ /* "minute-ly" job: Every minute for given hour/dow/month/dom. * Ensure that these jobs never run in the same minute: */ - minutely_time = time(0); + minutely_time = time(NULL); Debug(DSCH, ("Minute-ly job. Recording time %lu\n", minutely_time)); } @@ -169,7 +169,7 @@ *jobenv = build_env(e->envp); - time_t job_run_time = time(0L); + time_t job_run_time = time(NULL); if ((minutely_time > 0) && ((job_run_time / 60) != (minutely_time / 60))) { /* if a per-minute job is delayed into the next minute @@ -350,12 +350,12 @@ if (is_selinux_enabled() <= 0) return 0; - if (ucontextp == 0L) + if (ucontextp == NULL) return -1; - *ucontextp = 0L; + *ucontextp = NULL; - if ((range = env_get("MLS_LEVEL", jobenv)) != 0L) { + if ((range = env_get("MLS_LEVEL", jobenv)) != NULL) { context_t ccon; if (!(ccon = context_new(u->scontext))) { log_it(u->name, getpid(), "context_new FAILED for MLS_LEVEL", @@ -404,7 +404,7 @@ if (is_selinux_enabled() <= 0) return 0; - if (u->scontext == 0L) { + if (u->scontext == NULL) { if (security_getenforce() > 0) { log_it(u->name, getpid(), "NULL security context for user", "", 0); return -1; @@ -592,7 +592,7 @@ void free_security_context(security_context_t * scontext) { if (*scontext != NULL) { freecon(*scontext); - *scontext = 0L; + *scontext = NULL; } } #endif @@ -675,3 +675,74 @@ return jobenv; #endif } + +/* int in_file(const char *string, FILE *file, int error) + * return TRUE if one of the lines in file matches string exactly, + * FALSE if no lines match, and error on error. + */ +static int in_file(const char *string, FILE * file, int error) { + char line[MAX_TEMPSTR]; + char *endp; + + if (fseek(file, 0L, SEEK_SET)) + return (error); + while (fgets(line, MAX_TEMPSTR, file)) { + if (line[0] != '\0') { + endp = &line[strlen(line) - 1]; + if (*endp != '\n') + return (error); + *endp = '\0'; + if (0 == strcmp(line, string)) + return (TRUE); + } + } + if (ferror(file)) + return (error); + return (FALSE); +} + +/* int allowed(const char *username, const char *allow_file, const char *deny_file) + * returns TRUE if (allow_file exists and user is listed) + * or (deny_file exists and user is NOT listed). + * root is always allowed. + */ +int allowed(const char *username, const char *allow_file, + const char *deny_file) { + FILE *fp; + int isallowed; + char buf[128]; + + if (getuid() == 0) + return TRUE; + isallowed = FALSE; + if ((fp = fopen(allow_file, "r")) != NULL) { + isallowed = in_file(username, fp, FALSE); + fclose(fp); + if ((getuid() == 0) && (!isallowed)) { + snprintf(buf, sizeof (buf), + "root used -u for user %s not in cron.allow", username); + log_it("crontab", getpid(), "warning", buf, 0); + isallowed = TRUE; + } + } + else if ((fp = fopen(deny_file, "r")) != NULL) { + isallowed = !in_file(username, fp, FALSE); + fclose(fp); + if ((getuid() == 0) && (!isallowed)) { + snprintf(buf, sizeof (buf), + "root used -u for user %s in cron.deny", username); + log_it("crontab", getpid(), "warning", buf, 0); + isallowed = TRUE; + } + } +#ifdef WITH_AUDIT + if (isallowed == FALSE) { + int audit_fd = audit_open(); + audit_log_user_message(audit_fd, AUDIT_USER_START, "cron deny", + NULL, NULL, NULL, 0); + close(audit_fd); + } +#endif + return (isallowed); +} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cronie-cronie-1.5.4/src/user.c new/cronie-cronie-1.5.5/src/user.c --- old/cronie-cronie-1.5.4/src/user.c 2019-03-18 11:19:06.000000000 +0100 +++ new/cronie-cronie-1.5.5/src/user.c 2019-10-31 17:33:33.000000000 +0100 @@ -116,13 +116,24 @@ #endif /* load the crontab */ - while (status >= TRUE) { + while (status >= OK) { if (!skip_comments(file) && !u->system) { log_error("too many garbage characters"); + status = TRUE; break; } status = load_env (envstr, file); switch (status) { + case ERR: + /* If envstr has content, we reached EOF + * without a newline, and the line will be + * ignored. + */ + if (envstr[0] != '\0') { + FileName = tabname; + log_error("missing newline before EOF"); + } + break; case FALSE: ++entries; if (!u->system && entries > MAX_USER_ENTRIES) { @@ -135,7 +146,6 @@ if (e) { e->next = u->crontab; u->crontab = e; - status = TRUE; } break; case TRUE: ++++++ cronie-nheader_lines.diff ++++++ --- /var/tmp/diff_new_pack.iTVJmd/_old 2019-11-07 23:15:13.188448902 +0100 +++ /var/tmp/diff_new_pack.iTVJmd/_new 2019-11-07 23:15:13.188448902 +0100 @@ -9,9 +9,9 @@ -#define NHEADER_LINES 0 +#define NHEADER_LINES 3 - enum opt_t {opt_unknown, opt_list, opt_delete, opt_edit, opt_replace, opt_hostset, opt_hostget}; - -@@ -485,7 +485,7 @@ static void edit_cmd(void) { + #define COMMENT_COLOR "\x1B[34m" + #define RESET_COLOR "\033[0m" +@@ -500,7 +500,7 @@ static void edit_cmd(void) { char n[MAX_FNAME], q[MAX_TEMPSTR]; const char *editor; FILE *f; @@ -20,7 +20,7 @@ struct stat statbuf; struct utimbuf utimebuf; WAIT_T waiter; -@@ -537,13 +537,25 @@ static void edit_cmd(void) { +@@ -552,13 +552,25 @@ static void edit_cmd(void) { } Set_LineNum(1) @@ -53,7 +53,7 @@ while (EOF != (ch = get_char(f))) putc(ch, NewCrontab); -@@ -751,6 +763,7 @@ static int replace_cmd(void) { +@@ -766,6 +778,7 @@ static int replace_cmd(void) { int error = 0; entry *e; uid_t file_owner; @@ -61,7 +61,7 @@ char **envp; char *safename; int envs = 0, entries = 0; -@@ -781,10 +794,10 @@ static int replace_cmd(void) { +@@ -796,10 +809,10 @@ static int replace_cmd(void) { * * VERY IMPORTANT: make sure NHEADER_LINES agrees with this code. */
