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