mirror of
https://github.com/curl/curl.git
synced 2025-04-18 16:30:45 +08:00
hsts: handle unlimited expiry
When setting a blank expire string, meaning unlimited, curl would pass TIME_T_MAX to getime_r() when creating the output, while on 64 bit systems such a large value cannot be convetered to a tm struct making curl to exit the loop with an error instead. It can't be converted because the year it would represent doesn't fit in the 'int tm_year' field! Starting now, unlimited expiry is instead handled differently by using a human readable expiry date spelled out as "unlimited" instead of trying to use a distant actual date. Test 1660 and 1915 have been updated to help verify this change. Reported-by: Jonathan Cardoso Fixes #7720 Closes #7721
This commit is contained in:
parent
d5a70e77b2
commit
54f6d836d8
40
lib/hsts.c
40
lib/hsts.c
@ -49,6 +49,7 @@
|
||||
#define MAX_HSTS_HOSTLENSTR "256"
|
||||
#define MAX_HSTS_DATELEN 64
|
||||
#define MAX_HSTS_DATELENSTR "64"
|
||||
#define UNLIMITED "unlimited"
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
/* to play well with debug builds, we can *set* a fixed time this will
|
||||
@ -283,13 +284,17 @@ static CURLcode hsts_push(struct Curl_easy *data,
|
||||
e.namelen = strlen(sts->host);
|
||||
e.includeSubDomains = sts->includeSubDomains;
|
||||
|
||||
result = Curl_gmtime((time_t)sts->expires, &stamp);
|
||||
if(result)
|
||||
return result;
|
||||
if(sts->expires != TIME_T_MAX) {
|
||||
result = Curl_gmtime((time_t)sts->expires, &stamp);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d",
|
||||
stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
|
||||
stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
|
||||
msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d",
|
||||
stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
|
||||
stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
|
||||
}
|
||||
else
|
||||
strcpy(e.expire, UNLIMITED);
|
||||
|
||||
sc = data->set.hsts_write(data, &e, i,
|
||||
data->set.hsts_write_userp);
|
||||
@ -303,14 +308,18 @@ static CURLcode hsts_push(struct Curl_easy *data,
|
||||
static CURLcode hsts_out(struct stsentry *sts, FILE *fp)
|
||||
{
|
||||
struct tm stamp;
|
||||
CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
fprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n",
|
||||
sts->includeSubDomains ? ".": "", sts->host,
|
||||
stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
|
||||
stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
|
||||
if(sts->expires != TIME_T_MAX) {
|
||||
CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp);
|
||||
if(result)
|
||||
return result;
|
||||
fprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n",
|
||||
sts->includeSubDomains ? ".": "", sts->host,
|
||||
stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
|
||||
stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
|
||||
}
|
||||
else
|
||||
fprintf(fp, "%s%s \"%s\"\n",
|
||||
sts->includeSubDomains ? ".": "", sts->host, UNLIMITED);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -403,7 +412,8 @@ static CURLcode hsts_add(struct hsts *h, char *line)
|
||||
"%" MAX_HSTS_HOSTLENSTR "s \"%" MAX_HSTS_DATELENSTR "[^\"]\"",
|
||||
host, date);
|
||||
if(2 == rc) {
|
||||
time_t expires = Curl_getdate_capped(date);
|
||||
time_t expires = strcmp(date, UNLIMITED) ? Curl_getdate_capped(date) :
|
||||
TIME_T_MAX;
|
||||
CURLcode result;
|
||||
char *p = host;
|
||||
bool subdomain = FALSE;
|
||||
|
@ -20,6 +20,7 @@ HSTS
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
.readfrom.example "20211001 04:47:41"
|
||||
.old.example "20161001 04:47:41"
|
||||
.new.example "unlimited"
|
||||
</file>
|
||||
|
||||
# This date is exactly "20190124 22:34:21" UTC
|
||||
@ -59,7 +60,7 @@ foo.example.com [example.com]: 1569905261 includeSubDomains
|
||||
'forexample.net' is not HSTS
|
||||
'example.net' is not HSTS
|
||||
expire.example [expire.example]: 1548369268
|
||||
Number of entries: 3
|
||||
Number of entries: 4
|
||||
expire.example [expire.example]: 1548369268
|
||||
expire.example [expire.example]: 1548369268
|
||||
expire.example [expire.example]: 1548369268
|
||||
@ -74,6 +75,7 @@ expire.example [expire.example]: 1548369268
|
||||
<file name="log/hsts%TESTNUMBER" mode="text">
|
||||
# Your HSTS cache. https://curl.se/docs/hsts.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
.new.example "unlimited"
|
||||
.example.com "20191001 04:47:41"
|
||||
example.org "20200124 22:34:21"
|
||||
</file>
|
||||
|
@ -42,9 +42,9 @@ http://%HOSTIP:%NOLISTENPORT/not-there/%TESTNUMBER
|
||||
</errorcode>
|
||||
<stdout>
|
||||
[0/4] 1.example.com 20370320 01:02:03
|
||||
[1/4] 2.example.com 20370320 01:02:03
|
||||
[2/4] 3.example.com 20370320 01:02:03
|
||||
[3/4] 4.example.com 20370320 01:02:03
|
||||
[1/4] 2.example.com 20370320 03:02:01
|
||||
[2/4] 3.example.com 20370319 01:02:03
|
||||
[3/4] 4.example.com unlimited
|
||||
</stdout>
|
||||
</verify>
|
||||
</testcase>
|
||||
|
@ -25,12 +25,18 @@
|
||||
#include "warnless.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
static const char *preload_hosts[] = {
|
||||
"1.example.com",
|
||||
"2.example.com",
|
||||
"3.example.com",
|
||||
"4.example.com",
|
||||
NULL /* end of list marker */
|
||||
struct entry {
|
||||
const char *name;
|
||||
const char *exp;
|
||||
};
|
||||
|
||||
static struct entry preload_hosts[] = {
|
||||
/* curl turns 39 that day just before 31-bit time_t overflow */
|
||||
{ "1.example.com", "20370320 01:02:03" },
|
||||
{ "2.example.com", "20370320 03:02:01" },
|
||||
{ "3.example.com", "20370319 01:02:03" },
|
||||
{ "4.example.com", "" },
|
||||
{ NULL, NULL } /* end of list marker */
|
||||
};
|
||||
|
||||
struct state {
|
||||
@ -42,15 +48,16 @@ static CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *e,
|
||||
void *userp)
|
||||
{
|
||||
const char *host;
|
||||
const char *expire;
|
||||
struct state *s = (struct state *)userp;
|
||||
(void)easy;
|
||||
host = preload_hosts[s->index++];
|
||||
host = preload_hosts[s->index].name;
|
||||
expire = preload_hosts[s->index++].exp;
|
||||
|
||||
if(host && (strlen(host) < e->namelen)) {
|
||||
strcpy(e->name, host);
|
||||
e->includeSubDomains = FALSE;
|
||||
strcpy(e->expire, "20370320 01:02:03"); /* curl turns 39 that day
|
||||
just before 31-bit time_t overflow */
|
||||
strcpy(e->expire, expire);
|
||||
fprintf(stderr, "add '%s'\n", host);
|
||||
}
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user