1 // Copyright (c) 2012 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 // This file implements a standalone host process for Me2Me. 6 7 #include <string> 8 9 #include "base/at_exit.h" 10 #include "base/bind.h" 11 #include "base/callback.h" 12 #include "base/command_line.h" 13 #include "base/debug/alias.h" 14 #include "base/files/file_path.h" 15 #include "base/files/file_util.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "base/message_loop/message_loop.h" 18 #include "base/single_thread_task_runner.h" 19 #include "base/strings/string_number_conversions.h" 20 #include "base/strings/string_util.h" 21 #include "base/strings/utf_string_conversions.h" 22 #include "base/synchronization/waitable_event.h" 23 #include "base/threading/thread.h" 24 #include "build/build_config.h" 25 #include "crypto/nss_util.h" 26 #include "ipc/ipc_channel.h" 27 #include "ipc/ipc_channel_proxy.h" 28 #include "ipc/ipc_listener.h" 29 #include "media/base/media.h" 30 #include "net/base/network_change_notifier.h" 31 #include "net/socket/client_socket_factory.h" 32 #include "net/socket/ssl_server_socket.h" 33 #include "net/url_request/url_fetcher.h" 34 #include "remoting/base/auto_thread_task_runner.h" 35 #include "remoting/base/breakpad.h" 36 #include "remoting/base/constants.h" 37 #include "remoting/base/logging.h" 38 #include "remoting/base/rsa_key_pair.h" 39 #include "remoting/base/service_urls.h" 40 #include "remoting/base/util.h" 41 #include "remoting/host/branding.h" 42 #include "remoting/host/chromoting_host.h" 43 #include "remoting/host/chromoting_host_context.h" 44 #include "remoting/host/chromoting_messages.h" 45 #include "remoting/host/config_file_watcher.h" 46 #include "remoting/host/config_watcher.h" 47 #include "remoting/host/desktop_environment.h" 48 #include "remoting/host/desktop_session_connector.h" 49 #include "remoting/host/dns_blackhole_checker.h" 50 #include "remoting/host/heartbeat_sender.h" 51 #include "remoting/host/host_change_notification_listener.h" 52 #include "remoting/host/host_config.h" 53 #include "remoting/host/host_event_logger.h" 54 #include "remoting/host/host_exit_codes.h" 55 #include "remoting/host/host_main.h" 56 #include "remoting/host/host_status_logger.h" 57 #include "remoting/host/host_status_sender.h" 58 #include "remoting/host/ipc_constants.h" 59 #include "remoting/host/ipc_desktop_environment.h" 60 #include "remoting/host/ipc_host_event_logger.h" 61 #include "remoting/host/json_host_config.h" 62 #include "remoting/host/logging.h" 63 #include "remoting/host/me2me_desktop_environment.h" 64 #include "remoting/host/pairing_registry_delegate.h" 65 #include "remoting/host/policy_hack/policy_watcher.h" 66 #include "remoting/host/session_manager_factory.h" 67 #include "remoting/host/signaling_connector.h" 68 #include "remoting/host/single_window_desktop_environment.h" 69 #include "remoting/host/token_validator_factory_impl.h" 70 #include "remoting/host/usage_stats_consent.h" 71 #include "remoting/host/username.h" 72 #include "remoting/host/video_frame_recorder_host_extension.h" 73 #include "remoting/protocol/me2me_host_authenticator_factory.h" 74 #include "remoting/protocol/network_settings.h" 75 #include "remoting/protocol/pairing_registry.h" 76 #include "remoting/protocol/token_validator.h" 77 #include "remoting/signaling/xmpp_signal_strategy.h" 78 79 #if defined(OS_POSIX) 80 #include <signal.h> 81 #include <sys/types.h> 82 #include <unistd.h> 83 #include "base/file_descriptor_posix.h" 84 #include "remoting/host/pam_authorization_factory_posix.h" 85 #include "remoting/host/posix/signal_handler.h" 86 #endif // defined(OS_POSIX) 87 88 #if defined(OS_MACOSX) 89 #include "base/mac/scoped_cftyperef.h" 90 #endif // defined(OS_MACOSX) 91 92 #if defined(OS_LINUX) 93 #include <gtk/gtk.h> 94 #include <X11/Xlib.h> 95 #include "remoting/host/audio_capturer_linux.h" 96 #endif // defined(OS_LINUX) 97 98 #if defined(OS_WIN) 99 #include <commctrl.h> 100 #include "base/win/registry.h" 101 #include "base/win/scoped_handle.h" 102 #include "remoting/host/pairing_registry_delegate_win.h" 103 #include "remoting/host/win/session_desktop_environment.h" 104 #endif // defined(OS_WIN) 105 106 using remoting::protocol::PairingRegistry; 107 using remoting::protocol::NetworkSettings; 108 109 namespace { 110 111 // This is used for tagging system event logs. 112 const char kApplicationName[] = "chromoting"; 113 114 #if defined(OS_LINUX) 115 // The command line switch used to pass name of the pipe to capture audio on 116 // linux. 117 const char kAudioPipeSwitchName[] = "audio-pipe-name"; 118 119 // The command line switch used to pass name of the unix domain socket used to 120 // listen for gnubby requests. 121 const char kAuthSocknameSwitchName[] = "ssh-auth-sockname"; 122 #endif // defined(OS_LINUX) 123 124 // The command line switch used by the parent to request the host to signal it 125 // when it is successfully started. 126 const char kSignalParentSwitchName[] = "signal-parent"; 127 128 // Command line switch used to enable VP9 encoding. 129 const char kEnableVp9SwitchName[] = "enable-vp9"; 130 131 // Command line switch used to enable and configure the frame-recorder. 132 const char kFrameRecorderBufferKbName[] = "frame-recorder-buffer-kb"; 133 134 // Value used for --host-config option to indicate that the path must be read 135 // from stdin. 136 const char kStdinConfigPath[] = "-"; 137 138 const char kWindowIdSwitchName[] = "window-id"; 139 140 } // namespace 141 142 namespace remoting { 143 144 class HostProcess 145 : public ConfigWatcher::Delegate, 146 public HeartbeatSender::Listener, 147 public HostChangeNotificationListener::Listener, 148 public IPC::Listener, 149 public base::RefCountedThreadSafe<HostProcess> { 150 public: 151 HostProcess(scoped_ptr<ChromotingHostContext> context, 152 int* exit_code_out); 153 154 // ConfigWatcher::Delegate interface. 155 virtual void OnConfigUpdated(const std::string& serialized_config) OVERRIDE; 156 virtual void OnConfigWatcherError() OVERRIDE; 157 158 // IPC::Listener implementation. 159 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 160 virtual void OnChannelError() OVERRIDE; 161 162 // HeartbeatSender::Listener overrides. 163 virtual void OnHeartbeatSuccessful() OVERRIDE; 164 virtual void OnUnknownHostIdError() OVERRIDE; 165 166 // HostChangeNotificationListener::Listener overrides. 167 virtual void OnHostDeleted() OVERRIDE; 168 169 // Initializes the pairing registry on Windows. 170 void OnInitializePairingRegistry( 171 IPC::PlatformFileForTransit privileged_key, 172 IPC::PlatformFileForTransit unprivileged_key); 173 174 private: 175 enum HostState { 176 // Host process has just been started. Waiting for config and policies to be 177 // read from the disk. 178 HOST_INITIALIZING, 179 180 // Host is started and running. 181 HOST_STARTED, 182 183 // Host is being stopped and will need to be started again. 184 HOST_STOPPING_TO_RESTART, 185 186 // Host is being stopped. 187 HOST_STOPPING, 188 189 // Host has been stopped. 190 HOST_STOPPED, 191 192 // Allowed state transitions: 193 // INITIALIZING->STARTED 194 // INITIALIZING->STOPPED 195 // STARTED->STOPPING_TO_RESTART 196 // STARTED->STOPPING 197 // STOPPING_TO_RESTART->STARTED 198 // STOPPING_TO_RESTART->STOPPING 199 // STOPPING->STOPPED 200 // STOPPED->STARTED 201 // 202 // |host_| must be NULL in INITIALIZING and STOPPED states and not-NULL in 203 // all other states. 204 }; 205 206 friend class base::RefCountedThreadSafe<HostProcess>; 207 virtual ~HostProcess(); 208 209 void StartOnNetworkThread(); 210 211 #if defined(OS_POSIX) 212 // Callback passed to RegisterSignalHandler() to handle SIGTERM events. 213 void SigTermHandler(int signal_number); 214 #endif 215 216 // Called to initialize resources on the UI thread. 217 void StartOnUiThread(); 218 219 // Initializes IPC control channel and config file path from |cmd_line|. 220 // Called on the UI thread. 221 bool InitWithCommandLine(const base::CommandLine* cmd_line); 222 223 // Called on the UI thread to start monitoring the configuration file. 224 void StartWatchingConfigChanges(); 225 226 // Called on the network thread to set the host's Authenticator factory. 227 void CreateAuthenticatorFactory(); 228 229 // Tear down resources that run on the UI thread. 230 void ShutdownOnUiThread(); 231 232 // Applies the host config, returning true if successful. 233 bool ApplyConfig(scoped_ptr<JsonHostConfig> config); 234 235 // Handles policy updates, by calling On*PolicyUpdate methods. 236 void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies); 237 void ApplyHostDomainPolicy(); 238 void ApplyUsernamePolicy(); 239 bool OnHostDomainPolicyUpdate(base::DictionaryValue* policies); 240 bool OnUsernamePolicyUpdate(base::DictionaryValue* policies); 241 bool OnNatPolicyUpdate(base::DictionaryValue* policies); 242 bool OnRelayPolicyUpdate(base::DictionaryValue* policies); 243 bool OnUdpPortPolicyUpdate(base::DictionaryValue* policies); 244 bool OnCurtainPolicyUpdate(base::DictionaryValue* policies); 245 bool OnHostTalkGadgetPrefixPolicyUpdate(base::DictionaryValue* policies); 246 bool OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies); 247 bool OnPairingPolicyUpdate(base::DictionaryValue* policies); 248 bool OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies); 249 250 void StartHost(); 251 252 void OnAuthFailed(); 253 254 void RestartHost(); 255 256 // Stops the host and shuts down the process with the specified |exit_code|. 257 void ShutdownHost(HostExitCodes exit_code); 258 259 void ScheduleHostShutdown(); 260 261 void ShutdownOnNetworkThread(); 262 263 // Crashes the process in response to a daemon's request. The daemon passes 264 // the location of the code that detected the fatal error resulted in this 265 // request. 266 void OnCrash(const std::string& function_name, 267 const std::string& file_name, 268 const int& line_number); 269 270 scoped_ptr<ChromotingHostContext> context_; 271 272 // Created on the UI thread but used from the network thread. 273 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_; 274 275 // Accessed on the UI thread. 276 scoped_ptr<IPC::ChannelProxy> daemon_channel_; 277 278 // XMPP server/remoting bot configuration (initialized from the command line). 279 XmppSignalStrategy::XmppServerConfig xmpp_server_config_; 280 std::string directory_bot_jid_; 281 282 // Created on the UI thread but used from the network thread. 283 base::FilePath host_config_path_; 284 std::string host_config_; 285 scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_; 286 287 // Accessed on the network thread. 288 HostState state_; 289 290 scoped_ptr<ConfigWatcher> config_watcher_; 291 292 std::string host_id_; 293 protocol::SharedSecretHash host_secret_hash_; 294 scoped_refptr<RsaKeyPair> key_pair_; 295 std::string oauth_refresh_token_; 296 std::string serialized_config_; 297 std::string host_owner_; 298 std::string host_owner_email_; 299 bool use_service_account_; 300 bool enable_vp9_; 301 int64_t frame_recorder_buffer_size_; 302 303 scoped_ptr<policy_hack::PolicyWatcher> policy_watcher_; 304 std::string host_domain_; 305 bool host_username_match_required_; 306 bool allow_nat_traversal_; 307 bool allow_relay_; 308 int min_udp_port_; 309 int max_udp_port_; 310 std::string talkgadget_prefix_; 311 bool allow_pairing_; 312 313 bool curtain_required_; 314 ThirdPartyAuthConfig third_party_auth_config_; 315 bool enable_gnubby_auth_; 316 317 // Boolean to change flow, where ncessary, if we're 318 // capturing a window instead of the entire desktop. 319 bool enable_window_capture_; 320 321 // Used to specify which window to stream, if enabled. 322 webrtc::WindowId window_id_; 323 324 scoped_ptr<OAuthTokenGetter> oauth_token_getter_; 325 scoped_ptr<XmppSignalStrategy> signal_strategy_; 326 scoped_ptr<SignalingConnector> signaling_connector_; 327 scoped_ptr<HeartbeatSender> heartbeat_sender_; 328 scoped_ptr<HostStatusSender> host_status_sender_; 329 scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_; 330 scoped_ptr<HostStatusLogger> host_status_logger_; 331 scoped_ptr<HostEventLogger> host_event_logger_; 332 333 scoped_ptr<ChromotingHost> host_; 334 335 // Used to keep this HostProcess alive until it is shutdown. 336 scoped_refptr<HostProcess> self_; 337 338 #if defined(REMOTING_MULTI_PROCESS) 339 DesktopSessionConnector* desktop_session_connector_; 340 #endif // defined(REMOTING_MULTI_PROCESS) 341 342 int* exit_code_out_; 343 bool signal_parent_; 344 345 scoped_ptr<PairingRegistry::Delegate> pairing_registry_delegate_; 346 }; 347 348 HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context, 349 int* exit_code_out) 350 : context_(context.Pass()), 351 state_(HOST_INITIALIZING), 352 use_service_account_(false), 353 enable_vp9_(false), 354 frame_recorder_buffer_size_(0), 355 host_username_match_required_(false), 356 allow_nat_traversal_(true), 357 allow_relay_(true), 358 min_udp_port_(0), 359 max_udp_port_(0), 360 allow_pairing_(true), 361 curtain_required_(false), 362 enable_gnubby_auth_(false), 363 enable_window_capture_(false), 364 window_id_(0), 365 #if defined(REMOTING_MULTI_PROCESS) 366 desktop_session_connector_(NULL), 367 #endif // defined(REMOTING_MULTI_PROCESS) 368 self_(this), 369 exit_code_out_(exit_code_out), 370 signal_parent_(false) { 371 StartOnUiThread(); 372 } 373 374 HostProcess::~HostProcess() { 375 // Verify that UI components have been torn down. 376 DCHECK(!config_watcher_); 377 DCHECK(!daemon_channel_); 378 DCHECK(!desktop_environment_factory_); 379 380 // We might be getting deleted on one of the threads the |host_context| owns, 381 // so we need to post it back to the caller thread to safely join & delete the 382 // threads it contains. This will go away when we move to AutoThread. 383 // |context_release()| will null |context_| before the method is invoked, so 384 // we need to pull out the task-runner on which to call DeleteSoon first. 385 scoped_refptr<base::SingleThreadTaskRunner> task_runner = 386 context_->ui_task_runner(); 387 task_runner->DeleteSoon(FROM_HERE, context_.release()); 388 } 389 390 bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) { 391 #if defined(REMOTING_MULTI_PROCESS) 392 // Parse the handle value and convert it to a handle/file descriptor. 393 std::string channel_name = 394 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName); 395 396 int pipe_handle = 0; 397 if (channel_name.empty() || 398 !base::StringToInt(channel_name, &pipe_handle)) { 399 LOG(ERROR) << "Invalid '" << kDaemonPipeSwitchName 400 << "' value: " << channel_name; 401 return false; 402 } 403 404 #if defined(OS_WIN) 405 base::win::ScopedHandle pipe(reinterpret_cast<HANDLE>(pipe_handle)); 406 IPC::ChannelHandle channel_handle(pipe.Get()); 407 #elif defined(OS_POSIX) 408 base::FileDescriptor pipe(pipe_handle, true); 409 IPC::ChannelHandle channel_handle(channel_name, pipe); 410 #endif // defined(OS_POSIX) 411 412 // Connect to the daemon process. 413 daemon_channel_ = IPC::ChannelProxy::Create(channel_handle, 414 IPC::Channel::MODE_CLIENT, 415 this, 416 context_->network_task_runner()); 417 #else // !defined(REMOTING_MULTI_PROCESS) 418 // Connect to the daemon process. 419 std::string channel_name = 420 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName); 421 if (!channel_name.empty()) { 422 daemon_channel_ = 423 IPC::ChannelProxy::Create(channel_name, 424 IPC::Channel::MODE_CLIENT, 425 this, 426 context_->network_task_runner().get()); 427 } 428 429 if (cmd_line->HasSwitch(kHostConfigSwitchName)) { 430 host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName); 431 432 // Read config from stdin if necessary. 433 if (host_config_path_ == base::FilePath(kStdinConfigPath)) { 434 char buf[4096]; 435 size_t len; 436 while ((len = fread(buf, 1, sizeof(buf), stdin)) > 0) { 437 host_config_.append(buf, len); 438 } 439 } 440 } else { 441 base::FilePath default_config_dir = remoting::GetConfigDir(); 442 host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile); 443 } 444 445 if (host_config_path_ != base::FilePath(kStdinConfigPath) && 446 !base::PathExists(host_config_path_)) { 447 LOG(ERROR) << "Can't find host config at " << host_config_path_.value(); 448 return false; 449 } 450 #endif // !defined(REMOTING_MULTI_PROCESS) 451 452 // Ignore certificate requests - the host currently has no client certificate 453 // support, so ignoring certificate requests allows connecting to servers that 454 // request, but don't require, a certificate (optional client authentication). 455 net::URLFetcher::SetIgnoreCertificateRequests(true); 456 457 ServiceUrls* service_urls = ServiceUrls::GetInstance(); 458 bool xmpp_server_valid = net::ParseHostAndPort( 459 service_urls->xmpp_server_address(), 460 &xmpp_server_config_.host, &xmpp_server_config_.port); 461 if (!xmpp_server_valid) { 462 LOG(ERROR) << "Invalid XMPP server: " << 463 service_urls->xmpp_server_address(); 464 return false; 465 } 466 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls(); 467 directory_bot_jid_ = service_urls->directory_bot_jid(); 468 469 signal_parent_ = cmd_line->HasSwitch(kSignalParentSwitchName); 470 471 enable_window_capture_ = cmd_line->HasSwitch(kWindowIdSwitchName); 472 if (enable_window_capture_) { 473 474 #if defined(OS_LINUX) || defined(OS_WIN) 475 LOG(WARNING) << "Window capturing is not fully supported on Linux or " 476 "Windows."; 477 #endif // defined(OS_LINUX) || defined(OS_WIN) 478 479 // uint32_t is large enough to hold window IDs on all platforms. 480 uint32_t window_id; 481 if (base::StringToUint( 482 cmd_line->GetSwitchValueASCII(kWindowIdSwitchName), 483 &window_id)) { 484 window_id_ = static_cast<webrtc::WindowId>(window_id); 485 } else { 486 LOG(ERROR) << "Window with window id: " << window_id_ 487 << " not found. Shutting down host."; 488 return false; 489 } 490 } 491 return true; 492 } 493 494 void HostProcess::OnConfigUpdated( 495 const std::string& serialized_config) { 496 if (!context_->network_task_runner()->BelongsToCurrentThread()) { 497 context_->network_task_runner()->PostTask(FROM_HERE, 498 base::Bind(&HostProcess::OnConfigUpdated, this, serialized_config)); 499 return; 500 } 501 502 // Filter out duplicates. 503 if (serialized_config_ == serialized_config) 504 return; 505 506 HOST_LOG << "Processing new host configuration."; 507 508 serialized_config_ = serialized_config; 509 scoped_ptr<JsonHostConfig> config(new JsonHostConfig(base::FilePath())); 510 if (!config->SetSerializedData(serialized_config)) { 511 LOG(ERROR) << "Invalid configuration."; 512 ShutdownHost(kInvalidHostConfigurationExitCode); 513 return; 514 } 515 516 if (!ApplyConfig(config.Pass())) { 517 LOG(ERROR) << "Failed to apply the configuration."; 518 ShutdownHost(kInvalidHostConfigurationExitCode); 519 return; 520 } 521 522 if (state_ == HOST_INITIALIZING) { 523 // TODO(sergeyu): Currently OnPolicyUpdate() assumes that host config is 524 // already loaded so PolicyWatcher has to be started here. Separate policy 525 // loading from policy verifications and move |policy_watcher_| 526 // initialization to StartOnNetworkThread(). 527 policy_watcher_.reset( 528 policy_hack::PolicyWatcher::Create(context_->file_task_runner())); 529 policy_watcher_->StartWatching( 530 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this))); 531 } else { 532 // Reapply policies that could be affected by a new config. 533 ApplyHostDomainPolicy(); 534 ApplyUsernamePolicy(); 535 536 if (state_ == HOST_STARTED) { 537 // TODO(sergeyu): Here we assume that PIN is the only part of the config 538 // that may change while the service is running. Change ApplyConfig() to 539 // detect other changes in the config and restart host if necessary here. 540 CreateAuthenticatorFactory(); 541 } 542 } 543 } 544 545 void HostProcess::OnConfigWatcherError() { 546 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 547 ShutdownHost(kInvalidHostConfigurationExitCode); 548 } 549 550 void HostProcess::StartOnNetworkThread() { 551 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 552 553 #if !defined(REMOTING_MULTI_PROCESS) 554 if (host_config_path_ == base::FilePath(kStdinConfigPath)) { 555 // Process config we've read from stdin. 556 OnConfigUpdated(host_config_); 557 } else { 558 // Start watching the host configuration file. 559 config_watcher_.reset(new ConfigFileWatcher(context_->network_task_runner(), 560 context_->file_task_runner(), 561 host_config_path_)); 562 config_watcher_->Watch(this); 563 } 564 #endif // !defined(REMOTING_MULTI_PROCESS) 565 566 #if defined(OS_POSIX) 567 remoting::RegisterSignalHandler( 568 SIGTERM, 569 base::Bind(&HostProcess::SigTermHandler, base::Unretained(this))); 570 #endif // defined(OS_POSIX) 571 } 572 573 #if defined(OS_POSIX) 574 void HostProcess::SigTermHandler(int signal_number) { 575 DCHECK(signal_number == SIGTERM); 576 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 577 HOST_LOG << "Caught SIGTERM: Shutting down..."; 578 ShutdownHost(kSuccessExitCode); 579 } 580 #endif // OS_POSIX 581 582 void HostProcess::CreateAuthenticatorFactory() { 583 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 584 585 if (state_ != HOST_STARTED) 586 return; 587 588 std::string local_certificate = key_pair_->GenerateCertificate(); 589 if (local_certificate.empty()) { 590 LOG(ERROR) << "Failed to generate host certificate."; 591 ShutdownHost(kInitializationFailed); 592 return; 593 } 594 595 scoped_refptr<PairingRegistry> pairing_registry = NULL; 596 if (allow_pairing_) { 597 if (!pairing_registry_delegate_) 598 pairing_registry_delegate_ = CreatePairingRegistryDelegate(); 599 600 if (pairing_registry_delegate_) { 601 pairing_registry = new PairingRegistry(context_->file_task_runner(), 602 pairing_registry_delegate_.Pass()); 603 } 604 } 605 606 scoped_ptr<protocol::AuthenticatorFactory> factory; 607 608 if (third_party_auth_config_.is_empty()) { 609 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret( 610 use_service_account_, host_owner_, local_certificate, key_pair_, 611 host_secret_hash_, pairing_registry); 612 613 } else if (third_party_auth_config_.is_valid()) { 614 scoped_ptr<protocol::TokenValidatorFactory> token_validator_factory( 615 new TokenValidatorFactoryImpl( 616 third_party_auth_config_, 617 key_pair_, context_->url_request_context_getter())); 618 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth( 619 use_service_account_, host_owner_, local_certificate, key_pair_, 620 token_validator_factory.Pass()); 621 622 } else { 623 // TODO(rmsousa): If the policy is bad the host should not go online. It 624 // should keep running, but not connected, until the policies are fixed. 625 // Having it show up as online and then reject all clients is misleading. 626 LOG(ERROR) << "One of the third-party token URLs is empty or invalid. " 627 << "Host will reject all clients until policies are corrected. " 628 << "TokenUrl: " << third_party_auth_config_.token_url << ", " 629 << "TokenValidationUrl: " 630 << third_party_auth_config_.token_validation_url; 631 factory = protocol::Me2MeHostAuthenticatorFactory::CreateRejecting(); 632 } 633 634 #if defined(OS_POSIX) 635 // On Linux and Mac, perform a PAM authorization step after authentication. 636 factory.reset(new PamAuthorizationFactory(factory.Pass())); 637 #endif 638 host_->SetAuthenticatorFactory(factory.Pass()); 639 640 host_->set_pairing_registry(pairing_registry); 641 } 642 643 // IPC::Listener implementation. 644 bool HostProcess::OnMessageReceived(const IPC::Message& message) { 645 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread()); 646 647 #if defined(REMOTING_MULTI_PROCESS) 648 bool handled = true; 649 IPC_BEGIN_MESSAGE_MAP(HostProcess, message) 650 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash) 651 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration, 652 OnConfigUpdated) 653 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_InitializePairingRegistry, 654 OnInitializePairingRegistry) 655 IPC_MESSAGE_FORWARD( 656 ChromotingDaemonNetworkMsg_DesktopAttached, 657 desktop_session_connector_, 658 DesktopSessionConnector::OnDesktopSessionAgentAttached) 659 IPC_MESSAGE_FORWARD(ChromotingDaemonNetworkMsg_TerminalDisconnected, 660 desktop_session_connector_, 661 DesktopSessionConnector::OnTerminalDisconnected) 662 IPC_MESSAGE_UNHANDLED(handled = false) 663 IPC_END_MESSAGE_MAP() 664 665 CHECK(handled) << "Received unexpected IPC type: " << message.type(); 666 return handled; 667 668 #else // !defined(REMOTING_MULTI_PROCESS) 669 return false; 670 #endif // !defined(REMOTING_MULTI_PROCESS) 671 } 672 673 void HostProcess::OnChannelError() { 674 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread()); 675 676 // Shutdown the host if the daemon process disconnects the IPC channel. 677 context_->network_task_runner()->PostTask( 678 FROM_HERE, 679 base::Bind(&HostProcess::ShutdownHost, this, kSuccessExitCode)); 680 } 681 682 void HostProcess::StartOnUiThread() { 683 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread()); 684 685 if (!InitWithCommandLine(base::CommandLine::ForCurrentProcess())) { 686 // Shutdown the host if the command line is invalid. 687 context_->network_task_runner()->PostTask( 688 FROM_HERE, base::Bind(&HostProcess::ShutdownHost, this, 689 kUsageExitCode)); 690 return; 691 } 692 693 #if defined(OS_LINUX) 694 // If an audio pipe is specific on the command-line then initialize 695 // AudioCapturerLinux to capture from it. 696 base::FilePath audio_pipe_name = base::CommandLine::ForCurrentProcess()-> 697 GetSwitchValuePath(kAudioPipeSwitchName); 698 if (!audio_pipe_name.empty()) { 699 remoting::AudioCapturerLinux::InitializePipeReader( 700 context_->audio_task_runner(), audio_pipe_name); 701 } 702 703 base::FilePath gnubby_socket_name = base::CommandLine::ForCurrentProcess()-> 704 GetSwitchValuePath(kAuthSocknameSwitchName); 705 if (!gnubby_socket_name.empty()) 706 remoting::GnubbyAuthHandler::SetGnubbySocketName(gnubby_socket_name); 707 #endif // defined(OS_LINUX) 708 709 // Create a desktop environment factory appropriate to the build type & 710 // platform. 711 #if defined(OS_WIN) 712 IpcDesktopEnvironmentFactory* desktop_environment_factory = 713 new IpcDesktopEnvironmentFactory( 714 context_->audio_task_runner(), 715 context_->network_task_runner(), 716 context_->video_capture_task_runner(), 717 context_->network_task_runner(), 718 daemon_channel_.get()); 719 desktop_session_connector_ = desktop_environment_factory; 720 #else // !defined(OS_WIN) 721 DesktopEnvironmentFactory* desktop_environment_factory; 722 if (enable_window_capture_) { 723 desktop_environment_factory = 724 new SingleWindowDesktopEnvironmentFactory( 725 context_->network_task_runner(), 726 context_->input_task_runner(), 727 context_->ui_task_runner(), 728 window_id_); 729 } else { 730 desktop_environment_factory = 731 new Me2MeDesktopEnvironmentFactory( 732 context_->network_task_runner(), 733 context_->input_task_runner(), 734 context_->ui_task_runner()); 735 } 736 #endif // !defined(OS_WIN) 737 738 desktop_environment_factory_.reset(desktop_environment_factory); 739 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_); 740 741 context_->network_task_runner()->PostTask( 742 FROM_HERE, 743 base::Bind(&HostProcess::StartOnNetworkThread, this)); 744 } 745 746 void HostProcess::ShutdownOnUiThread() { 747 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread()); 748 749 // Tear down resources that need to be torn down on the UI thread. 750 network_change_notifier_.reset(); 751 daemon_channel_.reset(); 752 desktop_environment_factory_.reset(); 753 754 // It is now safe for the HostProcess to be deleted. 755 self_ = NULL; 756 757 #if defined(OS_LINUX) 758 // Cause the global AudioPipeReader to be freed, otherwise the audio 759 // thread will remain in-use and prevent the process from exiting. 760 // TODO(wez): DesktopEnvironmentFactory should own the pipe reader. 761 // See crbug.com/161373 and crbug.com/104544. 762 AudioCapturerLinux::InitializePipeReader(NULL, base::FilePath()); 763 #endif 764 } 765 766 // Overridden from HeartbeatSender::Listener 767 void HostProcess::OnUnknownHostIdError() { 768 LOG(ERROR) << "Host ID not found."; 769 ShutdownHost(kInvalidHostIdExitCode); 770 } 771 772 void HostProcess::OnHeartbeatSuccessful() { 773 HOST_LOG << "Host ready to receive connections."; 774 #if defined(OS_POSIX) 775 if (signal_parent_) { 776 kill(getppid(), SIGUSR1); 777 signal_parent_ = false; 778 } 779 #endif 780 } 781 782 void HostProcess::OnHostDeleted() { 783 LOG(ERROR) << "Host was deleted from the directory."; 784 ShutdownHost(kInvalidHostIdExitCode); 785 } 786 787 void HostProcess::OnInitializePairingRegistry( 788 IPC::PlatformFileForTransit privileged_key, 789 IPC::PlatformFileForTransit unprivileged_key) { 790 DCHECK(!pairing_registry_delegate_); 791 792 #if defined(OS_WIN) 793 // Initialize the pairing registry delegate. 794 scoped_ptr<PairingRegistryDelegateWin> delegate( 795 new PairingRegistryDelegateWin()); 796 bool result = delegate->SetRootKeys( 797 reinterpret_cast<HKEY>( 798 IPC::PlatformFileForTransitToPlatformFile(privileged_key)), 799 reinterpret_cast<HKEY>( 800 IPC::PlatformFileForTransitToPlatformFile(unprivileged_key))); 801 if (!result) 802 return; 803 804 pairing_registry_delegate_ = delegate.PassAs<PairingRegistry::Delegate>(); 805 #else // !defined(OS_WIN) 806 NOTREACHED(); 807 #endif // !defined(OS_WIN) 808 } 809 810 // Applies the host config, returning true if successful. 811 bool HostProcess::ApplyConfig(scoped_ptr<JsonHostConfig> config) { 812 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 813 814 if (!config->GetString(kHostIdConfigPath, &host_id_)) { 815 LOG(ERROR) << "host_id is not defined in the config."; 816 return false; 817 } 818 819 std::string key_base64; 820 if (!config->GetString(kPrivateKeyConfigPath, &key_base64)) { 821 LOG(ERROR) << "Private key couldn't be read from the config file."; 822 return false; 823 } 824 825 key_pair_ = RsaKeyPair::FromString(key_base64); 826 if (!key_pair_.get()) { 827 LOG(ERROR) << "Invalid private key in the config file."; 828 return false; 829 } 830 831 std::string host_secret_hash_string; 832 if (!config->GetString(kHostSecretHashConfigPath, 833 &host_secret_hash_string)) { 834 host_secret_hash_string = "plain:"; 835 } 836 837 if (!host_secret_hash_.Parse(host_secret_hash_string)) { 838 LOG(ERROR) << "Invalid host_secret_hash."; 839 return false; 840 } 841 842 // Use an XMPP connection to the Talk network for session signalling. 843 if (!config->GetString(kXmppLoginConfigPath, &xmpp_server_config_.username) || 844 !(config->GetString(kXmppAuthTokenConfigPath, 845 &xmpp_server_config_.auth_token) || 846 config->GetString(kOAuthRefreshTokenConfigPath, 847 &oauth_refresh_token_))) { 848 LOG(ERROR) << "XMPP credentials are not defined in the config."; 849 return false; 850 } 851 852 if (!oauth_refresh_token_.empty()) { 853 // SignalingConnector is responsible for getting OAuth token. 854 xmpp_server_config_.auth_token = ""; 855 xmpp_server_config_.auth_service = "oauth2"; 856 } else if (!config->GetString(kXmppAuthServiceConfigPath, 857 &xmpp_server_config_.auth_service)) { 858 // For the me2me host, we default to ClientLogin token for chromiumsync 859 // because earlier versions of the host had no HTTP stack with which to 860 // request an OAuth2 access token. 861 xmpp_server_config_.auth_service = kChromotingTokenDefaultServiceName; 862 } 863 864 if (config->GetString(kHostOwnerConfigPath, &host_owner_)) { 865 // Service account configs have a host_owner, different from the xmpp_login. 866 use_service_account_ = true; 867 } else { 868 // User credential configs only have an xmpp_login, which is also the owner. 869 host_owner_ = xmpp_server_config_.username; 870 use_service_account_ = false; 871 } 872 873 // For non-Gmail Google accounts, the owner base JID differs from the email. 874 // host_owner_ contains the base JID (used for authenticating clients), while 875 // host_owner_email contains the account's email (used for UI and logs). 876 if (!config->GetString(kHostOwnerEmailConfigPath, &host_owner_email_)) { 877 host_owner_email_ = host_owner_; 878 } 879 880 // Allow offering of VP9 encoding to be overridden by the command-line. 881 if (CommandLine::ForCurrentProcess()->HasSwitch(kEnableVp9SwitchName)) { 882 enable_vp9_ = true; 883 } else { 884 config->GetBoolean(kEnableVp9ConfigPath, &enable_vp9_); 885 } 886 887 // Allow the command-line to override the size of the frame recorder buffer. 888 std::string frame_recorder_buffer_kb; 889 if (CommandLine::ForCurrentProcess()->HasSwitch( 890 kFrameRecorderBufferKbName)) { 891 frame_recorder_buffer_kb = 892 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 893 kFrameRecorderBufferKbName); 894 } else { 895 config->GetString(kFrameRecorderBufferKbConfigPath, 896 &frame_recorder_buffer_kb); 897 } 898 if (!frame_recorder_buffer_kb.empty()) { 899 int buffer_kb = 0; 900 if (base::StringToInt(frame_recorder_buffer_kb, &buffer_kb)) { 901 frame_recorder_buffer_size_ = 1024LL * buffer_kb; 902 } 903 } 904 905 return true; 906 } 907 908 void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) { 909 if (!context_->network_task_runner()->BelongsToCurrentThread()) { 910 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind( 911 &HostProcess::OnPolicyUpdate, this, base::Passed(&policies))); 912 return; 913 } 914 915 bool restart_required = false; 916 restart_required |= OnHostDomainPolicyUpdate(policies.get()); 917 restart_required |= OnCurtainPolicyUpdate(policies.get()); 918 // Note: UsernamePolicyUpdate must run after OnCurtainPolicyUpdate. 919 restart_required |= OnUsernamePolicyUpdate(policies.get()); 920 restart_required |= OnNatPolicyUpdate(policies.get()); 921 restart_required |= OnRelayPolicyUpdate(policies.get()); 922 restart_required |= OnUdpPortPolicyUpdate(policies.get()); 923 restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(policies.get()); 924 restart_required |= OnHostTokenUrlPolicyUpdate(policies.get()); 925 restart_required |= OnPairingPolicyUpdate(policies.get()); 926 restart_required |= OnGnubbyAuthPolicyUpdate(policies.get()); 927 928 if (state_ == HOST_INITIALIZING) { 929 StartHost(); 930 } else if (state_ == HOST_STARTED && restart_required) { 931 RestartHost(); 932 } 933 } 934 935 void HostProcess::ApplyHostDomainPolicy() { 936 HOST_LOG << "Policy sets host domain: " << host_domain_; 937 938 // If the user does not have a Google email, their client JID will not be 939 // based on their email. In that case, the username/host domain policies would 940 // be meaningless, since there is no way to check that the JID attempting to 941 // connect actually corresponds to the owner email in question. 942 if (host_owner_ != host_owner_email_) { 943 LOG(ERROR) << "The username and host domain policies cannot be enabled for " 944 << "accounts with a non-Google email."; 945 ShutdownHost(kInvalidHostDomainExitCode); 946 } 947 948 if (!host_domain_.empty() && 949 !EndsWith(host_owner_, std::string("@") + host_domain_, false)) { 950 LOG(ERROR) << "The host domain does not match the policy."; 951 ShutdownHost(kInvalidHostDomainExitCode); 952 } 953 } 954 955 bool HostProcess::OnHostDomainPolicyUpdate(base::DictionaryValue* policies) { 956 // Returns true if the host has to be restarted after this policy update. 957 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 958 959 if (!policies->GetString(policy_hack::PolicyWatcher::kHostDomainPolicyName, 960 &host_domain_)) { 961 return false; 962 } 963 964 ApplyHostDomainPolicy(); 965 return false; 966 } 967 968 void HostProcess::ApplyUsernamePolicy() { 969 // See comment in ApplyHostDomainPolicy. 970 if (host_owner_ != host_owner_email_) { 971 LOG(ERROR) << "The username and host domain policies cannot be enabled for " 972 << "accounts with a non-Google email."; 973 ShutdownHost(kUsernameMismatchExitCode); 974 } 975 976 if (host_username_match_required_) { 977 HOST_LOG << "Policy requires host username match."; 978 std::string username = GetUsername(); 979 bool shutdown = username.empty() || 980 !StartsWithASCII(host_owner_, username + std::string("@"), 981 false); 982 983 #if defined(OS_MACOSX) 984 // On Mac, we run as root at the login screen, so the username won't match. 985 // However, there's no need to enforce the policy at the login screen, as 986 // the client will have to reconnect if a login occurs. 987 if (shutdown && getuid() == 0) { 988 shutdown = false; 989 } 990 #endif 991 992 // Curtain-mode on Windows presents the standard OS login prompt to the user 993 // for each connection, removing the need for an explicit user-name matching 994 // check. 995 #if defined(OS_WIN) && defined(REMOTING_RDP_SESSION) 996 if (curtain_required_) 997 return; 998 #endif // defined(OS_WIN) && defined(REMOTING_RDP_SESSION) 999 1000 // Shutdown the host if the username does not match. 1001 if (shutdown) { 1002 LOG(ERROR) << "The host username does not match."; 1003 ShutdownHost(kUsernameMismatchExitCode); 1004 } 1005 } else { 1006 HOST_LOG << "Policy does not require host username match."; 1007 } 1008 } 1009 1010 bool HostProcess::OnUsernamePolicyUpdate(base::DictionaryValue* policies) { 1011 // Returns false: never restart the host after this policy update. 1012 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1013 1014 if (!policies->GetBoolean( 1015 policy_hack::PolicyWatcher::kHostMatchUsernamePolicyName, 1016 &host_username_match_required_)) { 1017 return false; 1018 } 1019 1020 ApplyUsernamePolicy(); 1021 return false; 1022 } 1023 1024 bool HostProcess::OnNatPolicyUpdate(base::DictionaryValue* policies) { 1025 // Returns true if the host has to be restarted after this policy update. 1026 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1027 1028 if (!policies->GetBoolean(policy_hack::PolicyWatcher::kNatPolicyName, 1029 &allow_nat_traversal_)) { 1030 return false; 1031 } 1032 1033 if (allow_nat_traversal_) { 1034 HOST_LOG << "Policy enables NAT traversal."; 1035 } else { 1036 HOST_LOG << "Policy disables NAT traversal."; 1037 } 1038 return true; 1039 } 1040 1041 bool HostProcess::OnRelayPolicyUpdate(base::DictionaryValue* policies) { 1042 // Returns true if the host has to be restarted after this policy update. 1043 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1044 1045 if (!policies->GetBoolean(policy_hack::PolicyWatcher::kRelayPolicyName, 1046 &allow_relay_)) { 1047 return false; 1048 } 1049 1050 if (allow_relay_) { 1051 HOST_LOG << "Policy enables use of relay server."; 1052 } else { 1053 HOST_LOG << "Policy disables use of relay server."; 1054 } 1055 return true; 1056 } 1057 1058 bool HostProcess::OnUdpPortPolicyUpdate(base::DictionaryValue* policies) { 1059 // Returns true if the host has to be restarted after this policy update. 1060 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1061 1062 std::string udp_port_range; 1063 if (!policies->GetString(policy_hack::PolicyWatcher::kUdpPortRangePolicyName, 1064 &udp_port_range)) { 1065 return false; 1066 } 1067 1068 // Use default values if policy setting is empty or invalid. 1069 int min_udp_port = 0; 1070 int max_udp_port = 0; 1071 if (!udp_port_range.empty() && 1072 !NetworkSettings::ParsePortRange(udp_port_range, &min_udp_port, 1073 &max_udp_port)) { 1074 LOG(WARNING) << "Invalid port range policy: \"" << udp_port_range 1075 << "\". Using default values."; 1076 } 1077 1078 if (min_udp_port_ != min_udp_port || max_udp_port_ != max_udp_port) { 1079 if (min_udp_port != 0 && max_udp_port != 0) { 1080 HOST_LOG << "Policy restricts UDP port range to [" << min_udp_port 1081 << ", " << max_udp_port << "]"; 1082 } else { 1083 HOST_LOG << "Policy does not restrict UDP port range."; 1084 } 1085 min_udp_port_ = min_udp_port; 1086 max_udp_port_ = max_udp_port; 1087 return true; 1088 } 1089 return false; 1090 } 1091 1092 bool HostProcess::OnCurtainPolicyUpdate(base::DictionaryValue* policies) { 1093 // Returns true if the host has to be restarted after this policy update. 1094 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1095 1096 if (!policies->GetBoolean( 1097 policy_hack::PolicyWatcher::kHostRequireCurtainPolicyName, 1098 &curtain_required_)) { 1099 return false; 1100 } 1101 1102 #if defined(OS_MACOSX) 1103 if (curtain_required_) { 1104 // When curtain mode is in effect on Mac, the host process runs in the 1105 // user's switched-out session, but launchd will also run an instance at 1106 // the console login screen. Even if no user is currently logged-on, we 1107 // can't support remote-access to the login screen because the current host 1108 // process model disconnects the client during login, which would leave 1109 // the logged in session un-curtained on the console until they reconnect. 1110 // 1111 // TODO(jamiewalch): Fix this once we have implemented the multi-process 1112 // daemon architecture (crbug.com/134894) 1113 if (getuid() == 0) { 1114 LOG(ERROR) << "Running the host in the console login session is yet not " 1115 "supported."; 1116 ShutdownHost(kLoginScreenNotSupportedExitCode); 1117 return false; 1118 } 1119 } 1120 #endif 1121 1122 if (curtain_required_) { 1123 HOST_LOG << "Policy requires curtain-mode."; 1124 } else { 1125 HOST_LOG << "Policy does not require curtain-mode."; 1126 } 1127 1128 if (host_) 1129 host_->SetEnableCurtaining(curtain_required_); 1130 return false; 1131 } 1132 1133 bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate( 1134 base::DictionaryValue* policies) { 1135 // Returns true if the host has to be restarted after this policy update. 1136 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1137 1138 if (!policies->GetString( 1139 policy_hack::PolicyWatcher::kHostTalkGadgetPrefixPolicyName, 1140 &talkgadget_prefix_)) { 1141 return false; 1142 } 1143 1144 HOST_LOG << "Policy sets talkgadget prefix: " << talkgadget_prefix_; 1145 return true; 1146 } 1147 1148 bool HostProcess::OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies) { 1149 // Returns true if the host has to be restarted after this policy update. 1150 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1151 1152 bool token_policy_changed = false; 1153 std::string token_url_string; 1154 if (policies->GetString( 1155 policy_hack::PolicyWatcher::kHostTokenUrlPolicyName, 1156 &token_url_string)) { 1157 token_policy_changed = true; 1158 third_party_auth_config_.token_url = GURL(token_url_string); 1159 } 1160 std::string token_validation_url_string; 1161 if (policies->GetString( 1162 policy_hack::PolicyWatcher::kHostTokenValidationUrlPolicyName, 1163 &token_validation_url_string)) { 1164 token_policy_changed = true; 1165 third_party_auth_config_.token_validation_url = 1166 GURL(token_validation_url_string); 1167 } 1168 if (policies->GetString( 1169 policy_hack::PolicyWatcher::kHostTokenValidationCertIssuerPolicyName, 1170 &third_party_auth_config_.token_validation_cert_issuer)) { 1171 token_policy_changed = true; 1172 } 1173 1174 if (token_policy_changed) { 1175 HOST_LOG << "Policy sets third-party token URLs: " 1176 << "TokenUrl: " 1177 << third_party_auth_config_.token_url << ", " 1178 << "TokenValidationUrl: " 1179 << third_party_auth_config_.token_validation_url << ", " 1180 << "TokenValidationCertificateIssuer: " 1181 << third_party_auth_config_.token_validation_cert_issuer; 1182 } 1183 return token_policy_changed; 1184 } 1185 1186 bool HostProcess::OnPairingPolicyUpdate(base::DictionaryValue* policies) { 1187 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1188 1189 if (!policies->GetBoolean( 1190 policy_hack::PolicyWatcher::kHostAllowClientPairing, 1191 &allow_pairing_)) { 1192 return false; 1193 } 1194 1195 if (allow_pairing_) { 1196 HOST_LOG << "Policy enables client pairing."; 1197 } else { 1198 HOST_LOG << "Policy disables client pairing."; 1199 } 1200 return true; 1201 } 1202 1203 bool HostProcess::OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies) { 1204 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1205 1206 if (!policies->GetBoolean( 1207 policy_hack::PolicyWatcher::kHostAllowGnubbyAuthPolicyName, 1208 &enable_gnubby_auth_)) { 1209 return false; 1210 } 1211 1212 if (enable_gnubby_auth_) { 1213 HOST_LOG << "Policy enables gnubby auth."; 1214 } else { 1215 HOST_LOG << "Policy disables gnubby auth."; 1216 } 1217 1218 if (desktop_environment_factory_) 1219 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_); 1220 1221 return true; 1222 } 1223 1224 void HostProcess::StartHost() { 1225 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1226 DCHECK(!host_); 1227 DCHECK(!signal_strategy_.get()); 1228 DCHECK(state_ == HOST_INITIALIZING || state_ == HOST_STOPPING_TO_RESTART || 1229 state_ == HOST_STOPPED) << state_; 1230 state_ = HOST_STARTED; 1231 1232 signal_strategy_.reset( 1233 new XmppSignalStrategy(net::ClientSocketFactory::GetDefaultFactory(), 1234 context_->url_request_context_getter(), 1235 xmpp_server_config_)); 1236 1237 scoped_ptr<DnsBlackholeChecker> dns_blackhole_checker( 1238 new DnsBlackholeChecker(context_->url_request_context_getter(), 1239 talkgadget_prefix_)); 1240 1241 // Create a NetworkChangeNotifier for use by the signaling connector. 1242 network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); 1243 1244 signaling_connector_.reset(new SignalingConnector( 1245 signal_strategy_.get(), 1246 dns_blackhole_checker.Pass(), 1247 base::Bind(&HostProcess::OnAuthFailed, this))); 1248 1249 if (!oauth_refresh_token_.empty()) { 1250 scoped_ptr<OAuthTokenGetter::OAuthCredentials> oauth_credentials; 1251 oauth_credentials.reset( 1252 new OAuthTokenGetter::OAuthCredentials( 1253 xmpp_server_config_.username, oauth_refresh_token_, 1254 use_service_account_)); 1255 1256 oauth_token_getter_.reset(new OAuthTokenGetter( 1257 oauth_credentials.Pass(), context_->url_request_context_getter(), 1258 false)); 1259 1260 signaling_connector_->EnableOAuth(oauth_token_getter_.get()); 1261 } 1262 1263 uint32 network_flags = 0; 1264 if (allow_nat_traversal_) { 1265 network_flags = NetworkSettings::NAT_TRAVERSAL_STUN | 1266 NetworkSettings::NAT_TRAVERSAL_OUTGOING; 1267 if (allow_relay_) 1268 network_flags |= NetworkSettings::NAT_TRAVERSAL_RELAY; 1269 } 1270 1271 NetworkSettings network_settings(network_flags); 1272 1273 if (min_udp_port_ && max_udp_port_) { 1274 network_settings.min_port = min_udp_port_; 1275 network_settings.max_port = max_udp_port_; 1276 } else if (!allow_nat_traversal_) { 1277 // For legacy reasons we have to restrict the port range to a set of default 1278 // values when nat traversal is disabled, even if the port range was not 1279 // set in policy. 1280 network_settings.min_port = NetworkSettings::kDefaultMinPort; 1281 network_settings.max_port = NetworkSettings::kDefaultMaxPort; 1282 } 1283 1284 host_.reset(new ChromotingHost( 1285 signal_strategy_.get(), 1286 desktop_environment_factory_.get(), 1287 CreateHostSessionManager(signal_strategy_.get(), network_settings, 1288 context_->url_request_context_getter()), 1289 context_->audio_task_runner(), 1290 context_->input_task_runner(), 1291 context_->video_capture_task_runner(), 1292 context_->video_encode_task_runner(), 1293 context_->network_task_runner(), 1294 context_->ui_task_runner())); 1295 1296 if (enable_vp9_) { 1297 scoped_ptr<protocol::CandidateSessionConfig> config = 1298 host_->protocol_config()->Clone(); 1299 config->EnableVideoCodec(protocol::ChannelConfig::CODEC_VP9); 1300 host_->set_protocol_config(config.Pass()); 1301 } 1302 1303 if (frame_recorder_buffer_size_ > 0) { 1304 scoped_ptr<VideoFrameRecorderHostExtension> frame_recorder_extension( 1305 new VideoFrameRecorderHostExtension()); 1306 frame_recorder_extension->SetMaxContentBytes(frame_recorder_buffer_size_); 1307 host_->AddExtension(frame_recorder_extension.PassAs<HostExtension>()); 1308 } 1309 1310 // TODO(simonmorris): Get the maximum session duration from a policy. 1311 #if defined(OS_LINUX) 1312 host_->SetMaximumSessionDuration(base::TimeDelta::FromHours(20)); 1313 #endif 1314 1315 heartbeat_sender_.reset(new HeartbeatSender( 1316 this, host_id_, signal_strategy_.get(), key_pair_, 1317 directory_bot_jid_)); 1318 1319 host_status_sender_.reset(new HostStatusSender( 1320 host_id_, signal_strategy_.get(), key_pair_, directory_bot_jid_)); 1321 1322 host_change_notification_listener_.reset(new HostChangeNotificationListener( 1323 this, host_id_, signal_strategy_.get(), directory_bot_jid_)); 1324 1325 host_status_logger_.reset( 1326 new HostStatusLogger(host_->AsWeakPtr(), ServerLogEntry::ME2ME, 1327 signal_strategy_.get(), directory_bot_jid_)); 1328 1329 // Set up reporting the host status notifications. 1330 #if defined(REMOTING_MULTI_PROCESS) 1331 host_event_logger_.reset( 1332 new IpcHostEventLogger(host_->AsWeakPtr(), daemon_channel_.get())); 1333 #else // !defined(REMOTING_MULTI_PROCESS) 1334 host_event_logger_ = 1335 HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName); 1336 #endif // !defined(REMOTING_MULTI_PROCESS) 1337 1338 host_->SetEnableCurtaining(curtain_required_); 1339 host_->Start(host_owner_email_); 1340 1341 CreateAuthenticatorFactory(); 1342 } 1343 1344 void HostProcess::OnAuthFailed() { 1345 ShutdownHost(kInvalidOauthCredentialsExitCode); 1346 } 1347 1348 void HostProcess::RestartHost() { 1349 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1350 DCHECK_EQ(state_, HOST_STARTED); 1351 1352 state_ = HOST_STOPPING_TO_RESTART; 1353 ShutdownOnNetworkThread(); 1354 } 1355 1356 void HostProcess::ShutdownHost(HostExitCodes exit_code) { 1357 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1358 1359 *exit_code_out_ = exit_code; 1360 1361 switch (state_) { 1362 case HOST_INITIALIZING: 1363 state_ = HOST_STOPPING; 1364 ShutdownOnNetworkThread(); 1365 break; 1366 1367 case HOST_STARTED: 1368 state_ = HOST_STOPPING; 1369 host_status_sender_->SendOfflineStatus(exit_code); 1370 ScheduleHostShutdown(); 1371 break; 1372 1373 case HOST_STOPPING_TO_RESTART: 1374 state_ = HOST_STOPPING; 1375 break; 1376 1377 case HOST_STOPPING: 1378 case HOST_STOPPED: 1379 // Host is already stopped or being stopped. No action is required. 1380 break; 1381 } 1382 } 1383 1384 // TODO(weitaosu): shut down the host once we get an ACK for the offline status 1385 // XMPP message. 1386 void HostProcess::ScheduleHostShutdown() { 1387 // Delay the shutdown by 2 second to allow SendOfflineStatus to complete. 1388 context_->network_task_runner()->PostDelayedTask( 1389 FROM_HERE, 1390 base::Bind(&HostProcess::ShutdownOnNetworkThread, base::Unretained(this)), 1391 base::TimeDelta::FromSeconds(2)); 1392 } 1393 1394 void HostProcess::ShutdownOnNetworkThread() { 1395 DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); 1396 1397 host_.reset(); 1398 host_event_logger_.reset(); 1399 host_status_logger_.reset(); 1400 heartbeat_sender_.reset(); 1401 host_status_sender_.reset(); 1402 host_change_notification_listener_.reset(); 1403 signaling_connector_.reset(); 1404 oauth_token_getter_.reset(); 1405 signal_strategy_.reset(); 1406 network_change_notifier_.reset(); 1407 1408 if (state_ == HOST_STOPPING_TO_RESTART) { 1409 StartHost(); 1410 } else if (state_ == HOST_STOPPING) { 1411 state_ = HOST_STOPPED; 1412 1413 if (policy_watcher_.get()) { 1414 base::WaitableEvent done_event(true, false); 1415 policy_watcher_->StopWatching(&done_event); 1416 done_event.Wait(); 1417 policy_watcher_.reset(); 1418 } 1419 1420 config_watcher_.reset(); 1421 1422 // Complete the rest of shutdown on the main thread. 1423 context_->ui_task_runner()->PostTask( 1424 FROM_HERE, 1425 base::Bind(&HostProcess::ShutdownOnUiThread, this)); 1426 } else { 1427 // This method is only called in STOPPING_TO_RESTART and STOPPING states. 1428 NOTREACHED(); 1429 } 1430 } 1431 1432 void HostProcess::OnCrash(const std::string& function_name, 1433 const std::string& file_name, 1434 const int& line_number) { 1435 char message[1024]; 1436 base::snprintf(message, sizeof(message), 1437 "Requested by %s at %s, line %d.", 1438 function_name.c_str(), file_name.c_str(), line_number); 1439 base::debug::Alias(message); 1440 1441 // The daemon requested us to crash the process. 1442 CHECK(false) << message; 1443 } 1444 1445 int HostProcessMain() { 1446 #if defined(OS_LINUX) 1447 // Required in order for us to run multiple X11 threads. 1448 XInitThreads(); 1449 1450 // Required for any calls into GTK functions, such as the Disconnect and 1451 // Continue windows, though these should not be used for the Me2Me case 1452 // (crbug.com/104377). 1453 gtk_init(NULL, NULL); 1454 #endif 1455 1456 // Enable support for SSL server sockets, which must be done while still 1457 // single-threaded. 1458 net::EnableSSLServerSockets(); 1459 1460 // Ensures runtime specific CPU features are initialized. 1461 media::InitializeCPUSpecificMediaFeatures(); 1462 1463 // Create the main message loop and start helper threads. 1464 base::MessageLoopForUI message_loop; 1465 scoped_ptr<ChromotingHostContext> context = 1466 ChromotingHostContext::Create(new AutoThreadTaskRunner( 1467 message_loop.message_loop_proxy(), base::MessageLoop::QuitClosure())); 1468 if (!context) 1469 return kInitializationFailed; 1470 1471 // Create & start the HostProcess using these threads. 1472 // TODO(wez): The HostProcess holds a reference to itself until Shutdown(). 1473 // Remove this hack as part of the multi-process refactoring. 1474 int exit_code = kSuccessExitCode; 1475 new HostProcess(context.Pass(), &exit_code); 1476 1477 // Run the main (also UI) message loop until the host no longer needs it. 1478 message_loop.Run(); 1479 1480 return exit_code; 1481 } 1482 1483 } // namespace remoting 1484