Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / components / data_reduction_proxy / core / browser / data_reduction_proxy_auth_request_handler.cc
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/core/browser/data_reduction_proxy_auth_request_handler.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol.h"
15 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
16 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
17 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
18 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
19 #include "components/data_reduction_proxy/core/common/version.h"
20 #include "crypto/random.h"
21 #include "net/base/host_port_pair.h"
22 #include "net/proxy/proxy_server.h"
23 #include "net/url_request/url_request.h"
24 #include "url/gurl.h"
25
26 #if !defined(OS_ANDROID) && !defined(OS_IOS)
27 #include "google_apis/google_api_keys.h"
28 #endif
29
30 namespace data_reduction_proxy {
31
32 // The empty version for the authentication protocol. Currently used by
33 // Android webview.
34 #if defined(OS_ANDROID)
35 const char kAndroidWebViewProtocolVersion[] = "";
36 #endif
37
38 #define CLIENT_ENUM(name, str_value) \
39     case name: return str_value;
40 const char* GetString(Client client) {
41   switch (client) {
42     CLIENT_ENUMS_LIST
43   }
44   NOTREACHED();
45   return "";
46 }
47 #undef CLIENT_ENUM
48
49 // static
50 bool DataReductionProxyAuthRequestHandler::IsKeySetOnCommandLine() {
51   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
52   return command_line.HasSwitch(
53       data_reduction_proxy::switches::kDataReductionProxyKey);
54 }
55
56 DataReductionProxyAuthRequestHandler::DataReductionProxyAuthRequestHandler(
57     Client client,
58     DataReductionProxyParams* params,
59     scoped_refptr<base::SingleThreadTaskRunner> network_task_runner)
60     : client_(GetString(client)),
61       data_reduction_proxy_params_(params),
62       network_task_runner_(network_task_runner) {
63   GetChromiumBuildAndPatch(ChromiumVersion(), &build_number_, &patch_number_);
64   Init();
65 }
66
67 DataReductionProxyAuthRequestHandler::DataReductionProxyAuthRequestHandler(
68     Client client,
69     const std::string& version,
70     DataReductionProxyParams* params,
71     scoped_refptr<base::SingleThreadTaskRunner> network_task_runner)
72     : client_(GetString(client)),
73       data_reduction_proxy_params_(params),
74       network_task_runner_(network_task_runner) {
75   GetChromiumBuildAndPatch(version, &build_number_, &patch_number_);
76   Init();
77 }
78
79 std::string DataReductionProxyAuthRequestHandler::ChromiumVersion() const {
80 #if defined(PRODUCT_VERSION)
81   return PRODUCT_VERSION;
82 #else
83   return std::string();
84 #endif
85 }
86
87
88 void DataReductionProxyAuthRequestHandler::GetChromiumBuildAndPatch(
89     const std::string& version,
90     std::string* build,
91     std::string* patch) const {
92   std::vector<std::string> version_parts;
93   base::SplitString(version, '.', &version_parts);
94   if (version_parts.size() != 4)
95     return;
96   *build = version_parts[2];
97   *patch = version_parts[3];
98 }
99
100 void DataReductionProxyAuthRequestHandler::Init() {
101   InitAuthentication(GetDefaultKey());
102 }
103
104
105 DataReductionProxyAuthRequestHandler::~DataReductionProxyAuthRequestHandler() {
106 }
107
108 // static
109 base::string16 DataReductionProxyAuthRequestHandler::AuthHashForSalt(
110     int64 salt,
111     const std::string& key) {
112   std::string salted_key =
113       base::StringPrintf("%lld%s%lld",
114                          static_cast<long long>(salt),
115                          key.c_str(),
116                          static_cast<long long>(salt));
117   return base::UTF8ToUTF16(base::MD5String(salted_key));
118 }
119
120
121
122 base::Time DataReductionProxyAuthRequestHandler::Now() const {
123   return base::Time::Now();
124 }
125
126 void DataReductionProxyAuthRequestHandler::RandBytes(
127     void* output, size_t length) {
128   crypto::RandBytes(output, length);
129 }
130
131 void DataReductionProxyAuthRequestHandler::MaybeAddRequestHeader(
132     net::URLRequest* request,
133     const net::ProxyServer& proxy_server,
134     net::HttpRequestHeaders* request_headers) {
135   DCHECK(network_task_runner_->BelongsToCurrentThread());
136   if (!proxy_server.is_valid())
137     return;
138   if (proxy_server.is_direct())
139     return;
140   MaybeAddRequestHeaderImpl(proxy_server.host_port_pair(),
141                             false,
142                             request_headers);
143 }
144
145 void DataReductionProxyAuthRequestHandler::MaybeAddProxyTunnelRequestHandler(
146     const net::HostPortPair& proxy_server,
147     net::HttpRequestHeaders* request_headers) {
148   DCHECK(network_task_runner_->BelongsToCurrentThread());
149   MaybeAddRequestHeaderImpl(proxy_server, true, request_headers);
150 }
151
152 void DataReductionProxyAuthRequestHandler::AddAuthorizationHeader(
153     net::HttpRequestHeaders* headers) {
154   base::Time now = Now();
155   if (now - last_update_time_ > base::TimeDelta::FromHours(24)) {
156     last_update_time_ = now;
157     ComputeCredentials(last_update_time_, &session_, &credentials_);
158   }
159   const char kChromeProxyHeader[] = "Chrome-Proxy";
160   std::string header_value;
161   if (headers->HasHeader(kChromeProxyHeader)) {
162     headers->GetHeader(kChromeProxyHeader, &header_value);
163     headers->RemoveHeader(kChromeProxyHeader);
164     header_value += ", ";
165   }
166   header_value +=
167       "ps=" + session_ + ", sid=" + credentials_;
168   if (!build_number_.empty() && !patch_number_.empty())
169     header_value += ", b=" + build_number_ + ", p=" + patch_number_;
170   if (!client_.empty())
171     header_value += ", c=" + client_;
172   headers->SetHeader(kChromeProxyHeader, header_value);
173 }
174
175 void DataReductionProxyAuthRequestHandler::ComputeCredentials(
176     const base::Time& now,
177     std::string* session,
178     std::string* credentials) {
179   DCHECK(session);
180   DCHECK(credentials);
181   int64 timestamp =
182       (now - base::Time::UnixEpoch()).InMilliseconds() / 1000;
183
184   int32 rand[3];
185   RandBytes(rand, 3 * sizeof(rand[0]));
186   *session = base::StringPrintf("%lld-%u-%u-%u",
187                                 static_cast<long long>(timestamp),
188                                 rand[0],
189                                 rand[1],
190                                 rand[2]);
191   *credentials = base::UTF16ToUTF8(AuthHashForSalt(timestamp, key_));
192
193   DVLOG(1) << "session: [" << *session << "] "
194            << "password: [" << *credentials  << "]";
195 }
196
197 void DataReductionProxyAuthRequestHandler::InitAuthentication(
198     const std::string& key) {
199   if (!network_task_runner_->BelongsToCurrentThread()) {
200     network_task_runner_->PostTask(
201         FROM_HERE,
202         base::Bind(&DataReductionProxyAuthRequestHandler::InitAuthentication,
203                    base::Unretained(this),
204                    key));
205     return;
206   }
207
208   if (key.empty())
209     return;
210
211   key_ = key;
212   last_update_time_ = Now();
213   ComputeCredentials(last_update_time_, &session_, &credentials_);
214 }
215
216 std::string DataReductionProxyAuthRequestHandler::GetDefaultKey() const {
217   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
218   std::string key =
219     command_line.GetSwitchValueASCII(switches::kDataReductionProxyKey);
220 // Android and iOS get the default key from a preprocessor constant. All other
221 // platforms get the key from google_apis
222 #if defined(OS_ANDROID) || defined(OS_IOS)
223 #if defined(SPDY_PROXY_AUTH_VALUE)
224   if (key.empty())
225     key = SPDY_PROXY_AUTH_VALUE;
226 #endif
227 #else
228   if (key.empty()) {
229     key = google_apis::GetSpdyProxyAuthValue();
230   }
231 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
232   return key;
233 }
234
235 void DataReductionProxyAuthRequestHandler::MaybeAddRequestHeaderImpl(
236     const net::HostPortPair& proxy_server,
237     bool expect_ssl,
238     net::HttpRequestHeaders* request_headers) {
239   if (proxy_server.IsEmpty())
240     return;
241   if (data_reduction_proxy_params_ &&
242       data_reduction_proxy_params_->IsDataReductionProxy(proxy_server, NULL) &&
243       net::HostPortPair::FromURL(
244           data_reduction_proxy_params_->ssl_origin()).Equals(
245               proxy_server) == expect_ssl) {
246     AddAuthorizationHeader(request_headers);
247   }
248 }
249
250 }  // namespace data_reduction_proxy