| 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/it2me/it2me_host.h" | 5 #include "remoting/host/it2me/it2me_host.h" |
| 6 | 6 |
| 7 #include <cstdint> | 7 #include <cstdint> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 host_context_->video_capture_task_runner(), | 92 host_context_->video_capture_task_runner(), |
| 93 host_context_->input_task_runner(), host_context_->ui_task_runner())); | 93 host_context_->input_task_runner(), host_context_->ui_task_runner())); |
| 94 | 94 |
| 95 // Start monitoring configured policies. | 95 // Start monitoring configured policies. |
| 96 policy_watcher_->StartWatching( | 96 policy_watcher_->StartWatching( |
| 97 base::Bind(&It2MeHost::OnPolicyUpdate, this), | 97 base::Bind(&It2MeHost::OnPolicyUpdate, this), |
| 98 base::Bind(&It2MeHost::OnPolicyError, this)); | 98 base::Bind(&It2MeHost::OnPolicyError, this)); |
| 99 | 99 |
| 100 // Switch to the network thread to start the actual connection. | 100 // Switch to the network thread to start the actual connection. |
| 101 host_context_->network_task_runner()->PostTask( | 101 host_context_->network_task_runner()->PostTask( |
| 102 FROM_HERE, base::Bind(&It2MeHost::ShowConfirmationPrompt, this)); | 102 FROM_HERE, base::Bind(&It2MeHost::ReadPolicyAndConnect, this)); |
| 103 } | 103 } |
| 104 | 104 |
| 105 void It2MeHost::Disconnect() { | 105 void It2MeHost::Disconnect() { |
| 106 DCHECK(task_runner_->BelongsToCurrentThread()); | 106 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 107 host_context_->network_task_runner()->PostTask( | 107 host_context_->network_task_runner()->PostTask( |
| 108 FROM_HERE, base::Bind(&It2MeHost::DisconnectOnNetworkThread, this)); | 108 FROM_HERE, base::Bind(&It2MeHost::DisconnectOnNetworkThread, this)); |
| 109 } | 109 } |
| 110 | 110 |
| 111 void It2MeHost::DisconnectOnNetworkThread() { | 111 void It2MeHost::DisconnectOnNetworkThread() { |
| 112 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); | 112 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 143 DCHECK(task_runner_->BelongsToCurrentThread()); | 143 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 144 host_context_->network_task_runner()->PostTask( | 144 host_context_->network_task_runner()->PostTask( |
| 145 FROM_HERE, base::Bind(&It2MeHost::RequestNatPolicy, this)); | 145 FROM_HERE, base::Bind(&It2MeHost::RequestNatPolicy, this)); |
| 146 return; | 146 return; |
| 147 } | 147 } |
| 148 | 148 |
| 149 if (policy_received_) | 149 if (policy_received_) |
| 150 UpdateNatPolicy(nat_traversal_enabled_); | 150 UpdateNatPolicy(nat_traversal_enabled_); |
| 151 } | 151 } |
| 152 | 152 |
| 153 void It2MeHost::ShowConfirmationPrompt() { | |
| 154 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); | |
| 155 | |
| 156 SetState(kStarting, ""); | |
| 157 | |
| 158 std::unique_ptr<It2MeConfirmationDialog> confirmation_dialog = | |
| 159 confirmation_dialog_factory_->Create(); | |
| 160 | |
| 161 // TODO(dcaiafa): Remove after dialog implementations for all platforms exist. | |
| 162 if (!confirmation_dialog) { | |
| 163 ReadPolicyAndConnect(); | |
| 164 return; | |
| 165 } | |
| 166 | |
| 167 confirmation_dialog_proxy_.reset( | |
| 168 new It2MeConfirmationDialogProxy(host_context_->ui_task_runner(), | |
| 169 std::move(confirmation_dialog))); | |
| 170 | |
| 171 confirmation_dialog_proxy_->Show( | |
| 172 base::Bind(&It2MeHost::OnConfirmationResult, base::Unretained(this))); | |
| 173 } | |
| 174 | |
| 175 void It2MeHost::OnConfirmationResult(It2MeConfirmationDialog::Result result) { | |
| 176 switch (result) { | |
| 177 case It2MeConfirmationDialog::Result::OK: | |
| 178 ReadPolicyAndConnect(); | |
| 179 break; | |
| 180 | |
| 181 case It2MeConfirmationDialog::Result::CANCEL: | |
| 182 DisconnectOnNetworkThread(); | |
| 183 break; | |
| 184 | |
| 185 default: | |
| 186 NOTREACHED(); | |
| 187 return; | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 void It2MeHost::ReadPolicyAndConnect() { | 153 void It2MeHost::ReadPolicyAndConnect() { |
| 192 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); | 154 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
| 193 DCHECK_EQ(kStarting, state_); | 155 DCHECK_EQ(kDisconnected, state_); |
| 156 |
| 157 SetState(kStarting, ""); |
| 194 | 158 |
| 195 // Only proceed to FinishConnect() if at least one policy update has been | 159 // Only proceed to FinishConnect() if at least one policy update has been |
| 196 // received. | 160 // received. Otherwise, create the policy watcher and thunk the connect. |
| 197 if (policy_received_) { | 161 if (policy_received_) { |
| 198 FinishConnect(); | 162 FinishConnect(); |
| 199 } else { | 163 } else { |
| 200 // Otherwise, create the policy watcher, and thunk the connect. | 164 pending_connect_ = base::Bind(&It2MeHost::FinishConnect, this); |
| 201 pending_connect_ = | |
| 202 base::Bind(&It2MeHost::FinishConnect, this); | |
| 203 } | 165 } |
| 204 } | 166 } |
| 205 | 167 |
| 206 void It2MeHost::FinishConnect() { | 168 void It2MeHost::FinishConnect() { |
| 207 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); | 169 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
| 208 | 170 |
| 209 if (state_ != kStarting) { | 171 if (state_ != kStarting) { |
| 210 // Host has been stopped while we were fetching policy. | 172 // Host has been stopped while we were fetching policy. |
| 211 return; | 173 return; |
| 212 } | 174 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 } | 266 } |
| 305 } | 267 } |
| 306 | 268 |
| 307 void It2MeHost::OnClientConnected(const std::string& jid) { | 269 void It2MeHost::OnClientConnected(const std::string& jid) { |
| 308 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); | 270 DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
| 309 | 271 |
| 310 // ChromotingHost doesn't allow multiple concurrent connection and the | 272 // ChromotingHost doesn't allow multiple concurrent connection and the |
| 311 // host is destroyed in OnClientDisconnected() after the first connection. | 273 // host is destroyed in OnClientDisconnected() after the first connection. |
| 312 CHECK_NE(state_, kConnected); | 274 CHECK_NE(state_, kConnected); |
| 313 | 275 |
| 314 std::string client_username = jid; | 276 std::string client_username; |
| 315 size_t pos = client_username.find('/'); | 277 if (!SplitJidResource(jid, &client_username, /*resource=*/nullptr)) { |
| 316 if (pos != std::string::npos) | 278 LOG(WARNING) << "Incorrectly formatted JID received: " << jid; |
| 317 client_username.replace(pos, std::string::npos, ""); | 279 client_username = jid; |
| 280 } |
| 318 | 281 |
| 319 HOST_LOG << "Client " << client_username << " connected."; | 282 HOST_LOG << "Client " << client_username << " connected."; |
| 320 | 283 |
| 321 // Pass the client user name to the script object before changing state. | 284 // Pass the client user name to the script object before changing state. |
| 322 task_runner_->PostTask( | 285 task_runner_->PostTask( |
| 323 FROM_HERE, base::Bind(&It2MeHost::Observer::OnClientAuthenticated, | 286 FROM_HERE, base::Bind(&It2MeHost::Observer::OnClientAuthenticated, |
| 324 observer_, client_username)); | 287 observer_, client_username)); |
| 325 | 288 |
| 326 SetState(kConnected, ""); | 289 SetState(kConnected, ""); |
| 327 } | 290 } |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 task_runner_->PostTask( | 478 task_runner_->PostTask( |
| 516 FROM_HERE, base::Bind(&It2MeHost::Observer::OnStoreAccessCode, | 479 FROM_HERE, base::Bind(&It2MeHost::Observer::OnStoreAccessCode, |
| 517 observer_, access_code, lifetime)); | 480 observer_, access_code, lifetime)); |
| 518 | 481 |
| 519 SetState(kReceivedAccessCode, ""); | 482 SetState(kReceivedAccessCode, ""); |
| 520 } | 483 } |
| 521 | 484 |
| 522 void It2MeHost::ValidateConnectionDetails( | 485 void It2MeHost::ValidateConnectionDetails( |
| 523 const std::string& remote_jid, | 486 const std::string& remote_jid, |
| 524 const protocol::ValidatingAuthenticator::ResultCallback& result_callback) { | 487 const protocol::ValidatingAuthenticator::ResultCallback& result_callback) { |
| 488 // First ensure the JID we received is valid. |
| 489 std::string client_username; |
| 490 if (!SplitJidResource(remote_jid, &client_username, /*resource=*/nullptr)) { |
| 491 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid |
| 492 << ": Invalid JID."; |
| 493 result_callback.Run( |
| 494 protocol::ValidatingAuthenticator::Result::ERROR_INVALID_ACCOUNT); |
| 495 return; |
| 496 } |
| 497 |
| 498 if (client_username.empty()) { |
| 499 LOG(ERROR) << "Invalid user name passed in: " << remote_jid; |
| 500 result_callback.Run( |
| 501 protocol::ValidatingAuthenticator::Result::ERROR_INVALID_ACCOUNT); |
| 502 return; |
| 503 } |
| 504 |
| 525 // Check the client domain policy. | 505 // Check the client domain policy. |
| 526 if (!required_client_domain_.empty()) { | 506 if (!required_client_domain_.empty()) { |
| 527 std::string client_username; | |
| 528 if (!SplitJidResource(remote_jid, &client_username, /*resource=*/nullptr)) { | |
| 529 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid | |
| 530 << ": Invalid JID."; | |
| 531 result_callback.Run(ValidationResult::ERROR_INVALID_ACCOUNT); | |
| 532 return; | |
| 533 } | |
| 534 if (!base::EndsWith(client_username, | 507 if (!base::EndsWith(client_username, |
| 535 std::string("@") + required_client_domain_, | 508 std::string("@") + required_client_domain_, |
| 536 base::CompareCase::INSENSITIVE_ASCII)) { | 509 base::CompareCase::INSENSITIVE_ASCII)) { |
| 537 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid | 510 LOG(ERROR) << "Rejecting incoming connection from " << remote_jid |
| 538 << ": Domain mismatch."; | 511 << ": Domain mismatch."; |
| 539 result_callback.Run(ValidationResult::ERROR_INVALID_ACCOUNT); | 512 result_callback.Run(ValidationResult::ERROR_INVALID_ACCOUNT); |
| 540 return; | 513 return; |
| 541 } | 514 } |
| 542 } | 515 } |
| 543 | 516 |
| 544 result_callback.Run(ValidationResult::SUCCESS); | 517 // Show a confirmation dialog to the user to allow them to confirm/reject it. |
| 518 std::unique_ptr<It2MeConfirmationDialog> confirmation_dialog = |
| 519 confirmation_dialog_factory_->Create(); |
| 520 |
| 521 // TODO(joedow): Remove this once confirmation dialog exists on all platforms. |
| 522 if (!confirmation_dialog) { |
| 523 result_callback.Run(ValidationResult::SUCCESS); |
| 524 return; |
| 525 } |
| 526 |
| 527 confirmation_dialog_proxy_.reset(new It2MeConfirmationDialogProxy( |
| 528 host_context_->ui_task_runner(), std::move(confirmation_dialog))); |
| 529 |
| 530 confirmation_dialog_proxy_->Show( |
| 531 client_username, base::Bind(&It2MeHost::OnConfirmationResult, |
| 532 base::Unretained(this), result_callback)); |
| 533 } |
| 534 |
| 535 void It2MeHost::OnConfirmationResult( |
| 536 const protocol::ValidatingAuthenticator::ResultCallback& result_callback, |
| 537 It2MeConfirmationDialog::Result result) { |
| 538 switch (result) { |
| 539 case It2MeConfirmationDialog::Result::OK: |
| 540 result_callback.Run(ValidationResult::SUCCESS); |
| 541 break; |
| 542 |
| 543 case It2MeConfirmationDialog::Result::CANCEL: |
| 544 result_callback.Run(ValidationResult::ERROR_REJECTED_BY_USER); |
| 545 break; |
| 546 } |
| 545 } | 547 } |
| 546 | 548 |
| 547 It2MeHostFactory::It2MeHostFactory() {} | 549 It2MeHostFactory::It2MeHostFactory() {} |
| 548 | 550 |
| 549 It2MeHostFactory::~It2MeHostFactory() {} | 551 It2MeHostFactory::~It2MeHostFactory() {} |
| 550 | 552 |
| 551 scoped_refptr<It2MeHost> It2MeHostFactory::CreateIt2MeHost( | 553 scoped_refptr<It2MeHost> It2MeHostFactory::CreateIt2MeHost( |
| 552 std::unique_ptr<ChromotingHostContext> context, | 554 std::unique_ptr<ChromotingHostContext> context, |
| 553 policy::PolicyService* policy_service, | 555 policy::PolicyService* policy_service, |
| 554 base::WeakPtr<It2MeHost::Observer> observer, | 556 base::WeakPtr<It2MeHost::Observer> observer, |
| 555 const XmppSignalStrategy::XmppServerConfig& xmpp_server_config, | 557 const XmppSignalStrategy::XmppServerConfig& xmpp_server_config, |
| 556 const std::string& directory_bot_jid) { | 558 const std::string& directory_bot_jid) { |
| 557 DCHECK(context->ui_task_runner()->BelongsToCurrentThread()); | 559 DCHECK(context->ui_task_runner()->BelongsToCurrentThread()); |
| 558 | 560 |
| 559 std::unique_ptr<It2MeConfirmationDialogFactory> confirmation_dialog_factory( | 561 std::unique_ptr<It2MeConfirmationDialogFactory> confirmation_dialog_factory( |
| 560 new It2MeConfirmationDialogFactory()); | 562 new It2MeConfirmationDialogFactory()); |
| 561 std::unique_ptr<PolicyWatcher> policy_watcher = | 563 std::unique_ptr<PolicyWatcher> policy_watcher = |
| 562 PolicyWatcher::Create(policy_service, context->file_task_runner()); | 564 PolicyWatcher::Create(policy_service, context->file_task_runner()); |
| 563 return new It2MeHost(std::move(context), std::move(policy_watcher), | 565 return new It2MeHost(std::move(context), std::move(policy_watcher), |
| 564 std::move(confirmation_dialog_factory), observer, | 566 std::move(confirmation_dialog_factory), observer, |
| 565 xmpp_server_config, directory_bot_jid); | 567 xmpp_server_config, directory_bot_jid); |
| 566 } | 568 } |
| 567 | 569 |
| 568 } // namespace remoting | 570 } // namespace remoting |
| OLD | NEW |