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

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: 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 "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 std::string GetEncoded(const std::string& input) {
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 size_t start, end;
43 while (true) {
44 start = input->find("[");
45 if (start == std::string::npos) break;
46 end = input->find("]", start);
47 std::string need_to_encode = input->substr(start + 1, end - start - 1);
48 *input = input->substr(0, start) + GetEncoded(need_to_encode) +
49 input->substr(end + 1);
50 }
51 }
52
53 const int kMaxVectorSize = 10;
54 // Put a list of strings into a vector.
55 std::vector<std::string> StringsToVector(std::string* input) {
56 std::vector<std::string> vector;
57 for (size_t i=0; i<kMaxVectorSize; ++i) {
58 if (input[i].size()) {
59 if (input[i] == " ")
60 vector.push_back("");
61 else
62 vector.push_back(input[i]);
63 }
64 }
65 return vector;
66 }
67
68 // Testcase for fingerprint checking functions. |received_fingerprint| is
69 // fingerprint received from the data reduction proxy. |expected_tampered| is
70 // expected tampered or not result.
71 struct TamperDetectionTestCase {
72 std::string label;
73 std::string raw_header;
74 std::string received_fingerprint;
75 bool expected_tampered;
76 bool expected_has_chrome_proxy_via_header;
77 };
78
79 } // namespace
80
81 namespace data_reduction_proxy {
82
83 class DataReductionProxyTamperDetectionTest : public testing::Test {
84 public:
85 static void TestFingerprintCommon(const TamperDetectionTestCase& test,
86 DataReductionProxyTamperDetection::FingerprintCode fingerprint);
87 };
88
89 // Common function for testing fingerprint checking functions. For a given
90 // header string |test.raw_header|, generates HttpResponseHeaders |headers| and
91 // checks specified fingerprint checking function returns expected result or
92 // not.
93 void DataReductionProxyTamperDetectionTest::TestFingerprintCommon(
94 const TamperDetectionTestCase& test,
95 DataReductionProxyTamperDetection::FingerprintCode fingerprint_code) {
96 std::string raw_headers(test.raw_header);
97 HeadersToRaw(&raw_headers);
98 net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(raw_headers);
99
100 // Removes Chrome-Proxy header's fingerprint from Chrome-Proxy header.
101 std::vector<std::string> chrome_proxy_header_values =
102 DataReductionProxyTamperDetection::
103 GetHeaderValues(headers, "Chrome-Proxy");
104
105 DataReductionProxyTamperDetection::RemoveChromeProxyFingerprint(
106 &chrome_proxy_header_values);
107
108 DataReductionProxyTamperDetection tamper_detection(
109 headers, true, 0, &chrome_proxy_header_values);
110
111 bool tampered, has_chrome_proxy_via_header = false;
112 switch (fingerprint_code) {
113 case DataReductionProxyTamperDetection::CHROMEPROXY:
114 tampered = tamper_detection.IsChromeProxyHeaderTampered(
115 test.received_fingerprint);
116 break;
117 case DataReductionProxyTamperDetection::VIA:
118 tampered = tamper_detection.IsViaHeaderTampered(
119 test.received_fingerprint, &has_chrome_proxy_via_header);
120 EXPECT_EQ(test.expected_has_chrome_proxy_via_header,
121 has_chrome_proxy_via_header)<<test.label;
bolian 2014/07/23 23:22:57 space before and after "<<". everywhere.
xingx 2014/07/24 01:18:50 Done.
122 break;
123 case DataReductionProxyTamperDetection::OTHERHEADERS:
124 tampered = tamper_detection.AreOtherHeadersTampered(
125 test.received_fingerprint);
126 break;
127 case DataReductionProxyTamperDetection::CONTENTLENGTH:
128 tampered = tamper_detection.IsContentLengthHeaderTampered(
129 test.received_fingerprint);
130 break;
131 case DataReductionProxyTamperDetection::NONEXIST:
132 default:
133 NOTREACHED();
134 break;
135 }
136
137 EXPECT_EQ(test.expected_tampered, tampered)<<test.label;
138 }
139
140 // Checks function IsChromeProxyHeaderTampered.
bolian 2014/07/24 07:11:58 s/Checks/Tests. And in below cases as well.
141 TEST_F(DataReductionProxyTamperDetectionTest, ChromeProxy) {
142 // |received_fingerprint| is not the actual fingerprint from data reduction
143 // proxy, instead, the base64 encoded field is in plain text (within "[]")
bolian 2014/07/23 23:22:57 I think I now understand you tests, but probably b
xingx 2014/07/24 01:18:50 Done. But a little bit tricky, Chrome-Proxy finger
144 // and needs to be encoded first.
145 TamperDetectionTestCase test[] = {
146 {
147 "Checks sorting.",
148 "HTTP/1.1 200 OK\n"
bolian 2014/07/23 23:22:57 Do you need the 200 OK line? You are not enforcing
xingx 2014/07/24 01:18:50 I need that to parse it as a HTTP header, otherwis
149 "Chrome-Proxy: c,b,a,3,2,1,fcp=f\n",
150 "[1,2,3,a,b,c,]",
151 false,
152 },
153 {
154 "Checks Chrome-Proxy's fingerprint removing.",
155 "HTTP/1.1 200 OK\n"
156 "Chrome-Proxy: a,b,c,d,e,3,2,1,fcp=f\n",
157 "[1,2,3,a,b,c,d,e,]",
158 false,
159 },
160 {
161 "Checks no Chrome-Proxy header case (should not happen).",
162 "HTTP/1.1 200 OK\n",
163 "[]",
164 false,
165 },
166 {
167 "Checks empty Chrome-Proxy header case (should not happen).",
168 "HTTP/1.1 200 OK\n"
169 "Chrome-Proxy: \n",
170 "[,]",
171 false,
172 },
173 {
174 "Checks Chrome-Proxy header with its fingerprint only case.",
175 "HTTP/1.1 200 OK\n"
176 "Chrome-Proxy: fcp=f\n",
177 "[]",
178 false,
179 },
180 {
181 "Checks empty Chrome-Proxy header case, with extra ',' and ' '",
182 "HTTP/1.1 200 OK\n"
183 "Chrome-Proxy: fcp=f , \n",
184 "[]",
185 false,
186 },
187 {
188 "Changed no value to empty value.",
189 "HTTP/1.1 200 OK\n"
190 "Chrome-Proxy: fcp=f\n",
191 "[,]",
192 true,
193 },
194 {
195 "Changed header values.",
196 "HTTP/1.1 200 OK\n"
197 "Chrome-Proxy: a,b=2,c,d=1,fcp=f\n",
198 "[a,b=3,c,d=1,]",
199 true,
200 },
201 {
202 "Changed order of header values.",
203 "HTTP/1.1 200 OK\n"
204 "Chrome-Proxy: c,b,a,fcp=1\n",
205 "[c,b,a,]",
206 true,
207 },
208 {
209 "Checks Chrome-Proxy header with extra ' '.",
210 "HTTP/1.1 200 OK\n"
211 "Chrome-Proxy: a , b , c, d, fcp=f\n",
212 "[a,b,c,d,]",
213 false
214 },
215 {
216 "Check Chrome-Proxy header with multiple lines and ' '.",
217 "HTTP/1.1 200 OK\n"
218 "Chrome-Proxy: a , c , d, fcp=f \n"
219 "Chrome-Proxy: b \n",
220 "[a,b,c,d,]",
221 false
222 },
223 {
224 "Checks Chrome-Proxy header with multiple lines, at different positions",
225 "HTTP/1.1 200 OK\n"
226 "Chrome-Proxy: a \n"
227 "Chrome-Proxy: c \n"
228 "Content-Type: 1\n"
229 "Cache-Control: 2\n"
230 "ETag: 3\n"
231 "Chrome-Proxy: b \n"
232 "Connection: 4\n"
233 "Expires: 5\n"
234 "Chrome-Proxy: fcp=f \n"
235 "Via: \n"
236 "Content-Length: 12345\n",
237 "[a,b,c,]",
238 false
239 },
240 {
241 "Checks Chrome-Proxy header with multiple same values.",
242 "HTTP/1.1 200 OK\n"
243 "Chrome-Proxy: a \n"
244 "Chrome-Proxy: b\n"
245 "Chrome-Proxy: c\n"
246 "Chrome-Proxy: d, fcp=f \n"
247 "Chrome-Proxy: a \n",
248 "[a,a,b,c,d,]",
249 false
250 },
251 {
252 "Changed Chrome-Proxy header with multiple lines..",
253 "HTTP/1.1 200 OK\n"
254 "Chrome-Proxy: a\n"
255 "Chrome-Proxy: a\n"
256 "Chrome-Proxy: b\n"
257 "Chrome-Proxy: c,fcp=f\n",
258 "[a,b,c,]",
259 true,
260 },
261 {
262 "Checks case whose received fingerprint is empty.",
263 "HTTP/1.1 200 OK\n"
264 "Chrome-Proxy: a,b,c,fcp=1\n",
265 "[]",
266 true,
267 },
268 {
269 "Checks case whose received fingerprint cannot be base64 decoded.",
270 "HTTP/1.1 200 OK\n"
271 "Chrome-Proxy: a,b,c,fcp=1\n",
272 "not_base64_encoded",
273 true,
274 },
275 };
276
277 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
278 ReplaceWithEncodedString(&test[i].received_fingerprint);
279
280 DataReductionProxyTamperDetectionTest::TestFingerprintCommon(test[i],
281 DataReductionProxyTamperDetection::CHROMEPROXY);
282 }
283 }
284
285 // Check function IsViaHeaderTampered.
286 TEST_F(DataReductionProxyTamperDetectionTest, Via) {
287 TamperDetectionTestCase test[] = {
288 {
289 "Checks the case that Chrome-Compression-Proxy occurs at the last.",
290 "HTTP/1.1 200 OK\n"
291 "Via: a, b, c, 1.1 Chrome-Compression-Proxy\n",
292 "",
293 false,
294 true,
295 },
296 {
297 "Checks when there is intermediary.",
298 "HTTP/1.1 200 OK\n"
299 "Via: a, b, c, 1.1 Chrome-Compression-Proxy, xyz\n",
300 "",
301 true,
302 true,
303 },
304 {
305 "Checks the case of empty Via header.",
306 "HTTP/1.1 200 OK\n"
307 "Via: \n",
308 "",
309 false,
310 false,
311 },
312 {
313 "Checks the case that only the data reduction proxy's Via header occurs.",
314 "HTTP/1.1 200 OK\n"
315 "Via: 1.1 Chrome-Compression-Proxy \n",
316 "",
317 false,
318 true,
319 },
320 {
321 "Checks the case that there are ' ', i.e., empty value after the data"
322 " reduction proxy's Via header.",
323 "HTTP/1.1 200 OK\n"
324 "Via: 1.1 Chrome-Compression-Proxy , , \n",
325 "",
326 false,
327 true,
328 },
329 {
330 "Checks the case when there is no Via header",
331 "HTTP/1.1 200 OK\n",
332 "",
333 false,
334 false,
335 },
336 // Same to above test cases, but with deprecated data reduciton proxy Via
337 // header.
338 {
339 "Checks the case that Chrome Compression Proxy occurs at the last.",
340 "HTTP/1.1 200 OK\n"
341 "Via: a, b, c, 1.1 Chrome Compression Proxy\n",
342 "",
343 false,
344 true,
345 },
346 {
347 "Checks when there is intermediary.",
348 "HTTP/1.1 200 OK\n"
349 "Via: a, b, c, 1.1 Chrome Compression Proxy, xyz\n",
350 "",
351 true,
352 true,
353 },
354 {
355 "Checks the case of empty Via header.",
356 "HTTP/1.1 200 OK\n"
357 "Via: \n",
358 "",
359 false,
360 false,
361 },
362 {
363 "Checks the case that only the data reduction proxy's Via header occurs.",
364 "HTTP/1.1 200 OK\n"
365 "Via: 1.1 Chrome Compression Proxy \n",
366 "",
367 false,
368 true,
369 },
370 {
371 "Checks the case that there are ' ', i.e., empty value after the data"
372 "reduction proxy's Via header.",
373 "HTTP/1.1 200 OK\n"
374 "Via: 1.1 Chrome Compression Proxy , , \n",
375 "",
376 false,
377 true,
378 },
379 {
380 "Checks the case when there is no Via header",
381 "HTTP/1.1 200 OK\n",
382 "",
383 false,
384 false,
385 },
386 };
387
388 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
389 DataReductionProxyTamperDetectionTest::TestFingerprintCommon(test[i],
390 DataReductionProxyTamperDetection::VIA);
391 }
392 }
393
394 // Checks function AreOtherHeadersTampered.
395 TEST_F(DataReductionProxyTamperDetectionTest, OtherHeaders) {
396 // For following testcases, |received_fingerprint| is not the actual
397 // fingerprint from data reduction proxy, instead, the base64 encoded field
398 // is in plain text (within "[]") and needs to be encoded first. For example,
399 // "[12345;]|content-length" needs to be encoded to
400 // "Base64Encoded(MD5(12345;))|content-length" before calling the checking
401 // function.
402 TamperDetectionTestCase test[] = {
403 {
404 "Checks the case that only one header is requested.",
405 "HTTP/1.1 200 OK\n"
406 "Content-Length: 12345\n",
407 "[12345,;]|content-length",
408 false
409 },
410 {
411 "Checks the case that there is only one requested header and it does not"
412 "exist.",
413 "HTTP/1.1 200 OK\n",
414 "[;]|non_exist_header",
415 false
416 },
417 {
418 "Checks the case of multiple headers are requested.",
419 "HTTP/1.1 200 OK\n"
420 "Content-Type: 1\n"
421 "Cache-Control: 2\n"
422 "ETag: 3\n"
423 "Connection: 4\n"
424 "Expires: 5\n",
425 "[1,;2,;3,;4,;5,;]|content-type|cache-control|etag|connection|expires",
426 false
427 },
428 {
429 "Checks the case that one header has multiple values.",
430 "HTTP/1.1 200 OK\n"
431 "Content-Type: aaa1, bbb1, ccc1\n"
432 "Cache-Control: aaa2\n",
433 "[aaa1,bbb1,ccc1,;aaa2,;]|content-type|cache-control",
434 false
435 },
436 {
437 "Checks the case that one header has multiple lines.",
438 "HTTP/1.1 200 OK\n"
439 "Content-Type: aaa1, ccc1\n"
440 "Content-Type: xxx1, bbb1, ccc1\n"
441 "Cache-Control: aaa2\n",
442 "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,;]|content-type|cache-control",
443 false
444 },
445 {
446 "Checks the case that more than one headers have multiple values.",
447 "HTTP/1.1 200 OK\n"
448 "Content-Type: aaa1, ccc1\n"
449 "Cache-Control: ccc2 , bbb2\n"
450 "Content-Type: bbb1, ccc1\n"
451 "Cache-Control: aaa2 \n",
452 "[aaa1,bbb1,ccc1,ccc1,;aaa2,bbb2,ccc2,;]|content-type|cache-control",
453 false
454 },
455 {
456 "Checks the case that one of the requested headers is missing (Expires).",
457 "HTTP/1.1 200 OK\n"
458 "Content-Type: aaa1, ccc1\n",
459 "[aaa1,ccc1,;;]|content-type|expires",
460 false
461 },
462 {
463 "Checks the case that some of the requested headers have empty value.",
464 "HTTP/1.1 200 OK\n"
465 "Content-Type: \n"
466 "Cache-Control: \n",
467 "[,;,;]|content-type|cache-control",
468 false
469 },
470 {
471 "Checks the case that all the requested headers are missing.",
472 "HTTP/1.1 200 OK\n",
473 "[;;]|content-type|expires",
474 false
475 },
476 {
477 "Checks the case that some headers are missing, some of them are empty.",
478 "HTTP/1.1 200 OK\n"
479 "Cache-Control: \n",
480 "[;,;]|content-type|cache-control",
481 false
482 },
483 {
484 "Checks the case there is no requested header (header list is empty).",
485 "HTTP/1.1 200 OK\n"
486 "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
487 "Content-Type: 1\n"
488 "Cache-Control: 2\n",
489 "[]",
490 false
491 },
492 {
493 "Checks tampered requested header values.",
494 "HTTP/1.1 200 OK\n"
495 "Content-Type: aaa1, ccc1\n"
496 "Cache-Control: ccc2 , bbb2\n",
497 "[aaa1,bbb1,;bbb2,ccc2,;]|content-type|cache-control",
498 true
499 },
500 /* will lead to NOTREACHED() */
501 /*
502 {
503 "Checks the case that base64 decoding fails.",
504 "HTTP/1.1 200 OK\n"
505 "Cache-Control: \n"
506 "Connection: \n"
507 "Expires: 5\n"
508 "Via: \n"
509 "Content-Length: 12345\n",
510 "abcde|content-type|cache-control|etag|connection|expires",
511 true
512 },
513 */
514 };
515
516 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
517 ReplaceWithEncodedString(&(test[i].received_fingerprint));
518 DataReductionProxyTamperDetectionTest::TestFingerprintCommon(test[i],
519 DataReductionProxyTamperDetection::OTHERHEADERS);
520 }
521 }
522
523 // Checks function IsContentLengthTampered.
524 TEST_F(DataReductionProxyTamperDetectionTest, ContentLength) {
525 TamperDetectionTestCase test[] = {
526 {
527 "Checks the case fingerprint matches received response.",
528 "HTTP/1.1 200 OK\n"
529 "Content-Length: 12345\n",
530 "12345",
531 false,
532 },
533 {
534 "Checks case that response got modified.",
535 "HTTP/1.1 200 OK\n"
536 "Content-Length: 12345\n",
537 "125",
538 true,
539 },
540 {
541 "Checks the case that the data reduction proxy has not sent"
542 "Content-Length header.",
543 "HTTP/1.1 200 OK\n"
544 "Content-Length: 12345\n",
545 "",
546 false,
547 },
548 {
549 "Checks the case that the data reduction proxy sends invalid"
550 "Content-Length header.",
551 "HTTP/1.1 200 OK\n"
552 "Content-Length: 12345\n",
553 "aaa",
554 false,
555 },
556 {
557 "Checks the case that the data reduction proxy sends invalid"
558 "Content-Length header.",
559 "HTTP/1.1 200 OK\n"
560 "Content-Length: aaa\n",
561 "aaa",
562 false,
563 },
564 {
565 "Checks the case that Content-Length header is missing at the Chromium"
566 "client side.",
567 "HTTP/1.1 200 OK\n",
568 "123",
569 false,
570 },
571 {
572 "Checks the case that Content-Length header are missing at both end.",
573 "HTTP/1.1 200 OK\n",
574 "",
575 false,
576 },
577 };
578
579 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
580 DataReductionProxyTamperDetectionTest::TestFingerprintCommon(test[i],
581 DataReductionProxyTamperDetection::CONTENTLENGTH);
582 }
583 }
584
585 // Testcase for RemoveChromeProxyFingerprint function.
586 TEST_F(DataReductionProxyTamperDetectionTest, HeaderRemoving) {
587 struct {
588 std::string label;
589 std::string input_values[kMaxVectorSize];
590 std::string expected_output_values[kMaxVectorSize];
591 } test[] = {
592 {
593 "Checks the case that there is no Chrome-Proxy header's fingerprint.",
594 {"1", "2", "3", "5",},
595 {"1", "2", "3", "5",},
596 },
597 {
598 "Checks the case that there is Chrome-Proxy header's fingerprint.",
599 {"1", "2", "3", "fcp=4", "5",},
600 {"1", "2", "3", "5",},
601 },
602 {
603 "Checks the case that there is Chrome-Proxy header's fingerprint, and it"
604 "occurs at the end.",
605 {"1", "2", "3", "fcp=4",},
606 {"1", "2", "3",},
607 },
608 {
609 "Checks the case that there is Chrome-Proxy header's fingerprint, and it"
610 "occurs at the beginning.",
611 {"fcp=1", "2", "3",},
612 {"2", "3",},
613 },
614 };
615
616 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
617 std::vector<std::string> input_values =
618 StringsToVector(test[i].input_values);
619 std::vector<std::string> output_values =
620 StringsToVector(test[i].expected_output_values);
621
622 DataReductionProxyTamperDetection::RemoveChromeProxyFingerprint(
623 &input_values);
624
625 EXPECT_EQ(input_values, output_values)<<test[i].label;
626 }
627 }
628
629 // Testcase for ValuesToSortedString function.
630 TEST_F(DataReductionProxyTamperDetectionTest, ValuesToSortedString) {
631 struct {
632 std::string label;
633 std::string input_values[kMaxVectorSize];
634 std::string expected_output_string;
635 } test[] = {
636 {
637 "Checks the correctness of sorting.",
638 {"1", "2", "3",},
639 "1,2,3,",
640 },
641 {
642 "Checks the case that there is an empty input vector.",
643 {},
644 "",
645 },
646 {
647 "Checks the case that there is an empty string in the input vector.",
648 // Use " " to represent empty value.
649 {" ",},
650 ",",
651 },
652 };
653
654 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
655 std::vector<std::string> input_values =
656 StringsToVector(test[i].input_values);
657
658 std::string output_string = DataReductionProxyTamperDetection::
659 ValuesToSortedString(&input_values);
660
661 EXPECT_EQ(output_string, test[i].expected_output_string)<<test[i].label;
662 }
663 }
664
665 // Testcase for GetHeaderValues function.
666 TEST_F(DataReductionProxyTamperDetectionTest, GetHeaderValues) {
667 struct {
668 std::string label;
669 std::string raw_header;
670 std::string header_name;
671 std::string expected_output_values[kMaxVectorSize];
672 } test[] = {
673 {
674 "Checks the correctness of getting single line header.",
675 "HTTP/1.1 200 OK\n"
676 "test: 1, 2, 3\n",
677 "test",
678 {"1", "2", "3"},
679 },
680 {
681 "Checks the correctness of getting multiple lines header.",
682 "HTTP/1.1 200 OK\n"
683 "test: 1, 2, 3\n"
684 "test: 4, 5, 6\n"
685 "test: 7, 8, 9\n",
686 "test",
687 {"1", "2", "3", "4", "5", "6", "7", "8", "9"},
688 },
689 {
690 "Checks the correctness of getting missing header.",
691 "HTTP/1.1 200 OK\n",
692 "test",
693 {},
694 },
695 {
696 "Checks the correctness of getting empty header.",
697 "HTTP/1.1 200 OK\n"
698 "test: \n",
699 "test",
700 {" "},
701 },
702 };
703
704 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
705 std::string raw_headers(test[i].raw_header);
706 HeadersToRaw(&raw_headers);
707 net::HttpResponseHeaders* headers =
708 new net::HttpResponseHeaders(raw_headers);
709
710 std::vector<std::string> expected_output_values =
711 StringsToVector(test[i].expected_output_values);
712
713 std::vector<std::string> output_values =
714 DataReductionProxyTamperDetection::GetHeaderValues(
715 headers, test[i].header_name);
716 EXPECT_EQ(expected_output_values, output_values)<<test[i].label;
717 }
718 }
719
720 // Testcase for main function DetectAndReport. First generate
721 // simulated response from the data reduction proxy, by replacing fingerprint
722 // with its base64 encoded MD5 value and appending it to Chrome-Proxy header.
723 // Then runs through function CheckResponseFingerprint.
724 TEST_F(DataReductionProxyTamperDetectionTest, Completed) {
725 struct {
726 std::string label;
727 std::string raw_header;
728 std::string chrome_header;
729 bool expected_contain_tamper_detect_fingerprints;
730 bool expected_tampered_chrome_proxy;
731 bool expected_tampered_via;
732 bool expected_tampered_other_headers;
733 bool expected_tampered_content_length;
734 bool expected_has_chrome_proxy_via_header;
735 } test[] = {
736 {
737 "Check normal case, Chrome-Proxy fingerprint doesn't exist",
738 "HTTP/1.1 200 OK\n"
739 "Via: a1, b2, 1.1 Chrome-Compression-Proxy\n"
740 "Content-Length: 12345\n"
741 "header1: header_1\n"
742 "header2: header_2\n"
743 "header3: header_3\n",
744 "a,b,c,d,e," +
745 std::string(kChromeProxyActionFingerprintContentLength) + "=12345," +
746 std::string(kChromeProxyActionFingerprintOtherHeaders) +
747 "=[header_1,;header_2,;header_3,;]|header1|header2|header3," +
748 std::string(kChromeProxyActionFingerprintVia) + "=0,",
749 true,
750 false,
751 false,
752 false,
753 false,
754 true,
755 },
756 };
757
758 for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
759 // Replace fingerprint with base64 encoded MD5 value.
760 ReplaceWithEncodedString(&(test[i].chrome_header));
761 // Generate fingerprint for Chrome-Proxy header.
762 std::string chrome_header_fingerprint = GetEncoded(test[i].chrome_header);
763 // Append Chrome-Proxy header to response headers.
764 test[i].raw_header += "Chrome-Proxy: " + test[i].chrome_header +
765 std::string(kChromeProxyActionFingerprintChromeProxy) +
766 "=" + chrome_header_fingerprint + "\n";
767
768 std::string raw_headers(test[i].raw_header);
769 HeadersToRaw(&raw_headers);
770 scoped_refptr<net::HttpResponseHeaders> headers =
771 new net::HttpResponseHeaders(raw_headers);
772
773 // Below copying codes from DetectAndReport, with checking points
774 // added.
775 std::string chrome_proxy_fingerprint;
776 bool contain_chrome_proxy_fingerprint = GetDataReductionProxyActionValue(
777 headers,
778 kChromeProxyActionFingerprintChromeProxy,
779 &chrome_proxy_fingerprint);
780
781
782 EXPECT_EQ(test[i].expected_contain_tamper_detect_fingerprints,
783 contain_chrome_proxy_fingerprint)<<test[i].label;
784 if (!contain_chrome_proxy_fingerprint)
785 return;
786 std::vector<std::string> chrome_proxy_header_values =
787 DataReductionProxyTamperDetection::
788 GetHeaderValues(headers, "Chrome-Proxy");
789
790 DataReductionProxyTamperDetection::
791 RemoveChromeProxyFingerprint(&chrome_proxy_header_values);
792
793 DataReductionProxyTamperDetection tamper_detection(
794 headers,
795 true,
796 0,
797 &chrome_proxy_header_values);
798
799 bool tampered_chrome_proxy =
800 tamper_detection.IsChromeProxyHeaderTampered(chrome_proxy_fingerprint);
801 EXPECT_EQ(test[i].expected_tampered_chrome_proxy, tampered_chrome_proxy)
802 <<test[i].label;
803 if (tampered_chrome_proxy)
804 return;
805
806 std::map<std::string, DataReductionProxyTamperDetection::FingerprintCode>::
807 iterator it;
808 for (it = tamper_detection.fingerprint_name_code_map_.begin();
809 it != tamper_detection.fingerprint_name_code_map_.end(); ++it) {
810 std::string fingerprint;
811 if (!GetDataReductionProxyActionValue(
812 headers, it->first, &fingerprint)) {
813 continue;
814 }
815
816 bool tampered = false;
817 switch (it->second) {
818 case DataReductionProxyTamperDetection::VIA:
819 bool has_chrome_proxy_via_header;
820 tampered = tamper_detection.IsViaHeaderTampered(
821 fingerprint, &has_chrome_proxy_via_header);
822 EXPECT_EQ(test[i].expected_tampered_via, tampered)<<test[i].label;
823 EXPECT_EQ(test[i].expected_has_chrome_proxy_via_header,
824 has_chrome_proxy_via_header)<<test[i].label;
825 break;
826 case DataReductionProxyTamperDetection::OTHERHEADERS:
827 tampered = tamper_detection.AreOtherHeadersTampered(fingerprint);
828 EXPECT_EQ(test[i].expected_tampered_other_headers, tampered)
829 <<test[i].label;
830 break;
831 case DataReductionProxyTamperDetection::CONTENTLENGTH:
832 tampered = tamper_detection.IsContentLengthHeaderTampered(fingerprint);
833 EXPECT_EQ(test[i].expected_tampered_content_length, tampered)
834 <<test[i].label;
835 break;
836 default:
837 NOTREACHED();
838 break;
839 }
840 }
841 }
842 }
843
844 } // namespace
OLDNEW
« no previous file with comments | « components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detect.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698