[go: nahoru, domu]

blob: 42d28e248b83c6e23f0e49c170fcf0d361a55d39 [file] [log] [blame]
// Copyright 2020 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 "chrome/updater/policy/win/group_policy_manager.h"
#include <ostream>
#include <string>
#include <utility>
#include <userenv.h>
#include "base/enterprise_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/scoped_generic.h"
#include "base/strings/sys_string_conversions.h"
#include "base/values.h"
#include "base/win/registry.h"
#include "chrome/updater/external_constants.h"
#include "chrome/updater/policy/manager.h"
#include "chrome/updater/win/win_constants.h"
namespace updater {
namespace {
// Registry values.
// Preferences Category.
const char kRegValueAutoUpdateCheckPeriodOverrideMinutes[] =
"AutoUpdateCheckPeriodMinutes";
const char kRegValueUpdatesSuppressedStartHour[] = "UpdatesSuppressedStartHour";
const char kRegValueUpdatesSuppressedStartMin[] = "UpdatesSuppressedStartMin";
const char kRegValueUpdatesSuppressedDurationMin[] =
"UpdatesSuppressedDurationMin";
// This policy specifies what kind of download URLs could be returned to the
// client in the update response and in which order of priority. The client
// provides this information in the update request as a hint for the server.
// The server may decide to ignore the hint. As a general idea, some urls are
// cacheable, some urls have higher bandwidth, and some urls are slightly more
// secure since they are https.
const char kRegValueDownloadPreference[] = "DownloadPreference";
// Proxy Server Category. (The registry keys used, and the values of ProxyMode,
// directly mirror that of Chrome. However, we omit ProxyBypassList, as the
// domains that Omaha uses are largely fixed.)
const char kRegValueProxyMode[] = "ProxyMode";
const char kRegValueProxyServer[] = "ProxyServer";
const char kRegValueProxyPacUrl[] = "ProxyPacUrl";
// Package cache constants.
const char kRegValueCacheSizeLimitMBytes[] = "PackageCacheSizeLimit";
const char kRegValueCacheLifeLimitDays[] = "PackageCacheLifeLimit";
// Applications Category.
// The prefix strings have the app's GUID appended to them.
const char kRegValueInstallAppsDefault[] = "InstallDefault";
const char kRegValueInstallAppPrefix[] = "Install";
const char kRegValueUpdateAppsDefault[] = "UpdateDefault";
const char kRegValueUpdateAppPrefix[] = "Update";
const char kRegValueTargetVersionPrefix[] = "TargetVersionPrefix";
const char kRegValueTargetChannel[] = "TargetChannel";
const char kRegValueRollbackToTargetVersion[] = "RollbackToTargetVersion";
struct ScopedHCriticalPolicySectionTraits {
static HANDLE InvalidValue() { return nullptr; }
static void Free(HANDLE handle) {
if (handle != InvalidValue())
::LeaveCriticalPolicySection(handle);
}
};
// Manages the lifetime of critical policy section handle allocated by
// ::EnterCriticalPolicySection.
using scoped_hpolicy =
base::ScopedGeneric<HANDLE, updater::ScopedHCriticalPolicySectionTraits>;
} // namespace
GroupPolicyManager::GroupPolicyManager(
scoped_refptr<ExternalConstants> external_constants)
: external_constants_group_policies_(external_constants->GroupPolicies()) {
LoadAllPolicies();
}
GroupPolicyManager::~GroupPolicyManager() = default;
bool GroupPolicyManager::IsManaged() const {
return !policies_.DictEmpty() && IsManagedInternal();
}
bool GroupPolicyManager::IsManagedInternal() const {
return !external_constants_group_policies_.DictEmpty() ||
base::IsManagedDevice();
}
std::string GroupPolicyManager::source() const {
return std::string("GroupPolicy");
}
bool GroupPolicyManager::GetLastCheckPeriodMinutes(int* minutes) const {
return GetIntPolicy(kRegValueAutoUpdateCheckPeriodOverrideMinutes, minutes);
}
bool GroupPolicyManager::GetUpdatesSuppressedTimes(
UpdatesSuppressedTimes* suppressed_times) const {
return GetIntPolicy(kRegValueUpdatesSuppressedStartHour,
&suppressed_times->start_hour_) &&
GetIntPolicy(kRegValueUpdatesSuppressedStartMin,
&suppressed_times->start_minute_) &&
GetIntPolicy(kRegValueUpdatesSuppressedDurationMin,
&suppressed_times->duration_minute_);
}
bool GroupPolicyManager::GetDownloadPreferenceGroupPolicy(
std::string* download_preference) const {
return GetStringPolicy(kRegValueDownloadPreference, download_preference);
}
bool GroupPolicyManager::GetPackageCacheSizeLimitMBytes(
int* cache_size_limit) const {
return GetIntPolicy(kRegValueCacheSizeLimitMBytes, cache_size_limit);
}
bool GroupPolicyManager::GetPackageCacheExpirationTimeDays(
int* cache_life_limit) const {
return GetIntPolicy(kRegValueCacheLifeLimitDays, cache_life_limit);
}
bool GroupPolicyManager::GetEffectivePolicyForAppInstalls(
const std::string& app_id,
int* install_policy) const {
std::string app_value_name(kRegValueInstallAppPrefix);
app_value_name.append(app_id);
return GetIntPolicy(app_value_name.c_str(), install_policy)
? true
: GetIntPolicy(kRegValueInstallAppsDefault, install_policy);
}
bool GroupPolicyManager::GetEffectivePolicyForAppUpdates(
const std::string& app_id,
int* update_policy) const {
std::string app_value_name(kRegValueUpdateAppPrefix);
app_value_name.append(app_id);
return GetIntPolicy(app_value_name.c_str(), update_policy)
? true
: GetIntPolicy(kRegValueUpdateAppsDefault, update_policy);
}
bool GroupPolicyManager::GetTargetChannel(const std::string& app_id,
std::string* channel) const {
std::string app_value_name(kRegValueTargetChannel);
app_value_name.append(app_id);
return GetStringPolicy(app_value_name.c_str(), channel);
}
bool GroupPolicyManager::GetTargetVersionPrefix(
const std::string& app_id,
std::string* target_version_prefix) const {
std::string app_value_name(kRegValueTargetVersionPrefix);
app_value_name.append(app_id);
return GetStringPolicy(app_value_name.c_str(), target_version_prefix);
}
bool GroupPolicyManager::IsRollbackToTargetVersionAllowed(
const std::string& app_id,
bool* rollback_allowed) const {
std::string app_value_name(kRegValueRollbackToTargetVersion);
app_value_name.append(app_id);
int is_rollback_allowed = 0;
if (GetIntPolicy(app_value_name.c_str(), &is_rollback_allowed)) {
*rollback_allowed = is_rollback_allowed;
return true;
}
return false;
}
bool GroupPolicyManager::GetProxyMode(std::string* proxy_mode) const {
return GetStringPolicy(kRegValueProxyMode, proxy_mode);
}
bool GroupPolicyManager::GetProxyPacUrl(std::string* proxy_pac_url) const {
return GetStringPolicy(kRegValueProxyPacUrl, proxy_pac_url);
}
bool GroupPolicyManager::GetProxyServer(std::string* proxy_server) const {
return GetStringPolicy(kRegValueProxyServer, proxy_server);
}
bool GroupPolicyManager::GetIntPolicy(const std::string& key,
int* value) const {
const base::Value* policy =
policies_.FindKeyOfType(key, base::Value::Type::INTEGER);
if (policy == nullptr)
return false;
*value = policy->GetInt();
return true;
}
bool GroupPolicyManager::GetStringPolicy(const std::string& key,
std::string* value) const {
const base::Value* policy =
policies_.FindKeyOfType(key, base::Value::Type::STRING);
if (policy == nullptr)
return false;
*value = policy->GetString();
return true;
}
void GroupPolicyManager::LoadAllPolicies() {
scoped_hpolicy policy_lock;
if (IsManagedInternal()) {
// GPO rules mandate a call to EnterCriticalPolicySection() before reading
// policies (and a matching LeaveCriticalPolicySection() call after read).
// Acquire the lock for managed machines because group policies are
// applied only in this case, and the lock acquisition can take a long
// time, in the worst case scenarios.
policy_lock.reset(::EnterCriticalPolicySection(true));
CHECK(policy_lock.is_valid()) << "Failed to get policy lock.";
}
if (!external_constants_group_policies_.DictEmpty()) {
policies_ = external_constants_group_policies_.Clone();
return;
}
base::Value::DictStorage policy_storage;
for (base::win::RegistryValueIterator it(HKEY_LOCAL_MACHINE,
UPDATER_POLICIES_KEY);
it.Valid(); ++it) {
const std::string key_name = base::SysWideToUTF8(it.Name());
switch (it.Type()) {
case REG_SZ:
policy_storage.emplace(key_name,
base::Value(base::SysWideToUTF8(it.Value())));
break;
case REG_DWORD:
policy_storage.emplace(
key_name, base::Value(*(reinterpret_cast<const int*>(it.Value()))));
break;
default:
// Ignore all types that are not used by updater policies.
break;
}
}
policies_ = base::Value(std::move(policy_storage));
}
} // namespace updater