// Copyright (c) 2012 The Chromium OS 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 "policy/device_policy_impl.h"

#include <algorithm>
#include <map>
#include <memory>
#include <set>
#include <string>

#include <base/check.h>
#include <base/containers/adapters.h>
#include <base/files/file_util.h>
#include <base/json/json_reader.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/memory/ptr_util.h>
#include <base/stl_util.h>
#include <base/time/time.h>
#include <base/values.h>
#include <openssl/evp.h>
#include <openssl/x509.h>

#include "bindings/chrome_device_policy.pb.h"
#include "bindings/device_management_backend.pb.h"
#include "policy/policy_util.h"
#include "policy/resilient_policy_util.h"

namespace em = enterprise_management;

namespace policy {

// TODO(crbug.com/984789): Remove once support for OpenSSL <1.1 is dropped.
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define EVP_MD_CTX_new EVP_MD_CTX_create
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
#endif

// Maximum value of RollbackAllowedMilestones policy.
const int kMaxRollbackAllowedMilestones = 4;

namespace {
const char kPolicyPath[] = "/var/lib/devicesettings/policy";
const char kPublicKeyPath[] = "/var/lib/devicesettings/owner.key";

// Reads the public key used to sign the policy from |key_file| and stores it
// in |public_key|. Returns true on success.
bool ReadPublicKeyFromFile(const base::FilePath& key_file,
                           std::string* public_key) {
  if (!base::PathExists(key_file))
    return false;
  public_key->clear();
  if (!base::ReadFileToString(key_file, public_key) || public_key->empty()) {
    LOG(ERROR) << "Could not read public key off disk";
    return false;
  }
  return true;
}

// Verifies that the |signed_data| has correct |signature| with |public_key|.
bool VerifySignature(const std::string& signed_data,
                     const std::string& signature,
                     const std::string& public_key) {
  std::unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX*)> ctx(EVP_MD_CTX_new(),
                                                         EVP_MD_CTX_free);
  if (!ctx)
    return false;

  const EVP_MD* digest = EVP_sha1();

  char* key = const_cast<char*>(public_key.data());
  BIO* bio = BIO_new_mem_buf(key, public_key.length());
  if (!bio)
    return false;

  EVP_PKEY* public_key_ssl = d2i_PUBKEY_bio(bio, nullptr);
  if (!public_key_ssl) {
    BIO_free_all(bio);
    return false;
  }

  const unsigned char* sig =
      reinterpret_cast<const unsigned char*>(signature.data());
  int rv = EVP_VerifyInit_ex(ctx.get(), digest, nullptr);
  if (rv == 1) {
    EVP_VerifyUpdate(ctx.get(), signed_data.data(), signed_data.length());
    rv = EVP_VerifyFinal(ctx.get(), sig, signature.length(), public_key_ssl);
  }

  EVP_PKEY_free(public_key_ssl);
  BIO_free_all(bio);

