Fix 'calendar -a' in several ways.

o Do not run any iconv() processing in -a. The locale of root user is not
  what is desired by most of the users who receive their calendar mail.
  Just assume that users store their calendars in a format that is readable
  to them. This fixes regression from r344340.
o fork() and setusercontext(LOGIN_SETALL) for every user. This makes LANG
  set inside a calendar file mostly excessive, as we will pick up user's
  login class LANG.
o This also executes complex function cal() that parses user owned files
  with appropriate user privileges.
  Previously it was run with privileges dropped only temporary for execution
  of cal(), and fully dropped only before invoking sendmail (see r22473).

Reviewed by:	bapt (older version of patch)
This commit is contained in:
glebius 2019-09-10 04:21:48 +00:00
parent 259fac9439
commit 7ff75f4a5a
3 changed files with 38 additions and 30 deletions

View File

@ -6,7 +6,7 @@
PROG= calendar
SRCS= calendar.c locale.c events.c dates.c parsedata.c io.c day.c \
ostern.c paskha.c pom.c sunpos.c
LIBADD= m
LIBADD= m util
INTER= de_AT.ISO_8859-15 de_DE.ISO8859-1 fr_FR.ISO8859-1 \
hr_HR.ISO8859-2 hu_HU.ISO8859-2 pt_BR.ISO8859-1 \
pt_BR.UTF-8 ru_RU.KOI8-R ru_RU.UTF-8 uk_UA.KOI8-U

View File

@ -44,9 +44,11 @@ static char sccsid[] = "@(#)calendar.c 8.3 (Berkeley) 3/25/94";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <locale.h>
#include <login_cap.h>
#include <langinfo.h>
#include <pwd.h>
#include <stdio.h>
@ -68,7 +70,7 @@ static time_t f_time = 0;
double UTCOffset = UTCOFFSET_NOTSET;
int EastLongitude = LONGITUDE_NOTSET;
#ifdef WITH_ICONV
const char *outputEncoding;
const char *outputEncoding = NULL;
#endif
static void usage(void) __dead2;
@ -84,12 +86,6 @@ main(int argc, char *argv[])
struct tm tp1, tp2;
(void)setlocale(LC_ALL, "");
#ifdef WITH_ICONV
/* save the information about the encoding used in the terminal */
outputEncoding = strdup(nl_langinfo(CODESET));
if (outputEncoding == NULL)
errx(1, "cannot allocate memory");
#endif
while ((ch = getopt(argc, argv, "-A:aB:D:dF:f:l:t:U:W:?")) != -1)
switch (ch) {
@ -218,15 +214,33 @@ main(int argc, char *argv[])
if (doall)
while ((pw = getpwent()) != NULL) {
(void)setegid(pw->pw_gid);
(void)initgroups(pw->pw_name, pw->pw_gid);
(void)seteuid(pw->pw_uid);
if (!chdir(pw->pw_dir))
pid_t pid;
if (chdir(pw->pw_dir) == -1)
continue;
pid = fork();
if (pid < 0)
err(1, "fork");
if (pid == 0) {
login_cap_t *lc;
lc = login_getpwclass(pw);
if (setusercontext(lc, pw, pw->pw_uid,
LOGIN_SETALL) != 0)
errx(1, "setusercontext");
cal();
(void)seteuid(0);
exit(0);
}
}
else
else {
#ifdef WITH_ICONV
/* Save the information about the encoding used in the terminal. */
outputEncoding = strdup(nl_langinfo(CODESET));
if (outputEncoding == NULL)
errx(1, "cannot allocate memory");
#endif
cal();
}
exit(0);
}

View File

@ -290,16 +290,24 @@ cal_parse(FILE *in, FILE *out)
if (buf[0] == '\0')
continue;
/* Parse special definitions: LANG, Easter, Paskha etc */
/*
* Setting LANG in user's calendar was an old workaround
* for 'calendar -a' being run with C locale to properly
* print user's calendars in their native languages.
* Now that 'calendar -a' does fork with setusercontext(),
* and does not run iconv(), this variable has little use.
*/
if (strncmp(buf, "LANG=", 5) == 0) {
(void)setlocale(LC_ALL, buf + 5);
d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
#ifdef WITH_ICONV
set_new_encoding();
if (!doall)
set_new_encoding();
#endif
setnnames();
continue;
}
/* Parse special definitions: Easter, Paskha etc */
REPLACE("Easter=", 7, neaster);
REPLACE("Paskha=", 7, npaskha);
REPLACE("ChineseNewYear=", 15, ncny);
@ -445,7 +453,6 @@ opencalout(void)
void
closecal(FILE *fp)
{
uid_t uid;
struct stat sbuf;
int nread, pdes[2], status;
char buf[1024];
@ -470,19 +477,6 @@ closecal(FILE *fp)
(void)close(pdes[0]);
}
(void)close(pdes[1]);
uid = geteuid();
if (setuid(getuid()) < 0) {
warnx("setuid failed");
_exit(1);
}
if (setgid(getegid()) < 0) {
warnx("setgid failed");
_exit(1);
}
if (setuid(uid) < 0) {
warnx("setuid failed");
_exit(1);
}
execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",
"\"Reminder Service\"", (char *)NULL);
warn(_PATH_SENDMAIL);