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