  return rv == 1;
}

// Decodes the connection type enum from the device settings protobuf to string
// representations. The strings must match the connection manager definitions.
std::string DecodeConnectionType(int type) {
  static const char* const kConnectionTypes[] = {
      "ethernet", "wifi", "wimax", "bluetooth", "cellular",
  };

  if (type < 0 || type >= static_cast<int>(base::size(kConnectionTypes)))
    return std::string();

  return kConnectionTypes[type];
}

// TODO(adokar): change type to base::Optional<int> when available.
int ConvertDayOfWeekStringToInt(const std::string& day_of_week_str) {
  if (day_of_week_str == "Sunday")
    return 0;
  if (day_of_week_str == "Monday")
    return 1;
  if (day_of_week_str == "Tuesday")
    return 2;
  if (day_of_week_str == "Wednesday")
    return 3;
  if (day_of_week_str == "Thursday")
    return 4;
  if (day_of_week_str == "Friday")
    return 5;
  if (day_of_week_str == "Saturday")
    return 6;
  return -1;
}

bool DecodeWeeklyTimeFromValue(const base::Value& dict_value,
                               int* day_of_week_out,
                               base::TimeDelta* time_out) {
  const std::string* day_of_week_str = dict_value.FindStringKey("day_of_week");
  if (!day_of_week_str) {
    LOG(ERROR) << "Day of the week is absent.";
    return false;
  }
  *day_of_week_out = ConvertDayOfWeekStringToInt(*day_of_week_str);
  if (*day_of_week_out == -1) {
    LOG(ERROR) << "Undefined day of the week: " << *day_of_week_str;
    return false;
  }

  base::Optional<int> hours = dict_value.FindIntKey("hours");
  if (!hours.has_value() || hours < 0 || hours > 23) {
    LOG(ERROR) << "Hours are absent or are outside of the range [0, 24).";
    return false;
  }

  base::Optional<int> minutes = dict_value.FindIntKey("minutes");
  if (!minutes.has_value() || minutes < 0 || minutes > 59) {
    LOG(ERROR) << "Minutes are absent or are outside the range [0, 60)";
    return false;
  }

  *time_out = base::TimeDelta::FromMinutes(*minutes) +
              base::TimeDelta::FromHours(*hours);
  return true;
}

base::Optional<base::Value> DecodeListValueFromJSON(
    const std::string& json_string) {
  auto decoded_json = base::JSONReader::ReadAndReturnValueWithError(
      json_string, base::JSON_ALLOW_TRAILING_COMMAS);
  if (!decoded_json.value) {
    LOG(ERROR) << "Invalid JSON string: " << decoded_json.error_message;
    return base::nullopt;
  }

  if (!decoded_json.value->is_list()) {
    LOG(ERROR) << "JSON string is not a list";
    return base::nullopt;
  }

  return std::move(decoded_json.value);
}

base::Optional<base::Value> DecodeDictValueFromJSON(
    const std::string& json_string, const std::string& entry_name) {
  auto decoded_json = base::JSONReader::ReadAndReturnValueWithError(
      json_string, base::JSON_ALLOW_TRAILING_COMMAS);
  if (!decoded_json.value) {
    LOG(ERROR) << "Invalid JSON string in " << entry_name << ": "
               << decoded_json.error_message;
    return base::nullopt;
  }

  if (!decoded_json.value->is_dict()) {
    LOG(ERROR) << "Invalid JSON string in " << entry_name << ": "
               << "JSON string is not a dictionary";
    return base::nullopt;
  }

  return std::move(decoded_json.value);
}

}  // namespace

DevicePolicyImpl::DevicePolicyImpl()
    : policy_path_(kPolicyPath), keyfile_path_(kPublicKeyPath) {}

DevicePolicyImpl::~DevicePolicyImpl() {}

bool DevicePolicyImpl::LoadPolicy() {
  std::map<int, base::FilePath> sorted_policy_file_paths =
      policy::GetSortedResilientPolicyFilePaths(policy_path_);
  if (sorted_policy_file_paths.empty())
    return false;

  // Try to load the existent policy files one by one in reverse order of their
  // index until we succeed. The default policy, if present, appears as index 0
  // in the map and is loaded the last. This is intentional as that file is the
  // oldest.
  bool policy_loaded = false;
  for (const auto& map_pair : base::Reversed(sorted_policy_file_paths)) {
    const base::FilePath& policy_path = map_pair.second;
    if (LoadPolicyFromFile(policy_path)) {
      policy_loaded = true;
      break;
    }
  }

  return policy_loaded;
}

bool DevicePolicyImpl::IsEnterpriseEnrolled() const {
  DCHECK(install_attributes_reader_);
  if (!install_attributes_reader_->IsLocked())
    return false;

  const std::string& device_mode = install_attributes_reader_->GetAttribute(
      InstallAttributesReader::kAttrMode);
  return device_mode == InstallAttributesReader::kDeviceModeEnterprise ||
         device_mode == InstallAttributesReader::kDeviceModeEnterpriseAD;
}

bool DevicePolicyImpl::GetPolicyRefreshRate(int* rate) const {
  if (!device_policy_.has_device_policy_refresh_rate())
    return false;
  *rate = static_cast<int>(
      device_policy_.device_policy_refresh_rate().device_policy_refresh_rate());
  return true;
}

bool DevicePolicyImpl::GetGuestModeEnabled(bool* guest_mode_enabled) const {
  if (!device_policy_.has_guest_mode_enabled())
    return false;
  *guest_mode_enabled =
      device_policy_.guest_mode_enabled().guest_mode_enabled();
  return true;
}

bool DevicePolicyImpl::GetCameraEnabled(bool* camera_enabled) const {
  if (!device_policy_.has_camera_enabled())
    return false;
  *camera_enabled = device_policy_.camera_enabled().camera_enabled();
  return true;
}

