// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/daemon_process.h"

#include <stdint.h>

#include <memory>
#include <utility>

#include "base/base_switches.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/process/process.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/win/registry.h"
#include "base/win/scoped_handle.h"
#include "base/win/win_util.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/base/scoped_sc_handle_win.h"
#include "remoting/host/branding.h"
#include "remoting/host/chromoting_messages.h"
#include "remoting/host/desktop_session_win.h"
#include "remoting/host/host_exit_codes.h"
#include "remoting/host/host_main.h"
#include "remoting/host/ipc_constants.h"
#include "remoting/host/pairing_registry_delegate_win.h"
#include "remoting/host/screen_resolution.h"
#include "remoting/host/switches.h"
#include "remoting/host/win/launch_process_with_token.h"
#include "remoting/host/win/security_descriptor.h"
#include "remoting/host/win/unprivileged_process_delegate.h"
#include "remoting/host/win/worker_process_launcher.h"

using base::win::ScopedHandle;
using base::TimeDelta;

namespace {

// Duplicates |key| and returns the value that can be sent over IPC.
IPC::PlatformFileForTransit GetRegistryKeyForTransit(
    const base::win::RegKey& key) {
  base::PlatformFile handle =
      reinterpret_cast<base::PlatformFile>(key.Handle());
  return IPC::GetPlatformFileForTransit(handle, false);
}

}  // namespace

namespace remoting {

class WtsTerminalMonitor;

// The command line parameters that should be copied from the service's command
// line to the host process.
const char kEnableVp9SwitchName[] = "enable-vp9";
const char kEnableH264SwitchName[] = "enable-h264";
const char* kCopiedSwitchNames[] = {switches::kV, switches::kVModule,
                                    kEnableVp9SwitchName,
                                    kEnableH264SwitchName};

class DaemonProcessWin : public DaemonProcess {
 public:
  DaemonProcessWin(
      scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
      scoped_refptr<AutoThreadTaskRunner> io_task_runner,
      const base::Closure& stopped_callback);
  ~DaemonProcessWin() override;

  // WorkerProcessIpcDelegate implementation.
  void OnChannelConnected(int32_t peer_pid) override;
  void OnPermanentError(int exit_code) override;

  // DaemonProcess overrides.
  void SendToNetwork(IPC::Message* message) override;
  bool OnDesktopSessionAgentAttached(
      int terminal_id,
      int session_id,
      const IPC::ChannelHandle& desktop_pipe) override;

 protected:
  // DaemonProcess implementation.
  std::unique_ptr<DesktopSession> DoCreateDesktopSession(
      int terminal_id,
      const ScreenResolution& resolution,
      bool virtual_terminal) override;
  void DoCrashNetworkProcess(const base::Location& location) override;
  void LaunchNetworkProcess() override;

  // Changes the service start type to 'manual'.
  void DisableAutoStart();

  // Initializes the pairing registry on the host side by sending
  // ChromotingDaemonNetworkMsg_InitializePairingRegistry message.
  bool InitializePairingRegistry();

  // Opens the pairing registry keys.
  bool OpenPairingRegistry();

 private:
  // Mojo keeps the task runner passed to it alive forever, so an
  // AutoThreadTaskRunner should not be passed to it. Otherwise, the process may
  // never shut down cleanly.
  mojo::core::ScopedIPCSupport ipc_support_;

  std::unique_ptr<WorkerProcessLauncher> network_launcher_;

  // Handle of the network process.
  ScopedHandle network_process_;

  base::win::RegKey pairing_registry_privileged_key_;
  base::win::RegKey pairing_registry_unprivileged_key_;

