Bug 12202 - If-None-Match requests always return 304 with FileETag None directive
Summary: If-None-Match requests always return 304 with FileETag None directive
Status: CLOSED FIXED
Alias: None
Product: Apache httpd-1.3
Classification: Unclassified
Component: core (show other bugs)
Version: HEAD
Hardware: All All
: P3 critical (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords: PatchAvailable
Depends on:
Blocks:
 
Reported: 2002-08-31 00:13 UTC by Andrew Ho
Modified: 2004-11-16 19:05 UTC (History)
0 users



Attachments
Patch against apache-1.3/src/main/http_protocol.c (530 bytes, patch)
2002-08-31 06:01 UTC, Andrew Ho
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Ho 2002-08-31 00:13:16 UTC
If Apache has the FileETag directive set to "None" and an If-None-Match header 
is sent in a request, Apache always sends back a 304 Not Modified response, 
regardless of the content of the ETag(s) sent in the If-None-Match header.

This bug is pretty high priority, because it means that if a site running 
Apache normally serves ETags but then stops serving them by setting FileETag 
None, any downstream caches which understand ETags and send If-None-Match 
requests will stop getting updated content.

How to reproduce:

    1. Make a regular HTTP request to Apache for any static file,
       and note its ETag.

    2. Make another HTTP request for that file, sending an If-None-Match
       header (for example, if the ETag from step 1 is "abcdef", send
       the header If-None-Match: "abcdef"). Apache should correctly
       return a 304 Not Modified response.

    3. Make a new If-None-Match request with a bogus ETag, for example
       by sending If-None-Match: "xxx". Apache should correctly return
       a 200 OK and include an entity body.

    4. Add a FileETag None directive to the Apache configuration,
       and restart Apache.

    5. Make the same If-None-Match request as in step 2. Again, Apache
       should correctly return a 304 Not Modified response.

    6. Make the same bogus If-None-Match request as in step 3 (or any
       other If-None-Match request with a bogus ETag). Apache will
       incorrectly return a 304 Not Modified response.

Steps 4 and 6 are enough to reproduce the bug but the other steps give a little 
context by showing the correct behavior.

We have reproduced this bug with Apache 1.3.23 on OpenBSD and Apache 1.3.26 on 
Solaris x86. We strongly suspect the bug to be platform independent; a quick 
perusal of the code makes it look like the culprit is the strstr() inside 
ap_meets_conditions() in src/main/http_protocol.c (line 612 of the Apache 
1.3.26 distribution):

    if_nonematch = ap_table_get(r->headers_in, "If-None-Match");
    if (if_nonematch != NULL) {
        if (r->method_number == M_GET) {
            if (if_nonematch[0] == '*')
                return HTTP_NOT_MODIFIED;
            if (etag != NULL) {
                if (ap_table_get(r->headers_in, "Range")) {
                    if (etag[0] != 'W' &&
                        ap_find_list_item(r->pool, if_nonematch, etag)) {
                        return HTTP_NOT_MODIFIED;
                    }
                }
   /* here */   else if (strstr(if_nonematch, etag)) {
                    return HTTP_NOT_MODIFIED;
                }

The problem appears to be that when FileETag None is set, the If-None-Match 
header is set to "" because ap_make_etag() returns "" in that case. 
Unfortunately, strstr(str, "") always returns true, so Apache incorrectly 
returns 304 Not Modified for all requests.

A quick hack would be to have ap_make_etag() return an impossible sentinel 
value instead of "" when FileETag None is set. A better fix would be to ignore 
the If-None-Match logic altogether if FileETag None is set, as there is no 
other sensible behavior.
Comment 1 Andrew Ho 2002-08-31 05:59:46 UTC
I have confirmed that the bug exists in the current CVS HEAD.
Simple one-line patch is coming...
Comment 2 Andrew Ho 2002-08-31 06:01:31 UTC
Created attachment 2879 [details]
Patch against apache-1.3/src/main/http_protocol.c
Comment 3 Justin Erenkrantz 2002-09-01 18:47:17 UTC
Fixed in revision 1.327 of http_protocol.c