diff --git a/usr.sbin/cron/cron/cron.h b/usr.sbin/cron/cron/cron.h index c125874686f..1effde41fe7 100644 --- a/usr.sbin/cron/cron/cron.h +++ b/usr.sbin/cron/cron/cron.h @@ -237,7 +237,7 @@ user *load_user __P((int, struct passwd *, char *)), entry *load_entry __P((FILE *, void (*)(), struct passwd *, char **)); -FILE *cron_popen __P((char *, char *)); +FILE *cron_popen __P((char *, char *, entry *)); /* in the C tradition, we only create diff --git a/usr.sbin/cron/cron/do_command.c b/usr.sbin/cron/cron/do_command.c index 009d21ba8c1..1e65b418983 100644 --- a/usr.sbin/cron/cron/do_command.c +++ b/usr.sbin/cron/cron/do_command.c @@ -418,11 +418,11 @@ child_process(e, u) (void) gethostname(hostname, MAXHOSTNAMELEN); (void) snprintf(mailcmd, sizeof(mailcmd), MAILARGS, MAILCMD); - if (!(mail = cron_popen(mailcmd, "w"))) { + if (!(mail = cron_popen(mailcmd, "w", e))) { warn("%s", MAILCMD); (void) _exit(ERROR_EXIT); } - fprintf(mail, "From: root (Cron Daemon)\n"); + fprintf(mail, "From: %s (Cron Daemon)\n", usernm); fprintf(mail, "To: %s\n", mailto); fprintf(mail, "Subject: Cron <%s@%s> %s\n", usernm, first_word(hostname, "."), diff --git a/usr.sbin/cron/cron/popen.c b/usr.sbin/cron/cron/popen.c index e0861f5614b..56f85e71d47 100644 --- a/usr.sbin/cron/cron/popen.c +++ b/usr.sbin/cron/cron/popen.c @@ -34,6 +34,12 @@ static const char rcsid[] = #include "cron.h" #include #include +#if defined(SYSLOG) +# include +#endif +#if defined(LOGIN_CAP) +# include +#endif #define MAX_ARGS 100 @@ -48,14 +54,20 @@ static PID_T *pids; static int fds; FILE * -cron_popen(program, type) +cron_popen(program, type, e) char *program, *type; + entry *e; { register char *cp; FILE *iop; int argc, pdes[2]; PID_T pid; + char *usernm; char *argv[MAX_ARGS + 1]; +# if defined(LOGIN_CAP) + struct passwd *pwd; + login_cap_t *lc; +# endif #if WANT_GLOBBING char **pop, *vv[2]; int gargc; @@ -106,6 +118,15 @@ cron_popen(program, type) goto pfree; /* NOTREACHED */ case 0: /* child */ + if (e != NULL) { +#ifdef SYSLOG + closelog(); +#endif + + /* get new pgrp, void tty, etc. + */ + (void) setsid(); + } if (*type == 'r') { /* Do not share our parent's stdin */ (void)close(0); @@ -128,6 +149,42 @@ cron_popen(program, type) (void)open("/dev/null", O_RDWR); (void)close(pdes[1]); } +# if defined(LOGIN_CAP) + if (e != NULL) { + /* Set user's entire context, but skip the environment + * as cron provides a separate interface for this + */ + usernm = env_get("LOGNAME", e->envp); + if ((pwd = getpwnam(usernm)) == NULL) + pwd = getpwuid(e->uid); + lc = NULL; + if (pwd != NULL) { + pwd->pw_gid = e->gid; + if (e->class != NULL) + lc = login_getclass(e->class); + } + if (pwd && + setusercontext(lc, pwd, e->uid, + LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETENV)) == 0) + (void) endpwent(); + else { + /* fall back to the old method */ + (void) endpwent(); +# endif + /* set our directory, uid and gid. Set gid first, + * since once we set uid, we've lost root privledges. + */ + setgid(e->gid); +# if defined(BSD) + initgroups(usernm, e->gid); +# endif + setlogin(usernm); + setuid(e->uid); /* we aren't root after this..*/ +#if defined(LOGIN_CAP) + } +#endif + chdir(env_get("HOME", e->envp)); + } #if WANT_GLOBBING execvp(gargv[0], gargv); #else