dhclient: fix time parsing for leases expiring after 2038

Convert lease parsing to timegm to calculate timestamp. For reference, when
writing the lease, we use gmtime to convert the timestamp to struct tm.

Reviewed By:	markj, vangyzen
MFC after:	2 weeks
Sponsored by:	Dell EMC Isilon
Differential Revision:	https://reviews.freebsd.org/D40760
This commit is contained in:
Alex Bahm 2023-07-10 10:56:05 -05:00 committed by Eric van Gyzen
parent 6c049996ec
commit c210cac00f
4 changed files with 64 additions and 27 deletions

View File

@ -444,9 +444,7 @@ convert_num(unsigned char *buf, char *str, unsigned base, int size)
time_t
parse_date(FILE *cfile)
{
static int months[11] = { 31, 59, 90, 120, 151, 181,
212, 243, 273, 304, 334 };
int guess, token;
int token;
struct tm tm;
char *val;
@ -570,27 +568,5 @@ parse_date(FILE *cfile)
return (0);
}
/* Guess the time value... */
guess = ((((((365 * (tm.tm_year - 70) + /* Days in years since '70 */
(tm.tm_year - 69) / 4 + /* Leap days since '70 */
(tm.tm_mon /* Days in months this year */
? months[tm.tm_mon - 1]
: 0) +
(tm.tm_mon > 1 && /* Leap day this year */
!((tm.tm_year - 72) & 3)) +
tm.tm_mday - 1) * 24) + /* Day of month */
tm.tm_hour) * 60) +
tm.tm_min) * 60) + tm.tm_sec;
/*
* This guess could be wrong because of leap seconds or other
* weirdness we don't know about that the system does. For
* now, we're just going to accept the guess, but at some point
* it might be nice to do a successive approximation here to get
* an exact value. Even if the error is small, if the server
* is restarted frequently (and thus the lease database is
* reread), the error could accumulate into something
* significant.
*/
return (guess);
return (timegm(&tm));
}

View File

@ -6,7 +6,8 @@ ATF_TESTS_SH= pcp
PLAIN_TESTS_C= option-domain-search_test
SRCS.option-domain-search_test= alloc.c convert.c hash.c options.c \
tables.c fake.c option-domain-search.c
tables.c parse.c conflex.c tree.c fake.c \
option-domain-search.c
CFLAGS.option-domain-search_test+= -I${.CURDIR:H}
LIBADD.option-domain-search_test= util

View File

@ -7,6 +7,7 @@
#include "dhcpd.h"
extern jmp_buf env;
int warnings_occurred;
void
error(const char *fmt, ...)
@ -52,6 +53,20 @@ note(const char *fmt, ...)
return ret;
}
int
parse_warn(const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
return ret;
}
void
bootp(struct packet *packet)
{

View File

@ -303,6 +303,49 @@ multiple_domains_valid()
free(option->data);
}
static
void
parse_date_helper(const char *string, time_t timestamp)
{
int ret = 0;
FILE *file = NULL;
time_t ts;
file = fopen("/tmp/dhclient.test", "w");
if (!file)
abort();
ret = fwrite(string, strlen(string), 1, file);
if (ret <= 0)
abort();
fclose(file);
file = fopen("/tmp/dhclient.test", "r");
if (!file)
abort();
new_parse("test");
ts = parse_date(file);
if (ts != timestamp)
abort();
fclose(file);
}
void
parse_date_valid(void)
{
int ret;
ret = setjmp(env);
if (ret != 0)
abort();
parse_date_helper(" 2 2024/7/2 20:25:50;\n", 1719951950);
parse_date_helper(" 1 2091/7/2 20:25:50;\n", 3834246350);
}
int
main(int argc, char *argv[])
{
@ -324,5 +367,7 @@ main(int argc, char *argv[])
multiple_domains_valid();
parse_date_valid();
return (0);
}