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