| OLD | NEW | 
|---|
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "components/policy/core/common/policy_loader_win.h" | 5 #include "components/policy/core/common/policy_loader_win.h" | 
| 6 | 6 | 
| 7 #include <windows.h> | 7 #include <windows.h> | 
| 8 #include <ntdsapi.h>  // For Ds[Un]Bind | 8 #include <ntdsapi.h>  // For Ds[Un]Bind | 
| 9 #include <rpc.h>      // For struct GUID | 9 #include <rpc.h>      // For struct GUID | 
| 10 #include <shlwapi.h>  // For PathIsUNC() | 10 #include <shlwapi.h>  // For PathIsUNC() | 
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 83 // Hence, | 83 // Hence, | 
| 84 //   (a) existing enumerated constants should never be deleted or reordered, and | 84 //   (a) existing enumerated constants should never be deleted or reordered, and | 
| 85 //   (b) new constants should only be appended at the end of the enumeration. | 85 //   (b) new constants should only be appended at the end of the enumeration. | 
| 86 enum DomainCheckErrors { | 86 enum DomainCheckErrors { | 
| 87   // The check error below is no longer possible. | 87   // The check error below is no longer possible. | 
| 88   DEPRECATED_DOMAIN_CHECK_ERROR_GET_JOIN_INFO = 0, | 88   DEPRECATED_DOMAIN_CHECK_ERROR_GET_JOIN_INFO = 0, | 
| 89   DOMAIN_CHECK_ERROR_DS_BIND = 1, | 89   DOMAIN_CHECK_ERROR_DS_BIND = 1, | 
| 90   DOMAIN_CHECK_ERROR_SIZE,  // Not a DomainCheckError.  Must be last. | 90   DOMAIN_CHECK_ERROR_SIZE,  // Not a DomainCheckError.  Must be last. | 
| 91 }; | 91 }; | 
| 92 | 92 | 
| 93 // Encapculates logic to determine if enterprise policies should be honored. |  | 
| 94 // This is used in various places below. |  | 
| 95 bool ShouldHonorPolicies() { |  | 
| 96   return base::win::IsEnterpriseManaged(); |  | 
| 97 } |  | 
| 98 |  | 
| 99 // Verifies that untrusted policies contain only safe values. Modifies the | 93 // Verifies that untrusted policies contain only safe values. Modifies the | 
| 100 // |policy| in place. | 94 // |policy| in place. | 
| 101 void FilterUntrustedPolicy(PolicyMap* policy) { | 95 void FilterUntrustedPolicy(PolicyMap* policy) { | 
| 102   if (ShouldHonorPolicies()) | 96   if (base::win::IsEnrolledToDomain()) | 
| 103     return; | 97     return; | 
| 104 | 98 | 
| 105   int invalid_policies = 0; | 99   int invalid_policies = 0; | 
| 106   const PolicyMap::Entry* map_entry = | 100   const PolicyMap::Entry* map_entry = | 
| 107       policy->Get(key::kExtensionInstallForcelist); | 101       policy->Get(key::kExtensionInstallForcelist); | 
| 108   if (map_entry && map_entry->value) { | 102   if (map_entry && map_entry->value) { | 
| 109     const base::ListValue* policy_list_value = NULL; | 103     const base::ListValue* policy_list_value = NULL; | 
| 110     if (!map_entry->value->GetAsList(&policy_list_value)) | 104     if (!map_entry->value->GetAsList(&policy_list_value)) | 
| 111       return; | 105       return; | 
| 112 | 106 | 
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 290 } | 284 } | 
| 291 | 285 | 
| 292 // Collects stats about the enterprise environment that can be used to decide | 286 // Collects stats about the enterprise environment that can be used to decide | 
| 293 // how to parse the existing policy information. | 287 // how to parse the existing policy information. | 
| 294 void CollectEnterpriseUMAs() { | 288 void CollectEnterpriseUMAs() { | 
| 295   // Collect statistics about the windows suite. | 289   // Collect statistics about the windows suite. | 
| 296   UMA_HISTOGRAM_ENUMERATION("EnterpriseCheck.OSType", | 290   UMA_HISTOGRAM_ENUMERATION("EnterpriseCheck.OSType", | 
| 297                             base::win::OSInfo::GetInstance()->version_type(), | 291                             base::win::OSInfo::GetInstance()->version_type(), | 
| 298                             base::win::SUITE_LAST); | 292                             base::win::SUITE_LAST); | 
| 299 | 293 | 
| 300   UMA_HISTOGRAM_BOOLEAN("EnterpriseCheck.InDomain", | 294   bool in_domain = base::win::IsEnrolledToDomain(); | 
| 301                         base::win::IsEnrolledToDomain()); | 295   UMA_HISTOGRAM_BOOLEAN("EnterpriseCheck.InDomain", in_domain); | 
| 302   UMA_HISTOGRAM_BOOLEAN("EnterpriseCheck.IsManaged", |  | 
| 303                         base::win::IsDeviceRegisteredWithManagement()); |  | 
| 304   UMA_HISTOGRAM_BOOLEAN("EnterpriseCheck.IsEnterpriseUser", |  | 
| 305                         base::win::IsEnterpriseManaged()); |  | 
| 306 } | 296 } | 
| 307 | 297 | 
| 308 }  // namespace | 298 }  // namespace | 
| 309 | 299 | 
| 310 const base::FilePath::CharType PolicyLoaderWin::kPRegFileName[] = | 300 const base::FilePath::CharType PolicyLoaderWin::kPRegFileName[] = | 
| 311     FILE_PATH_LITERAL("Registry.pol"); | 301     FILE_PATH_LITERAL("Registry.pol"); | 
| 312 | 302 | 
| 313 PolicyLoaderWin::PolicyLoaderWin( | 303 PolicyLoaderWin::PolicyLoaderWin( | 
| 314     scoped_refptr<base::SequencedTaskRunner> task_runner, | 304     scoped_refptr<base::SequencedTaskRunner> task_runner, | 
| 315     const base::string16& chrome_policy_key, | 305     const base::string16& chrome_policy_key, | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 369 | 359 | 
| 370   // Policy scope and corresponding hive. | 360   // Policy scope and corresponding hive. | 
| 371   static const struct { | 361   static const struct { | 
| 372     PolicyScope scope; | 362     PolicyScope scope; | 
| 373     HKEY hive; | 363     HKEY hive; | 
| 374   } kScopes[] = { | 364   } kScopes[] = { | 
| 375     { POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE }, | 365     { POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE }, | 
| 376     { POLICY_SCOPE_USER,    HKEY_CURRENT_USER  }, | 366     { POLICY_SCOPE_USER,    HKEY_CURRENT_USER  }, | 
| 377   }; | 367   }; | 
| 378 | 368 | 
| 379   bool honor_policies = ShouldHonorPolicies(); | 369   bool is_enterprise = base::win::IsEnrolledToDomain(); | 
| 380   VLOG(1) << "Reading policy from the registry is " | 370   VLOG(1) << "Reading policy from the registry is " | 
| 381           << (honor_policies ? "enabled." : "disabled."); | 371           << (is_enterprise ? "enabled." : "disabled."); | 
| 382 | 372 | 
| 383   // Load policy data for the different scopes/levels and merge them. | 373   // Load policy data for the different scopes/levels and merge them. | 
| 384   std::unique_ptr<PolicyBundle> bundle(new PolicyBundle()); | 374   std::unique_ptr<PolicyBundle> bundle(new PolicyBundle()); | 
| 385   PolicyMap* chrome_policy = | 375   PolicyMap* chrome_policy = | 
| 386       &bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); | 376       &bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); | 
| 387   for (size_t i = 0; i < arraysize(kScopes); ++i) { | 377   for (size_t i = 0; i < arraysize(kScopes); ++i) { | 
| 388     PolicyScope scope = kScopes[i].scope; | 378     PolicyScope scope = kScopes[i].scope; | 
| 389     PolicyLoadStatusSample status; | 379     PolicyLoadStatusSample status; | 
| 390     RegistryDict gpo_dict; | 380     RegistryDict gpo_dict; | 
| 391 | 381 | 
| 392     // Note: GPO rules mandate a call to EnterCriticalPolicySection() here, and | 382     // Note: GPO rules mandate a call to EnterCriticalPolicySection() here, and | 
| 393     // a matching LeaveCriticalPolicySection() call below after the | 383     // a matching LeaveCriticalPolicySection() call below after the | 
| 394     // ReadPolicyFromGPO() block. Unfortunately, the policy mutex may be | 384     // ReadPolicyFromGPO() block. Unfortunately, the policy mutex may be | 
| 395     // unavailable for extended periods of time, and there are reports of this | 385     // unavailable for extended periods of time, and there are reports of this | 
| 396     // happening in the wild: http://crbug.com/265862. | 386     // happening in the wild: http://crbug.com/265862. | 
| 397     // | 387     // | 
| 398     // Blocking for minutes is neither acceptable for Chrome startup, nor on | 388     // Blocking for minutes is neither acceptable for Chrome startup, nor on | 
| 399     // the FILE thread on which this code runs in steady state. Given that | 389     // the FILE thread on which this code runs in steady state. Given that | 
| 400     // there have never been any reports of issues due to partially-applied / | 390     // there have never been any reports of issues due to partially-applied / | 
| 401     // corrupt group policy, this code intentionally omits the | 391     // corrupt group policy, this code intentionally omits the | 
| 402     // EnterCriticalPolicySection() call. | 392     // EnterCriticalPolicySection() call. | 
| 403     // | 393     // | 
| 404     // If there's ever reason to revisit this decision, one option could be to | 394     // If there's ever reason to revisit this decision, one option could be to | 
| 405     // make the EnterCriticalPolicySection() call on a dedicated thread and | 395     // make the EnterCriticalPolicySection() call on a dedicated thread and | 
| 406     // timeout on it more aggressively. For now, there's no justification for | 396     // timeout on it more aggressively. For now, there's no justification for | 
| 407     // the additional effort this would introduce. | 397     // the additional effort this would introduce. | 
| 408 | 398 | 
| 409     bool is_registry_forced = honor_policies || gpo_provider_ == nullptr; | 399     bool is_registry_forced = is_enterprise || gpo_provider_ == nullptr; | 
| 410     if (is_registry_forced || !ReadPolicyFromGPO(scope, &gpo_dict, &status)) { | 400     if (is_registry_forced || !ReadPolicyFromGPO(scope, &gpo_dict, &status)) { | 
| 411       VLOG_IF(1, !is_registry_forced) << "Failed to read GPO files for " | 401       VLOG_IF(1, !is_registry_forced) << "Failed to read GPO files for " | 
| 412                                       << scope << " falling back to registry."; | 402                                       << scope << " falling back to registry."; | 
| 413       gpo_dict.ReadRegistry(kScopes[i].hive, chrome_policy_key_); | 403       gpo_dict.ReadRegistry(kScopes[i].hive, chrome_policy_key_); | 
| 414     } | 404     } | 
| 415 | 405 | 
| 416     // Remove special-cased entries from the GPO dictionary. | 406     // Remove special-cased entries from the GPO dictionary. | 
| 417     std::unique_ptr<RegistryDict> recommended_dict( | 407     std::unique_ptr<RegistryDict> recommended_dict( | 
| 418         gpo_dict.RemoveKey(kKeyRecommended)); | 408         gpo_dict.RemoveKey(kKeyRecommended)); | 
| 419     std::unique_ptr<RegistryDict> third_party_dict( | 409     std::unique_ptr<RegistryDict> third_party_dict( | 
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 620 | 610 | 
| 621 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { | 611 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { | 
| 622   DCHECK(object == user_policy_changed_event_.handle() || | 612   DCHECK(object == user_policy_changed_event_.handle() || | 
| 623          object == machine_policy_changed_event_.handle()) | 613          object == machine_policy_changed_event_.handle()) | 
| 624       << "unexpected object signaled policy reload, obj = " | 614       << "unexpected object signaled policy reload, obj = " | 
| 625       << std::showbase << std::hex << object; | 615       << std::showbase << std::hex << object; | 
| 626   Reload(false); | 616   Reload(false); | 
| 627 } | 617 } | 
| 628 | 618 | 
| 629 }  // namespace policy | 619 }  // namespace policy | 
| OLD | NEW | 
|---|