bool DevicePolicyImpl::GetShowUserNames(bool* show_user_names) const {
  if (!device_policy_.has_show_user_names())
    return false;
  *show_user_names = device_policy_.show_user_names().show_user_names();
  return true;
}

bool DevicePolicyImpl::GetDataRoamingEnabled(bool* data_roaming_enabled) const {
  if (!device_policy_.has_data_roaming_enabled())
    return false;
  *data_roaming_enabled =
      device_policy_.data_roaming_enabled().data_roaming_enabled();
  return true;
}

bool DevicePolicyImpl::GetAllowNewUsers(bool* allow_new_users) const {
  if (!device_policy_.has_allow_new_users())
    return false;
  *allow_new_users = device_policy_.allow_new_users().allow_new_users();
  return true;
}

bool DevicePolicyImpl::GetMetricsEnabled(bool* metrics_enabled) const {
  if (!device_policy_.has_metrics_enabled())
    return false;
  *metrics_enabled = device_policy_.metrics_enabled().metrics_enabled();
  return true;
}

bool DevicePolicyImpl::GetReportVersionInfo(bool* report_version_info) const {
  if (!device_policy_.has_device_reporting())
    return false;

  const em::DeviceReportingProto& proto = device_policy_.device_reporting();
  if (!proto.has_report_version_info())
    return false;

  *report_version_info = proto.report_version_info();
  return true;
}

bool DevicePolicyImpl::GetReportActivityTimes(
    bool* report_activity_times) const {
  if (!device_policy_.has_device_reporting())
    return false;

  const em::DeviceReportingProto& proto = device_policy_.device_reporting();
  if (!proto.has_report_activity_times())
    return false;

  *report_activity_times = proto.report_activity_times();
  return true;
}

bool DevicePolicyImpl::GetReportBootMode(bool* report_boot_mode) const {
  if (!device_policy_.has_device_reporting())
    return false;

  const em::DeviceReportingProto& proto = device_policy_.device_reporting();
  if (!proto.has_report_boot_mode())
    return false;

  *report_boot_mode = proto.report_boot_mode();
  return true;
}

bool DevicePolicyImpl::GetEphemeralUsersEnabled(
    bool* ephemeral_users_enabled) const {
  if (!device_policy_.has_ephemeral_users_enabled())
    return false;
  *ephemeral_users_enabled =
      device_policy_.ephemeral_users_enabled().ephemeral_users_enabled();
  return true;
}

bool DevicePolicyImpl::GetReleaseChannel(std::string* release_channel) const {
  if (!device_policy_.has_release_channel())
    return false;

  const em::ReleaseChannelProto& proto = device_policy_.release_channel();
  if (!proto.has_release_channel())
    return false;

  *release_channel = proto.release_channel();
  return true;
}

bool DevicePolicyImpl::GetReleaseChannelDelegated(
    bool* release_channel_delegated) const {
  if (!device_policy_.has_release_channel())
    return false;

  const em::ReleaseChannelProto& proto = device_policy_.release_channel();
  if (!proto.has_release_channel_delegated())
    return false;

  *release_channel_delegated = proto.release_channel_delegated();
  return true;
}

bool DevicePolicyImpl::GetReleaseLtsTag(std::string* lts_tag) const {
  if (!device_policy_.has_release_channel())
    return false;

  const em::ReleaseChannelProto& proto = device_policy_.release_channel();
  if (!proto.has_release_lts_tag())
    return false;

  *lts_tag = proto.release_lts_tag();
  return true;
}

bool DevicePolicyImpl::GetUpdateDisabled(bool* update_disabled) const {
  if (!IsEnterpriseEnrolled())
    return false;

  if (!device_policy_.has_auto_update_settings())
    return false;

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();
  if (!proto.has_update_disabled())
    return false;

  *update_disabled = proto.update_disabled();
  return true;
}

bool DevicePolicyImpl::GetTargetVersionPrefix(
    std::string* target_version_prefix) const {
  if (!IsEnterpriseEnrolled())
    return false;

  if (!device_policy_.has_auto_update_settings())
    return false;

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();
  if (!proto.has_target_version_prefix())
    return false;

  *target_version_prefix = proto.target_version_prefix();
  return true;
}

