// Copyright (c) 2014 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 "components/policy/core/common/policy_loader_win.h"

#include <lm.h>       // For NetGetJoinInformation
// <security.h> needs this.
#define SECURITY_WIN32 1
#include <security.h>  // For GetUserNameEx()
#include <stddef.h>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/scoped_native_library.h"
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "base/win/shlwapi.h"  // For PathIsUNC()
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "components/policy/core/common/policy_bundle.h"
#include "components/policy/core/common/policy_load_status.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/core/common/registry_dict.h"
#include "components/policy/core/common/schema.h"
#include "components/policy/policy_constants.h"

namespace policy {

namespace {

const char kKeyMandatory[] = "policy";
const char kKeyRecommended[] = "recommended";
const char kKeyThirdParty[] = "3rdparty";

// The web store url that is the only trusted source for extensions.
const char kExpectedWebStoreUrl[] =
    ";https://clients2.google.com/service/update2/crx";
// String to be prepended to each blocked entry.
const char kBlockedExtensionPrefix[] = "[BLOCKED]";

// List of policies that are considered only if the user is part of a AD domain.
// Please document any new additions in policy_templates.json!
const char* kInsecurePolicies[] = {
    key::kChromeCleanupEnabled,
    key::kChromeCleanupReportingEnabled,
    key::kCloudPolicyOverridesMachinePolicy,
    key::kDefaultSearchProviderEnabled,
    key::kHomepageIsNewTabPage,
    key::kHomepageLocation,
    key::kMetricsReportingEnabled,
    key::kNewTabPageLocation,
    key::kPasswordProtectionChangePasswordURL,
    key::kPasswordProtectionLoginURLs,
    key::kRestoreOnStartup,
    key::kRestoreOnStartupURLs,
    key::kSafeBrowsingForTrustedSourcesEnabled,
    key::kSafeBrowsingEnabled,
    key::kSafeBrowsingWhitelistDomains,
};

// The list of possible errors that can occur while collecting information about
// the current enterprise environment.
// This enum is used to define the buckets for an enumerated UMA histogram.
// Hence,
//   (a) existing enumerated constants should never be deleted or reordered, and
//   (b) new constants should only be appended at the end of the enumeration.
enum DomainCheckErrors {
  // The check error below is no longer possible.
  DEPRECATED_DOMAIN_CHECK_ERROR_GET_JOIN_INFO = 0,
  DOMAIN_CHECK_ERROR_DS_BIND = 1,
  DOMAIN_CHECK_ERROR_SIZE,  // Not a DomainCheckError.  Must be last.
};

// Encapculates logic to determine if enterprise policies should be honored.
// This is used in various places below.
bool ShouldHonorPolicies() {
  bool is_enterprise_version =
      base::win::OSInfo::GetInstance()->version_type() != base::win::SUITE_HOME;
  return base::win::IsEnrolledToDomain() ||
         (base::win::IsDeviceRegisteredWithManagement() &&
          is_enterprise_version);
}

// Verifies that untrusted policies contain only safe values. Modifies the
// |policy| in place.
void FilterUntrustedPolicy(PolicyMap* policy) {
  if (ShouldHonorPolicies())
    return;

  int invalid_policies = 0;
  const PolicyMap::Entry* map_entry =
      policy->Get(key::kExtensionInstallForcelist);
  if (map_entry && map_entry->value) {
    const base::ListValue* policy_list_value = nullptr;
    if (!map_entry->value->GetAsList(&policy_list_value))
      return;

    std::unique_ptr<base::ListValue> filtered_values(new base::ListValue);
    for (const auto& list_entry : *policy_list_value) {
      std::string entry;
      if (!list_entry.GetAsString(&entry))
        continue;
      size_t pos = entry.find(';');
      if (pos == std::string::npos)
        continue;
      // Only allow custom update urls in enterprise environments.
      if (!base::LowerCaseEqualsASCII(entry.substr(pos),
                                      kExpectedWebStoreUrl)) {
        entry = kBlockedExtensionPrefix + entry;
        invalid_policies++;
      }

      filtered_values->AppendString(entry);
    }
    if (invalid_policies) {
      PolicyMap::Entry filtered_entry = map_entry->DeepCopy();
      filtered_entry.value = std::move(filtered_values);
      policy->Set(key::kExtensionInstallForcelist, std::move(filtered_entry));

      const PolicyDetails* details =
          GetChromePolicyDetails(key::kExtensionInstallForcelist);
      base::UmaHistogramSparse("EnterpriseCheck.InvalidPolicies", details->id);
    }
  }

  for (size_t i = 0; i < base::size(kInsecurePolicies); ++i) {
    if (policy->Get(kInsecurePolicies[i])) {
      // TODO(pastarmovj): Surface this issue in the about:policy page.
      policy->Erase(kInsecurePolicies[i]);
      invalid_policies++;
      const PolicyDetails* details =
          GetChromePolicyDetails(kInsecurePolicies[i]);
      base::UmaHistogramSparse("EnterpriseCheck.InvalidPolicies", details->id);
    }
  }

  UMA_HISTOGRAM_COUNTS_1M("EnterpriseCheck.InvalidPoliciesDetected",
                          invalid_policies);
}

// Parses |gpo_dict| according to |schema| and writes the resulting policy
// settings to |policy| for the given |scope| and |level|.
void ParsePolicy(const RegistryDict* gpo_dict,
                 PolicyLevel level,
                 PolicyScope scope,
                 const Schema& schema,
                 PolicyMap* policy) {
  if (!gpo_dict)
    return;

  std::unique_ptr<base::Value> policy_value(gpo_dict->ConvertToJSON(schema));
  const base::DictionaryValue* policy_dict = nullptr;
  if (!policy_value->GetAsDictionary(&policy_dict) || !policy_dict) {
    LOG(WARNING) << "Root policy object is not a dictionary!";
    return;
  }

  policy->LoadFrom(policy_dict, level, scope, POLICY_SOURCE_PLATFORM);
}

// Returns a name, using the |get_name| callback, which may refuse the call if
// the name is longer than _MAX_PATH. So this helper function takes care of the
// retry with the required size.
bool GetName(const base::Callback<BOOL(LPWSTR, LPDWORD)>& get_name,
             base::string16* name) {
  DCHECK(name);
  DWORD size = _MAX_PATH;
  if (!get_name.Run(base::WriteInto(name, size), &size)) {
    if (::GetLastError() != ERROR_MORE_DATA)
      return false;
    // Try again with the required size. This time it must work, the size should
    // not have changed in between the two calls.
    if (!get_name.Run(base::WriteInto(name, size), &size))
      return false;
  }
  return true;
}

// To convert the weird BOOLEAN return value type of ::GetUserNameEx().
BOOL GetUserNameExBool(EXTENDED_NAME_FORMAT format, LPWSTR name, PULONG size) {
  // ::GetUserNameEx is documented to return a nonzero value on success.
  return ::GetUserNameEx(format, name, size) != 0;
}

// Make sure to use the real NetGetJoinInformation, otherwise fallback to the
// linked one.
bool IsDomainJoined() {
  base::ScopedClosureRunner free_library;
  decltype(&::NetGetJoinInformation) net_get_join_information_function =
      &::NetGetJoinInformation;
  decltype(&::NetApiBufferFree) net_api_buffer_free_function =
      &::NetApiBufferFree;
  bool got_function_addresses = false;
  // Use an absolute path to load the DLL to avoid DLL preloading attacks.
  base::FilePath path;
  if (base::PathService::Get(base::DIR_SYSTEM, &path)) {
    HINSTANCE net_api_library = ::LoadLibraryEx(
        path.Append(FILE_PATH_LITERAL("netapi32.dll")).value().c_str(), nullptr,
        LOAD_WITH_ALTERED_SEARCH_PATH);
    if (net_api_library) {
      free_library.ReplaceClosure(
          base::BindOnce(base::IgnoreResult(&::FreeLibrary), net_api_library));
      net_get_join_information_function =
          reinterpret_cast<decltype(&::NetGetJoinInformation)>(
              ::GetProcAddress(net_api_library, "NetGetJoinInformation"));
      net_api_buffer_free_function =
          reinterpret_cast<decltype(&::NetApiBufferFree)>(
              ::GetProcAddress(net_api_library, "NetApiBufferFree"));

      if (net_get_join_information_function && net_api_buffer_free_function) {
        got_function_addresses = true;
      } else {
        net_get_join_information_function = &::NetGetJoinInformation;
        net_api_buffer_free_function = &::NetApiBufferFree;
      }
    }
  }
  base::UmaHistogramBoolean("EnterpriseCheck.NetGetJoinInformationAddress",
                            got_function_addresses);

  LPWSTR buffer = nullptr;
  NETSETUP_JOIN_STATUS buffer_type = NetSetupUnknownStatus;
  bool is_joined = net_get_join_information_function(
                       nullptr, &buffer, &buffer_type) == NERR_Success &&
                   buffer_type == NetSetupDomainName;
  if (buffer)
    net_api_buffer_free_function(buffer);

  return is_joined;
}

// Collects stats about the enterprise environment that can be used to decide
// how to parse the existing policy information.
void CollectEnterpriseUMAs() {
  // Collect statistics about the windows suite.
  UMA_HISTOGRAM_ENUMERATION("EnterpriseCheck.OSType",
                            base::win::OSInfo::GetInstance()->version_type(),
                            base::win::SUITE_LAST);

  base::UmaHistogramBoolean("EnterpriseCheck.IsDomainJoined", IsDomainJoined());
  base::UmaHistogramBoolean("EnterpriseCheck.InDomain",
                            base::win::IsEnrolledToDomain());
  base::UmaHistogramBoolean("EnterpriseCheck.IsManaged",
                            base::win::IsDeviceRegisteredWithManagement());
  base::UmaHistogramBoolean("EnterpriseCheck.IsEnterpriseUser",
                            base::win::IsEnterpriseManaged());

  base::string16 machine_name;
  if (GetName(base::Bind(&::GetComputerNameEx, ::ComputerNameDnsHostname),
              &machine_name)) {
    base::string16 user_name;
    if (GetName(base::Bind(&GetUserNameExBool, ::NameSamCompatible),
                &user_name)) {
      // A local user has the machine name in its sam compatible name, e.g.,
      // 'MACHINE_NAME\username', otherwise it is perfixed with the domain name
      // as opposed to the machine, e.g., 'COMPANY\username'.
      base::UmaHistogramBoolean(
          "EnterpriseCheck.IsLocalUser",
          base::StartsWith(user_name, machine_name,
                           base::CompareCase::INSENSITIVE_ASCII) &&
              user_name[machine_name.size()] == L'\\');
    }

    base::string16 full_machine_name;
    if (GetName(
            base::Bind(&::GetComputerNameEx, ::ComputerNameDnsFullyQualified),
            &full_machine_name)) {
      // ComputerNameDnsFullyQualified is the same as the
      // ComputerNameDnsHostname when not domain joined, otherwise it has a
      // suffix.
      base::UmaHistogramBoolean(
          "EnterpriseCheck.IsLocalMachine",
          base::EqualsCaseInsensitiveASCII(machine_name, full_machine_name));
    }
  }
}

}  // namespace

PolicyLoaderWin::PolicyLoaderWin(
    scoped_refptr<base::SequencedTaskRunner> task_runner,
    const base::string16& chrome_policy_key)
    : AsyncPolicyLoader(task_runner),
      is_initialized_(false),
      chrome_policy_key_(chrome_policy_key),
      user_policy_changed_event_(
          base::WaitableEvent::ResetPolicy::AUTOMATIC,
          base::WaitableEvent::InitialState::NOT_SIGNALED),
      machine_policy_changed_event_(
          base::WaitableEvent::ResetPolicy::AUTOMATIC,
          base::WaitableEvent::InitialState::NOT_SIGNALED),
      user_policy_watcher_failed_(false),
      machine_policy_watcher_failed_(false) {
  if (!::RegisterGPNotification(user_policy_changed_event_.handle(), false)) {
    DPLOG(WARNING) << "Failed to register user group policy notification";
    user_policy_watcher_failed_ = true;
  }
  if (!::RegisterGPNotification(machine_policy_changed_event_.handle(), true)) {
    DPLOG(WARNING) << "Failed to register machine group policy notification.";
    machine_policy_watcher_failed_ = true;
  }
}

PolicyLoaderWin::~PolicyLoaderWin() {
  if (!user_policy_watcher_failed_) {
    ::UnregisterGPNotification(user_policy_changed_event_.handle());
    user_policy_watcher_.StopWatching();
  }
  if (!machine_policy_watcher_failed_) {
    ::UnregisterGPNotification(machine_policy_changed_event_.handle());
    machine_policy_watcher_.StopWatching();
  }
}

// static
std::unique_ptr<PolicyLoaderWin> PolicyLoaderWin::Create(
    scoped_refptr<base::SequencedTaskRunner> task_runner,
    const base::string16& chrome_policy_key) {
  return base::WrapUnique(new PolicyLoaderWin(task_runner, chrome_policy_key));
}

void PolicyLoaderWin::InitOnBackgroundThread() {
  is_initialized_ = true;
  SetupWatches();
  CollectEnterpriseUMAs();
}

std::unique_ptr<PolicyBundle> PolicyLoaderWin::Load() {
  // Reset the watches BEFORE reading the individual policies to avoid
  // missing a change notification.
  if (is_initialized_)
    SetupWatches();

  // Policy scope and corresponding hive.
  static const struct {
    PolicyScope scope;
    HKEY hive;
  } kScopes[] = {
      {POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE},
      {POLICY_SCOPE_USER, HKEY_CURRENT_USER},
  };

  // Load policy data for the different scopes/levels and merge them.
  std::unique_ptr<PolicyBundle> bundle(new PolicyBundle());
  PolicyMap* chrome_policy =
      &bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
  for (size_t i = 0; i < base::size(kScopes); ++i) {
    PolicyScope scope = kScopes[i].scope;
    PolicyLoadStatusUmaReporter status;
    RegistryDict gpo_dict;

    gpo_dict.ReadRegistry(kScopes[i].hive, chrome_policy_key_);

    // Remove special-cased entries from the GPO dictionary.
    std::unique_ptr<RegistryDict> recommended_dict(
        gpo_dict.RemoveKey(kKeyRecommended));
    std::unique_ptr<RegistryDict> third_party_dict(
        gpo_dict.RemoveKey(kKeyThirdParty));

    // Load Chrome policy.
    LoadChromePolicy(&gpo_dict, POLICY_LEVEL_MANDATORY, scope, chrome_policy);
    LoadChromePolicy(recommended_dict.get(), POLICY_LEVEL_RECOMMENDED, scope,
                     chrome_policy);

    // Load 3rd-party policy.
    if (third_party_dict)
      Load3rdPartyPolicy(third_party_dict.get(), scope, bundle.get());
  }

  return bundle;
}

void PolicyLoaderWin::LoadChromePolicy(const RegistryDict* gpo_dict,
                                       PolicyLevel level,
                                       PolicyScope scope,
                                       PolicyMap* chrome_policy_map) {
  PolicyMap policy;
  const Schema* chrome_schema =
      schema_map()->GetSchema(PolicyNamespace(POLICY_DOMAIN_CHROME, ""));
  ParsePolicy(gpo_dict, level, scope, *chrome_schema, &policy);
  FilterUntrustedPolicy(&policy);
  chrome_policy_map->MergeFrom(policy);
}

void PolicyLoaderWin::Load3rdPartyPolicy(const RegistryDict* gpo_dict,
                                         PolicyScope scope,
                                         PolicyBundle* bundle) {
  // Map of known 3rd party policy domain name to their enum values.
  static const struct {
    const char* name;
    PolicyDomain domain;
  } k3rdPartyDomains[] = {
      {"extensions", POLICY_DOMAIN_EXTENSIONS},
  };

  // Policy level and corresponding path.
  static const struct {
    PolicyLevel level;
    const char* path;
  } kLevels[] = {
      {POLICY_LEVEL_MANDATORY, kKeyMandatory},
      {POLICY_LEVEL_RECOMMENDED, kKeyRecommended},
  };

  for (size_t i = 0; i < base::size(k3rdPartyDomains); i++) {
    const char* name = k3rdPartyDomains[i].name;
    const PolicyDomain domain = k3rdPartyDomains[i].domain;
    const RegistryDict* domain_dict = gpo_dict->GetKey(name);
    if (!domain_dict)
      continue;

    for (RegistryDict::KeyMap::const_iterator component(
             domain_dict->keys().begin());
         component != domain_dict->keys().end(); ++component) {
      const PolicyNamespace policy_namespace(domain, component->first);

      const Schema* schema_from_map = schema_map()->GetSchema(policy_namespace);
      if (!schema_from_map) {
        // This extension isn't installed or doesn't support policies.
        continue;
      }
      Schema schema = *schema_from_map;

      // Parse policy.
      for (size_t j = 0; j < base::size(kLevels); j++) {
        const RegistryDict* policy_dict =
            component->second->GetKey(kLevels[j].path);
        if (!policy_dict)
          continue;

        PolicyMap policy;
        ParsePolicy(policy_dict, kLevels[j].level, scope, schema, &policy);
        bundle->Get(policy_namespace).MergeFrom(policy);
      }
    }
  }
}

void PolicyLoaderWin::SetupWatches() {
  DCHECK(is_initialized_);
  if (!user_policy_watcher_failed_ &&
      !user_policy_watcher_.GetWatchedObject() &&
      !user_policy_watcher_.StartWatchingOnce(
          user_policy_changed_event_.handle(), this)) {
    DLOG(WARNING) << "Failed to start watch for user policy change event";
    user_policy_watcher_failed_ = true;
  }
  if (!machine_policy_watcher_failed_ &&
      !machine_policy_watcher_.GetWatchedObject() &&
      !machine_policy_watcher_.StartWatchingOnce(
          machine_policy_changed_event_.handle(), this)) {
    DLOG(WARNING) << "Failed to start watch for machine policy change event";
    machine_policy_watcher_failed_ = true;
  }
}

void PolicyLoaderWin::OnObjectSignaled(HANDLE object) {
  DCHECK(object == user_policy_changed_event_.handle() ||
         object == machine_policy_changed_event_.handle())
      << "unexpected object signaled policy reload, obj = " << std::showbase
      << std::hex << object;
  Reload(false);
}

}  // namespace policy
