// 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 "chromeos/settings/install_attributes.h"

#include <stddef.h>

#include <utility>

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
#include "base/system/sys_info.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "chromeos/chromeos_paths.h"
#include "chromeos/dbus/cryptohome/rpc.pb.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/util/tpm_util.h"
#include "components/policy/proto/install_attributes.pb.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace {

InstallAttributes* g_install_attributes = nullptr;

// Calling SetForTesting sets this flag. This flag means that the production
// code which calls Initialize and Shutdown will have no effect - the test
// install attributes will remain in place until ShutdownForTesting is called.
bool g_using_install_attributes_for_testing = false;

// Number of TPM lock state query retries during consistency check.
const int kDbusRetryCount = 12;

// Interval of TPM lock state query retries during consistency check.
const int kDbusRetryIntervalInSeconds = 5;

std::string ReadMapKey(const std::map<std::string, std::string>& map,
                       const std::string& key) {
  std::map<std::string, std::string>::const_iterator entry = map.find(key);
  if (entry != map.end()) {
    return entry->second;
  }
  return std::string();
}

void WarnIfNonempty(const std::map<std::string, std::string>& map,
                    const std::string& key) {
  if (!ReadMapKey(map, key).empty()) {
    LOG(WARNING) << key << " expected to be empty.";
  }
}

// Reports the metric for whether the locking succeeded with existing locked
// attributes equal to the requested ones.
void ReportExistingLockUma(bool is_existing_lock) {
  UMA_HISTOGRAM_BOOLEAN("Enterprise.ExistingInstallAttributesLock",
                        is_existing_lock);
}

}  // namespace

// static
void InstallAttributes::Initialize() {
  // Don't reinitialize if a specific instance has already been set for test.
  if (g_using_install_attributes_for_testing)
    return;

  DCHECK(!g_install_attributes);
  DCHECK(DBusThreadManager::IsInitialized());
  g_install_attributes =
      new InstallAttributes(DBusThreadManager::Get()->GetCryptohomeClient());
  base::FilePath install_attrs_file;
  CHECK(base::PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES,
                               &install_attrs_file));
  g_install_attributes->Init(install_attrs_file);
}

// static
bool InstallAttributes::IsInitialized() {
  return g_install_attributes;
}

// static
void InstallAttributes::Shutdown() {
  if (g_using_install_attributes_for_testing)
    return;

  DCHECK(g_install_attributes);
  delete g_install_attributes;
  g_install_attributes = nullptr;
}

// static
InstallAttributes* InstallAttributes::Get() {
  DCHECK(g_install_attributes);
  return g_install_attributes;
}

// static
void InstallAttributes::SetForTesting(InstallAttributes* test_instance) {
  DCHECK(!g_install_attributes);
  DCHECK(!g_using_install_attributes_for_testing);
  g_install_attributes = test_instance;
  g_using_install_attributes_for_testing = true;
}

// static
void InstallAttributes::ShutdownForTesting() {
  DCHECK(g_using_install_attributes_for_testing);
  // Don't delete the test instance, we are not the owner.
  g_install_attributes = nullptr;
  g_using_install_attributes_for_testing = false;
}

// static
std::string
InstallAttributes::GetEnterpriseOwnedInstallAttributesBlobForTesting(
    const std::string& user_name) {
  cryptohome::SerializedInstallAttributes install_attrs_proto;
  cryptohome::SerializedInstallAttributes::Attribute* attribute = nullptr;

  attribute = install_attrs_proto.add_attributes();
  attribute->set_name(InstallAttributes::kAttrEnterpriseOwned);
  attribute->set_value("true");

  attribute = install_attrs_proto.add_attributes();
  attribute->set_name(InstallAttributes::kAttrEnterpriseUser);
  attribute->set_value(user_name);

  return install_attrs_proto.SerializeAsString();
}

InstallAttributes::InstallAttributes(CryptohomeClient* cryptohome_client)
    : cryptohome_client_(cryptohome_client),
      weak_ptr_factory_(this) {
}

