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