// Copyright 2013 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/setup/daemon_controller_delegate_win.h"

#include <stddef.h>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "base/win/scoped_bstr.h"
#include "remoting/base/scoped_sc_handle_win.h"
#include "remoting/host/branding.h"
#include "remoting/host/host_config.h"
#include "remoting/host/usage_stats_consent.h"
#include "remoting/host/win/security_descriptor.h"

namespace remoting {

namespace {

// The maximum size of the configuration file. "1MB ought to be enough" for any
// reasonable configuration we will ever need. 1MB is low enough to make
// the probability of out of memory situation fairly low. OOM is still possible
// and we will crash if it occurs.
const size_t kMaxConfigFileSize = 1024 * 1024;

// The host configuration file name.
const base::FilePath::CharType kConfigFileName[] =
    FILE_PATH_LITERAL("host.json");

// The unprivileged configuration file name.
const base::FilePath::CharType kUnprivilegedConfigFileName[] =
    FILE_PATH_LITERAL("host_unprivileged.json");

// The extension for the temporary file.
const base::FilePath::CharType kTempFileExtension[] =
    FILE_PATH_LITERAL("json~");

// The host configuration file security descriptor that enables full access to
// Local System and built-in administrators only.
const char kConfigFileSecurityDescriptor[] =
    "O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)";

const char kUnprivilegedConfigFileSecurityDescriptor[] =
    "O:BAG:BAD:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;AU)";

// Configuration keys.

// The configuration keys that cannot be specified in UpdateConfig().
const char* const kReadonlyKeys[] = {
  kHostIdConfigPath, kHostOwnerConfigPath, kHostOwnerEmailConfigPath,
  kXmppLoginConfigPath };

// The configuration keys whose values may be read by GetConfig().
const char* const kUnprivilegedConfigKeys[] = {
  kHostIdConfigPath, kXmppLoginConfigPath };

// Reads and parses the configuration file up to |kMaxConfigFileSize| in
// size.
bool ReadConfig(const base::FilePath& filename,
                std::unique_ptr<base::DictionaryValue>* config_out) {
  std::string file_content;
  if (!base::ReadFileToStringWithMaxSize(filename, &file_content,
                                         kMaxConfigFileSize)) {
    PLOG(ERROR) << "Failed to read '" << filename.value() << "'.";
    return false;
  }

  // Parse the JSON configuration, expecting it to contain a dictionary.
  std::unique_ptr<base::Value> value =
      base::JSONReader::Read(file_content, base::JSON_ALLOW_TRAILING_COMMAS);

  base::DictionaryValue* dictionary;
  if (!value || !value->GetAsDictionary(&dictionary)) {
    LOG(ERROR) << "Failed to parse '" << filename.value() << "'.";
    return false;
  }

  ignore_result(value.release());
  config_out->reset(dictionary);
  return true;
}

base::FilePath GetTempLocationFor(const base::FilePath& filename) {
  return filename.ReplaceExtension(kTempFileExtension);
}

// Writes a config file to a temporary location.
bool WriteConfigFileToTemp(const base::FilePath& filename,
                           const char* security_descriptor,
                           const std::string& content) {
  // Create the security descriptor for the configuration file.
  ScopedSd sd = ConvertSddlToSd(security_descriptor);
  if (!sd) {
    PLOG(ERROR)
        << "Failed to create a security descriptor for the configuration file";
    return false;
  }

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

  // Create a temporary file and write configuration to it.
  base::FilePath tempname = GetTempLocationFor(filename);
  base::win::ScopedHandle file(
      CreateFileW(tempname.value().c_str(),
                  GENERIC_WRITE,
                  0,
                  &security_attributes,
                  CREATE_ALWAYS,
                  FILE_FLAG_SEQUENTIAL_SCAN,
                  nullptr));

  if (!file.IsValid()) {
    PLOG(ERROR) << "Failed to create '" << filename.value() << "'";
    return false;
  }

  DWORD written;
  if (!::WriteFile(file.Get(), content.c_str(), content.length(),
                   &written, nullptr)) {
    PLOG(ERROR) << "Failed to write to '" << filename.value() << "'";
    return false;
  }

  return true;
}

// Moves a config file from its temporary location to its permanent location.
bool MoveConfigFileFromTemp(const base::FilePath& filename) {
  // Now that the configuration is stored successfully replace the actual
  // configuration file.
  base::FilePath tempname = GetTempLocationFor(filename);
  if (!MoveFileExW(tempname.value().c_str(),
                   filename.value().c_str(),
                   MOVEFILE_REPLACE_EXISTING)) {
      PLOG(ERROR) << "Failed to rename '" << tempname.value() << "' to '"
                  << filename.value() << "'";
      return false;
  }

  return true;
}

// Writes the configuration file up to |kMaxConfigFileSize| in size.
bool WriteConfig(const std::string& content) {
  if (content.length() > kMaxConfigFileSize) {
      return false;
  }

  // Extract the configuration data that the user will verify.
  std::unique_ptr<base::Value> config_value = base::JSONReader::Read(content);
  if (!config_value.get()) {
    return false;
  }
  base::DictionaryValue* config_dict = nullptr;
  if (!config_value->GetAsDictionary(&config_dict)) {
    return false;
  }
  std::string email;
  if (!config_dict->GetString(kHostOwnerEmailConfigPath, &email) &&
      !config_dict->GetString(kHostOwnerConfigPath, &email) &&
      !config_dict->GetString(kXmppLoginConfigPath, &email)) {
    return false;
  }
  std::string host_id, host_secret_hash;
  if (!config_dict->GetString(kHostIdConfigPath, &host_id) ||
      !config_dict->GetString(kHostSecretHashConfigPath, &host_secret_hash)) {
    return false;
  }

  // Extract the unprivileged fields from the configuration.
  base::DictionaryValue unprivileged_config_dict;
  for (const char* key : kUnprivilegedConfigKeys) {
    base::string16 value;
    if (config_dict->GetString(key, &value)) {
      unprivileged_config_dict.SetString(key, value);
    }
  }
  std::string unprivileged_config_str;
  base::JSONWriter::Write(unprivileged_config_dict, &unprivileged_config_str);

  // Write the full configuration file to a temporary location.
  base::FilePath full_config_file_path =
      remoting::GetConfigDir().Append(kConfigFileName);
  if (!WriteConfigFileToTemp(full_config_file_path,
                             kConfigFileSecurityDescriptor,
                             content)) {
    return false;
  }

  // Write the unprivileged configuration file to a temporary location.
  base::FilePath unprivileged_config_file_path =
      remoting::GetConfigDir().Append(kUnprivilegedConfigFileName);
  if (!WriteConfigFileToTemp(unprivileged_config_file_path,
                             kUnprivilegedConfigFileSecurityDescriptor,
                             unprivileged_config_str)) {
    return false;
  }

  // Move the full and unprivileged configuration files to their permanent
  // locations.
  return MoveConfigFileFromTemp(full_config_file_path) &&
         MoveConfigFileFromTemp(unprivileged_config_file_path);
}

DaemonController::State ConvertToDaemonState(DWORD service_state) {
  switch (service_state) {
  case SERVICE_RUNNING:
    return DaemonController::STATE_STARTED;

  case SERVICE_CONTINUE_PENDING:
  case SERVICE_START_PENDING:
    return DaemonController::STATE_STARTING;
    break;

  case SERVICE_PAUSE_PENDING:
  case SERVICE_STOP_PENDING:
    return DaemonController::STATE_STOPPING;
    break;

  case SERVICE_PAUSED:
  case SERVICE_STOPPED:
    return DaemonController::STATE_STOPPED;
    break;

  default:
    NOTREACHED();
    return DaemonController::STATE_UNKNOWN;
  }
}

ScopedScHandle OpenService(DWORD access) {
  // Open the service and query its current state.
  ScopedScHandle scmanager(
      ::OpenSCManagerW(nullptr, SERVICES_ACTIVE_DATABASE,
                       SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE));
  if (!scmanager.IsValid()) {
    PLOG(ERROR) << "Failed to connect to the service control manager";
    return ScopedScHandle();
  }

  ScopedScHandle service(::OpenServiceW(scmanager.Get(), kWindowsServiceName,
                                        access));
  if (!service.IsValid()) {
    PLOG(ERROR) << "Failed to open to the '" << kWindowsServiceName
                << "' service";
  }

  return service;
}

void InvokeCompletionCallback(
    const DaemonController::CompletionCallback& done, bool success) {
  DaemonController::AsyncResult async_result =
      success ? DaemonController::RESULT_OK : DaemonController::RESULT_FAILED;
  done.Run(async_result);
}

bool StartDaemon() {
  DWORD access = SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS |
                 SERVICE_START | SERVICE_STOP;
  ScopedScHandle service = OpenService(access);
  if (!service.IsValid())
    return false;

  // Change the service start type to 'auto'.
  if (!::ChangeServiceConfigW(service.Get(),
                              SERVICE_NO_CHANGE,
                              SERVICE_AUTO_START,
                              SERVICE_NO_CHANGE,
                              nullptr,
                              nullptr,
                              nullptr,
                              nullptr,
                              nullptr,
                              nullptr,
                              nullptr)) {
    PLOG(ERROR) << "Failed to change the '" << kWindowsServiceName
                << "'service start type to 'auto'";
    return false;
  }

  // Start the service.
  if (!StartService(service.Get(), 0, nullptr)) {
    DWORD error = GetLastError();
    if (error != ERROR_SERVICE_ALREADY_RUNNING) {
      LOG(ERROR) << "Failed to start the '" << kWindowsServiceName
                  << "'service: " << error;

      return false;
    }
  }

  return true;
}

bool StopDaemon() {
  DWORD access = SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS |
                 SERVICE_START | SERVICE_STOP;
  ScopedScHandle service = OpenService(access);
  if (!service.IsValid())
    return false;

  // Change the service start type to 'manual'.
  if (!::ChangeServiceConfigW(service.Get(),
                              SERVICE_NO_CHANGE,
                              SERVICE_DEMAND_START,
                              SERVICE_NO_CHANGE,
                              nullptr,
                              nullptr,
                              nullptr,
                              nullptr,
                              nullptr,
                              nullptr,
                              nullptr)) {
    PLOG(ERROR) << "Failed to change the '" << kWindowsServiceName
                << "'service start type to 'manual'";
    return false;
  }

  // Stop the service.
  SERVICE_STATUS status;
  if (!ControlService(service.Get(), SERVICE_CONTROL_STOP, &status)) {
    DWORD error = GetLastError();
    if (error != ERROR_SERVICE_NOT_ACTIVE) {
      LOG(ERROR) << "Failed to stop the '" << kWindowsServiceName
                  << "'service: " << error;
      return false;
    }
  }

  return true;
}

}  // namespace

DaemonControllerDelegateWin::DaemonControllerDelegateWin() {
}

DaemonControllerDelegateWin::~DaemonControllerDelegateWin() {
}

DaemonController::State DaemonControllerDelegateWin::GetState() {
  // TODO(alexeypa): Make the thread alertable, so we can switch to APC
  // notifications rather than polling.
  ScopedScHandle service = OpenService(SERVICE_QUERY_STATUS);
  if (!service.IsValid())
    return DaemonController::STATE_UNKNOWN;

  SERVICE_STATUS status;
  if (!::QueryServiceStatus(service.Get(), &status)) {
    PLOG(ERROR) << "Failed to query the state of the '"
                << kWindowsServiceName << "' service";
    return DaemonController::STATE_UNKNOWN;
  }

  return ConvertToDaemonState(status.dwCurrentState);
}

std::unique_ptr<base::DictionaryValue>
DaemonControllerDelegateWin::GetConfig() {
  base::FilePath config_dir = remoting::GetConfigDir();

  // Read the unprivileged part of host configuration.
  std::unique_ptr<base::DictionaryValue> config;
  if (!ReadConfig(config_dir.Append(kUnprivilegedConfigFileName), &config))
    return nullptr;

  return config;
}

void DaemonControllerDelegateWin::UpdateConfig(
    std::unique_ptr<base::DictionaryValue> config,
    const DaemonController::CompletionCallback& done) {
  // Check for bad keys.
  for (size_t i = 0; i < arraysize(kReadonlyKeys); ++i) {
    if (config->HasKey(kReadonlyKeys[i])) {
      LOG(ERROR) << "Cannot update config: '" << kReadonlyKeys[i]
                 << "' is read only.";
      InvokeCompletionCallback(done, false);
      return;
    }
  }
  // Get the old config.
  base::FilePath config_dir = remoting::GetConfigDir();
  std::unique_ptr<base::DictionaryValue> config_old;
  if (!ReadConfig(config_dir.Append(kConfigFileName), &config_old)) {
    InvokeCompletionCallback(done, false);
    return;
  }

  // Merge items from the given config into the old config.
  config_old->MergeDictionary(config.release());

  // Write the updated config.
  std::string config_updated_str;
  base::JSONWriter::Write(*config_old, &config_updated_str);
  bool result = WriteConfig(config_updated_str);

  InvokeCompletionCallback(done, result);
}

void DaemonControllerDelegateWin::Stop(
    const DaemonController::CompletionCallback& done) {
  bool result = StopDaemon();

  InvokeCompletionCallback(done, result);
}

DaemonController::UsageStatsConsent
DaemonControllerDelegateWin::GetUsageStatsConsent() {
  DaemonController::UsageStatsConsent consent;
  consent.supported = true;
  consent.allowed = false;
  consent.set_by_policy = false;

  // Get the recorded user's consent.
  bool allowed;
  bool set_by_policy;
  // If the user's consent is not recorded yet, assume that the user didn't
  // consent to collecting crash dumps.
  if (remoting::GetUsageStatsConsent(&allowed, &set_by_policy)) {
    consent.allowed = allowed;
    consent.set_by_policy = set_by_policy;
  }

  return consent;
}

void DaemonControllerDelegateWin::SetConfigAndStart(
    std::unique_ptr<base::DictionaryValue> config,
    bool consent,
    const DaemonController::CompletionCallback& done) {
  // Record the user's consent.
  if (!remoting::SetUsageStatsConsent(consent)) {
    InvokeCompletionCallback(done, false);
    return;
  }

  // Set the configuration.
  std::string config_str;
  base::JSONWriter::Write(*config, &config_str);

  // Determine the config directory path and create it if necessary.
  base::FilePath config_dir = remoting::GetConfigDir();
  if (!base::CreateDirectory(config_dir)) {
    PLOG(ERROR) << "Failed to create the config directory.";
    InvokeCompletionCallback(done, false);
    return;
  }

  if (!WriteConfig(config_str)) {
    InvokeCompletionCallback(done, false);
    return;
  }

  // Start daemon.
  InvokeCompletionCallback(done, StartDaemon());
}

scoped_refptr<DaemonController> DaemonController::Create() {
  return new DaemonController(
      base::WrapUnique(new DaemonControllerDelegateWin()));
}

}  // namespace remoting
