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 #include "components/data_reduction_proxy/browser/data_reduction_proxy_tamper_de tect.h" | |
6 | |
7 #include <string.h> | |
8 #include <algorithm> | |
9 #include <map> | |
10 #include <vector> | |
11 | |
12 #include "base/base64.h" | |
13 #include "base/md5.h" | |
14 #include "base/strings/string_number_conversions.h" | |
15 #include "base/strings/string_split.h" | |
16 #include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" | |
17 #include "net/android/network_library.h" | |
18 #include "net/http/http_response_headers.h" | |
19 #include "net/http/http_util.h" | |
20 #include "testing/gtest/include/gtest/gtest.h" | |
21 | |
22 namespace { | |
23 | |
24 void HeadersToRaw(std::string* headers) { | |
25 std::replace(headers->begin(), headers->end(), '\n', '\0'); | |
26 if (!headers->empty()) | |
27 *headers += '\0'; | |
28 } | |
29 | |
30 // Calcuates MD5 hash value for a string and then base64 encode it. | |
31 static std::string GetEncoded(const std::string& input) { | |
bolian
2014/07/21 23:43:05
s/static//
xingx
2014/07/23 19:00:29
Done.
| |
32 base::MD5Digest digest; | |
33 base::MD5Sum(input.c_str(), input.size(), &digest); | |
34 std::string base64encoded; | |
35 base::Base64Encode(std::string((char*)digest.a, | |
36 ARRAYSIZE_UNSAFE(digest.a)), &base64encoded); | |
37 return base64encoded; | |
38 } | |
39 | |
40 // Replaces all contents within "[]" by corresponding base64 encoded MD5 value. | |
41 void ReplaceWithEncodedString(std::string* input) | |
42 { | |
43 size_t start, end; | |
44 while (true) { | |
45 start = input->find("["); | |
46 if (start == std::string::npos) break; | |
47 end = input->find("]", start); | |
48 std::string need_to_encode = input->substr(start + 1, end - start - 1); | |
49 *input = input->substr(0, start) + GetEncoded(need_to_encode) + | |
50 input->substr(end + 1); | |
51 } | |
52 } | |
53 | |
54 // Testcase for fingerprint checking functions. |received_fingerprint| is | |
55 // fingerprint received from the data reduction proxy. |expected_tampered| is | |
56 // expected tampered or not result. | |
57 struct TestCaseCheckingFingerprint { | |
bolian
2014/07/21 23:43:05
rename it to TamperDetectionTestCase?
xingx
2014/07/23 19:00:29
Done.
| |
58 std::string raw_header; | |
59 std::string received_fingerprint; | |
60 bool expected_tampered; | |
61 bool expected_has_chrome_proxy_via_header; | |
62 }; | |
63 | |
64 } // namespace | |
65 | |
66 namespace data_reduction_proxy { | |
67 | |
68 class DataReductionProxyTamperDetectionTest : public testing::Test { | |
69 public: | |
70 static void TestFingerprintCommon(const TestCaseCheckingFingerprint& test, | |
71 DataReductionProxyTamperDetection::FingerprintCode fingerprint); | |
72 }; | |
73 | |
74 // Common function for testing fingerprint checking functions. For a given | |
75 // header string |test.raw_header|, generates HttpResponseHeaders |headers| and | |
76 // checks specified fingerprint checking function returns expected result or | |
77 // not. | |
78 void DataReductionProxyTamperDetectionTest::TestFingerprintCommon( | |
79 const TestCaseCheckingFingerprint& test, | |
80 DataReductionProxyTamperDetection::FingerprintCode fingerprint) { | |
bolian
2014/07/21 23:43:05
s/fingerprint/fingerprint_code/
xingx
2014/07/23 19:00:29
Done.
| |
81 std::string raw_headers(test.raw_header); | |
82 HeadersToRaw(&raw_headers); | |
83 scoped_refptr<net::HttpResponseHeaders> headers( | |
bolian
2014/07/21 23:43:05
why scoped_refptr? Will a stack var of net::HttpR
xingx
2014/07/23 19:00:29
Done.
bolian
2014/07/23 23:22:57
You are leaking memory. Just
net::HttpResponseHead
| |
84 new net::HttpResponseHeaders(raw_headers)); | |
85 | |
86 // Removes Chrome-Proxy header's fingerprint from Chrome-Proxy header. | |
87 std::vector<std::string> chrome_proxy_header_values = | |
88 DataReductionProxyTamperDetection:: | |
89 GetHeaderValues(headers, "Chrome-Proxy"); | |
90 | |
91 DataReductionProxyTamperDetection::RemoveChromeProxyFingerprint( | |
92 &chrome_proxy_header_values); | |
93 | |
94 DataReductionProxyTamperDetection tamper_detection( | |
95 headers, true, 0, &chrome_proxy_header_values); | |
96 | |
97 bool tampered; | |
bolian
2014/07/21 23:43:05
set a default value.
xingx
2014/07/23 19:00:29
Done.
| |
98 switch (fingerprint) { | |
99 case DataReductionProxyTamperDetection::CHROMEPROXY: | |
100 tampered = tamper_detection.IsChromeProxyHeaderTampered( | |
101 test.received_fingerprint); | |
102 break; | |
103 case DataReductionProxyTamperDetection::VIA: | |
104 bool has_chrome_proxy_via_header; | |
105 tampered = tamper_detection.IsViaHeaderTampered( | |
106 test.received_fingerprint, &has_chrome_proxy_via_header); | |
107 EXPECT_EQ(test.expected_has_chrome_proxy_via_header, | |
108 has_chrome_proxy_via_header); | |
109 break; | |
110 case DataReductionProxyTamperDetection::OTHERHEADERS: | |
111 tampered = tamper_detection.AreOtherHeadersTampered( | |
112 test.received_fingerprint); | |
113 break; | |
114 case DataReductionProxyTamperDetection::CONTENTLENGTH: | |
115 tampered = tamper_detection.IsContentLengthHeaderTampered( | |
116 test.received_fingerprint); | |
117 break; | |
118 case DataReductionProxyTamperDetection::NONEXIST: | |
119 break; | |
bolian
2014/07/21 23:43:04
not setting tampered in this case?
xingx
2014/07/23 19:00:29
It should not reach here.
| |
120 } | |
121 | |
122 EXPECT_EQ(test.expected_tampered, tampered); | |
123 } | |
124 | |
125 // Checks function IsChromeProxyHeaderTampered. | |
126 TEST_F(DataReductionProxyTamperDetectionTest, ChromeProxy) { | |
127 TestCaseCheckingFingerprint test[] = { | |
128 // Checks sorting values and decoding. | |
bolian
2014/07/21 23:43:05
This is the case that server does not ask for dete
xingx
2014/07/23 19:00:29
No, this is the case we check ChromeProxy's finger
| |
129 { | |
130 "HTTP/1.1 200 OK \n" | |
131 "Chrome-Proxy: aut=aauutthh," | |
132 "fp=123,bbbypas=0,aaxxx=xxx,bbbloc=1\n", | |
133 "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,fp=123,", | |
134 false, | |
135 }, | |
136 | |
137 // Checks Chrome-Proxy's fingerprint removing. | |
138 { | |
139 "HTTP/1.1 200 OK \n" | |
140 "Chrome-Proxy: a,b,c,d,e,3,2,1," + | |
141 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
142 "=1231\n", | |
143 "1,2,3,a,b,c,d,e,", | |
144 false, | |
145 }, | |
146 | |
147 // Checks no Chrome-Proxy header case (should not happen). | |
148 { | |
149 "HTTP/1.1 200 OK \n" | |
150 "Content-Length: 12345\n", | |
151 "", | |
152 false, | |
153 }, | |
154 | |
155 // Checks empty Chrome-Proxy header case (should not happen). | |
156 { | |
157 "HTTP/1.1 200 OK \n" | |
158 "Chrome-Proxy: \n", | |
159 ",", | |
160 false, | |
161 }, | |
162 | |
163 // Checks Chrome-Proxy header with its fingerprint only case. | |
164 { | |
165 "HTTP/1.1 200 OK \n" | |
166 "Chrome-Proxy: " + | |
167 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
168 "=xyz\n", | |
169 "", | |
170 false, | |
171 }, | |
172 | |
173 // Checks empty Chrome-Proxy header case, with extra "," | |
174 { | |
175 "HTTP/1.1 200 OK \n" | |
176 "Chrome-Proxy: " + | |
177 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
178 "=abcde , \n", | |
179 "", | |
180 false, | |
181 }, | |
182 | |
183 // Checks empty Chrome-Proxy header, different to fingerprint. | |
184 { | |
185 "HTTP/1.1 200 OK \n" | |
186 "Chrome-Proxy: " + | |
187 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
188 "=xyz\n", | |
189 ",", | |
190 true, | |
191 }, | |
192 | |
193 // Chrome-Proxy header different to its fingerprint. | |
bolian
2014/07/21 23:43:05
This comment does not make sense. Do you mean
// M
xingx
2014/07/23 19:00:29
Done.
| |
194 { | |
195 "HTTP/1.1 200 OK \n" | |
196 "Chrome-Proxy: aut=aauutthh,bbbypas=2,aaxxx=xxx,bbbloc=1\n", | |
bolian
2014/07/21 23:43:04
can you minimize you headers to test exact this ca
xingx
2014/07/23 19:00:29
Done.
| |
197 "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,", | |
198 true, | |
199 }, | |
200 | |
201 // Chrome-Proxy header different to its fingerprint. | |
bolian
2014/07/21 23:43:05
How is this different than above (your comment is
xingx
2014/07/23 19:00:29
Done.
| |
202 { | |
203 "HTTP/1.1 200 OK \n" | |
204 "Chrome-Proxy: a,aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n", | |
205 "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,", | |
206 true, | |
207 }, | |
208 | |
209 // Chrome-Proxy header different to its fingerprint in order. | |
210 { | |
211 "HTTP/1.1 200 OK \n" | |
212 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n", | |
213 "aaxxx=xxx,aut=aauutthh,bbbypas=0,bbbloc=1,", | |
214 true, | |
215 }, | |
216 | |
217 // Checks Chrome-Proxy header with extra " ". | |
218 { | |
219 "HTTP/1.1 200 OK \n" | |
220 "Chrome-Proxy: aut=aauutthh , bbbypas=0 , aaxxx=xxx" | |
221 " ,bbbloc=1 \n", | |
222 "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,", | |
223 false | |
224 }, | |
225 | |
226 // Check Chrome-Proxy header, with extra lines and " ". | |
227 { | |
228 "HTTP/1.1 200 OK \n" | |
229 "Chrome-Proxy: aut=aauutthh , bbbypas=0 , bbbloc=1 \n" | |
230 "Chrome-Proxy: aaxxx=xxx \n", | |
231 "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,", | |
232 false | |
233 }, | |
234 | |
235 // Checks Chrome-Proxy header with multiple lines. | |
236 { | |
237 "HTTP/1.1 200 OK \n" | |
238 "Chrome-Proxy: aaxxx=xxx \n" | |
239 "Chrome-Proxy: aut=aauutthh\n" | |
240 "Chrome-Proxy: bbbypas=0\n" | |
241 "Chrome-Proxy:bbbloc=1 \n", | |
242 "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,", | |
243 false | |
244 }, | |
245 | |
246 // Checks Chrome-Proxy header with multiple lines, at different positions | |
247 // of the entire header. | |
248 { | |
249 "HTTP/1.1 200 OK \n" | |
250 "Chrome-Proxy: aaxxx=xxx \n" | |
251 "Chrome-Proxy: aut=aauutthh\n" | |
252 "Content-Type: 1\n" | |
253 "Cache-Control: 2\n" | |
254 "ETag: 3\n" | |
255 "Chrome-Proxy: bbbypas=0\n" | |
256 "Connection: 4\n" | |
257 "Expires: 5\n" | |
258 "Chrome-Proxy: bbbloc=1\n" | |
259 "Via: \n" | |
260 "Content-Length: 12345\n" | |
261 "fp=123 \n", | |
262 "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,", | |
263 false | |
264 }, | |
265 | |
266 // Checks Chrome-Proxy header with multiple same values. | |
267 { | |
268 "HTTP/1.1 200 OK \n" | |
269 "Chrome-Proxy: aaxxx=xxx \n" | |
270 "Chrome-Proxy: aut=aauutthh\n" | |
271 "Content-Type: 1\n" | |
272 "Cache-Control: 2\n" | |
273 "ETag: 3\n" | |
274 "Chrome-Proxy: bbbypas=0\n" | |
275 "Connection: 4\n" | |
276 "Expires: 5\n" | |
277 "Chrome-Proxy: bbbloc=1, fp=123 \n" | |
278 "Chrome-Proxy: aaxxx=xxx \n" | |
279 "Via: \n" | |
280 "Content-Length: 12345\n", | |
281 "aaxxx=xxx,aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,fp=123,", | |
282 false | |
283 }, | |
284 | |
285 // Checks Chrome-Proxy header with multiple same values. | |
286 { | |
287 "HTTP/1.1 200 OK \n" | |
288 "Chrome-Proxy: aaxxx=xxx \n" | |
289 "Chrome-Proxy: aut=aauutthh\n" | |
290 "Content-Type: 1\n" | |
291 "Cache-Control: 2\n" | |
292 "ETag: 3\n" | |
293 "Chrome-Proxy: bbbypas=0\n" | |
294 "Connection: 4\n" | |
295 "Expires: 5\n" | |
296 "Chrome-Proxy: bbbloc=1, fp=123 \n" + | |
297 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
298 "xyn \n" + | |
299 "Chrome-Proxy: aaxxx=xxx \n" | |
300 "Via: \n" | |
301 "Content-Length: 12345\n", | |
302 "aaxxx=xxx,aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,fp=123,", | |
303 false | |
304 }, | |
305 | |
306 // Checks Chrome-Proxy header with multiple same values, but different to | |
307 // fingerprint. | |
308 { | |
309 "HTTP/1.1 200 OK \n" | |
310 "Chrome-Proxy: aaxxx=xxx \n" | |
311 "Chrome-Proxy: aaxxx=xxx \n" | |
312 "Chrome-Proxy: aut=aauutthh\n" | |
313 "Content-Type: 1\n" | |
314 "Cache-Control: 2\n" | |
315 "ETag: 3\n" | |
316 "Chrome-Proxy: bbbypas=0\n" | |
317 "Connection: 4\n" | |
318 "Expires: 5\n" | |
319 "Chrome-Proxy: bbbloc=1\n" | |
320 "Chrome-Proxy: aaxxx=xxx \n" | |
321 "Via: \n" | |
322 "Content-Length: 12345\n", | |
323 "aaxxx=xxx,aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,", | |
324 true, | |
325 }, | |
326 | |
327 // Check Chrome-Proxy header with multiple same values, but different to | |
328 // fingerprint. | |
329 { | |
330 "HTTP/1.1 200 OK \n" | |
331 "Chrome-Proxy: aaxxx=xxx \n" | |
332 "Chrome-Proxy: aaxxx=xxx \n" | |
333 "Chrome-Proxy: aut=aauutthh\n" | |
334 "Content-Type: 1\n" | |
335 "Cache-Control: 2\n" | |
336 "ETag: 3\n" | |
337 "Chrome-Proxy: bbbypas=0\n" | |
338 "Connection: 4\n" | |
339 "Expires: 5\n" + | |
340 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
341 "xyn \n" + | |
342 "Chrome-Proxy: bbbloc=1\n" | |
343 "Chrome-Proxy: aaxxx=xxx \n" | |
344 "Via: \n" | |
345 "Content-Length: 12345\n", | |
346 "aaxxx=xxx,aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,", | |
347 true, | |
348 }, | |
349 | |
350 // Check Chrome-Proxy header with multiple lines, but different to | |
351 // fingerprint. | |
352 { | |
353 "HTTP/1.1 200 OK \n" | |
354 "Content-Type: 1\n" | |
355 "Cache-Control: 2\n" | |
356 "ETag: 3\n" | |
357 "Chrome-Proxy: bbbypas=0\n" | |
358 "Connection: 4\n" | |
359 "Expires: 5\n" | |
360 "Chrome-Proxy: bbbloc=1\n" | |
361 "Chrome-Proxy: aaxxx=xxx \n" | |
362 "Via: \n" | |
363 "Content-Length: 12345\n", | |
364 "aaxxx=xxx,aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,", | |
365 true, | |
366 }, | |
367 | |
368 // Checks case whose received fingerprint is empty. | |
369 { | |
370 "HTTP/1.1 200 OK \n" | |
371 "Chrome-Proxy: aaxxx=xxx \n" | |
372 "Chrome-Proxy: aaxxx=xxx \n" | |
373 "Chrome-Proxy: aut=aauutthh\n" | |
374 "Content-Type: 1\n" | |
375 "Cache-Control: 2\n" | |
376 "ETag: 3\n" | |
377 "Chrome-Proxy: bbbypas=0\n" | |
378 "Connection: 4\n" | |
379 "Expires: 5\n" | |
380 "Chrome-Proxy: bbbloc=1\n" | |
381 "Chrome-Proxy: aaxxx=xxx \n" | |
382 "Via: \n" | |
383 "Content-Length: 12345\n", | |
384 "", | |
385 true, | |
386 }, | |
387 | |
388 }; | |
389 | |
390 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) { | |
391 test[i].received_fingerprint = | |
bolian
2014/07/21 23:43:05
You need to test the case that fcp value encoding
xingx
2014/07/23 19:00:29
Done.
| |
392 GetEncoded(test[i].received_fingerprint); | |
393 | |
394 DataReductionProxyTamperDetectionTest::TestFingerprintCommon(test[i], | |
bolian
2014/07/21 23:43:04
If you one case fails, can you easily tell which o
xingx
2014/07/23 19:00:29
Done.
| |
395 DataReductionProxyTamperDetection::CHROMEPROXY); | |
396 } | |
397 } | |
398 | |
399 // Check function IsViaHeaderTampered. | |
400 TEST_F(DataReductionProxyTamperDetectionTest, Via) { | |
401 TestCaseCheckingFingerprint test[] = { | |
402 // Checks the case that Chrome-Compression-Proxy occurs at the last. | |
403 { | |
404 "HTTP/1.1 200 OK \n" | |
405 "Via: a, b, c, 1.1 Chrome-Compression-Proxy\n", | |
406 "0", | |
407 false, | |
408 true, | |
409 }, | |
410 | |
411 // Checks when there is intermediary between the data reduction proxy and | |
412 // the Chromium client. | |
413 { | |
414 "HTTP/1.1 200 OK \n" | |
415 "Via: a, b, c, 1.1 Chrome-Compression-Proxy, xyz\n", | |
416 "0", | |
417 true, | |
418 true, | |
419 }, | |
420 | |
421 // Checks the case of empty Via header. | |
422 { | |
423 "HTTP/1.1 200 OK \n" | |
424 "Via: \n", | |
425 "0", | |
426 false, | |
427 false, | |
428 }, | |
429 | |
430 // Checks the case that only the data reduction proxy's Via header occurs. | |
431 { | |
432 "HTTP/1.1 200 OK \n" | |
433 "Via: 1.1 Chrome-Compression-Proxy \n", | |
434 "0", | |
435 false, | |
436 true, | |
437 }, | |
438 | |
439 // Checks the case that there are " ", i.e., empty value after the data | |
440 // reduction proxy's Via header. | |
441 { | |
442 "HTTP/1.1 200 OK \n" | |
443 "Via: 1.1 Chrome-Compression-Proxy , , \n", | |
444 "0", | |
445 false, | |
446 true, | |
447 }, | |
448 | |
449 // Checks the case when there is no Via header | |
450 { | |
451 "HTTP/1.1 200 OK \n", | |
452 "0", | |
453 false, | |
454 false, | |
455 }, | |
456 | |
457 // Same to above test cases, but with deprecated data reduciton proxy Via | |
458 // header. | |
459 { | |
460 "HTTP/1.1 200 OK \n" | |
461 "Via: a, b, c, 1.1 Chrome Compression Proxy\n", | |
462 "0", | |
463 false, | |
464 true, | |
465 }, | |
466 | |
467 { | |
468 "HTTP/1.1 200 OK \n" | |
469 "Via: a, b, c, 1.1 Chrome Compression Proxy, xyz\n", | |
470 "0", | |
471 true, | |
472 true, | |
473 }, | |
474 | |
475 { | |
476 "HTTP/1.1 200 OK \n" | |
477 "Via: \n", | |
478 "0", | |
479 false, | |
480 false, | |
481 }, | |
482 | |
483 { | |
484 "HTTP/1.1 200 OK \n" | |
485 "Via: 1.1 Chrome Compression Proxy \n", | |
486 "0", | |
487 false, | |
488 true, | |
489 }, | |
490 | |
491 { | |
492 "HTTP/1.1 200 OK \n" | |
493 "Via: 1.1 Chrome Compression Proxy , , \n", | |
494 "0", | |
495 false, | |
496 true, | |
497 }, | |
498 | |
499 { | |
500 "HTTP/1.1 200 OK \n", | |
501 "0", | |
502 false, | |
503 false, | |
504 }, | |
505 }; | |
506 | |
507 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) { | |
508 DataReductionProxyTamperDetectionTest::TestFingerprintCommon(test[i], | |
509 DataReductionProxyTamperDetection::VIA); | |
510 } | |
511 } | |
512 | |
513 // Checks function AreOtherHeadersTampered. | |
514 TEST_F(DataReductionProxyTamperDetectionTest, OtherHeaders) { | |
515 // For following testcases, |received_fingerprint| is not the actual | |
516 // fingerprint from data reduction proxy, instead, the base64 encoded field | |
517 // is in plain text (within "[]") and needs to be encoded first. For example, | |
518 // "[12345;]:content-length" needs to be encoded to | |
519 // "Base64Encoded(MD5(12345;))|content-length" before calling the checking | |
520 // function. | |
521 TestCaseCheckingFingerprint test[] = { | |
522 // Checks the case of correct fingerprint. | |
523 { | |
524 "HTTP/1.1 200 OK \n" | |
525 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
526 "Content-Type: 1\n" | |
527 "Cache-Control: 2\n" | |
528 "ETag: 3\n" | |
529 "Connection: 4\n" | |
530 "Expires: 5\n" | |
531 "Via: \n" + | |
532 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
533 "abcde \n" | |
534 "Content-Length: 12345\n", | |
535 "[1,;2,;3,;4,;5,;]|content-type|cache-control|etag|connection|expires", | |
536 false | |
537 }, | |
538 | |
539 // Checks the case of correct fingerprint. | |
540 { | |
541 "HTTP/1.1 200 OK \n" | |
542 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
543 "Content-Type: aaa1\n" | |
544 "Cache-Control: aaa2\n" + | |
545 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
546 "abcde \n" + | |
547 "ETag: aaa3\n" | |
548 "Connection: aaa4\n" | |
549 "Expires: aaa5\n" | |
550 "Via: \n" | |
551 "Content-Length: 12345\n", | |
552 "[aaa1,;aaa2,;aaa3,;aaa4,;aaa5,;]|content-type|cache-control|" | |
553 "etag|connection|expires", | |
554 false | |
555 }, | |
556 | |
557 // Checks the case that one header has multiple values. | |
558 { | |
559 "HTTP/1.1 200 OK \n" | |
560 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" + | |
561 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
562 "abcde \n" + | |
563 "Content-Type: aaa1, bbb1, ccc1\n" | |
564 "Cache-Control: aaa2\n" | |
565 "ETag: aaa3\n" | |
566 "Connection: aaa4\n" | |
567 "Expires: aaa5\n" | |
568 "Via: \n" | |
569 "Content-Length: 12345\n", | |
570 "[aaa1,bbb1,ccc1,;aaa2,;aaa3,;aaa4,;aaa5,;]|" | |
571 "content-type|cache-control|etag|connection|expires", | |
572 false | |
573 }, | |
574 | |
575 // Checks the case that one header has multiple lines. | |
576 { | |
577 "HTTP/1.1 200 OK \n" | |
578 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
579 "Content-Type: aaa1, ccc1\n" | |
580 "Content-Type: xxx1, bbb1, ccc1\n" | |
581 "Cache-Control: aaa2\n" | |
582 "ETag: aaa3\n" | |
583 "Connection: aaa4\n" | |
584 "Expires: aaa5\n" | |
585 "Via: \n" + | |
586 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
587 "abcde \n" + | |
588 "Content-Length: 12345\n", | |
589 "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,;aaa3,;aaa4,;aaa5,;]|" | |
590 "content-type|cache-control|etag|connection|expires", | |
591 false | |
592 }, | |
593 | |
594 // Checks the case that one header has multiple values, and such multiple | |
595 // lines occur at different positions. | |
596 { | |
597 "HTTP/1.1 200 OK \n" + | |
598 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
599 "abcde \n" + | |
600 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
601 "Content-Type: aaa1, ccc1\n" | |
602 "Cache-Control: aaa2\n" | |
603 "ETag: aaa3\n" | |
604 "Content-Type: xxx1, bbb1, ccc1\n" | |
605 "Connection: aaa4\n" | |
606 "Expires: aaa5\n" | |
607 "Via: \n" | |
608 "Content-Length: 12345\n", | |
609 "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,;aaa3,;aaa4,;aaa5,;]" | |
610 "|content-type|cache-control|etag|connection|expires", | |
611 false | |
612 }, | |
613 | |
614 // Checks the case that more than one headers have multiple values. | |
615 { | |
616 "HTTP/1.1 200 OK \n" | |
617 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
618 "Content-Type: aaa1, ccc1\n" | |
619 "Cache-Control: ccc2 , bbb2\n" | |
620 "ETag: aaa3\n" | |
621 "Content-Type: xxx1, bbb1, ccc1\n" | |
622 "Connection: aaa4\n" | |
623 "Cache-Control: aaa2 \n" | |
624 "Expires: aaa5\n" + | |
625 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
626 "abcde \n" + | |
627 "Via: \n" | |
628 "Content-Length: 12345\n", | |
629 "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,bbb2,ccc2,;aaa3,;aaa4,;aaa5,;]|" | |
630 "content-type|cache-control|etag|connection|expires", | |
631 false | |
632 }, | |
633 | |
634 // Checks the case that one of the requested headers is missing (Expires). | |
635 { | |
636 "HTTP/1.1 200 OK \n" | |
637 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
638 "Content-Type: aaa1, ccc1\n" | |
639 "Cache-Control: ccc2 , bbb2\n" | |
640 "ETag: aaa3\n" | |
641 "Content-Type: xxx1, bbb1, ccc1\n" | |
642 "Connection: aaa4\n" | |
643 "Cache-Control: aaa2 \n" | |
644 "Via: \n" | |
645 "Content-Length: 12345\n" + | |
646 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
647 "abcde \n", | |
648 "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,bbb2,ccc2,;aaa3,;aaa4,;;]|" | |
649 "content-type|cache-control|etag|connection|expires", | |
650 false | |
651 }, | |
652 | |
653 // Checks the case that more than one of the requested headers are missing. | |
654 // (Content-Type, Expires). | |
655 { | |
656 "HTTP/1.1 200 OK \n" + | |
657 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
658 "abcde \n" + | |
659 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
660 "Cache-Control: ccc2 , bbb2\n" | |
661 "ETag: aaa3\n" | |
662 "Connection: aaa4\n" | |
663 "Cache-Control: aaa2 \n" | |
664 "Via: \n" | |
665 "Content-Length: 12345\n", | |
666 "[;aaa2,bbb2,ccc2,;aaa3,;aaa4,;;]|content-type|cache-control|" | |
667 "etag|connection|expires", | |
668 false | |
669 }, | |
670 | |
671 // Checks the case that all the requested headers are missing. | |
672 { | |
673 "HTTP/1.1 200 OK \n" | |
674 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
675 "Via: \n" | |
676 "Content-Length: 12345\n" + | |
677 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
678 "abcde \n", | |
679 "[;;;;;]|content-type|cache-control|etag|connection|expires", | |
680 false | |
681 }, | |
682 | |
683 // Checks the case that only one header is requested. | |
684 { | |
685 "HTTP/1.1 200 OK \n" | |
686 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
687 "Via: \n" | |
688 "Content-Length: 12345\n" + | |
689 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
690 "abcde \n", | |
691 "[12345,;]|content-length", | |
692 false | |
693 }, | |
694 | |
695 // Checks the case that fingerprint is different to received one. | |
696 { | |
697 "HTTP/1.1 200 OK \n" | |
698 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
699 "Content-Type: aaa1, ccc1\n" | |
700 "Cache-Control: ccc2 , bbb2\n" | |
701 "ETag: etag\n" | |
702 "Content-Type: xxx1, bbb1, ccc1\n" | |
703 "Connection: aaa4\n" | |
704 "Cache-Control: aaa2 \n" | |
705 "Via: \n" | |
706 "Content-Length: 12345\n", | |
707 "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,bbb2,ccc2,;aaa3,;aaa4,;;]|" | |
708 "content-type|cache-control|etag|connection|expires", | |
709 true | |
710 }, | |
711 | |
712 // Checks the case that some of the requested headers have empty value | |
713 // (different to above header-missing case). | |
714 { | |
715 "HTTP/1.1 200 OK \n" | |
716 "Content-Type: \n" | |
717 "Cache-Control: \n" | |
718 "ETag: \n" | |
719 "Connection: \n" | |
720 "Expires: 5\n" + | |
721 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
722 "abcde \n" + | |
723 "Via: \n" | |
724 "Content-Length: 12345\n", | |
725 "[,;,;,;,;5,;]|content-type|cache-control|etag|connection|expires", | |
726 false | |
727 }, | |
728 | |
729 // Checks the case that some headers are missing, some of them are of | |
730 // empty values (whether delimiter "," and ";" work correctly). | |
731 { | |
732 "HTTP/1.1 200 OK \n" | |
733 "Cache-Control: \n" | |
734 "Connection: \n" | |
735 "Expires: 5\n" | |
736 "Via: \n" | |
737 "Content-Length: 12345\n" + | |
738 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
739 "abcde \n", | |
740 "[;,;;,;5,;]|content-type|cache-control|etag|connection|expires", | |
741 false | |
742 }, | |
743 | |
744 // Checks the case there is no requested header (header list is empty). | |
745 { | |
746 "HTTP/1.1 200 OK \n" | |
747 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
748 "Content-Type: 1\n" | |
749 "Cache-Control: 2\n" | |
750 "ETag: 3\n" | |
751 "Connection: 4\n" + | |
752 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
753 "abcde \n" + | |
754 "Expires: 5\n" | |
755 "Via: \n" | |
756 "Content-Length: 12345\n", | |
757 "[]", | |
758 false | |
759 }, | |
760 | |
761 // Checks the case that there is only one requested header and it does not | |
762 // exist. | |
763 { | |
764 "HTTP/1.1 200 OK \n" | |
765 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" | |
766 "Content-Type: 1\n" | |
767 "Cache-Control: 2\n" | |
768 "ETag: 3\n" | |
769 "Connection: 4\n" | |
770 "Expires: 5\n" | |
771 "Via: \n" + | |
772 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
773 "abcde \n" + | |
774 "Content-Length: 12345\n", | |
775 "[;]|non_exist_header", | |
776 false | |
777 }, | |
778 | |
779 // Checks the case that there is only one requested header. | |
780 { | |
781 "HTTP/1.1 200 OK \n" | |
782 "Cache-Control: \n" | |
783 "Connection: \n" | |
784 "Expires: 5\n" | |
785 "Via: \n" | |
786 "Content-Length: 12345\n" + | |
787 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
788 "abcde \n", | |
789 "[;]|content-type", | |
790 false | |
791 }, | |
792 | |
793 /* Lead to NOTREACHED() */ | |
794 /* | |
795 // special case, if base64 decoding fails | |
796 { | |
797 "HTTP/1.1 200 OK \n" | |
798 "Cache-Control: \n" | |
799 "Connection: \n" | |
800 "Expires: 5\n" | |
801 "Via: \n" | |
802 "Content-Length: 12345\n", | |
803 ";|content-type", | |
804 true | |
805 }, | |
806 | |
807 // special case, if base64 decoding fails | |
808 { | |
809 "HTTP/1.1 200 OK \n" | |
810 "Cache-Control: \n" | |
811 "Connection: \n" | |
812 "Expires: 5\n" | |
813 "Via: \n" | |
814 "Content-Length: 12345\n", | |
815 "abcde|content-type|cache-control|etag|connection|expires", | |
816 true | |
817 }, | |
818 */ | |
819 }; | |
820 | |
821 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) { | |
822 ReplaceWithEncodedString(&(test[i].received_fingerprint)); | |
823 DataReductionProxyTamperDetectionTest::TestFingerprintCommon(test[i], | |
824 DataReductionProxyTamperDetection::OTHERHEADERS); | |
825 } | |
826 } | |
827 | |
828 // Checks function IsContentLengthTampered. | |
829 TEST_F(DataReductionProxyTamperDetectionTest, ContentLength) { | |
830 TestCaseCheckingFingerprint test[] = { | |
831 // Checks the case fingerprint matches received response. | |
832 { | |
833 "HTTP/1.1 200 OK \n" | |
834 "Content-Type: 1\n" | |
835 "Content-Length: 12345\n", | |
836 "12345", | |
837 false, | |
838 }, | |
839 | |
840 // Checks the case that fingerprint does not match received response. | |
841 { | |
842 "HTTP/1.1 200 OK \n" | |
843 "Content-Type: text/html; charset=ISO-8859-4\n" | |
844 "Content-Length: 12345\n", | |
845 "125", | |
846 true, | |
847 }, | |
848 | |
849 // Checks the case that the data reduction proxy has not sent | |
850 // Content-Length header. | |
851 { | |
852 "HTTP/1.1 200 OK \n" | |
853 "Content-Type: text/javascript\n" | |
854 "Content-Length: 12345\n", | |
855 "", | |
856 false, | |
857 }, | |
858 | |
859 // Checks the case that the data reduction proxy sends invalid | |
860 // Content-Length header. | |
861 { | |
862 "HTTP/1.1 200 OK \n" | |
863 "Content-Type: text/javascript\n" | |
864 "Content-Length: 12345\n", | |
865 "aaa", | |
866 false, | |
867 }, | |
868 | |
869 // Checks the case that the data reduction proxy sends invalid | |
870 // Content-Length header. | |
871 { | |
872 "HTTP/1.1 200 OK \n" | |
873 "Content-Type: text/javascript\n" | |
874 "Content-Length: aaa\n", | |
875 "aaa", | |
876 false, | |
877 }, | |
878 | |
879 // Checks the case that Content-Length header are missing at both end. | |
880 { | |
881 "HTTP/1.1 200 OK \n" | |
882 "Content-Type: 1\n", | |
883 "", | |
884 false, | |
885 }, | |
886 | |
887 // Checks the case that Content-Length is 0. | |
888 { | |
889 "HTTP/1.1 200 OK \n" | |
890 "Content-Type: application/x-javascript\n" | |
891 "Content-Length: 0\n", | |
892 "0", | |
893 false, | |
894 }, | |
895 | |
896 // Checks the case that Content-Length is empty at the data reduction proxy | |
897 // side. | |
898 { | |
899 "HTTP/1.1 200 OK \n" | |
900 "Content-Type: application/x-javascript\n" | |
901 "Content-Length: 123\n", | |
902 ",", | |
903 false, | |
904 }, | |
905 | |
906 // Checks the case that Content-Length header is missing at the Chromium | |
907 // client side. | |
908 { | |
909 "HTTP/1.1 200 OK \n" | |
910 "Content-Type: application/javascript \n", | |
911 "123", | |
912 false, | |
913 }, | |
914 }; | |
915 | |
916 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) { | |
917 DataReductionProxyTamperDetectionTest::TestFingerprintCommon(test[i], | |
918 DataReductionProxyTamperDetection::CONTENTLENGTH); | |
919 } | |
920 } | |
921 | |
922 // Testcase for RemoveChromeProxyFingerprint function. | |
923 TEST_F(DataReductionProxyTamperDetectionTest, HeaderRemoving) { | |
924 struct { | |
925 std::string input_values[10]; | |
926 std::string expected_output_values[10]; | |
927 } test[] = { | |
928 // Checks the case that there is no Chrome-Proxy header's fingerprint. | |
929 { | |
930 {"1", "2", "3", "5",}, | |
931 {"1", "2", "3", "5",}, | |
932 }, | |
933 // Checks the case that there is Chrome-Proxy header's fingerprint. | |
934 { | |
935 {"1", "2", "3", | |
936 std::string(kChromeProxyActionFingerprintChromeProxy) + "=4", "5",}, | |
937 {"1", "2", "3", "5",}, | |
938 }, | |
939 // Checks the case that there is Chrome-Proxy header's fingerprint, and it | |
940 // occurs at the end. | |
941 { | |
942 {"1", "2", "3", | |
943 std::string(kChromeProxyActionFingerprintChromeProxy) + "=4",}, | |
944 {"1", "2", "3",}, | |
945 }, | |
946 // Checks the case that there is Chrome-Proxy header's fingerprint, and it | |
947 // occurs at the beginning. | |
948 { | |
949 {std::string(kChromeProxyActionFingerprintChromeProxy) | |
950 + "=1", "2", "3",}, | |
951 {"2", "3",}, | |
952 }, | |
953 }; | |
954 | |
955 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) { | |
956 std::vector<std::string> input_values, output_values; | |
957 for (size_t j=0; j<ARRAYSIZE_UNSAFE(test[i].input_values); ++j) { | |
958 if (test[i].input_values[j].size()) | |
959 input_values.push_back(test[i].input_values[j]); | |
960 } | |
961 for (size_t j=0; j<ARRAYSIZE_UNSAFE(test[i].expected_output_values); ++j) { | |
962 if (test[i].expected_output_values[j].size()) | |
963 output_values.push_back(test[i].expected_output_values[j]); | |
964 } | |
965 | |
966 DataReductionProxyTamperDetection::RemoveChromeProxyFingerprint( | |
967 &input_values); | |
968 | |
969 EXPECT_EQ(input_values, output_values); | |
970 } | |
971 } | |
972 | |
973 // Testcase for ValuesToSortedString function. | |
974 TEST_F(DataReductionProxyTamperDetectionTest, ValuesToSortedString) { | |
975 struct { | |
976 std::string input_values[10]; | |
977 std::string expected_output_string; | |
978 } test[] = { | |
979 // Checks the correctness of sorting. | |
980 { | |
981 {"1", "2", "3",}, | |
982 "1,2,3,", | |
983 }, | |
984 // Checks the case that there is an empty input vector. | |
985 { | |
986 {}, | |
987 "", | |
988 }, | |
989 // Checks the case that there is an empty string in the input vector. | |
990 { | |
991 {" ",}, | |
992 ",", | |
993 }, | |
994 }; | |
995 | |
996 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) { | |
997 std::vector<std::string> input_values; | |
998 for (size_t j=0; j<ARRAYSIZE_UNSAFE(test[i].input_values); ++j) { | |
999 if (test[i].input_values[j].size()) { | |
1000 if (test[i].input_values[j] == " ") | |
1001 input_values.push_back(""); | |
1002 else | |
1003 input_values.push_back(test[i].input_values[j]); | |
1004 } | |
1005 } | |
1006 | |
1007 std::string output_string = DataReductionProxyTamperDetection:: | |
1008 ValuesToSortedString(&input_values); | |
1009 | |
1010 EXPECT_EQ(output_string, test[i].expected_output_string); | |
1011 } | |
1012 } | |
1013 | |
1014 // Testcase for GetHeaderValues function. | |
1015 TEST_F(DataReductionProxyTamperDetectionTest, GetHeaderValues) { | |
1016 struct { | |
1017 std::string raw_header; | |
1018 std::string header_name; | |
1019 std::string expected_output_values[10]; | |
1020 } test[] = { | |
1021 // Checks the correctness of getting single line header. | |
1022 { | |
1023 "HTTP/1.1 200 OK \n" | |
1024 "test: 1, 2, 3\n", | |
1025 "test", | |
1026 {"1", "2", "3"}, | |
1027 }, | |
1028 // Checks the correctness of getting multiple lines header. | |
1029 { | |
1030 "HTTP/1.1 200 OK \n" | |
1031 "test: 1, 2, 3\n" | |
1032 "test: 4, 5, 6\n" | |
1033 "test: 7, 8, 9\n", | |
1034 "test", | |
1035 {"1", "2", "3", "4", "5", "6", "7", "8", "9"}, | |
1036 }, | |
1037 // Checks the correctness of getting missing header. | |
1038 { | |
1039 "HTTP/1.1 200 OK \n", | |
1040 "test", | |
1041 {}, | |
1042 }, | |
1043 // Checks the correctness of getting empty header. | |
1044 { | |
1045 "HTTP/1.1 200 OK \n" | |
1046 "test: \n", | |
1047 "test", | |
1048 {" "}, | |
1049 }, | |
1050 }; | |
1051 | |
1052 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) { | |
1053 std::string raw_headers(test[i].raw_header); | |
1054 HeadersToRaw(&raw_headers); | |
1055 scoped_refptr<net::HttpResponseHeaders> headers = | |
1056 new net::HttpResponseHeaders(raw_headers); | |
1057 | |
1058 std::vector<std::string> expected_output_values; | |
1059 for (size_t j=0; j<ARRAYSIZE_UNSAFE(test[i].expected_output_values); ++j) { | |
1060 if ((test[i].expected_output_values[j]).size()) { | |
1061 if (test[i].expected_output_values[j] == " ") | |
1062 expected_output_values.push_back(""); | |
1063 else | |
1064 expected_output_values.push_back(test[i].expected_output_values[j]); | |
1065 } | |
1066 } | |
1067 | |
1068 std::vector<std::string> output_values = | |
1069 DataReductionProxyTamperDetection::GetHeaderValues( | |
1070 headers, test[i].header_name); | |
1071 EXPECT_EQ(expected_output_values, output_values); | |
1072 } | |
1073 } | |
1074 | |
1075 // Testcase for main function CheckResponseFingerprint. First generate | |
1076 // simulated response from the data reduction proxy, by replacing fingerprint | |
1077 // with its base64 encoded MD5 value and appending it to Chrome-Proxy header. | |
1078 // Then runs through function CheckResponseFingerprint. | |
1079 TEST_F(DataReductionProxyTamperDetectionTest, Completed) { | |
1080 struct { | |
1081 std::string raw_header; | |
1082 std::string chrome_header; | |
1083 bool expected_contain_tamper_detect_fingerprints; | |
1084 bool expected_tampered_chrome_proxy; | |
1085 bool expected_tampered_via; | |
1086 bool expected_tampered_other_headers; | |
1087 bool expected_tampered_content_length; | |
1088 bool expected_has_chrome_proxy_via_header; | |
1089 } test[] = { | |
1090 // Check normal case, Chrome-Proxy fingerprint doesn't exist | |
1091 { | |
1092 "HTTP/1.1 200 OK \n" | |
1093 "Via: a1, b2, 1.1 Chrome-Compression-Proxy\n" | |
1094 "Content-Length: 12345\n" | |
1095 "header1: header_1\n" | |
1096 "header2: header_2\n" | |
1097 "header3: header_3\n", | |
1098 "a,b,c,d,e," + | |
1099 std::string(kChromeProxyActionFingerprintContentLength) + "=12345," + | |
1100 std::string(kChromeProxyActionFingerprintOtherHeaders) + | |
1101 "=[header_1,;header_2,;header_3,;]|header1|header2|header3," + | |
1102 std::string(kChromeProxyActionFingerprintVia) + "=0,", | |
1103 true, | |
1104 false, | |
1105 false, | |
1106 false, | |
1107 false, | |
1108 true, | |
1109 }, | |
1110 }; | |
1111 | |
1112 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) { | |
1113 // Replace fingerprint with base64 encoded MD5 value. | |
1114 ReplaceWithEncodedString(&(test[i].chrome_header)); | |
1115 // Generate fingerprint for Chrome-Proxy header. | |
1116 std::string chrome_header_fingerprint = GetEncoded(test[i].chrome_header); | |
1117 // Append Chrome-Proxy header to response headers. | |
1118 test[i].raw_header += "Chrome-Proxy: " + test[i].chrome_header + | |
1119 std::string(kChromeProxyActionFingerprintChromeProxy) + | |
1120 "=" + chrome_header_fingerprint + "\n"; | |
1121 | |
1122 std::string raw_headers(test[i].raw_header); | |
1123 HeadersToRaw(&raw_headers); | |
1124 scoped_refptr<net::HttpResponseHeaders> headers = | |
1125 new net::HttpResponseHeaders(raw_headers); | |
1126 | |
1127 // Below copying codes from CheckResponseFingerprint, with checking points | |
1128 // added. | |
1129 std::string chrome_proxy_fingerprint; | |
1130 bool contain_chrome_proxy_fingerprint = GetDataReductionProxyActionValue( | |
1131 headers, | |
1132 kChromeProxyActionFingerprintChromeProxy, | |
1133 &chrome_proxy_fingerprint); | |
1134 | |
1135 | |
1136 EXPECT_EQ(test[i].expected_contain_tamper_detect_fingerprints, | |
1137 contain_chrome_proxy_fingerprint); | |
1138 if (!contain_chrome_proxy_fingerprint) | |
1139 return; | |
1140 std::vector<std::string> chrome_proxy_header_values = | |
1141 DataReductionProxyTamperDetection:: | |
1142 GetHeaderValues(headers, "Chrome-Proxy"); | |
1143 | |
1144 DataReductionProxyTamperDetection:: | |
1145 RemoveChromeProxyFingerprint(&chrome_proxy_header_values); | |
1146 | |
1147 DataReductionProxyTamperDetection tamper_detection( | |
1148 headers, | |
1149 true, | |
1150 0, | |
1151 &chrome_proxy_header_values); | |
1152 | |
1153 bool tampered_chrome_proxy = | |
1154 tamper_detection.IsChromeProxyHeaderTampered(chrome_proxy_fingerprint); | |
1155 EXPECT_EQ(test[i].expected_tampered_chrome_proxy, tampered_chrome_proxy); | |
1156 if (tampered_chrome_proxy) | |
1157 return; | |
1158 | |
1159 std::map<std::string, DataReductionProxyTamperDetection::FingerprintCode>:: | |
1160 iterator it; | |
1161 for (it = tamper_detection.fingerprint_name_code_map_.begin(); | |
1162 it != tamper_detection.fingerprint_name_code_map_.end(); ++it) { | |
1163 std::string fingerprint; | |
1164 if (!GetDataReductionProxyActionValue( | |
1165 headers, it->first, &fingerprint)) { | |
1166 continue; | |
1167 } | |
1168 | |
1169 bool tampered = false; | |
1170 switch (it->second) { | |
1171 case DataReductionProxyTamperDetection::VIA: | |
1172 bool has_chrome_proxy_via_header; | |
1173 tampered = tamper_detection.IsViaHeaderTampered( | |
1174 fingerprint, &has_chrome_proxy_via_header); | |
1175 EXPECT_EQ(test[i].expected_tampered_via, tampered); | |
1176 EXPECT_EQ(test[i].expected_has_chrome_proxy_via_header, | |
1177 has_chrome_proxy_via_header); | |
1178 break; | |
1179 case DataReductionProxyTamperDetection::OTHERHEADERS: | |
1180 tampered = tamper_detection.AreOtherHeadersTampered(fingerprint); | |
1181 EXPECT_EQ(test[i].expected_tampered_other_headers, tampered); | |
1182 break; | |
1183 case DataReductionProxyTamperDetection::CONTENTLENGTH: | |
1184 tampered = tamper_detection.IsContentLengthHeaderTampered(fingerprint); | |
1185 EXPECT_EQ(test[i].expected_tampered_content_length, tampered); | |
1186 break; | |
1187 default: | |
1188 NOTREACHED(); | |
1189 break; | |
1190 } | |
1191 } | |
1192 } | |
1193 } | |
1194 | |
1195 } // namespace | |
OLD | NEW |