Roll src/third_party/WebKit 3a0ba1e:fcd7003 (svn 191141:191149)
[chromium-blink-merge.git] / remoting / host / remoting_me2me_host.cc
blob51331685545149971eb38bd295ca6849fd48cc2a
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 // Host offline reasons not associated with shutting down the host process
151 // and therefore not expressible through HostExitCodes enum.
152 const char kHostOfflineReasonPolicyReadError[] = "POLICY_READ_ERROR";
153 const char kHostOfflineReasonPolicyChangeRequiresRestart[] =
154 "POLICY_CHANGE_REQUIRES_RESTART";
156 } // namespace
158 namespace remoting {
160 class HostProcess : public ConfigWatcher::Delegate,
161 public HostSignalingManager::Listener,
162 public HostChangeNotificationListener::Listener,
163 public IPC::Listener,
164 public base::RefCountedThreadSafe<HostProcess> {
165 public:
166 // |shutdown_watchdog| is armed when shutdown is started, and should be kept
167 // alive as long as possible until the process exits (since destroying the
168 // watchdog disarms it).
169 HostProcess(scoped_ptr<ChromotingHostContext> context,
170 int* exit_code_out,
171 ShutdownWatchdog* shutdown_watchdog);
173 // ConfigWatcher::Delegate interface.
174 void OnConfigUpdated(const std::string& serialized_config) override;
175 void OnConfigWatcherError() override;
177 // IPC::Listener implementation.
178 bool OnMessageReceived(const IPC::Message& message) override;
179 void OnChannelError() override;
181 // HostChangeNotificationListener::Listener overrides.
182 void OnHostDeleted() override;
184 // Handler of the ChromotingDaemonNetworkMsg_InitializePairingRegistry IPC
185 // message.
186 void OnInitializePairingRegistry(
187 IPC::PlatformFileForTransit privileged_key,
188 IPC::PlatformFileForTransit unprivileged_key);
190 private:
191 // See SetState method for a list of allowed state transitions.
192 enum HostState {
193 // Waiting for valid config and policies to be read from the disk.
194 // Either the host process has just been started, or it is trying to start
195 // again after temporarily going offline due to policy change or error.
196 HOST_STARTING,
198 // Host is started and running.
199 HOST_STARTED,
201 // Host is sending offline reason, before trying to restart.
202 HOST_GOING_OFFLINE_TO_RESTART,
204 // Host is sending offline reason, before shutting down.
205 HOST_GOING_OFFLINE_TO_STOP,
207 // Host has been stopped (host process will end soon).
208 HOST_STOPPED,
211 enum PolicyState {
212 // Cannot start the host, because a valid policy has not been read yet.
213 POLICY_INITIALIZING,
215 // Policy was loaded successfully.
216 POLICY_LOADED,
218 // Policy error was detected, and we haven't yet sent out a
219 // host-offline-reason (i.e. because we haven't yet read the config).
220 POLICY_ERROR_REPORT_PENDING,
222 // Policy error was detected, and we have sent out a host-offline-reason.
223 POLICY_ERROR_REPORTED,
226 friend class base::RefCountedThreadSafe<HostProcess>;
227 ~HostProcess() override;
229 void SetState(HostState target_state);
231 void StartOnNetworkThread();
233 #if defined(OS_POSIX)
234 // Callback passed to RegisterSignalHandler() to handle SIGTERM events.
235 void SigTermHandler(int signal_number);
236 #endif
238 // Called to initialize resources on the UI thread.
239 void StartOnUiThread();
241 // Initializes IPC control channel and config file path from |cmd_line|.
242 // Called on the UI thread.
243 bool InitWithCommandLine(const base::CommandLine* cmd_line);
245 // Called on the UI thread to start monitoring the configuration file.
246 void StartWatchingConfigChanges();
248 // Called on the network thread to set the host's Authenticator factory.
249 void CreateAuthenticatorFactory();
251 // Tear down resources that run on the UI thread.
252 void ShutdownOnUiThread();
254 // Applies the host config, returning true if successful.
255 bool ApplyConfig(const base::DictionaryValue& config);
257 // Handles policy updates, by calling On*PolicyUpdate methods.
258 void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies);
259 void OnPolicyError();
260 void ReportPolicyErrorAndRestartHost();
261 void ApplyHostDomainPolicy();
262 void ApplyUsernamePolicy();
263 bool OnHostDomainPolicyUpdate(base::DictionaryValue* policies);
264 bool OnUsernamePolicyUpdate(base::DictionaryValue* policies);
265 bool OnNatPolicyUpdate(base::DictionaryValue* policies);
266 bool OnRelayPolicyUpdate(base::DictionaryValue* policies);
267 bool OnUdpPortPolicyUpdate(base::DictionaryValue* policies);
268 bool OnCurtainPolicyUpdate(base::DictionaryValue* policies);
269 bool OnHostTalkGadgetPrefixPolicyUpdate(base::DictionaryValue* policies);
270 bool OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies);
271 bool OnPairingPolicyUpdate(base::DictionaryValue* policies);
272 bool OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies);
274 scoped_ptr<HostSignalingManager> CreateHostSignalingManager();
276 void StartHostIfReady();
277 void StartHost();
279 // Overrides for HostSignalingManager::Listener interface.
280 void OnHeartbeatSuccessful() override;
281 void OnUnknownHostIdError() override;
282 void OnAuthFailed() override;
284 void RestartHost(const std::string& host_offline_reason);
285 void ShutdownHost(HostExitCodes exit_code);
287 // Helper methods doing the work needed by RestartHost and ShutdownHost.
288 void GoOffline(const std::string& host_offline_reason);
289 void OnHostOfflineReasonAck(bool success);
291 #if defined(OS_WIN)
292 // Initializes the pairing registry on Windows. This should be invoked on the
293 // network thread.
294 void InitializePairingRegistry(
295 IPC::PlatformFileForTransit privileged_key,
296 IPC::PlatformFileForTransit unprivileged_key);
297 #endif // defined(OS_WIN)
299 // Crashes the process in response to a daemon's request. The daemon passes
300 // the location of the code that detected the fatal error resulted in this
301 // request.
302 void OnCrash(const std::string& function_name,
303 const std::string& file_name,
304 const int& line_number);
306 scoped_ptr<ChromotingHostContext> context_;
308 // Accessed on the UI thread.
309 scoped_ptr<IPC::ChannelProxy> daemon_channel_;
311 // XMPP server/remoting bot configuration (initialized from the command line).
312 XmppSignalStrategy::XmppServerConfig xmpp_server_config_;
313 std::string directory_bot_jid_;
315 // Created on the UI thread but used from the network thread.
316 base::FilePath host_config_path_;
317 std::string host_config_;
318 scoped_ptr<DesktopEnvironmentFactory> desktop_environment_factory_;
320 // Accessed on the network thread.
321 HostState state_;
323 scoped_ptr<ConfigWatcher> config_watcher_;
325 std::string host_id_;
326 protocol::SharedSecretHash host_secret_hash_;
327 scoped_refptr<RsaKeyPair> key_pair_;
328 std::string oauth_refresh_token_;
329 std::string serialized_config_;
330 std::string host_owner_;
331 std::string host_owner_email_;
332 bool use_service_account_;
333 bool enable_vp9_;
334 int64_t frame_recorder_buffer_size_;
336 scoped_ptr<PolicyWatcher> policy_watcher_;
337 PolicyState policy_state_;
338 std::string host_domain_;
339 bool host_username_match_required_;
340 bool allow_nat_traversal_;
341 bool allow_relay_;
342 uint16 min_udp_port_;
343 uint16 max_udp_port_;
344 std::string talkgadget_prefix_;
345 bool allow_pairing_;
347 bool curtain_required_;
348 ThirdPartyAuthConfig third_party_auth_config_;
349 bool enable_gnubby_auth_;
351 // Boolean to change flow, where necessary, if we're
352 // capturing a window instead of the entire desktop.
353 bool enable_window_capture_;
355 // Used to specify which window to stream, if enabled.
356 webrtc::WindowId window_id_;
358 // Used to send heartbeats while running, and the reason for going offline
359 // when shutting down.
360 scoped_ptr<HostSignalingManager> host_signaling_manager_;
362 scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_;
363 scoped_ptr<HostStatusLogger> host_status_logger_;
364 scoped_ptr<HostEventLogger> host_event_logger_;
366 scoped_ptr<ChromotingHost> host_;
368 // Used to keep this HostProcess alive until it is shutdown.
369 scoped_refptr<HostProcess> self_;
371 #if defined(REMOTING_MULTI_PROCESS)
372 DesktopSessionConnector* desktop_session_connector_;
373 #endif // defined(REMOTING_MULTI_PROCESS)
375 int* exit_code_out_;
376 bool signal_parent_;
378 scoped_refptr<PairingRegistry> pairing_registry_;
380 ShutdownWatchdog* shutdown_watchdog_;
382 DISALLOW_COPY_AND_ASSIGN(HostProcess);
385 HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context,
386 int* exit_code_out,
387 ShutdownWatchdog* shutdown_watchdog)
388 : context_(context.Pass()),
389 state_(HOST_STARTING),
390 use_service_account_(false),
391 enable_vp9_(false),
392 frame_recorder_buffer_size_(0),
393 policy_state_(POLICY_INITIALIZING),
394 host_username_match_required_(false),
395 allow_nat_traversal_(true),
396 allow_relay_(true),
397 min_udp_port_(0),
398 max_udp_port_(0),
399 allow_pairing_(true),
400 curtain_required_(false),
401 enable_gnubby_auth_(false),
402 enable_window_capture_(false),
403 window_id_(0),
404 #if defined(REMOTING_MULTI_PROCESS)
405 desktop_session_connector_(nullptr),
406 #endif // defined(REMOTING_MULTI_PROCESS)
407 self_(this),
408 exit_code_out_(exit_code_out),
409 signal_parent_(false),
410 shutdown_watchdog_(shutdown_watchdog) {
411 StartOnUiThread();
414 HostProcess::~HostProcess() {
415 // Verify that UI components have been torn down.
416 DCHECK(!config_watcher_);
417 DCHECK(!daemon_channel_);
418 DCHECK(!desktop_environment_factory_);
420 // We might be getting deleted on one of the threads the |host_context| owns,
421 // so we need to post it back to the caller thread to safely join & delete the
422 // threads it contains. This will go away when we move to AutoThread.
423 // |context_release()| will null |context_| before the method is invoked, so
424 // we need to pull out the task-runner on which to call DeleteSoon first.
425 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
426 context_->ui_task_runner();
427 task_runner->DeleteSoon(FROM_HERE, context_.release());
430 bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) {
431 #if defined(REMOTING_MULTI_PROCESS)
432 // Parse the handle value and convert it to a handle/file descriptor.
433 std::string channel_name =
434 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
436 int pipe_handle = 0;
437 if (channel_name.empty() ||
438 !base::StringToInt(channel_name, &pipe_handle)) {
439 LOG(ERROR) << "Invalid '" << kDaemonPipeSwitchName
440 << "' value: " << channel_name;
441 return false;
444 #if defined(OS_WIN)
445 base::win::ScopedHandle pipe(reinterpret_cast<HANDLE>(pipe_handle));
446 IPC::ChannelHandle channel_handle(pipe.Get());
447 #elif defined(OS_POSIX)
448 base::FileDescriptor pipe(pipe_handle, true);
449 IPC::ChannelHandle channel_handle(channel_name, pipe);
450 #endif // defined(OS_POSIX)
452 // Connect to the daemon process.
453 daemon_channel_ = IPC::ChannelProxy::Create(channel_handle,
454 IPC::Channel::MODE_CLIENT,
455 this,
456 context_->network_task_runner());
457 #else // !defined(REMOTING_MULTI_PROCESS)
458 // Connect to the daemon process.
459 std::string channel_name =
460 cmd_line->GetSwitchValueASCII(kDaemonPipeSwitchName);
461 if (!channel_name.empty()) {
462 daemon_channel_ =
463 IPC::ChannelProxy::Create(channel_name,
464 IPC::Channel::MODE_CLIENT,
465 this,
466 context_->network_task_runner().get());
469 if (cmd_line->HasSwitch(kHostConfigSwitchName)) {
470 host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName);
472 // Read config from stdin if necessary.
473 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
474 char buf[4096];
475 size_t len;
476 while ((len = fread(buf, 1, sizeof(buf), stdin)) > 0) {
477 host_config_.append(buf, len);
480 } else {
481 base::FilePath default_config_dir = remoting::GetConfigDir();
482 host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile);
485 if (host_config_path_ != base::FilePath(kStdinConfigPath) &&
486 !base::PathExists(host_config_path_)) {
487 LOG(ERROR) << "Can't find host config at " << host_config_path_.value();
488 return false;
490 #endif // !defined(REMOTING_MULTI_PROCESS)
492 // Ignore certificate requests - the host currently has no client certificate
493 // support, so ignoring certificate requests allows connecting to servers that
494 // request, but don't require, a certificate (optional client authentication).
495 net::URLFetcher::SetIgnoreCertificateRequests(true);
497 ServiceUrls* service_urls = ServiceUrls::GetInstance();
498 bool xmpp_server_valid = net::ParseHostAndPort(
499 service_urls->xmpp_server_address(),
500 &xmpp_server_config_.host, &xmpp_server_config_.port);
501 if (!xmpp_server_valid) {
502 LOG(ERROR) << "Invalid XMPP server: " <<
503 service_urls->xmpp_server_address();
504 return false;
506 xmpp_server_config_.use_tls = service_urls->xmpp_server_use_tls();
507 directory_bot_jid_ = service_urls->directory_bot_jid();
509 signal_parent_ = cmd_line->HasSwitch(kSignalParentSwitchName);
511 enable_window_capture_ = cmd_line->HasSwitch(kWindowIdSwitchName);
512 if (enable_window_capture_) {
514 #if defined(OS_LINUX) || defined(OS_WIN)
515 LOG(WARNING) << "Window capturing is not fully supported on Linux or "
516 "Windows.";
517 #endif // defined(OS_LINUX) || defined(OS_WIN)
519 // uint32_t is large enough to hold window IDs on all platforms.
520 uint32_t window_id;
521 if (base::StringToUint(
522 cmd_line->GetSwitchValueASCII(kWindowIdSwitchName),
523 &window_id)) {
524 window_id_ = static_cast<webrtc::WindowId>(window_id);
525 } else {
526 LOG(ERROR) << "Window with window id: " << window_id_
527 << " not found. Shutting down host.";
528 return false;
531 return true;
534 void HostProcess::OnConfigUpdated(
535 const std::string& serialized_config) {
536 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
537 context_->network_task_runner()->PostTask(FROM_HERE,
538 base::Bind(&HostProcess::OnConfigUpdated, this, serialized_config));
539 return;
542 // Filter out duplicates.
543 if (serialized_config_ == serialized_config)
544 return;
546 HOST_LOG << "Processing new host configuration.";
548 serialized_config_ = serialized_config;
549 scoped_ptr<base::DictionaryValue> config(
550 HostConfigFromJson(serialized_config));
551 if (!config) {
552 LOG(ERROR) << "Invalid configuration.";
553 ShutdownHost(kInvalidHostConfigurationExitCode);
554 return;
557 if (!ApplyConfig(*config)) {
558 LOG(ERROR) << "Failed to apply the configuration.";
559 ShutdownHost(kInvalidHostConfigurationExitCode);
560 return;
563 if (state_ == HOST_STARTING) {
564 StartHostIfReady();
565 } else if (state_ == HOST_STARTED) {
566 // Reapply policies that could be affected by a new config.
567 DCHECK_EQ(policy_state_, POLICY_LOADED);
568 ApplyHostDomainPolicy();
569 ApplyUsernamePolicy();
571 // TODO(sergeyu): Here we assume that PIN is the only part of the config
572 // that may change while the service is running. Change ApplyConfig() to
573 // detect other changes in the config and restart host if necessary here.
574 CreateAuthenticatorFactory();
578 void HostProcess::OnConfigWatcherError() {
579 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
580 ShutdownHost(kInvalidHostConfigurationExitCode);
583 // Allowed state transitions (enforced via DCHECKs in SetState method):
584 // STARTING->STARTED (once we have valid config + policy)
585 // STARTING->GOING_OFFLINE_TO_STOP
586 // STARTING->GOING_OFFLINE_TO_RESTART
587 // STARTED->GOING_OFFLINE_TO_STOP
588 // STARTED->GOING_OFFLINE_TO_RESTART
589 // GOING_OFFLINE_TO_RESTART->GOING_OFFLINE_TO_STOP
590 // GOING_OFFLINE_TO_RESTART->STARTING (after OnHostOfflineReasonAck)
591 // GOING_OFFLINE_TO_STOP->STOPPED (after OnHostOfflineReasonAck)
593 // |host_| must be not-null in STARTED state and nullptr in all other states
594 // (although this invariant can be temporarily violated when doing
595 // synchronous processing on the networking thread).
596 void HostProcess::SetState(HostState target_state) {
597 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
599 // DCHECKs below enforce state allowed transitions listed in HostState.
600 switch (state_) {
601 case HOST_STARTING:
602 DCHECK((target_state == HOST_STARTED) ||
603 (target_state == HOST_GOING_OFFLINE_TO_STOP) ||
604 (target_state == HOST_GOING_OFFLINE_TO_RESTART))
605 << state_ << " -> " << target_state;
606 break;
607 case HOST_STARTED:
608 DCHECK((target_state == HOST_GOING_OFFLINE_TO_STOP) ||
609 (target_state == HOST_GOING_OFFLINE_TO_RESTART))
610 << state_ << " -> " << target_state;
611 break;
612 case HOST_GOING_OFFLINE_TO_RESTART:
613 DCHECK((target_state == HOST_GOING_OFFLINE_TO_STOP) ||
614 (target_state == HOST_STARTING))
615 << state_ << " -> " << target_state;
616 break;
617 case HOST_GOING_OFFLINE_TO_STOP:
618 DCHECK_EQ(target_state, HOST_STOPPED);
619 break;
620 case HOST_STOPPED: // HOST_STOPPED is a terminal state.
621 default:
622 NOTREACHED() << state_ << " -> " << target_state;
623 break;
625 state_ = target_state;
628 void HostProcess::StartOnNetworkThread() {
629 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
631 #if !defined(REMOTING_MULTI_PROCESS)
632 if (host_config_path_ == base::FilePath(kStdinConfigPath)) {
633 // Process config we've read from stdin.
634 OnConfigUpdated(host_config_);
635 } else {
636 // Start watching the host configuration file.
637 config_watcher_.reset(new ConfigFileWatcher(context_->network_task_runner(),
638 context_->file_task_runner(),
639 host_config_path_));
640 config_watcher_->Watch(this);
642 #endif // !defined(REMOTING_MULTI_PROCESS)
644 #if defined(OS_POSIX)
645 remoting::RegisterSignalHandler(
646 SIGTERM,
647 base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
648 #endif // defined(OS_POSIX)
651 #if defined(OS_POSIX)
652 void HostProcess::SigTermHandler(int signal_number) {
653 DCHECK(signal_number == SIGTERM);
654 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
655 HOST_LOG << "Caught SIGTERM: Shutting down...";
656 ShutdownHost(kSuccessExitCode);
658 #endif // OS_POSIX
660 void HostProcess::CreateAuthenticatorFactory() {
661 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
663 if (state_ != HOST_STARTED)
664 return;
666 std::string local_certificate = key_pair_->GenerateCertificate();
667 if (local_certificate.empty()) {
668 LOG(ERROR) << "Failed to generate host certificate.";
669 ShutdownHost(kInitializationFailed);
670 return;
673 scoped_ptr<protocol::AuthenticatorFactory> factory;
675 if (third_party_auth_config_.is_empty()) {
676 scoped_refptr<PairingRegistry> pairing_registry;
677 if (allow_pairing_) {
678 // On Windows |pairing_registry_| is initialized in
679 // InitializePairingRegistry().
680 #if !defined(OS_WIN)
681 if (!pairing_registry_) {
682 scoped_ptr<PairingRegistry::Delegate> delegate =
683 CreatePairingRegistryDelegate();
685 if (delegate)
686 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
687 delegate.Pass());
689 #endif // defined(OS_WIN)
691 pairing_registry = pairing_registry_;
694 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
695 use_service_account_, host_owner_, local_certificate, key_pair_,
696 host_secret_hash_, pairing_registry);
698 host_->set_pairing_registry(pairing_registry);
699 } else if (third_party_auth_config_.is_valid()) {
700 scoped_ptr<protocol::TokenValidatorFactory> token_validator_factory(
701 new TokenValidatorFactoryImpl(
702 third_party_auth_config_,
703 key_pair_, context_->url_request_context_getter()));
704 factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
705 use_service_account_, host_owner_, local_certificate, key_pair_,
706 token_validator_factory.Pass());
708 } else {
709 // TODO(rmsousa): If the policy is bad the host should not go online. It
710 // should keep running, but not connected, until the policies are fixed.
711 // Having it show up as online and then reject all clients is misleading.
712 LOG(ERROR) << "One of the third-party token URLs is empty or invalid. "
713 << "Host will reject all clients until policies are corrected. "
714 << "TokenUrl: " << third_party_auth_config_.token_url << ", "
715 << "TokenValidationUrl: "
716 << third_party_auth_config_.token_validation_url;
717 factory = protocol::Me2MeHostAuthenticatorFactory::CreateRejecting();
720 #if defined(OS_POSIX)
721 // On Linux and Mac, perform a PAM authorization step after authentication.
722 factory.reset(new PamAuthorizationFactory(factory.Pass()));
723 #endif
724 host_->SetAuthenticatorFactory(factory.Pass());
727 // IPC::Listener implementation.
728 bool HostProcess::OnMessageReceived(const IPC::Message& message) {
729 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
731 #if defined(REMOTING_MULTI_PROCESS)
732 bool handled = true;
733 IPC_BEGIN_MESSAGE_MAP(HostProcess, message)
734 IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash)
735 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration,
736 OnConfigUpdated)
737 IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_InitializePairingRegistry,
738 OnInitializePairingRegistry)
739 IPC_MESSAGE_FORWARD(
740 ChromotingDaemonNetworkMsg_DesktopAttached,
741 desktop_session_connector_,
742 DesktopSessionConnector::OnDesktopSessionAgentAttached)
743 IPC_MESSAGE_FORWARD(ChromotingDaemonNetworkMsg_TerminalDisconnected,
744 desktop_session_connector_,
745 DesktopSessionConnector::OnTerminalDisconnected)
746 IPC_MESSAGE_UNHANDLED(handled = false)
747 IPC_END_MESSAGE_MAP()
749 CHECK(handled) << "Received unexpected IPC type: " << message.type();
750 return handled;
752 #else // !defined(REMOTING_MULTI_PROCESS)
753 return false;
754 #endif // !defined(REMOTING_MULTI_PROCESS)
757 void HostProcess::OnChannelError() {
758 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
760 // Shutdown the host if the daemon process disconnects the IPC channel.
761 context_->network_task_runner()->PostTask(
762 FROM_HERE,
763 base::Bind(&HostProcess::ShutdownHost, this, kSuccessExitCode));
766 void HostProcess::StartOnUiThread() {
767 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
769 if (!InitWithCommandLine(base::CommandLine::ForCurrentProcess())) {
770 // Shutdown the host if the command line is invalid.
771 context_->network_task_runner()->PostTask(
772 FROM_HERE, base::Bind(&HostProcess::ShutdownHost, this,
773 kUsageExitCode));
774 return;
777 policy_watcher_ =
778 PolicyWatcher::Create(nullptr, context_->file_task_runner());
779 policy_watcher_->StartWatching(
780 base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)),
781 base::Bind(&HostProcess::OnPolicyError, base::Unretained(this)));
783 #if defined(OS_LINUX)
784 // If an audio pipe is specific on the command-line then initialize
785 // AudioCapturerLinux to capture from it.
786 base::FilePath audio_pipe_name = base::CommandLine::ForCurrentProcess()->
787 GetSwitchValuePath(kAudioPipeSwitchName);
788 if (!audio_pipe_name.empty()) {
789 remoting::AudioCapturerLinux::InitializePipeReader(
790 context_->audio_task_runner(), audio_pipe_name);
793 base::FilePath gnubby_socket_name = base::CommandLine::ForCurrentProcess()->
794 GetSwitchValuePath(kAuthSocknameSwitchName);
795 if (!gnubby_socket_name.empty())
796 remoting::GnubbyAuthHandler::SetGnubbySocketName(gnubby_socket_name);
797 #endif // defined(OS_LINUX)
799 // Create a desktop environment factory appropriate to the build type &
800 // platform.
801 #if defined(OS_WIN)
802 IpcDesktopEnvironmentFactory* desktop_environment_factory =
803 new IpcDesktopEnvironmentFactory(
804 context_->audio_task_runner(),
805 context_->network_task_runner(),
806 context_->video_capture_task_runner(),
807 context_->network_task_runner(),
808 daemon_channel_.get());
809 desktop_session_connector_ = desktop_environment_factory;
810 #else // !defined(OS_WIN)
811 DesktopEnvironmentFactory* desktop_environment_factory;
812 if (enable_window_capture_) {
813 desktop_environment_factory =
814 new SingleWindowDesktopEnvironmentFactory(
815 context_->network_task_runner(),
816 context_->input_task_runner(),
817 context_->ui_task_runner(),
818 window_id_);
819 } else {
820 desktop_environment_factory =
821 new Me2MeDesktopEnvironmentFactory(
822 context_->network_task_runner(),
823 context_->input_task_runner(),
824 context_->ui_task_runner());
826 #endif // !defined(OS_WIN)
828 desktop_environment_factory_.reset(desktop_environment_factory);
829 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
831 context_->network_task_runner()->PostTask(
832 FROM_HERE,
833 base::Bind(&HostProcess::StartOnNetworkThread, this));
836 void HostProcess::ShutdownOnUiThread() {
837 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
839 // Tear down resources that need to be torn down on the UI thread.
840 daemon_channel_.reset();
841 desktop_environment_factory_.reset();
842 policy_watcher_.reset();
844 // It is now safe for the HostProcess to be deleted.
845 self_ = nullptr;
847 #if defined(OS_LINUX)
848 // Cause the global AudioPipeReader to be freed, otherwise the audio
849 // thread will remain in-use and prevent the process from exiting.
850 // TODO(wez): DesktopEnvironmentFactory should own the pipe reader.
851 // See crbug.com/161373 and crbug.com/104544.
852 AudioCapturerLinux::InitializePipeReader(nullptr, base::FilePath());
853 #endif
856 void HostProcess::OnUnknownHostIdError() {
857 LOG(ERROR) << "Host ID not found.";
858 ShutdownHost(kInvalidHostIdExitCode);
861 void HostProcess::OnHeartbeatSuccessful() {
862 HOST_LOG << "Host ready to receive connections.";
863 #if defined(OS_POSIX)
864 if (signal_parent_) {
865 kill(getppid(), SIGUSR1);
866 signal_parent_ = false;
868 #endif
871 void HostProcess::OnHostDeleted() {
872 LOG(ERROR) << "Host was deleted from the directory.";
873 ShutdownHost(kInvalidHostIdExitCode);
876 void HostProcess::OnInitializePairingRegistry(
877 IPC::PlatformFileForTransit privileged_key,
878 IPC::PlatformFileForTransit unprivileged_key) {
879 DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
881 #if defined(OS_WIN)
882 context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
883 &HostProcess::InitializePairingRegistry,
884 this, privileged_key, unprivileged_key));
885 #else // !defined(OS_WIN)
886 NOTREACHED();
887 #endif // !defined(OS_WIN)
890 #if defined(OS_WIN)
891 void HostProcess::InitializePairingRegistry(
892 IPC::PlatformFileForTransit privileged_key,
893 IPC::PlatformFileForTransit unprivileged_key) {
894 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
895 // |privileged_key| can be nullptr but not |unprivileged_key|.
896 DCHECK(unprivileged_key);
897 // |pairing_registry_| should only be initialized once.
898 DCHECK(!pairing_registry_);
900 HKEY privileged_hkey = reinterpret_cast<HKEY>(
901 IPC::PlatformFileForTransitToPlatformFile(privileged_key));
902 HKEY unprivileged_hkey = reinterpret_cast<HKEY>(
903 IPC::PlatformFileForTransitToPlatformFile(unprivileged_key));
905 scoped_ptr<PairingRegistryDelegateWin> delegate(
906 new PairingRegistryDelegateWin());
907 delegate->SetRootKeys(privileged_hkey, unprivileged_hkey);
909 pairing_registry_ = new PairingRegistry(context_->file_task_runner(),
910 delegate.Pass());
912 // (Re)Create the authenticator factory now that |pairing_registry_| has been
913 // initialized.
914 CreateAuthenticatorFactory();
916 #endif // !defined(OS_WIN)
918 // Applies the host config, returning true if successful.
919 bool HostProcess::ApplyConfig(const base::DictionaryValue& config) {
920 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
922 if (!config.GetString(kHostIdConfigPath, &host_id_)) {
923 LOG(ERROR) << "host_id is not defined in the config.";
924 return false;
927 std::string key_base64;
928 if (!config.GetString(kPrivateKeyConfigPath, &key_base64)) {
929 LOG(ERROR) << "Private key couldn't be read from the config file.";
930 return false;
933 key_pair_ = RsaKeyPair::FromString(key_base64);
934 if (!key_pair_.get()) {
935 LOG(ERROR) << "Invalid private key in the config file.";
936 return false;
939 std::string host_secret_hash_string;
940 if (!config.GetString(kHostSecretHashConfigPath,
941 &host_secret_hash_string)) {
942 host_secret_hash_string = "plain:";
945 if (!host_secret_hash_.Parse(host_secret_hash_string)) {
946 LOG(ERROR) << "Invalid host_secret_hash.";
947 return false;
950 // Use an XMPP connection to the Talk network for session signaling.
951 if (!config.GetString(kXmppLoginConfigPath, &xmpp_server_config_.username) ||
952 !config.GetString(kOAuthRefreshTokenConfigPath, &oauth_refresh_token_)) {
953 LOG(ERROR) << "XMPP credentials are not defined in the config.";
954 return false;
957 if (config.GetString(kHostOwnerConfigPath, &host_owner_)) {
958 // Service account configs have a host_owner, different from the xmpp_login.
959 use_service_account_ = true;
960 } else {
961 // User credential configs only have an xmpp_login, which is also the owner.
962 host_owner_ = xmpp_server_config_.username;
963 use_service_account_ = false;
966 // For non-Gmail Google accounts, the owner base JID differs from the email.
967 // host_owner_ contains the base JID (used for authenticating clients), while
968 // host_owner_email contains the account's email (used for UI and logs).
969 if (!config.GetString(kHostOwnerEmailConfigPath, &host_owner_email_)) {
970 host_owner_email_ = host_owner_;
973 // Allow offering of VP9 encoding to be overridden by the command-line.
974 if (base::CommandLine::ForCurrentProcess()->HasSwitch(kEnableVp9SwitchName)) {
975 enable_vp9_ = true;
976 } else {
977 config.GetBoolean(kEnableVp9ConfigPath, &enable_vp9_);
980 // Allow the command-line to override the size of the frame recorder buffer.
981 int frame_recorder_buffer_kb = 0;
982 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
983 kFrameRecorderBufferKbName)) {
984 std::string switch_value =
985 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
986 kFrameRecorderBufferKbName);
987 base::StringToInt(switch_value, &frame_recorder_buffer_kb);
988 } else {
989 config.GetInteger(kFrameRecorderBufferKbConfigPath,
990 &frame_recorder_buffer_kb);
992 if (frame_recorder_buffer_kb > 0) {
993 frame_recorder_buffer_size_ = 1024LL * frame_recorder_buffer_kb;
996 return true;
999 void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
1000 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
1001 context_->network_task_runner()->PostTask(
1002 FROM_HERE, base::Bind(&HostProcess::OnPolicyUpdate, this,
1003 base::Passed(&policies)));
1004 return;
1007 bool restart_required = false;
1008 restart_required |= OnHostDomainPolicyUpdate(policies.get());
1009 restart_required |= OnCurtainPolicyUpdate(policies.get());
1010 // Note: UsernamePolicyUpdate must run after OnCurtainPolicyUpdate.
1011 restart_required |= OnUsernamePolicyUpdate(policies.get());
1012 restart_required |= OnNatPolicyUpdate(policies.get());
1013 restart_required |= OnRelayPolicyUpdate(policies.get());
1014 restart_required |= OnUdpPortPolicyUpdate(policies.get());
1015 restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(policies.get());
1016 restart_required |= OnHostTokenUrlPolicyUpdate(policies.get());
1017 restart_required |= OnPairingPolicyUpdate(policies.get());
1018 restart_required |= OnGnubbyAuthPolicyUpdate(policies.get());
1020 policy_state_ = POLICY_LOADED;
1022 if (state_ == HOST_STARTING) {
1023 StartHostIfReady();
1024 } else if (state_ == HOST_STARTED) {
1025 if (restart_required)
1026 RestartHost(kHostOfflineReasonPolicyChangeRequiresRestart);
1030 void HostProcess::OnPolicyError() {
1031 if (!context_->network_task_runner()->BelongsToCurrentThread()) {
1032 context_->network_task_runner()->PostTask(
1033 FROM_HERE, base::Bind(&HostProcess::OnPolicyError, this));
1034 return;
1037 if (policy_state_ != POLICY_ERROR_REPORTED) {
1038 policy_state_ = POLICY_ERROR_REPORT_PENDING;
1039 if ((state_ == HOST_STARTED) ||
1040 (state_ == HOST_STARTING && !serialized_config_.empty())) {
1041 ReportPolicyErrorAndRestartHost();
1046 void HostProcess::ReportPolicyErrorAndRestartHost() {
1047 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1048 DCHECK(!serialized_config_.empty());
1050 DCHECK_EQ(policy_state_, POLICY_ERROR_REPORT_PENDING);
1051 policy_state_ = POLICY_ERROR_REPORTED;
1053 LOG(INFO) << "Restarting the host due to policy errors.";
1054 RestartHost(kHostOfflineReasonPolicyReadError);
1057 void HostProcess::ApplyHostDomainPolicy() {
1058 if (state_ != HOST_STARTED)
1059 return;
1061 HOST_LOG << "Policy sets host domain: " << host_domain_;
1063 if (!host_domain_.empty()) {
1064 // If the user does not have a Google email, their client JID will not be
1065 // based on their email. In that case, the username/host domain policies
1066 // would be meaningless, since there is no way to check that the JID
1067 // trying to connect actually corresponds to the owner email in question.
1068 if (host_owner_ != host_owner_email_) {
1069 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1070 << "for accounts with a non-Google email.";
1071 ShutdownHost(kInvalidHostDomainExitCode);
1074 if (!EndsWith(host_owner_, std::string("@") + host_domain_, false)) {
1075 LOG(ERROR) << "The host domain does not match the policy.";
1076 ShutdownHost(kInvalidHostDomainExitCode);
1081 bool HostProcess::OnHostDomainPolicyUpdate(base::DictionaryValue* policies) {
1082 // Returns true if the host has to be restarted after this policy update.
1083 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1085 if (!policies->GetString(policy::key::kRemoteAccessHostDomain,
1086 &host_domain_)) {
1087 return false;
1090 ApplyHostDomainPolicy();
1091 return false;
1094 void HostProcess::ApplyUsernamePolicy() {
1095 if (state_ != HOST_STARTED)
1096 return;
1098 if (host_username_match_required_) {
1099 HOST_LOG << "Policy requires host username match.";
1101 // See comment in ApplyHostDomainPolicy.
1102 if (host_owner_ != host_owner_email_) {
1103 LOG(ERROR) << "The username and host domain policies cannot be enabled "
1104 << "for accounts with a non-Google email.";
1105 ShutdownHost(kUsernameMismatchExitCode);
1108 std::string username = GetUsername();
1109 bool shutdown = username.empty() ||
1110 !StartsWithASCII(host_owner_, username + std::string("@"),
1111 false);
1113 #if defined(OS_MACOSX)
1114 // On Mac, we run as root at the login screen, so the username won't match.
1115 // However, there's no need to enforce the policy at the login screen, as
1116 // the client will have to reconnect if a login occurs.
1117 if (shutdown && getuid() == 0) {
1118 shutdown = false;
1120 #endif
1122 // Curtain-mode on Windows presents the standard OS login prompt to the user
1123 // for each connection, removing the need for an explicit user-name matching
1124 // check.
1125 #if defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1126 if (curtain_required_)
1127 return;
1128 #endif // defined(OS_WIN) && defined(REMOTING_RDP_SESSION)
1130 // Shutdown the host if the username does not match.
1131 if (shutdown) {
1132 LOG(ERROR) << "The host username does not match.";
1133 ShutdownHost(kUsernameMismatchExitCode);
1135 } else {
1136 HOST_LOG << "Policy does not require host username match.";
1140 bool HostProcess::OnUsernamePolicyUpdate(base::DictionaryValue* policies) {
1141 // Returns false: never restart the host after this policy update.
1142 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1144 if (!policies->GetBoolean(policy::key::kRemoteAccessHostMatchUsername,
1145 &host_username_match_required_)) {
1146 return false;
1149 ApplyUsernamePolicy();
1150 return false;
1153 bool HostProcess::OnNatPolicyUpdate(base::DictionaryValue* policies) {
1154 // Returns true if the host has to be restarted after this policy update.
1155 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1157 if (!policies->GetBoolean(policy::key::kRemoteAccessHostFirewallTraversal,
1158 &allow_nat_traversal_)) {
1159 return false;
1162 if (allow_nat_traversal_) {
1163 HOST_LOG << "Policy enables NAT traversal.";
1164 } else {
1165 HOST_LOG << "Policy disables NAT traversal.";
1167 return true;
1170 bool HostProcess::OnRelayPolicyUpdate(base::DictionaryValue* policies) {
1171 // Returns true if the host has to be restarted after this policy update.
1172 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1174 if (!policies->GetBoolean(
1175 policy::key::kRemoteAccessHostAllowRelayedConnection,
1176 &allow_relay_)) {
1177 return false;
1180 if (allow_relay_) {
1181 HOST_LOG << "Policy enables use of relay server.";
1182 } else {
1183 HOST_LOG << "Policy disables use of relay server.";
1185 return true;
1188 bool HostProcess::OnUdpPortPolicyUpdate(base::DictionaryValue* policies) {
1189 // Returns true if the host has to be restarted after this policy update.
1190 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1192 std::string udp_port_range;
1193 if (!policies->GetString(policy::key::kRemoteAccessHostUdpPortRange,
1194 &udp_port_range)) {
1195 return false;
1198 // Use default values if policy setting is empty or invalid.
1199 uint16 min_udp_port = 0;
1200 uint16 max_udp_port = 0;
1201 if (!udp_port_range.empty() &&
1202 !NetworkSettings::ParsePortRange(udp_port_range, &min_udp_port,
1203 &max_udp_port)) {
1204 LOG(WARNING) << "Invalid port range policy: \"" << udp_port_range
1205 << "\". Using default values.";
1208 if (min_udp_port_ != min_udp_port || max_udp_port_ != max_udp_port) {
1209 if (min_udp_port != 0 && max_udp_port != 0) {
1210 HOST_LOG << "Policy restricts UDP port range to [" << min_udp_port
1211 << ", " << max_udp_port << "]";
1212 } else {
1213 HOST_LOG << "Policy does not restrict UDP port range.";
1215 min_udp_port_ = min_udp_port;
1216 max_udp_port_ = max_udp_port;
1217 return true;
1219 return false;
1222 bool HostProcess::OnCurtainPolicyUpdate(base::DictionaryValue* policies) {
1223 // Returns true if the host has to be restarted after this policy update.
1224 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1226 if (!policies->GetBoolean(policy::key::kRemoteAccessHostRequireCurtain,
1227 &curtain_required_)) {
1228 return false;
1231 #if defined(OS_MACOSX)
1232 if (curtain_required_) {
1233 // When curtain mode is in effect on Mac, the host process runs in the
1234 // user's switched-out session, but launchd will also run an instance at
1235 // the console login screen. Even if no user is currently logged-on, we
1236 // can't support remote-access to the login screen because the current host
1237 // process model disconnects the client during login, which would leave
1238 // the logged in session un-curtained on the console until they reconnect.
1240 // TODO(jamiewalch): Fix this once we have implemented the multi-process
1241 // daemon architecture (crbug.com/134894)
1242 if (getuid() == 0) {
1243 LOG(ERROR) << "Running the host in the console login session is yet not "
1244 "supported.";
1245 ShutdownHost(kLoginScreenNotSupportedExitCode);
1246 return false;
1249 #endif
1251 if (curtain_required_) {
1252 HOST_LOG << "Policy requires curtain-mode.";
1253 } else {
1254 HOST_LOG << "Policy does not require curtain-mode.";
1257 if (host_)
1258 host_->SetEnableCurtaining(curtain_required_);
1259 return false;
1262 bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate(
1263 base::DictionaryValue* policies) {
1264 // Returns true if the host has to be restarted after this policy update.
1265 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1267 if (!policies->GetString(policy::key::kRemoteAccessHostTalkGadgetPrefix,
1268 &talkgadget_prefix_)) {
1269 return false;
1272 HOST_LOG << "Policy sets talkgadget prefix: " << talkgadget_prefix_;
1273 return true;
1276 bool HostProcess::OnHostTokenUrlPolicyUpdate(base::DictionaryValue* policies) {
1277 // Returns true if the host has to be restarted after this policy update.
1278 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1280 bool token_policy_changed = false;
1281 std::string token_url_string;
1282 if (policies->GetString(policy::key::kRemoteAccessHostTokenUrl,
1283 &token_url_string)) {
1284 token_policy_changed = true;
1285 third_party_auth_config_.token_url = GURL(token_url_string);
1287 std::string token_validation_url_string;
1288 if (policies->GetString(policy::key::kRemoteAccessHostTokenValidationUrl,
1289 &token_validation_url_string)) {
1290 token_policy_changed = true;
1291 third_party_auth_config_.token_validation_url =
1292 GURL(token_validation_url_string);
1294 if (policies->GetString(
1295 policy::key::kRemoteAccessHostTokenValidationCertificateIssuer,
1296 &third_party_auth_config_.token_validation_cert_issuer)) {
1297 token_policy_changed = true;
1300 if (token_policy_changed) {
1301 HOST_LOG << "Policy sets third-party token URLs: "
1302 << "TokenUrl: "
1303 << third_party_auth_config_.token_url << ", "
1304 << "TokenValidationUrl: "
1305 << third_party_auth_config_.token_validation_url << ", "
1306 << "TokenValidationCertificateIssuer: "
1307 << third_party_auth_config_.token_validation_cert_issuer;
1309 return token_policy_changed;
1312 bool HostProcess::OnPairingPolicyUpdate(base::DictionaryValue* policies) {
1313 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1315 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowClientPairing,
1316 &allow_pairing_)) {
1317 return false;
1320 if (allow_pairing_) {
1321 HOST_LOG << "Policy enables client pairing.";
1322 } else {
1323 HOST_LOG << "Policy disables client pairing.";
1325 return true;
1328 bool HostProcess::OnGnubbyAuthPolicyUpdate(base::DictionaryValue* policies) {
1329 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1331 if (!policies->GetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth,
1332 &enable_gnubby_auth_)) {
1333 return false;
1336 if (enable_gnubby_auth_) {
1337 HOST_LOG << "Policy enables gnubby auth.";
1338 } else {
1339 HOST_LOG << "Policy disables gnubby auth.";
1342 if (desktop_environment_factory_)
1343 desktop_environment_factory_->SetEnableGnubbyAuth(enable_gnubby_auth_);
1345 return true;
1348 scoped_ptr<HostSignalingManager> HostProcess::CreateHostSignalingManager() {
1349 DCHECK(!host_id_.empty()); // |ApplyConfig| should already have been run.
1351 scoped_ptr<OAuthTokenGetter::OAuthCredentials> oauth_credentials(
1352 new OAuthTokenGetter::OAuthCredentials(xmpp_server_config_.username,
1353 oauth_refresh_token_,
1354 use_service_account_));
1356 return HostSignalingManager::Create(
1357 this, context_->url_request_context_getter(), xmpp_server_config_,
1358 talkgadget_prefix_, host_id_, key_pair_, directory_bot_jid_,
1359 oauth_credentials.Pass());
1362 void HostProcess::StartHostIfReady() {
1363 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1364 DCHECK_EQ(state_, HOST_STARTING);
1366 // Start the host if both the config and the policies are loaded.
1367 if (!serialized_config_.empty()) {
1368 if (policy_state_ == POLICY_LOADED) {
1369 StartHost();
1370 } else if (policy_state_ == POLICY_ERROR_REPORT_PENDING) {
1371 ReportPolicyErrorAndRestartHost();
1376 void HostProcess::StartHost() {
1377 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1378 DCHECK(!host_);
1379 DCHECK(!host_signaling_manager_);
1381 SetState(HOST_STARTED);
1383 host_signaling_manager_ = CreateHostSignalingManager();
1385 uint32 network_flags = 0;
1386 if (allow_nat_traversal_) {
1387 network_flags = NetworkSettings::NAT_TRAVERSAL_STUN |
1388 NetworkSettings::NAT_TRAVERSAL_OUTGOING;
1389 if (allow_relay_)
1390 network_flags |= NetworkSettings::NAT_TRAVERSAL_RELAY;
1393 NetworkSettings network_settings(network_flags);
1395 if (min_udp_port_ && max_udp_port_) {
1396 network_settings.min_port = min_udp_port_;
1397 network_settings.max_port = max_udp_port_;
1398 } else if (!allow_nat_traversal_) {
1399 // For legacy reasons we have to restrict the port range to a set of default
1400 // values when nat traversal is disabled, even if the port range was not
1401 // set in policy.
1402 network_settings.min_port = NetworkSettings::kDefaultMinPort;
1403 network_settings.max_port = NetworkSettings::kDefaultMaxPort;
1406 host_.reset(new ChromotingHost(
1407 host_signaling_manager_->signal_strategy(),
1408 desktop_environment_factory_.get(),
1409 CreateHostSessionManager(host_signaling_manager_->signal_strategy(),
1410 network_settings,
1411 context_->url_request_context_getter()),
1412 context_->audio_task_runner(), context_->input_task_runner(),
1413 context_->video_capture_task_runner(),
1414 context_->video_encode_task_runner(), context_->network_task_runner(),
1415 context_->ui_task_runner()));
1417 if (enable_vp9_) {
1418 scoped_ptr<protocol::CandidateSessionConfig> config =
1419 host_->protocol_config()->Clone();
1420 config->EnableVideoCodec(protocol::ChannelConfig::CODEC_VP9);
1421 host_->set_protocol_config(config.Pass());
1424 if (frame_recorder_buffer_size_ > 0) {
1425 scoped_ptr<VideoFrameRecorderHostExtension> frame_recorder_extension(
1426 new VideoFrameRecorderHostExtension());
1427 frame_recorder_extension->SetMaxContentBytes(frame_recorder_buffer_size_);
1428 host_->AddExtension(frame_recorder_extension.Pass());
1431 // TODO(simonmorris): Get the maximum session duration from a policy.
1432 #if defined(OS_LINUX)
1433 host_->SetMaximumSessionDuration(base::TimeDelta::FromHours(20));
1434 #endif
1436 host_change_notification_listener_.reset(new HostChangeNotificationListener(
1437 this, host_id_, host_signaling_manager_->signal_strategy(),
1438 directory_bot_jid_));
1440 host_status_logger_.reset(new HostStatusLogger(
1441 host_->AsWeakPtr(), ServerLogEntry::ME2ME,
1442 host_signaling_manager_->signal_strategy(), directory_bot_jid_));
1444 // Set up reporting the host status notifications.
1445 #if defined(REMOTING_MULTI_PROCESS)
1446 host_event_logger_.reset(
1447 new IpcHostEventLogger(host_->AsWeakPtr(), daemon_channel_.get()));
1448 #else // !defined(REMOTING_MULTI_PROCESS)
1449 host_event_logger_ =
1450 HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName);
1451 #endif // !defined(REMOTING_MULTI_PROCESS)
1453 host_->SetEnableCurtaining(curtain_required_);
1454 host_->Start(host_owner_email_);
1456 CreateAuthenticatorFactory();
1458 ApplyHostDomainPolicy();
1459 ApplyUsernamePolicy();
1462 void HostProcess::OnAuthFailed() {
1463 ShutdownHost(kInvalidOauthCredentialsExitCode);
1466 void HostProcess::RestartHost(const std::string& host_offline_reason) {
1467 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1468 DCHECK(!host_offline_reason.empty());
1470 SetState(HOST_GOING_OFFLINE_TO_RESTART);
1471 GoOffline(host_offline_reason);
1474 void HostProcess::ShutdownHost(HostExitCodes exit_code) {
1475 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1477 *exit_code_out_ = exit_code;
1479 switch (state_) {
1480 case HOST_STARTING:
1481 case HOST_STARTED:
1482 SetState(HOST_GOING_OFFLINE_TO_STOP);
1483 GoOffline(ExitCodeToString(exit_code));
1484 break;
1486 case HOST_GOING_OFFLINE_TO_RESTART:
1487 SetState(HOST_GOING_OFFLINE_TO_STOP);
1488 break;
1490 case HOST_GOING_OFFLINE_TO_STOP:
1491 case HOST_STOPPED:
1492 // Host is already stopped or being stopped. No action is required.
1493 break;
1497 void HostProcess::GoOffline(const std::string& host_offline_reason) {
1498 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1499 DCHECK(!host_offline_reason.empty());
1500 DCHECK((state_ == HOST_GOING_OFFLINE_TO_STOP) ||
1501 (state_ == HOST_GOING_OFFLINE_TO_RESTART));
1503 // Shut down everything except the HostSignalingManager.
1504 host_.reset();
1505 host_event_logger_.reset();
1506 host_status_logger_.reset();
1507 host_change_notification_listener_.reset();
1509 // Before shutting down HostSignalingManager, send the |host_offline_reason|
1510 // if possible (i.e. if we have the config).
1511 if (!serialized_config_.empty()) {
1512 if (!host_signaling_manager_) {
1513 host_signaling_manager_ = CreateHostSignalingManager();
1516 host_signaling_manager_->SendHostOfflineReason(
1517 host_offline_reason,
1518 base::TimeDelta::FromSeconds(kHostOfflineReasonTimeoutSeconds),
1519 base::Bind(&HostProcess::OnHostOfflineReasonAck, this));
1520 return; // Shutdown will resume after OnHostOfflineReasonAck.
1523 // Continue the shutdown without sending the host offline reason.
1524 HOST_LOG << "Can't send offline reason (" << host_offline_reason << ") "
1525 << "without a valid host config.";
1526 OnHostOfflineReasonAck(false);
1529 void HostProcess::OnHostOfflineReasonAck(bool success) {
1530 DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
1531 DCHECK(!host_); // Assert that the host is really offline at this point.
1533 HOST_LOG << "SendHostOfflineReason " << (success ? "succeeded." : "failed.");
1534 host_signaling_manager_.reset();
1536 if (state_ == HOST_GOING_OFFLINE_TO_RESTART) {
1537 SetState(HOST_STARTING);
1538 StartHostIfReady();
1539 } else if (state_ == HOST_GOING_OFFLINE_TO_STOP) {
1540 SetState(HOST_STOPPED);
1542 shutdown_watchdog_->SetExitCode(*exit_code_out_);
1543 shutdown_watchdog_->Arm();
1545 config_watcher_.reset();
1547 // Complete the rest of shutdown on the main thread.
1548 context_->ui_task_runner()->PostTask(
1549 FROM_HERE, base::Bind(&HostProcess::ShutdownOnUiThread, this));
1550 } else {
1551 NOTREACHED();
1555 void HostProcess::OnCrash(const std::string& function_name,
1556 const std::string& file_name,
1557 const int& line_number) {
1558 char message[1024];
1559 base::snprintf(message, sizeof(message),
1560 "Requested by %s at %s, line %d.",
1561 function_name.c_str(), file_name.c_str(), line_number);
1562 base::debug::Alias(message);
1564 // The daemon requested us to crash the process.
1565 CHECK(false) << message;
1568 int HostProcessMain() {
1569 #if defined(OS_LINUX)
1570 // Required in order for us to run multiple X11 threads.
1571 XInitThreads();
1573 // Required for any calls into GTK functions, such as the Disconnect and
1574 // Continue windows, though these should not be used for the Me2Me case
1575 // (crbug.com/104377).
1576 gtk_init(nullptr, nullptr);
1577 #endif
1579 // Enable support for SSL server sockets, which must be done while still
1580 // single-threaded.
1581 net::EnableSSLServerSockets();
1583 // Ensures runtime specific CPU features are initialized.
1584 media::InitializeCPUSpecificMediaFeatures();
1586 // Create the main message loop and start helper threads.
1587 base::MessageLoopForUI message_loop;
1588 scoped_ptr<ChromotingHostContext> context =
1589 ChromotingHostContext::Create(new AutoThreadTaskRunner(
1590 message_loop.message_loop_proxy(), base::MessageLoop::QuitClosure()));
1591 if (!context)
1592 return kInitializationFailed;
1594 // NetworkChangeNotifier must be initialized after MessageLoop.
1595 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier(
1596 net::NetworkChangeNotifier::Create());
1598 // BasicURLRequestContext holds references to threads, so it needs to be
1599 // dereferences on UI threads. Store the reference to the URLRequestGetter to
1600 // make sure it's not destroyed on other threads.
1601 // TODO(sergeyu): Consider fixing it in BasicURLRequestContext.
1602 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
1603 context->url_request_context_getter();
1605 // Create & start the HostProcess using these threads.
1606 // TODO(wez): The HostProcess holds a reference to itself until Shutdown().
1607 // Remove this hack as part of the multi-process refactoring.
1608 int exit_code = kSuccessExitCode;
1609 ShutdownWatchdog shutdown_watchdog(
1610 base::TimeDelta::FromSeconds(kShutdownTimeoutSeconds));
1611 new HostProcess(context.Pass(), &exit_code, &shutdown_watchdog);
1613 // Run the main (also UI) message loop until the host no longer needs it.
1614 message_loop.Run();
1616 return exit_code;
1619 } // namespace remoting