chromium/remoting/host/remoting_me2me_host.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file implements a standalone host process for Me2Me.

#include <stddef.h>

#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/message_loop/message_pump_type.h"
#include "base/metrics/field_trial.h"
#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringize_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_executor.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/policy/policy_constants.h"
#include "components/webrtc/thread_wrapper.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_listener.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "net/base/network_change_notifier.h"
#include "net/base/url_util.h"
#include "net/socket/client_socket_factory.h"
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/base/constants.h"
#include "remoting/base/corp_session_authz_service_client_factory.h"
#include "remoting/base/cpu_utils.h"
#include "remoting/base/host_settings.h"
#include "remoting/base/is_google_email.h"
#include "remoting/base/local_session_policies_provider.h"
#include "remoting/base/logging.h"
#include "remoting/base/oauth_token_getter_impl.h"
#include "remoting/base/oauth_token_getter_proxy.h"
#include "remoting/base/rsa_key_pair.h"
#include "remoting/base/service_urls.h"
#include "remoting/base/session_policies.h"
#include "remoting/base/util.h"
#include "remoting/host/base/desktop_environment_options.h"
#include "remoting/host/base/host_exit_codes.h"
#include "remoting/host/base/switches.h"
#include "remoting/host/base/username.h"
#include "remoting/host/branding.h"
#include "remoting/host/chromoting_host.h"
#include "remoting/host/chromoting_host_context.h"
#include "remoting/host/config_file_watcher.h"
#include "remoting/host/config_watcher.h"
#include "remoting/host/corp_host_status_logger.h"
#include "remoting/host/crash_process.h"
#include "remoting/host/desktop_environment.h"
#include "remoting/host/desktop_session_connector.h"
#include "remoting/host/ftl_echo_message_listener.h"
#include "remoting/host/ftl_host_change_notification_listener.h"
#include "remoting/host/ftl_signaling_connector.h"
#include "remoting/host/heartbeat_sender.h"
#include "remoting/host/host_config.h"
#include "remoting/host/host_event_logger.h"
#include "remoting/host/host_power_save_blocker.h"
#include "remoting/host/host_status_logger.h"
#include "remoting/host/input_injector.h"
#include "remoting/host/ipc_desktop_environment.h"
#include "remoting/host/ipc_host_event_logger.h"
#include "remoting/host/me2me_desktop_environment.h"
#include "remoting/host/mojom/chromoting_host_services.mojom.h"
#include "remoting/host/mojom/desktop_session.mojom.h"
#include "remoting/host/mojom/remoting_host.mojom.h"
#include "remoting/host/pairing_registry_delegate.h"
#include "remoting/host/pin_hash.h"
#include "remoting/host/policy_watcher.h"
#include "remoting/host/security_key/security_key_auth_handler.h"
#include "remoting/host/security_key/security_key_extension.h"
#include "remoting/host/session_policies_from_dict.h"
#include "remoting/host/shutdown_watchdog.h"
#include "remoting/host/test_echo_extension.h"
#include "remoting/host/usage_stats_consent.h"
#include "remoting/host/zombie_host_detector.h"
#include "remoting/protocol/authenticator.h"
#include "remoting/protocol/channel_authenticator.h"
#include "remoting/protocol/chromium_port_allocator_factory.h"
#include "remoting/protocol/host_authentication_config.h"
#include "remoting/protocol/jingle_session_manager.h"
#include "remoting/protocol/me2me_host_authenticator_factory.h"
#include "remoting/protocol/pairing_registry.h"
#include "remoting/protocol/transport_context.h"
#include "remoting/signaling/ftl_host_device_id_provider.h"
#include "remoting/signaling/ftl_signal_strategy.h"
#include "remoting/signaling/remoting_log_to_server.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/webrtc/rtc_base/event_tracer.h"

#if BUILDFLAG(IS_POSIX)
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "base/file_descriptor_posix.h"
#include "remoting/host/pam_authorization_factory_posix.h"
#include "remoting/host/posix/signal_handler.h"
#endif  // BUILDFLAG(IS_POSIX)

#if BUILDFLAG(IS_APPLE)
#include "remoting/host/audio_capturer_mac.h"
#include "remoting/host/desktop_capturer_checker.h"
#include "remoting/host/mac/permission_utils.h"
#endif  // BUILDFLAG(IS_APPLE)

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#if defined(REMOTING_USE_X11)
#include <gtk/gtk.h>
#endif  // defined(REMOTING_USE_X11)

#if defined(REMOTING_USE_X11)
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/x/xlib_support.h"
#endif  // defined(REMOTING_USE_X11)
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include "base/linux_util.h"
#include "remoting/host/audio_capturer_linux.h"
#include "remoting/host/linux/certificate_watcher.h"
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_LINUX)
#include "remoting/host/host_utmp_logger.h"
#endif

