Use gmtime_r() and localtime_r() instead of gmtime() and localtime().

This commit is contained in:
Todd C. Miller
2021-09-17 10:55:06 -06:00
parent fa71679b5a
commit 18f1884ddc
15 changed files with 135 additions and 166 deletions

View File

@@ -424,7 +424,7 @@ send_mail(const struct eventlog *evlog, const char *fmt, ...)
const struct eventlog_config *evl_conf = eventlog_getconf(); const struct eventlog_config *evl_conf = eventlog_getconf();
const char *cp, *timefmt = evl_conf->time_fmt; const char *cp, *timefmt = evl_conf->time_fmt;
char timebuf[1024]; char timebuf[1024];
struct tm *tm; struct tm gmt;
time_t now; time_t now;
FILE *mail; FILE *mail;
int fd, pfd[2], status; int fd, pfd[2], status;
@@ -445,7 +445,7 @@ send_mail(const struct eventlog *evlog, const char *fmt, ...)
debug_return_bool(false); debug_return_bool(false);
time(&now); time(&now);
if ((tm = gmtime(&now)) == NULL) if (gmtime_r(&now, &gmt) == NULL)
debug_return_bool(false); debug_return_bool(false);
/* Fork and return, child will daemonize. */ /* Fork and return, child will daemonize. */
@@ -568,7 +568,7 @@ send_mail(const struct eventlog *evlog, const char *fmt, ...)
(void) fprintf(mail, "\nContent-Type: text/plain; charset=\"%s\"\nContent-Transfer-Encoding: 8bit", nl_langinfo(CODESET)); (void) fprintf(mail, "\nContent-Type: text/plain; charset=\"%s\"\nContent-Transfer-Encoding: 8bit", nl_langinfo(CODESET));
#endif /* HAVE_NL_LANGINFO && CODESET */ #endif /* HAVE_NL_LANGINFO && CODESET */
strftime(timebuf, sizeof(timebuf), timefmt, tm); strftime(timebuf, sizeof(timebuf), timefmt, &gmt);
if (evlog != NULL) { if (evlog != NULL) {
(void) fprintf(mail, "\n\n%s : %s : %s : ", evlog->submithost, timebuf, (void) fprintf(mail, "\n\n%s : %s : %s : ", evlog->submithost, timebuf,
evlog->submituser); evlog->submituser);
@@ -619,16 +619,16 @@ json_add_timestamp(struct json_container *json, const char *name,
const char *timefmt = evl_conf->time_fmt; const char *timefmt = evl_conf->time_fmt;
time_t secs = ts->tv_sec; time_t secs = ts->tv_sec;
char timebuf[1024]; char timebuf[1024];
struct tm *tm; struct tm gmt;
if ((tm = gmtime(&secs)) != NULL) { if (gmtime_r(&secs, &gmt) != NULL) {
strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", tm); strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt);
json_value.type = JSON_STRING; json_value.type = JSON_STRING;
json_value.u.string = timebuf; // -V507 json_value.u.string = timebuf; // -V507
if (!sudo_json_add_value(json, "iso8601", &json_value)) if (!sudo_json_add_value(json, "iso8601", &json_value))
goto oom; goto oom;
strftime(timebuf, sizeof(timebuf), timefmt, tm); strftime(timebuf, sizeof(timebuf), timefmt, &gmt);
json_value.type = JSON_STRING; json_value.type = JSON_STRING;
json_value.u.string = timebuf; // -V507 json_value.u.string = timebuf; // -V507
if (!sudo_json_add_value(json, "localtime", &json_value)) if (!sudo_json_add_value(json, "localtime", &json_value))
@@ -1117,7 +1117,7 @@ do_logfile_sudo(const char *logline, const struct eventlog *evlog,
const char *timefmt = evl_conf->time_fmt; const char *timefmt = evl_conf->time_fmt;
const char *logfile = evl_conf->logpath; const char *logfile = evl_conf->logpath;
time_t tv_sec = event_time->tv_sec; time_t tv_sec = event_time->tv_sec;
struct tm *timeptr; struct tm tm;
bool ret = false; bool ret = false;
FILE *fp; FILE *fp;
int len; int len;
@@ -1132,10 +1132,10 @@ do_logfile_sudo(const char *logline, const struct eventlog *evlog,
goto done; goto done;
} }
if ((timeptr = localtime(&tv_sec)) != NULL) { if (localtime_r(&tv_sec, &tm) != NULL) {
/* strftime() does not guarantee to NUL-terminate so we must check. */ /* strftime() does not guarantee to NUL-terminate so we must check. */
timebuf[sizeof(timebuf) - 1] = '\0'; timebuf[sizeof(timebuf) - 1] = '\0';
if (strftime(timebuf, sizeof(timebuf), timefmt, timeptr) != 0 && if (strftime(timebuf, sizeof(timebuf), timefmt, &tm) != 0 &&
timebuf[sizeof(timebuf) - 1] == '\0') { timebuf[sizeof(timebuf) - 1] == '\0') {
timestr = timebuf; timestr = timebuf;
} }

View File

@@ -103,16 +103,16 @@ expand_iolog_path(const char *inpath, char *path, size_t pathlen,
/* Expand strftime escapes as needed. */ /* Expand strftime escapes as needed. */
if (strfit) { if (strfit) {
struct tm tm;
time_t now; time_t now;
struct tm *timeptr;
time(&now); time(&now);
if ((timeptr = localtime(&now)) == NULL) if (localtime_r(&now, &tm) == NULL)
goto bad; goto bad;
/* We only call strftime() on the current part of the buffer. */ /* We only call strftime() on the current part of the buffer. */
tmpbuf[sizeof(tmpbuf) - 1] = '\0'; tmpbuf[sizeof(tmpbuf) - 1] = '\0';
len = strftime(tmpbuf, sizeof(tmpbuf), path, timeptr); len = strftime(tmpbuf, sizeof(tmpbuf), path, &tm);
if (len == 0 || tmpbuf[sizeof(tmpbuf) - 1] != '\0') if (len == 0 || tmpbuf[sizeof(tmpbuf) - 1] != '\0')
goto bad; /* strftime() failed, buf too small? */ goto bad; /* strftime() failed, buf too small? */

View File

@@ -130,20 +130,19 @@ do_check(char *dir_in, char *file_in, char *tdir_out, char *tfile_out)
{ {
char dir[PATH_MAX], dir_out[PATH_MAX]; char dir[PATH_MAX], dir_out[PATH_MAX];
char file[PATH_MAX], file_out[PATH_MAX]; char file[PATH_MAX], file_out[PATH_MAX];
struct tm *timeptr; struct tm tm;
time_t now; time_t now;
int error = 0; int error = 0;
/* /*
* Expand any strftime(3) escapes * Expand any strftime(3) escapes
* XXX - want to pass timeptr to expand_iolog_path * XXX - want to pass tm to expand_iolog_path
*/ */
time(&now); time(&now);
timeptr = localtime(&now); if (localtime_r(&now, &tm) == NULL)
if (timeptr == NULL) sudo_fatal("localtime_r");
sudo_fatalx("localtime returned NULL"); strftime(dir_out, sizeof(dir_out), tdir_out, &tm);
strftime(dir_out, sizeof(dir_out), tdir_out, timeptr); strftime(file_out, sizeof(file_out), tfile_out, &tm);
strftime(file_out, sizeof(file_out), tfile_out, timeptr);
if (!expand_iolog_path(dir_in, dir, sizeof(dir), &path_escapes[1], NULL)) if (!expand_iolog_path(dir_in, dir, sizeof(dir), &path_escapes[1], NULL))
sudo_fatalx("unable to expand I/O log dir"); sudo_fatalx("unable to expand I/O log dir");

View File

@@ -617,9 +617,10 @@ sudo_debug_write2_v1(int fd, const char *func, const char *file, int lineno,
timebuf[0] = '\0'; timebuf[0] = '\0';
if (gettimeofday(&tv, NULL) != -1) { if (gettimeofday(&tv, NULL) != -1) {
time_t now = tv.tv_sec; time_t now = tv.tv_sec;
struct tm *tm = localtime(&now); struct tm tm;
if (tm != NULL) { size_t tlen;
size_t tlen = strftime(timebuf, sizeof(timebuf), "%b %e %H:%M:%S", tm); if (localtime_r(&now, &tm) != NULL) {
tlen = strftime(timebuf, sizeof(timebuf), "%b %e %H:%M:%S", &tm);
if (tlen == 0) { if (tlen == 0) {
/* contents are undefined on error */ /* contents are undefined on error */
timebuf[0] = '\0'; timebuf[0] = '\0';

View File

@@ -341,10 +341,10 @@ add_timestamp(struct json_container *json, struct timespec *ts)
struct json_value json_value; struct json_value json_value;
time_t secs = ts->tv_sec; time_t secs = ts->tv_sec;
char timebuf[1024]; char timebuf[1024];
struct tm *tm; struct tm gmt;
debug_decl(add_timestamp, SUDO_DEBUG_PLUGIN); debug_decl(add_timestamp, SUDO_DEBUG_PLUGIN);
if ((tm = gmtime(&secs)) == NULL) if (gmtime_r(&secs, &gmt) == NULL)
debug_return_bool(false); debug_return_bool(false);
sudo_json_open_object(json, "timestamp"); sudo_json_open_object(json, "timestamp");
@@ -357,12 +357,12 @@ add_timestamp(struct json_container *json, struct timespec *ts)
json_value.u.number = ts->tv_nsec; json_value.u.number = ts->tv_nsec;
sudo_json_add_value(json, "nanoseconds", &json_value); sudo_json_add_value(json, "nanoseconds", &json_value);
strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", tm); strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt);
json_value.type = JSON_STRING; json_value.type = JSON_STRING;
json_value.u.string = timebuf; json_value.u.string = timebuf;
sudo_json_add_value(json, "iso8601", &json_value); sudo_json_add_value(json, "iso8601", &json_value);
strftime(timebuf, sizeof(timebuf), "%a %b %e %H:%M:%S %Z %Y", tm); strftime(timebuf, sizeof(timebuf), "%a %b %e %H:%M:%S %Z %Y", &gmt);
json_value.type = JSON_STRING; json_value.type = JSON_STRING;
json_value.u.string = timebuf; json_value.u.string = timebuf;
sudo_json_add_value(json, "localtime", &json_value); sudo_json_add_value(json, "localtime", &json_value);

View File

@@ -117,7 +117,7 @@ static int
sample_approval_check(char * const command_info[], char * const run_argv[], sample_approval_check(char * const command_info[], char * const run_argv[],
char * const run_envp[], const char **errstr) char * const run_envp[], const char **errstr)
{ {
struct tm *tm; struct tm tm;
time_t now; time_t now;
int ret = 0; int ret = 0;
debug_decl(sample_approval_check, SUDO_DEBUG_PLUGIN); debug_decl(sample_approval_check, SUDO_DEBUG_PLUGIN);
@@ -126,14 +126,14 @@ sample_approval_check(char * const command_info[], char * const run_argv[],
* Only approve requests that are within business hours, * Only approve requests that are within business hours,
* which are 9am - 5pm local time. Does not check holidays. * which are 9am - 5pm local time. Does not check holidays.
*/ */
if (time(&now) == -1 || (tm = localtime(&now)) == NULL) if (time(&now) == -1 || localtime_r(&now, &tm) == NULL)
goto done; goto done;
if (tm->tm_wday < 1 || tm->tm_wday > 5) { if (tm.tm_wday < 1 || tm.tm_wday > 5) {
/* bad weekday */ /* bad weekday */
goto done; goto done;
} }
if (tm->tm_hour < 9 || tm->tm_hour > 17 || if (tm.tm_hour < 9 || tm.tm_hour > 17 ||
(tm->tm_hour == 17 && tm->tm_min > 0)) { (tm.tm_hour == 17 && tm.tm_min > 0)) {
/* bad hour */ /* bad hour */
goto done; goto done;
} }

View File

@@ -597,7 +597,7 @@ print_cmndspec_json(struct json_container *jsonc,
struct json_value value; struct json_value value;
struct defaults *def; struct defaults *def;
struct member *m; struct member *m;
struct tm *tp; struct tm gmt;
char timebuf[sizeof("20120727121554Z")]; char timebuf[sizeof("20120727121554Z")];
debug_decl(print_cmndspec_json, SUDOERS_DEBUG_UTIL); debug_decl(print_cmndspec_json, SUDOERS_DEBUG_UTIL);
@@ -647,10 +647,10 @@ print_cmndspec_json(struct json_container *jsonc,
sudo_json_add_value_as_object(jsonc, "command_timeout", &value); sudo_json_add_value_as_object(jsonc, "command_timeout", &value);
} }
if (cs->notbefore != UNSPEC) { if (cs->notbefore != UNSPEC) {
if ((tp = gmtime(&cs->notbefore)) == NULL) { if (gmtime_r(&cs->notbefore, &gmt) == NULL) {
sudo_warn("%s", U_("unable to get GMT time")); sudo_warn("%s", U_("unable to get GMT time"));
} else { } else {
if (strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", tp) == 0) { if (strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt) == 0) {
sudo_warnx("%s", U_("unable to format timestamp")); sudo_warnx("%s", U_("unable to format timestamp"));
} else { } else {
value.type = JSON_STRING; value.type = JSON_STRING;
@@ -660,10 +660,10 @@ print_cmndspec_json(struct json_container *jsonc,
} }
} }
if (cs->notafter != UNSPEC) { if (cs->notafter != UNSPEC) {
if ((tp = gmtime(&cs->notafter)) == NULL) { if (gmtime_r(&cs->notafter, &gmt) == NULL) {
sudo_warn("%s", U_("unable to get GMT time")); sudo_warn("%s", U_("unable to get GMT time"));
} else { } else {
if (strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", tp) == 0) { if (strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt) == 0) {
sudo_warnx("%s", U_("unable to format timestamp")); sudo_warnx("%s", U_("unable to format timestamp"));
} else { } else {
value.type = JSON_STRING; value.type = JSON_STRING;

View File

@@ -318,7 +318,7 @@ print_cmndspec_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree,
{ {
struct cmndspec *next = *nextp; struct cmndspec *next = *nextp;
struct member *m; struct member *m;
struct tm *tp; struct tm gmt;
char *attr_val; char *attr_val;
bool last_one; bool last_one;
char timebuf[sizeof("20120727121554Z")]; char timebuf[sizeof("20120727121554Z")];
@@ -342,10 +342,10 @@ print_cmndspec_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree,
/* Print sudoNotBefore and sudoNotAfter attributes */ /* Print sudoNotBefore and sudoNotAfter attributes */
if (cs->notbefore != UNSPEC) { if (cs->notbefore != UNSPEC) {
if ((tp = gmtime(&cs->notbefore)) == NULL) { if (gmtime_r(&cs->notbefore, &gmt) == NULL) {
sudo_warn("%s", U_("unable to get GMT time")); sudo_warn("%s", U_("unable to get GMT time"));
} else { } else {
if (strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", tp) == 0) { if (strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt) == 0) {
sudo_warnx("%s", U_("unable to format timestamp")); sudo_warnx("%s", U_("unable to format timestamp"));
} else { } else {
print_attribute_ldif(fp, "sudoNotBefore", timebuf); print_attribute_ldif(fp, "sudoNotBefore", timebuf);
@@ -353,10 +353,10 @@ print_cmndspec_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree,
} }
} }
if (cs->notafter != UNSPEC) { if (cs->notafter != UNSPEC) {
if ((tp = gmtime(&cs->notafter)) == NULL) { if (gmtime_r(&cs->notafter, &gmt) == NULL) {
sudo_warn("%s", U_("unable to get GMT time")); sudo_warn("%s", U_("unable to get GMT time"));
} else { } else {
if (strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", tp) == 0) { if (strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt) == 0) {
sudo_warnx("%s", U_("unable to format timestamp")); sudo_warnx("%s", U_("unable to format timestamp"));
} else { } else {
print_attribute_ldif(fp, "sudoNotAfter", timebuf); print_attribute_ldif(fp, "sudoNotAfter", timebuf);

View File

@@ -241,15 +241,19 @@ sudoers_format_cmndspec(struct sudo_lbuf *lbuf,
} }
if (cs->notbefore != UNSPEC && FIELD_CHANGED(prev_cs, cs, notbefore)) { if (cs->notbefore != UNSPEC && FIELD_CHANGED(prev_cs, cs, notbefore)) {
char buf[sizeof("CCYYMMDDHHMMSSZ")]; char buf[sizeof("CCYYMMDDHHMMSSZ")];
struct tm *tm = gmtime(&cs->notbefore); struct tm gmt;
if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", tm) != 0) if (gmtime_r(&cs->notbefore, &gmt) != NULL) {
sudo_lbuf_append(lbuf, "NOTBEFORE=%s ", buf); if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", &gmt) != 0)
sudo_lbuf_append(lbuf, "NOTBEFORE=%s ", buf);
}
} }
if (cs->notafter != UNSPEC && FIELD_CHANGED(prev_cs, cs, notafter)) { if (cs->notafter != UNSPEC && FIELD_CHANGED(prev_cs, cs, notafter)) {
char buf[sizeof("CCYYMMDDHHMMSSZ")]; char buf[sizeof("CCYYMMDDHHMMSSZ")];
struct tm *tm = gmtime(&cs->notafter); struct tm gmt;
if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", tm) != 0) if (gmtime_r(&cs->notafter, &gmt) != NULL) {
sudo_lbuf_append(lbuf, "NOTAFTER=%s ", buf); if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", &gmt) != 0)
sudo_lbuf_append(lbuf, "NOTAFTER=%s ", buf);
}
} }
if (TAG_CHANGED(prev_cs, cs, tags, setenv)) if (TAG_CHANGED(prev_cs, cs, tags, setenv))
sudo_lbuf_append(lbuf, tags.setenv ? "SETENV: " : "NOSETENV: "); sudo_lbuf_append(lbuf, tags.setenv ? "SETENV: " : "NOSETENV: ");

View File

@@ -577,7 +577,7 @@ Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes,
static int DaysInMonth[12] = { static int DaysInMonth[12] = {
31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
}; };
struct tm *tm; struct tm tm;
time_t tod; time_t tod;
time_t Julian; time_t Julian;
int i; int i;
@@ -610,7 +610,7 @@ Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes,
return -1; return -1;
Julian += tod; Julian += tod;
if (DSTmode == DSTon if (DSTmode == DSTon
|| (DSTmode == DSTmaybe && (tm = localtime(&Julian)) && tm->tm_isdst)) || (DSTmode == DSTmaybe && localtime_r(&Julian, &tm) && tm.tm_isdst))
Julian -= 60 * 60; Julian -= 60 * 60;
return Julian; return Julian;
} }
@@ -619,18 +619,16 @@ Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes,
static time_t static time_t
DSTcorrect(time_t Start, time_t Future) DSTcorrect(time_t Start, time_t Future)
{ {
struct tm *start_tm; struct tm start_tm;
struct tm *future_tm; struct tm future_tm;
time_t StartDay; time_t StartDay;
time_t FutureDay; time_t FutureDay;
start_tm = localtime(&Start); if (!localtime_r(&Start, &start_tm) || !localtime_r(&Future, &future_tm))
future_tm = localtime(&Future);
if (!start_tm || !future_tm)
return -1; return -1;
StartDay = (start_tm->tm_hour + 1) % 24; StartDay = (start_tm.tm_hour + 1) % 24;
FutureDay = (future_tm->tm_hour + 1) % 24; FutureDay = (future_tm.tm_hour + 1) % 24;
return (Future - Start) + (StartDay - FutureDay) * 60L * 60L; return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
} }
@@ -638,13 +636,13 @@ DSTcorrect(time_t Start, time_t Future)
static time_t static time_t
RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber) RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
{ {
struct tm *tm; struct tm tm;
time_t now; time_t now;
now = Start; now = Start;
if (!(tm = localtime(&now))) if (!localtime_r(&now, &tm))
return -1; return -1;
now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7); now += SECSPERDAY * ((DayNumber - tm.tm_wday + 7) % 7);
now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1); now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
return DSTcorrect(Start, now); return DSTcorrect(Start, now);
} }
@@ -653,20 +651,20 @@ RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
static time_t static time_t
RelativeMonth(time_t Start, time_t RelMonth) RelativeMonth(time_t Start, time_t RelMonth)
{ {
struct tm *tm; struct tm tm;
time_t Month; time_t Month;
time_t Year; time_t Year;
if (RelMonth == 0) if (RelMonth == 0)
return 0; return 0;
if (!(tm = localtime(&Start))) if (!localtime_r(&Start, &tm))
return -1; return -1;
Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth; Month = 12 * (tm.tm_year + 1900) + tm.tm_mon + RelMonth;
Year = Month / 12; Year = Month / 12;
Month = Month % 12 + 1; Month = Month % 12 + 1;
return DSTcorrect(Start, return DSTcorrect(Start,
Convert(Month, (time_t)tm->tm_mday, Year, Convert(Month, (time_t)tm.tm_mday, Year,
(time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec, (time_t)tm.tm_hour, (time_t)tm.tm_min, (time_t)tm.tm_sec,
MER24, DSTmaybe)); MER24, DSTmaybe));
} }
@@ -855,7 +853,7 @@ difftm(struct tm *a, struct tm *b)
time_t time_t
get_date(char *p) get_date(char *p)
{ {
struct tm *tm, *gmt, gmtbuf; struct tm tm, gmt;
time_t Start; time_t Start;
time_t tod; time_t tod;
time_t now; time_t now;
@@ -864,36 +862,19 @@ get_date(char *p)
yyInput = p; yyInput = p;
(void)time (&now); (void)time (&now);
gmt = gmtime (&now); if (gmtime_r (&now, &gmt) == NULL)
if (gmt != NULL)
{
/* Make a copy, in case localtime modifies *tm (I think
that comment now applies to *gmt, but I am too
lazy to dig into how gmtime and locatime allocate the
structures they return pointers to). */
gmtbuf = *gmt;
gmt = &gmtbuf;
}
if (! (tm = localtime (&now)))
return -1; return -1;
if (gmt != NULL) if (localtime_r (&now, &tm) == NULL)
tz = difftm (gmt, tm) / 60; return -1;
else
/* We are on a system like VMS, where the system clock is
in local time and the system has no concept of timezones.
Hopefully we can fake this out (for the case in which the
user specifies no timezone) by just saying the timezone
is zero. */
tz = 0;
if(tm->tm_isdst) tz = difftm (&gmt, &tm) / 60;
if (tm.tm_isdst)
tz += 60; tz += 60;
yyYear = tm->tm_year + 1900; yyYear = tm.tm_year + 1900;
yyMonth = tm->tm_mon + 1; yyMonth = tm.tm_mon + 1;
yyDay = tm->tm_mday; yyDay = tm.tm_mday;
yyTimezone = tz; yyTimezone = tz;
yyDSTmode = DSTmaybe; yyDSTmode = DSTmaybe;
yyHour = 0; yyHour = 0;
@@ -921,7 +902,7 @@ get_date(char *p)
else { else {
Start = now; Start = now;
if (!yyHaveRel) if (!yyHaveRel)
Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec; Start -= ((tm.tm_hour * 60L + tm.tm_min) * 60L) + tm.tm_sec;
} }
Start += yyRelSeconds; Start += yyRelSeconds;
@@ -962,7 +943,7 @@ main(int argc, char *argv[])
/* NOTREACHED */ /* NOTREACHED */
} }
#endif /* TEST */ #endif /* TEST */
#line 952 "getdate.c" #line 933 "getdate.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */ /* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(void) static int yygrowstack(void)
{ {
@@ -1442,7 +1423,7 @@ case 41:
yyval.Meridian = yyvsp[0].Meridian; yyval.Meridian = yyvsp[0].Meridian;
} }
break; break;
#line 1432 "getdate.c" #line 1413 "getdate.c"
} }
yyssp -= yym; yyssp -= yym;
yystate = *yyssp; yystate = *yyssp;

View File

@@ -549,7 +549,7 @@ Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes,
static int DaysInMonth[12] = { static int DaysInMonth[12] = {
31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
}; };
struct tm *tm; struct tm tm;
time_t tod; time_t tod;
time_t Julian; time_t Julian;
int i; int i;
@@ -582,7 +582,7 @@ Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes,
return -1; return -1;
Julian += tod; Julian += tod;
if (DSTmode == DSTon if (DSTmode == DSTon
|| (DSTmode == DSTmaybe && (tm = localtime(&Julian)) && tm->tm_isdst)) || (DSTmode == DSTmaybe && localtime_r(&Julian, &tm) && tm.tm_isdst))
Julian -= 60 * 60; Julian -= 60 * 60;
return Julian; return Julian;
} }
@@ -591,18 +591,16 @@ Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes,
static time_t static time_t
DSTcorrect(time_t Start, time_t Future) DSTcorrect(time_t Start, time_t Future)
{ {
struct tm *start_tm; struct tm start_tm;
struct tm *future_tm; struct tm future_tm;
time_t StartDay; time_t StartDay;
time_t FutureDay; time_t FutureDay;
start_tm = localtime(&Start); if (!localtime_r(&Start, &start_tm) || !localtime_r(&Future, &future_tm))
future_tm = localtime(&Future);
if (!start_tm || !future_tm)
return -1; return -1;
StartDay = (start_tm->tm_hour + 1) % 24; StartDay = (start_tm.tm_hour + 1) % 24;
FutureDay = (future_tm->tm_hour + 1) % 24; FutureDay = (future_tm.tm_hour + 1) % 24;
return (Future - Start) + (StartDay - FutureDay) * 60L * 60L; return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
} }
@@ -610,13 +608,13 @@ DSTcorrect(time_t Start, time_t Future)
static time_t static time_t
RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber) RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
{ {
struct tm *tm; struct tm tm;
time_t now; time_t now;
now = Start; now = Start;
if (!(tm = localtime(&now))) if (!localtime_r(&now, &tm))
return -1; return -1;
now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7); now += SECSPERDAY * ((DayNumber - tm.tm_wday + 7) % 7);
now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1); now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
return DSTcorrect(Start, now); return DSTcorrect(Start, now);
} }
@@ -625,20 +623,20 @@ RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
static time_t static time_t
RelativeMonth(time_t Start, time_t RelMonth) RelativeMonth(time_t Start, time_t RelMonth)
{ {
struct tm *tm; struct tm tm;
time_t Month; time_t Month;
time_t Year; time_t Year;
if (RelMonth == 0) if (RelMonth == 0)
return 0; return 0;
if (!(tm = localtime(&Start))) if (!localtime_r(&Start, &tm))
return -1; return -1;
Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth; Month = 12 * (tm.tm_year + 1900) + tm.tm_mon + RelMonth;
Year = Month / 12; Year = Month / 12;
Month = Month % 12 + 1; Month = Month % 12 + 1;
return DSTcorrect(Start, return DSTcorrect(Start,
Convert(Month, (time_t)tm->tm_mday, Year, Convert(Month, (time_t)tm.tm_mday, Year,
(time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec, (time_t)tm.tm_hour, (time_t)tm.tm_min, (time_t)tm.tm_sec,
MER24, DSTmaybe)); MER24, DSTmaybe));
} }
@@ -827,7 +825,7 @@ difftm(struct tm *a, struct tm *b)
time_t time_t
get_date(char *p) get_date(char *p)
{ {
struct tm *tm, *gmt, gmtbuf; struct tm tm, gmt;
time_t Start; time_t Start;
time_t tod; time_t tod;
time_t now; time_t now;
@@ -836,36 +834,19 @@ get_date(char *p)
yyInput = p; yyInput = p;
(void)time (&now); (void)time (&now);
gmt = gmtime (&now); if (gmtime_r (&now, &gmt) == NULL)
if (gmt != NULL)
{
/* Make a copy, in case localtime modifies *tm (I think
that comment now applies to *gmt, but I am too
lazy to dig into how gmtime and locatime allocate the
structures they return pointers to). */
gmtbuf = *gmt;
gmt = &gmtbuf;
}
if (! (tm = localtime (&now)))
return -1; return -1;
if (gmt != NULL) if (localtime_r (&now, &tm) == NULL)
tz = difftm (gmt, tm) / 60; return -1;
else
/* We are on a system like VMS, where the system clock is
in local time and the system has no concept of timezones.
Hopefully we can fake this out (for the case in which the
user specifies no timezone) by just saying the timezone
is zero. */
tz = 0;
if(tm->tm_isdst) tz = difftm (&gmt, &tm) / 60;
if (tm.tm_isdst)
tz += 60; tz += 60;
yyYear = tm->tm_year + 1900; yyYear = tm.tm_year + 1900;
yyMonth = tm->tm_mon + 1; yyMonth = tm.tm_mon + 1;
yyDay = tm->tm_mday; yyDay = tm.tm_mday;
yyTimezone = tz; yyTimezone = tz;
yyDSTmode = DSTmaybe; yyDSTmode = DSTmaybe;
yyHour = 0; yyHour = 0;
@@ -893,7 +874,7 @@ get_date(char *p)
else { else {
Start = now; Start = now;
if (!yyHaveRel) if (!yyHaveRel)
Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec; Start -= ((tm.tm_hour * 60L + tm.tm_min) * 60L) + tm.tm_sec;
} }
Start += yyRelSeconds; Start += yyRelSeconds;

View File

@@ -1,7 +1,7 @@
/* /*
* SPDX-License-Identifier: ISC * SPDX-License-Identifier: ISC
* *
* Copyright (c) 2017 Todd C. Miller <Todd.Miller@sudo.ws> * Copyright (c) 2017, 2021 Todd C. Miller <Todd.Miller@sudo.ws>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -32,42 +32,41 @@
/* /*
* Returns the offset from GMT in seconds (algorithm taken from sendmail). * Returns the offset from GMT in seconds (algorithm taken from sendmail).
* Warning: clobbers the static storage used by localtime() and gmtime().
*/ */
#ifdef HAVE_STRUCT_TM_TM_GMTOFF #ifdef HAVE_STRUCT_TM_TM_GMTOFF
long long
get_gmtoff(time_t *when) get_gmtoff(time_t *when)
{ {
struct tm *local; struct tm local;
local = localtime(when); if (localtime_r(when, &local) == NULL)
return local->tm_gmtoff; return 0;
return local.tm_gmtoff;
} }
#else #else
long long
get_gmtoff(time_t *when) get_gmtoff(time_t *when)
{ {
struct tm *gm, gmt, *local; struct tm gmt, local;
long offset; long offset;
if ((gm = gmtime(when)) == NULL) if (gmtime_r(when, &gmt) == NULL)
return 0; return 0;
gmt = *gm; if (localtime_r(when, &local) == NULL)
if ((local = localtime(when)) == NULL)
return 0; return 0;
offset = (local->tm_sec - gmt.tm_sec) + offset = (local.tm_sec - gmt.tm_sec) +
((local->tm_min - gmt.tm_min) * 60) + ((local.tm_min - gmt.tm_min) * 60) +
((local->tm_hour - gmt.tm_hour) * 3600); ((local.tm_hour - gmt.tm_hour) * 3600);
/* Timezone may cause year rollover to happen on a different day. */ /* Timezone may cause year rollover to happen on a different day. */
if (local->tm_year < gmt.tm_year) if (local.tm_year < gmt.tm_year)
offset -= 24 * 3600; offset -= 24 * 3600;
else if (local->tm_year > gmt.tm_year) else if (local.tm_year > gmt.tm_year)
offset -= 24 * 3600; offset -= 24 * 3600;
else if (local->tm_yday < gmt.tm_yday) else if (local.tm_yday < gmt.tm_yday)
offset -= 24 * 3600; offset -= 24 * 3600;
else if (local->tm_yday > gmt.tm_yday) else if (local.tm_yday > gmt.tm_yday)
offset += 24 * 3600; offset += 24 * 3600;
return offset; return offset;

View File

@@ -491,7 +491,7 @@ done:
static bool static bool
sudo_ldap_timefilter(char *buffer, size_t buffersize) sudo_ldap_timefilter(char *buffer, size_t buffersize)
{ {
struct tm *tp; struct tm gmt;
time_t now; time_t now;
char timebuffer[sizeof("20120727121554.0Z")]; char timebuffer[sizeof("20120727121554.0Z")];
int len = -1; int len = -1;
@@ -499,13 +499,13 @@ sudo_ldap_timefilter(char *buffer, size_t buffersize)
/* Make sure we have a formatted timestamp for __now__. */ /* Make sure we have a formatted timestamp for __now__. */
time(&now); time(&now);
if ((tp = gmtime(&now)) == NULL) { if (gmtime_r(&now, &gmt) == NULL) {
sudo_warn("%s", U_("unable to get GMT time")); sudo_warn("%s", U_("unable to get GMT time"));
goto done; goto done;
} }
/* Format the timestamp according to the RFC. */ /* Format the timestamp according to the RFC. */
if (strftime(timebuffer, sizeof(timebuffer), "%Y%m%d%H%M%S.0Z", tp) == 0) { if (strftime(timebuffer, sizeof(timebuffer), "%Y%m%d%H%M%S.0Z", &gmt) == 0) {
sudo_warnx("%s", U_("unable to format timestamp")); sudo_warnx("%s", U_("unable to format timestamp"));
goto done; goto done;
} }

View File

@@ -622,15 +622,19 @@ display_priv_long(struct sudoers_parse_tree *parse_tree, struct passwd *pw,
} }
if (cs->notbefore != UNSPEC) { if (cs->notbefore != UNSPEC) {
char buf[sizeof("CCYYMMDDHHMMSSZ")]; char buf[sizeof("CCYYMMDDHHMMSSZ")];
struct tm *tm = gmtime(&cs->notbefore); struct tm gmt;
if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", tm) != 0) if (gmtime_r(&cs->notbefore, &gmt) != NULL) {
sudo_lbuf_append(lbuf, " NotBefore: %s\n", buf); if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", &gmt) != 0)
sudo_lbuf_append(lbuf, " NotBefore: %s\n", buf);
}
} }
if (cs->notafter != UNSPEC) { if (cs->notafter != UNSPEC) {
char buf[sizeof("CCYYMMDDHHMMSSZ")]; char buf[sizeof("CCYYMMDDHHMMSSZ")];
struct tm *tm = gmtime(&cs->notafter); struct tm gmt;
if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", tm) != 0) if (gmtime_r(&cs->notafter, &gmt) != NULL) {
sudo_lbuf_append(lbuf, " NotAfter: %s\n", buf); if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", &gmt) != 0)
sudo_lbuf_append(lbuf, " NotAfter: %s\n", buf);
}
} }
sudo_lbuf_append(lbuf, "%s", _(" Commands:\n")); sudo_lbuf_append(lbuf, "%s", _(" Commands:\n"));
} }

View File

@@ -37,13 +37,13 @@ char *
get_timestr(time_t tstamp, int log_year) get_timestr(time_t tstamp, int log_year)
{ {
static char buf[128]; static char buf[128];
struct tm *timeptr; struct tm tm;
if ((timeptr = localtime(&tstamp)) != NULL) { if (localtime_r(&tstamp, &tm) != NULL) {
/* strftime() does not guarantee to NUL-terminate so we must check. */ /* strftime() does not guarantee to NUL-terminate so we must check. */
buf[sizeof(buf) - 1] = '\0'; buf[sizeof(buf) - 1] = '\0';
if (strftime(buf, sizeof(buf), log_year ? "%h %e %T %Y" : "%h %e %T", if (strftime(buf, sizeof(buf), log_year ? "%h %e %T %Y" : "%h %e %T",
timeptr) != 0 && buf[sizeof(buf) - 1] == '\0') &tm) != 0 && buf[sizeof(buf) - 1] == '\0')
return buf; return buf;
} }
return NULL; return NULL;