diff --git a/etc/pam.d/Makefile b/etc/pam.d/Makefile index d1ab9f42f356..9e5746cd13fe 100644 --- a/etc/pam.d/Makefile +++ b/etc/pam.d/Makefile @@ -3,6 +3,7 @@ NO_OBJ= FILES= README \ + atrun \ ftpd \ gdm \ imap \ diff --git a/etc/pam.d/atrun b/etc/pam.d/atrun new file mode 100644 index 000000000000..6829469c9595 --- /dev/null +++ b/etc/pam.d/atrun @@ -0,0 +1,10 @@ +# +# $FreeBSD$ +# +# PAM configuration for the "atrun" service +# + +# Note well: enabling pam_nologin for atrun will currently result +# in jobs discarded, not just delayed, during a no-login period. +#account required pam_nologin.so +account required pam_unix.so diff --git a/libexec/atrun/Makefile b/libexec/atrun/Makefile index 40ebd063e9ed..c922dc530329 100644 --- a/libexec/atrun/Makefile +++ b/libexec/atrun/Makefile @@ -12,11 +12,11 @@ BINDIR= ${ATLIB_DIR} CLEANFILES= ${MAN} CFLAGS+=-I${MAINSRC} -I${.CURDIR} -CFLAGS+=-DLOGIN_CAP +CFLAGS+=-DLOGIN_CAP -DPAM WFORMAT=0 -DPADD= ${LIBUTIL} -LDADD= -lutil +DPADD= ${LIBPAM} ${LIBUTIL} +LDADD= -lpam -lutil atrun.8: atrun.man @${ECHO} Making ${.TARGET:T} from ${.ALLSRC:T}; \ diff --git a/libexec/atrun/atrun.c b/libexec/atrun/atrun.c index 374c10b68235..a7cef873eeef 100644 --- a/libexec/atrun/atrun.c +++ b/libexec/atrun/atrun.c @@ -58,6 +58,10 @@ static const char rcsid[] = #ifdef LOGIN_CAP #include #endif +#ifdef PAM +#include +#include +#endif #if (MAXLOGNAME-1) > UT_NAMESIZE #define LOGNAMESIZE UT_NAMESIZE @@ -87,6 +91,7 @@ static const char rcsid[] = /* File scope variables */ +static const char * const atrun = "atrun"; /* service name for syslog etc. */ static int debug = 0; void perr(const char *fmt, ...); @@ -135,7 +140,14 @@ run_file(const char *filename, uid_t uid, gid_t gid) int fflags; long nuid; long ngid; - +#ifdef PAM + pam_handle_t *pamh = NULL; + int pam_err; + struct pam_conv pamc = { + .conv = openpam_nullconv, + .appdata_ptr = NULL + }; +#endif PRIV_START @@ -163,18 +175,31 @@ run_file(const char *filename, uid_t uid, gid_t gid) perrx("Userid %lu not found - aborting job %s", (unsigned long) uid, filename); +#ifdef PAM + PRIV_START + + pam_err = pam_start(atrun, pentry->pw_name, &pamc, &pamh); + if (pam_err != PAM_SUCCESS) + perrx("cannot start PAM: %s", pam_strerror(pamh, pam_err)); + + 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) + perrx("Account %s (userid %lu) unavailable for job %s: %s", + pentry->pw_name, (unsigned long)uid, + filename, pam_strerror(pamh, pam_err)); + + pam_end(pamh, pam_err); + + PRIV_END +#endif /* PAM */ + PRIV_START stream=fopen(filename, "r"); PRIV_END -#ifdef __FreeBSD__ - if (pentry->pw_expire && time(NULL) >= pentry->pw_expire) - perrx("Userid %lu is expired - aborting job %s", - (unsigned long) uid, filename); -#endif - if (stream == NULL) perr("cannot open input file"); @@ -444,7 +469,7 @@ main(int argc, char *argv[]) RELINQUISH_PRIVS_ROOT(DAEMON_UID, DAEMON_GID) - openlog("atrun", LOG_PID, LOG_CRON); + openlog(atrun, LOG_PID, LOG_CRON); opterr = 0; while((c=getopt(argc, argv, "dl:"))!= -1)