InstallAttributes::~InstallAttributes() {}

void InstallAttributes::Init(const base::FilePath& cache_file) {
  DCHECK(!device_locked_);

  // Mark the consistency check as running to ensure that LockDevice() is
  // blocked, but wait for the cryptohome service to be available before
  // actually calling TriggerConsistencyCheck().
  consistency_check_running_ = true;
  cryptohome_client_->WaitForServiceToBeAvailable(
      base::Bind(&InstallAttributes::OnCryptohomeServiceInitiallyAvailable,
                 weak_ptr_factory_.GetWeakPtr()));

  if (!base::PathExists(cache_file)) {
    LOG_IF(WARNING, base::SysInfo::IsRunningOnChromeOS())
        << "Install attributes missing, first sign in";
    return;
  }

  device_locked_ = true;

  char buf[16384];
  int len = base::ReadFile(cache_file, buf, sizeof(buf));
  if (len == -1 || len >= static_cast<int>(sizeof(buf))) {
    PLOG(ERROR) << "Failed to read " << cache_file.value();
    return;
  }

  cryptohome::SerializedInstallAttributes install_attrs_proto;
  if (!install_attrs_proto.ParseFromArray(buf, len)) {
    LOG(ERROR) << "Failed to parse install attributes cache.";
    return;
  }

  google::protobuf::RepeatedPtrField<
      const cryptohome::SerializedInstallAttributes::Attribute>::iterator entry;
  std::map<std::string, std::string> attr_map;
  for (entry = install_attrs_proto.attributes().begin();
       entry != install_attrs_proto.attributes().end();
       ++entry) {
    // The protobuf values contain terminating null characters, so we have to
    // sanitize the value here.
    attr_map.insert(std::make_pair(entry->name(),
                                   std::string(entry->value().c_str())));
  }

  DecodeInstallAttributes(attr_map);
}

void InstallAttributes::ReadImmutableAttributes(const base::Closure& callback) {
  if (device_locked_) {
    callback.Run();
    return;
  }

  cryptohome_client_->InstallAttributesIsReady(
      base::Bind(&InstallAttributes::ReadAttributesIfReady,
                 weak_ptr_factory_.GetWeakPtr(), callback));
}

void InstallAttributes::ReadAttributesIfReady(const base::Closure& callback,
                                              base::Optional<bool> is_ready) {
  if (is_ready.value_or(false)) {
    registration_mode_ = policy::DEVICE_MODE_NOT_SET;
    if (!tpm_util::InstallAttributesIsInvalid() &&
        !tpm_util::InstallAttributesIsFirstInstall()) {
      device_locked_ = true;

      static const char* const kEnterpriseAttributes[] = {
        kAttrEnterpriseDeviceId,
        kAttrEnterpriseDomain,
        kAttrEnterpriseRealm,
        kAttrEnterpriseMode,
        kAttrEnterpriseOwned,
        kAttrEnterpriseUser,
        kAttrConsumerKioskEnabled,
      };
      std::map<std::string, std::string> attr_map;
      for (size_t i = 0; i < arraysize(kEnterpriseAttributes); ++i) {
        std::string value;
        if (tpm_util::InstallAttributesGet(kEnterpriseAttributes[i], &value))
          attr_map[kEnterpriseAttributes[i]] = value;
      }

      DecodeInstallAttributes(attr_map);
    }
  }
  callback.Run();
}

void InstallAttributes::SetBlockDevmodeInTpm(
    bool block_devmode,
    DBusMethodCallback<cryptohome::BaseReply> callback) {
  DCHECK(!callback.is_null());
  DCHECK(!device_locked_);

  cryptohome::SetFirmwareManagementParametersRequest request;
  // Set the flags, according to enum FirmwareManagementParametersFlags from
  // rpc.proto if devmode is blocked.
  if (block_devmode) {
    request.set_flags(
        cryptohome::DEVELOPER_DISABLE_BOOT |
        cryptohome::DEVELOPER_DISABLE_CASE_CLOSED_DEBUGGING_UNLOCK);
  }

  cryptohome_client_->SetFirmwareManagementParametersInTpm(request,
                                                           std::move(callback));
}

