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