PAM support for cron(8)

Matthias Schmidt schmidtm at mathematik.uni-marburg.de
Wed Dec 12 03:45:56 PST 2007


Hi,

as stated in my last message, I ported PAM support for cron(8) from
FreeBSD (have a look at [1]).  The commit message is really clear about
the vantages so I don't want to elaborate on that :)

A patch is attached.  I'm not really sure how to handle $FreeBSD$ IDs.
I just added the IDs from the FreeBSD files I used.  The patch applies
clean (against HEAD) and works flawlessly.

Regards,

	Matthias

[1] http://lists.freebsd.org/pipermail/cvs-src/2007-June/080023.html

-- 
Dipl.-Inf. Matthias Schmidt <schmidtm at mathematik.uni-marburg.de>
Dept. of Mathematics and Computer Science, Distributed Systems Group
University of Marburg, Hans-Meerwein-Strasse, 35032 Marburg, Germany
Tel: +49.6421.28 21 591, Fax: +49.6421.28 21 573, Office C4347
Index: Makefile
===================================================================
RCS file: /usr/dcvs/src/usr.sbin/cron/cron/Makefile,v
retrieving revision 1.2
diff -u -r1.2 Makefile
--- Makefile	17 Jun 2003 04:29:53 -0000	1.2
+++ Makefile	12 Dec 2007 11:39:16 -0000
@@ -1,11 +1,11 @@
-# $FreeBSD: src/usr.sbin/cron/cron/Makefile,v 1.12.2.1 2001/04/25 12:09:23 ru Exp $
+# $FreeBSD: src/usr.sbin/cron/cron/Makefile,v 1.16 2007/06/17 17:25:53 yar Exp $
 # $DragonFly: src/usr.sbin/cron/cron/Makefile,v 1.2 2003/06/17 04:29:53 dillon Exp $
 
 PROG=	cron
 SRCS=	cron.c database.c do_command.c job.c user.c popen.c
-CFLAGS+=-DLOGIN_CAP
-DPADD=	${LIBCRON} ${LIBUTIL}
-LDADD=	${LIBCRON} -lutil
+CFLAGS+=-DLOGIN_CAP -DPAM
+DPADD=	${LIBCRON} ${LIBPAM} ${LIBUTIL}
+LDADD=	${LIBCRON} -lpam -lutil
 MAN=	cron.8
 
 .include <bsd.prog.mk>
Index: cron.8
===================================================================
RCS file: /usr/dcvs/src/usr.sbin/cron/cron/cron.8,v
retrieving revision 1.3
diff -u -r1.3 cron.8
--- cron.8	18 Mar 2006 20:29:50 -0000	1.3
+++ cron.8	12 Dec 2007 11:39:16 -0000
@@ -15,10 +15,10 @@
 .\" * Paul Vixie          <paul at vix.com>          uunet!decwrl!vixie!paul
 .\" */
 .\"
-.\" $FreeBSD: src/usr.sbin/cron/cron/cron.8,v 1.7.2.9 2003/03/11 21:13:48 trhodes Exp $
+.\" $FreeBSD: src/usr.sbin/cron/cron/cron.8,v 1.25 2007/06/17 17:25:53 yar Exp $
 .\" $DragonFly: src/usr.sbin/cron/cron/cron.8,v 1.3 2006/03/18 20:29:50 dillon Exp $
 .\"
-.Dd December 20, 1993
+.Dd June 17, 2007
 .Dt CRON 8
 .Os
 .Sh NAME
@@ -54,11 +54,22 @@
 .Pa /etc/crontab
 which is in a different format (see
 .Xr crontab 5 ) .
+.Pp
 The
 .Nm
 utility
 then wakes up every minute, examining all stored crontabs, checking each