void InstallAttributes::LockDevice(policy::DeviceMode device_mode,
                                   const std::string& domain,
                                   const std::string& realm,
                                   const std::string& device_id,
                                   const LockResultCallback& callback) {
  CHECK((device_mode == policy::DEVICE_MODE_ENTERPRISE && !domain.empty() &&
         realm.empty() && !device_id.empty()) ||
        (device_mode == policy::DEVICE_MODE_ENTERPRISE_AD && domain.empty() &&
         !realm.empty() && !device_id.empty()) ||
        (device_mode == policy::DEVICE_MODE_DEMO && !domain.empty() &&
         realm.empty() && !device_id.empty()) ||
        (device_mode == policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH &&
         domain.empty() && realm.empty() && device_id.empty()));
  DCHECK(!callback.is_null());
  CHECK_EQ(device_lock_running_, false);

  // Check for existing lock first.
  if (device_locked_) {
    if (device_mode != registration_mode_) {
      LOG(ERROR) << "Trying to re-lock with wrong mode: device_mode: "
                 << device_mode
                 << ", registration_mode: " << registration_mode_;
      callback.Run(LOCK_WRONG_MODE);
      return;
    }

    if (domain != registration_domain_ ||
        realm != registration_realm_ ||
        device_id != registration_device_id_) {
      LOG(ERROR) << "Trying to re-lock with non-matching parameters.";
      callback.Run(LOCK_WRONG_DOMAIN);
      return;
    }

    // Already locked in the right mode, signal success.
    ReportExistingLockUma(true /* is_existing_lock */);
    callback.Run(LOCK_SUCCESS);
    return;
  }

  // In case the consistency check is still running, postpone the device locking
  // until it has finished.  This should not introduce additional delay since
  // device locking must wait for TPM initialization anyways.
  if (consistency_check_running_) {
    CHECK(post_check_action_.is_null());
    post_check_action_ = base::Bind(&InstallAttributes::LockDevice,
                                    weak_ptr_factory_.GetWeakPtr(),
                                    device_mode,
                                    domain,
                                    realm,
                                    device_id,
                                    callback);
    return;
  }

  device_lock_running_ = true;
  cryptohome_client_->InstallAttributesIsReady(
      base::BindOnce(&InstallAttributes::LockDeviceIfAttributesIsReady,
                     weak_ptr_factory_.GetWeakPtr(), device_mode, domain, realm,
                     device_id, callback));
}

void InstallAttributes::LockDeviceIfAttributesIsReady(
    policy::DeviceMode device_mode,
    const std::string& domain,
    const std::string& realm,
    const std::string& device_id,
    const LockResultCallback& callback,
    base::Optional<bool> is_ready) {
  if (!is_ready.has_value() || !is_ready.value()) {
    device_lock_running_ = false;
    callback.Run(LOCK_NOT_READY);
    return;
  }

  // Clearing the TPM password seems to be always a good deal.
  if (tpm_util::TpmIsEnabled() && !tpm_util::TpmIsBeingOwned() &&
      tpm_util::TpmIsOwned()) {
    cryptohome_client_->CallTpmClearStoredPasswordAndBlock();
  }

  // Make sure we really have a working InstallAttrs.
  if (tpm_util::InstallAttributesIsInvalid()) {
    LOG(ERROR) << "Install attributes invalid.";
    device_lock_running_ = false;
    callback.Run(LOCK_BACKEND_INVALID);
    return;
  }

  if (!tpm_util::InstallAttributesIsFirstInstall()) {
    LOG(ERROR) << "Install attributes already installed.";
    device_lock_running_ = false;
    callback.Run(LOCK_ALREADY_LOCKED);
    return;
  }

  // Set values in the InstallAttrs.
  std::string kiosk_enabled, enterprise_owned;
  if (device_mode == policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH) {
    kiosk_enabled = "true";
  } else {
    enterprise_owned = "true";
  }
  std::string mode = GetDeviceModeString(device_mode);
  if (!tpm_util::InstallAttributesSet(kAttrConsumerKioskEnabled,
                                      kiosk_enabled) ||
      !tpm_util::InstallAttributesSet(kAttrEnterpriseOwned, enterprise_owned) ||
      !tpm_util::InstallAttributesSet(kAttrEnterpriseMode, mode) ||
      !tpm_util::InstallAttributesSet(kAttrEnterpriseDomain, domain) ||
      !tpm_util::InstallAttributesSet(kAttrEnterpriseRealm, realm) ||
      !tpm_util::InstallAttributesSet(kAttrEnterpriseDeviceId, device_id)) {
    LOG(ERROR) << "Failed writing attributes.";
    device_lock_running_ = false;
    callback.Run(LOCK_SET_ERROR);
    return;
  }

  if (!tpm_util::InstallAttributesFinalize() ||
      tpm_util::InstallAttributesIsFirstInstall()) {
    LOG(ERROR) << "Failed locking.";
    device_lock_running_ = false;
    callback.Run(LOCK_FINALIZE_ERROR);
    return;
  }

  ReadImmutableAttributes(
      base::Bind(&InstallAttributes::OnReadImmutableAttributes,
                 weak_ptr_factory_.GetWeakPtr(),
                 device_mode,
                 domain,
                 realm,
                 device_id,
                 callback));
}

