mirror of
https://github.com/curl/curl.git
synced 2026-08-26 07:13:32 +03:00
altsvc: continue after unknown parameters
Parse extension names and values before deciding whether a parameter is known. This prevents long names and token or quoted-string values from hiding later ma or persist parameters, as required by RFC 7838 section 3. Add unit coverage for long extension names and both value forms, including an escaped quote and semicolon inside a quoted string. Fixes #22644 Closes #22676
This commit is contained in:
parent
bb8ec5eb65
commit
81ade54120
2 changed files with 54 additions and 20 deletions
50
lib/altsvc.c
50
lib/altsvc.c
|
|
@ -471,6 +471,8 @@ static void altsvc_flush(struct altsvcinfo *asi,
|
|||
}
|
||||
}
|
||||
|
||||
#define ALTSVC_MA 1
|
||||
#define ALTSVC_PERSIST 2
|
||||
static void altsvc_parse_params(const char **pp,
|
||||
time_t *pmaxage,
|
||||
bool *ppersist)
|
||||
|
|
@ -482,36 +484,44 @@ static void altsvc_parse_params(const char **pp,
|
|||
for(;;) {
|
||||
struct Curl_str name;
|
||||
struct Curl_str val;
|
||||
const char *vp;
|
||||
curl_off_t num;
|
||||
bool quoted;
|
||||
int keyword = 0;
|
||||
|
||||
/* allow some extra whitespaces around name and value */
|
||||
if(curlx_str_until(pp, &name, 20, '=') ||
|
||||
curlx_str_single(pp, '=') ||
|
||||
curlx_str_cspn(pp, &val, ",;"))
|
||||
if(curlx_str_until(pp, &name, MAX_ALTSVC_LINE, '=') ||
|
||||
curlx_str_single(pp, '='))
|
||||
break; /* skip further parameter parsing */
|
||||
|
||||
curlx_str_trimblanks(&name);
|
||||
curlx_str_passblanks(pp);
|
||||
if(**pp == '\"') {
|
||||
if(curlx_str_quotedword(pp, &val, MAX_ALTSVC_LINE))
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if(curlx_str_cspn(pp, &val, ",;\r\n"))
|
||||
break;
|
||||
}
|
||||
curlx_str_trimblanks(&val);
|
||||
/* the value might be quoted */
|
||||
vp = curlx_str(&val);
|
||||
quoted = (*vp == '\"');
|
||||
if(quoted)
|
||||
vp++;
|
||||
/* we process 2 number value parameters: 'ma' and 'persist' */
|
||||
if(curlx_str_number(&vp, &num, TIME_T_MAX))
|
||||
break; /* not a number, skip further parameter parsing */
|
||||
|
||||
if(curlx_str_casecompare(&name, "ma"))
|
||||
*pmaxage = (time_t)num;
|
||||
else if(curlx_str_casecompare(&name, "persist") && (num == 1))
|
||||
*ppersist = TRUE;
|
||||
keyword = ALTSVC_MA;
|
||||
else if(curlx_str_casecompare(&name, "persist"))
|
||||
keyword = ALTSVC_PERSIST;
|
||||
|
||||
if(keyword) {
|
||||
const char *vp = curlx_str(&val);
|
||||
const char *vend = vp + curlx_strlen(&val);
|
||||
if(curlx_str_number(&vp, &num, TIME_T_MAX))
|
||||
break; /* not a number, skip further parameter parsing */
|
||||
if(vp != vend)
|
||||
break; /* not entirely a number, skip further parameter parsing */
|
||||
if(keyword == ALTSVC_MA)
|
||||
*pmaxage = (time_t)num;
|
||||
else if(num == 1)
|
||||
*ppersist = TRUE;
|
||||
}
|
||||
|
||||
*pp = vp; /* point to the byte ending the value */
|
||||
curlx_str_passblanks(pp);
|
||||
if(quoted && curlx_str_single(pp, '\"'))
|
||||
break; /* was quoted but not ended in quote, skip */
|
||||
curlx_str_passblanks(pp);
|
||||
if(curlx_str_single(pp, ';'))
|
||||
break; /* no further parameters */
|
||||
|
|
|
|||
|
|
@ -34,8 +34,10 @@ static CURLcode test_unit1654(const char *arg)
|
|||
CURL *curl = NULL;
|
||||
CURLcode result;
|
||||
struct altsvcinfo *asi = Curl_altsvc_init();
|
||||
struct altsvc *dstentry = NULL;
|
||||
struct Curl_peer *origin = NULL;
|
||||
const struct Curl_scheme *scheme = &Curl_scheme_https;
|
||||
bool same_destination = FALSE;
|
||||
|
||||
abort_if(!asi, "Curl_altsvc_i");
|
||||
result = Curl_altsvc_load(asi, arg);
|
||||
|
|
@ -160,6 +162,28 @@ static CURLcode test_unit1654(const char *arg)
|
|||
origin, ALPN_h2);
|
||||
fail_if(result, "Curl_altsvc_parse(12) failed!");
|
||||
|
||||
/* Unknown extension parameters must not hide later known parameters. */
|
||||
if(Curl_peer_create(curl, scheme, "params.example", 443, &origin))
|
||||
goto fail;
|
||||
result = Curl_altsvc_parse(curl, asi,
|
||||
"h2=\":443\"; long-extension-parameter=token; "
|
||||
"ext=token; "
|
||||
"quoted=\"a;\\\"b\"; ma=120; persist=1\r\n",
|
||||
origin, ALPN_h1);
|
||||
fail_if(result, "Curl_altsvc_parse(13) failed!");
|
||||
if(!Curl_altsvc_lookup(asi, origin, ALPN_h1, &dstentry,
|
||||
CURLALTSVC_H2, &same_destination)) {
|
||||
fail_unless(FALSE, "alt-svc entry not found");
|
||||
goto fail;
|
||||
}
|
||||
fail_unless(dstentry->expires == 1548369261 + 120,
|
||||
"unknown parameters hid ma");
|
||||
fail_unless(dstentry->persist, "unknown parameters hid persist");
|
||||
fail_unless(same_destination, "wrong alt-svc destination");
|
||||
|
||||
result = Curl_altsvc_parse(curl, asi, "clear\r\n", origin, ALPN_h1);
|
||||
fail_if(result, "Curl_altsvc_parse(14) failed!");
|
||||
|
||||
Curl_altsvc_save(curl, asi, outname);
|
||||
|
||||
fail:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue