From d6d071b36b3d00632649d0535d87d0d9cf9ebcc6 Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Mon, 18 Oct 2021 23:32:50 -0400 Subject: [PATCH 1/5] Fix #1399 - Add a grammar corresponding to the parsing algorithm --- draft-ietf-httpbis-rfc6265bis.md | 69 +++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/draft-ietf-httpbis-rfc6265bis.md b/draft-ietf-httpbis-rfc6265bis.md index 3b6f862550..05429594c4 100644 --- a/draft-ietf-httpbis-rfc6265bis.md +++ b/draft-ietf-httpbis-rfc6265bis.md @@ -478,12 +478,14 @@ Cookie and Set-Cookie header fields. The Set-Cookie HTTP response header field is used to send cookies from the server to the user agent. -### Syntax {#abnf-syntax} +### Syntax {#sane-abnf-syntax} Informally, the Set-Cookie response header field contains a cookie, which begins with a name-value-pair, followed by zero or more attribute-value pairs. Servers -SHOULD NOT send Set-Cookie header fields that fail to conform to the following -grammar: +SHOULD NOT send Set-Cookie header fields that fail to conform to the grammar below. + +Note that the grammar used by the user agent when processing Set-Cookie header fields +is more permissive than this grammar. (See {{ua-abnf-syntax}} for more details.) ~~~ abnf set-cookie = set-cookie-string @@ -1121,7 +1123,8 @@ in {{sane-set-cookie}} forbids whitespace in these positions. In addition, the algorithm below accommodates some characters that are not cookie-octets according to the grammar in {{sane-set-cookie}}. User agents use this algorithm so as to interoperate with servers that do not follow the recommendations in -{{sane-profile}}. +{{sane-profile}}. See {{ua-set-cookie}} for a grammar that corresponds to +the algorithm. NOTE: As set-cookie-string may originate from a non-HTTP API, it is not guaranteed to be free of CTL characters, so this algorithm handles them @@ -1394,6 +1397,62 @@ with elapsed since the cookie's creation-time is at most a duration of the user agent's choosing. +## Syntax {#ua-abnf-syntax} + +Based on the parsing algorithms defined above, the following grammar defines +the syntax requirements enforced by user agents when parsing specific +subcomponents of the Cookie and Set-Cookie header fields: + +~~~ abnf +set-cookie = set-cookie-string +set-cookie-string = cookie-pair *( BWS ";" OWS cookie-av) +cookie-pair = *1(BWS cookie-name BWS "=") BWS cookie-value BWS + ; cookie-name plus cookie-value must be less than + ; or equal to 4096 octets + +cookie-name = *4096(cookie-name-octet) +cookie-value = *4096(cookie-value-octet) +cookie-name-octet = %x09 / %x20-3A / %x3C / %x3E-7E / %x80-FF + ; octets excluding non-whitespace CTLs, + ; semicolon, and equals +cookie-value-octet = %x09 / %x20-3A / %x3C-7E / %x80-FF + ; octets excluding non-whitespace CTLs and + ; semicolon + +cookie-av = expires-av / max-age-av / domain-av / + path-av / secure-av / httponly-av / + samesite-av / extension-av + ; attributes that don't conform to the grammars + ; below are ignored + +expires-av = "Expires" BWS "=" BWS cookie-date BWS + ; cookie-date is defined in separate grammar + ; in a previous section + +max-age-av = "Max-Age" BWS "=" BWS max-age-value BWS +max-age-value = 1*1024(DIGIT) / "-" 1*1023(DIGIT) + +domain-av = "Domain" BWS "=" BWS domain-value BWS +domain-value = 1*1024(cookie-value-octet) + ; a leading dot in domain-value will be removed + ; if present + +path-av = "Path" BWS "=" BWS path-value BWS +path-value = 1*1024(cookie-value-octet) + +secure-av = "Secure" BWS *ignored-value + +httponly-av = "HttpOnly" BWS *ignored-value + +samesite-av = "SameSite" BWS "=" BWS samesite-value BWS +samesite-value = "Strict" / "Lax" / "None" + +extension-av = 1*cookie-name-octet BWS *optional-value + +ignored-value = "=" BWS *1024(cookie-value-octet) BWS +optional-value = ignored-value +~~~ + ## Storage Model {#storage-model} The user agent stores the following fields about each cookie: name, value, @@ -2255,7 +2314,7 @@ reference detailing how the attribute is to be processed and stored. New registrations happen on a "RFC Required" basis (see Section 4.7 of {{RFC8126}}). The attribute to be registered MUST match the `extension-av` -syntax defined in {{abnf-syntax}}. Note that attribute names are generally +syntax defined in {{sane-abnf-syntax}}. Note that attribute names are generally defined in CamelCase, but technically accepted case-insensitively. ### Registration From 60efc12f09c9f9140703bbfddbb4ff0e2204aaab Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Mon, 18 Oct 2021 23:54:13 -0400 Subject: [PATCH 2/5] Update incorrect grammar link --- draft-ietf-httpbis-rfc6265bis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft-ietf-httpbis-rfc6265bis.md b/draft-ietf-httpbis-rfc6265bis.md index 05429594c4..e437a3637b 100644 --- a/draft-ietf-httpbis-rfc6265bis.md +++ b/draft-ietf-httpbis-rfc6265bis.md @@ -1123,7 +1123,7 @@ in {{sane-set-cookie}} forbids whitespace in these positions. In addition, the algorithm below accommodates some characters that are not cookie-octets according to the grammar in {{sane-set-cookie}}. User agents use this algorithm so as to interoperate with servers that do not follow the recommendations in -{{sane-profile}}. See {{ua-set-cookie}} for a grammar that corresponds to +{{sane-profile}}. See {{ua-abnf-syntax}} for a grammar that corresponds to the algorithm. NOTE: As set-cookie-string may originate from a non-HTTP API, it is not From 8f95fe9fea565dc9d73fb4ca9bafb5fe8cac6fa6 Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Wed, 20 Oct 2021 18:20:05 -0400 Subject: [PATCH 3/5] Address review feedback This commit addresses review feedback and improves the correctness of the grammar for various edge cases (Ex: `Domain=;` and `Path;`). It also fixes some issues with how '/' was used in the previous commit. --- draft-ietf-httpbis-rfc6265bis.md | 58 +++++++++++++++++++------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/draft-ietf-httpbis-rfc6265bis.md b/draft-ietf-httpbis-rfc6265bis.md index e437a3637b..78d83d4454 100644 --- a/draft-ietf-httpbis-rfc6265bis.md +++ b/draft-ietf-httpbis-rfc6265bis.md @@ -312,6 +312,9 @@ and WSP (whitespace). The OWS (optional whitespace) and BWS (bad whitespace) rules are defined in Section 5.6.3 of {{!HTTPSEM=I-D.ietf-httpbis-semantics}}. +Note that per {{RFC5234}}, all strings literals used in the grammars are +case-insensitive (e.g. "Secure" is equiavelent to "secure" and "sEcUrE"). + ## Terminology The terms "user agent", "client", "server", "proxy", and "origin server" have @@ -478,11 +481,12 @@ Cookie and Set-Cookie header fields. The Set-Cookie HTTP response header field is used to send cookies from the server to the user agent. -### Syntax {#sane-abnf-syntax} +### Syntax {#server-abnf-syntax} Informally, the Set-Cookie response header field contains a cookie, which begins with a name-value-pair, followed by zero or more attribute-value pairs. Servers -SHOULD NOT send Set-Cookie header fields that fail to conform to the grammar below. +SHOULD NOT send Set-Cookie header fields that fail to conform to the grammar +immediately below. Note that the grammar used by the user agent when processing Set-Cookie header fields is more permissive than this grammar. (See {{ua-abnf-syntax}} for more details.) @@ -1400,15 +1404,15 @@ with ## Syntax {#ua-abnf-syntax} Based on the parsing algorithms defined above, the following grammar defines -the syntax requirements enforced by user agents when parsing specific -subcomponents of the Cookie and Set-Cookie header fields: +the syntax requirements enforced by user agents when parsing +set-cookie-strings: ~~~ abnf set-cookie = set-cookie-string set-cookie-string = cookie-pair *( BWS ";" OWS cookie-av) cookie-pair = *1(BWS cookie-name BWS "=") BWS cookie-value BWS - ; cookie-name plus cookie-value must be less than - ; or equal to 4096 octets + ; the sum of the lengths of cookie-name and cookie-value + ; must be less than or equal to 4096 octets cookie-name = *4096(cookie-name-octet) cookie-value = *4096(cookie-value-octet) @@ -1425,32 +1429,38 @@ cookie-av = expires-av / max-age-av / domain-av / ; attributes that don't conform to the grammars ; below are ignored +ignored-eq-value = "" / ("=" BWS ignored-value) +ignored-value = optional-value +optional-value = *1024(cookie-value-octet) + expires-av = "Expires" BWS "=" BWS cookie-date BWS - ; cookie-date is defined in separate grammar + ; cookie-date is defined in a separate grammar ; in a previous section -max-age-av = "Max-Age" BWS "=" BWS max-age-value BWS -max-age-value = 1*1024(DIGIT) / "-" 1*1023(DIGIT) - -domain-av = "Domain" BWS "=" BWS domain-value BWS -domain-value = 1*1024(cookie-value-octet) - ; a leading dot in domain-value will be removed - ; if present +max-age-av = "Max-Age" BWS max-age-eq-value BWS +max-age-eq-value = "" / ("=" BWS max-age-value) +max-age-value = *1024(DIGIT) / ("-" *1023(DIGIT)) -path-av = "Path" BWS "=" BWS path-value BWS -path-value = 1*1024(cookie-value-octet) +domain-av = "Domain" BWS domain-eq-value BWS +domain-eq-value = "" / ("=" BWS domain-value) +domain-value = optional-value + ; a leading %x2E (period) in domain-value will be + ; removed if present -secure-av = "Secure" BWS *ignored-value +path-av = "Path" BWS path-eq-value BWS +path-eq-value = "" / ("=" BWS path-value) +path-value = optional-value -httponly-av = "HttpOnly" BWS *ignored-value +secure-av = "Secure" BWS ignored-eq-value BWS -samesite-av = "SameSite" BWS "=" BWS samesite-value BWS -samesite-value = "Strict" / "Lax" / "None" +httponly-av = "HttpOnly" BWS ignored-eq-value BWS -extension-av = 1*cookie-name-octet BWS *optional-value +samesite-av = "SameSite" BWS samesite-eq-value BWS +samesite-eq-value = "" / ("=" BWS samesite-value) +samesite-value = "Strict" / "Lax" / "None" / ignored-value -ignored-value = "=" BWS *1024(cookie-value-octet) BWS -optional-value = ignored-value +extension-av = 1*cookie-name-octet BWS extension-eq-value BWS +extension-eq-value = "" / ("=" BWS optional-value) ~~~ ## Storage Model {#storage-model} @@ -2314,7 +2324,7 @@ reference detailing how the attribute is to be processed and stored. New registrations happen on a "RFC Required" basis (see Section 4.7 of {{RFC8126}}). The attribute to be registered MUST match the `extension-av` -syntax defined in {{sane-abnf-syntax}}. Note that attribute names are generally +syntax defined in {{server-abnf-syntax}}. Note that attribute names are generally defined in CamelCase, but technically accepted case-insensitively. ### Registration From 6728b5baf3d64836e14016408ded0d8ae5449949 Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Thu, 21 Oct 2021 01:19:02 -0400 Subject: [PATCH 4/5] Fix type (should be 'equivalent') Co-authored-by: Julian Reschke --- draft-ietf-httpbis-rfc6265bis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft-ietf-httpbis-rfc6265bis.md b/draft-ietf-httpbis-rfc6265bis.md index 78d83d4454..4f6fa59b52 100644 --- a/draft-ietf-httpbis-rfc6265bis.md +++ b/draft-ietf-httpbis-rfc6265bis.md @@ -313,7 +313,7 @@ The OWS (optional whitespace) and BWS (bad whitespace) rules are defined in Section 5.6.3 of {{!HTTPSEM=I-D.ietf-httpbis-semantics}}. Note that per {{RFC5234}}, all strings literals used in the grammars are -case-insensitive (e.g. "Secure" is equiavelent to "secure" and "sEcUrE"). +case-insensitive (e.g. "Secure" is equivalent to "secure" and "sEcUrE"). ## Terminology From 38fc7afe144439b07e6af2483694544d60e3ac76 Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Mon, 1 Nov 2021 12:46:35 -0400 Subject: [PATCH 5/5] Split up attribute grammars into the corresponding sections --- draft-ietf-httpbis-rfc6265bis.md | 160 +++++++++++++++++++------------ 1 file changed, 98 insertions(+), 62 deletions(-) diff --git a/draft-ietf-httpbis-rfc6265bis.md b/draft-ietf-httpbis-rfc6265bis.md index 4f6fa59b52..d4d8157e81 100644 --- a/draft-ietf-httpbis-rfc6265bis.md +++ b/draft-ietf-httpbis-rfc6265bis.md @@ -1219,6 +1219,39 @@ said to "receive a cookie" from the request-uri with name cookie-name, value cookie-value, and attributes cookie-attribute-list. (See {{storage-model}} for additional requirements triggered by receiving a cookie.) +### Syntax {#ua-abnf-syntax} + +Based on the parsing algorithms defined above, the following grammar defines +the syntax requirements enforced by user agents when parsing set-cookie-strings: + +~~~ abnf +set-cookie = set-cookie-string +set-cookie-string = cookie-pair *( BWS ";" OWS cookie-av) +cookie-pair = *1(BWS cookie-name BWS "=") BWS cookie-value BWS + ; the sum of the lengths of cookie-name and + ; cookie-value must be less than or equal to 4096 + ; octets. + +cookie-name = *4096(cookie-name-octet) +cookie-value = *4096(cookie-value-octet) +cookie-name-octet = %x09 / %x20-3A / %x3C / %x3E-7E / %x80-FF + ; octets excluding non-whitespace CTLs, + ; semicolon, and equals. +cookie-value-octet = %x09 / %x20-3A / %x3C-7E / %x80-FF + ; octets excluding non-whitespace CTLs and + ; semicolon. + +cookie-attr = 1*cookie-name-octet BWS cookie-attr-eq-value BWS +cookie-attr-eq-value = "" / ("=" BWS optional-attr-value) + ; cookie-attr defines the base syntax for all cookie attributes. More + ; specific grammars for each of the recognized attribute names can be + ; found in the sections below. + +optional-attr-value = *1024(cookie-value-octet) +ignored-attr-eq-value = "" / ("=" BWS ignored-atrr-value) +ignored-attr-value = optional-attr-value +~~~ + ### The Expires Attribute If the attribute-name case-insensitively matches the string "Expires", the @@ -1243,6 +1276,15 @@ user agent MUST process the cookie-av as follows. 6. Append an attribute to the cookie-attribute-list with an attribute-name of Expires and an attribute-value of expiry-time. +Based on the parsing algorithm above, the syntax requirements for the Expires +attribute are represented by the grammar below. Expires attributes not +conforming to this grammar are ignored. + +~~~ abnf +expires-av = "Expires" BWS "=" BWS cookie-date BWS + ; cookie-date is defined in the "Dates" section. +~~~ + ### The Max-Age Attribute If the attribute-name case-insensitively matches the string "Max-Age", the @@ -1268,6 +1310,16 @@ user agent MUST process the cookie-av as follows. 7. Append an attribute to the cookie-attribute-list with an attribute-name of Max-Age and an attribute-value of expiry-time. +Based on the parsing algorithm above, the syntax requirements for the Max-Age +attribute are represented by the grammar below. Max-Age attributes not +conforming to this grammar are ignored. + +~~~ abnf +max-age-av = "Max-Age" BWS max-age-eq-value BWS +max-age-eq-value = "" / ("=" BWS max-age-value) +max-age-value = *1024(DIGIT) / ("-" *1023(DIGIT)) +~~~ + ### The Domain Attribute If the attribute-name case-insensitively matches the string "Domain", the user @@ -1283,6 +1335,18 @@ agent MUST process the cookie-av as follows. 4. Append an attribute to the cookie-attribute-list with an attribute-name of Domain and an attribute-value of cookie-domain. +Based on the parsing algorithm above, the syntax requirements for the Domain +attribute are represented by the grammar below. Domain attributes not +conforming to this grammar are ignored. + +~~~ abnf +domain-av = "Domain" BWS domain-eq-value BWS +domain-eq-value = "" / ("=" BWS domain-value) +domain-value = optional-attr-value + ; a leading %x2E (period) in domain-value will be + ; removed if present. +~~~ + ### The Path Attribute If the attribute-name case-insensitively matches the string "Path", the user @@ -1300,18 +1364,42 @@ agent MUST process the cookie-av as follows. 2. Append an attribute to the cookie-attribute-list with an attribute-name of Path and an attribute-value of cookie-path. +Based on the parsing algorithm above, the syntax requirements for the Path +attribute are represented by the grammar below. Path attributes not conforming +to this grammar are ignored. + +~~~ abnf +path-av = "Path" BWS path-eq-value BWS +path-eq-value = "" / ("=" BWS path-value) +path-value = optional-attr-value +~~~ + ### The Secure Attribute If the attribute-name case-insensitively matches the string "Secure", the user agent MUST append an attribute to the cookie-attribute-list with an attribute-name of Secure and an empty attribute-value. +The syntax requirements for the Secure attribute are represented by the +grammar below. Secure attributes not conforming to this grammar are ignored. + +~~~ abnf +secure-av = "Secure" BWS ignored-attr-eq-value BWS +~~~ + ### The HttpOnly Attribute If the attribute-name case-insensitively matches the string "HttpOnly", the user agent MUST append an attribute to the cookie-attribute-list with an attribute-name of HttpOnly and an empty attribute-value. +The syntax requirements for the HttpOnly attribute are represented by the +grammar below. HttpOnly attributes not conforming to this grammar are ignored. + +~~~ abnf +httponly-av = "HttpOnly" BWS ignored-attr-eq-value BWS +~~~ + ### The SameSite Attribute If the attribute-name case-insensitively matches the string "SameSite", the @@ -1331,6 +1419,16 @@ user agent MUST process the cookie-av as follows: 5. Append an attribute to the cookie-attribute-list with an attribute-name of "SameSite" and an attribute-value of `enforcement`. +Based on the parsing algorithm above, the syntax requirements for the SameSite +attribute are represented by the grammar below. SameSite attributes not +conforming to this grammar are ignored. + +~~~ abnf +samesite-av = "SameSite" BWS samesite-eq-value BWS +samesite-eq-value = "" / ("=" BWS samesite-value) +samesite-value = "Strict" / "Lax" / "None" / ignored-attr-value +~~~ + #### "Strict" and "Lax" enforcement {#strict-lax} Same-site cookies in "Strict" enforcement mode will not be sent along with @@ -1401,68 +1499,6 @@ with elapsed since the cookie's creation-time is at most a duration of the user agent's choosing. -## Syntax {#ua-abnf-syntax} - -Based on the parsing algorithms defined above, the following grammar defines -the syntax requirements enforced by user agents when parsing -set-cookie-strings: - -~~~ abnf -set-cookie = set-cookie-string -set-cookie-string = cookie-pair *( BWS ";" OWS cookie-av) -cookie-pair = *1(BWS cookie-name BWS "=") BWS cookie-value BWS - ; the sum of the lengths of cookie-name and cookie-value - ; must be less than or equal to 4096 octets - -cookie-name = *4096(cookie-name-octet) -cookie-value = *4096(cookie-value-octet) -cookie-name-octet = %x09 / %x20-3A / %x3C / %x3E-7E / %x80-FF - ; octets excluding non-whitespace CTLs, - ; semicolon, and equals -cookie-value-octet = %x09 / %x20-3A / %x3C-7E / %x80-FF - ; octets excluding non-whitespace CTLs and - ; semicolon - -cookie-av = expires-av / max-age-av / domain-av / - path-av / secure-av / httponly-av / - samesite-av / extension-av - ; attributes that don't conform to the grammars - ; below are ignored - -ignored-eq-value = "" / ("=" BWS ignored-value) -ignored-value = optional-value -optional-value = *1024(cookie-value-octet) - -expires-av = "Expires" BWS "=" BWS cookie-date BWS - ; cookie-date is defined in a separate grammar - ; in a previous section - -max-age-av = "Max-Age" BWS max-age-eq-value BWS -max-age-eq-value = "" / ("=" BWS max-age-value) -max-age-value = *1024(DIGIT) / ("-" *1023(DIGIT)) - -domain-av = "Domain" BWS domain-eq-value BWS -domain-eq-value = "" / ("=" BWS domain-value) -domain-value = optional-value - ; a leading %x2E (period) in domain-value will be - ; removed if present - -path-av = "Path" BWS path-eq-value BWS -path-eq-value = "" / ("=" BWS path-value) -path-value = optional-value - -secure-av = "Secure" BWS ignored-eq-value BWS - -httponly-av = "HttpOnly" BWS ignored-eq-value BWS - -samesite-av = "SameSite" BWS samesite-eq-value BWS -samesite-eq-value = "" / ("=" BWS samesite-value) -samesite-value = "Strict" / "Lax" / "None" / ignored-value - -extension-av = 1*cookie-name-octet BWS extension-eq-value BWS -extension-eq-value = "" / ("=" BWS optional-value) -~~~ - ## Storage Model {#storage-model} The user agent stores the following fields about each cookie: name, value,