OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 // This file implements the tamper detection logic, where we want to detect | |
bengr
2014/07/11 18:22:45
This comment should be moved to the .h.
xingx
2014/07/15 04:51:33
Done.
| |
6 // whether there are middleboxes and whether they are tampering the response | |
7 // which maybe break correct communication and data transfer between Chrome | |
8 // and data reduction proxy. | |
9 // | |
10 // A high-level description of our tamper detection process works in two steps: | |
11 // 1. Data reduction proxy selects the requests we want to detect tamper; | |
bengr
2014/07/11 18:22:46
The data...
xingx
2014/07/15 04:51:32
Done.
| |
12 // for the selected ones, data reduction proxy generates a series of | |
bengr
2014/07/11 18:22:47
the data reduction...
xingx
2014/07/15 04:51:34
Done.
| |
13 // fingerprints of the response, and append them to the Chrome-Proxy header; | |
bengr
2014/07/11 18:22:46
of -> for
appends it
xingx
2014/07/15 04:51:34
Done.
| |
14 // 2. At Chrome client side, once it sees such fingerprints, it uses the | |
bengr
2014/07/11 18:22:46
When Chrome sees such fingerprints in response hea
xingx
2014/07/15 04:51:33
Done.
| |
15 // same method of data reduction proxy to generate the fingerprints on | |
bengr
2014/07/11 18:22:44
of --> as the
remove "on the response it receives
xingx
2014/07/15 04:51:33
Done.
| |
16 // the response it receives, compare it to the result on the response | |
17 // data reduction proxy sends, i.e., the attached fingerprints in | |
18 // Chrome-Proxy header, to see if they are identical and report to UMA if | |
19 // there is any tamper detected. | |
20 // | |
21 // Right now we have 4 fingerprints (listed below). Chrome first check the | |
bengr
2014/07/11 18:22:47
Right now we --> Four fingerprints are defined (li
xingx
2014/07/15 04:51:33
Done.
| |
22 // fingerprint of Chrome-Proxy header. If Chrome-Proxy header has been | |
23 // tampered, then other fingerprints would not be checked; if not, Chrome | |
bengr
2014/07/11 18:22:46
This is Chromium code too.
In general you don't h
xingx
2014/07/15 04:51:34
Done.
| |
24 // parses the rest of the fingerprints and check whether there is tampering | |
bengr
2014/07/11 18:22:47
checks
xingx
2014/07/15 04:51:33
Done.
| |
25 // on each of them. | |
26 // | |
27 // 1. Chrome-Proxy header | |
28 // whether values of Chrome-Proxy have been tampered; | |
29 // 2. Via header | |
30 // whether there are middleboxes between Chrome and data reduction proxy; | |
31 // 3. Some other headers | |
32 // whether the values of a list of headers have been tampered; | |
33 // 4. Content-Length header | |
34 // whether the value of Content-Length is different to what data reduction | |
35 // proxy sends, which indicates that the response body has been tampered. | |
36 // | |
37 // Chrome reports tamper or not information for each fingerprint to UMA. In | |
bengr
2014/07/11 18:22:46
Up above you seem to suggest that UMA is only coll
xingx
2014/07/15 04:51:34
Done.
| |
38 // general, Chrome reports the number of tampers for each fingerprint on | |
39 // different carriers, as well as total number of tamper detection handled. | |
40 // The only special case is the 4th fingerprint, Content-Length, which we have | |
41 // another dimension, MIME types, Chrome reports the tamper on different MIME | |
42 // type independently. | |
43 | |
44 | |
45 #include <string.h> | |
46 #include <algorithm> | |
bengr
2014/07/11 18:22:47
alphabetize
xingx
2014/07/15 04:51:33
Done.
| |
47 #include <vector> | |
48 | |
49 #include "base/base64.h" | |
50 #include "base/md5.h" | |
51 #include "base/metrics/histogram.h" | |
52 #include "base/metrics/sparse_histogram.h" | |
53 #include "base/strings/string_number_conversions.h" | |
54 #include "components/data_reduction_proxy/browser/data_reduction_proxy_tamper_de tect.h" | |
55 | |
bengr
2014/07/11 18:22:44
remove the blank line
xingx
2014/07/15 04:51:34
Done.
| |
56 #include "net/android/network_library.h" | |
57 #include "net/http/http_request_headers.h" | |
58 #include "net/http/http_util.h" | |
59 | |
60 // Macro for UMA report. First report to either |https_histogram| or | |
bengr
2014/07/11 18:22:45
report -> reporting
xingx
2014/07/15 04:51:34
Done.
| |
61 // |http_histogram| depends on |scheme_is_https|, with carrier ID as bucket | |
bengr
2014/07/11 18:22:46
depends -> depending
xingx
2014/07/15 04:51:33
Done.
| |
62 // |mcc_mnc_|. Then report to http(s)_histogram_Total, which counts the total | |
bengr
2014/07/11 18:22:45
carrier_id_
bengr
2014/07/11 18:22:46
Is that the name of the histogram? Clarify.
xingx
2014/07/15 04:51:35
Done.
| |
63 // number. | |
64 #define UMA_REPORT(scheme_is_https, http_histogram, https_histogram, mcc_mnc) \ | |
bengr
2014/07/11 18:22:44
Why is this a macro. Make this a function.
xingx
2014/07/15 04:51:33
Because it is only 1 line of code and occurs a lot
| |
65 do { \ | |
66 if (scheme_is_https) { \ | |
67 UMA_HISTOGRAM_SPARSE_SLOWLY(https_histogram, mcc_mnc); \ | |
68 UMA_HISTOGRAM_COUNTS(https_histogram "_Total", 1); \ | |
69 } else { \ | |
70 UMA_HISTOGRAM_SPARSE_SLOWLY(http_histogram, mcc_mnc); \ | |
71 UMA_HISTOGRAM_COUNTS(http_histogram "_Total", 1); \ | |
72 }\ | |
73 } while (0) | |
74 | |
75 namespace data_reduction_proxy { | |
76 | |
77 namespace { | |
bengr
2014/07/11 18:22:45
I see no reason for this anonymous namespace to be
xingx
2014/07/15 04:51:35
Done.
| |
78 // Two fingerprints will be added to Chrome-Proxy header. One starts with | |
bengr
2014/07/11 18:22:47
I thought you were checking 4 things, not 2. Expla
xingx
2014/07/15 04:51:34
Done.
| |
79 // |kTamperDetectFingerprintChromeProxy|, which is the fingerprint for the | |
80 // Chrome-Proxy header. The other one starts with |kTamperDetectFingerprint|, | |
81 // which includes all other fingerprints. | |
82 const char kTamperDetectFingerprints[] = "fp="; | |
83 const char kTamperDetectFingerprintChromeProxy[] = "cp="; | |
84 | |
85 // Fingerprint |kTamperDetectFingerprint| contains multiple | |
86 // fingerprints, each starts with a tag followed by "=" and its fingerprint | |
87 // value. Three fingerprints and their respective tags are defined below. | |
88 const char kTamperDetectFingerprintVia[] = "via"; | |
89 const char kTamperDetectFingerprintOther[] = "oh"; | |
90 const char kTamperDetectFingerprintContengLength[] = "cl"; | |
91 | |
92 } // namespace | |
93 | |
94 void DataReductionProxyTamperDetect::CheckResponseFingerprint( | |
bengr
2014/07/11 18:22:47
add: "// static" above this line.
xingx
2014/07/15 04:51:35
Done.
| |
95 const net::HttpResponseHeaders* headers, | |
96 const bool is_secure_scheme) | |
97 { | |
98 std::vector<std::string> values = DataReductionProxyTamperDetect:: | |
bengr
2014/07/11 18:22:45
You don't need the DataReductionProxyTamperDetect:
xingx
2014/07/15 04:51:34
Done.
| |
99 GetHeaderValues(headers, "Chrome-Proxy"); | |
100 | |
101 // |chrome_proxy_fingerprint| holds the value of fingerprint of | |
102 // Chrome-Proxy header. | |
103 // |other_fingerprints| holds the value of other fingerprints. | |
104 std::string chrome_proxy_fingerprint, other_fingerprints; | |
105 | |
106 // Check if there are fingerprints (and thus need to detect tamper). | |
bengr
2014/07/11 18:22:47
tampering
xingx
2014/07/15 04:51:33
Done.
| |
107 if (!GetTamperDetectFingerprints(&values, | |
bengr
2014/07/11 18:22:46
rename: GetTamperDetectionFingerprints, or just Ge
xingx
2014/07/15 04:51:35
Done.
| |
108 &chrome_proxy_fingerprint, | |
109 &other_fingerprints)) | |
110 return; | |
111 | |
112 // Found tamper detect request field. | |
bengr
2014/07/11 18:22:46
detection
xingx
2014/07/15 04:51:35
Done.
| |
113 // Get carrier ID. | |
114 unsigned mcc_mnc = 0; | |
bengr
2014/07/11 18:22:46
carrier_id
xingx
2014/07/15 04:51:35
Done.
| |
115 base::StringToUint(net::android::GetTelephonyNetworkOperator(), &mcc_mnc); | |
bengr
2014/07/11 18:22:45
What do you do on other platforms? Will this even
| |
116 | |
117 DataReductionProxyTamperDetect tamper_detect(headers, is_secure_scheme, | |
bengr
2014/07/11 18:22:45
put each param on its own line if they don't all f
xingx
2014/07/15 04:51:33
Done.
| |
118 mcc_mnc, &values); | |
119 | |
120 // Check if Chrome-Proxy header has been tampered. | |
bengr
2014/07/11 18:22:46
if the Chrome-Proxy ... tampered with.
xingx
2014/07/15 04:51:34
Done.
| |
121 if (tamper_detect.IsChromeProxyHeaderTampered(chrome_proxy_fingerprint)) { | |
bengr
2014/07/11 18:22:46
rename tamper_detect as tamper_detection
xingx
2014/07/15 04:51:34
Done.
| |
122 UMA_REPORT(is_secure_scheme, | |
123 "DataReductionProxy.HTTPSHeaderTampered_ChromeProxy", | |
124 "DataReductionProxy.HTTPHeaderTampered_ChromeProxy", | |
125 mcc_mnc); | |
126 return; | |
127 } else | |
bengr
2014/07/11 18:22:45
add curly braces
xingx
2014/07/15 04:51:35
Done.
| |
128 UMA_REPORT(is_secure_scheme, | |
129 "DataReductionProxy.HTTPSHeaderTamperDetection", | |
130 "DataReductionProxy.HTTPHeaderTamperDetection", | |
131 mcc_mnc); | |
132 | |
133 // Separate fingerprints from |other_fingerprints|. | |
134 net::HttpUtil::ValuesIterator it(other_fingerprints.begin(), | |
bengr
2014/07/11 18:22:45
put all the parameters on one line
xingx
2014/07/15 04:51:35
Done.
| |
135 other_fingerprints.end(), '|'); | |
136 | |
137 // For each fingerprint, get its name |key| and the fingerprint value |value| | |
bengr
2014/07/11 18:22:45
I think DataReductionProxyHeaders should have a fu
| |
138 // from data reduction proxy. CheckReportFingerprint will handle the tamper | |
139 // detect and corresponding UMA report. | |
bengr
2014/07/11 18:22:47
detect --> detection
and report the corresponding
xingx
2014/07/15 04:51:35
Removed that two lines, codes explain it pretty mu
| |
140 size_t delimiter_pos = std::string::npos; | |
141 while (it.GetNext()) { | |
bengr
2014/07/11 18:22:44
can't you use the same logic as in data_reduction_
| |
142 delimiter_pos = it.value().find("="); | |
143 if (delimiter_pos == std::string::npos) | |
144 continue; | |
145 std::string key = it.value().substr(0, delimiter_pos); | |
146 std::string value = it.value().substr(delimiter_pos + 1); | |
147 | |
148 FingerprintCode fingerprint_code = tamper_detect.GetFingerprintCode(key); | |
149 switch (fingerprint_code) { | |
150 case VIA: | |
151 if (tamper_detect.IsViaHeaderTampered(value)) | |
152 tamper_detect.ReportViaHeaderTamperedUMA(); | |
153 break; | |
154 case OTHERHEADERS: | |
155 if (tamper_detect.AreOtherHeadersTampered(value)) | |
156 tamper_detect.ReportOtherHeadersTamperedUMA(); | |
157 break; | |
158 case CONTENTLENGTH: | |
159 if (tamper_detect.IsContentLengthHeaderTampered(value)) | |
160 tamper_detect.ReportContentLengthHeaderTamperedUMA(); | |
161 break; | |
162 default: | |
163 NOTREACHED(); | |
164 break; | |
165 } | |
166 } | |
167 return; | |
168 } | |
169 | |
170 // Initialize fingerprint code map. | |
171 DataReductionProxyTamperDetect::DataReductionProxyTamperDetect( | |
172 const net::HttpResponseHeaders* headers, const bool is_secure, | |
173 const unsigned mcc_mnc, std::vector<std::string>* values) | |
174 : response_headers_(headers), | |
175 is_secure_scheme_(is_secure), | |
176 mcc_mnc_(mcc_mnc), | |
177 clean_chrome_proxy_header_values_(values) { | |
178 fingperprint_tag_code_map_ = std::map<std::string, FingerprintCode>(); | |
179 fingperprint_tag_code_map_[kTamperDetectFingerprintVia] = VIA; | |
180 fingperprint_tag_code_map_[kTamperDetectFingerprintOther] = OTHERHEADERS; | |
181 fingperprint_tag_code_map_[kTamperDetectFingerprintContengLength] = | |
182 CONTENTLENGTH; | |
183 }; | |
184 | |
185 DataReductionProxyTamperDetect::~DataReductionProxyTamperDetect() {}; | |
186 | |
187 // Check whether Chrome-Proxy header has been tampered. | |
bengr
2014/07/11 18:22:46
tampered with.
bengr
2014/07/11 18:22:46
Checks whether the
xingx
2014/07/15 04:51:34
Done.
xingx
2014/07/15 04:51:35
Done.
| |
188 // |fingerprint| is the fingerprint Chrome received from data reduction proxy, | |
bengr
2014/07/11 18:22:45
remove "Chrome"
xingx
2014/07/15 04:51:34
Done.
| |
189 // which is Base64 encoded. Decode it first. Calculate the hash value of | |
bengr
2014/07/11 18:22:47
Calculates...
xingx
2014/07/15 04:51:33
Done.
| |
190 // Chrome-Proxy header. Note that |clean_chrome_proxy_header_values__| holds | |
191 // the values of Chrome-Proxy header with its own fingerprint removed, | |
192 // so it's the correct values to be used to calculate fingerprint. | |
193 // Compare calculated fingerprint to the fingerprint from data reduction proxy | |
bengr
2014/07/11 18:22:46
Compares...
xingx
2014/07/15 04:51:34
Done.
| |
194 // (the removed value) and see there is tamper detected. | |
195 bool DataReductionProxyTamperDetect::IsChromeProxyHeaderTampered( | |
196 const std::string& fingerprint) const { | |
bengr
2014/07/11 18:22:46
indent only 4.
xingx
2014/07/15 04:51:34
Done.
| |
197 std::string received_fingerprint; | |
198 if (!base::Base64Decode(fingerprint, &received_fingerprint)) | |
199 return true; | |
200 // Calculate the MD5 hash value of Chrome-Proxy. | |
201 std::string actual_fingerprint = GetMD5( | |
202 ValuesToSortedString(*clean_chrome_proxy_header_values_)); | |
bengr
2014/07/11 18:22:47
Where is memory allocated for this vector?
| |
203 | |
204 return received_fingerprint != actual_fingerprint; | |
205 } | |
206 | |
207 // Check whether there are proxies/middleboxes between Chrome | |
bengr
2014/07/11 18:22:44
Remove the first sentence and the word "Concretely
bengr
2014/07/11 18:22:45
Checks...
xingx
2014/07/15 04:51:33
Done.
xingx
2014/07/15 04:51:34
Done.
| |
208 // and data reduction proxy. Concretely, it checks whether there are other | |
bengr
2014/07/11 18:22:47
and the...
xingx
2014/07/15 04:51:35
removed.
| |
209 // proxies/middleboxes' name after data reduction proxy's name in Via header. | |
210 bool DataReductionProxyTamperDetect::IsViaHeaderTampered( | |
211 const std::string& fingerprint) const { | |
bengr
2014/07/11 18:22:45
indent only 4
xingx
2014/07/15 04:51:32
Done.
| |
212 | |
213 std::vector<std::string> vias = GetHeaderValues(response_headers_, "via"); | |
bengr
2014/07/11 18:22:45
vias -> via_header_values
xingx
2014/07/15 04:51:34
Done.
| |
214 | |
215 // If there is no tag, then data reduction proxy's tag have been removed. | |
bengr
2014/07/11 18:22:44
have -> has
bengr
2014/07/11 18:22:47
then the
xingx
2014/07/15 04:51:35
Done.
xingx
2014/07/15 04:51:35
Done.
| |
216 if (vias.size() == 0) return true; | |
bengr
2014/07/11 18:22:46
move the return to the next line.
xingx
2014/07/15 04:51:34
Done.
| |
217 | |
218 // Check whether the last proxy/middlebox is data reduction proxy or not. | |
bengr
2014/07/11 18:22:45
is the
xingx
2014/07/15 04:51:34
Done.
| |
219 bool seen_data_reduction_proxy = false; | |
bengr
2014/07/11 18:22:44
seen_data_reduction_proxy -> in_via_header
xingx
2014/07/15 04:51:33
Done.
| |
220 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDataReductionProxyViaValues); ++i) { | |
221 if (vias[vias.size() - 1].find(kDataReductionProxyViaValues[i]) != | |
222 std::string::npos) { | |
223 seen_data_reduction_proxy = true; | |
224 break; | |
225 } | |
226 } | |
227 | |
228 return !seen_data_reduction_proxy; | |
bengr
2014/07/11 18:22:47
In general, you shouldn't do any header processing
| |
229 } | |
230 | |
231 // Report Via header tamper detected. | |
232 void DataReductionProxyTamperDetect::ReportViaHeaderTamperedUMA() const { | |
233 UMA_REPORT(is_secure_scheme_, | |
234 "DataReductionProxy.HTTPSHeaderTampered_Via", | |
235 "DataReductionProxy.HTTPHeaderTampered_Via", | |
236 mcc_mnc_); | |
237 } | |
238 | |
239 // Check whether values of a predefined list of headers have been tampered. | |
240 // The format for |fingerprint| is: | |
241 // [base64fingerprint]:header_name1:header_namer2:... | |
242 // Firstly extract the header names in the |fingerprint|. | |
243 // For each header, | |
244 // 1) get all the values of such header; | |
245 // 2) sort the values alphabetically; | |
246 // 3) concatenate sorted values to a string and calculate MD5 hash on it. | |
247 // Finally, compare whether it equals to the received fingerprint. | |
248 bool DataReductionProxyTamperDetect::AreOtherHeadersTampered( | |
249 const std::string& fingerprint) const { | |
250 std::string received_fingerprint; | |
251 | |
252 // Fingerprint should never be empty. | |
253 DCHECK(fingerprint.size()); | |
254 | |
255 net::HttpUtil::ValuesIterator it(fingerprint.begin(), | |
256 fingerprint.end(), ':'); | |
257 | |
258 // Make sure there is [base64fingerprint] and it can be decoded. | |
259 if (!(it.GetNext() && | |
260 base::Base64Decode(std::string(it.value()), &received_fingerprint))) { | |
261 NOTREACHED(); | |
262 return true; | |
263 } | |
264 | |
265 std::string header_values; | |
266 // Enumerate the list of headers. | |
267 while (it.GetNext()) { | |
bengr
2014/07/11 18:22:47
This will start with the second fingerprint, becau
xingx
2014/07/15 04:51:33
Done.
| |
268 // Get values of one header. | |
269 std::vector<std::string> values = | |
270 GetHeaderValues(response_headers_, it.value()); | |
271 // Sort the values and concatenate them. | |
272 header_values += ValuesToSortedString(values) + ";"; | |
273 } | |
274 | |
275 // Calculate MD5 hash value on the concatenated string. | |
276 std::string actual_fingerprint = GetMD5(header_values); | |
277 | |
278 return received_fingerprint != actual_fingerprint; | |
279 } | |
280 | |
281 // Report other headers tamper detected. | |
bengr
2014/07/11 18:22:46
Reports...
xingx
2014/07/15 04:51:33
Done.
| |
282 void DataReductionProxyTamperDetect::ReportOtherHeadersTamperedUMA() const { | |
283 UMA_REPORT(is_secure_scheme_, | |
284 "DataReductionProxy.HTTPSHeaderTampered_OtherHeaders", | |
285 "DataReductionProxy.HTTPHeaderTampered_OtherHeaders", | |
286 mcc_mnc_); | |
287 } | |
288 | |
289 | |
290 // For Content-Length tamper detection... | |
bengr
2014/07/11 18:22:45
Use complete sentences.
xingx
2014/07/15 04:51:33
Done.
| |
291 // Check whether the Content-Length value is different from what | |
bengr
2014/07/11 18:22:47
Checks...
xingx
2014/07/15 04:51:32
Done.
| |
292 // data reduction proxy sees. This is an indicator that the response body | |
293 // have been modified. | |
bengr
2014/07/11 18:22:47
Fill comments out to 80 characters.
xingx
2014/07/15 04:51:33
Done.
| |
294 // It's modified only if we can decode Content-Length numbers at both end | |
295 // and such two numbers are not equal. | |
296 bool DataReductionProxyTamperDetect::IsContentLengthHeaderTampered( | |
297 const std::string& fingerprint) const { | |
bengr
2014/07/11 18:22:44
indent only 4
xingx
2014/07/15 04:51:35
Done.
| |
298 int received_content_length, actual_content_length; | |
299 // If Content-Length value from data reduction proxy is not available or | |
300 // it cannot be converted to integer, pass. | |
bengr
2014/07/11 18:22:45
to an
xingx
2014/07/15 04:51:33
Done.
| |
301 if (base::StringToInt(fingerprint, &received_content_length)) { | |
302 std::string actual_content_length_; | |
303 // If there is Content-Length at Chrome client side is not available, pass. | |
bengr
2014/07/11 18:22:46
We are on the client side.
xingx
2014/07/15 04:51:32
Done.
| |
304 if (response_headers_->GetNormalizedHeader("Content-Length", | |
305 &actual_content_length_)) { | |
306 // If the Content-Length value cannot be converted to integer, | |
307 // i.e., not valid, pass. | |
308 if (!base::StringToInt(actual_content_length_, &actual_content_length)) | |
309 return false; | |
310 return received_content_length != actual_content_length; | |
311 } | |
312 } | |
313 return false; | |
314 } | |
315 | |
316 // Report Content-Length tamper detected. | |
bengr
2014/07/11 18:22:47
Reports...
xingx
2014/07/15 04:51:33
Done.
| |
317 // Get MIME type of the response and report to different UMA histogram. | |
bengr
2014/07/11 18:22:45
Gets...
xingx
2014/07/15 04:51:33
Done.
| |
318 // Right now MIME types contain JavaScript, CSS, Images, and others. | |
319 void DataReductionProxyTamperDetect::ReportContentLengthHeaderTamperedUMA() | |
320 const { | |
321 UMA_REPORT(is_secure_scheme_, | |
322 "DataReductionProxy.HTTPSHeaderTampered_ContentLength", | |
323 "DataReductionProxy.HTTPHeaderTampered_ContentLength", | |
324 mcc_mnc_); | |
325 | |
326 // Get MIME type. | |
327 std::string mime_type; | |
328 response_headers_->GetMimeType(&mime_type); | |
329 | |
330 | |
331 // Report tampered JavaScript. | |
332 if (mime_type.compare("text/javascript") == 0 || | |
333 mime_type.compare("application/x-javascript") == 0 || | |
334 mime_type.compare("application/javascript") == 0) | |
335 UMA_REPORT(is_secure_scheme_, | |
336 "DataReductionProxy.HTTPSHeaderTampered_ContentLength_JS", | |
337 "DataReductionProxy.HTTPHeaderTampered_ContentLength_JS", | |
338 mcc_mnc_); | |
339 // Report tampered CSSs. | |
340 else if (mime_type.compare("text/css") == 0) | |
341 UMA_REPORT(is_secure_scheme_, | |
342 "DataReductionProxy.HTTPSHeaderTampered_ContentLength_CSS", | |
343 "DataReductionProxy.HTTPHeaderTampered_ContentLength_CSS", | |
344 mcc_mnc_); | |
345 // Report tampered images. | |
346 else if (mime_type.find("image") == 0) | |
347 UMA_REPORT(is_secure_scheme_, | |
348 "DataReductionProxy.HTTPSHeaderTampered_ContentLength_Image", | |
349 "DataReductionProxy.HTTPHeaderTampered_ContentLength_Image", | |
350 mcc_mnc_); | |
351 // Report tampered other MIME types. | |
352 else | |
353 UMA_REPORT(is_secure_scheme_, | |
354 "DataReductionProxy.HTTPSHeaderTampered_ContentLength_Other", | |
355 "DataReductionProxy.HTTPHeaderTampered_ContentLength_Other", | |
356 mcc_mnc_); | |
357 } | |
358 | |
359 DataReductionProxyTamperDetect::FingerprintCode | |
360 DataReductionProxyTamperDetect::GetFingerprintCode( | |
361 const std::string& tag) { | |
362 std::map<std::string, DataReductionProxyTamperDetect::FingerprintCode> | |
363 ::iterator it = fingperprint_tag_code_map_.find(tag); | |
364 | |
365 return it == fingperprint_tag_code_map_.end() ? NONEXIST : it->second; | |
366 } | |
367 | |
368 // Enumerate the values of Chrome-Proxy header and check if there are | |
369 // fingerprints of Chrome-Proxy header (kTamperDetectFingerprintChromeProxy) | |
370 // and other fingerprints (kTamperDetectFingerprint). If there are, save them | |
371 // accordingly and return true, otherwise return false. | |
372 bool DataReductionProxyTamperDetect::GetTamperDetectFingerprints( | |
373 std::vector<std::string>* values, | |
374 std::string* chrome_proxy_fingerprint, | |
375 std::string* other_fingerprints) { | |
376 int tamper_detect_fingerprints_index = -1; | |
377 | |
378 size_t size = values->size(); | |
379 for (size_t i = 0; i < size; ++i) { | |
380 if ((*values)[i].find(kTamperDetectFingerprintChromeProxy) == 0) { | |
381 tamper_detect_fingerprints_index = i; | |
382 // Save Chrome-Proxy fingerprint. | |
383 *chrome_proxy_fingerprint = (*values)[i].substr(strlen( | |
384 kTamperDetectFingerprintChromeProxy)); | |
385 } | |
386 else if ((*values)[i].find(kTamperDetectFingerprints) == 0) { | |
387 // Save other fingerprints. | |
388 *other_fingerprints = (*values)[i].substr( | |
389 strlen(kTamperDetectFingerprints)); | |
390 } | |
391 } | |
392 | |
393 if (tamper_detect_fingerprints_index == -1) | |
394 return false; | |
395 | |
396 // Erase Chrome-Proxy's fingerprint from Chrome-Proxy header for | |
397 // later fingerprint calculation. | |
398 values->erase(values->begin() + tamper_detect_fingerprints_index); | |
399 return true; | |
400 } | |
401 | |
402 // Utility function. Sort the strings in |values| alphabetically, concatenate | |
403 // them into a string. | |
404 std::string DataReductionProxyTamperDetect::ValuesToSortedString( | |
405 std::vector<std::string> &values) { | |
406 std::string aggregated_values; | |
407 | |
408 std::sort(values.begin(), values.end()); | |
409 for (size_t i = 0; i < values.size(); ++i) | |
410 aggregated_values += values[i] + ","; | |
411 return aggregated_values; | |
412 } | |
413 | |
414 // Utility function. For a given string, calculate and return the MD5 hash | |
415 // value of the string. | |
416 std::string DataReductionProxyTamperDetect::GetMD5(const std::string &input) { | |
417 base::MD5Digest digest; | |
418 base::MD5Sum(input.c_str(), input.size(), &digest); | |
419 return std::string((char*)digest.a, ARRAYSIZE_UNSAFE(digest.a)); | |
420 } | |
421 | |
422 // Utility function. For a given |header_name|, get all its values and return | |
423 // the vector contains all of the values. | |
424 std::vector<std::string> DataReductionProxyTamperDetect::GetHeaderValues( | |
425 const net::HttpResponseHeaders* headers, const std::string& header_name) { | |
426 std::vector<std::string> values; | |
427 std::string value; | |
428 void* iter = NULL; | |
429 while (headers->EnumerateHeader(&iter, header_name, &value)) { | |
430 values.push_back(value); | |
431 } | |
432 return values; | |
433 } | |
434 | |
435 } // namespace data_reduction_proxy | |
OLD | NEW |