// Copyright 2012 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cryptohome/lockbox-cache.h"

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

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <bindings/device_management_backend.pb.h>
#include <brillo/proto_bindings/install_attributes.pb.h>
#include <brillo/secure_blob.h>
#include <metrics/metrics_library.h>
#include <policy/device_local_account_policy_util.h>
#include <policy/device_policy_impl.h>

#include "cryptohome/lockbox.h"

namespace cryptohome {
namespace {
// Permissions of cache file (modulo umask).
const mode_t kCacheFilePermissions = 0644;
// Permissions of persistent file (modulo umask).
const mode_t kPersistentFilePermissions = 0644;
// An indicator to indicate that this is a device where we restored attributes.
const char kRestoredInstallAttributesFile[] =
    "/home/.shadow/install_attributes.restored";
// Record the result of the install attributes restoring process.
const char kInstallAttributesRestoreState[] =
    "Platform.DeviceManagement.InstallAttributesRestoreResult";
// The maximum length of the domain is 253, and assume the user name is
// less than 256, the total length of the username should be less than 512.
const size_t kMaxUsernameLength = 512;
// The maximum length of the device id is 36 (uuid length).
const size_t kMaxDeviceIdLength = 36;

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class RestoreResult {
  kNoDevicePolicy = 0,
  kSuccessWithEmpty = 1,
  kSuccessWithEnterprise = 2,
  kFailed = 3,
  kMaxValue = kFailed,
};

enum class Mode {
  kConsumerDeviceMode,
  kEnterpriseDeviceMode,
  kLegacyRetailDeviceMode,
  kConsumerKioskDeviceMode,
  kDemoDeviceMode,
};

bool AddSerializedAttribute(SerializedInstallAttributes& attrs,
                            const std::string& name,
                            const std::string& value) {
  SerializedInstallAttributes::Attribute* attr = attrs.add_attributes();
  if (!attr) {
    LOG(ERROR) << "Failed to add a new attribute.";
    return false;
  }

  attr->set_name(name);
  attr->set_value(value + std::string("\0", 1));
  return true;
}

std::optional<SerializedInstallAttributes> SerializedInstallAttributesFromMode(
    Mode mode, const enterprise_management::PolicyData& policy_data) {
  if (policy_data.username().size() > kMaxUsernameLength) {
    LOG(ERROR) << "Username is too long.";
    return std::nullopt;
  }
  if (policy_data.device_id().size() > kMaxDeviceIdLength) {
    LOG(ERROR) << "Device ID is too long.";
    return std::nullopt;
  }
  SerializedInstallAttributes attrs;
  attrs.set_version(1);

  std::string kiosk_enabled;
  std::string enterprise_owned;
  std::string enterprise_mode;
  std::string domain;
  std::string device_id;
  switch (mode) {
    case Mode::kConsumerDeviceMode:
      enterprise_owned = "true";
      enterprise_mode = "consumer";
      domain = policy::ExtractDomainName(policy_data.username());
      device_id = policy_data.device_id();
      break;
    case Mode::kEnterpriseDeviceMode:
      enterprise_owned = "true";
      enterprise_mode = "enterprise";
      domain = policy::ExtractDomainName(policy_data.username());
      device_id = policy_data.device_id();
      break;
    case Mode::kLegacyRetailDeviceMode:
      enterprise_owned = "true";
      enterprise_mode = "kiosk";
      domain = policy::ExtractDomainName(policy_data.username());
      device_id = policy_data.device_id();
      break;
    case Mode::kConsumerKioskDeviceMode:
      kiosk_enabled = "true";
      enterprise_mode = "consumer_kiosk";
      break;
    case Mode::kDemoDeviceMode:
      enterprise_owned = "true";
      enterprise_mode = "demo_mode";
      domain = policy::ExtractDomainName(policy_data.username());
      device_id = policy_data.device_id();
      break;
  }

  if (!AddSerializedAttribute(attrs, "consumer.app_kiosk_enabled",
                              kiosk_enabled)) {
    return std::nullopt;
  }
  if (!AddSerializedAttribute(attrs, "enterprise.owned", enterprise_owned)) {
    return std::nullopt;
  }
  if (!AddSerializedAttribute(attrs, "enterprise.mode", enterprise_mode)) {
    return std::nullopt;
  }
  if (!AddSerializedAttribute(attrs, "enterprise.domain", domain)) {
    return std::nullopt;
  }
  if (!AddSerializedAttribute(attrs, "enterprise.realm", "")) {
    return std::nullopt;
  }
  if (!AddSerializedAttribute(attrs, "enterprise.device_id", device_id)) {
    return std::nullopt;
  }

  return attrs;
}

bool RestoreIfVerificationPasses(const base::FilePath& lockbox_path,
                                 const SerializedInstallAttributes& attrs,
                                 libstorage::Platform& platform,
                                 LockboxContents& lockbox,
                                 brillo::Blob& lockbox_data) {
  lockbox_data.resize(attrs.ByteSizeLong());

  attrs.SerializeWithCachedSizesToArray(
      static_cast<google::protobuf::uint8*>(lockbox_data.data()));

  if (lockbox.Verify(lockbox_data) !=
      LockboxContents::VerificationResult::kValid) {
    return false;
  }

  // Indicate that we restored the install attributes.
  if (!platform.WriteFileAtomic(base::FilePath(kRestoredInstallAttributesFile),
                                lockbox_data, kPersistentFilePermissions)) {
    LOG(ERROR) << "Failed to write install attributes indicator";
    return false;
  }

  // Restore the install attributes file.
  if (!platform.WriteFileAtomic(lockbox_path, lockbox_data,
                                kPersistentFilePermissions)) {
    LOG(ERROR) << "Failed to write cache file";
    return false;
  }

  return true;
}

bool RestoreEmptyInstallAttributes(const base::FilePath& lockbox_path,
                                   libstorage::Platform& platform,
                                   LockboxContents& lockbox,
                                   brillo::Blob& lockbox_data) {
  SerializedInstallAttributes attrs;
  attrs.set_version(1);

  /* Try to restore with empty SerializedInstallAttributes */
  if (!RestoreIfVerificationPasses(lockbox_path, attrs, platform, lockbox,
                                   lockbox_data)) {
    return false;
  }

  LOG(INFO) << "Restored with empty install attributes successfully.";
  return true;
}

bool RestoreEnterpriseInstallAttributes(
    const base::FilePath& lockbox_path,
    const enterprise_management::PolicyData& policy_data,
    libstorage::Platform& platform,
    LockboxContents& lockbox,
    brillo::Blob& lockbox_data) {
  for (Mode mode : {
           Mode::kEnterpriseDeviceMode,
           Mode::kDemoDeviceMode,
           Mode::kConsumerKioskDeviceMode,
           Mode::kLegacyRetailDeviceMode,
           Mode::kConsumerDeviceMode,
       }) {
    std::optional<SerializedInstallAttributes> attrs =
        SerializedInstallAttributesFromMode(mode, policy_data);
    if (!attrs.has_value()) {
      continue;
    }
    if (RestoreIfVerificationPasses(lockbox_path, *attrs, platform, lockbox,
                                    lockbox_data)) {
      LOG(INFO) << "Restored with enterprise (mode= " << static_cast<int>(mode)
                << ") install attributes successfully.";
      return true;
    }
  }

  return false;
}

bool RestoreInstallAttributes(const base::FilePath& lockbox_path,
                              libstorage::Platform& platform,
                              LockboxContents& lockbox,
                              brillo::Blob& lockbox_data) {
  MetricsLibrary metrics;

  policy::DevicePolicyImpl device_policy;
  bool policy_loaded = device_policy.LoadPolicy(/*delete_invalid_files=*/false);
  if (device_policy.get_number_of_policy_files() == 0 || !policy_loaded) {
    LOG(ERROR) << "No valid device policy.";
    metrics.SendEnumToUMA(kInstallAttributesRestoreState,
                          RestoreResult::kNoDevicePolicy);
    return false;
  }

  const enterprise_management::PolicyData& policy_data =
      device_policy.get_policy_data();

  if (RestoreEmptyInstallAttributes(lockbox_path, platform, lockbox,
                                    lockbox_data)) {
    metrics.SendEnumToUMA(kInstallAttributesRestoreState,
                          RestoreResult::kSuccessWithEmpty);
    return true;
  }
  if (RestoreEnterpriseInstallAttributes(lockbox_path, policy_data, platform,
                                         lockbox, lockbox_data)) {
    metrics.SendEnumToUMA(kInstallAttributesRestoreState,
                          RestoreResult::kSuccessWithEnterprise);
    return true;
  }

  LOG(ERROR) << "Failed to restore install attributes.";
  metrics.SendEnumToUMA(kInstallAttributesRestoreState, RestoreResult::kFailed);
  return false;
}

}  // namespace

bool CacheLockbox(libstorage::Platform* platform,
                  const base::FilePath& nvram_path,
                  const base::FilePath& lockbox_path,
                  const base::FilePath& cache_path) {
  brillo::SecureBlob nvram;
  if (!platform->ReadFileToSecureBlob(nvram_path, &nvram)) {
    LOG(INFO) << "Failed to read NVRAM contents from " << nvram_path.value();
    return false;
  }
  std::unique_ptr<LockboxContents> lockbox = LockboxContents::New();
  if (!lockbox) {
    LOG(ERROR) << "Unsupported lockbox size!";
    return false;
  }
  if (!lockbox->Decode(nvram)) {
    LOG(ERROR) << "Lockbox failed to decode NVRAM data";
    return false;
  }

  brillo::Blob lockbox_data;
  if (!platform->ReadFile(lockbox_path, &lockbox_data)) {
    LOG(INFO) << "Failed to read lockbox data from " << lockbox_path.value();
    if (!RestoreInstallAttributes(lockbox_path, *platform, *lockbox,
                                  lockbox_data)) {
      return false;
    }
  }
  if (lockbox->Verify(lockbox_data) !=
      LockboxContents::VerificationResult::kValid) {
    LOG(ERROR) << "Lockbox did not verify!";
    if (!RestoreInstallAttributes(lockbox_path, *platform, *lockbox,
                                  lockbox_data)) {
      return false;
    }
  }

  // Write atomically (not durably) because cache file resides on tmpfs.
  if (!platform->WriteFileAtomic(cache_path, lockbox_data,
                                 kCacheFilePermissions)) {
    LOG(ERROR) << "Failed to write cache file";
    return false;
  }

  return true;
}

}  // namespace cryptohome
