[Patch] crontab

Pierre A. Humblet Pierre.Humblet@ieee.org
Tue Dec 21 14:13:00 GMT 2004


The attached patch makes cron more friendly to Windows2003
users who run it under a privileged user different from SYSTEM.

The main difference is that crontab now places the /var/cron/tabs
files in the Administrators (instead of System) group.
This is not expected to have an impact on existing installations.

cron_diagnose.sh checks access to various files by Administrators
(or by System on older system), and includes more tests.

Pierre
-------------- next part --------------
--- compat.h.orig	2003-04-15 11:13:42.000000000 -0400
+++ compat.h	2004-12-20 19:49:18.000000000 -0500
@@ -150,6 +150,15 @@

 #if defined(__CYGWIN__)
 #include <windows.h>
+#include <sys/cygwin.h>
+/* Macro to define variable length SID structures */
+#define SID(n, name, sid...) \
+struct  { \
+  BYTE  Revision; \
+  BYTE  SubAuthorityCount; \
+  SID_IDENTIFIER_AUTHORITY IdentifierAuthority; \
+  DWORD SubAuthority[n]; \
+} name = { SID_REVISION, n, {SECURITY_NT_AUTHORITY}, {sid}}
 #define CRONDIR		"/var/cron"
 #define _PATH_VARRUN	"/var/run/"
 #endif