bool DevicePolicyImpl::GetRollbackToTargetVersion(
    int* rollback_to_target_version) const {
  if (!device_policy_.has_auto_update_settings())
    return false;

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();
  if (!proto.has_rollback_to_target_version())
    return false;

  *rollback_to_target_version = proto.rollback_to_target_version();
  return true;
}

bool DevicePolicyImpl::GetRollbackAllowedMilestones(
    int* rollback_allowed_milestones) const {
  // This policy can be only set for devices which are enterprise enrolled.
  if (!IsEnterpriseEnrolled())
    return false;

  if (device_policy_.has_auto_update_settings()) {
    const em::AutoUpdateSettingsProto& proto =
        device_policy_.auto_update_settings();
    if (proto.has_rollback_allowed_milestones()) {
      // Policy is set, enforce minimum and maximum constraints.
      *rollback_allowed_milestones = proto.rollback_allowed_milestones();
      if (*rollback_allowed_milestones < 0)
        *rollback_allowed_milestones = 0;
      if (*rollback_allowed_milestones > kMaxRollbackAllowedMilestones)
        *rollback_allowed_milestones = kMaxRollbackAllowedMilestones;
      return true;
    }
  }
  // Policy is not present, use default for enterprise devices.
  VLOG(1) << "RollbackAllowedMilestones policy is not set, using default "
          << kMaxRollbackAllowedMilestones << ".";
  *rollback_allowed_milestones = kMaxRollbackAllowedMilestones;
  return true;
}

bool DevicePolicyImpl::GetScatterFactorInSeconds(
    int64_t* scatter_factor_in_seconds) const {
  if (!device_policy_.has_auto_update_settings())
    return false;

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();
  if (!proto.has_scatter_factor_in_seconds())
    return false;

  *scatter_factor_in_seconds = proto.scatter_factor_in_seconds();
  return true;
}

bool DevicePolicyImpl::GetAllowedConnectionTypesForUpdate(
    std::set<std::string>* connection_types) const {
  if (!IsEnterpriseEnrolled())
    return false;

  if (!device_policy_.has_auto_update_settings())
    return false;

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();
  if (proto.allowed_connection_types_size() <= 0)
    return false;

  for (int i = 0; i < proto.allowed_connection_types_size(); i++) {
    std::string type = DecodeConnectionType(proto.allowed_connection_types(i));
    if (!type.empty())
      connection_types->insert(type);
  }
  return true;
}

bool DevicePolicyImpl::GetOpenNetworkConfiguration(
    std::string* open_network_configuration) const {
  if (!device_policy_.has_open_network_configuration())
    return false;

  const em::DeviceOpenNetworkConfigurationProto& proto =
      device_policy_.open_network_configuration();
  if (!proto.has_open_network_configuration())
    return false;

  *open_network_configuration = proto.open_network_configuration();
  return true;
}

bool DevicePolicyImpl::GetOwner(std::string* owner) const {
  if (IsEnterpriseManaged()) {
    *owner = "";
    return true;
  }

  if (!policy_data_.has_username())
    return false;
  *owner = policy_data_.username();
  return true;
}

bool DevicePolicyImpl::GetHttpDownloadsEnabled(
    bool* http_downloads_enabled) const {
  if (!device_policy_.has_auto_update_settings())
    return false;

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();

  if (!proto.has_http_downloads_enabled())
    return false;

  *http_downloads_enabled = proto.http_downloads_enabled();
  return true;
}

bool DevicePolicyImpl::GetAuP2PEnabled(bool* au_p2p_enabled) const {
  if (!device_policy_.has_auto_update_settings())
    return false;

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();

  if (!proto.has_p2p_enabled())
    return false;

  *au_p2p_enabled = proto.p2p_enabled();
  return true;
}

bool DevicePolicyImpl::GetAllowKioskAppControlChromeVersion(
    bool* allow_kiosk_app_control_chrome_version) const {
  if (!device_policy_.has_allow_kiosk_app_control_chrome_version())
    return false;

  const em::AllowKioskAppControlChromeVersionProto& proto =
      device_policy_.allow_kiosk_app_control_chrome_version();

  if (!proto.has_allow_kiosk_app_control_chrome_version())
    return false;

  *allow_kiosk_app_control_chrome_version =
      proto.allow_kiosk_app_control_chrome_version();
  return true;
}

