altsvc: reject bad port numbers
The existing code tried but did not properly reject alternative services using negative or too large port numbers. With this fix, the logic now also flushes the old entries immediately before adding a new one, making a following header with an illegal entry not flush the already stored entry. Report from the ongoing source code audit by Trail of Bits. Adjusted test 356 to verify. Closes #9607
This commit is contained in:
Родитель
eb33ccd533
Коммит
ac612dfeee
25
lib/altsvc.c
25
lib/altsvc.c
|
@ -462,6 +462,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||||
struct altsvc *as;
|
struct altsvc *as;
|
||||||
unsigned short dstport = srcport; /* the same by default */
|
unsigned short dstport = srcport; /* the same by default */
|
||||||
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
|
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
|
||||||
|
size_t entries = 0;
|
||||||
#ifdef CURL_DISABLE_VERBOSE_STRINGS
|
#ifdef CURL_DISABLE_VERBOSE_STRINGS
|
||||||
(void)data;
|
(void)data;
|
||||||
#endif
|
#endif
|
||||||
|
@ -472,11 +473,10 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||||
|
|
||||||
DEBUGASSERT(asi);
|
DEBUGASSERT(asi);
|
||||||
|
|
||||||
/* Flush all cached alternatives for this source origin, if any */
|
|
||||||
altsvc_flush(asi, srcalpnid, srchost, srcport);
|
|
||||||
|
|
||||||
/* "clear" is a magic keyword */
|
/* "clear" is a magic keyword */
|
||||||
if(strcasecompare(alpnbuf, "clear")) {
|
if(strcasecompare(alpnbuf, "clear")) {
|
||||||
|
/* Flush cached alternatives for this source origin */
|
||||||
|
altsvc_flush(asi, srcalpnid, srchost, srcport);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,6 +494,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||||
bool quoted = FALSE;
|
bool quoted = FALSE;
|
||||||
time_t maxage = 24 * 3600; /* default is 24 hours */
|
time_t maxage = 24 * 3600; /* default is 24 hours */
|
||||||
bool persist = FALSE;
|
bool persist = FALSE;
|
||||||
|
bool valid = TRUE;
|
||||||
p++;
|
p++;
|
||||||
if(*p != ':') {
|
if(*p != ':') {
|
||||||
/* host name starts here */
|
/* host name starts here */
|
||||||
|
@ -503,7 +504,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||||
len = p - hostp;
|
len = p - hostp;
|
||||||
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
|
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
|
||||||
infof(data, "Excessive alt-svc host name, ignoring.");
|
infof(data, "Excessive alt-svc host name, ignoring.");
|
||||||
dstalpnid = ALPN_none;
|
valid = FALSE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memcpy(namebuf, hostp, len);
|
memcpy(namebuf, hostp, len);
|
||||||
|
@ -520,10 +521,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||||
unsigned long port = strtoul(++p, &end_ptr, 10);
|
unsigned long port = strtoul(++p, &end_ptr, 10);
|
||||||
if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
|
if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
|
||||||
infof(data, "Unknown alt-svc port number, ignoring.");
|
infof(data, "Unknown alt-svc port number, ignoring.");
|
||||||
dstalpnid = ALPN_none;
|
valid = FALSE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
dstport = curlx_ultous(port);
|
||||||
p = end_ptr;
|
p = end_ptr;
|
||||||
dstport = curlx_ultous(port);
|
|
||||||
}
|
}
|
||||||
if(*p++ != '\"')
|
if(*p++ != '\"')
|
||||||
break;
|
break;
|
||||||
|
@ -575,7 +577,12 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||||
persist = TRUE;
|
persist = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(dstalpnid) {
|
if(dstalpnid && valid) {
|
||||||
|
if(!entries++)
|
||||||
|
/* Flush cached alternatives for this source origin, if any - when
|
||||||
|
this is the first entry of the line. */
|
||||||
|
altsvc_flush(asi, srcalpnid, srchost, srcport);
|
||||||
|
|
||||||
as = altsvc_createid(srchost, dsthost,
|
as = altsvc_createid(srchost, dsthost,
|
||||||
srcalpnid, dstalpnid,
|
srcalpnid, dstalpnid,
|
||||||
srcport, dstport);
|
srcport, dstport);
|
||||||
|
@ -589,10 +596,6 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||||
Curl_alpnid2str(dstalpnid));
|
Curl_alpnid2str(dstalpnid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
infof(data, "Unknown alt-svc protocol \"%s\", skipping.",
|
|
||||||
alpnbuf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -16,7 +16,9 @@ Content-Length: 6
|
||||||
Connection: close
|
Connection: close
|
||||||
Content-Type: text/html
|
Content-Type: text/html
|
||||||
Funny-head: yesyes
|
Funny-head: yesyes
|
||||||
|
Alt-Svc: h1="nowhere.foo:-1"
|
||||||
Alt-Svc: h1="nowhere.foo:81", un-kno22!wn=":82"
|
Alt-Svc: h1="nowhere.foo:81", un-kno22!wn=":82"
|
||||||
|
Alt-Svc: h1="nowhere.foo:70000"
|
||||||
|
|
||||||
-foo-
|
-foo-
|
||||||
</data>
|
</data>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче