Bug 35217 - extension cache-control directives MUST be ignored
Summary: extension cache-control directives MUST be ignored
Status: RESOLVED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_cache (show other bugs)
Version: 2.5-HEAD
Hardware: All All
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL: http://coad.measurement-factory.com/c...
Keywords: FixedInTrunk, RFC
Depends on:
Blocks:
 
Reported: 2005-06-04 01:21 UTC by Co-Advisor
Modified: 2018-02-25 20:41 UTC (History)
0 users



Attachments
max-age in the extension name (31.09 KB, text/html)
2005-06-04 01:23 UTC, Co-Advisor
Details
max-age in the extension value (31.28 KB, text/html)
2005-06-04 01:27 UTC, Co-Advisor
Details
max-age in the extension name (plain) (22.51 KB, text/plain)
2008-08-26 11:54 UTC, Co-Advisor
Details
max-age in the extension value (plain) (22.70 KB, text/plain)
2008-08-26 11:58 UTC, Co-Advisor
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Co-Advisor 2005-06-04 01:21:03 UTC
Looks like a possible RFC 2616 MUST violation. 
mod_cache does not ignore extension Cache-control
directives. For example, when a directive includes
something that looks like a standard directive (but
is not), mod_cache honors the (non-existent) standard
directive.

See attached trace(s) for details and ways to reproduce
the violation mentioned above. Note that the test cases
check that a valid standard directive is honored first.
The extension directive is tested in "step 2".

Test case IDs in the trace link to human-oriented test case
description and RFC quotes, if available.
Comment 1 Co-Advisor 2005-06-04 01:23:27 UTC
Created attachment 15298 [details]
max-age in the extension name

this trace has max-age directive inside an
blah=value extension directive
Comment 2 Co-Advisor 2005-06-04 01:27:36 UTC
Created attachment 15299 [details]
max-age in the extension value

this trace has max-age directive inside the value
of the blah=value extension directive
Comment 3 Paul Querna 2005-12-06 07:49:57 UTC
I believe this issue is still present in 2.3/trunk.
Comment 4 rahul 2008-08-26 04:26:32 UTC
Confirming this in trunk again.

First request to cache the url .

|echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\n\r\n" | nc 0 8080                                 
HTTP/1.1 200 OK
Date: Tue, 26 Aug 2008 11:12:53 GMT
Server: Sun-Java-System-Web-Proxy-Server/4.0.4
Content-length: 5
Content-type: text/plain
Last-modified: Tue, 26 Aug 2008 11:12:33 GMT
Etag: "5-48b3e521"
Accept-ranges: bytes
Via: 1.0 agneyam:8000
Connection: close

abcd

This request used the cached URL

|echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\n\r\n" | nc 0 8080
HTTP/1.1 200 OK
Date: Tue, 26 Aug 2008 11:12:53 GMT
Server: Sun-Java-System-Web-Proxy-Server/4.0.4
Last-Modified: Tue, 26 Aug 2008 11:12:17 GMT
Content-length: 5
Etag: "5-48b3e521"
Accept-ranges: bytes
Via: 1.0 agneyam:8000
Age: 1
Connection: close
Content-Type: text/plain

abcd

This one didn't (Note the quoted "name"=value )
|echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\nCache-Control: " max-age=0 "=new\r\n\r\n" | nc 0 8080
HTTP/1.1 200 OK
Date: Tue, 26 Aug 2008 11:13:02 GMT
Server: Sun-Java-System-Web-Proxy-Server/4.0.4
Content-length: 5
Etag: "5-48b3e521"
Accept-ranges: bytes
Via: 1.0 agneyam:8000
Last-Modified: Tue, 26 Aug 2008 11:12:24 GMT
Connection: close
Content-Type: text/plain

abcd
Comment 5 rahul 2008-08-26 04:42:35 UTC
Accroding to 2616, A token is defined as

  token          = 1*<any CHAR except CTLs or separators>
       separators     = "(" | ")" | "<" | ">" | "@"
                      | "," | ";" | ":" | "\" | <">
                      | "/" | "[" | "]" | "?" | "="
                      | "{" | "}" | SP | HT

Note that (") is defined as a separator. So by definition a value such as "xxxxx" will be interpreted by stripping away the separators. Thus the value " max-age=0 "=blah is interpreted as [max-age=0] [=blah] where the second entry is invalid while the first entry is valid cache control directive. 

For this reason, the behavior of apache is correct.


Comment 6 Co-Advisor 2008-08-26 09:46:53 UTC
Comment #5 says:
> Note that (") is defined as a separator.

I do not know whether the problem has been fixed since our original report, but please note that the request in Comment #4 does not have quotes. The quotes you see will be eaten by the shell. To Apache, the request looks more like this:

GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\n
Cache-Control:  max-age=0 =new\r\n
\r\n

which contains a valid max-age directive followed by garbage.

The original test cases (see attachments) do not have this problem.

> So by definition a value such as
> "xxxxx" will be interpreted by stripping away the separators. Thus the value "
> max-age=0 "=blah is interpreted as [max-age=0] [=blah] where the second entry
> is invalid while the first entry is valid cache control directive. 

Whether quoted strings are not token-like opaque blobs but regular input (that apparently should be re-parsed and interpreted!) preceded and followed by a separator is highly debatable.

IMO, the second original test case leaves little doubt that there was a bug here because it uses a quoted string in the value of the extension directive. That usage is a 100% valid extension, right? Again, I do not know whether this has been fixed since.

HTH.
Comment 7 rahul 2008-08-26 10:17:53 UTC
|I do not know whether the problem has been fixed since our original report, but
|please note that the request in Comment #4 does not have quotes. The quotes you
|see will be eaten by the shell. To Apache, the request looks more like this:

you are right, my testcases were wrong,
but my conclusion did not have anything to do with them.

> > So by definition a value such as
> > "xxxxx" will be interpreted by stripping away the separators. Thus the value "
> > max-age=0 "=blah is interpreted as [max-age=0] [=blah] where the second entry
> > is invalid while the first entry is valid cache control directive. 
> 
> Whether quoted strings are not token-like opaque blobs but regular input (that
> apparently should be re-parsed and interpreted!) preceded and followed by a
> separator is highly debatable.

Not according to rfc 2616. RFC 2616 states quite clearly that cache-extension
should be either token or token=(token|quoted-string)

Cache-Control   = "Cache-Control" ":" 1#cache-directive
    cache-directive = cache-request-directive
         | cache-response-directive
    cache-request-directive =
           "no-cache"                          ; Section 14.9.1
         | "no-store"                          ; Section 14.9.2
         | "max-age" "=" delta-seconds         ; Section 14.9.3, 14.9.4
         | "max-stale" [ "=" delta-seconds ]   ; Section 14.9.3
         | "min-fresh" "=" delta-seconds       ; Section 14.9.3
         | "no-transform"                      ; Section 14.9.5
         | "only-if-cached"                    ; Section 14.9.4
         | cache-extension                     ; Section 14.9.6

cache-extension = token [ "=" ( token | quoted-string ) ]

(Note that a quoted string is allowed after the '=' not before.)

> IMO, the second original test case leaves little doubt that there was a bug
> here because it uses a quoted string in the value of the extension directive.
> That usage is a 100% valid extension, right? Again, I do not know whether this
> has been fixed since.

So with the above definition of token, what is below is not valid, 

Cache-Control: public, " max-age=8,max-age=8 "=blah\r\n

while this would be
Cache-Control: public, blah=" max-age=8,max-age=8 "\r\n

Comment 8 Co-Advisor 2008-08-26 10:32:04 UTC
> So with the above definition of token, what is below is not valid, 
>   Cache-Control: public, " max-age=8,max-age=8 "=blah\r\n
> while this would be
>   Cache-Control: public, blah=" max-age=8,max-age=8 "\r\n

In addition, none of the above HTTP headers contains the "max-age" Cache-Control directive, IMO.
Comment 9 rahul 2008-08-26 10:46:18 UTC
| In addition, none of the above HTTP headers contains the "max-age"
| Cache-Control directive, IMO.

Your original bug was that the entry that you posted (Cache-control: "xxxx"=blah) was a valid extension directive. But as per the RFC, it is not. The question now, is as to what the httpd should do when faced with an invalid entry.

That question is open to further deliberation. IMO that is fair game for httpd to do as it pleases.
Comment 10 Co-Advisor 2008-08-26 11:05:45 UTC
> Your original bug was that the entry that you posted (Cache-control:
> "xxxx"=blah) was a valid extension directive. 

Not exactly. There were two test cases in the original bug report. The first case is using the questionable quoted string as the directive name. The second test case does not. I do not recall claiming that both directives are perfectly valid -- I know that one of them is of questionable validity, but that is not the issue in this bug report.

> But as per the RFC, it is not.
> The question now, is as to what the httpd should do when faced with an invalid
> entry.

That question is possible for the first test case but not for the second.

And even for the first test case, I would not be surprised if httpd actually ignores directives it considers invalid. If that is correct, that the first test case is still good as it illustrates that httpd is not interpreting the invalid directive as invalid.
Comment 11 rahul 2008-08-26 11:19:26 UTC
(In reply to comment #10)
> > Your original bug was that the entry that you posted (Cache-control:
> > "xxxx"=blah) was a valid extension directive. 
> 
> Not exactly. There were two test cases in the original bug report. The first
> case is using the questionable quoted string as the directive name. The second
> test case does not. I do not recall claiming that both directives are perfectly
> valid -- I know that one of them is of questionable validity, but that is not
> the issue in this bug report.

Now, I am confused, could you please specify the request(s), current response
and expected response? (The html is long, and I don't think I am looking at the same lines as you are.)

(And can I request you to quote it in text format? html is rather hard quote
 again in threads.)

> > But as per the RFC, it is not.
> > The question now, is as to what the httpd should do when faced with an invalid
> > entry.
> 
> That question is possible for the first test case but not for the second.
> 
> And even for the first test case, I would not be surprised if httpd actually
> ignores directives it considers invalid. If that is correct, that the first
> test case is still good as it illustrates that httpd is not interpreting the
> invalid directive as invalid.
 

Comment 12 Co-Advisor 2008-08-26 11:54:51 UTC
Created attachment 22484 [details]
max-age in the extension name (plain)

Saved 1st test case attachment as text per rahul request
Comment 13 Co-Advisor 2008-08-26 11:58:50 UTC
Created attachment 22485 [details]
max-age in the extension value (plain)

Saved test case attachment as text per rahul request. This test case uses the following valid Cache-Control header:

  Cache-Control: public, foobar=" max-age=8,max-age=8 "\r\n

Again, I do not know whether this bug has been fixed since it was reported.

HTH.
Comment 14 Co-Advisor 2008-08-26 12:08:33 UTC
(In reply to comment #11)
> Now, I am confused, could you please specify the request(s), current response
> and expected response? (The html is long, and I don't think I am looking at the
> same lines as you are.)
> 
> (And can I request you to quote it in text format? html is rather hard quote
>  again in threads.)

Attached test case logs have all the exchanges with the proxy server. I have re-saved them in text format per your request, but they are easier to read if you use your browser to display the HTML attachment instead (you may have to save the HTML attachment as HTML for that to work).

The violation is (was?) not in sending a wrong response to a single request but in purging a cached document in reaction to an extension cache-control directive. You have to follow the trace to see that. FWIW, some folks find it easier to read the trace backwards, from the violation to the first request.

HTH.
Comment 15 rahul 2008-08-26 12:24:05 UTC
> Created an attachment (id=22485) [details]
> max-age in the extension value (plain)
> Saved test case attachment as text per rahul request. This test case uses the
> following valid Cache-Control header:
> 
>   Cache-Control: public, foobar=" max-age=8,max-age=8 "\r\n

Thanks a lot, it is much easier now, and I understand where we were not on the
same page.

> Again, I do not know whether this bug has been fixed since it was reported.

Let me know if this is not what you are referring to.
------------------------------------------------------
First a simple request with out directives to make it cache.

|echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\n\r\n" | nc 0 8080
HTTP/1.1 200 OK
Date: Tue, 26 Aug 2008 18:52:36 GMT
Server: Sun-Java-System-Web-Proxy-Server/4.0.4
Last-Modified: Tue, 26 Aug 2008 11:12:33 GMT
Content-length: 5
Etag: "5-48b3e521"
Accept-ranges: bytes
Via: 1.0 agneyam:8000
Age: 30
Connection: close
Content-Type: text/plain

abcd

as snooped in the backend.
--> [
GET /tst.txt HTTP/1.1
Host: webproxy.india.sun.com:8000
Cache-Control: "max-age=0"=me
Via: 1.0 agneyam:8000
Connection: Keep-Alive

]
------------------------------------------------------

Now trying with a vaild cache-control max-age (valid behavior).

|echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\nCache-Control: max-age=0\r\n\r\n" | nc 0 8080 
HTTP/1.1 200 OK
Date: Tue, 26 Aug 2008 18:53:43 GMT
Server: Sun-Java-System-Web-Proxy-Server/4.0.4
Content-length: 5
Etag: "5-48b3e521"
Accept-ranges: bytes
Via: 1.0 agneyam:8000
Last-Modified: Tue, 26 Aug 2008 11:12:33 GMT
Connection: close
Content-Type: text/plain

abcd


--> [
GET /tst.txt HTTP/1.1
Host: webproxy.india.sun.com:8000
Cache-Control: max-age=0
If-None-Match: "5-48b3e521"
If-Modified-Since: Tue, 26 Aug 2008 11:12:33 GMT
Via: 1.0 agneyam:8000
Connection: Keep-Alive

]
<-- [
HTTP/1.1 304 Use local copy
Server: Sun-Java-System-Web-Proxy-Server/4.0.4
Date: Tue, 26 Aug 2008 18:53:43 GMT
Etag: "5-48b3e521"

]

------------------------------------------------------
Now trying an invalid cache-control directive,

|echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\nCache-Control: \"max-age=0\"\r\n\r\n" | nc 0 8080
HTTP/1.1 200 OK
Date: Tue, 26 Aug 2008 18:53:43 GMT
Server: Sun-Java-System-Web-Proxy-Server/4.0.4
Last-Modified: Tue, 26 Aug 2008 11:12:33 GMT
Content-length: 5
Etag: "5-48b3e521"
Accept-ranges: bytes
Via: 1.0 agneyam:8000
Age: 2
Connection: close
Content-Type: text/plain

abcd

--> No request to the back end observed.

------------------------------------------------------
Now trying an second invalid cache-control directive,

|echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\nCache-Control: \" max-age=0 \"=foobar \r\n\r\n" | nc 0 8080
HTTP/1.1 200 OK
Date: Tue, 26 Aug 2008 18:58:18 GMT
Server: Sun-Java-System-Web-Proxy-Server/4.0.4
Last-Modified: Tue, 26 Aug 2008 11:12:33 GMT
Content-length: 5
Etag: "5-48b3e521"
Accept-ranges: bytes
Via: 1.0 agneyam:8000
Age: 115
Connection: close
Content-Type: text/plain

abcd

--> No request to the back end observed.

------------------------------------------------------
Trying a third invalid cache-control directive,

|echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\nCache-Control: foobar=\" max-age=0 \" \r\n\r\n" | nc 0 8080
HTTP/1.1 200 OK
Date: Tue, 26 Aug 2008 18:58:18 GMT
Server: Sun-Java-System-Web-Proxy-Server/4.0.4
Last-Modified: Tue, 26 Aug 2008 11:12:33 GMT
Content-length: 5
Etag: "5-48b3e521"
Accept-ranges: bytes
Via: 1.0 agneyam:8000
Age: 163
Connection: close
Content-Type: text/plain

abcd

--> No request to the back end observed.

------------------------------------------------------
And no cache-eviction observed.

Is my verification correct?, if it is, then it is not present in trunk any more (though may be present in the earlier versions |> 2.0.54 < trunk| )
thanks for the bug report.
Comment 16 Co-Advisor 2008-08-26 14:32:40 UTC
I do not see any problems with your verification steps. Looks like this bug was fixed.
Comment 17 rahul 2008-08-27 00:44:14 UTC
Verified fixed in 2.2.9
closing it as fixed.
Comment 18 Rainer Jung 2018-02-25 20:41:59 UTC
Undo spam change