#if BUILDFLAG(IS_WIN)
#include <commctrl.h>
#include "base/win/registry.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"
#include "remoting/host/pairing_registry_delegate_win.h"
#include "remoting/host/win/session_desktop_environment.h"
#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_LINUX)
#include "remoting/host/linux/wayland_manager.h"
#include "remoting/host/linux/wayland_utils.h"
#endif  // BUILDFLAG(IS_LINUX)

PairingRegistry;

#if BUILDFLAG(IS_APPLE)

// The following creates a section that tells Mac OS X that it is OK to let us
// inject input in the login screen. Just the name of the section is important,
// not its contents.
__attribute__((used))
__attribute__((section("__CGPreLoginApp,__cgpreloginapp")))
static const char magic_section[] = "";

#endif  // BUILDFLAG(IS_APPLE)

namespace {

#if !defined(REMOTING_MULTI_PROCESS)
// This is used for tagging system event logs.
const char kApplicationName[] =;

// Value used for --host-config option to indicate that the path must be read
// from stdin.
const char kStdinConfigPath[] =;
#endif  // !defined(REMOTING_MULTI_PROCESS)

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// The command line switch used to pass name of the pipe to capture audio on
// linux.
const char kAudioPipeSwitchName[] =;
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_POSIX)
// The command line switch used to pass name of the unix domain socket used to
// listen for security key requests.
const char kAuthSocknameSwitchName[] =;
#endif  // BUILDFLAG(IS_POSIX)

// The command line switch used by the parent to request the host to signal it
// when it is successfully started.
const char kSignalParentSwitchName[] =;

// Command line switch used to send a custom offline reason and exit.
const char kReportOfflineReasonSwitchName[] =;

// Maximum time to wait for clean shutdown to occur, before forcing termination
// of the process.
const int kShutdownTimeoutSeconds =;

// Maximum time to wait for reporting host-offline-reason to the service,
// before continuing normal process shutdown.
const int kHostOfflineReasonTimeoutSeconds =;

// Host offline reasons not associated with shutting down the host process
// and therefore not expressible through HostExitCodes enum.
const char kHostOfflineReasonPolicyReadError[] =;
const char kHostOfflineReasonPolicyChangeRequiresRestart[] =;
const char kHostOfflineReasonZombieStateDetected[] =;

// File to write webrtc trace events to. If not specified, webrtc trace events
// will not be enabled.
const char kWebRtcTraceEventFile[] =;

}  // namespace

namespace remoting {

class HostProcess : public ConfigWatcher::Delegate,
                    public FtlHostChangeNotificationListener::Listener,
                    public HeartbeatSender::Delegate,
                    public IPC::Listener,
                    public base::RefCountedThreadSafe<HostProcess>,
                    public mojom::RemotingHostControl,
                    public mojom::WorkerProcessControl {};

HostProcess::HostProcess(std::unique_ptr<ChromotingHostContext> context,
                         int* exit_code_out,
                         ShutdownWatchdog* shutdown_watchdog)
    :{}

HostProcess::~HostProcess() {}

bool HostProcess::InitWithCommandLine(const base::CommandLine* cmd_line) {}

void HostProcess::OnConfigUpdated(const std::string& serialized_config) {}

void HostProcess::OnConfigParsed(base::Value::Dict config) {}

void HostProcess::OnConfigWatcherError() {}

// Allowed state transitions (enforced via DCHECKs in SetState method):
//   STARTING->STARTED (once we have valid config + policy)
//   STARTING->GOING_OFFLINE_TO_STOP
//   STARTING->GOING_OFFLINE_TO_RESTART
//   STARTED->GOING_OFFLINE_TO_STOP
//   STARTED->GOING_OFFLINE_TO_RESTART
//   GOING_OFFLINE_TO_RESTART->GOING_OFFLINE_TO_STOP
//   GOING_OFFLINE_TO_RESTART->STARTING (after OnHostOfflineReasonAck)
//   GOING_OFFLINE_TO_STOP->STOPPED (after OnHostOfflineReasonAck)
//
// |host_| must be not-null in STARTED state and nullptr in all other states
// (although this invariant can be temporarily violated when doing
// synchronous processing on the networking thread).
void HostProcess::SetState(HostState target_state) {}

void HostProcess::StartOnNetworkThread() {}

void HostProcess::ShutdownOnNetworkThread() {}

#if BUILDFLAG(IS_POSIX)
void HostProcess::SigTermHandler(int signal_number) {}
#endif  // BUILDFLAG(IS_POSIX)

void HostProcess::CreateAuthenticatorFactory() {}

// IPC::Listener implementation.
bool HostProcess::OnMessageReceived(const IPC::Message& message) {}

void HostProcess::OnChannelError() {}

void HostProcess::OnAssociatedInterfaceRequest(
    const std::string& interface_name,
    mojo::ScopedInterfaceEndpointHandle handle) {}

void HostProcess::StartOnUiThread() {}

void HostProcess::ShutdownOnUiThread() {}

void HostProcess::OnHostNotFound() {}

void HostProcess::OnFirstHeartbeatSuccessful() {}

void HostProcess::OnUpdateHostOwner(const std::string& host_owner) {}

void HostProcess::OnUpdateIsCorpUser(bool is_corp_user) {}

void HostProcess::OnUpdateRequireSessionAuthorization(bool require) {}

void HostProcess::OnHostDeleted() {}

#if BUILDFLAG(IS_WIN)
void HostProcess::ApplyHostConfig(base::Value::Dict config) {
  DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());
  OnConfigParsed(std::move(config));
}