void InstallAttributes::OnReadImmutableAttributes(
    policy::DeviceMode mode,
    const std::string& domain,
    const std::string& realm,
    const std::string& device_id,
    const LockResultCallback& callback) {
  device_lock_running_ = false;

  if (registration_mode_ != mode ||
      registration_domain_ != domain ||
      registration_realm_ != realm ||
      registration_device_id_ != device_id) {
    LOG(ERROR) << "Locked data doesn't match.";
    callback.Run(LOCK_READBACK_ERROR);
    return;
  }

  ReportExistingLockUma(false /* is_existing_lock */);
  callback.Run(LOCK_SUCCESS);
}

bool InstallAttributes::IsEnterpriseManaged() const {
  if (!device_locked_) {
    return false;
  }
  return registration_mode_ == policy::DEVICE_MODE_ENTERPRISE ||
         registration_mode_ == policy::DEVICE_MODE_ENTERPRISE_AD ||
         registration_mode_ == policy::DEVICE_MODE_DEMO;
}

bool InstallAttributes::IsActiveDirectoryManaged() const {
  if (!device_locked_) {
    return false;
  }
  return registration_mode_ == policy::DEVICE_MODE_ENTERPRISE_AD;
}

bool InstallAttributes::IsCloudManaged() const {
  if (!device_locked_) {
    return false;
  }
  return registration_mode_ == policy::DEVICE_MODE_ENTERPRISE ||
         registration_mode_ == policy::DEVICE_MODE_DEMO;
}

bool InstallAttributes::IsConsumerKioskDeviceWithAutoLaunch() {
  return device_locked_ &&
         registration_mode_ == policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
}

void InstallAttributes::TriggerConsistencyCheck(int dbus_retries) {
  cryptohome_client_->TpmGetPassword(
      base::Bind(&InstallAttributes::OnTpmGetPasswordCompleted,
                 weak_ptr_factory_.GetWeakPtr(), dbus_retries));
}