  DISALLOW_COPY_AND_ASSIGN(DaemonProcessWin);
};

DaemonProcessWin::DaemonProcessWin(
    scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
    scoped_refptr<AutoThreadTaskRunner> io_task_runner,
    const base::Closure& stopped_callback)
    : DaemonProcess(caller_task_runner, io_task_runner, stopped_callback),
      ipc_support_(io_task_runner->task_runner(),
                   mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST) {}

DaemonProcessWin::~DaemonProcessWin() {
}

void DaemonProcessWin::OnChannelConnected(int32_t peer_pid) {
  // Obtain the handle of the network process.
  network_process_.Set(OpenProcess(PROCESS_DUP_HANDLE, false, peer_pid));
  if (!network_process_.IsValid()) {
    CrashNetworkProcess(FROM_HERE);
    return;
  }

  if (!InitializePairingRegistry()) {
    CrashNetworkProcess(FROM_HERE);
    return;
  }

  DaemonProcess::OnChannelConnected(peer_pid);
}

void DaemonProcessWin::OnPermanentError(int exit_code) {
  DCHECK(kMinPermanentErrorExitCode <= exit_code &&
         exit_code <= kMaxPermanentErrorExitCode);

  // Both kInvalidHostIdExitCode and kInvalidOauthCredentialsExitCode are
  // errors then will never go away with the current config.
  // Disabling automatic service start until the host is re-enabled and config
  // updated.
  if (exit_code == kInvalidHostIdExitCode ||
      exit_code == kInvalidOauthCredentialsExitCode) {
    DisableAutoStart();
  }

  DaemonProcess::OnPermanentError(exit_code);
}

void DaemonProcessWin::SendToNetwork(IPC::Message* message) {
  if (network_launcher_) {
    network_launcher_->Send(message);
  } else {
    delete message;
  }
}

bool DaemonProcessWin::OnDesktopSessionAgentAttached(
    int terminal_id,
    int session_id,
    const IPC::ChannelHandle& desktop_pipe) {
  SendToNetwork(new ChromotingDaemonNetworkMsg_DesktopAttached(
      terminal_id, session_id, desktop_pipe));
  return true;
}

std::unique_ptr<DesktopSession> DaemonProcessWin::DoCreateDesktopSession(
    int terminal_id,
    const ScreenResolution& resolution,
    bool virtual_terminal) {
  DCHECK(caller_task_runner()->BelongsToCurrentThread());

  if (virtual_terminal) {
    return DesktopSessionWin::CreateForVirtualTerminal(
        caller_task_runner(), io_task_runner(), this, terminal_id, resolution);
  } else {
    return DesktopSessionWin::CreateForConsole(
        caller_task_runner(), io_task_runner(), this, terminal_id, resolution);
  }
}

void DaemonProcessWin::DoCrashNetworkProcess(const base::Location& location) {
  DCHECK(caller_task_runner()->BelongsToCurrentThread());

  network_launcher_->Crash(location);
}

void DaemonProcessWin::LaunchNetworkProcess() {
  DCHECK(caller_task_runner()->BelongsToCurrentThread());
  DCHECK(!network_launcher_);

  // Construct the host binary name.
  base::FilePath host_binary;
  if (!GetInstalledBinaryPath(kHostBinaryName, &host_binary)) {
    Stop();
    return;
  }

  std::unique_ptr<base::CommandLine> target(new base::CommandLine(host_binary));
  target->AppendSwitchASCII(kProcessTypeSwitchName, kProcessTypeHost);
  target->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
                           kCopiedSwitchNames, base::size(kCopiedSwitchNames));

  std::unique_ptr<UnprivilegedProcessDelegate> delegate(
      new UnprivilegedProcessDelegate(io_task_runner(), std::move(target)));
  network_launcher_.reset(new WorkerProcessLauncher(std::move(delegate), this));
}

std::unique_ptr<DaemonProcess> DaemonProcess::Create(
    scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
    scoped_refptr<AutoThreadTaskRunner> io_task_runner,
    const base::Closure& stopped_callback) {
  std::unique_ptr<DaemonProcessWin> daemon_process(new DaemonProcessWin(
      caller_task_runner, io_task_runner, stopped_callback));
  daemon_process->Initialize();
  return std::move(daemon_process);
}

void DaemonProcessWin::DisableAutoStart() {
  ScopedScHandle scmanager(
      OpenSCManager(nullptr, SERVICES_ACTIVE_DATABASE,
                    SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE));
  if (!scmanager.IsValid()) {
    PLOG(INFO) << "Failed to connect to the service control manager";
    return;
  }

  DWORD desired_access = SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS;
  ScopedScHandle service(
      OpenService(scmanager.Get(), kWindowsServiceName, desired_access));
  if (!service.IsValid()) {
    PLOG(INFO) << "Failed to open to the '" << kWindowsServiceName
               << "' service";
    return;
  }

  // Change the service start type to 'manual'. All |nullptr| parameters below
  // mean that there is no change to the corresponding service parameter.
  if (!ChangeServiceConfig(service.Get(),
                           SERVICE_NO_CHANGE,
                           SERVICE_DEMAND_START,
                           SERVICE_NO_CHANGE,
                           nullptr,
                           nullptr,
                           nullptr,
                           nullptr,
                           nullptr,
                           nullptr,
                           nullptr)) {
    PLOG(INFO) << "Failed to change the '" << kWindowsServiceName
               << "'service start type to 'manual'";
  }
}