--- crontab.c.orig	2003-04-15 11:13:42.000000000 -0400
+++ crontab.c	2004-12-20 19:55:22.000000000 -0500
@@ -627,7 +627,7 @@ replace_cmd() {

 /* Cygwin can't support changing the owner since that requires crontab to
    be a s-uid application which is not supported.
-   As workaround we try to set group membership to be SYSTEM (== ROOT_UID)
+   As workaround we try to set group membership to be ADMINISTRATORS
    and setting permissions to 640 which should allow cron to work. */
 #ifndef __CYGWIN__
 #ifdef HAS_FCHOWN
@@ -636,7 +636,9 @@ replace_cmd() {
 	if (chown(tn, ROOT_UID, -1) < OK)
 #endif
 #else /* __CYGWIN__ */
-	if (chown(tn, -1, ROOT_UID) < OK)
+	const SID(2, AdminsSid, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS);
+	const int ADMINS_GID = cygwin_internal(CW_GET_GID_FROM_SID, &AdminsSid);
+	if (chown(tn, -1, ADMINS_GID) < OK)
 #endif
 	{
 		perror("chown");
--- cron.README.orig	2004-12-13 12:07:32.000000000 -0500
+++ cron.README	2004-12-20 23:01:16.000000000 -0500
@@ -17,6 +17,18 @@ Send patches and error reports to <cygwi
 Changes:
 ========

+3.0.1-15:
+---------
+
+Contribution by Pierre Humblet <Pierre.Humblet@ieee.org>:
+Crontab now changes group membership of the crontab files to be
+ADMINISTRATORS, to allow access from any privileged process.
+Modify cron_diagnose to:
+- check the new crontab file group setting.
+- verify access of /var/run, /usr/sbin/cron.exe and /usr/sbin/sendmail
+  by Administrators (instead of SYSTEM) and the local user.
+- get the system mounts directly from the registry.
+
 3.0.1-14:
 ---------

--- cron_diagnose.sh.orig	2004-12-13 12:09:14.000000000 -0500
+++ cron_diagnose.sh	2004-12-21 08:31:38.000000000 -0500
@@ -47,6 +47,18 @@ function sanity_check() {
 	check_program cygcheck cygwin || return
 } # === End of sanity_check() === #

+# ======================================================================
+# Routine: get_NT
+# ======================================================================
+function get_NT() {
+    NT2003=""
+    NT=$(uname -s | sed -ne 's/^CYGWIN_NT-\([^ ]*\)/\1/p')
+    if [ "$NT" \> 5.1 ]; then NT2003=yes; fi
+    if [ -z "$NT" ]; then
+	echo "This script is only meant to run on NT."
+	exit 0
+    fi
+} # === End of get_NT() === #

 # ======================================================================
 # Routine: warning_for_etc_file
@@ -84,14 +96,14 @@ function check_system_in_group() {

 # ======================================================================
 # Routine: get_system_and_admins_gids
-# Get the SYSTEM and ADMINs ids from /etc/group and /etc/passwd
+# Get the ADMINs ids from /etc/group and /etc/passwd
 # ======================================================================
 function get_system_and_admins_ids() {
     ADMINSGID=$(sed -ne '/^[^:]*:S-1-5-32-544:.*:/{s/[^:]*:[^:]*:\([0-9]*\):.*$/\1/p;q}' /etc/group)
     SYSTEMGID=$(sed -ne '/^[^:]*:S-1-5-18:.*:/{s/[^:]*:[^:]*:\([0-9]*\):.*$/\1/p;q}' /etc/group)
     if [ -z "$ADMINSGID" -o -z "$SYSTEMGID" ]; then
 		echo "It appears that you do not have entries for the"
-		echo "SYSTEM and/or ADMINISTRATORS sids in /etc/group."
+		echo "ADMINISTRATORS and/or SYSTEM sids in /etc/group."
 		echo
 		echo "Use the 'mkgroup' utility to generate them"
 		echo "   mkgroup -l > /etc/group"
@@ -100,10 +112,11 @@ function get_system_and_admins_ids() {
 		return 1;
     fi

+    ADMINSUID=$(sed -ne '/^[^:]*:[^:]*:[0-9]*:[0-9]*:[^:]*,S-1-5-32-544:.*:/{s/[^:]*:[^:]*:\([0-9]*\):.*$/\1/p;q}' /etc/passwd)
     SYSTEMUID=$(sed -ne '/^[^:]*:[^:]*:[0-9]*:[0-9]*:[^:]*,S-1-5-18:.*:/{s/[^:]*:[^:]*:\([0-9]*\):.*$/\1/p;q}' /etc/passwd)
-    if [ -z "$SYSTEMUID" ]; then
+    if [ -z "$ADMINSUID" -o -z "$SYSTEMUID" ]; then
 		echo "It appears that you do not have an entry for the"
-		echo "SYSTEM sid in /etc/passwd."
+		echo "ADMINISTRATORS and/or SYSTEM sids in /etc/passwd."
 		echo
 		echo "Use the 'mkpasswd' utility to generate it"
 		echo "   mkpasswd -l > /etc/passwd"
@@ -208,38 +221,43 @@ function check_dir_perms() {


 # ======================================================================
-# Routine: check_var_run
-# Check to see that SYSTEM or the Administrators group has write
-# permission in the directory /var/run.  This permission is needed
-# so that the cron.pid file can be created by the cron service.
-# ======================================================================
-function check_var_run() {
+# Routine: check_access
+# Check to see that the owner and Administrators have
+# proper access to the file or directory.
+# On installations older than Windows 2003, allow access by System
+# ======================================================================
+function check_access() {
+	local file="$1"
+        local perm="$2"
 	local notify=0;
+	local ls="$(ls -dLln "$file" 2> /dev/null)"

-	# If SYSTEM is the owner of /var/run and does not have write
-	# permission, then notify the user.
-	if [ $(ls -dln /var/run | awk '{ print $3 }') -eq $SYSTEMUID ]; then
-		if [ $(ls -dl /var/run | cut -b3) != w ]; then notify=1; fi
-	# If 'Administrators' has group access to /var/run, but does not have
-	# write permission, then notify the user.
-	elif [ $(ls -dln /var/run | awk '{ print $4 }') -eq $ADMINSGID ]; then
-		if [ $(ls -dl /var/run | cut -b6) != w ]; then notify=1; fi
-	# If 'everyone' / 'other' has write permission, then the permissions
-	# MUST be sufficient for SYSTEM and administrators to write to it.
-	elif [ $(ls -dln /var/run | cut -b9) != w ]; then notify=1; fi
+	# If the owner of the file does not have access,
+	# then notify the user.
+	if [ -z "$(echo "$ls" | sed -n /^."$perm"/p)" ]; then
+		notify=1;
+	# If 'Administrators' has owner or group access to the file,
+	# but does not have the desired access, then notify the user.
+	elif [ "$(echo "$ls" | awk '{ print $3 }')" -eq $ADMINSUID \
+	       -o \( -z "$NT2003" -a "$(echo "$ls" | awk '{ print $3 }')" -eq $SYSTEMUID \) ]; then
+	        true;
+	elif [ "$(echo "$ls" | awk '{ print $4 }')" -eq $ADMINSGID \
+	       -o \( -z "$NT2003" -a "$(echo "$ls" | awk '{ print $4 }')" -eq $SYSTEMGID \) ]; then
+		if [ -z "$(echo "$ls" | sed -n /^...."$perm"/p)" ]; then notify=1; fi
+	elif [ -z "$(echo "$ls" | sed -n /^......."$perm"/p)" ]; then notify=1; fi

 	if [ $notify -eq 1 ]; then
-		echo "The SYSTEM user or Administrators group needs to have";
-		echo "write permission in the directory /var/run.";
-		echo "Here are the permissions of this directory:";
+		echo "The owner and the Administrators need";
+		echo "to have $perm permission to $file.";
+		echo "Here are the current permissions:";
 		echo;
-		ls -dl /var/run;
+		ls -dlL "$file";
 		echo;
 		echo "Please change the user and/or group ownership and";
-		echo "permissions of /var/run, and then run this script again.";
+		echo "permissions of $file, and then run this script again.";
 		return 1;
 	fi
-} # === End of check_var_run() === #
+} # === End of check_access() === #


 # ======================================================================
@@ -251,8 +269,8 @@ function check_sys_mount() {
 	local mnt_point=$1
 	local dos_dir=$2

-	echo -e "Checking mount point for $mnt_point. . .\c";
-	if ! mount | grep -E -qe ".+ on $mnt_point .+system.+"; then
+	local SYSTEM_MOUNTS='/proc/registry/HKey_Local_Machine/Software/Cygnus Solutions/Cygwin/mounts v2'
+	if ! ls "$SYSTEM_MOUNTS" | grep -Eq "^${mnt_point}\$"; then
 		echo;
 		echo "The SYSTEM user cannot access the mount point ${mnt_point}."
 		echo "Please run the following command to add a system mount point:"
@@ -264,7 +282,6 @@ function check_sys_mount() {
 		echo "After adding this mount point, please re-run this script."
 		return 1
 	fi
-	echo "done";
 } # === End of check_sys_mount() === #


@@ -288,7 +305,8 @@ function check_cron_table() {
 		return 1
 	fi

-	if ! ls -l $cron_table | grep -F -q 'rw-r-----'; then
+	local ls="$(ls -ln "$cron_table")"
+	if ! echo "$ls" | grep -F -q 'rw-r-----'; then
 		echo "The file permissions of your cron table need to"
 		echo "provide read/write access for $user_id."
 		echo "The permissions of your cron table file are set to:"
@@ -302,24 +320,43 @@ function check_cron_table() {
 		return 1
 	fi

-	if ! ls -ln $cron_table | awk '{ print $4 }' | grep -F -q "$SYSTEMGID"; then
-		echo "The group membership of your cron table file should be SYSTEM,"
+	if [ "$(echo "$ls"  | awk '{ print $4 }')" -ne "$ADMINSGID" \
+	    -a \( -n "$NT2003" -o "$(echo "$ls" | awk '{ print $4 }')" -ne "$SYSTEMGID" \) ]; then
+		echo "The group membership of your cron table file should be ADMINISTRATORS,"
 		echo "as documented in the file /usr/share/doc/Cygwin/cron.README."
 		echo "Here is your cron table file:"
 		echo
 		ls -l $cron_table
 		echo
 		echo "You can change the group membership setting with:"
-		echo "	 chgrp $SYSTEMGID $cron_table"
+		echo "	 chgrp $ADMINSGID $cron_table"
 		echo "Please change your cron table's group membership, and"
 		echo "run this script again."
 		return 1
 	fi
 } # === End of check_cron_table() === #

+function check_myself() {
+	echo
+	if [ ! -x /usr/sbin/cron ]; then
+	    echo "If you are running cron as yourself,";
+	    echo "you need x access to /usr/sbin/cron.";
+	fi
+	if [ ! -w /var/run ]; then
+	    echo "If you are running cron as yourself,";
+	    echo "you need w access to /var/run.";
+        fi
+	if [ ! -x /usr/sbin/sendmail ]; then
+	    echo "If you are running cron as yourself,";
+	    echo "/usr/sbin/sendmail should point to an executable mailer";
+	fi
+        echo
+} # === End of check_myself() === #

 function main() {
-	echo -e "cron_diagnose.sh 1.9\n"
+	echo -e "cron_diagnose.sh 1.10\n"
+
+	get_NT

 	sanity_check || return

@@ -345,7 +382,15 @@ function main() {
 	check_dir_perms /var/cron || return
 	check_dir_perms /var/cron/tabs || return

-	check_var_run || return
+	# Check write access to /var/run, to create cron_pid
+	check_access /var/run .w. || return
+
+	# Check x access to /usr/sbin/cron
+ 	check_access /usr/sbin/cron ..x || return
+
+	# Check x access to /usr/sbin/sendmail
+ 	check_access /usr/sbin/sendmail ..x ||
+	   echo "     ssmtp and exim are suitable mailers."

 	check_sys_mount /usr/bin /bin || return
 	check_sys_mount /usr/lib /lib || return
@@ -354,7 +399,9 @@ function main() {

 	check_cron_table || return

-	echo "This script did not find any errors in your crontab setup."
+	echo "This script did not find any errors in your cron setup."
+	check_myself
+
 	echo "If you are still unable to get cron to work, then try"
 	echo "shutting down the cron service, uninstalling it,"
 	echo "reinstalling it, and restarting it."
@@ -363,6 +410,7 @@ function main() {
 	echo "  $ cygrunsrv --stop cron"
 	echo "  $ cygrunsrv --remove cron"
 	echo "  $ cygrunsrv --install cron -p /usr/sbin/cron -a -D"
+	echo "      (You can also add a -u switch)"
 	echo "  $ cygrunsrv --start cron"
 	echo


-------------- next part --------------
--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


More information about the Cygwin mailing list