The Cookie header specified in RFC 2965 (and earlier in RFC 2109) begins
with a cookie-version, and then with a semicolon- or comma-separated
representation of cookies.
Hypothetically, two distinct headers (one for Version 0 cookies and one for
Version 1 cookies) might be sent. On the other hand, in section 7.2 (Cookie
Spoofing) of RFC 2965, a header is presented in which the substring
$Version="1";
is placed in front of each of two cookies in a single header.
Perhaps the version specification could be taken to be that of the
highest-version sent; but alternately it might be taken to be that of the
lowest version sent.
I have sent e.mail to Lou Montulli (one of the authors), but he has not
responded. (I suspect that he has not received my message.) I have attempted
to sent e.mail to David M. Kristol (the other author), but Bell Labs
declares his address invalid. I have written to the IETF, but they have not
responded.
[...]
> The Cookie header specified in RFC 2965 (and earlier in RFC 2109) begins
> with a cookie-version, and then with a semicolon- or comma-separated
> representation of cookies.
>
> Hypothetically, two distinct headers (one for Version 0 cookies and
> one for Version 1 cookies) might be sent. On the other hand, in
> section 7.2 (Cookie Spoofing) of RFC 2965, a header is presented in
> which the substring
>
> $Version="1";
>
> is placed in front of each of two cookies in a single header.
Yes, and note the ", " separating them. Duplicate MIME headers can
be folded together, and there is no requirement that the $Version
value be the same for each "Cookie" header.
I don't see any problem here wrt RFC 2965. AFAICT the example in
section 7.2 is just a consequence of the HTTP specs.
--
Joe Schaefer
>> The Cookie header specified in RFC 2965 (and earlier in RFC 2109) begins
>> with a cookie-version, and then with a semicolon- or comma-separated
>> representation of cookies.
>>
>> Hypothetically, two distinct headers (one for Version 0 cookies and
>> one for Version 1 cookies) might be sent. On the other hand, in
>> section 7.2 (Cookie Spoofing) of RFC 2965, a header is presented in
>> which the substring
>>
>> $Version="1";
>>
>> is placed in front of each of two cookies in a single header.
>
> Yes, and note the ", " separating them.
I did, but I'm not sure what significance you want me to impute to it. The
standard does not say that when a version declaration appears more than one,
a comma is to be used as a separator. Indeed, the comma is specified
acceptable as a separator of cookies from the _same_ original header. If
this declaration is in fact acceptable, then it should be acceptable (under
current standards) with a semicolon before it.
> Duplicate MIME headers can
> be folded together, and there is no requirement that the $Version
> value be the same for each "Cookie" header.
But we cannot always safely make an inference about HTTP headers from MIME
specifications; and (by definition) distinct HTTP header types have distinct
properties. RFC indeed states
An origin server MAY include multiple Set-Cookie2 headers in
a response. Note that an intervening gateway could fold multiple
such headers into a single header.
but
[1] That's a declaration about _server_ behavior.
[2] The term "fold" isn't here defined. (In RFC 2068 (HTTP/1.1), the term
fold appears in the declaration
HTTP/1.1 headers can be folded onto multiple lines if
the continuation line begins with a space or horizontal
tab.
from which we may infer that therein "folding" refers to a sort of
_splitting_.)
[3] The only way to combine multiple headers into a single header while
conforming to the specification of the (client-sent) Cookie header (3.3.4)
is to strip away the Version-specification from all but the first of the
pre-folded headers (much as is the prefix "Cookie: ").
The specification is
cookie = "Cookie:" cookie-version 1*((";" | ",")
cookie-value)
cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
cookie-version = "$Version" "=" value
rather than
cookie = "Cookie:" (cookie-list) *("," cookie-list)
cookie-list = cookie-version 1*(";" cookie-value)
cookie-version = "$Version" "=" value
cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
or somesuch.
I also note, however, that the specifications in RFC 2965 are somewhat
informal. (For example, in 3.2.2, the specification of portlist is formally
incorrect.) Thus, I find it _plausible_ that the intention was that version
information may be provided more than once.
> I don't see any problem here wrt RFC 2965. AFAICT the example in
> section 7.2 is just a consequence of the HTTP specs.
Whatever its status with respect to the HTTP specs, it is not in keeping
with the Cookie specs!
The issue of what a client is to return (when cookies of different versions
match the server) needs to be addressed. And it would be best were it
addressed explicitly.
Unfortunately, the parties responsible for the RFC are incommunicado.
>> The Cookie header specified in RFC 2965 (and earlier in RFC 2109) begins
>> with a cookie-version, and then with a semicolon- or comma-separated
>> representation of cookies.
>>
>> Hypothetically, two distinct headers (one for Version 0 cookies and
>> one for Version 1 cookies) might be sent. On the other hand, in
>> section 7.2 (Cookie Spoofing) of RFC 2965, a header is presented in
>> which the substring
>>
>> $Version="1";
>>
>> is placed in front of each of two cookies in a single header.
>
> Yes, and note the ", " separating them.
I did, but I'm not sure what significance you want me to impute to it. The
standard does not say that when a version declaration appears more than one,
a comma is to be used as a separator. Indeed, the comma is specified
acceptable as a separator of cookies from the _same_ original header. If
this declaration is in fact acceptable, then it should be acceptable (under
current standards) with a semicolon before it.
> Duplicate MIME headers can
> be folded together, and there is no requirement that the $Version
> value be the same for each "Cookie" header.
But we cannot always safely make an inference about HTTP headers from MIME
specifications; and (by definition) distinct HTTP header types have distinct
properties. RFC 2965 indeed states
An origin server MAY include multiple Set-Cookie2 headers in
a response. Note that an intervening gateway could fold multiple
such headers into a single header.
but
[1] That's a declaration about _server_ behavior.
[2] The term "fold" isn't here defined. (In RFC 2068 (HTTP/1.1), the term
fold appears in the declaration
HTTP/1.1 headers can be folded onto multiple lines if
the continuation line begins with a space or horizontal
tab.
from which we may infer that therein "folding" refers to a sort of
_splitting_.)
[3] The only way to combine multiple headers into a single header while
conforming to the specification of the (client-sent) Cookie header (3.3.4)
is to strip away the Version-specification from all but the first of the
pre-combined headers (much as is the prefix "Cookie: ").
The specification is
cookie = "Cookie:" cookie-version 1*((";" | ",") cookie-value)
cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
cookie-version = "$Version" "=" value
rather than
cookie = "Cookie:" cookie-list *("," cookie-list)
cookie-list = cookie-version 1*(";" cookie-value)
cookie-version = "$Version" "=" value
cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
or somesuch.
I also note, however, that the specifications in RFC 2965 are somewhat
informal. (For example, in 3.2.2, the specification of portlist is formally
incorrect.) Thus, I find it _plausible_ that the intention was that version
information may be provided more than once.
> I don't see any problem here wrt RFC 2965. AFAICT the example in
> section 7.2 is just a consequence of the HTTP specs.
Whatever its status with respect to the HTTP specs, it does not appear to be
in keeping with the Cookie specs.
The issue of what a client is to return (when cookies of different versions
match the server) needs to be addressed. And it would be best were it
addressed explicitly.
Unfortunately, all parties responsible for the RFC are incommunicado!
> On 28-Nov-2002, the incomparable Joe Schaefer <joe+u...@sunstarsys.com>
> wrote:
>
> >> The Cookie header specified in RFC 2965 (and earlier in RFC 2109) begins
> >> with a cookie-version, and then with a semicolon- or comma-separated
> >> representation of cookies.
> >>
> >> Hypothetically, two distinct headers (one for Version 0 cookies and
> >> one for Version 1 cookies) might be sent. On the other hand, in
> >> section 7.2 (Cookie Spoofing) of RFC 2965, a header is presented in
> >> which the substring
> >>
> >> $Version="1";
> >>
> >> is placed in front of each of two cookies in a single header.
> >
> > Yes, and note the ", " separating them.
>
> I did, but I'm not sure what significance you want me to impute to it.
RFC 2616, Section 4.2, last paragraph:
Multiple message-header fields with the same field-name MAY be
present in a message if and only if the entire field-value for that
header field is defined as a comma-separated list [i.e., #(values)]. It
MUST be possible to combine the multiple header fields into one
"field-name: field-value" pair, without changing the semantics of the
message, by appending each subsequent field-value to the first, each
separated by a comma. The order in which header fields with the same
field-name are received is therefore significant to the interpretation
of the combined field value, and thus a proxy MUST NOT change the order
of these field values when a message is forwarded.
> The standard does not say that when a version declaration appears more
> than one, a comma is to be used as a separator.
Right- the HTTP standard says that sending multiple "Cookie" headers
MUST be equivalent to sending a single "Cookie" header with comma-
separated "field-values".
[...]
> I also note, however, that the specifications in RFC 2965 are somewhat
> informal. (For example, in 3.2.2, the specification of portlist is formally
> incorrect.) Thus, I find it _plausible_ that the intention was that version
> information may be provided more than once.
Agreed. However in light of 2616-4.2 above, I see the issue as
being one of semantics. The BNF in 2965 doesn't permit multiple
"$Version"s in a single header, AFAICT but there's no restriction on
the number of "Cookie" headers a client may send to the server in a
single request. Therefore the example in 7.2 must be interpreted
as a "combination" ("folding" was a poor choice of words, I
apologize) of two "Cookie" headers, since 2616 does not permit its
interpretation as a single "header".
IOW, semantics :-)
--
Joe Schaefer
>>> Yes, and note the ", " separating them.
>>
>> I did, but I'm not sure what significance you want me to impute to it.
>
> RFC 2616, Section 4.2, last paragraph:
>
> Multiple message-header fields with the same field-name MAY be
> present in a message if and only if the entire field-value for that
> header field is defined as a comma-separated list [i.e., #(values)]. It
> MUST be possible to combine the multiple header fields into one
> "field-name: field-value" pair, without changing the semantics of the
> message, by appending each subsequent field-value to the first, each
> separated by a comma. The order in which header fields with the same
> field-name are received is therefore significant to the interpretation
> of the combined field value, and thus a proxy MUST NOT change the order
> of these field values when a message is forwarded.
>
>> The standard does not say that when a version declaration appears more
>> than one, a comma is to be used as a separator.
>
> Right- the HTTP standard says that sending multiple "Cookie" headers
> MUST be equivalent to sending a single "Cookie" header with comma-
> separated "field-values".
Okay, I understand this, but it does not seem to resolve the problem.
>> I also note, however, that the specifications in RFC 2965 are somewhat
>> informal. [...] Thus, I find it _plausible_ that the intention was that
>> version information may be provided more than once.
>
> Agreed. However in light of 2616-4.2 above, I see the issue as
> being one of semantics.
Yes, but I think that you here mean to claim that it is a framing problem,
and unfortunately this is not a mere framing problem. The semantics (as
they stand) do not seem subject to any resolution.
> The BNF in 2965 doesn't permit multiple
> "$Version"s in a single header, AFAICT but there's no restriction on
> the number of "Cookie" headers a client may send to the server in a
> single request.
Well, let's look specifically at one sentence in the paragraph that you
quoted:
It MUST be possible to combine the multiple header fields
into one "field-name: field-value" pair, without changing
the semantics of the message, by appending each subsequent
field-value to the first, each separated by a comma.
As I read this, headers may be combined into a single header, by
concatenating them with intermediate commas, iff the result is an otherwise
valid header. But two headers each conforming to the specification in RFC
2965 at 3.3.4 cannot be thus joined to form a header that conforms to 3.3.4.
Again, relaxation of the constraints of 3.3.4, so that more than one version
specification may appear, may be the proper and intended resolution.
Unfortunately, though I see the (problematic) example in 7.2 as suggesting a
family of candidate solutions (which is why I drew attention to it), the
purpose of that example was to address a different issue (spoofing), and the
cookies are all of Version 1.
[...]
> [3] The only way to combine multiple headers into a single header while
> conforming to the specification of the (client-sent) Cookie header
> (3.3.4) is to strip away the Version-specification from all but the
> first of the pre-combined headers (much as is the prefix "Cookie: ").
>
> The specification is
>
> cookie = "Cookie:" cookie-version 1*((";" | ",") cookie-value)
> cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
> cookie-version = "$Version" "=" value
>
> rather than
>
> cookie = "Cookie:" cookie-list *("," cookie-list)
> cookie-list = cookie-version 1*(";" cookie-value)
> cookie-version = "$Version" "=" value
> cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
>
> or somesuch.
Yes, exactly so. Please ignore my previous followup to your post,
it's very late here and I see that you fully understand the issues.
Right now I think the only reasonable conclusion about the sample
"Cookie" header in 7.2 is that its incorrect, and should be 2 separate
Cookie headers. But I also think that's a minor detail, and that
you are raising a more significant point...
[...]
> The issue of what a client is to return (when cookies of different
> versions match the server) needs to be addressed. And it would be
> best were it addressed explicitly.
I'll think about this some more, after a bit of sleep and a reread
of 2965. I think it'd help if you put forth an example client-server
conversation, because 2965 does have *something* to say about client
behavior wrt varying $Version numbers.
Best.
--
Joe Schaefer
> But I also think that's a minor detail, and that
> you are raising a more significant point...
I believe so.
> I'll think about this some more, after a bit of sleep and a reread
> of 2965.
TNX much!
> I think it'd help if you put forth an example client-server
> conversation,
I'll try to do just that after I too have had some sleep &c. ;-) (I appear
to be fighting a flu.)
> 2965 does have *something* to say about client
> behavior wrt varying $Version numbers.
Yes, it does; but, if I recall correctly, the closest that it comes to the
issue here is in 9.1.
> On 29-Nov-2002, the incomparable Joe Schaefer wrote:
[...]
> > 2965 does have *something* to say about client
> > behavior wrt varying $Version numbers.
>
> Yes, it does; but, if I recall correctly, the closest that it comes to
> the issue here is in 9.1.
I'm still doing background research on this, but I came across a url
you might find useful in gaining perspective on the genesis of 2965:
http://cs.gnmu.edu/~setia/cs70-S02/p151-kristol.pdf
especially the detailed historical account in appendix A.
HTH.
--
Joe Schaefer
[...]
> I'm still doing background research on this, but I came across a url
> you might find useful in gaining perspective on the genesis of 2965:
[typo, sorry- this time I used cut & paste :-]
> (For example, in 3.2.2, the specification of portlist is formally
> incorrect.)
I need to correct this parenthetical assertion; AFAIK, the specification of
portlist is correct. It is the sepcification of the Version set-cookie-av
which is incorrect; from the examples, one sees that it is supposed to be
set-cookie-av = [...]
| "Version" "=" <"> 1*DIGIT <">
> I'm still doing background research on this, but I came across a url
> you might find useful in gaining perspective on the genesis of 2965:
>
> http://cs.gmu.edu/~setia/cs707-S02/p151-kristol.pdf
>
>
> especially the detailed historical account in appendix A.
TNX much! I am printing-up a copy even as I write this!
> I think it'd help if you put forth an example client-server
> conversation,
I'm thinking of a case such as follows. (Extra CRLFs in headers for
readability here.)
1. Client visits weber.ucsd.edu/~dmckiern/foo/bar/blakchop.htm . Server
sends
Set-Cookie: WEBER_VISITS=10;
expires=Thursday, 09-May-2058 06:30:00 GMT;
path=/; domain=.ucsd.edu
2. Client visits lusin.ucsd.edu/~acgamst/foo/bar/ . Server sends
Set-Cookie2: Lusin_Visit_Count = "3";
Domain = ".ucsd.edu";
Max-Age = 36000000;
Path = "/foo/";
Version = "1"
3. Client visits ieng9.ucsd.edu/~cs131f/ . Server sends
Set-Cookie: IENG9_VISITS=1;
expires=Thursday, 09-May-2058 06:30:00 GMT;
path=/foo/bar/; domain=.ucsd.edu
4. Client visits osiris.ucsd.edu/foo/bar/index.htm . What should the
client send?
One possibility would be to send three Cookie headers; another would be to
send two, with the Version 0 cookies consolidated. (This latter approach
would violate the _spirit_ but not _letter_ of the rule on ordering by
path-specificity in 3.3.4.) RFC 2965 presents _no_ explicit consideration of
multiple Cookie headers being used at a single pass (see previous
parenthetical note), which makes me suspicious of the legitimacy of such an
approach.
Version 0 cookies could be translated into Version 1 cookies. But this
would amount to lying to a server that might correlate Version with more
than merely the structure of cookie-avs.
Other possibilities exist.
> (For example, in 3.2.2, the specification of portlist is formally
> incorrect.)
I need to correct this parenthetical assertion; AFAIK, the specification of
portlist is correct. It is the sepcification of the Version set-cookie-av
which is incorrect; from the examples, one sees that it is supposed to be
set-cookie-av = [...]
| "Version" "=" (1*DIGIT | <"> 1*DIGIT <">)
> I came across a url
> you might find useful in gaining perspective on the genesis of 2965:
>
> http://cs.gmu.edu/~setia/cs707-S02/p151-kristol.pdf
Therein, I found a different e.mail address for Kristol, I have therefore
made another attempt to contact him. I will of course share anything that I
learn.
[...]
> I'm thinking of a case such as follows. (Extra CRLFs in headers for
> readability here.)
>
> 1. Client visits weber.ucsd.edu/~dmckiern/foo/bar/blakchop.htm .
> Server sends
>
> Set-Cookie: WEBER_VISITS=10;
> expires=Thursday, 09-May-2058 06:30:00 GMT;
> path=/; domain=.ucsd.edu
weber.ucsd.edu is not implementing 2965 (Set-Cookie isn't a 2965
header). Presumably the client is implementing both 2965 and Netscape's
standard, so it stores this as a Netscape ($Version=0) cookie.
> 2. Client visits lusin.ucsd.edu/~acgamst/foo/bar/ . Server sends
>
> Set-Cookie2: Lusin_Visit_Count = "3";
> Domain = ".ucsd.edu";
> Max-Age = 36000000;
> Path = "/foo/";
> Version = "1"
That is a 2965 cookie. Assuming the client enforces 3.3.2, it
should reject that cookie (AAUI the $Path above is not a "prefix"
of the request-URI). Since I don't think this technicality is
relevant to the topic of discussion, lets say the original URI was
so the client unequivocally stores it as a $Version=1 2956 cookie.
>
> 3. Client visits ieng9.ucsd.edu/~cs131f/ . Server sends
>
> Set-Cookie: IENG9_VISITS=1;
> expires=Thursday, 09-May-2058 06:30:00 GMT;
> path=/foo/bar/; domain=.ucsd.edu
Again, a Netscape cookie. The Netscape spec imposes no relation on the
request-URI and the cookie path, so the client stores this straightaway
as a Netscape cookie.
> 4. Client visits osiris.ucsd.edu/foo/bar/index.htm . What should the
> client send?
>
> One possibility would be to send three Cookie headers;
> another would be to send two, with the Version 0 cookies
> consolidated. (This latter approach would violate the _spirit_ but not
> _letter_ of the rule on ordering by path-specificity in 3.3.4.)
My reading of 9.1 is different. In particular, I see it this way:
A user agent that supports both this specification and Netscape-style
cookies SHOULD send a Cookie request header that follows the older
Netscape specification if it received the cookie in a Set-Cookie ...
^^^
a
(where the cookies in question are the ones relevant to the URI,
applying both specs independently).
My interpretation [1] suggests that the client SHOULD send
Cookie: IENG9_VISITS=1; Lusin_Visit_Count=3; WEBER_VISITS=1
Cookie2: $Version="1"
IOW, the user agent
1) downgrades [2] the 2956 cookie to a Netscape cookie,
2) follows the Netscape standard in constructing a Cookie header,
3) Notifies the server that it supports 2956 via the Cookie2 header.
Basically, interoperability trumps security here.
> RFC 2965 presents _no_ explicit consideration of multiple Cookie
> headers being used at a single pass (see previous parenthetical note),
> which makes me suspicious of the legitimacy of such an approach.
Agreed. Now that I'm awake :-), I don't believe that it is ever
valid for a client to send multiple Cookie headers within a single
request.
[1] - I've looked at a half-dozen clients that ostensibly support
both specs, and not one of them agrees with my interpretation.
[2] - To my knowledge, "downgrading" a 2956 cookie to a NS cookie
isn't described anywhere in any spec, but my intent should be
clear that this is only done for the purposes of serializing the
cookie data and constructing the Cookie header. It amounts
to simply not sending any of a 2956 cookie's attributes back
to the server, and following the Netscape spec for path
ordering.
--
Joe Schaefer
> My reading of 9.1 is different. In particular, I see it this way:
>
> A user agent that supports both this specification and Netscape-style
> cookies SHOULD send a Cookie request header that follows the older
> Netscape specification if it received the cookie in a Set-Cookie ...
> ^^^
> a
<snip>
> IOW, the user agent
>
> 1) downgrades [2] the 2956 cookie to a Netscape cookie,
> 2) follows the Netscape standard in constructing a Cookie header,
> 3) Notifies the server that it supports 2956 via the Cookie2 header.
>
> Basically, interoperability trumps security here.
That's a very appealing response.
But let's say that the client already holds a Version 1 (2965) cookie from
the fourth machine. (Alternately, make the fourth visit a return to the
second machine.) That cookie would then be returned as a Version 0
(Netscape) cookie. It seems to me that (because RFC 2965 did not explicitly
declare this or any policy) the programmers and coders of the server will
presume that their own cookie will be returned to them -- if at all -- as a
Version 1 cookie. Operationally, a domain- and path-matching Version 0
cookie could "break" server code widely thought to be compliant with RFC
2965.
(Off the top of my head, it also seems that translating Version 1 cookies to
Version 0 cookies could undermine some of the social objectives of the the
new standard. It would be unfortunate to give one site the power to effect
another in such a way.)
> [1] - I've looked at a half-dozen clients that ostensibly support
> both specs, and not one of them agrees with my interpretation.
Hahahahaha!!!
Well, one of those clients might be doing the right thing; but, if so, it is
perhaps only by chance co-incidence. A programmer doing his or her job
correctly would have had doubts, which you and I should find represented in
some form of public discourse or announcement!
> On 30-Nov-2002, the incomparable Joe Schaefer wrote:
>
> > My reading of 9.1 is different. In particular, I see it this way:
> >
> > A user agent that supports both this specification and Netscape-style
> > cookies SHOULD send a Cookie request header that follows the older
> > Netscape specification if it received the cookie in a Set-Cookie ...
> > ^^^
> > a
> <snip>
> > IOW, the user agent
> >
> > 1) downgrades [2] the 2956 cookie to a Netscape cookie,
> > 2) follows the Netscape standard in constructing a Cookie header,
> > 3) Notifies the server that it supports 2956 via the Cookie2 header.
> >
> > Basically, interoperability trumps security here.
>
> That's a very appealing response.
>
> But let's say that the client already holds a Version 1 (2965) cookie from
> the fourth machine. (Alternately, make the fourth visit a return to the
> second machine.) That cookie would then be returned as a Version 0
> (Netscape) cookie. It seems to me that (because RFC 2965 did not explicitly
> declare this or any policy) the programmers and coders of the server will
> presume that their own cookie will be returned to them -- if at all -- as a
> Version 1 cookie. Operationally, a domain- and path-matching Version 0
> cookie could "break" server code widely thought to be compliant with RFC
> 2965.
At this point in time, I'd consider it somewhat irresponsible for
server software to support 2965 to the exclusion of the Netscape spec.
Further, I'd rather postpone server-side expectations/discussions a bit,
since the server has no right to expect the client to do anything with
a cookie. As far as the server is concerned, the HTTP transaction is over.
Right now, I'm interested in learning what a user agent's "current
best practices" might/should be under the circumstances you have
described. I certainly don't believe that my proposed, theoretical
solution is best (or in the spirit of 2956), and it's certainly not
what browser implementers have done.
--
Joe Schaefer
> At this point in time, I'd consider it somewhat irresponsible for
> server software to support 2965 to the exclusion of the Netscape spec.
I agree entirely, but consider a server that send both a Set-Cookie and a
Set-Cookie2 header, with one or more cookies unique to the Set-Cookie2
header. I suspect that a programmer doing such a thing would not anticipate
those unique cookies coming back as Version 0 cookies.
> Further, I'd rather postpone server-side expectations/discussions a bit,
> since the server has no right to expect the client to do anything with
> a cookie. As far as the server is concerned, the HTTP transaction is
> over.
I'm willing to postpone such discussion (but I think that while a server has
no right to expect a client to return a cookie, it _might_ have a right to
expect that any return have certain properties).
> Right now, I'm interested in learning what a user agent's "current
> best practices" might/should be under the circumstances you have
> described.
I agree (though I think that best client practice must be informed both by
best server practice and by actual server practice, as vice versa).
I have in fact received (and just replied to) a message from David Kristol.
He believes that RFC 2616 permits Cookie headers to be combined into one as
in the example of RFC 2965 section 7.2, and that section 9.1 implies that
this is the course that one should take. (I have argued that thus combining
Cookie headers violates RFC 2616, and that 9.1 does not have such
implication.)
> I certainly don't believe that my proposed, theoretical
> solution is best (or in the spirit of 2965), and it's certainly not
> what browser implementers have done.
What have browser implementers done?
> I agree entirely, but consider a server that send both a Set-Cookie and a
> Set-Cookie2 header, with one or more cookies unique to the Set-Cookie2
> header. I suspect that a programmer doing such a thing would not
> anticipate those unique cookies coming back as Version 0 cookies.
(Lest there be some third-party confusing, let me note that I here have in
mind a situation where some _other_ server has also sent a relevant
Set-Cookie header.)
[...]
> I have in fact received (and just replied to) a message from David
> Kristol. He believes that RFC 2616 permits Cookie headers to be
> combined into one as in the example of RFC 2965 section 7.2, and that
> section 9.1 implies that this is the course that one should take. (I
> have argued that thus combining Cookie headers violates RFC 2616, and
> that 9.1 does not have such implication.)
Your argument certainly has merit.
[...]
> What have browser implementers done?
The short story: clients typically treat $Version as a per-cookie
attribute, and construct the "Cookie" header by concatenating each
individual cookie according to its original type: Netscape, 2109 (?!?!)
or 2965. (The long story isn't ready, and won't be for some time,
unless someone else wants to write about it :-).
In my irrelevant opinion, this is an undesirable outcome. I'd rather
have seen the Cookie2 header [1] omitted from 2965, and Section 9.1
replaced with language encouraging user agents to promote all outgoing
cookies to $Version=1 (with rigid compliance to 2965's Cookie BNF).
Specifically, I view the $Version component of the Cookie header to be
an in-band means of telling the server which Cookie spec the user agent
understands best. I do not view it as a per-cookie attribute.
In contrast to my earlier suggestion, I think the "current best
practices" should choose "security over interoperability" and take
some reasonable liberties with the Netscape spec. After all, that was
the intended result of 2109 (in particular Section 10.1.1 of RFC 2109).
[1]- http://lists.w3.org/Archives/Public/ietf-http-wg-old/1997MayAug/0776.html
--
Joe Schaefer
On 30-Nov-2002, the incomparable Joe Schaefer wrote:
>> I have in fact received (and just replied to) a message from David
>> Kristol. He believes that RFC 2616 permits Cookie headers to be
>> combined into one as in the example of RFC 2965 section 7.2, and that
>> section 9.1 implies that this is the course that one should take. (I
>> have argued that thus combining Cookie headers violates RFC 2616, and
>> that 9.1 does not have such implication.)
>
> Your argument certainly has merit.
Mr Kristol accepts the argument, and thus now declares the example at 7.2 to
be flawed.
> The short story: clients typically treat $Version as a per-cookie
> attribute, and construct the "Cookie" header by concatenating each
> individual cookie according to its original type: Netscape, 2109 (?!?!)
> or 2965. (The long story isn't ready, and won't be for some time,
> unless someone else wants to write about it :-).
>
> In my irrelevant opinion, this is an undesirable outcome.
I agree.
> I'd rather
> have seen the Cookie2 header [1] omitted from 2965, and Section 9.1
> replaced with language encouraging user agents to promote all outgoing
> cookies to $Version=1 (with rigid compliance to 2965's Cookie BNF).
I'd not considered omission of the Cookie2 header.
> In contrast to my earlier suggestion, I think the "current best
> practices" should choose "security over interoperability" and take
> some reasonable liberties with the Netscape spec.
I agree; the interoperability that most concerned me was that specifically
designed to promote secuirty.
I've received permission from Mr Kristol to post his e.mail to me. I will
now begin doing so.
-------- Original Message --------
Date: Sat, 30 Nov 2002 12:05:40 -0500
From: Dave Kristol
Subject: Re: RFC 2965
To: "Mc Kiernan, Daniel Kian"
Hi. I saw your posting in comp.infosystems.www.servers.unix, but I
hadn't had a chance to respond.
> I am having difficulty inferring what a client is supposed to transmit
> in its Cookie header when it has multiple cookies that domain-, port-,
> and path-match, but with at least one such cookie being Version 0, and
> at least one cookie being Version 1.
Well, for a start, note RFC 2965, sect. 9.1:
Existing cookie implementations, based on the Netscape specification,
use the Set-Cookie (not Set-Cookie2) header. User agents that
receive in the same response both a Set-Cookie and Set-Cookie2
response header for the same cookie MUST discard the Set-Cookie
information and use only the Set-Cookie2 information. Furthermore, a
user agent MUST assume, if it received a Set-Cookie2 response header,
that the sending server complies with this document and will
understand Cookie request headers that also follow this
specification.
So (as I think you inferred), you would send (conceptually) more than
one Cookie header to the server.
>
> In Section 7.2 (Cookie Spoofing), there is an example header
>
> Cookie: $Version="1"; session_id="1234",
> $Version="1"; session_id="1111"; $Domain=".cracker.edu"
>
> which suggests that the Version datum might accompany each cookie, or be
> used as a toggle, but this example would at least seem to conflict with
> the header specification of 3.3.4.
Well, in fact, there's no conflict, although there *is* a subtlety. RFC
2965 defines the content of a Cookie header, which represents one
cookie. RFC 2616 (HTTP/1.1) defines rules for combining (I called it
"folding", which apparently caused you some trouble) more than one
header of the same name. So the example in 7.2 is what you would get if
you combined these two Cookie headers:
Cookie: $Version="1"; session_id="1234"
Cookie: $Version="1"; session_id="1111"; $Domain=".cracker.edu"
In another message in your thread, you said:
> I also note, however, that the specifications in RFC 2965 are somewhat
> informal. (For example, in 3.2.2, the specification of portlist is
> formally incorrect.)
Can you explain why you think that there is a problem with portlist?
-------- Original Message --------
Date: Sat, 30 Nov 2002 12:05:40 -0500
From: Dave Kristol
Subject: Re: RFC 2965
To: "Mc Kiernan, Daniel Kian"
>> Hi. I saw your posting in comp.infosystems.www.servers.unix, but I
>> hadn't had a chance to respond.
>
> TNX much for responding. I would like your permission to post your
> remarks in Usenet, unless you are going to provide equivalent or
> preempting remarks therein.
You may post my remarks.
BTW, I have left Bell Labs (you probably figured that out already), and
I haven't really dealt with cookie issues for 1 1/2 years, except to
answer the occasional question like yours. So my logic and answers
could be rusty.
>>> I am having difficulty inferring what a client is supposed to
>>> transmit in its Cookie header when it has multiple cookies that
>>> domain-, port-, and path-match, but with at least one such cookie
>>> being Version 0, and at least one cookie being Version 1.
>>
>> Well, for a start, note RFC 2965, sect. 9.1:
>>
>> Existing cookie implementations, based on the Netscape specification,
>
> <snip>
>
>> specification.
>
> Unfortunately, that passage doesn't really address the question. The
> domain- and path-matching cookies may come from different sites than
> that to which the client is "now" connected. And the presumption that
> the server understands Version 1 cookies isn't the same as the
> presumption that it should be sent Version 1 cookies. (Mr Schaefer
> indeed concluded that all Version 1 cookies should be translated to
> Version 0 when any Version 0 cookie is to be sent. I raised some
> concerns about this interpretation, but those concerns don't seem
> logically overwhelming.)
Our assumption was indeed that you send V1 cookies to a server that
understands them. So maybe you need to give me an example of what you
have in mind.
Hmmm. Here's one different case. Suppose you have V1 cookies from
a.foo.com and b.foo.com, V0 cookies from c.foo.com, all of which say
Domain=".foo.com", and you're sending a request to, let's say,
c.foo.com. In that case you would want to send all the cookies to
c.foo.com (for Domain=".foo.com").
I think you're right that this does not work very well at all. Perhaps
we (the HTTP state management sub-group) were a bit too optimistic that
web sites would do reasonable things, like switch to using V1 cookies
for all their servers. Therefore, there was never the intent to
translate V1 cookies and then send them to V0 servers. IMO, the only
correct behavior for a client in the above example is to send just the
V0 cookie(s) to c.foo.com.
You've probably noticed that RFC 2965 (and 2109 before) avoided as much
as possible discussing Netscape's specification. The point of the RFCs
was to supercede NS cookies, though that effort may have failed. (For
more details, see "HTTP Cookies: Standards, Privacy, and Politics",
<http://arXiv.org/abs/cs.SE/0105018>, May 9, 2001, or the version in ACM
Transactions on Internet Technology, Volume 1, #2, November, 2001,
pp.151-198.) We did not address the possibility of sending V1 cookies
to V0 servers.
>> So (as I think you inferred), you would send (conceptually) more than
>> one Cookie header to the server.
>>
>>> In Section 7.2 (Cookie Spoofing), there is an example header
>>>
>>> Cookie: $Version="1"; session_id="1234",
>>> $Version="1"; session_id="1111"; $Domain=".cracker.edu"
>>>
>>> which suggests that the Version datum might accompany each cookie, or
>>> be used as a toggle, but this example would at least seem to conflict
>>> with the header specification of 3.3.4.
>>
>> Well, in fact, there's no conflict, although there *is* a subtlety.
>> RFC 2965 defines the content of a Cookie header, which represents one
>> cookie. RFC 2616 (HTTP/1.1) defines rules for combining (I called it
>> "folding", which apparently caused you some trouble) more than one
>> header of the same name. So the example in 7.2 is what you would get
>> if you combined these two Cookie headers:
>>
>> Cookie: $Version="1"; session_id="1234"
>> Cookie: $Version="1"; session_id="1111"; $Domain=".cracker.edu"
>
> But here's the relevant passage of RFC 2616 (in 4.2):
>
> Multiple message-header fields with the same field-name MAY
> be present in a message if and only if the entire field-
> value for that header field is defined as a comma-separated
> list [i.e., #(values)]. It MUST be possible to combine the
> multiple header fields into one "field-name: field-value"
> pair, without changing the semantics of the message, by
> appending each subsequent field-value to the first, each
> separated by a comma. The order in which header fields with
> the same field-name are received is therefore significant to
> the interpretation of the combined field value, and thus a
> proxy MUST NOT change the order of these field values when a
> message is forwarded.
That's a good point, and, as you point out, the syntax in RFC 2965 does
not allow for that combining in Cookie. So I have to agree with you,
which renders the 7.2 example bogus.
> Elsewhere in the Usenet thread, I've drawn attention to the second
> sentence amongst those rules:
>
> It MUST be possible to combine the multiple header fields
> into one "field-name: field-value" pair, without changing the
> semantics of the message, by appending each subsequent field-
> value to the first, each separated by a comma.
>
> As I read this, headers may be combined into a single header, by
> concatenating them with intermediate commas, iff the result is an
> otherwise valid header. But two headers each conforming to the
> specification in RFC 2965 at 3.3.4 cannot be thus joined to form a
> header that conforms to 3.3.4.
True.
> Further, as I also note, if one can _baldly_ send more than one Cookie
> header, then it becomes possible to violate the _spirit_ of the
> path-specificity ordering rule without violating the the _letter_ of
> that rule. If the example at 7.2 is _conceptually_ two headers, then an
> otherwise disallowed ordering might be permitted.
An example of what you mean might be helpful, and, yes, one can send
more than one Cookie header.
We had discussions about the combinatorics of path- and domain- matching
and basically threw up our hands, because it would be nearly impossible
to state a reasonable set of rules for the ordering of cookies. Instead
we hoped (admittedly, not a great way to write a standard) that
implementers would be reasonable in their use of cookies. Generally
that would mean that most cookies that are meant to be sent to the same
(set of) sites would share the same Domain= and Path= values, and we
were assured that that was usually the case by two vendors.
> Were the specification at 3.3.4 amended to read
>
> cookie = "Cookie:" cookie-list *("," cookie-list)
> cookie-list = cookie-version 1*(";" cookie-value)
> cookie-version = "$Version" "=" value
> cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
> NAME = attr
> VALUE = value
> path = "$Path" "=" value
> domain = "$Domain" "=" value
> port = "$Port" [ "=" <"> 1#(1*DIGIT) <"> ]
>
> this would provide a resolution. (I still believe that it would be
> desirable to provide explicit guidance for the case of differing
> Versions.)
To be honest, I no longer recall why we didn't go that route. It would
have helped to distinguish different cookie versions (if it ever came to
that), and it would help resolve the syntactic problem with combining
cookies. I have, in the back of my head, the notion that $Version would
apply to all cookies in the (RFC 2965) cookie token until another
$Version is seen, but perhaps I'm confusing that with Set-Cookie2.
>> In another message in your thread, you said:
>>
>>> I also note, however, that the specifications in RFC 2965 are somewhat
>>> informal. (For example, in 3.2.2, the specification of portlist is
>>> formally incorrect.)
>>
>> Can you explain why you think that there is a problem with portlist?
>
> Sorry, I was tired when I made that claim. I posted a correct at about
> 3 AM this morning. What I was incompetently remembering was the problem
> with the Version set-cookie-av. Your examples and other remarks make it
> plain that you wanted
>
> set-cookie-av = [...]
> | "Version" "=" (1*DIGIT | <"> 1*DIGIT <">)
>
> or (perhaps)
>
> set-cookie-av = [...]
> | "Version" "=" <"> 1*DIGIT <">
You're right about intent. If you look at 3.2.2, under the discussion
of semantics, there's Version=value, and I then state that the value is
a decimal integer. The intent was to allow (all) values to be quotable,
but I botched the syntax on this one.
> BTW, it seems that you might also have written
>
> | "Max-Age" "=" (1*DIGIT | <"> 1*DIGIT <">)
The same idea applies to Max-Age as to Version, but this time I put the
specificity about the value in the semantic description.
-------- Original Message --------
Date: Sat, 30 Nov 2002 16:35:46 -0500
From: Dave Kristol
Subject: Re: RFC 2965
To: "Mc Kiernan, Daniel Kian"
>> Hi. I saw your posting in comp.infosystems.www.servers.unix, but I
>> hadn't had a chance to respond.
>
> TNX much for responding. I would like your permission to post your
> remarks in Usenet, unless you are going to provide equivalent or
> preempting remarks therein.
You may post my remarks.
BTW, I have left Bell Labs (you probably figured that out already), and
I haven't really dealt with cookie issues for 1 1/2 years, except to
answer the occasional question like yours. So my logic and answers
could be rusty.
>>> I am having difficulty inferring what a client is supposed to
>>> transmit in its Cookie header when it has multiple cookies that
>>> domain-, port-, and path-match, but with at least one such cookie
>>> being Version 0, and at least one cookie being Version 1.
>>
>> Well, for a start, note RFC 2965, sect. 9.1:
>>
>> Existing cookie implementations, based on the Netscape specification,
>
>> So (as I think you inferred), you would send (conceptually) more than
>> one Cookie header to the server.
>>
>>> In Section 7.2 (Cookie Spoofing), there is an example header
>>>
>>> Cookie: $Version="1"; session_id="1234",
>>> $Version="1"; session_id="1111"; $Domain=".cracker.edu"
>>>
>>> which suggests that the Version datum might accompany each cookie, or
>>> be used as a toggle, but this example would at least seem to conflict
>>> with the header specification of 3.3.4.
>>
>> Well, in fact, there's no conflict, although there *is* a subtlety.
>> RFC 2965 defines the content of a Cookie header, which represents one
>> cookie. RFC 2616 (HTTP/1.1) defines rules for combining (I called it
>> "folding", which apparently caused you some trouble) more than one
>> header of the same name. So the example in 7.2 is what you would get
>> if you combined these two Cookie headers:
>>
>> Cookie: $Version="1"; session_id="1234"
>> Cookie: $Version="1"; session_id="1111"; $Domain=".cracker.edu"
>
True.
> cookie = "Cookie:" cookie-list *("," cookie-list)
> cookie-list = cookie-version 1*(";" cookie-value)
> cookie-version = "$Version" "=" value
> cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
> NAME = attr
> VALUE = value
> path = "$Path" "=" value
> domain = "$Domain" "=" value
> port = "$Port" [ "=" <"> 1#(1*DIGIT) <"> ]
>
> this would provide a resolution. (I still believe that it would be
> desirable to provide explicit guidance for the case of differing
> Versions.)
To be honest, I no longer recall why we didn't go that route. It would
have helped to distinguish different cookie versions (if it ever came to
that), and it would help resolve the syntactic problem with combining
cookies. I have, in the back of my head, the notion that $Version would
apply to all cookies in the (RFC 2965) cookie token until another
$Version is seen, but perhaps I'm confusing that with Set-Cookie2.
>> In another message in your thread, you said:
>>
>>> I also note, however, that the specifications in RFC 2965 are somewhat
>>> informal. (For example, in 3.2.2, the specification of portlist is
>>> formally incorrect.)
>>
>> Can you explain why you think that there is a problem with portlist?
>
cookie = "Cookie:" cookie-list *("," cookie-list)
I should have written
cookie = "Cookie:" cookie-list *(((",") | (";")) cookie-list)
for the sake of backward-compatibility. (Since this is just a
might-have-been, it's not all that important.)
> IMO, the only correct behavior for a client in the above example is
> to send just the V0 cookie(s) to c.foo.com.
My problem with this is at RFC 2965, section 9.1:
User agents that receive in the same response both a
Set-Cookie and Set-Cookie2 response header for the same
cookie MUST discard the Set-Cookie information and use only
the Set-Cookie2 information.
and
User agents that receive in the same response both a
Set-Cookie and Set-Cookie2 response header for the same
cookie MUST discard the Set-Cookie information and use only
the Set-Cookie2 information.
Thus, relevant Version 0 cookies may not be available in a case where the
client is behaving as if compatible with Version 0 (and not with Version 1).
One could write a client that instead cached otherwise superseded Version 0
cookies, violating the _letter_ of RFC 2965 if not the _spirit_; but that
programming task does _not_ sound attractive to me.
As Mr Schaefer has elsewhere noted, a server is not entitled to presume that
a client has accepted its cookies; but a user may enjoy more functionality
with a client that _does_. And, in this case, pre-2965 clients would
sometimes out-perform post-2965 clients!
> My problem with this is at RFC 2965, section 9.1:
>
> User agents that receive in the same response both a
> Set-Cookie and Set-Cookie2 response header for the same
> cookie MUST discard the Set-Cookie information and use only
> the Set-Cookie2 information.
>
> and
>
> User agents that receive in the same response both a
> Set-Cookie and Set-Cookie2 response header for the same
> cookie MUST discard the Set-Cookie information and use only
> the Set-Cookie2 information.
Mr Kristol notes that I repeated the same passage. I had meant the first
quoted to be
New cookies MUST replace both equivalent old- and new-style
cookies. That is, if a user agent that follows both this
specification and Netscape's original specification receives
a Set-Cookie2 response header, and the NAME and the Domain
and Path attributes match (per the Cookie Management section)
a Netscape-style cookie, the Netscape- style cookie MUST be
discarded, and the user agent MUST retain only the cookie
adhering to this specification.
My apologies to all.
> IMO, the only correct behavior for a client in the above example is
> to send just the V0 cookie(s) to c.foo.com.
My problem with this is at RFC 2965, section 9.1:
New cookies MUST replace both equivalent old- and new-style
cookies. That is, if a user agent that follows both this
specification and Netscape's original specification receives
a Set-Cookie2 response header, and the NAME and the Domain
and Path attributes match (per the Cookie Management section)
a Netscape-style cookie, the Netscape- style cookie MUST be
discarded, and the user agent MUST retain only the cookie
adhering to this specification.
and
User agents that receive in the same response both a
Set-Cookie and Set-Cookie2 response header for the same
cookie MUST discard the Set-Cookie information and use only
the Set-Cookie2 information.
Thus, relevant Version 0 cookies may not be available in a case where the