1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/http/http_vary_data.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "base/pickle.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
11*6777b538SAndroid Build Coastguard Worker #include "net/http/http_request_headers.h"
12*6777b538SAndroid Build Coastguard Worker #include "net/http/http_request_info.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/http/http_response_headers.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/http/http_util.h"
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker namespace net {
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker HttpVaryData::HttpVaryData() = default;
19*6777b538SAndroid Build Coastguard Worker
Init(const HttpRequestInfo & request_info,const HttpResponseHeaders & response_headers)20*6777b538SAndroid Build Coastguard Worker bool HttpVaryData::Init(const HttpRequestInfo& request_info,
21*6777b538SAndroid Build Coastguard Worker const HttpResponseHeaders& response_headers) {
22*6777b538SAndroid Build Coastguard Worker base::MD5Context ctx;
23*6777b538SAndroid Build Coastguard Worker base::MD5Init(&ctx);
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker is_valid_ = false;
26*6777b538SAndroid Build Coastguard Worker bool processed_header = false;
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker // Feed the MD5 context in the order of the Vary header enumeration. If the
29*6777b538SAndroid Build Coastguard Worker // Vary header repeats a header name, then that's OK.
30*6777b538SAndroid Build Coastguard Worker //
31*6777b538SAndroid Build Coastguard Worker // If the Vary header contains '*' then we can just notice it based on
32*6777b538SAndroid Build Coastguard Worker // |cached_response_headers| in MatchesRequest(), and don't have to worry
33*6777b538SAndroid Build Coastguard Worker // about the specific headers. We still want an HttpVaryData around, to let
34*6777b538SAndroid Build Coastguard Worker // us handle this case. See section 4.1 of RFC 7234.
35*6777b538SAndroid Build Coastguard Worker //
36*6777b538SAndroid Build Coastguard Worker size_t iter = 0;
37*6777b538SAndroid Build Coastguard Worker std::string name = "vary", request_header;
38*6777b538SAndroid Build Coastguard Worker while (response_headers.EnumerateHeader(&iter, name, &request_header)) {
39*6777b538SAndroid Build Coastguard Worker if (request_header == "*") {
40*6777b538SAndroid Build Coastguard Worker // What's in request_digest_ will never be looked at, but make it
41*6777b538SAndroid Build Coastguard Worker // deterministic so we don't serialize out uninitialized memory content.
42*6777b538SAndroid Build Coastguard Worker memset(&request_digest_, 0, sizeof(request_digest_));
43*6777b538SAndroid Build Coastguard Worker return is_valid_ = true;
44*6777b538SAndroid Build Coastguard Worker }
45*6777b538SAndroid Build Coastguard Worker AddField(request_info, request_header, &ctx);
46*6777b538SAndroid Build Coastguard Worker processed_header = true;
47*6777b538SAndroid Build Coastguard Worker }
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker if (!processed_header)
50*6777b538SAndroid Build Coastguard Worker return false;
51*6777b538SAndroid Build Coastguard Worker
52*6777b538SAndroid Build Coastguard Worker base::MD5Final(&request_digest_, &ctx);
53*6777b538SAndroid Build Coastguard Worker return is_valid_ = true;
54*6777b538SAndroid Build Coastguard Worker }
55*6777b538SAndroid Build Coastguard Worker
InitFromPickle(base::PickleIterator * iter)56*6777b538SAndroid Build Coastguard Worker bool HttpVaryData::InitFromPickle(base::PickleIterator* iter) {
57*6777b538SAndroid Build Coastguard Worker is_valid_ = false;
58*6777b538SAndroid Build Coastguard Worker const char* data;
59*6777b538SAndroid Build Coastguard Worker if (iter->ReadBytes(&data, sizeof(request_digest_))) {
60*6777b538SAndroid Build Coastguard Worker memcpy(&request_digest_, data, sizeof(request_digest_));
61*6777b538SAndroid Build Coastguard Worker return is_valid_ = true;
62*6777b538SAndroid Build Coastguard Worker }
63*6777b538SAndroid Build Coastguard Worker return false;
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker
Persist(base::Pickle * pickle) const66*6777b538SAndroid Build Coastguard Worker void HttpVaryData::Persist(base::Pickle* pickle) const {
67*6777b538SAndroid Build Coastguard Worker DCHECK(is_valid());
68*6777b538SAndroid Build Coastguard Worker pickle->WriteBytes(&request_digest_, sizeof(request_digest_));
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker
MatchesRequest(const HttpRequestInfo & request_info,const HttpResponseHeaders & cached_response_headers) const71*6777b538SAndroid Build Coastguard Worker bool HttpVaryData::MatchesRequest(
72*6777b538SAndroid Build Coastguard Worker const HttpRequestInfo& request_info,
73*6777b538SAndroid Build Coastguard Worker const HttpResponseHeaders& cached_response_headers) const {
74*6777b538SAndroid Build Coastguard Worker // Vary: * never matches.
75*6777b538SAndroid Build Coastguard Worker if (cached_response_headers.HasHeaderValue("vary", "*"))
76*6777b538SAndroid Build Coastguard Worker return false;
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Worker HttpVaryData new_vary_data;
79*6777b538SAndroid Build Coastguard Worker if (!new_vary_data.Init(request_info, cached_response_headers)) {
80*6777b538SAndroid Build Coastguard Worker // This case can happen if |this| was loaded from a cache that was populated
81*6777b538SAndroid Build Coastguard Worker // by a build before crbug.com/469675 was fixed.
82*6777b538SAndroid Build Coastguard Worker return false;
83*6777b538SAndroid Build Coastguard Worker }
84*6777b538SAndroid Build Coastguard Worker return memcmp(&new_vary_data.request_digest_, &request_digest_,
85*6777b538SAndroid Build Coastguard Worker sizeof(request_digest_)) == 0;
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker // static
GetRequestValue(const HttpRequestInfo & request_info,const std::string & request_header)89*6777b538SAndroid Build Coastguard Worker std::string HttpVaryData::GetRequestValue(
90*6777b538SAndroid Build Coastguard Worker const HttpRequestInfo& request_info,
91*6777b538SAndroid Build Coastguard Worker const std::string& request_header) {
92*6777b538SAndroid Build Coastguard Worker // Unfortunately, we do not have access to all of the request headers at this
93*6777b538SAndroid Build Coastguard Worker // point. Most notably, we do not have access to an Authorization header if
94*6777b538SAndroid Build Coastguard Worker // one will be added to the request.
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker std::string result;
97*6777b538SAndroid Build Coastguard Worker if (request_info.extra_headers.GetHeader(request_header, &result))
98*6777b538SAndroid Build Coastguard Worker return result;
99*6777b538SAndroid Build Coastguard Worker
100*6777b538SAndroid Build Coastguard Worker return std::string();
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker
103*6777b538SAndroid Build Coastguard Worker // static
AddField(const HttpRequestInfo & request_info,const std::string & request_header,base::MD5Context * ctx)104*6777b538SAndroid Build Coastguard Worker void HttpVaryData::AddField(const HttpRequestInfo& request_info,
105*6777b538SAndroid Build Coastguard Worker const std::string& request_header,
106*6777b538SAndroid Build Coastguard Worker base::MD5Context* ctx) {
107*6777b538SAndroid Build Coastguard Worker std::string request_value = GetRequestValue(request_info, request_header);
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker // Append a character that cannot appear in the request header line so that we
110*6777b538SAndroid Build Coastguard Worker // protect against case where the concatenation of two request headers could
111*6777b538SAndroid Build Coastguard Worker // look the same for a variety of values for the individual request headers.
112*6777b538SAndroid Build Coastguard Worker // For example, "foo: 12\nbar: 3" looks like "foo: 1\nbar: 23" otherwise.
113*6777b538SAndroid Build Coastguard Worker request_value.append(1, '\n');
114*6777b538SAndroid Build Coastguard Worker
115*6777b538SAndroid Build Coastguard Worker base::MD5Update(ctx, request_value);
116*6777b538SAndroid Build Coastguard Worker }
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker } // namespace net
119