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.
6 #include "components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "components/data_reduction_proxy/browser/data_reduction_proxy_params_test_utils.h"
15 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings_test_utils.h"
16 #include "net/base/auth.h"
17 #include "net/base/host_port_pair.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
23 const char kChromeProxyHeader[] = "chrome-proxy";
24 const char kOtherProxy[] = "testproxy:17";
27 #if defined(OS_ANDROID)
28 const char kClient[] = "android";
30 const char kClient[] = "ios";
32 const char kClient[] = "";
34 const char kVersion[] = "0.1.2.3";
35 const char kExpectedBuild[] = "2";
36 const char kExpectedPatch[] = "3";
37 const char kBogusVersion[] = "0.0";
38 const char kTestKey[] = "test-key";
39 const char kExpectedCredentials[] = "96bd72ec4a050ba60981743d41787768";
40 const char kExpectedSession[] = "0-1633771873-1633771873-1633771873";
42 const char kTestKey2[] = "test-key2";
43 const char kExpectedCredentials2[] = "c911fdb402f578787562cf7f00eda972";
44 const char kExpectedSession2[] = "0-1633771873-1633771873-1633771873";
45 #if defined(OS_ANDROID)
46 const char kExpectedHeader2[] =
47 "ps=0-1633771873-1633771873-1633771873, "
48 "sid=c911fdb402f578787562cf7f00eda972, b=2, p=3, c=android";
49 const char kExpectedHeader3[] =
50 "ps=86401-1633771873-1633771873-1633771873, "
51 "sid=d7c1c34ef6b90303b01c48a6c1db6419, b=2, p=3, c=android";
52 const char kExpectedHeader4[] =
53 "ps=0-1633771873-1633771873-1633771873, "
54 "sid=c911fdb402f578787562cf7f00eda972, c=android";
56 const char kExpectedHeader2[] =
57 "ps=0-1633771873-1633771873-1633771873, "
58 "sid=c911fdb402f578787562cf7f00eda972, b=2, p=3, c=ios";
59 const char kExpectedHeader3[] =
60 "ps=86401-1633771873-1633771873-1633771873, "
61 "sid=d7c1c34ef6b90303b01c48a6c1db6419, b=2, p=3, c=ios";
62 const char kExpectedHeader4[] =
63 "ps=0-1633771873-1633771873-1633771873, "
64 "sid=c911fdb402f578787562cf7f00eda972, c=ios";
66 const char kExpectedHeader2[] =
67 "ps=0-1633771873-1633771873-1633771873, "
68 "sid=c911fdb402f578787562cf7f00eda972, b=2, p=3";
69 const char kExpectedHeader3[] =
70 "ps=86401-1633771873-1633771873-1633771873, "
71 "sid=d7c1c34ef6b90303b01c48a6c1db6419, b=2, p=3";
72 const char kExpectedHeader4[] =
73 "ps=0-1633771873-1633771873-1633771873, "
74 "sid=c911fdb402f578787562cf7f00eda972";
77 const char kDataReductionProxyKey[] = "12345";
81 namespace data_reduction_proxy {
83 class TestDataReductionProxyAuthRequestHandler
84 : public DataReductionProxyAuthRequestHandler {
86 TestDataReductionProxyAuthRequestHandler(
87 const std::string& client,
88 const std::string& version,
89 DataReductionProxyParams* params,
90 base::MessageLoopProxy* loop_proxy)
91 : DataReductionProxyAuthRequestHandler(
92 client, version, params, loop_proxy) {}
94 virtual std::string GetDefaultKey() const OVERRIDE {
98 virtual base::Time Now() const OVERRIDE {
99 return base::Time::UnixEpoch() + now_offset_;
102 virtual void RandBytes(void* output, size_t length) OVERRIDE {
103 char* c = static_cast<char*>(output);
104 for (size_t i = 0; i < length; ++i) {
109 // Time after the unix epoch that Now() reports.
110 void set_offset(const base::TimeDelta& now_offset) {
111 now_offset_ = now_offset;
115 base::TimeDelta now_offset_;
120 class DataReductionProxyAuthRequestHandlerTest : public testing::Test {
122 DataReductionProxyAuthRequestHandlerTest()
123 : loop_proxy_(base::MessageLoopProxy::current().get()) {
125 // Required for MessageLoopProxy::current().
126 base::MessageLoopForUI loop_;
127 base::MessageLoopProxy* loop_proxy_;
130 TEST_F(DataReductionProxyAuthRequestHandlerTest, Authorization) {
131 scoped_ptr<TestDataReductionProxyParams> params;
133 new TestDataReductionProxyParams(
134 DataReductionProxyParams::kAllowed |
135 DataReductionProxyParams::kFallbackAllowed |
136 DataReductionProxyParams::kPromoAllowed,
137 TestDataReductionProxyParams::HAS_EVERYTHING &
138 ~TestDataReductionProxyParams::HAS_DEV_ORIGIN &
139 ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN));
140 TestDataReductionProxyAuthRequestHandler auth_handler(kClient,
145 base::RunLoop().RunUntilIdle();
146 EXPECT_EQ(auth_handler.client_, kClient);
147 EXPECT_EQ(kExpectedBuild, auth_handler.build_number_);
148 EXPECT_EQ(kExpectedPatch, auth_handler.patch_number_);
149 EXPECT_EQ(auth_handler.key_, kTestKey);
150 EXPECT_EQ(kExpectedCredentials, auth_handler.credentials_);
151 EXPECT_EQ(kExpectedSession, auth_handler.session_);
154 auth_handler.SetKeyOnUI(kTestKey2);
155 base::RunLoop().RunUntilIdle();
156 EXPECT_EQ(kTestKey2, auth_handler.key_);
157 EXPECT_EQ(kExpectedCredentials2, auth_handler.credentials_);
158 EXPECT_EQ(kExpectedSession2, auth_handler.session_);
160 // Don't write headers if the proxy is invalid.
161 net::HttpRequestHeaders headers;
162 auth_handler.MaybeAddRequestHeader(NULL, net::ProxyServer(), &headers);
163 EXPECT_FALSE(headers.HasHeader(kChromeProxyHeader));
165 // Don't write headers with a valid proxy, that's not a data reduction proxy.
166 auth_handler.MaybeAddRequestHeader(
168 net::ProxyServer::FromURI(kOtherProxy, net::ProxyServer::SCHEME_HTTP),
170 EXPECT_FALSE(headers.HasHeader(kChromeProxyHeader));
172 // Don't write headers with a valid data reduction ssl proxy.
173 auth_handler.MaybeAddRequestHeader(
175 net::ProxyServer::FromURI(
176 net::HostPortPair::FromURL(
177 GURL(params->DefaultSSLOrigin())).ToString(),
178 net::ProxyServer::SCHEME_HTTP),
180 EXPECT_FALSE(headers.HasHeader(kChromeProxyHeader));
182 // Write headers with a valid data reduction proxy.
183 auth_handler.MaybeAddRequestHeader(
185 net::ProxyServer::FromURI(
186 net::HostPortPair::FromURL(GURL(params->DefaultOrigin())).ToString(),
187 net::ProxyServer::SCHEME_HTTP),
189 EXPECT_TRUE(headers.HasHeader(kChromeProxyHeader));
190 std::string header_value;
191 headers.GetHeader(kChromeProxyHeader, &header_value);
192 EXPECT_EQ(kExpectedHeader2, header_value);
194 // Write headers with a valid data reduction ssl proxy when one is expected.
195 net::HttpRequestHeaders ssl_headers;
196 auth_handler.MaybeAddProxyTunnelRequestHandler(
197 net::HostPortPair::FromURL(GURL(params->DefaultSSLOrigin())),
199 EXPECT_TRUE(ssl_headers.HasHeader(kChromeProxyHeader));
200 std::string ssl_header_value;
201 ssl_headers.GetHeader(kChromeProxyHeader, &ssl_header_value);
202 EXPECT_EQ(kExpectedHeader2, ssl_header_value);
204 // Fast forward 24 hours. The header should be the same.
205 auth_handler.set_offset(base::TimeDelta::FromSeconds(24 * 60 * 60));
206 net::HttpRequestHeaders headers2;
207 // Write headers with a valid data reduction proxy.
208 auth_handler.MaybeAddRequestHeader(
210 net::ProxyServer::FromURI(
211 net::HostPortPair::FromURL(GURL(params->DefaultOrigin())).ToString(),
212 net::ProxyServer::SCHEME_HTTP),
214 EXPECT_TRUE(headers2.HasHeader(kChromeProxyHeader));
215 std::string header_value2;
216 headers2.GetHeader(kChromeProxyHeader, &header_value2);
217 EXPECT_EQ(kExpectedHeader2, header_value2);
219 // Fast forward one more second. The header should be new.
220 auth_handler.set_offset(base::TimeDelta::FromSeconds(24 * 60 * 60 + 1));
221 net::HttpRequestHeaders headers3;
222 // Write headers with a valid data reduction proxy.
223 auth_handler.MaybeAddRequestHeader(
225 net::ProxyServer::FromURI(
226 net::HostPortPair::FromURL(GURL(params->DefaultOrigin())).ToString(),
227 net::ProxyServer::SCHEME_HTTP),
229 EXPECT_TRUE(headers3.HasHeader(kChromeProxyHeader));
230 std::string header_value3;
231 headers3.GetHeader(kChromeProxyHeader, &header_value3);
232 EXPECT_EQ(kExpectedHeader3, header_value3);
235 TEST_F(DataReductionProxyAuthRequestHandlerTest, AuthorizationBogusVersion) {
236 scoped_ptr<TestDataReductionProxyParams> params;
238 new TestDataReductionProxyParams(
239 DataReductionProxyParams::kAllowed |
240 DataReductionProxyParams::kFallbackAllowed |
241 DataReductionProxyParams::kPromoAllowed,
242 TestDataReductionProxyParams::HAS_EVERYTHING &
243 ~TestDataReductionProxyParams::HAS_DEV_ORIGIN &
244 ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN));
245 TestDataReductionProxyAuthRequestHandler auth_handler(kClient,
249 EXPECT_TRUE(auth_handler.build_number_.empty());
250 EXPECT_TRUE(auth_handler.patch_number_.empty());
253 auth_handler.SetKeyOnUI(kTestKey2);
254 base::RunLoop().RunUntilIdle();
255 EXPECT_EQ(kTestKey2, auth_handler.key_);
256 EXPECT_EQ(kExpectedCredentials2, auth_handler.credentials_);
257 EXPECT_EQ(kExpectedSession2, auth_handler.session_);
259 net::HttpRequestHeaders headers;
260 // Write headers with a valid data reduction proxy;
261 auth_handler.MaybeAddRequestHeader(
263 net::ProxyServer::FromURI(
264 net::HostPortPair::FromURL(GURL(params->DefaultOrigin())).ToString(),
265 net::ProxyServer::SCHEME_HTTP),
267 EXPECT_TRUE(headers.HasHeader(kChromeProxyHeader));
268 std::string header_value;
269 headers.GetHeader(kChromeProxyHeader, &header_value);
270 EXPECT_EQ(kExpectedHeader4, header_value);
273 TEST_F(DataReductionProxyAuthRequestHandlerTest, AuthHashForSalt) {
274 std::string salt = "8675309"; // Jenny's number to test the hash generator.
275 std::string salted_key = salt + kDataReductionProxyKey + salt;
276 base::string16 expected_hash = base::UTF8ToUTF16(base::MD5String(salted_key));
277 EXPECT_EQ(expected_hash,
278 DataReductionProxyAuthRequestHandler::AuthHashForSalt(
279 8675309, kDataReductionProxyKey));
282 } // namespace data_reduction_proxy