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

Side by Side Diff: components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detect_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698