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