bool DaemonProcessWin::InitializePairingRegistry() {
  if (!pairing_registry_privileged_key_.Valid()) {
    if (!OpenPairingRegistry())
      return false;
  }

  // Duplicate handles to the network process.
  IPC::PlatformFileForTransit privileged_key = GetRegistryKeyForTransit(
      pairing_registry_privileged_key_);
  IPC::PlatformFileForTransit unprivileged_key = GetRegistryKeyForTransit(
      pairing_registry_unprivileged_key_);
  if (!(privileged_key.IsValid() && unprivileged_key.IsValid()))
    return false;

  // Initialize the pairing registry in the network process. This has to be done
  // before the host configuration is sent, otherwise the host will not use
  // the passed handles.
  SendToNetwork(new ChromotingDaemonNetworkMsg_InitializePairingRegistry(
      privileged_key, unprivileged_key));

  return true;
}

// A chromoting top crasher revealed that the pairing registry keys sometimes
// cannot be opened. The speculation is that those keys are absent for some
// reason. To reduce the host crashes we create those keys here if they are
// absent. See crbug.com/379360 for details.
bool DaemonProcessWin::OpenPairingRegistry() {
  DCHECK(!pairing_registry_privileged_key_.Valid());
  DCHECK(!pairing_registry_unprivileged_key_.Valid());

  // Open the root of the pairing registry. Create if absent.
  base::win::RegKey root;
  DWORD disposition;
  LONG result = root.CreateWithDisposition(
      HKEY_LOCAL_MACHINE, kPairingRegistryKeyName, &disposition,
      KEY_READ | KEY_CREATE_SUB_KEY);

  if (result != ERROR_SUCCESS) {
    ::SetLastError(result);
    PLOG(ERROR) << "Failed to open or create HKLM\\" << kPairingRegistryKeyName;
    return false;
  }

  if (disposition == REG_CREATED_NEW_KEY)
    LOG(WARNING) << "Created pairing registry root key which was absent.";

  // Open the pairing registry clients key. Create if absent.
  base::win::RegKey unprivileged;
  result = unprivileged.CreateWithDisposition(
      root.Handle(), kPairingRegistryClientsKeyName, &disposition,
      KEY_READ | KEY_WRITE);

  if (result != ERROR_SUCCESS) {
    ::SetLastError(result);
    PLOG(ERROR) << "Failed to open or create HKLM\\" << kPairingRegistryKeyName
                << "\\" << kPairingRegistryClientsKeyName;
    return false;
  }

  if (disposition == REG_CREATED_NEW_KEY)
    LOG(WARNING) << "Created pairing registry client key which was absent.";

  // Open the pairing registry secret key.
  base::win::RegKey privileged;
  result = privileged.Open(
      root.Handle(), kPairingRegistrySecretsKeyName, KEY_READ | KEY_WRITE);

  if (result == ERROR_FILE_NOT_FOUND) {
    LOG(WARNING) << "Pairing registry privileged key absent, creating.";

    // Create a security descriptor that gives full access to local system and
    // administrators and denies access by anyone else.
    std::string security_descriptor = "O:BAG:BAD:(A;;GA;;;BA)(A;;GA;;;SY)";

    ScopedSd sd = ConvertSddlToSd(security_descriptor);
    if (!sd) {
      PLOG(ERROR) << "Failed to create a security descriptor for the pairing"
                  << "registry privileged key.";
      return false;
    }

    SECURITY_ATTRIBUTES security_attributes = {0};
    security_attributes.nLength = sizeof(security_attributes);
    security_attributes.lpSecurityDescriptor = sd.get();
    security_attributes.bInheritHandle = FALSE;

    HKEY key = nullptr;
    result = ::RegCreateKeyEx(
        root.Handle(), kPairingRegistrySecretsKeyName, 0, nullptr, 0,
        KEY_READ | KEY_WRITE, &security_attributes, &key, &disposition);
    privileged.Set(key);
  }

  if (result != ERROR_SUCCESS) {
    ::SetLastError(result);
    PLOG(ERROR) << "Failed to open or create HKLM\\" << kPairingRegistryKeyName
                << "\\" << kPairingRegistrySecretsKeyName;
    return false;
  }

  pairing_registry_privileged_key_.Set(privileged.Take());
  pairing_registry_unprivileged_key_.Set(unprivileged.Take());
  return true;
}

}  // namespace remoting
