Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/policy/policy_loader_win.h" | 5 #include "chrome/browser/policy/policy_loader_win.h" |
| 6 | 6 |
| 7 #include <rpc.h> // For struct GUID | 7 #include <rpc.h> // For struct GUID |
| 8 #include <shlwapi.h> // For PathIsUNC() | 8 #include <shlwapi.h> // For PathIsUNC() |
| 9 #include <userenv.h> // For GPO functions | 9 #include <userenv.h> // For GPO functions |
| 10 #include <windows.h> | 10 #include <windows.h> |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 #include "base/logging.h" | 24 #include "base/logging.h" |
| 25 #include "base/scoped_native_library.h" | 25 #include "base/scoped_native_library.h" |
| 26 #include "base/stl_util.h" | 26 #include "base/stl_util.h" |
| 27 #include "base/string16.h" | 27 #include "base/string16.h" |
| 28 #include "base/string_util.h" | 28 #include "base/string_util.h" |
| 29 #include "base/strings/string_number_conversions.h" | 29 #include "base/strings/string_number_conversions.h" |
| 30 #include "base/sys_byteorder.h" | 30 #include "base/sys_byteorder.h" |
| 31 #include "base/utf_string_conversions.h" | 31 #include "base/utf_string_conversions.h" |
| 32 #include "base/win/registry.h" | 32 #include "base/win/registry.h" |
| 33 #include "chrome/browser/policy/policy_bundle.h" | 33 #include "chrome/browser/policy/policy_bundle.h" |
| 34 #include "chrome/browser/policy/policy_load_status.h" | |
| 34 #include "chrome/browser/policy/policy_map.h" | 35 #include "chrome/browser/policy/policy_map.h" |
| 35 #include "chrome/browser/policy/preg_parser_win.h" | 36 #include "chrome/browser/policy/preg_parser_win.h" |
| 36 #include "chrome/common/json_schema/json_schema_constants.h" | 37 #include "chrome/common/json_schema/json_schema_constants.h" |
| 37 #include "policy/policy_constants.h" | 38 #include "policy/policy_constants.h" |
| 38 | 39 |
| 39 namespace schema = json_schema_constants; | 40 namespace schema = json_schema_constants; |
| 40 | 41 |
| 41 using base::win::RegKey; | 42 using base::win::RegKey; |
| 42 using base::win::RegistryKeyIterator; | 43 using base::win::RegistryKeyIterator; |
| 43 using base::win::RegistryValueIterator; | 44 using base::win::RegistryValueIterator; |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 503 { POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE }, | 504 { POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE }, |
| 504 { POLICY_SCOPE_USER, HKEY_CURRENT_USER }, | 505 { POLICY_SCOPE_USER, HKEY_CURRENT_USER }, |
| 505 }; | 506 }; |
| 506 | 507 |
| 507 // Load policy data for the different scopes/levels and merge them. | 508 // Load policy data for the different scopes/levels and merge them. |
| 508 scoped_ptr<PolicyBundle> bundle(new PolicyBundle()); | 509 scoped_ptr<PolicyBundle> bundle(new PolicyBundle()); |
| 509 PolicyMap* chrome_policy = | 510 PolicyMap* chrome_policy = |
| 510 &bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); | 511 &bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); |
| 511 for (size_t i = 0; i < arraysize(kScopes); ++i) { | 512 for (size_t i = 0; i < arraysize(kScopes); ++i) { |
| 512 PolicyScope scope = kScopes[i].scope; | 513 PolicyScope scope = kScopes[i].scope; |
| 514 PolicyLoadStatusSample status(scope, -1); | |
| 513 base::DictionaryValue gpo_dict; | 515 base::DictionaryValue gpo_dict; |
| 514 | 516 |
| 515 HANDLE policy_lock = | 517 HANDLE policy_lock = |
| 516 EnterCriticalPolicySection(scope == POLICY_SCOPE_MACHINE); | 518 EnterCriticalPolicySection(scope == POLICY_SCOPE_MACHINE); |
| 517 if (policy_lock == NULL) | 519 if (policy_lock == NULL) |
| 518 PLOG(ERROR) << "EnterCriticalPolicySection"; | 520 PLOG(ERROR) << "EnterCriticalPolicySection"; |
| 519 | 521 |
| 520 if (!ReadPolicyFromGPO(scope, &gpo_dict)) { | 522 if (!ReadPolicyFromGPO(scope, &gpo_dict, &status)) { |
| 521 VLOG(1) << "Failed to read GPO files for " << scope | 523 VLOG(1) << "Failed to read GPO files for " << scope |
| 522 << " falling back to registry."; | 524 << " falling back to registry."; |
| 523 ReadRegistry(kScopes[i].hive, chrome_policy_key_, &gpo_dict); | 525 ReadRegistry(kScopes[i].hive, chrome_policy_key_, &gpo_dict); |
|
Joao da Silva
2013/04/16 17:31:04
No sampling for this case?
Mattias Nissler (ping if slow)
2013/04/16 18:51:14
It's all good! :)
Assuming ReadPolicyFromGPO samp
| |
| 524 } | 526 } |
| 525 | 527 |
| 526 if (!LeaveCriticalPolicySection(policy_lock)) | 528 if (!LeaveCriticalPolicySection(policy_lock)) |
| 527 PLOG(ERROR) << "LeaveCriticalPolicySection"; | 529 PLOG(ERROR) << "LeaveCriticalPolicySection"; |
| 528 | 530 |
| 529 // Remove special-cased entries from the GPO dictionary. | 531 // Remove special-cased entries from the GPO dictionary. |
| 530 base::DictionaryValue* temp_dict = NULL; | 532 base::DictionaryValue* temp_dict = NULL; |
| 531 scoped_ptr<base::DictionaryValue> recommended_dict( | 533 scoped_ptr<base::DictionaryValue> recommended_dict( |
| 532 RemoveDict(&gpo_dict, kKeyRecommended)); | 534 RemoveDict(&gpo_dict, kKeyRecommended)); |
| 533 scoped_ptr<base::DictionaryValue> third_party_dict( | 535 scoped_ptr<base::DictionaryValue> third_party_dict( |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 565 } | 567 } |
| 566 properties->SetWithoutPathExpansion(e->name, entry_schema.release()); | 568 properties->SetWithoutPathExpansion(e->name, entry_schema.release()); |
| 567 } | 569 } |
| 568 chrome_policy_schema_.SetStringWithoutPathExpansion( | 570 chrome_policy_schema_.SetStringWithoutPathExpansion( |
| 569 json_schema_constants::kType, json_schema_constants::kObject); | 571 json_schema_constants::kType, json_schema_constants::kObject); |
| 570 chrome_policy_schema_.SetWithoutPathExpansion( | 572 chrome_policy_schema_.SetWithoutPathExpansion( |
| 571 json_schema_constants::kProperties, properties.release()); | 573 json_schema_constants::kProperties, properties.release()); |
| 572 } | 574 } |
| 573 | 575 |
| 574 bool PolicyLoaderWin::ReadPRegFile(const base::FilePath& preg_file, | 576 bool PolicyLoaderWin::ReadPRegFile(const base::FilePath& preg_file, |
| 575 base::DictionaryValue* policy) { | 577 base::DictionaryValue* policy, |
| 578 PolicyLoadStatusSample* status) { | |
| 576 // The following deals with the minor annoyance that Wow64 FS redirection | 579 // The following deals with the minor annoyance that Wow64 FS redirection |
| 577 // might need to be turned off: This is the case if running as a 32-bit | 580 // might need to be turned off: This is the case if running as a 32-bit |
| 578 // process on a 64-bit system, in which case Wow64 FS redirection redirects | 581 // process on a 64-bit system, in which case Wow64 FS redirection redirects |
| 579 // access to the %WINDIR%/System32/GroupPolicy directory to | 582 // access to the %WINDIR%/System32/GroupPolicy directory to |
| 580 // %WINDIR%/SysWOW64/GroupPolicy, but the file is actually in the | 583 // %WINDIR%/SysWOW64/GroupPolicy, but the file is actually in the |
| 581 // system-native directory. | 584 // system-native directory. |
| 582 if (file_util::PathExists(preg_file)) { | 585 if (file_util::PathExists(preg_file)) { |
| 583 return preg_parser::ReadFile(preg_file, chrome_policy_key_, policy); | 586 return preg_parser::ReadFile(preg_file, chrome_policy_key_, policy, status); |
| 584 } else { | 587 } else { |
| 585 // Try with redirection switched off. | 588 // Try with redirection switched off. |
| 586 ScopedDisableWow64Redirection redirection_disable; | 589 ScopedDisableWow64Redirection redirection_disable; |
| 587 if (redirection_disable.is_active() && file_util::PathExists(preg_file)) | 590 if (redirection_disable.is_active() && file_util::PathExists(preg_file)) { |
| 588 return preg_parser::ReadFile(preg_file, chrome_policy_key_, policy); | 591 status->Add(POLICY_LOAD_STATUS_WOW64_REDIRECTION_DISABLED); |
| 592 return preg_parser::ReadFile(preg_file, chrome_policy_key_, policy, | |
| 593 status); | |
| 594 } | |
| 589 } | 595 } |
| 590 | 596 |
| 591 // Report the error. | 597 // Report the error. |
| 592 LOG(ERROR) << "PReg file doesn't exist: " << preg_file.value(); | 598 LOG(ERROR) << "PReg file doesn't exist: " << preg_file.value(); |
| 599 status->Add(POLICY_LOAD_STATUS_MISSING); | |
| 593 return false; | 600 return false; |
| 594 } | 601 } |
| 595 | 602 |
| 596 bool PolicyLoaderWin::LoadGPOPolicy(PolicyScope scope, | 603 bool PolicyLoaderWin::LoadGPOPolicy(PolicyScope scope, |
| 597 PGROUP_POLICY_OBJECT policy_object_list, | 604 PGROUP_POLICY_OBJECT policy_object_list, |
| 598 base::DictionaryValue* policy) { | 605 base::DictionaryValue* policy, |
| 606 PolicyLoadStatusSample* status) { | |
| 599 base::DictionaryValue parsed_policy; | 607 base::DictionaryValue parsed_policy; |
| 600 base::DictionaryValue forced_policy; | 608 base::DictionaryValue forced_policy; |
| 601 for (GROUP_POLICY_OBJECT* policy_object = policy_object_list; | 609 for (GROUP_POLICY_OBJECT* policy_object = policy_object_list; |
| 602 policy_object; policy_object = policy_object->pNext) { | 610 policy_object; policy_object = policy_object->pNext) { |
| 603 if (policy_object->dwOptions & GPO_FLAG_DISABLE) | 611 if (policy_object->dwOptions & GPO_FLAG_DISABLE) |
| 604 continue; | 612 continue; |
| 605 | 613 |
| 606 if (PathIsUNC(policy_object->lpFileSysPath)) { | 614 if (PathIsUNC(policy_object->lpFileSysPath)) { |
| 607 // UNC path: Assume this is an AD-managed machine, which updates the | 615 // UNC path: Assume this is an AD-managed machine, which updates the |
| 608 // registry via GPO's standard registry CSE periodically. Fall back to | 616 // registry via GPO's standard registry CSE periodically. Fall back to |
| 609 // reading from the registry in this case. | 617 // reading from the registry in this case. |
| 618 status->Add(POLICY_LOAD_STATUS_INACCCESSIBLE); | |
| 610 return false; | 619 return false; |
| 611 } | 620 } |
| 612 | 621 |
| 613 base::FilePath preg_file_path( | 622 base::FilePath preg_file_path( |
| 614 base::FilePath(policy_object->lpFileSysPath).Append(kPRegFileName)); | 623 base::FilePath(policy_object->lpFileSysPath).Append(kPRegFileName)); |
| 615 if (policy_object->dwOptions & GPO_FLAG_FORCE) { | 624 if (policy_object->dwOptions & GPO_FLAG_FORCE) { |
| 616 base::DictionaryValue new_forced_policy; | 625 base::DictionaryValue new_forced_policy; |
| 617 if (!ReadPRegFile(preg_file_path, &new_forced_policy)) | 626 if (!ReadPRegFile(preg_file_path, &new_forced_policy, status)) |
| 618 return false; | 627 return false; |
| 619 | 628 |
| 620 // Merge with existing forced policy, giving precedence to the existing | 629 // Merge with existing forced policy, giving precedence to the existing |
| 621 // forced policy. | 630 // forced policy. |
| 622 new_forced_policy.MergeDictionary(&forced_policy); | 631 new_forced_policy.MergeDictionary(&forced_policy); |
| 623 forced_policy.Swap(&new_forced_policy); | 632 forced_policy.Swap(&new_forced_policy); |
| 624 } else { | 633 } else { |
| 625 if (!ReadPRegFile(preg_file_path, &parsed_policy)) | 634 if (!ReadPRegFile(preg_file_path, &parsed_policy, status)) |
| 626 return false; | 635 return false; |
| 627 } | 636 } |
| 628 } | 637 } |
| 629 | 638 |
| 630 // Merge, give precedence to forced policy. | 639 // Merge, give precedence to forced policy. |
| 631 parsed_policy.MergeDictionary(&forced_policy); | 640 parsed_policy.MergeDictionary(&forced_policy); |
| 632 policy->Swap(&parsed_policy); | 641 policy->Swap(&parsed_policy); |
| 633 | 642 |
| 634 return true; | 643 return true; |
| 635 } | 644 } |
| 636 | 645 |
| 637 | 646 |
| 638 bool PolicyLoaderWin::ReadPolicyFromGPO(PolicyScope scope, | 647 bool PolicyLoaderWin::ReadPolicyFromGPO(PolicyScope scope, |
| 639 base::DictionaryValue* policy) { | 648 base::DictionaryValue* policy, |
| 649 PolicyLoadStatusSample* status) { | |
| 640 PGROUP_POLICY_OBJECT policy_object_list = NULL; | 650 PGROUP_POLICY_OBJECT policy_object_list = NULL; |
| 641 DWORD flags = scope == POLICY_SCOPE_MACHINE ? GPO_LIST_FLAG_MACHINE : 0; | 651 DWORD flags = scope == POLICY_SCOPE_MACHINE ? GPO_LIST_FLAG_MACHINE : 0; |
| 642 if (gpo_provider_->GetAppliedGPOList( | 652 if (gpo_provider_->GetAppliedGPOList( |
| 643 flags, NULL, NULL, &kRegistrySettingsCSEGUID, | 653 flags, NULL, NULL, &kRegistrySettingsCSEGUID, |
| 644 &policy_object_list) != ERROR_SUCCESS) { | 654 &policy_object_list) != ERROR_SUCCESS) { |
| 645 PLOG(ERROR) << "GetAppliedGPOList scope " << scope; | 655 PLOG(ERROR) << "GetAppliedGPOList scope " << scope; |
| 656 status->Add(POLICY_LOAD_STATUS_QUERY_FAILED); | |
| 646 return false; | 657 return false; |
| 647 } | 658 } |
| 648 | 659 |
| 649 bool result = LoadGPOPolicy(scope, policy_object_list, policy); | 660 bool result = true; |
| 650 if (!gpo_provider_->FreeGPOList(policy_object_list)) | 661 if (policy_object_list) { |
| 651 LOG(WARNING) << "FreeGPOList"; | 662 result = LoadGPOPolicy(scope, policy_object_list, policy, status); |
| 663 if (!gpo_provider_->FreeGPOList(policy_object_list)) | |
| 664 LOG(WARNING) << "FreeGPOList"; | |
| 665 } else { | |
| 666 status->Add(POLICY_LOAD_STATUS_NO_POLICY); | |
| 667 } | |
| 652 | 668 |
| 653 return result; | 669 return result; |
| 654 } | 670 } |
| 655 | 671 |
| 656 void PolicyLoaderWin::LoadChromePolicy(const base::DictionaryValue* gpo_dict, | 672 void PolicyLoaderWin::LoadChromePolicy(const base::DictionaryValue* gpo_dict, |
| 657 PolicyLevel level, | 673 PolicyLevel level, |
| 658 PolicyScope scope, | 674 PolicyScope scope, |
| 659 PolicyMap* chrome_policy_map) { | 675 PolicyMap* chrome_policy_map) { |
| 660 PolicyMap policy; | 676 PolicyMap policy; |
| 661 ParsePolicy(gpo_dict, level, scope, &chrome_policy_schema_, &policy); | 677 ParsePolicy(gpo_dict, level, scope, &chrome_policy_schema_, &policy); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 751 | 767 |
| 752 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { | 768 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { |
| 753 DCHECK(object == user_policy_changed_event_.handle() || | 769 DCHECK(object == user_policy_changed_event_.handle() || |
| 754 object == machine_policy_changed_event_.handle()) | 770 object == machine_policy_changed_event_.handle()) |
| 755 << "unexpected object signaled policy reload, obj = " | 771 << "unexpected object signaled policy reload, obj = " |
| 756 << std::showbase << std::hex << object; | 772 << std::showbase << std::hex << object; |
| 757 Reload(false); | 773 Reload(false); |
| 758 } | 774 } |
| 759 | 775 |
| 760 } // namespace policy | 776 } // namespace policy |
| OLD | NEW |