-command to see if it should be run in the current minute.  When executing
+command to see if it should be run in the current minute.  
+Before running a command from a per-account crontab file,
+.Nm
+checks the status of the account with
+.Xr pam 3
+and skips the command if the account is unavailable,
+e.g., locked out or expired.
+Commands from
+.Pa /etc/crontab
+bypass this check.
+When executing
 commands, any output is mailed to the owner of the crontab (or to the user
 named in the
 .Ev MAILTO
@@ -171,8 +182,21 @@
 trace through the execution, but do not perform any actions
 .El
 .El
+.Sh FILES
+.Bl -tag -width /etc/pam.d/cron -compact
+.It Pa /etc/crontab
+System crontab file
+.It Pa /etc/pam.d/cron
+.Xr pam.conf 5
+configuration file for
+.Nm
+.It Pa /var/cron/tabs
+Directory for personal crontab files
+.El
 .Sh SEE ALSO
 .Xr crontab 1 ,
-.Xr crontab 5
+.Xr pam 3 ,
+.Xr crontab 5 ,
+.Xr pam.conf 5
 .Sh AUTHORS
 .An Paul Vixie Aq paul at vix.com
Index: cron.h
===================================================================
RCS file: /usr/dcvs/src/usr.sbin/cron/cron/cron.h,v
retrieving revision 1.5
diff -u -r1.5 cron.h
--- cron.h	18 Mar 2006 20:29:50 -0000	1.5
+++ cron.h	12 Dec 2007 11:39:16 -0000
@@ -17,7 +17,7 @@
 
 /* cron.h - header for vixie's cron
  *
- * $FreeBSD: src/usr.sbin/cron/cron/cron.h,v 1.9.2.3 2001/05/28 23:37:26 babkin Exp $
+ * $FreeBSD: src/usr.sbin/cron/cron/cron.h,v 1.17 2007/06/17 17:25:53 yar Exp $
  * $DragonFly: src/usr.sbin/cron/cron/cron.h,v 1.5 2006/03/18 20:29:50 dillon Exp $
  *
  * vix 14nov88 [rest of log is in RCS]
@@ -76,6 +76,7 @@
 #define	MAX_UNAME	20	/* max length of username, should be overkill */
 #define	ROOT_UID	0	/* don't change this, it really must be root */
 #define	ROOT_USER	"root"	/* ditto */
+#define	SYS_NAME	"*system*" /* magic owner name for system crontab */
 
 				/* NOTE: these correspond to DebugFlagNames,
 				 *	defined below.
Index: database.c
===================================================================
RCS file: /usr/dcvs/src/usr.sbin/cron/cron/database.c,v
retrieving revision 1.6
diff -u -r1.6 database.c
--- database.c	8 Aug 2005 18:36:28 -0000	1.6
+++ database.c	12 Dec 2007 11:39:16 -0000
@@ -84,7 +84,7 @@
 	new_db.head = new_db.tail = NULL;
 
 	if (syscron_stat.st_mtime) {
-		process_crontab("root", "*system*",
+		process_crontab("root", SYS_NAME,
 				SYSCRONTAB, &syscron_stat,
 				&new_db, old_db);
 	}
@@ -189,7 +189,7 @@
 	int		crontab_fd = OK - 1;
 	user		*u;
 
-	if (strcmp(fname, "*system*") && !(pw = getpwnam(uname))) {
+	if (strcmp(fname, SYS_NAME) && !(pw = getpwnam(uname))) {
 		/* file doesn't have a user in passwd file.
 		 */
 		log_it(fname, getpid(), "ORPHAN", "no passwd entry");
Index: do_command.c
===================================================================
RCS file: /usr/dcvs/src/usr.sbin/cron/cron/do_command.c,v
retrieving revision 1.7
diff -u -r1.7 do_command.c
--- do_command.c	18 Mar 2006 20:29:50 -0000	1.7
+++ do_command.c	12 Dec 2007 11:54:06 -0000
@@ -14,7 +14,7 @@
  * I'll try to keep a version up to date.  I can be reached as follows:
  * Paul Vixie          <paul at vix.com>          uunet!decwrl!vixie!paul
  *
- * $FreeBSD: src/usr.sbin/cron/cron/do_command.c,v 1.15.2.5 2001/05/04 00:59:40 peter Exp $
+ * $FreeBSD: src/usr.sbin/cron/cron/do_command.c,v 1.27 2007/06/17 17:25:53 yar Exp $
  * $DragonFly: src/usr.sbin/cron/cron/do_command.c,v 1.7 2006/03/18 20:29:50 dillon Exp $
  */
 
@@ -29,7 +29,10 @@
 #if defined(LOGIN_CAP)
 # include <login_cap.h>
 #endif
-
+#ifdef PAM
+# include <security/pam_appl.h>
+# include <security/openpam.h>
+#endif
 
 static void		child_process(entry *, user *),
 			do_univ(user *);
@@ -92,6 +95,48 @@
 	usernm = env_get("LOGNAME", e->envp);
 	mailto = env_get("MAILTO", e->envp);
 
+#ifdef PAM
+	/* use PAM to see if the user's account is available,
+	 * i.e., not locked or expired or whatever.  skip this
+	 * for system tasks from /etc/crontab -- they can run
+	 * as any user.
+	 */
+	if (strcmp(u->name, SYS_NAME)) {	/* not equal */
+		pam_handle_t *pamh = NULL;
+		int pam_err;
+		struct pam_conv pamc = {
+			.conv = openpam_nullconv,
+			.appdata_ptr = NULL
+		};
+
+		Debug(DPROC, ("[%d] checking account with PAM\n", getpid()))
+
+		/* u->name keeps crontab owner name while LOGNAME is the name
+		 * of user to run command on behalf of.  they should be the
+		 * same for a task from a per-user crontab.
+		 */
+		if (strcmp(u->name, usernm)) {
+			log_it(usernm, getpid(), "username ambiguity", u->name);
+			exit(ERROR_EXIT);
+		}
+
+		pam_err = pam_start("cron", usernm, &pamc, &pamh);
+		if (pam_err != PAM_SUCCESS) {
+			log_it("CRON", getpid(), "error", "can't start PAM");
+			exit(ERROR_EXIT);
+		}
+
+		pam_err = pam_acct_mgmt(pamh, PAM_SILENT);
+		/* Expired password shouldn't prevent the job from running. */
+		if (pam_err != PAM_SUCCESS && pam_err != PAM_NEW_AUTHTOK_REQD) {
+			log_it(usernm, getpid(), "USER", "account unavailable");
+			exit(ERROR_EXIT);
+		}
+
+		pam_end(pamh, pam_err);
+	}
+#endif
+
 #ifdef USE_SIGCHLD
 	/* our parent is watching for our death by catching SIGCHLD.  we
 	 * do not care to watch for our children's deaths this way -- we




More information about the Submit mailing list