bool DevicePolicyImpl::GetUsbDetachableWhitelist(
    std::vector<UsbDeviceId>* usb_whitelist) const {
  const bool has_allowlist =
      device_policy_.has_usb_detachable_allowlist() &&
      device_policy_.usb_detachable_allowlist().id_size() != 0;
  const bool has_whitelist =
      device_policy_.has_usb_detachable_whitelist() &&
      device_policy_.usb_detachable_whitelist().id_size() != 0;

  if (!has_allowlist && !has_whitelist)
    return false;

  usb_whitelist->clear();
  if (has_allowlist) {
    const em::UsbDetachableAllowlistProto& proto =
        device_policy_.usb_detachable_allowlist();
    for (int i = 0; i < proto.id_size(); i++) {
      const em::UsbDeviceIdInclusiveProto& id = proto.id(i);
      UsbDeviceId dev_id;
      dev_id.vendor_id = id.has_vendor_id() ? id.vendor_id() : 0;
      dev_id.product_id = id.has_product_id() ? id.product_id() : 0;
      usb_whitelist->push_back(dev_id);
    }
  } else {
    const em::UsbDetachableWhitelistProto& proto =
        device_policy_.usb_detachable_whitelist();
    for (int i = 0; i < proto.id_size(); i++) {
      const em::UsbDeviceIdProto& id = proto.id(i);
      UsbDeviceId dev_id;
      dev_id.vendor_id = id.has_vendor_id() ? id.vendor_id() : 0;
      dev_id.product_id = id.has_product_id() ? id.product_id() : 0;
      usb_whitelist->push_back(dev_id);
    }
  }
  return true;
}

bool DevicePolicyImpl::GetDeviceUpdateStagingSchedule(
    std::vector<DayPercentagePair>* staging_schedule_out) const {
  staging_schedule_out->clear();

  if (!device_policy_.has_auto_update_settings())
    return false;

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();

  if (!proto.has_staging_schedule())
    return false;

  base::Optional<base::Value> list_val =
      DecodeListValueFromJSON(proto.staging_schedule());
  if (!list_val)
    return false;

  for (const auto& pair_value : list_val->GetList()) {
    if (!pair_value.is_dict())
      return false;
    base::Optional<int> days = pair_value.FindIntKey("days");
    base::Optional<int> percentage = pair_value.FindIntKey("percentage");
    if (!days.has_value() || !percentage.has_value())
      return false;
    // Limit the percentage to [0, 100] and days to [1, 28];
    staging_schedule_out->push_back({std::max(std::min(*days, 28), 1),
                                     std::max(std::min(*percentage, 100), 0)});
  }

  return true;
}

bool DevicePolicyImpl::GetAutoLaunchedKioskAppId(
    std::string* app_id_out) const {
  if (!device_policy_.has_device_local_accounts())
    return false;

  const em::DeviceLocalAccountsProto& local_accounts =
      device_policy_.device_local_accounts();

  // For auto-launched kiosk apps, the delay needs to be 0.
  if (local_accounts.has_auto_login_delay() &&
      local_accounts.auto_login_delay() != 0)
    return false;

  for (const em::DeviceLocalAccountInfoProto& account :
       local_accounts.account()) {
    // If this isn't an auto-login account, move to the next one.
    if (account.account_id() != local_accounts.auto_login_id())
      continue;

    // If the auto-launched account is not a kiosk app, bail out, we aren't
    // running in auto-launched kiosk mode.
    if (account.type() !=
        em::DeviceLocalAccountInfoProto::ACCOUNT_TYPE_KIOSK_APP) {
      return false;
    }

    *app_id_out = account.kiosk_app().app_id();
    return true;
  }

  // No auto-launched account found.
  return false;
}

bool DevicePolicyImpl::IsEnterpriseManaged() const {
  if (policy_data_.has_management_mode())
    return policy_data_.management_mode() == em::PolicyData::ENTERPRISE_MANAGED;
  // Fall back to checking the request token, see management_mode documentation
  // in device_management_backend.proto.
  return policy_data_.has_request_token();
}

bool DevicePolicyImpl::GetSecondFactorAuthenticationMode(int* mode_out) const {
  if (!device_policy_.has_device_second_factor_authentication())
    return false;

  const em::DeviceSecondFactorAuthenticationProto& proto =
      device_policy_.device_second_factor_authentication();

  if (!proto.has_mode())
    return false;

  *mode_out = proto.mode();
  return true;
}

