| Index: components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detect_unittest.cc
|
| diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detect_unittest.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detect_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ef6f4b686839903d2a872b0ae6b28054b207f5ec
|
| --- /dev/null
|
| +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detect_unittest.cc
|
| @@ -0,0 +1,1193 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <string.h>
|
| +#include <algorithm>
|
| +#include <vector>
|
| +
|
| +#include "base/base64.h"
|
| +#include "base/md5.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detect.h"
|
| +#include "net/android/network_library.h"
|
| +#include "net/http/http_request_headers.h"
|
| +#include "net/http/http_util.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +
|
| +namespace {
|
| +
|
| +// Utility function for simulating data reduction proxy's behavior:
|
| +// calcuate MD5 hash value for a string and encode it to base64 encoded string.
|
| +std::string GetEncoded(std::string& input) {
|
| + std::string ret;
|
| + base::Base64Encode(data_reduction_proxy::DataReductionProxyTamperDetect::
|
| + GetMD5(input), &ret);
|
| + return ret;
|
| +}
|
| +
|
| +void HeadersToRaw(std::string* headers) {
|
| + std::replace(headers->begin(), headers->end(), '\n', '\0');
|
| + if (!headers->empty())
|
| + *headers += '\0';
|
| +}
|
| +
|
| +// Utility function, replace all contents within "[]" by corresponding base64
|
| +// encoded MD5 value.
|
| +void ReplaceWithEncodedString(std::string& input)
|
| +{
|
| + size_t start, end;
|
| + while (true) {
|
| + start = input.find("[");
|
| + if (start == std::string::npos) break;
|
| + end = input.find("]", start);
|
| + std::string need_to_encode = input.substr(start + 1, end - start - 1);
|
| + input = input.substr(0, start) + GetEncoded(need_to_encode) +
|
| + input.substr(end + 1);
|
| + }
|
| +}
|
| +
|
| +// Testcase for fingerprint checking functions.
|
| +// |received_fingerprint| is fingerprint received from data reduction proxy.
|
| +// |expected_tampered| is expected tampered or not result.
|
| +struct FingerprintTestCase {
|
| + std::string raw_header;
|
| + std::string received_fingerprint;
|
| + bool expected_tampered;
|
| +};
|
| +
|
| +// Testcase for parsing fingerprints.
|
| +// |expected_contain_tamper_detect_fingerprints| is correct boolean value for
|
| +// whether there is fingerprint for |raw_header|.
|
| +// |expected_chrome_proxy_fingerprint| is correctly prased chrome proxy
|
| +// fingerprint. |expected_other_fingerprints| is correctly parsed other
|
| +// fingerprints.
|
| +struct ParsingTestCase {
|
| + std::string raw_header;
|
| + std::string expected_chrome_proxy_fingerprint;
|
| + std::string expected_other_fingerprints;
|
| + bool expected_contain_tamper_detect_fingerprints;
|
| +};
|
| +
|
| +// Testcase for entire fingerprint checking process.
|
| +struct CompletedTestCase {
|
| + std::string raw_header;
|
| + bool expected_contain_tamper_detect_fingerprints;
|
| + bool expected_tampered_chrome_proxy;
|
| + bool expected_tampered_via;
|
| + bool expected_tampered_other_headers;
|
| + bool expected_tampered_content_length;
|
| +};
|
| +
|
| +class DataReductionProxyTamperDetectTest : public testing::Test {
|
| +};
|
| +
|
| +// For a given header string |test.raw_header|, generate HttpResponseHeaders
|
| +// |headers| and initiate DataReductionProxyTamperDetect object.
|
| +// Check selected fingerprint type |fingerprint|.
|
| +void TestFingerprintCommon(const FingerprintTestCase& test,
|
| + data_reduction_proxy::FingerprintCode fingerprint) {
|
| + std::string raw_headers(test.raw_header);
|
| + HeadersToRaw(&raw_headers);
|
| + scoped_refptr<net::HttpResponseHeaders> headers(
|
| + new net::HttpResponseHeaders(raw_headers));
|
| +
|
| + std::vector<std::string> values = data_reduction_proxy::
|
| + DataReductionProxyTamperDetect::GetHeaderValues(headers, "Chrome-Proxy");
|
| + std::string chrome_proxy_fingerprint, other_fingerprints;
|
| +
|
| + data_reduction_proxy::ContainsTamperDetectFingerprints(
|
| + values, chrome_proxy_fingerprint, other_fingerprints);
|
| +
|
| + data_reduction_proxy::DataReductionProxyTamperDetect
|
| + tamper_detect(headers, true, 0, &values);
|
| +
|
| + bool tampered;
|
| + switch (fingerprint) {
|
| + case data_reduction_proxy::CHROMEPROXY:
|
| + tampered = tamper_detect.CheckHeaderChromeProxy(test.received_fingerprint);
|
| + break;
|
| + case data_reduction_proxy::VIA:
|
| + tampered = tamper_detect.CheckHeaderVia(test.received_fingerprint);
|
| + break;
|
| + case data_reduction_proxy::OTHERHEADERS:
|
| + tampered = tamper_detect.CheckHeaderOtherHeaders(
|
| + test.received_fingerprint);
|
| + break;
|
| + case data_reduction_proxy::CONTENTLENGTH:
|
| + tampered = tamper_detect.CheckHeaderContentLength(
|
| + test.received_fingerprint);
|
| + break;
|
| + case data_reduction_proxy::NONEXIST:
|
| + break;
|
| + }
|
| +
|
| + EXPECT_EQ(test.expected_tampered, tampered);
|
| +}
|
| +
|
| +// For a given header string |test.raw_header|, generate HttpResponseHeaders
|
| +// |headers|. Check the return of function ContainsTamperDetectFingerprints
|
| +// match the expected values or not.
|
| +void TestParsingCommon(const ParsingTestCase& test) {
|
| + std::string raw_headers(test.raw_header);
|
| + HeadersToRaw(&raw_headers);
|
| + scoped_refptr<net::HttpResponseHeaders> headers(
|
| + new net::HttpResponseHeaders(raw_headers));
|
| +
|
| + std::vector<std::string> values = data_reduction_proxy::
|
| + DataReductionProxyTamperDetect::GetHeaderValues(headers, "Chrome-Proxy");
|
| +
|
| + std::string chrome_proxy_fingerprint, other_fingerprints;
|
| + bool contain_tamper_detect_fingerprints = data_reduction_proxy::
|
| + ContainsTamperDetectFingerprints(values,
|
| + chrome_proxy_fingerprint,
|
| + other_fingerprints);
|
| +
|
| + EXPECT_EQ(test.expected_contain_tamper_detect_fingerprints,
|
| + contain_tamper_detect_fingerprints);
|
| +
|
| + if (contain_tamper_detect_fingerprints) {
|
| + EXPECT_EQ(test.expected_chrome_proxy_fingerprint,
|
| + chrome_proxy_fingerprint);
|
| +
|
| + EXPECT_EQ(test.expected_other_fingerprints,
|
| + other_fingerprints);
|
| + }
|
| +}
|
| +
|
| +// Mostly copying codes from CheckResponseFingerprint, added check
|
| +// functionality.
|
| +void TestCompletedCommon(const CompletedTestCase& test) {
|
| + std::string raw_headers(test.raw_header);
|
| + HeadersToRaw(&raw_headers);
|
| + scoped_refptr<net::HttpResponseHeaders> headers(
|
| + new net::HttpResponseHeaders(raw_headers));
|
| + std::vector<std::string> values = data_reduction_proxy::
|
| + DataReductionProxyTamperDetect::GetHeaderValues(headers, "Chrome-Proxy");
|
| +
|
| + std::string chrome_proxy_fingerprint, other_fingerprints;
|
| +
|
| + bool contain_tamper_detect_fingerprints = data_reduction_proxy::
|
| + ContainsTamperDetectFingerprints(values,
|
| + chrome_proxy_fingerprint,
|
| + other_fingerprints);
|
| + EXPECT_EQ(test.expected_contain_tamper_detect_fingerprints,
|
| + contain_tamper_detect_fingerprints);
|
| + if (!contain_tamper_detect_fingerprints)
|
| + return;
|
| +
|
| + data_reduction_proxy::DataReductionProxyTamperDetect tamper_detect(
|
| + headers, true, 0, &values);
|
| +
|
| + bool tampered_chrome_proxy =
|
| + tamper_detect.CheckHeaderChromeProxy(chrome_proxy_fingerprint);
|
| + EXPECT_EQ(test.expected_tampered_chrome_proxy, tampered_chrome_proxy);
|
| + if (tampered_chrome_proxy)
|
| + return;
|
| +
|
| + net::HttpUtil::ValuesIterator it(other_fingerprints.begin(),
|
| + other_fingerprints.end(), '|');
|
| +
|
| + size_t delimiter_pos = std::string::npos;
|
| + while (it.GetNext()) {
|
| +
|
| + delimiter_pos = it.value().find("=");
|
| + if (delimiter_pos == std::string::npos)
|
| + continue;
|
| + std::string key = it.value().substr(0, delimiter_pos);
|
| + std::string value = it.value().substr(delimiter_pos + 1);
|
| +
|
| + data_reduction_proxy::FingerprintCode fingerprint_code =
|
| + tamper_detect.GetFingerprintCode(key);
|
| + bool tampered = false;
|
| + switch (fingerprint_code) {
|
| + case data_reduction_proxy::VIA:
|
| + tampered = tamper_detect.CheckHeaderVia(value);
|
| + EXPECT_EQ(test.expected_tampered_via, tampered);
|
| + break;
|
| + case data_reduction_proxy::OTHERHEADERS:
|
| + tampered = tamper_detect.CheckHeaderOtherHeaders(value);
|
| + EXPECT_EQ(test.expected_tampered_other_headers, tampered);
|
| + break;
|
| + case data_reduction_proxy::CONTENTLENGTH:
|
| + tampered = tamper_detect.CheckHeaderContentLength(value);
|
| + EXPECT_EQ(test.expected_tampered_content_length, tampered);
|
| + break;
|
| + case data_reduction_proxy::CHROMEPROXY:
|
| + case data_reduction_proxy::NONEXIST:
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +TEST(DataReductionProxyTamperDetectTest, ChromeProxy) {
|
| + FingerprintTestCase test[] = {
|
| + // check sorting values and decoding
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh," +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "123,bbbypas=0,aaxxx=xxx,bbbloc=1\n",
|
| + "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0," +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) + "123,",
|
| + false,
|
| + },
|
| +
|
| + // check sorting
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: a,b,c,d,e,3,2,1," +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy)
|
| + + "1231\n",
|
| + "1,2,3,a,b,c,d,e,",
|
| + false,
|
| + },
|
| +
|
| + // check no Chrome-Proxy header case (should not happen)
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Length: 12345\n",
|
| + "",
|
| + false,
|
| + },
|
| +
|
| + // check empty Chrome-Proxy header case (should not happen)
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: \n",
|
| + ",",
|
| + false,
|
| + },
|
| +
|
| + // check empty Chrome-Proxy header case (should not happen)
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy)
|
| + + "xyz\n",
|
| + "",
|
| + false,
|
| + },
|
| +
|
| + // check empty Chrome-Proxy header case, with extra ","
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy)
|
| + + "abcde , \n",
|
| + "",
|
| + false,
|
| + },
|
| +
|
| + // check empty Chrome-Proxy header, different fingerprint
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy)
|
| + + "xyz\n",
|
| + ",",
|
| + true,
|
| + },
|
| +
|
| + // check regular Chrome-Proxy header, different fingerprint
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=2,aaxxx=xxx,bbbloc=1\n",
|
| + "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,",
|
| + true,
|
| + },
|
| +
|
| + // check regular Chrome-Proxy header, different fingerprint
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: a,aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n",
|
| + "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,",
|
| + true,
|
| + },
|
| +
|
| + // check regular Chrome-Proxy header, different fingerprint (order)
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n",
|
| + "aaxxx=xxx,aut=aauutthh,bbbypas=0,bbbloc=1,",
|
| + true,
|
| + },
|
| +
|
| + // check regular Chrome-Proxy header, with extra " "
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh , bbbypas=0 , aaxxx=xxx"
|
| + " ,bbbloc=1 \n",
|
| + "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,",
|
| + false
|
| + },
|
| +
|
| + // check regular Chrome-Proxy header, with extra lines and " "
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh , bbbypas=0 , bbbloc=1 \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n",
|
| + "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,",
|
| + false
|
| + },
|
| +
|
| + // check Chrome-Proxy header with multiple lines
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Chrome-Proxy: aut=aauutthh\n"
|
| + "Chrome-Proxy: bbbypas=0\n"
|
| + "Chrome-Proxy:bbbloc=1 \n",
|
| + "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,",
|
| + false
|
| + },
|
| +
|
| + // check Chrome-Proxy header with multiple lines, at different position
|
| + // of the entire header
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Chrome-Proxy: aut=aauutthh\n"
|
| + "Content-Type: 1\n"
|
| + "Cache-Control: 2\n"
|
| + "ETag: 3\n"
|
| + "Chrome-Proxy: bbbypas=0\n"
|
| + "Connection: 4\n"
|
| + "Expires: 5\n"
|
| + "Chrome-Proxy: bbbloc=1\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "123 \n",
|
| + "aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,",
|
| + false
|
| + },
|
| +
|
| + // check Chrome-Proxy header with multiple same values
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Chrome-Proxy: aut=aauutthh\n"
|
| + "Content-Type: 1\n"
|
| + "Cache-Control: 2\n"
|
| + "ETag: 3\n"
|
| + "Chrome-Proxy: bbbypas=0\n"
|
| + "Connection: 4\n"
|
| + "Expires: 5\n"
|
| + "Chrome-Proxy: bbbloc=1, " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "123 \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "aaxxx=xxx,aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0," +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) + "123,",
|
| + false
|
| + },
|
| +
|
| + // check Chrome-Proxy header with multiple same values, with Chrome-Proxy
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Chrome-Proxy: aut=aauutthh\n"
|
| + "Content-Type: 1\n"
|
| + "Cache-Control: 2\n"
|
| + "ETag: 3\n"
|
| + "Chrome-Proxy: bbbypas=0\n"
|
| + "Connection: 4\n"
|
| + "Expires: 5\n"
|
| + "Chrome-Proxy: bbbloc=1, " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "123 \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "xyn \n" +
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "aaxxx=xxx,aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0," +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) + "123,",
|
| + false
|
| + },
|
| +
|
| + // check Chrome-Proxy header with multiple same values,
|
| + // but different fingerprint
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Chrome-Proxy: aut=aauutthh\n"
|
| + "Content-Type: 1\n"
|
| + "Cache-Control: 2\n"
|
| + "ETag: 3\n"
|
| + "Chrome-Proxy: bbbypas=0\n"
|
| + "Connection: 4\n"
|
| + "Expires: 5\n"
|
| + "Chrome-Proxy: bbbloc=1\n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "aaxxx=xxx,aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,",
|
| + true,
|
| + },
|
| +
|
| + // check Chrome-Proxy header with multiple same values,
|
| + // but different fingerprint, with Chrome-Proxy
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Chrome-Proxy: aut=aauutthh\n"
|
| + "Content-Type: 1\n"
|
| + "Cache-Control: 2\n"
|
| + "ETag: 3\n"
|
| + "Chrome-Proxy: bbbypas=0\n"
|
| + "Connection: 4\n"
|
| + "Expires: 5\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "xyn \n" +
|
| + "Chrome-Proxy: bbbloc=1\n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "aaxxx=xxx,aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,",
|
| + true,
|
| + },
|
| +
|
| + // check Chrome-Proxy header with multiple lines,
|
| + // but different fingerprint
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: 1\n"
|
| + "Cache-Control: 2\n"
|
| + "ETag: 3\n"
|
| + "Chrome-Proxy: bbbypas=0\n"
|
| + "Connection: 4\n"
|
| + "Expires: 5\n"
|
| + "Chrome-Proxy: bbbloc=1\n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "aaxxx=xxx,aaxxx=xxx,aut=aauutthh,bbbloc=1,bbbypas=0,",
|
| + true,
|
| + },
|
| +
|
| + // check regular Chrome-Proxy header, but received fingerprint is empty
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Chrome-Proxy: aut=aauutthh\n"
|
| + "Content-Type: 1\n"
|
| + "Cache-Control: 2\n"
|
| + "ETag: 3\n"
|
| + "Chrome-Proxy: bbbypas=0\n"
|
| + "Connection: 4\n"
|
| + "Expires: 5\n"
|
| + "Chrome-Proxy: bbbloc=1\n"
|
| + "Chrome-Proxy: aaxxx=xxx \n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "",
|
| + true,
|
| + },
|
| +
|
| + };
|
| +
|
| + for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
|
| + test[i].received_fingerprint =
|
| + GetEncoded(test[i].received_fingerprint);
|
| + TestFingerprintCommon(test[i], data_reduction_proxy::CHROMEPROXY);
|
| + }
|
| +}
|
| +
|
| +TEST(DataReductionProxyTamperDetectTest, Via) {
|
| + FingerprintTestCase test[] = {
|
| + // check regular case, where Chrome-Compression-Proxy occurs at the last
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Via: a, b, c, Chrome-Compression-Proxy\n",
|
| + "0",
|
| + false
|
| + },
|
| +
|
| + // check when there is extra middlebox
|
| + // between data-reduction-proxy and phone
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Via: a, b, c, Chrome-Compression-Proxy, xyz\n",
|
| + "0",
|
| + true,
|
| + },
|
| +
|
| + // emtpy Via header, even no Chrome-Compression-Proxy tag
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Via: \n",
|
| + "0",
|
| + true,
|
| + },
|
| +
|
| + // only Chrome-Compression-Proxy tag occurs in Via header
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Via: Chrome-Compression-Proxy \n",
|
| + "0",
|
| + false
|
| + },
|
| +
|
| + // there are " ", i.e., empty value after Chrome-Compression-Proxy tag
|
| + // should not count as extra middleboxes
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Via: Chrome-Compression-Proxy , , \n",
|
| + "0",
|
| + false
|
| + },
|
| +
|
| + // special case when there is no Via header
|
| + {
|
| + "HTTP/1.1 200 OK \n",
|
| + "0",
|
| + true
|
| + },
|
| +
|
| + // same to above test cases, but with deprecated data reduciton proxy tag.
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Via: a, b, c, Chrome Compression Proxy\n",
|
| + "0",
|
| + false
|
| + },
|
| +
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Via: a, b, c, Chrome Compression Proxy, xyz\n",
|
| + "0",
|
| + true,
|
| + },
|
| +
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Via: Chrome Compression Proxy \n",
|
| + "0",
|
| + false
|
| + },
|
| +
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Via: Chrome Compression Proxy , , \n",
|
| + "0",
|
| + false
|
| + },
|
| + };
|
| +
|
| + for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
|
| + TestFingerprintCommon(test[i], data_reduction_proxy::VIA);
|
| + }
|
| +}
|
| +
|
| +TEST(DataReductionProxyTamperDetectTest, OtherHeaders) {
|
| + // For following testcases, |received_fingerprint| is not the actual
|
| + // fingerprint: the only difference is that the MD5 hash value field is
|
| + // the string text, e.g., we need to modify fingerprint:
|
| + // "12345;:content-length" to
|
| + // "[MD5(12345)];:content-length" before hand it to fingerprint checking
|
| + // function.
|
| + FingerprintTestCase test[] = {
|
| + // regular case, with correct fingerprint
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Content-Type: 1\n"
|
| + "Cache-Control: 2\n"
|
| + "ETag: 3\n"
|
| + "Connection: 4\n"
|
| + "Expires: 5\n"
|
| + "Via: \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n" +
|
| + "Content-Length: 12345\n",
|
| + "[1,;2,;3,;4,;5,;]:content-type:cache-control:etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // regular case, with correct fingerprint
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Content-Type: aaa1\n"
|
| + "Cache-Control: aaa2\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n" +
|
| + "ETag: aaa3\n"
|
| + "Connection: aaa4\n"
|
| + "Expires: aaa5\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "[aaa1,;aaa2,;aaa3,;aaa4,;aaa5,;]:content-type:cache-control:"
|
| + "etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // regular case, one header is with multiple values
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n" +
|
| + "Content-Type: aaa1, bbb1, ccc1\n"
|
| + "Cache-Control: aaa2\n"
|
| + "ETag: aaa3\n"
|
| + "Connection: aaa4\n"
|
| + "Expires: aaa5\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "[aaa1,bbb1,ccc1,;aaa2,;aaa3,;aaa4,;aaa5,;]:"
|
| + "content-type:cache-control:etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // regular case, one header has multiple lines
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Content-Type: aaa1, ccc1\n"
|
| + "Content-Type: xxx1, bbb1, ccc1\n"
|
| + "Cache-Control: aaa2\n"
|
| + "ETag: aaa3\n"
|
| + "Connection: aaa4\n"
|
| + "Expires: aaa5\n"
|
| + "Via: \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n" +
|
| + "Content-Length: 12345\n",
|
| + "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,;aaa3,;aaa4,;aaa5,;]:"
|
| + "content-type:cache-control:etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // regular case, one header has multiple lines,
|
| + // and such multiple lines occur at different positions
|
| + {
|
| + "HTTP/1.1 200 OK \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n" +
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Content-Type: aaa1, ccc1\n"
|
| + "Cache-Control: aaa2\n"
|
| + "ETag: aaa3\n"
|
| + "Content-Type: xxx1, bbb1, ccc1\n"
|
| + "Connection: aaa4\n"
|
| + "Expires: aaa5\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,;aaa3,;aaa4,;aaa5,;]"
|
| + ":content-type:cache-control:etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // regular case, more than one header have multiple lines,
|
| + // and such multiple lines occur at different positions
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Content-Type: aaa1, ccc1\n"
|
| + "Cache-Control: ccc2 , bbb2\n"
|
| + "ETag: aaa3\n"
|
| + "Content-Type: xxx1, bbb1, ccc1\n"
|
| + "Connection: aaa4\n"
|
| + "Cache-Control: aaa2 \n"
|
| + "Expires: aaa5\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n" +
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,bbb2,ccc2,;aaa3,;aaa4,;aaa5,;:]"
|
| + "content-type:cache-control:etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // regular case, response header does not have one header we need
|
| + // for fingerprint (expires)
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Content-Type: aaa1, ccc1\n"
|
| + "Cache-Control: ccc2 , bbb2\n"
|
| + "ETag: aaa3\n"
|
| + "Content-Type: xxx1, bbb1, ccc1\n"
|
| + "Connection: aaa4\n"
|
| + "Cache-Control: aaa2 \n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n",
|
| + "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,bbb2,ccc2,;aaa3,;aaa4,;;:]"
|
| + "content-type:cache-control:etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // regular case, response header does not have more than one header
|
| + // we need for fingerprint (content-type, expires)
|
| + {
|
| + "HTTP/1.1 200 OK \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n" +
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Cache-Control: ccc2 , bbb2\n"
|
| + "ETag: aaa3\n"
|
| + "Connection: aaa4\n"
|
| + "Cache-Control: aaa2 \n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "[;aaa2,bbb2,ccc2,;aaa3,;aaa4,;;]:content-type:cache-control:"
|
| + "etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // regular case, all the headers we need for fingerprint are missing
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n",
|
| + "[;;;;;]:content-type:cache-control:etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // regular case, with only one header required.
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n",
|
| + "[12345,;]:content-length",
|
| + false
|
| + },
|
| +
|
| + // regular case, but differ to received fingerprint
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Content-Type: aaa1, ccc1\n"
|
| + "Cache-Control: ccc2 , bbb2\n"
|
| + "ETag: etag\n"
|
| + "Content-Type: xxx1, bbb1, ccc1\n"
|
| + "Connection: aaa4\n"
|
| + "Cache-Control: aaa2 \n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "[aaa1,bbb1,ccc1,ccc1,xxx1,;aaa2,bbb2,ccc2,;aaa3,;aaa4,;;]:"
|
| + "content-type:cache-control:etag:connection:expires",
|
| + true,
|
| + },
|
| +
|
| + // special case, headers are not missing but some of them are empty
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: \n"
|
| + "Cache-Control: \n"
|
| + "ETag: \n"
|
| + "Connection: \n"
|
| + "Expires: 5\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n" +
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "[,;,;,;,;5,;]:content-type:cache-control:etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // special case, some headers do not exist, some are of empty value.
|
| + // check delimiter "," and ";" work correctly.
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Cache-Control: \n"
|
| + "Connection: \n"
|
| + "Expires: 5\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n",
|
| + "[;,;;,;5,;]:content-type:cache-control:etag:connection:expires",
|
| + false
|
| + },
|
| +
|
| + // special case, check if we don't check any header, i.e.,
|
| + // header list is empty
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Content-Type: 1\n"
|
| + "Cache-Control: 2\n"
|
| + "ETag: 3\n"
|
| + "Connection: 4\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n" +
|
| + "Expires: 5\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "",
|
| + false
|
| + },
|
| +
|
| + // special case, we only want to check one header, which does not
|
| + // exist in received header
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: aut=aauutthh,bbbypas=0,aaxxx=xxx,bbbloc=1\n"
|
| + "Content-Type: 1\n"
|
| + "Cache-Control: 2\n"
|
| + "ETag: 3\n"
|
| + "Connection: 4\n"
|
| + "Expires: 5\n"
|
| + "Via: \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n" +
|
| + "Content-Length: 12345\n",
|
| + "[;]:non_exist_header",
|
| + false
|
| + },
|
| +
|
| + // there is only one header in our header list
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Cache-Control: \n"
|
| + "Connection: \n"
|
| + "Expires: 5\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy) +
|
| + "abcde \n" +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "abcde \n",
|
| + "[;]:content-type",
|
| + false
|
| + },
|
| +
|
| + // special case, if base64 decoding fails
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Cache-Control: \n"
|
| + "Connection: \n"
|
| + "Expires: 5\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + ";:content-type",
|
| + false
|
| + },
|
| +
|
| + // special case, if base64 decoding fails
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Cache-Control: \n"
|
| + "Connection: \n"
|
| + "Expires: 5\n"
|
| + "Via: \n"
|
| + "Content-Length: 12345\n",
|
| + "abcde:content-type:cache-control:etag:connection:expires",
|
| + false
|
| + },
|
| + };
|
| +
|
| + for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
|
| + ReplaceWithEncodedString(test[i].received_fingerprint);
|
| + TestFingerprintCommon(test[i], data_reduction_proxy::OTHERHEADERS);
|
| + }
|
| +}
|
| +
|
| +TEST(DataReductionProxyTamperDetectTest, ContentLength) {
|
| + FingerprintTestCase test[] = {
|
| + // regular case, content-length is the same
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: 1\n"
|
| + "Content-Length: 12345\n",
|
| + "12345",
|
| + false,
|
| + },
|
| +
|
| + // regular case, content-length is not the same
|
| + // also check if retrieved content-type is correct
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: text/html; charset=ISO-8859-4\n"
|
| + "Content-Length: 12345\n",
|
| + "125",
|
| + true,
|
| + },
|
| +
|
| + // special case, data reduction proxy does not sent content-length
|
| + // i.e., content-length at data reduction proxy side is missing
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: text/javascript\n"
|
| + "Content-Length: 12345\n",
|
| + "",
|
| + false,
|
| + },
|
| +
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: text/javascript\n"
|
| + "Content-Length: 12345\n",
|
| + "aaa",
|
| + false,
|
| + },
|
| +
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: text/javascript\n"
|
| + "Content-Length: aaa\n",
|
| + "aaa",
|
| + false,
|
| + },
|
| +
|
| + // special case, content-length are missing at both end
|
| + // i.e., both data reduction proxy and chrome
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: 1\n",
|
| + "",
|
| + false,
|
| + },
|
| +
|
| + // special case, check when content-length is 0
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: application/x-javascript\n"
|
| + "Content-Length: 0\n",
|
| + "0",
|
| + false,
|
| + },
|
| +
|
| + // special case, check when data reduction proxy side's
|
| + // content-length is empty (header exist, but value is empty)
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: application/x-javascript\n"
|
| + "Content-Length: 123\n",
|
| + ",",
|
| + false,
|
| + },
|
| +
|
| + // when content-length is different, check whether it recognizes image.
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: image/gif \n"
|
| + "Content-Length: 123\n",
|
| + "0",
|
| + true,
|
| + },
|
| +
|
| + // when content-length is different, check whether it recognizes JS
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: application/x-javascript \n"
|
| + "Content-Length: 0\n",
|
| + "120",
|
| + true,
|
| + },
|
| +
|
| + // when content-length is different, check whether it recognizes JS
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: text/javascript \n"
|
| + "Content-Length: 123\n",
|
| + "0",
|
| + true,
|
| + },
|
| +
|
| + // when content-length is different, check whether it recognizes CSS
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: text/css\n"
|
| + "Content-Length: 111\n",
|
| + "0",
|
| + true,
|
| + },
|
| +
|
| + // when content-length is different (chrome side is missing),
|
| + // check whether it recognizes JS.
|
| + // (if phone side's content-length has been removed, shall we report?
|
| + // current implementation: not reporting.)
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Content-Type: application/javascript \n",
|
| + "123",
|
| + false,
|
| + },
|
| + };
|
| +
|
| + for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
|
| + TestFingerprintCommon(test[i], data_reduction_proxy::CONTENTLENGTH);
|
| + }
|
| +}
|
| +
|
| +TEST(DataReductionProxyTamperDetectTest, Parsing) {
|
| + ParsingTestCase test[] = {
|
| + // Check normal case, Chrome-Proxy fingerprint doesn't exist
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: f1:f1&f2:f2&f3:f3&f4:f4\n",
|
| + "",
|
| + "",
|
| + false
|
| + },
|
| + // Check normal case, Chrome-Proxy fingerprint exist,
|
| + // but other headers' fingerprint is not there.
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: f1, " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy)
|
| + + "abc \n",
|
| + "abc",
|
| + "",
|
| + true
|
| + },
|
| +
|
| + // Check normal case, both Chrome-Proxy fingerprint
|
| + // and other headers' fingerprint exist,
|
| + // but with different values and occur at different position.
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: f1, " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy)
|
| + + "abc \n"
|
| + "Chrome-Proxy: " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) + "def\n",
|
| + "abc",
|
| + "def",
|
| + true
|
| + },
|
| +
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: f1, " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy)
|
| + + "abc," +
|
| + data_reduction_proxy::kTamperDetectFingerprint + "def \n",
|
| + "abc",
|
| + "def",
|
| + true
|
| + },
|
| +
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: f1, " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy)
|
| + + "def," +
|
| + data_reduction_proxy::kTamperDetectFingerprint + "abc \n",
|
| + "def",
|
| + "abc",
|
| + true
|
| + },
|
| +
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: f1, " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) + "abc," +
|
| + data_reduction_proxy::kTamperDetectFingerprintChromeProxy + "def \n",
|
| + "def",
|
| + "abc",
|
| + true
|
| + },
|
| +
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Chrome-Proxy: f1, " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) + "def," +
|
| + data_reduction_proxy::kTamperDetectFingerprintChromeProxy + "abc \n",
|
| + "abc",
|
| + "def",
|
| + true
|
| + },
|
| + };
|
| +
|
| + for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
|
| + TestParsingCommon(test[i]);
|
| + }
|
| +}
|
| +
|
| +// Need to replace fingerprint with its MD5 value, and then
|
| +// append fingerprint for Chrome-Proxy header.
|
| +TEST(DataReductionProxyTamperDetectTest, Completed) {
|
| + CompletedTestCase test[] = {
|
| + // Check normal case, Chrome-Proxy fingerprint doesn't exist
|
| + {
|
| + "HTTP/1.1 200 OK \n"
|
| + "Via: a1, b2, Chrome-Compression-Proxy\n"
|
| + "Content-Length: 12345\n"
|
| + "header1: header_1\n"
|
| + "header2: header_2\n"
|
| + "header3: header_3\n"
|
| + "Chrome-Proxy: a,b,c,d,e, " +
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprint) +
|
| + "via=0|oh=[header_1,;header_2,;header_3,;]:header1:header2:header3|"
|
| + "cl=12345, ",
|
| + true,
|
| + false,
|
| + false,
|
| + false,
|
| + false
|
| + },
|
| + };
|
| +
|
| + for (size_t i=0; i<ARRAYSIZE_UNSAFE(test); ++i) {
|
| + // Replace fingerprint with base64 encoded MD5 value.
|
| + ReplaceWithEncodedString(test[i].raw_header);
|
| +
|
| + // Generate fingerprint for Chrome-Proxy header.
|
| + std::string raw_headers(test[i].raw_header);
|
| + HeadersToRaw(&raw_headers);
|
| + scoped_refptr<net::HttpResponseHeaders> headers(
|
| + new net::HttpResponseHeaders(raw_headers));
|
| + std::vector<std::string> values = data_reduction_proxy::
|
| + DataReductionProxyTamperDetect::
|
| + GetHeaderValues(headers, "Chrome-Proxy");
|
| +
|
| + std::string sorted_values = data_reduction_proxy::
|
| + DataReductionProxyTamperDetect::ValuesToSortedString(values);
|
| + std::string fingerprint = GetEncoded(sorted_values);
|
| +
|
| + test[i].raw_header +=
|
| + std::string(data_reduction_proxy::kTamperDetectFingerprintChromeProxy)
|
| + + fingerprint + "\n";
|
| + TestCompletedCommon(test[i]);
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
|
|