| 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> |
| 11 | 11 |
| 12 #include <string> | 12 #include <string> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 // shlwapi.dll is required for PathIsUNC(). | 15 // shlwapi.dll is required for PathIsUNC(). |
| 16 #pragma comment(lib, "shlwapi.lib") | 16 #pragma comment(lib, "shlwapi.lib") |
| 17 // userenv.dll is required for various GPO functions. | 17 // userenv.dll is required for various GPO functions. |
| 18 #pragma comment(lib, "userenv.lib") | 18 #pragma comment(lib, "userenv.lib") |
| 19 | 19 |
| 20 #include "base/basictypes.h" | 20 #include "base/basictypes.h" |
| 21 #include "base/file_util.h" | 21 #include "base/file_util.h" |
| 22 #include "base/json/json_reader.h" | 22 #include "base/json/json_reader.h" |
| 23 #include "base/lazy_instance.h" | 23 #include "base/lazy_instance.h" |
| 24 #include "base/logging.h" | 24 #include "base/logging.h" |
| 25 #include "base/message_loop/message_loop.h" |
| 25 #include "base/scoped_native_library.h" | 26 #include "base/scoped_native_library.h" |
| 26 #include "base/sequenced_task_runner.h" | 27 #include "base/sequenced_task_runner.h" |
| 27 #include "base/stl_util.h" | 28 #include "base/stl_util.h" |
| 28 #include "base/strings/string16.h" | 29 #include "base/strings/string16.h" |
| 29 #include "base/strings/string_util.h" | 30 #include "base/strings/string_util.h" |
| 31 #include "chrome/browser/policy/browser_policy_connector.h" |
| 30 #include "chrome/browser/policy/policy_bundle.h" | 32 #include "chrome/browser/policy/policy_bundle.h" |
| 33 #include "chrome/browser/policy/policy_domain_descriptor.h" |
| 31 #include "chrome/browser/policy/policy_load_status.h" | 34 #include "chrome/browser/policy/policy_load_status.h" |
| 32 #include "chrome/browser/policy/policy_map.h" | 35 #include "chrome/browser/policy/policy_map.h" |
| 36 #include "chrome/browser/policy/policy_service.h" |
| 33 #include "chrome/browser/policy/preg_parser_win.h" | 37 #include "chrome/browser/policy/preg_parser_win.h" |
| 34 #include "chrome/browser/policy/registry_dict_win.h" | 38 #include "chrome/browser/policy/registry_dict_win.h" |
| 35 #include "components/json_schema/json_schema_constants.h" | 39 #include "components/json_schema/json_schema_constants.h" |
| 36 #include "policy/policy_constants.h" | 40 #include "policy/policy_constants.h" |
| 37 | 41 |
| 38 namespace schema = json_schema_constants; | 42 namespace schema = json_schema_constants; |
| 39 | 43 |
| 40 namespace policy { | 44 namespace policy { |
| 41 | 45 |
| 42 namespace { | 46 namespace { |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 | 185 |
| 182 NOTREACHED() << "Unsupported policy value type " << value_type; | 186 NOTREACHED() << "Unsupported policy value type " << value_type; |
| 183 return json_schema_constants::kNull; | 187 return json_schema_constants::kNull; |
| 184 } | 188 } |
| 185 | 189 |
| 186 // Parses |gpo_dict| according to |schema| and writes the resulting policy | 190 // Parses |gpo_dict| according to |schema| and writes the resulting policy |
| 187 // settings to |policy| for the given |scope| and |level|. | 191 // settings to |policy| for the given |scope| and |level|. |
| 188 void ParsePolicy(const RegistryDict* gpo_dict, | 192 void ParsePolicy(const RegistryDict* gpo_dict, |
| 189 PolicyLevel level, | 193 PolicyLevel level, |
| 190 PolicyScope scope, | 194 PolicyScope scope, |
| 191 const base::DictionaryValue* schema, | 195 const PolicySchema* schema, |
| 192 PolicyMap* policy) { | 196 PolicyMap* policy) { |
| 193 if (!gpo_dict) | 197 if (!gpo_dict) |
| 194 return; | 198 return; |
| 195 | 199 |
| 196 scoped_ptr<base::Value> policy_value(gpo_dict->ConvertToJSON(schema)); | 200 scoped_ptr<base::Value> policy_value(gpo_dict->ConvertToJSON(schema)); |
| 197 const base::DictionaryValue* policy_dict = NULL; | 201 const base::DictionaryValue* policy_dict = NULL; |
| 198 if (!policy_value->GetAsDictionary(&policy_dict) || !policy_dict) { | 202 if (!policy_value->GetAsDictionary(&policy_dict) || !policy_dict) { |
| 199 LOG(WARNING) << "Root policy object is not a dictionary!"; | 203 LOG(WARNING) << "Root policy object is not a dictionary!"; |
| 200 return; | 204 return; |
| 201 } | 205 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 is_initialized_ = true; | 254 is_initialized_ = true; |
| 251 SetupWatches(); | 255 SetupWatches(); |
| 252 } | 256 } |
| 253 | 257 |
| 254 scoped_ptr<PolicyBundle> PolicyLoaderWin::Load() { | 258 scoped_ptr<PolicyBundle> PolicyLoaderWin::Load() { |
| 255 // Reset the watches BEFORE reading the individual policies to avoid | 259 // Reset the watches BEFORE reading the individual policies to avoid |
| 256 // missing a change notification. | 260 // missing a change notification. |
| 257 if (is_initialized_) | 261 if (is_initialized_) |
| 258 SetupWatches(); | 262 SetupWatches(); |
| 259 | 263 |
| 260 if (chrome_policy_schema_.empty()) | |
| 261 BuildChromePolicySchema(); | |
| 262 | |
| 263 // Policy scope and corresponding hive. | 264 // Policy scope and corresponding hive. |
| 264 static const struct { | 265 static const struct { |
| 265 PolicyScope scope; | 266 PolicyScope scope; |
| 266 HKEY hive; | 267 HKEY hive; |
| 267 } kScopes[] = { | 268 } kScopes[] = { |
| 268 { POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE }, | 269 { POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE }, |
| 269 { POLICY_SCOPE_USER, HKEY_CURRENT_USER }, | 270 { POLICY_SCOPE_USER, HKEY_CURRENT_USER }, |
| 270 }; | 271 }; |
| 271 | 272 |
| 272 // Load policy data for the different scopes/levels and merge them. | 273 // Load policy data for the different scopes/levels and merge them. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 chrome_policy); | 314 chrome_policy); |
| 314 | 315 |
| 315 // Load 3rd-party policy. | 316 // Load 3rd-party policy. |
| 316 if (third_party_dict) | 317 if (third_party_dict) |
| 317 Load3rdPartyPolicy(third_party_dict.get(), scope, bundle.get()); | 318 Load3rdPartyPolicy(third_party_dict.get(), scope, bundle.get()); |
| 318 } | 319 } |
| 319 | 320 |
| 320 return bundle.Pass(); | 321 return bundle.Pass(); |
| 321 } | 322 } |
| 322 | 323 |
| 323 void PolicyLoaderWin::BuildChromePolicySchema() { | |
| 324 scoped_ptr<base::DictionaryValue> properties(new base::DictionaryValue()); | |
| 325 for (const PolicyDefinitionList::Entry* e = policy_list_->begin; | |
| 326 e != policy_list_->end; ++e) { | |
| 327 const std::string schema_type = GetSchemaTypeForValueType(e->value_type); | |
| 328 scoped_ptr<base::DictionaryValue> entry_schema(new base::DictionaryValue()); | |
| 329 entry_schema->SetStringWithoutPathExpansion(json_schema_constants::kType, | |
| 330 schema_type); | |
| 331 | |
| 332 if (e->value_type == base::Value::TYPE_LIST) { | |
| 333 scoped_ptr<base::DictionaryValue> items_schema( | |
| 334 new base::DictionaryValue()); | |
| 335 items_schema->SetStringWithoutPathExpansion( | |
| 336 json_schema_constants::kType, json_schema_constants::kString); | |
| 337 entry_schema->SetWithoutPathExpansion(json_schema_constants::kItems, | |
| 338 items_schema.release()); | |
| 339 } | |
| 340 properties->SetWithoutPathExpansion(e->name, entry_schema.release()); | |
| 341 } | |
| 342 chrome_policy_schema_.SetStringWithoutPathExpansion( | |
| 343 json_schema_constants::kType, json_schema_constants::kObject); | |
| 344 chrome_policy_schema_.SetWithoutPathExpansion( | |
| 345 json_schema_constants::kProperties, properties.release()); | |
| 346 } | |
| 347 | |
| 348 bool PolicyLoaderWin::ReadPRegFile(const base::FilePath& preg_file, | 324 bool PolicyLoaderWin::ReadPRegFile(const base::FilePath& preg_file, |
| 349 RegistryDict* policy, | 325 RegistryDict* policy, |
| 350 PolicyLoadStatusSample* status) { | 326 PolicyLoadStatusSample* status) { |
| 351 // The following deals with the minor annoyance that Wow64 FS redirection | 327 // The following deals with the minor annoyance that Wow64 FS redirection |
| 352 // might need to be turned off: This is the case if running as a 32-bit | 328 // might need to be turned off: This is the case if running as a 32-bit |
| 353 // process on a 64-bit system, in which case Wow64 FS redirection redirects | 329 // process on a 64-bit system, in which case Wow64 FS redirection redirects |
| 354 // access to the %WINDIR%/System32/GroupPolicy directory to | 330 // access to the %WINDIR%/System32/GroupPolicy directory to |
| 355 // %WINDIR%/SysWOW64/GroupPolicy, but the file is actually in the | 331 // %WINDIR%/SysWOW64/GroupPolicy, but the file is actually in the |
| 356 // system-native directory. | 332 // system-native directory. |
| 357 if (base::PathExists(preg_file)) { | 333 if (base::PathExists(preg_file)) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 } | 414 } |
| 439 | 415 |
| 440 return result; | 416 return result; |
| 441 } | 417 } |
| 442 | 418 |
| 443 void PolicyLoaderWin::LoadChromePolicy(const RegistryDict* gpo_dict, | 419 void PolicyLoaderWin::LoadChromePolicy(const RegistryDict* gpo_dict, |
| 444 PolicyLevel level, | 420 PolicyLevel level, |
| 445 PolicyScope scope, | 421 PolicyScope scope, |
| 446 PolicyMap* chrome_policy_map) { | 422 PolicyMap* chrome_policy_map) { |
| 447 PolicyMap policy; | 423 PolicyMap policy; |
| 448 ParsePolicy(gpo_dict, level, scope, &chrome_policy_schema_, &policy); | 424 const PolicySchema* schema = NULL; |
| 425 scoped_refptr<const PolicyDomainDescriptor> descriptor = |
| 426 get_descriptor(POLICY_DOMAIN_CHROME); |
| 427 if (descriptor) |
| 428 schema = descriptor->get_schema(""); |
| 429 ParsePolicy(gpo_dict, level, scope, schema, &policy); |
| 449 chrome_policy_map->MergeFrom(policy); | 430 chrome_policy_map->MergeFrom(policy); |
| 450 } | 431 } |
| 451 | 432 |
| 433 const PolicySchema* PolicyLoaderWin::Load3rdPartyPolicySchema( |
| 434 PolicyDomain domain, |
| 435 const std::string& component_key, |
| 436 RegistryDict* component_dict) { |
| 437 |
| 438 // Try to find the schema in the domain descriptor, if it exists. |
| 439 scoped_refptr<const PolicyDomainDescriptor> descriptor = |
| 440 get_descriptor(domain); |
| 441 if (descriptor) { |
| 442 const PolicySchema* schema = |
| 443 descriptor->get_schema(domain + "//" + component_key); |
| 444 if (schema) |
| 445 return schema; |
| 446 } |
| 447 |
| 448 // Next, look in the registry entry. |
| 449 // TODO(joaodasilva): Remove this for M31. http://crbug.com/240704 |
| 450 std::string schema_json; |
| 451 const base::Value* schema_value = component_dict->GetValue(kKeySchema); |
| 452 if (schema_value && schema_value->GetAsString(&schema_json)) { |
| 453 std::string err; |
| 454 PolicySchema* parsed_schema = |
| 455 PolicySchema::Parse(schema_json, &err).release(); |
| 456 if (!parsed_schema) { |
| 457 LOG(ERROR) << "Failed to parse 3rd-party policy schema for " |
| 458 << domain << "/" << component_key << ": " |
| 459 << err; |
| 460 return NULL; |
| 461 } |
| 462 // We don't want to own the schema, but we need it around for the |
| 463 // rest of this task to parse the policy value. |
| 464 base::MessageLoop::current()->DeleteSoon(FROM_HERE, parsed_schema); |
| 465 return parsed_schema; |
| 466 } |
| 467 |
| 468 return NULL; |
| 469 } |
| 470 |
| 452 void PolicyLoaderWin::Load3rdPartyPolicy(const RegistryDict* gpo_dict, | 471 void PolicyLoaderWin::Load3rdPartyPolicy(const RegistryDict* gpo_dict, |
| 453 PolicyScope scope, | 472 PolicyScope scope, |
| 454 PolicyBundle* bundle) { | 473 PolicyBundle* bundle) { |
| 455 // Map of known 3rd party policy domain name to their enum values. | 474 // Map of known 3rd party policy domain name to their enum values. |
| 456 static const struct { | 475 static const struct { |
| 457 const char* name; | 476 const char* name; |
| 458 PolicyDomain domain; | 477 PolicyDomain domain; |
| 459 } k3rdPartyDomains[] = { | 478 } k3rdPartyDomains[] = { |
| 460 { "extensions", POLICY_DOMAIN_EXTENSIONS }, | 479 { "extensions", POLICY_DOMAIN_EXTENSIONS }, |
| 461 }; | 480 }; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 474 const PolicyDomain domain = k3rdPartyDomains[i].domain; | 493 const PolicyDomain domain = k3rdPartyDomains[i].domain; |
| 475 const RegistryDict* domain_dict = gpo_dict->GetKey(name); | 494 const RegistryDict* domain_dict = gpo_dict->GetKey(name); |
| 476 if (!domain_dict) | 495 if (!domain_dict) |
| 477 continue; | 496 continue; |
| 478 | 497 |
| 479 for (RegistryDict::KeyMap::const_iterator component( | 498 for (RegistryDict::KeyMap::const_iterator component( |
| 480 domain_dict->keys().begin()); | 499 domain_dict->keys().begin()); |
| 481 component != domain_dict->keys().end(); | 500 component != domain_dict->keys().end(); |
| 482 ++component) { | 501 ++component) { |
| 483 // Load the schema. | 502 // Load the schema. |
| 484 const base::DictionaryValue* schema_dict = NULL; | 503 const PolicySchema* schema = |
| 485 scoped_ptr<base::Value> schema; | 504 Load3rdPartyPolicySchema(domain, component->first, component->second); |
| 486 std::string schema_json; | |
| 487 const base::Value* schema_value = component->second->GetValue(kKeySchema); | |
| 488 if (schema_value && schema_value->GetAsString(&schema_json)) { | |
| 489 schema.reset(base::JSONReader::Read(schema_json)); | |
| 490 if (!schema || !schema->GetAsDictionary(&schema_dict)) { | |
| 491 LOG(WARNING) << "Failed to parse 3rd-part policy schema for " | |
| 492 << domain << "/" << component->first; | |
| 493 } | |
| 494 } | |
| 495 | 505 |
| 496 // Parse policy. | 506 // Parse policy. |
| 497 for (size_t j = 0; j < arraysize(kLevels); j++) { | 507 for (size_t j = 0; j < arraysize(kLevels); j++) { |
| 498 const RegistryDict* policy_dict = | 508 const RegistryDict* policy_dict = |
| 499 component->second->GetKey(kLevels[j].path); | 509 component->second->GetKey(kLevels[j].path); |
| 500 if (!policy_dict) | 510 if (!policy_dict) |
| 501 continue; | 511 continue; |
| 502 | 512 |
| 503 PolicyMap policy; | 513 PolicyMap policy; |
| 504 ParsePolicy(policy_dict, kLevels[j].level, scope, schema_dict, &policy); | 514 ParsePolicy(policy_dict, kLevels[j].level, scope, schema, &policy); |
| 505 PolicyNamespace policy_namespace(domain, component->first); | 515 PolicyNamespace policy_namespace(domain, component->first); |
| 506 bundle->Get(policy_namespace).MergeFrom(policy); | 516 bundle->Get(policy_namespace).MergeFrom(policy); |
| 507 } | 517 } |
| 508 } | 518 } |
| 509 } | 519 } |
| 510 } | 520 } |
| 511 | 521 |
| 512 void PolicyLoaderWin::SetupWatches() { | 522 void PolicyLoaderWin::SetupWatches() { |
| 513 DCHECK(is_initialized_); | 523 DCHECK(is_initialized_); |
| 514 if (!user_policy_watcher_failed_ && | 524 if (!user_policy_watcher_failed_ && |
| (...skipping 14 matching lines...) Expand all Loading... |
| 529 | 539 |
| 530 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { | 540 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { |
| 531 DCHECK(object == user_policy_changed_event_.handle() || | 541 DCHECK(object == user_policy_changed_event_.handle() || |
| 532 object == machine_policy_changed_event_.handle()) | 542 object == machine_policy_changed_event_.handle()) |
| 533 << "unexpected object signaled policy reload, obj = " | 543 << "unexpected object signaled policy reload, obj = " |
| 534 << std::showbase << std::hex << object; | 544 << std::showbase << std::hex << object; |
| 535 Reload(false); | 545 Reload(false); |
| 536 } | 546 } |
| 537 | 547 |
| 538 } // namespace policy | 548 } // namespace policy |
| OLD | NEW |