bool DevicePolicyImpl::GetDisallowedTimeIntervals(
    std::vector<WeeklyTimeInterval>* intervals_out) const {
  intervals_out->clear();
  if (!IsEnterpriseEnrolled())
    return false;

  if (!device_policy_.has_auto_update_settings()) {
    return false;
  }

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();

  if (!proto.has_disallowed_time_intervals()) {
    return false;
  }

  base::Optional<base::Value> list_val =
      DecodeListValueFromJSON(proto.disallowed_time_intervals());
  if (!list_val)
    return false;

  for (const auto& interval_value : list_val->GetList()) {
    if (!interval_value.is_dict()) {
      LOG(ERROR) << "Invalid JSON string given. Interval is not a dict.";
      return false;
    }
    const base::Value* start = interval_value.FindDictKey("start");
    const base::Value* end = interval_value.FindDictKey("end");
    if (!start || !end) {
      LOG(ERROR) << "Interval is missing start/end.";
      return false;
    }
    WeeklyTimeInterval weekly_interval;
    if (!DecodeWeeklyTimeFromValue(*start, &weekly_interval.start_day_of_week,
                                   &weekly_interval.start_time) ||
        !DecodeWeeklyTimeFromValue(*end, &weekly_interval.end_day_of_week,
                                   &weekly_interval.end_time)) {
      return false;
    }

    intervals_out->push_back(weekly_interval);
  }
  return true;
}

bool DevicePolicyImpl::GetDeviceQuickFixBuildToken(
    std::string* device_quick_fix_build_token) const {
  if (!IsEnterpriseEnrolled() || !device_policy_.has_auto_update_settings())
    return false;

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();
  if (!proto.has_device_quick_fix_build_token())
    return false;

  *device_quick_fix_build_token = proto.device_quick_fix_build_token();
  return true;
}

bool DevicePolicyImpl::GetDeviceDirectoryApiId(
    std::string* directory_api_id_out) const {
  if (!policy_data_.has_directory_api_id())
    return false;

  *directory_api_id_out = policy_data_.directory_api_id();
  return true;
}

bool DevicePolicyImpl::GetCustomerId(std::string* customer_id_out) const {
  if (!policy_data_.has_obfuscated_customer_id())
    return false;

  *customer_id_out = policy_data_.obfuscated_customer_id();
  return true;
}

bool DevicePolicyImpl::GetChannelDowngradeBehavior(
    int* channel_downgrade_behavior_out) const {
  if (!device_policy_.has_auto_update_settings())
    return false;

  const em::AutoUpdateSettingsProto& proto =
      device_policy_.auto_update_settings();
  if (!proto.has_channel_downgrade_behavior())
    return false;

  *channel_downgrade_behavior_out = proto.channel_downgrade_behavior();
  return true;
}

bool DevicePolicyImpl::GetHighestDeviceMinimumVersion(
    base::Version* version_out) const {
  if (!IsEnterpriseEnrolled())
    return false;

  if (!device_policy_.has_device_minimum_version())
    return false;

  const em::StringPolicyProto& policy_string(
      device_policy_.device_minimum_version());
  if (!policy_string.has_value())
    return false;

  const base::Optional<base::Value> decoded_policy =
      DecodeDictValueFromJSON(policy_string.value(), "device_minimum_version");
  if (!decoded_policy)
    return false;

  const base::Value* requirements_entries =
      decoded_policy->FindListKey("requirements");
  if (!requirements_entries || requirements_entries->GetList().empty())
    return false;

  base::Version highest_version("0");
  bool valid_version_found = false;
  for (const auto& version_value : requirements_entries->GetList()) {
    if (!version_value.is_dict()) {
      LOG(WARNING) << "Invalid JSON string given. Version is not a dictionary.";
      continue;
    }

    const std::string* version_str =
        version_value.FindStringKey("chromeos_version");
    if (!version_str) {
      LOG(WARNING) << " Invalid JSON string given. Version is missing.";
      continue;
    }

    base::Version version(*version_str);
    if (!version.IsValid()) {
      LOG(WARNING) << "Invalid JSON string given. String is not a version.";
      continue;
    }

    if (version > highest_version) {
      valid_version_found = true;
      highest_version = version;
    }
  }

  if (!valid_version_found) {
    LOG(ERROR) << "No valid entry found in device_minimum_version";
    return false;
  }

  *version_out = highest_version;
  return true;
}

