diff options
author | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-20 08:14:39 +0000 |
---|---|---|
committer | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-20 08:14:39 +0000 |
commit | cd5b9a73feb4a4178973ccd571b277fcdd83e590 (patch) | |
tree | 56dee2f3bc2065f4f44b39d3f8dbc25c568a2dde /net/http/http_response_headers.cc | |
parent | 5103a768ef9ba423590b7417baa3f1bda6daa829 (diff) | |
download | chromium_src-cd5b9a73feb4a4178973ccd571b277fcdd83e590.zip chromium_src-cd5b9a73feb4a4178973ccd571b277fcdd83e590.tar.gz chromium_src-cd5b9a73feb4a4178973ccd571b277fcdd83e590.tar.bz2 |
Add a flags to further control response header persistence. We use this to
filter out Set-Cookie and Set-Cookie2 response headers from being forwarded to
the renderer. This serves to prevent the renderer from having any access to
HttpOnly cookies, and it also prevents XMLHttpRequest consumers from being able
to read cookies in the HTTP response headers. This is consistent with changes
made to Firefox and WebKit.
Patch by marius.schilder@gmail.com
R=deanm,darin
Review URL: http://codereview.chromium.org/11264
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5767 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http/http_response_headers.cc')
-rw-r--r-- | net/http/http_response_headers.cc | 109 |
1 files changed, 72 insertions, 37 deletions
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc index 8c80c49..47d2f85 100644 --- a/net/http/http_response_headers.cc +++ b/net/http/http_response_headers.cc @@ -27,22 +27,32 @@ namespace net { namespace { -// These response headers are not persisted in a cached representation of the -// response headers. (This list comes from Mozilla's nsHttpResponseHead.cpp) -const char* const kTransientHeaders[] = { +// These headers are RFC 2616 hop-by-hop headers; +// not to be stored by caches. +const char* const kHopByHopResponseHeaders[] = { "connection", "proxy-connection", "keep-alive", - "www-authenticate", - "proxy-authenticate", "trailer", "transfer-encoding", - "upgrade", + "upgrade" +}; + +// These headers are challenge response headers; +// not to be stored by caches. +const char* const kChallengeResponseHeaders[] = { + "www-authenticate", + "proxy-authenticate" +}; + +// These headers are cookie setting headers; +// not to be stored by caches or disclosed otherwise. +const char* const kCookieResponseHeaders[] = { "set-cookie", "set-cookie2" }; -// These respones headers are not copied from a 304/206 response to the cached +// These response headers are not copied from a 304/206 response to the cached // response headers. This list is based on Mozilla's nsHttpResponseHead.cpp. const char* const kNonUpdatedHeaders[] = { "connection", @@ -90,41 +100,56 @@ HttpResponseHeaders::HttpResponseHeaders(const Pickle& pickle, void** iter) Parse(raw_input); } -void HttpResponseHeaders::Persist(Pickle* pickle, bool for_cache) { - if (for_cache) { - HeaderSet transient_headers; - GetTransientHeaders(&transient_headers); +void HttpResponseHeaders::Persist(Pickle* pickle, PersistOptions options) { + if (options == PERSIST_RAW) { + pickle->WriteString(raw_headers_); + return; // Done. + } - std::string blob; - blob.reserve(raw_headers_.size()); + HeaderSet filter_headers; - // this just copies the status line w/ terminator - blob.assign(raw_headers_.c_str(), strlen(raw_headers_.c_str()) + 1); + // Construct set of headers to filter out based on options. + if ((options & PERSIST_SANS_NON_CACHEABLE) == PERSIST_SANS_NON_CACHEABLE) + AddNonCacheableHeaders(&filter_headers); - for (size_t i = 0; i < parsed_.size(); ++i) { - DCHECK(!parsed_[i].is_continuation()); + if ((options & PERSIST_SANS_COOKIES) == PERSIST_SANS_COOKIES) + AddCookieHeaders(&filter_headers); - // locate the start of the next header - size_t k = i; - while (++k < parsed_.size() && parsed_[k].is_continuation()); - --k; + if ((options & PERSIST_SANS_CHALLENGES) == PERSIST_SANS_CHALLENGES) + AddChallengeHeaders(&filter_headers); - std::string header_name(parsed_[i].name_begin, parsed_[i].name_end); - StringToLowerASCII(&header_name); + if ((options & PERSIST_SANS_HOP_BY_HOP) == PERSIST_SANS_HOP_BY_HOP) + AddHopByHopHeaders(&filter_headers); - if (transient_headers.find(header_name) == transient_headers.end()) { - // includes terminator - blob.append(parsed_[i].name_begin, parsed_[k].value_end + 1); - } + std::string blob; + blob.reserve(raw_headers_.size()); + + // This copies the status line w/ terminator null. + // Note raw_headers_ has embedded nulls instead of \n, + // so this just copies the first header line. + blob.assign(raw_headers_.c_str(), strlen(raw_headers_.c_str()) + 1); + + for (size_t i = 0; i < parsed_.size(); ++i) { + DCHECK(!parsed_[i].is_continuation()); - i = k; + // Locate the start of the next header. + size_t k = i; + while (++k < parsed_.size() && parsed_[k].is_continuation()); + --k; + + std::string header_name(parsed_[i].name_begin, parsed_[i].name_end); + StringToLowerASCII(&header_name); + + if (filter_headers.find(header_name) == filter_headers.end()) { + // Includes terminator null due to the + 1. + blob.append(parsed_[i].name_begin, parsed_[k].value_end + 1); } - blob.push_back('\0'); - pickle->WriteString(blob); - } else { - pickle->WriteString(raw_headers_); + i = k; } + blob.push_back('\0'); + + pickle->WriteString(blob); } void HttpResponseHeaders::Update(const HttpResponseHeaders& new_headers) { @@ -557,7 +582,7 @@ void HttpResponseHeaders::AddToParsed(std::string::const_iterator name_begin, parsed_.push_back(header); } -void HttpResponseHeaders::GetTransientHeaders(HeaderSet* result) const { +void HttpResponseHeaders::AddNonCacheableHeaders(HeaderSet* result) const { // Add server specified transients. Any 'cache-control: no-cache="foo,bar"' // headers present in the response specify additional headers that we should // not store in the cache. @@ -602,11 +627,21 @@ void HttpResponseHeaders::GetTransientHeaders(HeaderSet* result) const { } } } +} + +void HttpResponseHeaders::AddHopByHopHeaders(HeaderSet* result) { + for (size_t i = 0; i < arraysize(kHopByHopResponseHeaders); ++i) + result->insert(std::string(kHopByHopResponseHeaders[i])); +} + +void HttpResponseHeaders::AddCookieHeaders(HeaderSet* result) { + for (size_t i = 0; i < arraysize(kCookieResponseHeaders); ++i) + result->insert(std::string(kCookieResponseHeaders[i])); +} - // Add standard transient headers. Perhaps we should move this to a - // statically cached hash_set to avoid duplicated work? - for (size_t i = 0; i < arraysize(kTransientHeaders); ++i) - result->insert(std::string(kTransientHeaders[i])); +void HttpResponseHeaders::AddChallengeHeaders(HeaderSet* result) { + for (size_t i = 0; i < arraysize(kChallengeResponseHeaders); ++i) + result->insert(std::string(kChallengeResponseHeaders[i])); } void HttpResponseHeaders::GetMimeTypeAndCharset(std::string* mime_type, |