[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnurl] 88/282: altsvc: improved header parser
From: |
gnunet |
Subject: |
[gnurl] 88/282: altsvc: improved header parser |
Date: |
Wed, 01 Apr 2020 14:29:13 +0200 |
This is an automated email from the git hooks/post-receive script.
ng0 pushed a commit to branch master
in repository gnurl.
commit 9e1f72075855d2b2770c2fb0f0083f15c8714616
Author: Harry Sintonen <address@hidden>
AuthorDate: Tue Feb 4 06:21:58 2020 +0200
altsvc: improved header parser
- Fixed the flag parsing to apply to specific alternative entry only, as
per RFC. The earlier code would also get totally confused by
multiprotocol header, parsing flags from the wrong part of the header.
- Fixed the parser terminating on unknown protocols, instead of skipping
them.
- Fixed a busyloop when protocol-id was present without an equal sign.
Closes #4875
---
lib/altsvc.c | 171 ++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 98 insertions(+), 73 deletions(-)
diff --git a/lib/altsvc.c b/lib/altsvc.c
index 93204e012..0e9a97826 100644
--- a/lib/altsvc.c
+++ b/lib/altsvc.c
@@ -351,12 +351,12 @@ static CURLcode getalnum(const char **ptr, char *alpnbuf,
size_t buflen)
while(*p && !ISBLANK(*p) && (*p != ';') && (*p != '='))
p++;
len = p - protop;
+ *ptr = p;
if(!len || (len >= buflen))
return CURLE_BAD_FUNCTION_ARGUMENT;
memcpy(alpnbuf, protop, len);
alpnbuf[len] = 0;
- *ptr = p;
return CURLE_OK;
}
@@ -402,6 +402,10 @@ static time_t debugtime(void *unused)
*
* 'value' points to the header *value*. That's contents to the right of the
* header name.
+ *
+ * Currently this function rejects invalid data without returning an error.
+ * Invalid host name, port number will result in the specific alternative
+ * being rejected. Unknown protocols are skipped.
*/
CURLcode Curl_altsvc_parse(struct Curl_easy *data,
struct altsvcinfo *asi, const char *value,
@@ -415,12 +419,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
struct altsvc *as;
unsigned short dstport = srcport; /* the same by default */
- const char *semip;
- time_t maxage = 24 * 3600; /* default is 24 hours */
- bool persist = FALSE;
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
- if(result)
- return result;
+ if(result) {
+ infof(data, "Excessive alt-svc header, ignoring...\n");
+ return CURLE_OK;
+ }
DEBUGASSERT(asi);
@@ -432,57 +435,20 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
return CURLE_OK;
}
- /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives
- but are set after the list on the line. Scan for the semicolons and get
- those fields first! */
- semip = p;
- do {
- semip = strchr(semip, ';');
- if(semip) {
- char option[32];
- unsigned long num;
- char *end_ptr;
- bool quoted = FALSE;
- semip++; /* pass the semicolon */
- result = getalnum(&semip, option, sizeof(option));
- if(result)
- break;
- while(*semip && ISBLANK(*semip))
- semip++;
- if(*semip != '=')
- continue;
- semip++;
- while(*semip && ISBLANK(*semip))
- semip++;
- if(*semip == '\"') {
- /* quoted value */
- semip++;
- quoted = TRUE;
- }
- num = strtoul(semip, &end_ptr, 10);
- if((end_ptr != semip) && num && (num < ULONG_MAX)) {
- if(strcasecompare("ma", option))
- maxage = num;
- else if(strcasecompare("persist", option) && (num == 1))
- persist = TRUE;
- if(quoted && (*end_ptr == '\"'))
- end_ptr++;
- }
- semip = end_ptr;
- }
- } while(semip);
-
do {
if(*p == '=') {
/* [protocol]="[host][:port]" */
dstalpnid = alpn2alpnid(alpnbuf);
- if(!dstalpnid) {
- infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf);
- return CURLE_OK;
- }
p++;
if(*p == '\"') {
const char *dsthost;
+ const char *value_ptr;
+ char option[32];
+ unsigned long num;
+ char *end_ptr;
+ bool quoted = FALSE;
+ time_t maxage = 24 * 3600; /* default is 24 hours */
+ bool persist = FALSE;
p++;
if(*p != ':') {
/* host name starts here */
@@ -490,11 +456,15 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
p++;
len = p - hostp;
- if(!len || (len >= MAX_ALTSVC_HOSTLEN))
- return CURLE_BAD_FUNCTION_ARGUMENT;
- memcpy(namebuf, hostp, len);
- namebuf[len] = 0;
- dsthost = namebuf;
+ if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
+ infof(data, "Excessive alt-svc host name, ignoring...\n");
+ dstalpnid = ALPN_none;
+ }
+ else {
+ memcpy(namebuf, hostp, len);
+ namebuf[len] = 0;
+ dsthost = namebuf;
+ }
}
else {
/* no destination name, use source host */
@@ -502,31 +472,86 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
}
if(*p == ':') {
/* a port number */
- char *end_ptr;
unsigned long port = strtoul(++p, &end_ptr, 10);
if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
infof(data, "Unknown alt-svc port number, ignoring...\n");
- return CURLE_OK;
+ dstalpnid = ALPN_none;
}
p = end_ptr;
dstport = curlx_ultous(port);
}
if(*p++ != '\"')
- return CURLE_BAD_FUNCTION_ARGUMENT;
- as = altsvc_createid(srchost, dsthost,
- srcalpnid, dstalpnid,
- srcport, dstport);
- if(as) {
- /* The expires time also needs to take the Age: value (if any) into
- account. [See RFC 7838 section 3.1] */
- as->expires = maxage + time(NULL);
- as->persist = persist;
- Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
- asi->num++; /* one more entry */
- infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
- Curl_alpnid2str(dstalpnid));
+ break;
+ /* Handle the optional 'ma' and 'persist' flags. Unknown flags
+ are skipped. */
+ for(;;) {
+ while(*p && ISBLANK(*p) && *p != ';' && *p != ',')
+ p++;
+ if(!*p || *p == ',')
+ break;
+ p++; /* pass the semicolon */
+ if(!*p)
+ break;
+ result = getalnum(&p, option, sizeof(option));
+ if(result) {
+ /* skip option if name is too long */
+ option[0] = '\0';
+ }
+ while(*p && ISBLANK(*p))
+ p++;
+ if(*p != '=')
+ return CURLE_OK;
+ p++;
+ while(*p && ISBLANK(*p))
+ p++;
+ if(!*p)
+ return CURLE_OK;
+ if(*p == '\"') {
+ /* quoted value */
+ p++;
+ quoted = TRUE;
+ }
+ value_ptr = p;
+ if(quoted) {
+ while(*p && *p != '\"')
+ p++;
+ if(!*p++)
+ return CURLE_OK;
+ }
+ else {
+ while(*p && !ISBLANK(*p) && *p!= ';' && *p != ',')
+ p++;
+ }
+ num = strtoul(value_ptr, &end_ptr, 10);
+ if((end_ptr != value_ptr) && (num < ULONG_MAX)) {
+ if(strcasecompare("ma", option))
+ maxage = num;
+ else if(strcasecompare("persist", option) && (num == 1))
+ persist = TRUE;
+ }
+ }
+ if(dstalpnid) {
+ as = altsvc_createid(srchost, dsthost,
+ srcalpnid, dstalpnid,
+ srcport, dstport);
+ if(as) {
+ /* The expires time also needs to take the Age: value (if any) into
+ account. [See RFC 7838 section 3.1] */
+ as->expires = maxage + time(NULL);
+ as->persist = persist;
+ Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
+ asi->num++; /* one more entry */
+ infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
+ Curl_alpnid2str(dstalpnid));
+ }
+ }
+ else {
+ infof(data, "Unknown alt-svc protocol \"%s\", skipping...\n",
+ alpnbuf);
}
}
+ else
+ break;
/* after the double quote there can be a comma if there's another
string or a semicolon if no more */
if(*p == ',') {
@@ -534,11 +559,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
p++;
result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
if(result)
- /* failed to parse, but since we already did at least one host we
- return OK */
- return CURLE_OK;
+ break;
}
}
+ else
+ break;
} while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));
return CURLE_OK;
--
To stop receiving notification emails like this one, please contact
address@hidden.
- [gnurl] 78/282: cirrus: Add some missing semicolons, (continued)
- [gnurl] 78/282: cirrus: Add some missing semicolons, gnunet, 2020/04/01
- [gnurl] 71/282: cookie: check __Secure- and __Host- case sensitively, gnunet, 2020/04/01
- [gnurl] 79/282: travis: update non-OpenSSL Linux jobs to Bionic, gnunet, 2020/04/01
- [gnurl] 77/282: cleanup: fix typos and wording in docs and comments, gnunet, 2020/04/01
- [gnurl] 85/282: ntlm: Pass the Curl_easy structure to the private winbind functions, gnunet, 2020/04/01
- [gnurl] 97/282: ntlm_wb: Use Curl_socketpair() for greater portability, gnunet, 2020/04/01
- [gnurl] 87/282: ngtcp2: fixed to only use AF_INET6 when ENABLE_IPV6, gnunet, 2020/04/01
- [gnurl] 90/282: RELEASE-PROCEDURE: feature win is closed post-release a few days, gnunet, 2020/04/01
- [gnurl] 89/282: altsvc: set h3 version at a common single spot, gnunet, 2020/04/01
- [gnurl] 96/282: contributors: Also include people who contributed to curl-www, gnunet, 2020/04/01
- [gnurl] 88/282: altsvc: improved header parser,
gnunet <=
- [gnurl] 104/282: asyn-thread: remove dead code, gnunet, 2020/04/01
- [gnurl] 92/282: curl: error on --alt-svc use w/o support, gnunet, 2020/04/01
- [gnurl] 99/282: ftp: remove the duplicated user/password struct fields, gnunet, 2020/04/01
- [gnurl] 91/282: docs/HTTP3: add --enable-alt-svc to curl's configure, gnunet, 2020/04/01
- [gnurl] 93/282: ftp: shrink temp buffers used for PORT, gnunet, 2020/04/01
- [gnurl] 102/282: configure.ac: fix comments about --with-quiche, gnunet, 2020/04/01
- [gnurl] 95/282: contrithanks: Use the most recent tag by default, gnunet, 2020/04/01
- [gnurl] 101/282: checksrc.bat: Fix not being able to run script from the main curl directory, gnunet, 2020/04/01
- [gnurl] 103/282: github: Instructions to post "uname -a" on Unix systems in issues, gnunet, 2020/04/01
- [gnurl] 94/282: scripts: use last set tag if none given, gnunet, 2020/04/01