void InstallAttributes::OnTpmGetPasswordCompleted(
    int dbus_retries_remaining,
    base::Optional<std::string> result) {
  if (!result.has_value() && dbus_retries_remaining) {
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&InstallAttributes::TriggerConsistencyCheck,
                   weak_ptr_factory_.GetWeakPtr(), dbus_retries_remaining - 1),
        base::TimeDelta::FromSeconds(kDbusRetryIntervalInSeconds));
    return;
  }

  base::HistogramBase::Sample state;
  // If the result has a value, we are interested if install attributes file
  // exists (device_locked_), if the device is enrolled (registration_mode_) and
  // if the TPM is locked, meaning the TPM password is deleted so
  // the value from result is empty.
  if (result.has_value()) {
    const bool is_cloud_managed =
        registration_mode_ == policy::DEVICE_MODE_ENTERPRISE ||
        registration_mode_ == policy::DEVICE_MODE_DEMO;
    state = (device_locked_ ? 1 : 0) | (is_cloud_managed ? 2 : 0) |
            (result->empty() ? 4 : 0);
  } else {
    state = 8;
  }
  UMA_HISTOGRAM_ENUMERATION("Enterprise.AttributesTPMConsistency", state, 9);

  // Run any action (LockDevice call) that might have queued behind the
  // consistency check.
  consistency_check_running_ = false;
  if (!post_check_action_.is_null()) {
    post_check_action_.Run();
    post_check_action_.Reset();
  }
}

// Warning: The values for these keys (but not the keys themselves) are stored
// in the protobuf with a trailing zero.  Also note that some of these constants
// have been copied to login_manager/device_policy_service.cc.  Please make sure
// that all changes to the constants are reflected there as well.
const char InstallAttributes::kConsumerDeviceMode[] = "consumer";
const char InstallAttributes::kEnterpriseDeviceMode[] = "enterprise";
const char InstallAttributes::kEnterpriseADDeviceMode[] = "enterprise_ad";
const char InstallAttributes::kLegacyRetailDeviceMode[] = "kiosk";
const char InstallAttributes::kConsumerKioskDeviceMode[] = "consumer_kiosk";
const char InstallAttributes::kDemoDeviceMode[] = "demo_mode";

const char InstallAttributes::kAttrEnterpriseDeviceId[] =
    "enterprise.device_id";
const char InstallAttributes::kAttrEnterpriseDomain[] = "enterprise.domain";
const char InstallAttributes::kAttrEnterpriseRealm[] = "enterprise.realm";
const char InstallAttributes::kAttrEnterpriseMode[] = "enterprise.mode";
const char InstallAttributes::kAttrEnterpriseOwned[] = "enterprise.owned";
const char InstallAttributes::kAttrEnterpriseUser[] = "enterprise.user";
const char InstallAttributes::kAttrConsumerKioskEnabled[] =
    "consumer.app_kiosk_enabled";

void InstallAttributes::OnCryptohomeServiceInitiallyAvailable(
    bool service_is_ready) {
  if (!service_is_ready)
    LOG(ERROR) << "Failed waiting for cryptohome D-Bus service availability.";

  // Start the consistency check even if we failed to wait for availability;
  // hopefully the service will become available eventually.
  TriggerConsistencyCheck(kDbusRetryCount);
}

std::string InstallAttributes::GetDeviceModeString(policy::DeviceMode mode) {
  switch (mode) {
    case policy::DEVICE_MODE_CONSUMER:
      return InstallAttributes::kConsumerDeviceMode;
    case policy::DEVICE_MODE_ENTERPRISE:
      return InstallAttributes::kEnterpriseDeviceMode;
    case policy::DEVICE_MODE_ENTERPRISE_AD:
      return InstallAttributes::kEnterpriseADDeviceMode;
    case policy::DEVICE_MODE_LEGACY_RETAIL_MODE:
      return InstallAttributes::kLegacyRetailDeviceMode;
    case policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH:
      return InstallAttributes::kConsumerKioskDeviceMode;
    case policy::DEVICE_MODE_DEMO:
      return InstallAttributes::kDemoDeviceMode;
    case policy::DEVICE_MODE_PENDING:
    case policy::DEVICE_MODE_NOT_SET:
      break;
  }
  NOTREACHED() << "Invalid device mode: " << mode;
  return std::string();
}