void HostProcess::InitializePairingRegistry(
    ::mojo::PlatformHandle privileged_handle,
    ::mojo::PlatformHandle unprivileged_handle) {
  // This IPC is handled on the UI thread and bounced over to the network thread
  // so being called on any other thread is unexpected.
  DCHECK(context_->ui_task_runner()->BelongsToCurrentThread() ||
         context_->network_task_runner()->BelongsToCurrentThread());

  if (context_->ui_task_runner()->BelongsToCurrentThread()) {
    context_->network_task_runner()->PostTask(
        FROM_HERE, base::BindOnce(&HostProcess::InitializePairingRegistry, this,
                                  std::move(privileged_handle),
                                  std::move(unprivileged_handle)));
    return;
  }
  DCHECK(context_->network_task_runner()->BelongsToCurrentThread());

  // |pairing_registry_| must only be initialized once.
  DCHECK(!pairing_registry_) << "Received multiple calls to initialize the "
                             << "pairing registry";

  std::unique_ptr<PairingRegistryDelegateWin> delegate(
      new PairingRegistryDelegateWin());
  delegate->SetRootKeys(static_cast<HKEY>(privileged_handle.ReleaseHandle()),
                        static_cast<HKEY>(unprivileged_handle.ReleaseHandle()));

  pairing_registry_ =
      new PairingRegistry(context_->file_task_runner(), std::move(delegate));

  // (Re)Create the authenticator factory now that |pairing_registry_| has been
  // initialized.
  CreateAuthenticatorFactory();
}

void HostProcess::BindChromotingHostServices(
    mojo::PendingReceiver<mojom::ChromotingHostServices> receiver,
    int peer_pid) {
  if (context_->ui_task_runner()->BelongsToCurrentThread()) {
    context_->network_task_runner()->PostTask(
        FROM_HERE, base::BindOnce(&HostProcess::BindChromotingHostServices,
                                  this, std::move(receiver), peer_pid));
    return;
  }
  // This IPC is handled on the UI thread and bounced over to the network thread
  // so being called on any other thread is unexpected.
  DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
  if (!host_) {
    LOG(ERROR) << "Binding rejected. Host has not started.";
    return;
  }
  host_->BindChromotingHostServices(std::move(receiver), peer_pid);
}

#endif  // BUILDFLAG(IS_WIN)

// Applies the host config, returning true if successful.
bool HostProcess::ApplyConfig(const base::Value::Dict& config) {}

void HostProcess::OnPolicyUpdate(base::Value::Dict policies) {}

void HostProcess::OnPolicyError() {}

void HostProcess::ReportPolicyErrorAndRestartHost() {}

void HostProcess::ApplyHostDomainListPolicy() {}

void HostProcess::ApplyAllowRemoteAccessConnections() {}

bool HostProcess::OnHostDomainListPolicyUpdate(
    const base::Value::Dict& policies) {}

bool HostProcess::OnClientDomainListPolicyUpdate(
    const base::Value::Dict& policies) {}

void HostProcess::ApplyUsernamePolicy() {}

bool HostProcess::OnUsernamePolicyUpdate(const base::Value::Dict& policies) {}

bool HostProcess::OnCurtainPolicyUpdate(const base::Value::Dict& policies) {}

bool HostProcess::OnPairingPolicyUpdate(const base::Value::Dict& policies) {}

bool HostProcess::OnGnubbyAuthPolicyUpdate(const base::Value::Dict& policies) {}

bool HostProcess::OnAllowPinAuthenticationUpdate(
    const base::Value::Dict& policies) {}

bool HostProcess::OnEnableUserInterfacePolicyUpdate(
    const base::Value::Dict& policies) {}

bool HostProcess::OnAllowRemoteAccessConnections(
    const base::Value::Dict& policies) {}

void HostProcess::InitializeSignaling() {}

void HostProcess::StartHostIfReady() {}

void HostProcess::StartHost() {}

void HostProcess::OnAuthFailed() {}

void HostProcess::OnZombieStateDetected() {}

void HostProcess::RestartHost(const std::string& host_offline_reason) {}

void HostProcess::ShutdownHost(HostExitCodes exit_code) {}

void HostProcess::GoOffline(const std::string& host_offline_reason) {}

void HostProcess::OnHostOfflineReasonAck(bool success) {}

void HostProcess::CrashProcess(const std::string& function_name,
                               const std::string& file_name,
                               int line_number) {}

int HostProcessMain() {}

}  // namespace remoting