Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(654)

Side by Side Diff: components/data_reduction_proxy/common/data_reduction_proxy_headers.cc

Issue 387353003: Modify data_reduction_proxy_header to support tamper detection logic. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@work
Patch Set: Modify HasDataReductionProxyViaHeader to tell whether data reduction proxy occurs at last or not. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" 5 #include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_piece.h" 10 #include "base/strings/string_piece.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/time/time.h" 12 #include "base/time/time.h"
13 #include "net/http/http_response_headers.h" 13 #include "net/http/http_response_headers.h"
14 #include "net/http/http_status_code.h" 14 #include "net/http/http_status_code.h"
15 #include "net/proxy/proxy_service.h" 15 #include "net/proxy/proxy_service.h"
16 16
17 using base::StringPiece; 17 using base::StringPiece;
18 using base::TimeDelta; 18 using base::TimeDelta;
19 using net::ProxyService; 19 using net::ProxyService;
20 20
21 namespace data_reduction_proxy { 21 namespace data_reduction_proxy {
22 22
23 bool GetDataReductionProxyActionValue(
24 const net::HttpResponseHeaders* headers,
25 const std::string& action_prefix,
26 std::string* action_value) {
27 DCHECK(action_prefix.size());
bengr 2014/07/16 19:23:56 DCHECK(!action_prefix.empty());
xingx 2014/07/16 21:22:33 Done.
28 void* iter = NULL;
29 std::string value;
30 std::string name = "chrome-proxy";
bengr 2014/07/16 19:23:56 Add an anonymous namespace above this namespace an
xingx 2014/07/16 21:22:33 Done.
31
32 while (headers->EnumerateHeader(&iter, name, &value)) {
33 if (value.size() > action_prefix.size()) {
34 if (LowerCaseEqualsASCII(value.begin(),
35 value.begin() + action_prefix.size(),
36 action_prefix.c_str()) &&
37 value[action_prefix.size()] == '=') {
bengr 2014/07/16 19:23:56 I think it's better to add '=' to the prefix befor
xingx 2014/07/16 21:22:33 Done. "enforce the last character is not '='", b
38 if (action_value)
39 *action_value = value.substr(action_prefix.size() + 1);
40 return true;
41 }
42 }
43 }
44 return false;
45 }
46
23 bool GetDataReductionProxyBypassDuration( 47 bool GetDataReductionProxyBypassDuration(
24 const net::HttpResponseHeaders* headers, 48 const net::HttpResponseHeaders* headers,
25 const std::string& action_prefix, 49 const std::string& action_prefix,
26 base::TimeDelta* duration) { 50 base::TimeDelta* duration) {
51 DCHECK(action_prefix.size());
27 void* iter = NULL; 52 void* iter = NULL;
28 std::string value; 53 std::string value;
29 std::string name = "chrome-proxy"; 54 std::string name = "chrome-proxy";
30 55
31 while (headers->EnumerateHeader(&iter, name, &value)) { 56 while (headers->EnumerateHeader(&iter, name, &value)) {
32 if (value.size() > action_prefix.size()) { 57 if (value.size() > action_prefix.size()) {
33 if (LowerCaseEqualsASCII(value.begin(), 58 if (LowerCaseEqualsASCII(value.begin(),
34 value.begin() + action_prefix.size(), 59 value.begin() + action_prefix.size(),
35 action_prefix.c_str())) { 60 action_prefix.c_str()) &&
61 value[action_prefix.size()] == '=') {
bengr 2014/07/16 19:23:56 See above comment. The loop logic shouldn't change
xingx 2014/07/16 21:22:33 Done.
xingx 2014/07/16 21:22:33 Done.
36 int64 seconds; 62 int64 seconds;
37 if (!base::StringToInt64( 63 if (!base::StringToInt64(
38 StringPiece(value.begin() + action_prefix.size(), value.end()), 64 StringPiece(value.begin() + action_prefix.size() + 1,
65 value.end()),
39 &seconds) || seconds < 0) { 66 &seconds) || seconds < 0) {
40 continue; // In case there is a well formed instruction. 67 continue; // In case there is a well formed instruction.
41 } 68 }
42 *duration = TimeDelta::FromSeconds(seconds); 69 *duration = TimeDelta::FromSeconds(seconds);
43 return true; 70 return true;
44 } 71 }
45 } 72 }
46 } 73 }
47 return false; 74 return false;
48 } 75 }
49 76
50 bool GetDataReductionProxyInfo(const net::HttpResponseHeaders* headers, 77 bool GetDataReductionProxyInfo(const net::HttpResponseHeaders* headers,
51 DataReductionProxyInfo* proxy_info) { 78 DataReductionProxyInfo* proxy_info) {
52 DCHECK(proxy_info); 79 DCHECK(proxy_info);
53 proxy_info->bypass_all = false; 80 proxy_info->bypass_all = false;
54 proxy_info->bypass_duration = TimeDelta(); 81 proxy_info->bypass_duration = TimeDelta();
55 // Support header of the form Chrome-Proxy: bypass|block=<duration>, where 82 // Support header of the form Chrome-Proxy: bypass|block=<duration>, where
56 // <duration> is the number of seconds to wait before retrying 83 // <duration> is the number of seconds to wait before retrying
57 // the proxy. If the duration is 0, then the default proxy retry delay 84 // the proxy. If the duration is 0, then the default proxy retry delay
58 // (specified in |ProxyList::UpdateRetryInfoOnFallback|) will be used. 85 // (specified in |ProxyList::UpdateRetryInfoOnFallback|) will be used.
59 // 'bypass' instructs Chrome to bypass the currently connected data reduction 86 // 'bypass' instructs Chrome to bypass the currently connected data reduction
60 // proxy, whereas 'block' instructs Chrome to bypass all available data 87 // proxy, whereas 'block' instructs Chrome to bypass all available data
61 // reduction proxies. 88 // reduction proxies.
62 89
63 // 'block' takes precedence over 'bypass', so look for it first. 90 // 'block' takes precedence over 'bypass', so look for it first.
64 // TODO(bengr): Reduce checks for 'block' and 'bypass' to a single loop. 91 // TODO(bengr): Reduce checks for 'block' and 'bypass' to a single loop.
65 if (GetDataReductionProxyBypassDuration( 92 if (GetDataReductionProxyBypassDuration(
66 headers, "block=", &proxy_info->bypass_duration)) { 93 headers, "block", &proxy_info->bypass_duration)) {
67 proxy_info->bypass_all = true; 94 proxy_info->bypass_all = true;
68 return true; 95 return true;
69 } 96 }
70 97
71 // Next, look for 'bypass'. 98 // Next, look for 'bypass'.
72 if (GetDataReductionProxyBypassDuration( 99 if (GetDataReductionProxyBypassDuration(
73 headers, "bypass=", &proxy_info->bypass_duration)) { 100 headers, "bypass", &proxy_info->bypass_duration)) {
74 return true; 101 return true;
75 } 102 }
76 return false; 103 return false;
77 } 104 }
78 105
79 bool HasDataReductionProxyViaHeader(const net::HttpResponseHeaders* headers) { 106 bool HasDataReductionProxyViaHeader(const net::HttpResponseHeaders* headers,
107 bool* is_the_last) {
bengr 2014/07/16 19:23:56 change to has_intermediary.
xingx 2014/07/16 21:22:33 Done.
80 const size_t kVersionSize = 4; 108 const size_t kVersionSize = 4;
81 const char kDataReductionProxyViaValue[] = "Chrome-Compression-Proxy"; 109 const char kDataReductionProxyViaValue[] = "Chrome-Compression-Proxy";
82 size_t value_len = strlen(kDataReductionProxyViaValue); 110 size_t value_len = strlen(kDataReductionProxyViaValue);
83 void* iter = NULL; 111 void* iter = NULL;
84 std::string value; 112 std::string value;
85 113
86 // Case-sensitive comparison of |value|. Assumes the received protocol and the 114 // Case-sensitive comparison of |value|. Assumes the received protocol and the
87 // space following it are always |kVersionSize| characters. E.g., 115 // space following it are always |kVersionSize| characters. E.g.,
88 // 'Via: 1.1 Chrome-Compression-Proxy' 116 // 'Via: 1.1 Chrome-Compression-Proxy'
89 while (headers->EnumerateHeader(&iter, "via", &value)) { 117 while (headers->EnumerateHeader(&iter, "via", &value)) {
90 if (value.size() >= kVersionSize + value_len && 118 if (value.size() >= kVersionSize + value_len &&
91 !value.compare(kVersionSize, value_len, kDataReductionProxyViaValue)) 119 !value.compare(kVersionSize, value_len, kDataReductionProxyViaValue)) {
120 if (is_the_last)
121 *is_the_last = !(headers->EnumerateHeader(&iter, "via", &value));
92 return true; 122 return true;
123 }
93 } 124 }
94 125
95 // TODO(bengr): Remove deprecated header value. 126 // TODO(bengr): Remove deprecated header value.
96 const char kDeprecatedDataReductionProxyViaValue[] = 127 const char kDeprecatedDataReductionProxyViaValue[] =
97 "1.1 Chrome Compression Proxy"; 128 "1.1 Chrome Compression Proxy";
98 iter = NULL; 129 iter = NULL;
99 while (headers->EnumerateHeader(&iter, "via", &value)) 130 while (headers->EnumerateHeader(&iter, "via", &value))
100 if (value == kDeprecatedDataReductionProxyViaValue) 131 if (value == kDeprecatedDataReductionProxyViaValue) {
132 if (is_the_last)
133 *is_the_last = !(headers->EnumerateHeader(&iter, "via", &value));
101 return true; 134 return true;
135 }
102 136
103 return false; 137 return false;
104 } 138 }
105 139
106 net::ProxyService::DataReductionProxyBypassEventType 140 net::ProxyService::DataReductionProxyBypassEventType
107 GetDataReductionProxyBypassEventType( 141 GetDataReductionProxyBypassEventType(
108 const net::HttpResponseHeaders* headers, 142 const net::HttpResponseHeaders* headers,
109 DataReductionProxyInfo* data_reduction_proxy_info) { 143 DataReductionProxyInfo* data_reduction_proxy_info) {
110 DCHECK(data_reduction_proxy_info); 144 DCHECK(data_reduction_proxy_info);
111 if (GetDataReductionProxyInfo(headers, data_reduction_proxy_info)) { 145 if (GetDataReductionProxyInfo(headers, data_reduction_proxy_info)) {
112 // A chrome-proxy response header is only present in a 502. For proper 146 // A chrome-proxy response header is only present in a 502. For proper
113 // reporting, this check must come before the 5xx checks below. 147 // reporting, this check must come before the 5xx checks below.
114 if (data_reduction_proxy_info->bypass_duration < TimeDelta::FromMinutes(30)) 148 if (data_reduction_proxy_info->bypass_duration < TimeDelta::FromMinutes(30))
115 return ProxyService::SHORT_BYPASS; 149 return ProxyService::SHORT_BYPASS;
116 return ProxyService::LONG_BYPASS; 150 return ProxyService::LONG_BYPASS;
117 } 151 }
118 if (headers->response_code() == net::HTTP_INTERNAL_SERVER_ERROR || 152 if (headers->response_code() == net::HTTP_INTERNAL_SERVER_ERROR ||
119 headers->response_code() == net::HTTP_BAD_GATEWAY || 153 headers->response_code() == net::HTTP_BAD_GATEWAY ||
120 headers->response_code() == net::HTTP_SERVICE_UNAVAILABLE) { 154 headers->response_code() == net::HTTP_SERVICE_UNAVAILABLE) {
121 // Fall back if a 500, 502 or 503 is returned. 155 // Fall back if a 500, 502 or 503 is returned.
122 return ProxyService::INTERNAL_SERVER_ERROR_BYPASS; 156 return ProxyService::INTERNAL_SERVER_ERROR_BYPASS;
123 } 157 }
124 if (!HasDataReductionProxyViaHeader(headers) && 158 if (!HasDataReductionProxyViaHeader(headers, NULL) &&
125 (headers->response_code() != net::HTTP_NOT_MODIFIED)) { 159 (headers->response_code() != net::HTTP_NOT_MODIFIED)) {
126 // A Via header might not be present in a 304. Since the goal of a 304 160 // A Via header might not be present in a 304. Since the goal of a 304
127 // response is to minimize information transfer, a sender in general 161 // response is to minimize information transfer, a sender in general
128 // should not generate representation metadata other than Cache-Control, 162 // should not generate representation metadata other than Cache-Control,
129 // Content-Location, Date, ETag, Expires, and Vary. 163 // Content-Location, Date, ETag, Expires, and Vary.
130 164
131 // The proxy Via header might also not be present in a 4xx response. 165 // The proxy Via header might also not be present in a 4xx response.
132 // Separate this case from other responses that are missing the header. 166 // Separate this case from other responses that are missing the header.
133 if (headers->response_code() >= net::HTTP_BAD_REQUEST && 167 if (headers->response_code() >= net::HTTP_BAD_REQUEST &&
134 headers->response_code() < net::HTTP_INTERNAL_SERVER_ERROR) { 168 headers->response_code() < net::HTTP_INTERNAL_SERVER_ERROR) {
135 return ProxyService::PROXY_4XX_BYPASS; 169 return ProxyService::PROXY_4XX_BYPASS;
136 } 170 }
137 return ProxyService::MISSING_VIA_HEADER; 171 return ProxyService::MISSING_VIA_HEADER;
138 } 172 }
139 // There is no bypass event. 173 // There is no bypass event.
140 return ProxyService::BYPASS_EVENT_TYPE_MAX; 174 return ProxyService::BYPASS_EVENT_TYPE_MAX;
141 } 175 }
142 176
143 } // namespace data_reduction_proxy 177 } // namespace data_reduction_proxy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698