bool DevicePolicyImpl::GetDeviceMarketSegment(
    DeviceMarketSegment* device_market_segment) const {
  if (!policy_data_.has_market_segment()) {
    return false;
  }

  em::PolicyData::MarketSegment market_segment = policy_data_.market_segment();
  switch (market_segment) {
    case em::PolicyData::MARKET_SEGMENT_UNSPECIFIED:
      *device_market_segment = DeviceMarketSegment::kUnknown;
      break;
    case em::PolicyData::ENROLLED_EDUCATION:
      *device_market_segment = DeviceMarketSegment::kEducation;
      break;
    case em::PolicyData::ENROLLED_ENTERPRISE:
      *device_market_segment = DeviceMarketSegment::kEnterprise;
      break;
    default:
      LOG(ERROR) << "MarketSegment enum value has changed!";
      *device_market_segment = DeviceMarketSegment::kUnknown;
  }

  return true;
}

bool DevicePolicyImpl::GetDeviceDebugPacketCaptureAllowed(bool* allowed) const {
  if (!device_policy_.has_device_debug_packet_capture_allowed())
    return false;

  const em::DeviceDebugPacketCaptureAllowedProto& proto =
      device_policy_.device_debug_packet_capture_allowed();

  if (!proto.has_allowed())
    return false;

  *allowed = proto.allowed();
  return true;
}

bool DevicePolicyImpl::VerifyPolicyFile(const base::FilePath& policy_path) {
  if (!verify_root_ownership_) {
    return true;
  }

  // Both the policy and its signature have to exist.
  if (!base::PathExists(policy_path) || !base::PathExists(keyfile_path_)) {
    return false;
  }

  // Check if the policy and signature file is owned by root.
  struct stat file_stat;
  stat(policy_path.value().c_str(), &file_stat);
  if (file_stat.st_uid != 0) {
    LOG(ERROR) << "Policy file is not owned by root!";
    return false;
  }
  stat(keyfile_path_.value().c_str(), &file_stat);
  if (file_stat.st_uid != 0) {
    LOG(ERROR) << "Policy signature file is not owned by root!";
    return false;
  }
  return true;
}

bool DevicePolicyImpl::VerifyPolicySignature() {
  if (policy_.has_policy_data_signature()) {
    std::string policy_data = policy_.policy_data();
    std::string policy_data_signature = policy_.policy_data_signature();
    std::string public_key;
    if (!ReadPublicKeyFromFile(base::FilePath(keyfile_path_), &public_key)) {
      LOG(ERROR) << "Could not read owner key off disk";
      return false;
    }
    if (!VerifySignature(policy_data, policy_data_signature, public_key)) {
      LOG(ERROR) << "Signature does not match the data or can not be verified!";
      return false;
    }
    return true;
  }
  LOG(ERROR) << "The policy blob is not signed!";
  return false;
}

bool DevicePolicyImpl::LoadPolicyFromFile(const base::FilePath& policy_path) {
  std::string policy_data_str;
  if (policy::LoadPolicyFromPath(policy_path, &policy_data_str, &policy_) !=
      LoadPolicyResult::kSuccess) {
    return false;
  }
  if (!policy_.has_policy_data()) {
    LOG(ERROR) << "Policy on disk could not be parsed!";
    return false;
  }
  if (!policy_data_.ParseFromString(policy_.policy_data()) ||
      !policy_data_.has_policy_value()) {
    LOG(ERROR) << "Policy on disk could not be parsed!";
    return false;
  }

  bool verify_policy = verify_policy_;
  if (!install_attributes_reader_) {
    install_attributes_reader_ = std::make_unique<InstallAttributesReader>();
  }
  const std::string& mode = install_attributes_reader_->GetAttribute(
      InstallAttributesReader::kAttrMode);
  if (mode == InstallAttributesReader::kDeviceModeEnterpriseAD) {
    verify_policy = false;
  }
  if (verify_policy && !VerifyPolicyFile(policy_path)) {
    return false;
  }

  // Make sure the signature is still valid.
  if (verify_policy && !VerifyPolicySignature()) {
    LOG(ERROR) << "Policy signature verification failed!";
    return false;
  }
  if (!device_policy_.ParseFromString(policy_data_.policy_value())) {
    LOG(ERROR) << "Policy on disk could not be parsed!";
    return false;
  }

  return true;
}

}  // namespace policy