policy::DeviceMode InstallAttributes::GetDeviceModeFromString(
    const std::string& mode) {
  if (mode == InstallAttributes::kConsumerDeviceMode)
    return policy::DEVICE_MODE_CONSUMER;
  if (mode == InstallAttributes::kEnterpriseDeviceMode)
    return policy::DEVICE_MODE_ENTERPRISE;
  if (mode == InstallAttributes::kEnterpriseADDeviceMode)
    return policy::DEVICE_MODE_ENTERPRISE_AD;
  if (mode == InstallAttributes::kLegacyRetailDeviceMode)
    return policy::DEVICE_MODE_LEGACY_RETAIL_MODE;
  if (mode == InstallAttributes::kConsumerKioskDeviceMode)
    return policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
  if (mode == InstallAttributes::kDemoDeviceMode)
    return policy::DEVICE_MODE_DEMO;
  return policy::DEVICE_MODE_NOT_SET;
}

void InstallAttributes::DecodeInstallAttributes(
    const std::map<std::string, std::string>& attr_map) {
  // Start from a clean slate.
  registration_mode_ = policy::DEVICE_MODE_NOT_SET;
  registration_domain_.clear();
  registration_realm_.clear();
  registration_device_id_.clear();

  const std::string enterprise_owned =
      ReadMapKey(attr_map, kAttrEnterpriseOwned);
  const std::string consumer_kiosk_enabled =
      ReadMapKey(attr_map, kAttrConsumerKioskEnabled);
  const std::string mode = ReadMapKey(attr_map, kAttrEnterpriseMode);
  const std::string domain = ReadMapKey(attr_map, kAttrEnterpriseDomain);
  const std::string realm = ReadMapKey(attr_map, kAttrEnterpriseRealm);
  const std::string device_id = ReadMapKey(attr_map, kAttrEnterpriseDeviceId);
  const std::string user_deprecated = ReadMapKey(attr_map, kAttrEnterpriseUser);

  if (enterprise_owned == "true") {
    WarnIfNonempty(attr_map, kAttrConsumerKioskEnabled);
    registration_device_id_ = device_id;

    // Set registration_mode_.
    registration_mode_ = GetDeviceModeFromString(mode);
    if (registration_mode_ != policy::DEVICE_MODE_ENTERPRISE &&
        registration_mode_ != policy::DEVICE_MODE_ENTERPRISE_AD &&
        registration_mode_ != policy::DEVICE_MODE_DEMO) {
      if (!mode.empty()) {
        LOG(WARNING) << "Bad " << kAttrEnterpriseMode << ": " << mode;
      }
      registration_mode_ = policy::DEVICE_MODE_ENTERPRISE;
    }

    if (registration_mode_ == policy::DEVICE_MODE_ENTERPRISE ||
        registration_mode_ == policy::DEVICE_MODE_DEMO) {
      // Either set registration_domain_ ...
      WarnIfNonempty(attr_map, kAttrEnterpriseRealm);
      if (!domain.empty()) {
        // The canonicalization is for compatibility with earlier versions.
        registration_domain_ = gaia::CanonicalizeDomain(domain);
      } else if (!user_deprecated.empty()) {
        // Compatibility for pre M19 code.
        registration_domain_ = gaia::ExtractDomainName(user_deprecated);
      } else {
        LOG(WARNING) << "Couldn't read domain.";
      }
    } else {
      // ... or set registration_realm_.
      WarnIfNonempty(attr_map, kAttrEnterpriseDomain);
      if (!realm.empty()) {
        registration_realm_ = realm;
      } else {
        LOG(WARNING) << "Couldn't read realm.";
      }
    }

    return;
  }

  WarnIfNonempty(attr_map, kAttrEnterpriseOwned);
  WarnIfNonempty(attr_map, kAttrEnterpriseDomain);
  WarnIfNonempty(attr_map, kAttrEnterpriseRealm);
  WarnIfNonempty(attr_map, kAttrEnterpriseDeviceId);
  WarnIfNonempty(attr_map, kAttrEnterpriseUser);
  if (consumer_kiosk_enabled == "true") {
    registration_mode_ = policy::DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
    return;
  }

  WarnIfNonempty(attr_map, kAttrConsumerKioskEnabled);
  if (user_deprecated.empty()) {
    registration_mode_ = policy::DEVICE_MODE_CONSUMER;
  }
}

}  // namespace chromeos
