OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/token_validator_factory_impl.h" | 5 #include "remoting/host/token_validator_base.h" |
6 | |
7 #include <set> | |
8 | 6 |
9 #include "base/base64.h" | 7 #include "base/base64.h" |
10 #include "base/bind.h" | 8 #include "base/bind.h" |
11 #include "base/callback.h" | 9 #include "base/callback.h" |
12 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
13 #include "base/location.h" | |
14 #include "base/logging.h" | 11 #include "base/logging.h" |
15 #include "base/memory/weak_ptr.h" | 12 #include "base/memory/weak_ptr.h" |
16 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
17 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
18 #include "base/values.h" | 15 #include "base/values.h" |
19 #include "crypto/random.h" | |
20 #include "net/base/escape.h" | 16 #include "net/base/escape.h" |
21 #include "net/base/io_buffer.h" | 17 #include "net/base/io_buffer.h" |
22 #include "net/base/request_priority.h" | 18 #include "net/base/request_priority.h" |
23 #include "net/base/upload_bytes_element_reader.h" | 19 #include "net/base/upload_bytes_element_reader.h" |
24 #include "net/base/upload_data_stream.h" | 20 #include "net/base/upload_data_stream.h" |
25 #include "net/ssl/client_cert_store.h" | 21 #include "net/ssl/client_cert_store.h" |
26 #if defined(USE_NSS) | 22 #if defined(USE_NSS) |
27 #include "net/ssl/client_cert_store_nss.h" | 23 #include "net/ssl/client_cert_store_nss.h" |
28 #elif defined(OS_WIN) | 24 #elif defined(OS_WIN) |
29 #include "net/ssl/client_cert_store_win.h" | 25 #include "net/ssl/client_cert_store_win.h" |
30 #elif defined(OS_MACOSX) | 26 #elif defined(OS_MACOSX) |
31 #include "net/ssl/client_cert_store_mac.h" | 27 #include "net/ssl/client_cert_store_mac.h" |
32 #endif | 28 #endif |
33 #include "net/ssl/ssl_cert_request_info.h" | 29 #include "net/ssl/ssl_cert_request_info.h" |
34 #include "net/url_request/url_request.h" | 30 #include "net/url_request/url_request.h" |
35 #include "net/url_request/url_request_context.h" | 31 #include "net/url_request/url_request_context.h" |
36 #include "net/url_request/url_request_status.h" | 32 #include "net/url_request/url_request_status.h" |
37 #include "remoting/base/rsa_key_pair.h" | |
38 #include "url/gurl.h" | 33 #include "url/gurl.h" |
39 | 34 |
40 namespace { | 35 namespace { |
41 | 36 |
42 // Length in bytes of the cryptographic nonce used to salt the token scope. | |
43 const size_t kNonceLength = 16; // 128 bits. | |
44 const int kBufferSize = 4096; | 37 const int kBufferSize = 4096; |
45 const char kCertIssuerWildCard[] = "*"; | 38 const char kCertIssuerWildCard[] = "*"; |
46 | 39 |
47 } // namespace | 40 } // namespace |
48 | 41 |
49 namespace remoting { | 42 namespace remoting { |
50 | 43 |
51 class TokenValidatorImpl | 44 TokenValidatorBase::TokenValidatorBase( |
52 : public net::URLRequest::Delegate, | |
53 public protocol::ThirdPartyHostAuthenticator::TokenValidator { | |
54 public: | |
55 TokenValidatorImpl( | |
56 const ThirdPartyAuthConfig& third_party_auth_config, | |
57 scoped_refptr<RsaKeyPair> key_pair, | |
58 const std::string& local_jid, | |
59 const std::string& remote_jid, | |
60 scoped_refptr<net::URLRequestContextGetter> request_context_getter); | |
61 virtual ~TokenValidatorImpl(); | |
62 | |
63 // TokenValidator interface. | |
64 virtual const GURL& token_url() const OVERRIDE; | |
65 virtual const std::string& token_scope() const OVERRIDE; | |
66 virtual void ValidateThirdPartyToken( | |
67 const std::string& token, | |
68 const base::Callback<void( | |
69 const std::string& shared_secret)>& on_token_validated) OVERRIDE; | |
70 | |
71 // URLFetcherDelegate interface. | |
72 virtual void OnResponseStarted(net::URLRequest* source) OVERRIDE; | |
73 virtual void OnReadCompleted(net::URLRequest* source, | |
74 int bytes_read) OVERRIDE; | |
75 virtual void OnCertificateRequested( | |
76 net::URLRequest* source, | |
77 net::SSLCertRequestInfo* cert_request_info) OVERRIDE; | |
78 | |
79 private: | |
80 static std::string CreateScope(const std::string& local_jid, | |
81 const std::string& remote_jid); | |
82 | |
83 void OnCertificatesSelected(net::CertificateList* selected_certs, | |
84 net::ClientCertStore* unused); | |
85 bool IsValidScope(const std::string& token_scope); | |
86 std::string ProcessResponse(); | |
87 | |
88 std::string post_body_; | |
89 scoped_ptr<net::URLRequest> request_; | |
90 scoped_refptr<net::IOBuffer> buffer_; | |
91 std::string data_; | |
92 ThirdPartyAuthConfig third_party_auth_config_; | |
93 scoped_refptr<RsaKeyPair> key_pair_; | |
94 std::string token_scope_; | |
95 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; | |
96 base::Callback<void(const std::string& shared_secret)> on_token_validated_; | |
97 | |
98 base::WeakPtrFactory<TokenValidatorImpl> weak_factory_; | |
99 | |
100 DISALLOW_COPY_AND_ASSIGN(TokenValidatorImpl); | |
101 }; | |
102 | |
103 TokenValidatorImpl::TokenValidatorImpl( | |
104 const ThirdPartyAuthConfig& third_party_auth_config, | 45 const ThirdPartyAuthConfig& third_party_auth_config, |
105 scoped_refptr<RsaKeyPair> key_pair, | 46 const std::string& token_scope, |
106 const std::string& local_jid, | |
107 const std::string& remote_jid, | |
108 scoped_refptr<net::URLRequestContextGetter> request_context_getter) | 47 scoped_refptr<net::URLRequestContextGetter> request_context_getter) |
109 : buffer_(new net::IOBuffer(kBufferSize)), | 48 : third_party_auth_config_(third_party_auth_config), |
110 third_party_auth_config_(third_party_auth_config), | 49 token_scope_(token_scope), |
111 key_pair_(key_pair), | |
112 request_context_getter_(request_context_getter), | 50 request_context_getter_(request_context_getter), |
| 51 buffer_(new net::IOBuffer(kBufferSize)), |
113 weak_factory_(this) { | 52 weak_factory_(this) { |
114 DCHECK(third_party_auth_config_.token_url.is_valid()); | 53 DCHECK(third_party_auth_config_.token_url.is_valid()); |
115 DCHECK(third_party_auth_config_.token_validation_url.is_valid()); | 54 DCHECK(third_party_auth_config_.token_validation_url.is_valid()); |
116 DCHECK(key_pair_.get()); | |
117 token_scope_ = CreateScope(local_jid, remote_jid); | |
118 } | 55 } |
119 | 56 |
120 TokenValidatorImpl::~TokenValidatorImpl() { | 57 TokenValidatorBase::~TokenValidatorBase() { |
121 } | 58 } |
122 | 59 |
123 // TokenValidator interface. | 60 // TokenValidator interface. |
124 void TokenValidatorImpl::ValidateThirdPartyToken( | 61 void TokenValidatorBase::ValidateThirdPartyToken( |
125 const std::string& token, | 62 const std::string& token, |
126 const base::Callback<void( | 63 const base::Callback<void( |
127 const std::string& shared_secret)>& on_token_validated) { | 64 const std::string& shared_secret)>& on_token_validated) { |
128 DCHECK(!request_); | 65 DCHECK(!request_); |
129 DCHECK(!on_token_validated.is_null()); | 66 DCHECK(!on_token_validated.is_null()); |
130 | 67 |
131 on_token_validated_ = on_token_validated; | 68 on_token_validated_ = on_token_validated; |
132 | 69 |
133 post_body_ = "code=" + net::EscapeUrlEncodedData(token, true) + | 70 StartValidateRequest(token); |
134 "&client_id=" + net::EscapeUrlEncodedData( | |
135 key_pair_->GetPublicKey(), true) + | |
136 "&client_secret=" + net::EscapeUrlEncodedData( | |
137 key_pair_->SignMessage(token), true) + | |
138 "&grant_type=authorization_code"; | |
139 | |
140 request_ = request_context_getter_->GetURLRequestContext()->CreateRequest( | |
141 third_party_auth_config_.token_validation_url, net::DEFAULT_PRIORITY, | |
142 this); | |
143 request_->SetExtraRequestHeaderByName( | |
144 net::HttpRequestHeaders::kContentType, | |
145 "application/x-www-form-urlencoded", true); | |
146 request_->set_method("POST"); | |
147 scoped_ptr<net::UploadElementReader> reader( | |
148 new net::UploadBytesElementReader( | |
149 post_body_.data(), post_body_.size())); | |
150 request_->set_upload(make_scoped_ptr( | |
151 net::UploadDataStream::CreateWithReader(reader.Pass(), 0))); | |
152 request_->Start(); | |
153 } | 71 } |
154 | 72 |
155 const GURL& TokenValidatorImpl::token_url() const { | 73 const GURL& TokenValidatorBase::token_url() const { |
156 return third_party_auth_config_.token_url; | 74 return third_party_auth_config_.token_url; |
157 } | 75 } |
158 | 76 |
159 const std::string& TokenValidatorImpl::token_scope() const { | 77 const std::string& TokenValidatorBase::token_scope() const { |
160 return token_scope_; | 78 return token_scope_; |
161 } | 79 } |
162 | 80 |
163 // URLFetcherDelegate interface. | 81 // URLFetcherDelegate interface. |
164 void TokenValidatorImpl::OnResponseStarted(net::URLRequest* source) { | 82 void TokenValidatorBase::OnResponseStarted(net::URLRequest* source) { |
165 DCHECK_EQ(request_.get(), source); | 83 DCHECK_EQ(request_.get(), source); |
166 | 84 |
167 int bytes_read = 0; | 85 int bytes_read = 0; |
168 request_->Read(buffer_.get(), kBufferSize, &bytes_read); | 86 request_->Read(buffer_.get(), kBufferSize, &bytes_read); |
169 OnReadCompleted(request_.get(), bytes_read); | 87 OnReadCompleted(request_.get(), bytes_read); |
170 } | 88 } |
171 | 89 |
172 void TokenValidatorImpl::OnReadCompleted(net::URLRequest* source, | 90 void TokenValidatorBase::OnReadCompleted(net::URLRequest* source, |
173 int bytes_read) { | 91 int bytes_read) { |
174 DCHECK_EQ(request_.get(), source); | 92 DCHECK_EQ(request_.get(), source); |
175 | 93 |
176 do { | 94 do { |
177 if (!request_->status().is_success() || bytes_read <= 0) | 95 if (!request_->status().is_success() || bytes_read <= 0) |
178 break; | 96 break; |
179 | 97 |
180 data_.append(buffer_->data(), bytes_read); | 98 data_.append(buffer_->data(), bytes_read); |
181 } while (request_->Read(buffer_.get(), kBufferSize, &bytes_read)); | 99 } while (request_->Read(buffer_.get(), kBufferSize, &bytes_read)); |
182 | 100 |
183 const net::URLRequestStatus status = request_->status(); | 101 const net::URLRequestStatus status = request_->status(); |
184 | 102 |
185 if (!status.is_io_pending()) { | 103 if (!status.is_io_pending()) { |
186 std::string shared_token = ProcessResponse(); | 104 std::string shared_token = ProcessResponse(); |
187 request_.reset(); | 105 request_.reset(); |
188 on_token_validated_.Run(shared_token); | 106 on_token_validated_.Run(shared_token); |
189 } | 107 } |
190 } | 108 } |
191 | 109 |
192 void TokenValidatorImpl::OnCertificateRequested( | 110 void TokenValidatorBase::OnCertificateRequested( |
193 net::URLRequest* source, | 111 net::URLRequest* source, |
194 net::SSLCertRequestInfo* cert_request_info) { | 112 net::SSLCertRequestInfo* cert_request_info) { |
195 DCHECK_EQ(request_.get(), source); | 113 DCHECK_EQ(request_.get(), source); |
196 | 114 |
197 net::ClientCertStore* client_cert_store; | 115 net::ClientCertStore* client_cert_store; |
198 #if defined(USE_NSS) | 116 #if defined(USE_NSS) |
199 client_cert_store = new net::ClientCertStoreNSS( | 117 client_cert_store = new net::ClientCertStoreNSS( |
200 net::ClientCertStoreNSS::PasswordDelegateFactory()); | 118 net::ClientCertStoreNSS::PasswordDelegateFactory()); |
201 #elif defined(OS_WIN) | 119 #elif defined(OS_WIN) |
202 client_cert_store = new net::ClientCertStoreWin(); | 120 client_cert_store = new net::ClientCertStoreWin(); |
203 #elif defined(OS_MACOSX) | 121 #elif defined(OS_MACOSX) |
204 client_cert_store = new net::ClientCertStoreMac(); | 122 client_cert_store = new net::ClientCertStoreMac(); |
205 #else | 123 #else |
206 #error Unknown platform. | 124 #error Unknown platform. |
207 #endif | 125 #endif |
208 // The callback is uncancellable, and GetClientCert requires selected_certs | 126 // The callback is uncancellable, and GetClientCert requires selected_certs |
209 // and client_cert_store to stay alive until the callback is called. So we | 127 // and client_cert_store to stay alive until the callback is called. So we |
210 // must give it a WeakPtr for |this|, and ownership of the other parameters. | 128 // must give it a WeakPtr for |this|, and ownership of the other parameters. |
211 net::CertificateList* selected_certs(new net::CertificateList()); | 129 net::CertificateList* selected_certs(new net::CertificateList()); |
212 client_cert_store->GetClientCerts( | 130 client_cert_store->GetClientCerts( |
213 *cert_request_info, selected_certs, | 131 *cert_request_info, selected_certs, |
214 base::Bind(&TokenValidatorImpl::OnCertificatesSelected, | 132 base::Bind(&TokenValidatorBase::OnCertificatesSelected, |
215 weak_factory_.GetWeakPtr(), base::Owned(selected_certs), | 133 weak_factory_.GetWeakPtr(), base::Owned(selected_certs), |
216 base::Owned(client_cert_store))); | 134 base::Owned(client_cert_store))); |
217 } | 135 } |
218 | 136 |
219 void TokenValidatorImpl::OnCertificatesSelected( | 137 void TokenValidatorBase::OnCertificatesSelected( |
220 net::CertificateList* selected_certs, | 138 net::CertificateList* selected_certs, |
221 net::ClientCertStore* unused) { | 139 net::ClientCertStore* unused) { |
222 const std::string& issuer = | 140 const std::string& issuer = |
223 third_party_auth_config_.token_validation_cert_issuer; | 141 third_party_auth_config_.token_validation_cert_issuer; |
224 if (request_) { | 142 if (request_) { |
225 for (size_t i = 0; i < selected_certs->size(); ++i) { | 143 for (size_t i = 0; i < selected_certs->size(); ++i) { |
226 if (issuer == kCertIssuerWildCard || | 144 if (issuer == kCertIssuerWildCard || |
227 issuer == (*selected_certs)[i]->issuer().common_name) { | 145 issuer == (*selected_certs)[i]->issuer().common_name) { |
228 request_->ContinueWithCertificate((*selected_certs)[i]); | 146 request_->ContinueWithCertificate((*selected_certs)[i]); |
229 return; | 147 return; |
230 } | 148 } |
231 } | 149 } |
232 request_->ContinueWithCertificate(NULL); | 150 request_->ContinueWithCertificate(NULL); |
233 } | 151 } |
234 } | 152 } |
235 | 153 |
236 bool TokenValidatorImpl::IsValidScope(const std::string& token_scope) { | 154 bool TokenValidatorBase::IsValidScope(const std::string& token_scope) { |
237 // TODO(rmsousa): Deal with reordering/subsets/supersets/aliases/etc. | 155 // TODO(rmsousa): Deal with reordering/subsets/supersets/aliases/etc. |
238 return token_scope == token_scope_; | 156 return token_scope == token_scope_; |
239 } | 157 } |
240 | 158 |
241 std::string TokenValidatorImpl::CreateScope( | 159 std::string TokenValidatorBase::ProcessResponse() { |
242 const std::string& local_jid, | |
243 const std::string& remote_jid) { | |
244 std::string nonce_bytes; | |
245 crypto::RandBytes(WriteInto(&nonce_bytes, kNonceLength + 1), kNonceLength); | |
246 std::string nonce; | |
247 base::Base64Encode(nonce_bytes, &nonce); | |
248 return "client:" + remote_jid + " host:" + local_jid + " nonce:" + nonce; | |
249 } | |
250 | |
251 std::string TokenValidatorImpl::ProcessResponse() { | |
252 // Verify that we got a successful response. | 160 // Verify that we got a successful response. |
253 net::URLRequestStatus status = request_->status(); | 161 net::URLRequestStatus status = request_->status(); |
254 if (!status.is_success()) { | 162 if (!status.is_success()) { |
255 LOG(ERROR) << "Error validating token, status=" << status.status() | 163 LOG(ERROR) << "Error validating token, status=" << status.status() |
256 << " err=" << status.error(); | 164 << " err=" << status.error(); |
257 return std::string(); | 165 return std::string(); |
258 } | 166 } |
259 | 167 |
260 int response = request_->GetResponseCode(); | 168 int response = request_->GetResponseCode(); |
261 if (response != 200) { | 169 if (response != 200) { |
(...skipping 18 matching lines...) Expand all Loading... |
280 << "', expected: '" << token_scope_ <<"'."; | 188 << "', expected: '" << token_scope_ <<"'."; |
281 return std::string(); | 189 return std::string(); |
282 } | 190 } |
283 | 191 |
284 std::string shared_secret; | 192 std::string shared_secret; |
285 // Everything is valid, so return the shared secret to the caller. | 193 // Everything is valid, so return the shared secret to the caller. |
286 dict->GetStringWithoutPathExpansion("access_token", &shared_secret); | 194 dict->GetStringWithoutPathExpansion("access_token", &shared_secret); |
287 return shared_secret; | 195 return shared_secret; |
288 } | 196 } |
289 | 197 |
290 TokenValidatorFactoryImpl::TokenValidatorFactoryImpl( | |
291 const ThirdPartyAuthConfig& third_party_auth_config, | |
292 scoped_refptr<RsaKeyPair> key_pair, | |
293 scoped_refptr<net::URLRequestContextGetter> request_context_getter) | |
294 : third_party_auth_config_(third_party_auth_config), | |
295 key_pair_(key_pair), | |
296 request_context_getter_(request_context_getter) { | |
297 } | |
298 | |
299 TokenValidatorFactoryImpl::~TokenValidatorFactoryImpl() { | |
300 } | |
301 | |
302 scoped_ptr<protocol::ThirdPartyHostAuthenticator::TokenValidator> | |
303 TokenValidatorFactoryImpl::CreateTokenValidator( | |
304 const std::string& local_jid, | |
305 const std::string& remote_jid) { | |
306 return scoped_ptr<protocol::ThirdPartyHostAuthenticator::TokenValidator>( | |
307 new TokenValidatorImpl(third_party_auth_config_, | |
308 key_pair_, local_jid, remote_jid, | |
309 request_context_getter_)); | |
310 } | |
311 | |
312 } // namespace remoting | 198 } // namespace remoting |
OLD | NEW |