Infer appropriate GNU_STACK alignment for a shared library.
[chromium-blink-merge.git] / remoting / host / remoting_me2me_host.cc
blobb66f8376f791bea52a9ff8cc57ce6339324331d2
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.
7 #include <string>
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/threading/thread.h"
23 #include "build/build_config.h"
24 #include "crypto/nss_util.h"
25 #include "ipc/ipc_channel.h"
26 #include "ipc/ipc_channel_proxy.h"
27 #include "ipc/ipc_listener.h"
28 #include "media/base/media.h"
29 #include "net/base/network_change_notifier.h"
30 #include "net/socket/client_socket_factory.h"
31 #include "net/socket/ssl_server_socket.h"
32 #include "net/url_request/url_fetcher.h"
33 #include "policy/policy_constants.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/host_change_notification_listener.h"
50 #include "remoting/host/host_config.h"
51 #include "remoting/host/host_event_logger.h"
52 #include "remoting/host/host_exit_codes.h"
53 #include "remoting/host/host_main.h"
54 #include "remoting/host/host_signaling_manager.h"
55 #include "remoting/host/host_status_logger.h"
56 #include "remoting/host/ipc_constants.h"
57 #include "remoting/host/ipc_desktop_environment.h"
58 #include "remoting/host/ipc_host_event_logger.h"
59 #include "remoting/host/logging.h"
60 #include "remoting/host/me2me_desktop_environment.h"
61 #include "remoting/host/pairing_registry_delegate.h"
62 #include "remoting/host/policy_watcher.h"
63 #include "remoting/host/session_manager_factory.h"
64 #include "remoting/host/shutdown_watchdog.h"
65 #include "remoting/host/signaling_connector.h"
66 #include "remoting/host/single_window_desktop_environment.h"
67 #include "remoting/host/token_validator_factory_impl.h"
68 #include "remoting/host/usage_stats_consent.h"
69 #include "remoting/host/username.h"
70 #include "remoting/host/video_frame_recorder_host_extension.h"
71 #include "remoting/protocol/me2me_host_authenticator_factory.h"
72 #include "remoting/protocol/network_settings.h"
73 #include "remoting/protocol/pairing_registry.h"
74 #include "remoting/protocol/token_validator.h"
75 #include "remoting/signaling/xmpp_signal_strategy.h"
77 #if defined(OS_POSIX)
78 #include <signal.h>
79 #include <sys/types.h>
80 #include <unistd.h>
81 #include "base/file_descriptor_posix.h"
82 #include "remoting/host/pam_authorization_factory_posix.h"
83 #include "remoting/host/posix/signal_handler.h"
84 #endif // defined(OS_POSIX)
86 #if defined(OS_MACOSX)
87 #include "base/mac/scoped_cftyperef.h"
88 #endif // defined(OS_MACOSX)
90 #if defined(OS_LINUX)
91 #include <gtk/gtk.h>
92 #include <X11/Xlib.h>
93 #include "remoting/host/audio_capturer_linux.h"
94 #endif // defined(OS_LINUX)
96 #if defined(OS_WIN)
97 #include <commctrl.h>
98 #include "base/win/registry.h"
99 #include "base/win/scoped_handle.h"
100 #include "remoting/host/pairing_registry_delegate_win.h"
101 #include "remoting/host/win/session_desktop_environment.h"
102 #endif // defined(OS_WIN)
104 using remoting::protocol::PairingRegistry;
105 using remoting::protocol::NetworkSettings;
107 #if defined(USE_REMOTING_MACOSX_INTERNAL)
108 #include "remoting/tools/internal/internal_mac-inl.h"
109 #endif
111 namespace {
113 // This is used for tagging system event logs.
114 const char kApplicationName[] = "chromoting";
116 #if defined(OS_LINUX)
117 // The command line switch used to pass name of the pipe to capture audio on
118 // linux.
119 const char kAudioPipeSwitchName[] = "audio-pipe-name";
121 // The command line switch used to pass name of the unix domain socket used to
122 // listen for gnubby requests.
123 const char kAuthSocknameSwitchName[] = "ssh-auth-sockname";
124 #endif // defined(OS_LINUX)
126 // The command line switch used by the parent to request the host to signal it
127 // when it is successfully started.
128 const char kSignalParentSwitchName[] = "signal-parent";
130 // Command line switch used to enable VP9 encoding.
131 const char kEnableVp9SwitchName[] = "enable-vp9";
133 // Command line switch used to enable and configure the frame-recorder.
134 const char kFrameRecorderBufferKbName[] = "frame-recorder-buffer-kb";
136 // Value used for --host-config option to indicate that the path must be read
137 // from stdin.
138 const char kStdinConfigPath[] = "-";
140 const char kWindowIdSwitchName[] = "window-id";
142 // Maximum time to wait for clean shutdown to occur, before forcing termination
143 // of the process.
144 const int kShutdownTimeoutSeconds = 15;
146 // Maximum time to wait for reporting host-offline-reason to the service,
147 // before continuing normal process shutdown.
148 const int kHostOfflineReasonTimeoutSeconds = 10;
150 } // namespace
152 namespace remoting {
154 class HostProcess : public ConfigWatcher::Delegate,
155 public HostSignalingManager::Listener,
156 public HostChangeNotificationListener::Listener,
157 public IPC::Listener,
158 public base::RefCountedThreadSafe<HostProcess> {
159 public:
160 // |shutdown_watchdog| is armed when shutdown is started, and should be kept
161 // alive as long as possible until the process exits (since destroying the
162 // watchdog disarms it).
163 HostProcess(scoped_ptr<ChromotingHostContext> context,
164 int* exit_code_out,
165 ShutdownWatchdog* shutdown_watchdog);
167 // ConfigWatcher::Delegate interface.
168 void OnConfigUpdated(const std::string& serialized_config) override;
169 void OnConfigWatcherError() override;
171 // IPC::Listener implementation.
172 bool OnMessageReceived(const IPC::Message& message) override;
173 void OnChannelError() override;
175 // HostChangeNotificationListener::Listener overrides.
176 void OnHostDeleted() override;
178 // Handler of the ChromotingDaemonNetworkMsg_InitializePairingRegistry IPC
179 // message.
180 void OnInitializePairingRegistry(
181 IPC::PlatformFileForTransit privileged_key,
182 IPC::PlatformFileForTransit unprivileged_key);
184 private:
185 enum HostState {
186 // Host process has just been started. Waiting for config and policies to be
187 // read from the disk.
188 HOST_INITIALIZING,
190 // Host is started and running.
191 HOST_STARTED,
193 // Host is being stopped and will need to be started again.
194 HOST_STOPPING_TO_RESTART,
196 // Host is being stopped.
197 HOST_STOPPING,
199 // Host has been stopped.
200 HOST_STOPPED,
202 // Allowed state transitions:
203 // INITIALIZING->STARTED
204 // INITIALIZING->STOPPED
205 // STARTED->STOPPING_TO_RESTART
206 // STARTED->STOPPING
207 // STOPPING_TO_RESTART->STARTED
208 // STOPPING_TO_RESTART->STOPPING
209 // STOPPING->STOPPED
210 // STOPPED->STARTED
212 // |host_| must be nullptr in INITIALIZING and STOPPED states and not
213 // nullptr in all other states.
216 friend class base::RefCountedThreadSafe<HostProcess>;
217 ~HostProcess() override;
219 void StartOnNetworkThread();
221 #if defined(OS_POSIX)
222 // Callback passed to RegisterSignalHandler() to handle SIGTERM events.
223 void SigTermHandler(int signal_number);
224 #endif
226 // Called to initialize resources on the UI thread.
227 void StartOnUiThread();
229 // Initializes IPC control channel and config file path from |cmd_line|.
230 // Called on the UI thread.
231 bool InitWithCommandLine(const base::CommandLine* cmd_line);
233 // Called on the UI thread to start monitoring the configuration file.
234 void StartWatchingConfigChanges();
236 // Called on the network thread to set the host's Authenticator factory.
237 void CreateAuthenticatorFactory();
239 // Tear down resources that run on the UI thread.
240 void ShutdownOnUiThread();
242 // Applies the host config, returning true if successful.
243 bool ApplyConfig(const base::DictionaryValue& config);
245 // Handles policy updates, by calling On*PolicyUpdate methods.
246 void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies);
247 void OnPolicyError();
248 void ApplyHostDomainPolicy();
249 void ApplyUsernamePolicy();
250 bool OnHostDomainPolicyUpdate(base::DictionaryValue* policies);
251 bool OnUsernamePolicyUpdate(base::DictionaryValue* policies);
252 bool OnNatPolicyUpdate(base::DictionaryValue* policies);
253 bool OnRelayPolicyUpdate(base::DictionaryValue* policies);
254 bool OnUdpPortPolicyUpdate(base::DictionaryValue* policies);
255 bool OnCurtainPolicyUpdate(base::DictionaryValue* policies);
256 bool OnHostTalkGadgetPrefixPolicyUpdate(base::DictionaryValue* policies);
257 bool OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies);
258 bool OnPairingPolicyUpdate(base::DictionaryValue* policies);
259 bool OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies);
261 scoped_ptr<HostSignalingManager> CreateHostSignalingManager();
263 void StartHostIfReady();
264 void StartHost();
266 // Overrides for HostSignalingManager::Listener interface.
267 void OnHeartbeatSuccessful() override;
268 void OnUnknownHostIdError() override;
269 void OnAuthFailed() override;
271 void RestartHost();
273 // Stops the host and shuts down the process with the specified |exit_code|.
274 void ShutdownHost(HostExitCodes exit_code);
276 // Private helper used by ShutdownHost method to initiate sending of
277 // host-offline-reason before continuing shutdown.
278 void SendOfflineReasonAndShutdownOnNetworkThread(HostExitCodes exit_code);
280 void ShutdownOnNetworkThread();
282 #if defined(OS_WIN)
283 // Initializes the pairing registry on Windows. This should be invoked on the
284 // network thread.
285 void InitializePairingRegistry(
286 IPC::PlatformFileForTransit privileged_key,
287 IPC::PlatformFileForTransit unprivileged_key);
288 #endif // defined(OS_WIN)
290 // Crashes the process in response to a daemon's request. The daemon passes
291 // the location of the code that detected the fatal error resulted in this
292 // request.
293 void OnCrash(const std::string& function_name,
294 const std::string& file_name,
295 const int& line_number);
297 scoped_ptr<ChromotingHostContext> context_;
299 // Accessed on the UI thread.
300 scoped_ptr<IPC::ChannelProxy> daemon_channel_;
302 // XMPP server/remoting bot configuration (initialized from the command line).
303 XmppSignalStrategy::XmppServerConfig xmpp_server_config_;
304 std::string directory_bot_jid_;
306 // Created on the UI thread but used from the network thread.
307 base::FilePath host_config_path_;
308 std::string host_config_;
309 scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
311 // Accessed on the network thread.
312 HostState state_;
314 scoped_ptr<ConfigWatcher> config_watcher_;
316 std::string host_id_;
317 protocol::SharedSecretHash host_secret_hash_;
318 scoped_refptr<RsaKeyPair> key_pair_;
319 std::string oauth_refresh_token_;
320 std::string serialized_config_;
321 std::string host_owner_;
322 std::string host_owner_email_;
323 bool use_service_account_;
324 bool enable_vp9_;
325 int64_t frame_recorder_buffer_size_;
327 scoped_ptr<PolicyWatcher> policy_watcher_;
328 bool policies_loaded_;
329 std::string host_domain_;
330 bool host_username_match_required_;
331 bool allow_nat_traversal_;
332 bool allow_relay_;
333 uint16 min_udp_port_;
334 uint16 max_udp_port_;
335 std::string talkgadget_prefix_;
336 bool allow_pairing_;
338 bool curtain_required_;
339 ThirdPartyAuthConfig third_party_auth_config_;
340 bool enable_gnubby_auth_;
342 // Boolean to change flow, where necessary, if we're
343 // capturing a window instead of the entire desktop.
344 bool enable_window_capture_;
346 // Used to specify which window to stream, if enabled.
347 webrtc::WindowId window_id_;
349 // Used to send heartbeats while running, and the reason for going offline
350 // when shutting down.
351 scoped_ptr<HostSignalingManager> host_signaling_manager_;
353 scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_;
354 scoped_ptr<HostStatusLogger> host_status_logger_;
355 scoped_ptr<HostEventLogger> host_event_logger_;
357 scoped_ptr<ChromotingHost> host_;
359 // Used to keep this HostProcess alive until it is shutdown.
360 scoped_refptr<HostProcess> self_;
362 #if defined(REMOTING_MULTI_PROCESS)
363 DesktopSessionConnector* desktop_session_connector_;
364 #endif // defined(REMOTING_MULTI_PROCESS)
366 int* exit_code_out_;
367 bool signal_parent_;
369 scoped_refptr<PairingRegistry> pairing_registry_;
371 ShutdownWatchdog* shutdown_watchdog_;
373 DISALLOW_COPY_AND_ASSIGN(HostProcess);
376 HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context,
377 int* exit_code_out,
378 ShutdownWatchdog* shutdown_watchdog)
379 : context_(context.Pass()),
380 state_(HOST_INITIALIZING),
381 use_service_account_(false),
382 enable_vp9_(false),
383 frame_recorder_buffer_size_(0),
384 policies_loaded_(false),
385 host_username_match_required_(false),
386 allow_nat_traversal_(true),
387 allow_relay_(true),
388 min_udp_port_(0),
389 max_udp_port_(0),
390 allow_pairing_(true),
391 curtain_required_(false),
392 enable_gnubby_auth_(false),
393 enable_window_capture_(false),
394 window_id_(0),
395 #if defined(REMOTING_MULTI_PROCESS)
396 desktop_session_connector_(nullptr),
397 #endif // defined(REMOTING_MULTI_PROCESS)
398 self_(this),
399 exit_code_out_(exit_code_out),
400 signal_parent_(false),
401 shutdown_watchdog_(shutdown_watchdog) {
402 StartOnUiThread();
405 HostProcess::~HostProcess() {
406 // Verify that UI components have been torn down.
407 DCHECK(!config_watcher_);
408 DCHECK(!daemon_channel_);
409 DCHECK(!desktop_environment_factory_);
411 // We might be getting deleted on one of the threads the |host_context| owns,
412 // so we need to post it back to the caller thread to safely join & delete the
413 // threads it contains. This will go away when we move to AutoThread.
414 // |context_release()| will null |context_| before the method is invoked, so
415 // we need to pull out the task-runner on which to call DeleteSoon first.
416 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
417 context_->ui_task_runner();
418 task_runner->DeleteSoon(FROM_HERE, context_.release());
421 bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) {
422 #if defined(REMOTING_MULTI_PROCESS)
423 // Parse the handle value and convert it to a handle/file descriptor.
424 std::string channel_name =
425 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
427 int pipe_handle = 0;
428 if (channel_name.empty() ||
429 !base::StringToInt(channel_name, &pipe_handle)) {
430 LOG(ERROR) << "Invalid '" << kDaemonPipeSwitchName
431 << "' value: " << channel_name;
432 return false;
435 #if defined(OS_WIN)
436 base::win::ScopedHandle pipe(reinterpret_cast<HANDLE>(pipe_handle));
437 IPC::ChannelHandle channel_handle(pipe.Get());
438 #elif defined(OS_POSIX)
439 base::FileDescriptor pipe(pipe_handle, true);
440 IPC::ChannelHandle channel_handle(channel_name, pipe);
441 #endif // defined(OS_POSIX)
443 // Connect to the daemon process.
444 daemon_channel_ = IPC::ChannelProxy::Create(channel_handle,
445 IPC::Channel::MODE_CLIENT,
446 this,
447 context_->network_task_runner());
448 #else // !defined(REMOTING_MULTI_PROCESS)
449 // Connect to the daemon process.
450 std::string channel_name =
451 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
452 if (!channel_name.empty()) {
453 daemon_channel_ =
454 IPC::ChannelProxy::Create(channel_name,
455 IPC::Channel::MODE_CLIENT,
456 this,
457 context_->network_task_runner().get());
460 if (cmd_line->HasSwitch(kHostConfigSwitchName)) {
461 host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName);
463 // Read config from stdin if necessary.
464 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
465 char buf[4096];
466 size_t len;
467 while ((len = fread(buf, 1, sizeof(buf), stdin)) > 0) {
468 host_config_.append(buf, len);
471 } else {
472 base::FilePath default_config_dir = remoting::GetConfigDir();
473 host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile);
476 if (host_config_path_ != base::FilePath(kStdinConfigPath) &&
477 !base::PathExists(host_config_path_)) {
478 LOG(ERROR) << "Can't find host config at " << host_config_path_.value();
479 return false;
481 #endif // !defined(REMOTING_MULTI_PROCESS)
483 // Ignore certificate requests - the host currently has no client certificate
484 // support, so ignoring certificate requests allows connecting to servers that
485 // request, but don't require, a certificate (optional client authentication).
486 net::URLFetcher::SetIgnoreCertificateRequests(true);
488 ServiceUrls* service_urls = ServiceUrls::GetInstance();
489 bool xmpp_server_valid = net::ParseHostAndPort(
490 service_urls->xmpp_server_address(),
491 &xmpp_server_config_.host, &xmpp_server_config_.port);
492 if (!xmpp_server_valid) {
493 LOG(ERROR) << "Invalid XMPP server: " <<
494 service_urls->xmpp_server_address();
495 return false;
497 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls();
498 directory_bot_jid_ = service_urls->directory_bot_jid();
500 signal_parent_ = cmd_line->HasSwitch(kSignalParentSwitchName);
502 enable_window_capture_ = cmd_line->HasSwitch(kWindowIdSwitchName);
503 if (enable_window_capture_) {
505 #if defined(OS_LINUX) || defined(OS_WIN)
506 LOG(WARNING) << "Window capturing is not fully supported on Linux or "
507 "Windows.";
508 #endif // defined(OS_LINUX) || defined(OS_WIN)
510 // uint32_t is large enough to hold window IDs on all platforms.
511 uint32_t window_id;
512 if (base::StringToUint(
513 cmd_line->GetSwitchValueASCII(kWindowIdSwitchName),
514 &window_id)) {
515 window_id_ = static_cast<webrtc::WindowId>(window_id);
516 } else {
517 LOG(ERROR) << "Window with window id: " << window_id_
518 << " not found. Shutting down host.";
519 return false;
522 return true;
525 void HostProcess::OnConfigUpdated(
526 const std::string& serialized_config) {
527 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
528 context_->network_task_runner()->PostTask(FROM_HERE,
529 base::Bind(&HostProcess::OnConfigUpdated, this, serialized_config));
530 return;
533 // Filter out duplicates.
534 if (serialized_config_ == serialized_config)
535 return;
537 HOST_LOG << "Processing new host configuration.";
539 serialized_config_ = serialized_config;
540 scoped_ptr<base::DictionaryValue> config(
541 HostConfigFromJson(serialized_config));
542 if (!config) {
543 LOG(ERROR) << "Invalid configuration.";
544 ShutdownHost(kInvalidHostConfigurationExitCode);
545 return;
548 if (!ApplyConfig(*config)) {
549 LOG(ERROR) << "Failed to apply the configuration.";
550 ShutdownHost(kInvalidHostConfigurationExitCode);
551 return;
554 if (state_ == HOST_INITIALIZING) {
555 StartHostIfReady();
556 } else if (state_ == HOST_STARTED) {
557 DCHECK(policies_loaded_);
559 // Reapply policies that could be affected by a new config.
560 ApplyHostDomainPolicy();
561 ApplyUsernamePolicy();
563 // TODO(sergeyu): Here we assume that PIN is the only part of the config
564 // that may change while the service is running. Change ApplyConfig() to
565 // detect other changes in the config and restart host if necessary here.
566 CreateAuthenticatorFactory();
570 void HostProcess::OnConfigWatcherError() {
571 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
572 ShutdownHost(kInvalidHostConfigurationExitCode);
575 void HostProcess::StartOnNetworkThread() {
576 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
578 #if !defined(REMOTING_MULTI_PROCESS)
579 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
580 // Process config we've read from stdin.
581 OnConfigUpdated(host_config_);
582 } else {
583 // Start watching the host configuration file.
584 config_watcher_.reset(new ConfigFileWatcher(context_->network_task_runner(),
585 context_->file_task_runner(),
586 host_config_path_));
587 config_watcher_->Watch(this);
589 #endif // !defined(REMOTING_MULTI_PROCESS)
591 #if defined(OS_POSIX)
592 remoting::RegisterSignalHandler(
593 SIGTERM,
594 base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
595 #endif // defined(OS_POSIX)
598 #if defined(OS_POSIX)
599 void HostProcess::SigTermHandler(int signal_number) {
600 DCHECK(signal_number == SIGTERM);
601 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
602 HOST_LOG << "Caught SIGTERM: Shutting down...";
603 ShutdownHost(kSuccessExitCode);
605 #endif // OS_POSIX
607 void HostProcess::CreateAuthenticatorFactory() {
608 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
610 if (state_ != HOST_STARTED)
611 return;
613 std::string local_certificate = key_pair_->GenerateCertificate();
614 if (local_certificate.empty()) {
615 LOG(ERROR) << "Failed to generate host certificate.";
616 ShutdownHost(kInitializationFailed);
617 return;
620 scoped_ptr<protocol::AuthenticatorFactory> factory;
622 if (third_party_auth_config_.is_empty()) {
623 scoped_refptr<PairingRegistry> pairing_registry;
624 if (allow_pairing_) {
625 // On Windows |pairing_registry_| is initialized in
626 // InitializePairingRegistry().
627 #if !defined(OS_WIN)
628 if (!pairing_registry_) {
629 scoped_ptr<PairingRegistry::Delegate> delegate =
630 CreatePairingRegistryDelegate();
632 if (delegate)
633 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
634 delegate.Pass());
636 #endif // defined(OS_WIN)
638 pairing_registry = pairing_registry_;
641 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
642 use_service_account_, host_owner_, local_certificate, key_pair_,
643 host_secret_hash_, pairing_registry);
645 host_->set_pairing_registry(pairing_registry);
646 } else if (third_party_auth_config_.is_valid()) {
647 scoped_ptr<protocol::TokenValidatorFactory> token_validator_factory(
648 new TokenValidatorFactoryImpl(
649 third_party_auth_config_,
650 key_pair_, context_->url_request_context_getter()));
651 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
652 use_service_account_, host_owner_, local_certificate, key_pair_,
653 token_validator_factory.Pass());
655 } else {
656 // TODO(rmsousa): If the policy is bad the host should not go online. It
657 // should keep running, but not connected, until the policies are fixed.
658 // Having it show up as online and then reject all clients is misleading.
659 LOG(ERROR) << "One of the third-party token URLs is empty or invalid. "
660 << "Host will reject all clients until policies are corrected. "
661 << "TokenUrl: " << third_party_auth_config_.token_url << ", "
662 << "TokenValidationUrl: "
663 << third_party_auth_config_.token_validation_url;
664 factory = protocol::Me2MeHostAuthenticatorFactory::CreateRejecting();
667 #if defined(OS_POSIX)
668 // On Linux and Mac, perform a PAM authorization step after authentication.
669 factory.reset(new PamAuthorizationFactory(factory.Pass()));
670 #endif
671 host_->SetAuthenticatorFactory(factory.Pass());
674 // IPC::Listener implementation.
675 bool HostProcess::OnMessageReceived(const IPC::Message& message) {
676 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
678 #if defined(REMOTING_MULTI_PROCESS)
679 bool handled = true;
680 IPC_BEGIN_MESSAGE_MAP(HostProcess, message)
681 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash)
682 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration,
683 OnConfigUpdated)
684 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_InitializePairingRegistry,
685 OnInitializePairingRegistry)
686 IPC_MESSAGE_FORWARD(
687 ChromotingDaemonNetworkMsg_DesktopAttached,
688 desktop_session_connector_,
689 DesktopSessionConnector::OnDesktopSessionAgentAttached)
690 IPC_MESSAGE_FORWARD(ChromotingDaemonNetworkMsg_TerminalDisconnected,
691 desktop_session_connector_,
692 DesktopSessionConnector::OnTerminalDisconnected)
693 IPC_MESSAGE_UNHANDLED(handled = false)
694 IPC_END_MESSAGE_MAP()
696 CHECK(handled) << "Received unexpected IPC type: " << message.type();
697 return handled;
699 #else // !defined(REMOTING_MULTI_PROCESS)
700 return false;
701 #endif // !defined(REMOTING_MULTI_PROCESS)
704 void HostProcess::OnChannelError() {
705 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
707 // Shutdown the host if the daemon process disconnects the IPC channel.
708 context_->network_task_runner()->PostTask(
709 FROM_HERE,
710 base::Bind(&HostProcess::ShutdownHost, this, kSuccessExitCode));
713 void HostProcess::StartOnUiThread() {
714 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
716 if (!InitWithCommandLine(base::CommandLine::ForCurrentProcess())) {
717 // Shutdown the host if the command line is invalid.
718 context_->network_task_runner()->PostTask(
719 FROM_HERE, base::Bind(&HostProcess::ShutdownHost, this,
720 kUsageExitCode));
721 return;
724 policy_watcher_ =
725 PolicyWatcher::Create(nullptr, context_->file_task_runner());
726 policy_watcher_->StartWatching(
727 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)),
728 base::Bind(&HostProcess::OnPolicyError, base::Unretained(this)));
730 #if defined(OS_LINUX)
731 // If an audio pipe is specific on the command-line then initialize
732 // AudioCapturerLinux to capture from it.
733 base::FilePath audio_pipe_name = base::CommandLine::ForCurrentProcess()->
734 GetSwitchValuePath(kAudioPipeSwitchName);
735 if (!audio_pipe_name.empty()) {
736 remoting::AudioCapturerLinux::InitializePipeReader(
737 context_->audio_task_runner(), audio_pipe_name);
740 base::FilePath gnubby_socket_name = base::CommandLine::ForCurrentProcess()->
741 GetSwitchValuePath(kAuthSocknameSwitchName);
742 if (!gnubby_socket_name.empty())
743 remoting::GnubbyAuthHandler::SetGnubbySocketName(gnubby_socket_name);
744 #endif // defined(OS_LINUX)
746 // Create a desktop environment factory appropriate to the build type &
747 // platform.
748 #if defined(OS_WIN)
749 IpcDesktopEnvironmentFactory* desktop_environment_factory =
750 new IpcDesktopEnvironmentFactory(
751 context_->audio_task_runner(),
752 context_->network_task_runner(),
753 context_->video_capture_task_runner(),
754 context_->network_task_runner(),
755 daemon_channel_.get());
756 desktop_session_connector_ = desktop_environment_factory;
757 #else // !defined(OS_WIN)
758 DesktopEnvironmentFactory* desktop_environment_factory;
759 if (enable_window_capture_) {
760 desktop_environment_factory =
761 new SingleWindowDesktopEnvironmentFactory(
762 context_->network_task_runner(),
763 context_->input_task_runner(),
764 context_->ui_task_runner(),
765 window_id_);
766 } else {
767 desktop_environment_factory =
768 new Me2MeDesktopEnvironmentFactory(
769 context_->network_task_runner(),
770 context_->input_task_runner(),
771 context_->ui_task_runner());
773 #endif // !defined(OS_WIN)
775 desktop_environment_factory_.reset(desktop_environment_factory);
776 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
778 context_->network_task_runner()->PostTask(
779 FROM_HERE,
780 base::Bind(&HostProcess::StartOnNetworkThread, this));
783 void HostProcess::ShutdownOnUiThread() {
784 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
786 // Tear down resources that need to be torn down on the UI thread.
787 daemon_channel_.reset();
788 desktop_environment_factory_.reset();
790 policy_watcher_.reset();
792 // It is now safe for the HostProcess to be deleted.
793 self_ = nullptr;
795 #if defined(OS_LINUX)
796 // Cause the global AudioPipeReader to be freed, otherwise the audio
797 // thread will remain in-use and prevent the process from exiting.
798 // TODO(wez): DesktopEnvironmentFactory should own the pipe reader.
799 // See crbug.com/161373 and crbug.com/104544.
800 AudioCapturerLinux::InitializePipeReader(nullptr, base::FilePath());
801 #endif
804 void HostProcess::OnUnknownHostIdError() {
805 LOG(ERROR) << "Host ID not found.";
806 ShutdownHost(kInvalidHostIdExitCode);
809 void HostProcess::OnHeartbeatSuccessful() {
810 HOST_LOG << "Host ready to receive connections.";
811 #if defined(OS_POSIX)
812 if (signal_parent_) {
813 kill(getppid(), SIGUSR1);
814 signal_parent_ = false;
816 #endif
819 void HostProcess::OnHostDeleted() {
820 LOG(ERROR) << "Host was deleted from the directory.";
821 ShutdownHost(kInvalidHostIdExitCode);
824 void HostProcess::OnInitializePairingRegistry(
825 IPC::PlatformFileForTransit privileged_key,
826 IPC::PlatformFileForTransit unprivileged_key) {
827 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
829 #if defined(OS_WIN)
830 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
831 &HostProcess::InitializePairingRegistry,
832 this, privileged_key, unprivileged_key));
833 #else // !defined(OS_WIN)
834 NOTREACHED();
835 #endif // !defined(OS_WIN)
838 #if defined(OS_WIN)
839 void HostProcess::InitializePairingRegistry(
840 IPC::PlatformFileForTransit privileged_key,
841 IPC::PlatformFileForTransit unprivileged_key) {
842 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
843 // |privileged_key| can be nullptr but not |unprivileged_key|.
844 DCHECK(unprivileged_key);
845 // |pairing_registry_| should only be initialized once.
846 DCHECK(!pairing_registry_);
848 HKEY privileged_hkey = reinterpret_cast<HKEY>(
849 IPC::PlatformFileForTransitToPlatformFile(privileged_key));
850 HKEY unprivileged_hkey = reinterpret_cast<HKEY>(
851 IPC::PlatformFileForTransitToPlatformFile(unprivileged_key));
853 scoped_ptr<PairingRegistryDelegateWin> delegate(
854 new PairingRegistryDelegateWin());
855 delegate->SetRootKeys(privileged_hkey, unprivileged_hkey);
857 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
858 delegate.Pass());
860 // (Re)Create the authenticator factory now that |pairing_registry_| has been
861 // initialized.
862 CreateAuthenticatorFactory();
864 #endif // !defined(OS_WIN)
866 // Applies the host config, returning true if successful.
867 bool HostProcess::ApplyConfig(const base::DictionaryValue& config) {
868 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
870 if (!config.GetString(kHostIdConfigPath, &host_id_)) {
871 LOG(ERROR) << "host_id is not defined in the config.";
872 return false;
875 std::string key_base64;
876 if (!config.GetString(kPrivateKeyConfigPath, &key_base64)) {
877 LOG(ERROR) << "Private key couldn't be read from the config file.";
878 return false;
881 key_pair_ = RsaKeyPair::FromString(key_base64);
882 if (!key_pair_.get()) {
883 LOG(ERROR) << "Invalid private key in the config file.";
884 return false;
887 std::string host_secret_hash_string;
888 if (!config.GetString(kHostSecretHashConfigPath,
889 &host_secret_hash_string)) {
890 host_secret_hash_string = "plain:";
893 if (!host_secret_hash_.Parse(host_secret_hash_string)) {
894 LOG(ERROR) << "Invalid host_secret_hash.";
895 return false;
898 // Use an XMPP connection to the Talk network for session signalling.
899 if (!config.GetString(kXmppLoginConfigPath, &xmpp_server_config_.username) ||
900 !(config.GetString(kXmppAuthTokenConfigPath,
901 &xmpp_server_config_.auth_token) ||
902 config.GetString(kOAuthRefreshTokenConfigPath,
903 &oauth_refresh_token_))) {
904 LOG(ERROR) << "XMPP credentials are not defined in the config.";
905 return false;
908 if (!oauth_refresh_token_.empty()) {
909 // SignalingConnector (inside HostSignalingManager) is responsible for
910 // getting OAuth token.
911 xmpp_server_config_.auth_token = "";
912 xmpp_server_config_.auth_service = "oauth2";
913 } else if (!config.GetString(kXmppAuthServiceConfigPath,
914 &xmpp_server_config_.auth_service)) {
915 // For the me2me host, we default to ClientLogin token for chromiumsync
916 // because earlier versions of the host had no HTTP stack with which to
917 // request an OAuth2 access token.
918 xmpp_server_config_.auth_service = kChromotingTokenDefaultServiceName;
921 if (config.GetString(kHostOwnerConfigPath, &host_owner_)) {
922 // Service account configs have a host_owner, different from the xmpp_login.
923 use_service_account_ = true;
924 } else {
925 // User credential configs only have an xmpp_login, which is also the owner.
926 host_owner_ = xmpp_server_config_.username;
927 use_service_account_ = false;
930 // For non-Gmail Google accounts, the owner base JID differs from the email.
931 // host_owner_ contains the base JID (used for authenticating clients), while
932 // host_owner_email contains the account's email (used for UI and logs).
933 if (!config.GetString(kHostOwnerEmailConfigPath, &host_owner_email_)) {
934 host_owner_email_ = host_owner_;
937 // Allow offering of VP9 encoding to be overridden by the command-line.
938 if (base::CommandLine::ForCurrentProcess()->HasSwitch(kEnableVp9SwitchName)) {
939 enable_vp9_ = true;
940 } else {
941 config.GetBoolean(kEnableVp9ConfigPath, &enable_vp9_);
944 // Allow the command-line to override the size of the frame recorder buffer.
945 int frame_recorder_buffer_kb = 0;
946 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
947 kFrameRecorderBufferKbName)) {
948 std::string switch_value =
949 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
950 kFrameRecorderBufferKbName);
951 base::StringToInt(switch_value, &frame_recorder_buffer_kb);
952 } else {
953 config.GetInteger(kFrameRecorderBufferKbConfigPath,
954 &frame_recorder_buffer_kb);
956 if (frame_recorder_buffer_kb > 0) {
957 frame_recorder_buffer_size_ = 1024LL * frame_recorder_buffer_kb;
960 return true;
963 void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
964 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
965 context_->network_task_runner()->PostTask(
966 FROM_HERE, base::Bind(&HostProcess::OnPolicyUpdate, this,
967 base::Passed(&policies)));
968 return;
971 bool restart_required = false;
972 restart_required |= OnHostDomainPolicyUpdate(policies.get());
973 restart_required |= OnCurtainPolicyUpdate(policies.get());
974 // Note: UsernamePolicyUpdate must run after OnCurtainPolicyUpdate.
975 restart_required |= OnUsernamePolicyUpdate(policies.get());
976 restart_required |= OnNatPolicyUpdate(policies.get());
977 restart_required |= OnRelayPolicyUpdate(policies.get());
978 restart_required |= OnUdpPortPolicyUpdate(policies.get());
979 restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(policies.get());
980 restart_required |= OnHostTokenUrlPolicyUpdate(policies.get());
981 restart_required |= OnPairingPolicyUpdate(policies.get());
982 restart_required |= OnGnubbyAuthPolicyUpdate(policies.get());
984 policies_loaded_ = true;
986 if (state_ == HOST_INITIALIZING) {
987 StartHostIfReady();
988 } else if (state_ == HOST_STARTED) {
989 if (restart_required)
990 RestartHost();
994 void HostProcess::OnPolicyError() {
995 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
996 context_->network_task_runner()->PostTask(
997 FROM_HERE, base::Bind(&HostProcess::OnPolicyError, this));
998 return;
1001 ShutdownHost(kInvalidHostConfigurationExitCode);
1004 void HostProcess::ApplyHostDomainPolicy() {
1005 if (state_ != HOST_STARTED)
1006 return;
1008 HOST_LOG << "Policy sets host domain: " << host_domain_;
1010 if (!host_domain_.empty()) {
1011 // If the user does not have a Google email, their client JID will not be
1012 // based on their email. In that case, the username/host domain policies
1013 // would be meaningless, since there is no way to check that the JID
1014 // trying to connect actually corresponds to the owner email in question.
1015 if (host_owner_ != host_owner_email_) {
1016 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1017 << "for accounts with a non-Google email.";
1018 ShutdownHost(kInvalidHostDomainExitCode);
1021 if (!EndsWith(host_owner_, std::string("@") + host_domain_, false)) {
1022 LOG(ERROR) << "The host domain does not match the policy.";
1023 ShutdownHost(kInvalidHostDomainExitCode);
1028 bool HostProcess::OnHostDomainPolicyUpdate(base::DictionaryValue* policies) {
1029 // Returns true if the host has to be restarted after this policy update.
1030 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1032 if (!policies->GetString(policy::key::kRemoteAccessHostDomain,
1033 &host_domain_)) {
1034 return false;
1037 ApplyHostDomainPolicy();
1038 return false;
1041 void HostProcess::ApplyUsernamePolicy() {
1042 if (state_ != HOST_STARTED)
1043 return;
1045 if (host_username_match_required_) {
1046 HOST_LOG << "Policy requires host username match.";
1048 // See comment in ApplyHostDomainPolicy.
1049 if (host_owner_ != host_owner_email_) {
1050 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1051 << "for accounts with a non-Google email.";
1052 ShutdownHost(kUsernameMismatchExitCode);
1055 std::string username = GetUsername();
1056 bool shutdown = username.empty() ||
1057 !StartsWithASCII(host_owner_, username + std::string("@"),
1058 false);
1060 #if defined(OS_MACOSX)
1061 // On Mac, we run as root at the login screen, so the username won't match.
1062 // However, there's no need to enforce the policy at the login screen, as
1063 // the client will have to reconnect if a login occurs.
1064 if (shutdown && getuid() == 0) {
1065 shutdown = false;
1067 #endif
1069 // Curtain-mode on Windows presents the standard OS login prompt to the user
1070 // for each connection, removing the need for an explicit user-name matching
1071 // check.
1072 #if defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1073 if (curtain_required_)
1074 return;
1075 #endif // defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1077 // Shutdown the host if the username does not match.
1078 if (shutdown) {
1079 LOG(ERROR) << "The host username does not match.";
1080 ShutdownHost(kUsernameMismatchExitCode);
1082 } else {
1083 HOST_LOG << "Policy does not require host username match.";
1087 bool HostProcess::OnUsernamePolicyUpdate(base::DictionaryValue* policies) {
1088 // Returns false: never restart the host after this policy update.
1089 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1091 if (!policies->GetBoolean(policy::key::kRemoteAccessHostMatchUsername,
1092 &host_username_match_required_)) {
1093 return false;
1096 ApplyUsernamePolicy();
1097 return false;
1100 bool HostProcess::OnNatPolicyUpdate(base::DictionaryValue* policies) {
1101 // Returns true if the host has to be restarted after this policy update.
1102 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1104 if (!policies->GetBoolean(policy::key::kRemoteAccessHostFirewallTraversal,
1105 &allow_nat_traversal_)) {
1106 return false;
1109 if (allow_nat_traversal_) {
1110 HOST_LOG << "Policy enables NAT traversal.";
1111 } else {
1112 HOST_LOG << "Policy disables NAT traversal.";
1114 return true;
1117 bool HostProcess::OnRelayPolicyUpdate(base::DictionaryValue* policies) {
1118 // Returns true if the host has to be restarted after this policy update.
1119 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1121 if (!policies->GetBoolean(
1122 policy::key::kRemoteAccessHostAllowRelayedConnection,
1123 &allow_relay_)) {
1124 return false;
1127 if (allow_relay_) {
1128 HOST_LOG << "Policy enables use of relay server.";
1129 } else {
1130 HOST_LOG << "Policy disables use of relay server.";
1132 return true;
1135 bool HostProcess::OnUdpPortPolicyUpdate(base::DictionaryValue* policies) {
1136 // Returns true if the host has to be restarted after this policy update.
1137 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1139 std::string udp_port_range;
1140 if (!policies->GetString(policy::key::kRemoteAccessHostUdpPortRange,
1141 &udp_port_range)) {
1142 return false;
1145 // Use default values if policy setting is empty or invalid.
1146 uint16 min_udp_port = 0;
1147 uint16 max_udp_port = 0;
1148 if (!udp_port_range.empty() &&
1149 !NetworkSettings::ParsePortRange(udp_port_range, &min_udp_port,
1150 &max_udp_port)) {
1151 LOG(WARNING) << "Invalid port range policy: \"" << udp_port_range
1152 << "\". Using default values.";
1155 if (min_udp_port_ != min_udp_port || max_udp_port_ != max_udp_port) {
1156 if (min_udp_port != 0 && max_udp_port != 0) {
1157 HOST_LOG << "Policy restricts UDP port range to [" << min_udp_port
1158 << ", " << max_udp_port << "]";
1159 } else {
1160 HOST_LOG << "Policy does not restrict UDP port range.";
1162 min_udp_port_ = min_udp_port;
1163 max_udp_port_ = max_udp_port;
1164 return true;
1166 return false;
1169 bool HostProcess::OnCurtainPolicyUpdate(base::DictionaryValue* policies) {
1170 // Returns true if the host has to be restarted after this policy update.
1171 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1173 if (!policies->GetBoolean(policy::key::kRemoteAccessHostRequireCurtain,
1174 &curtain_required_)) {
1175 return false;
1178 #if defined(OS_MACOSX)
1179 if (curtain_required_) {
1180 // When curtain mode is in effect on Mac, the host process runs in the
1181 // user's switched-out session, but launchd will also run an instance at
1182 // the console login screen. Even if no user is currently logged-on, we
1183 // can't support remote-access to the login screen because the current host
1184 // process model disconnects the client during login, which would leave
1185 // the logged in session un-curtained on the console until they reconnect.
1187 // TODO(jamiewalch): Fix this once we have implemented the multi-process
1188 // daemon architecture (crbug.com/134894)
1189 if (getuid() == 0) {
1190 LOG(ERROR) << "Running the host in the console login session is yet not "
1191 "supported.";
1192 ShutdownHost(kLoginScreenNotSupportedExitCode);
1193 return false;
1196 #endif
1198 if (curtain_required_) {
1199 HOST_LOG << "Policy requires curtain-mode.";
1200 } else {
1201 HOST_LOG << "Policy does not require curtain-mode.";
1204 if (host_)
1205 host_->SetEnableCurtaining(curtain_required_);
1206 return false;
1209 bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate(
1210 base::DictionaryValue* policies) {
1211 // Returns true if the host has to be restarted after this policy update.
1212 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1214 if (!policies->GetString(policy::key::kRemoteAccessHostTalkGadgetPrefix,
1215 &talkgadget_prefix_)) {
1216 return false;
1219 HOST_LOG << "Policy sets talkgadget prefix: " << talkgadget_prefix_;
1220 return true;
1223 bool HostProcess::OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies) {
1224 // Returns true if the host has to be restarted after this policy update.
1225 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1227 bool token_policy_changed = false;
1228 std::string token_url_string;
1229 if (policies->GetString(policy::key::kRemoteAccessHostTokenUrl,
1230 &token_url_string)) {
1231 token_policy_changed = true;
1232 third_party_auth_config_.token_url = GURL(token_url_string);
1234 std::string token_validation_url_string;
1235 if (policies->GetString(policy::key::kRemoteAccessHostTokenValidationUrl,
1236 &token_validation_url_string)) {
1237 token_policy_changed = true;
1238 third_party_auth_config_.token_validation_url =
1239 GURL(token_validation_url_string);
1241 if (policies->GetString(
1242 policy::key::kRemoteAccessHostTokenValidationCertificateIssuer,
1243 &third_party_auth_config_.token_validation_cert_issuer)) {
1244 token_policy_changed = true;
1247 if (token_policy_changed) {
1248 HOST_LOG << "Policy sets third-party token URLs: "
1249 << "TokenUrl: "
1250 << third_party_auth_config_.token_url << ", "
1251 << "TokenValidationUrl: "
1252 << third_party_auth_config_.token_validation_url << ", "
1253 << "TokenValidationCertificateIssuer: "
1254 << third_party_auth_config_.token_validation_cert_issuer;
1256 return token_policy_changed;
1259 bool HostProcess::OnPairingPolicyUpdate(base::DictionaryValue* policies) {
1260 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1262 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowClientPairing,
1263 &allow_pairing_)) {
1264 return false;
1267 if (allow_pairing_) {
1268 HOST_LOG << "Policy enables client pairing.";
1269 } else {
1270 HOST_LOG << "Policy disables client pairing.";
1272 return true;
1275 bool HostProcess::OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies) {
1276 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1278 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth,
1279 &enable_gnubby_auth_)) {
1280 return false;
1283 if (enable_gnubby_auth_) {
1284 HOST_LOG << "Policy enables gnubby auth.";
1285 } else {
1286 HOST_LOG << "Policy disables gnubby auth.";
1289 if (desktop_environment_factory_)
1290 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
1292 return true;
1295 scoped_ptr<HostSignalingManager> HostProcess::CreateHostSignalingManager() {
1296 DCHECK(!host_id_.empty()); // |ApplyConfig| should already have been run.
1298 scoped_ptr<OAuthTokenGetter::OAuthCredentials> oauth_credentials(
1299 new OAuthTokenGetter::OAuthCredentials(xmpp_server_config_.username,
1300 oauth_refresh_token_,
1301 use_service_account_));
1303 return HostSignalingManager::Create(this, context_->network_task_runner(),
1304 context_->url_request_context_getter(),
1305 xmpp_server_config_, talkgadget_prefix_,
1306 host_id_, key_pair_, directory_bot_jid_,
1307 oauth_credentials.Pass());
1310 void HostProcess::StartHostIfReady() {
1311 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1312 DCHECK_EQ(state_, HOST_INITIALIZING);
1314 // Start the host if both the config and the policies are loaded.
1315 if (!serialized_config_.empty() && policies_loaded_)
1316 StartHost();
1319 void HostProcess::StartHost() {
1320 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1321 DCHECK(!host_);
1322 DCHECK(!host_signaling_manager_);
1324 DCHECK(state_ == HOST_INITIALIZING || state_ == HOST_STOPPING_TO_RESTART ||
1325 state_ == HOST_STOPPED)
1326 << "state_ = " << state_;
1327 state_ = HOST_STARTED;
1329 host_signaling_manager_ = CreateHostSignalingManager();
1331 uint32 network_flags = 0;
1332 if (allow_nat_traversal_) {
1333 network_flags = NetworkSettings::NAT_TRAVERSAL_STUN |
1334 NetworkSettings::NAT_TRAVERSAL_OUTGOING;
1335 if (allow_relay_)
1336 network_flags |= NetworkSettings::NAT_TRAVERSAL_RELAY;
1339 NetworkSettings network_settings(network_flags);
1341 if (min_udp_port_ && max_udp_port_) {
1342 network_settings.min_port = min_udp_port_;
1343 network_settings.max_port = max_udp_port_;
1344 } else if (!allow_nat_traversal_) {
1345 // For legacy reasons we have to restrict the port range to a set of default
1346 // values when nat traversal is disabled, even if the port range was not
1347 // set in policy.
1348 network_settings.min_port = NetworkSettings::kDefaultMinPort;
1349 network_settings.max_port = NetworkSettings::kDefaultMaxPort;
1352 host_.reset(new ChromotingHost(
1353 host_signaling_manager_->signal_strategy(),
1354 desktop_environment_factory_.get(),
1355 CreateHostSessionManager(host_signaling_manager_->signal_strategy(),
1356 network_settings,
1357 context_->url_request_context_getter()),
1358 context_->audio_task_runner(), context_->input_task_runner(),
1359 context_->video_capture_task_runner(),
1360 context_->video_encode_task_runner(), context_->network_task_runner(),
1361 context_->ui_task_runner()));
1363 if (enable_vp9_) {
1364 scoped_ptr<protocol::CandidateSessionConfig> config =
1365 host_->protocol_config()->Clone();
1366 config->EnableVideoCodec(protocol::ChannelConfig::CODEC_VP9);
1367 host_->set_protocol_config(config.Pass());
1370 if (frame_recorder_buffer_size_ > 0) {
1371 scoped_ptr<VideoFrameRecorderHostExtension> frame_recorder_extension(
1372 new VideoFrameRecorderHostExtension());
1373 frame_recorder_extension->SetMaxContentBytes(frame_recorder_buffer_size_);
1374 host_->AddExtension(frame_recorder_extension.Pass());
1377 // TODO(simonmorris): Get the maximum session duration from a policy.
1378 #if defined(OS_LINUX)
1379 host_->SetMaximumSessionDuration(base::TimeDelta::FromHours(20));
1380 #endif
1382 host_change_notification_listener_.reset(new HostChangeNotificationListener(
1383 this, host_id_, host_signaling_manager_->signal_strategy(),
1384 directory_bot_jid_));
1386 host_status_logger_.reset(new HostStatusLogger(
1387 host_->AsWeakPtr(), ServerLogEntry::ME2ME,
1388 host_signaling_manager_->signal_strategy(), directory_bot_jid_));
1390 // Set up reporting the host status notifications.
1391 #if defined(REMOTING_MULTI_PROCESS)
1392 host_event_logger_.reset(
1393 new IpcHostEventLogger(host_->AsWeakPtr(), daemon_channel_.get()));
1394 #else // !defined(REMOTING_MULTI_PROCESS)
1395 host_event_logger_ =
1396 HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName);
1397 #endif // !defined(REMOTING_MULTI_PROCESS)
1399 host_->SetEnableCurtaining(curtain_required_);
1400 host_->Start(host_owner_email_);
1402 CreateAuthenticatorFactory();
1404 ApplyHostDomainPolicy();
1405 ApplyUsernamePolicy();
1408 void HostProcess::OnAuthFailed() {
1409 ShutdownHost(kInvalidOauthCredentialsExitCode);
1412 void HostProcess::RestartHost() {
1413 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1414 DCHECK_EQ(state_, HOST_STARTED);
1416 state_ = HOST_STOPPING_TO_RESTART;
1417 ShutdownOnNetworkThread();
1420 void HostProcess::SendOfflineReasonAndShutdownOnNetworkThread(
1421 HostExitCodes exit_code) {
1422 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1423 DCHECK(host_signaling_manager_);
1424 host_signaling_manager_.release()->SendHostOfflineReasonAndDelete(
1425 ExitCodeToString(exit_code),
1426 base::TimeDelta::FromSeconds(kHostOfflineReasonTimeoutSeconds));
1427 ShutdownOnNetworkThread();
1430 void HostProcess::ShutdownHost(HostExitCodes exit_code) {
1431 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1433 *exit_code_out_ = exit_code;
1435 switch (state_) {
1436 case HOST_INITIALIZING:
1437 state_ = HOST_STOPPING;
1438 DCHECK(!host_signaling_manager_);
1439 host_signaling_manager_ = CreateHostSignalingManager();
1440 SendOfflineReasonAndShutdownOnNetworkThread(exit_code);
1441 break;
1443 case HOST_STARTED:
1444 state_ = HOST_STOPPING;
1445 SendOfflineReasonAndShutdownOnNetworkThread(exit_code);
1446 break;
1448 case HOST_STOPPING_TO_RESTART:
1449 state_ = HOST_STOPPING;
1450 break;
1452 case HOST_STOPPING:
1453 case HOST_STOPPED:
1454 // Host is already stopped or being stopped. No action is required.
1455 break;
1459 void HostProcess::ShutdownOnNetworkThread() {
1460 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1462 host_.reset();
1463 host_event_logger_.reset();
1464 host_status_logger_.reset();
1465 host_signaling_manager_.reset();
1466 host_change_notification_listener_.reset();
1468 if (state_ == HOST_STOPPING_TO_RESTART) {
1469 StartHost();
1470 } else if (state_ == HOST_STOPPING) {
1471 state_ = HOST_STOPPED;
1473 shutdown_watchdog_->SetExitCode(*exit_code_out_);
1474 shutdown_watchdog_->Arm();
1476 config_watcher_.reset();
1478 // Complete the rest of shutdown on the main thread.
1479 context_->ui_task_runner()->PostTask(
1480 FROM_HERE, base::Bind(&HostProcess::ShutdownOnUiThread, this));
1481 } else {
1482 // This method is only called in STOPPING_TO_RESTART and STOPPING states.
1483 NOTREACHED();
1487 void HostProcess::OnCrash(const std::string& function_name,
1488 const std::string& file_name,
1489 const int& line_number) {
1490 char message[1024];
1491 base::snprintf(message, sizeof(message),
1492 "Requested by %s at %s, line %d.",
1493 function_name.c_str(), file_name.c_str(), line_number);
1494 base::debug::Alias(message);
1496 // The daemon requested us to crash the process.
1497 CHECK(false) << message;
1500 int HostProcessMain() {
1501 #if defined(OS_LINUX)
1502 // Required in order for us to run multiple X11 threads.
1503 XInitThreads();
1505 // Required for any calls into GTK functions, such as the Disconnect and
1506 // Continue windows, though these should not be used for the Me2Me case
1507 // (crbug.com/104377).
1508 gtk_init(nullptr, nullptr);
1509 #endif
1511 // Enable support for SSL server sockets, which must be done while still
1512 // single-threaded.
1513 net::EnableSSLServerSockets();
1515 // Ensures runtime specific CPU features are initialized.
1516 media::InitializeCPUSpecificMediaFeatures();
1518 // Create the main message loop and start helper threads.
1519 base::MessageLoopForUI message_loop;
1520 scoped_ptr<ChromotingHostContext> context =
1521 ChromotingHostContext::Create(new AutoThreadTaskRunner(
1522 message_loop.message_loop_proxy(), base::MessageLoop::QuitClosure()));
1523 if (!context)
1524 return kInitializationFailed;
1526 // NetworkChangeNotifier must be initialized after MessageLoop.
1527 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier(
1528 net::NetworkChangeNotifier::Create());
1530 // BasicURLRequestContext holds references to threads, so it needs to be
1531 // dereferences on UI threads. Store the reference to the URLRequestGetter to
1532 // make sure it's not destroyed on other threads.
1533 // TODO(sergeyu): Consider fixing it in BasicURLRequestContext.
1534 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
1535 context->url_request_context_getter();
1537 // Create & start the HostProcess using these threads.
1538 // TODO(wez): The HostProcess holds a reference to itself until Shutdown().
1539 // Remove this hack as part of the multi-process refactoring.
1540 int exit_code = kSuccessExitCode;
1541 ShutdownWatchdog shutdown_watchdog(
1542 base::TimeDelta::FromSeconds(kShutdownTimeoutSeconds));
1543 new HostProcess(context.Pass(), &exit_code, &shutdown_watchdog);
1545 // Run the main (also UI) message loop until the host no longer needs it.
1546 message_loop.Run();
1548 return exit_code;
1551 } // namespace remoting