| 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 <windows.h> | 7 #include <windows.h> |
| 8 #include <rpc.h> // For struct GUID | 8 #include <rpc.h> // For struct GUID |
| 9 #include <shlwapi.h> // For PathIsUNC() | 9 #include <shlwapi.h> // For PathIsUNC() |
| 10 #include <userenv.h> // For GPO functions | 10 #include <userenv.h> // For GPO functions |
| 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" | |
| 23 #include "base/lazy_instance.h" | 22 #include "base/lazy_instance.h" |
| 24 #include "base/logging.h" | 23 #include "base/logging.h" |
| 25 #include "base/scoped_native_library.h" | 24 #include "base/scoped_native_library.h" |
| 26 #include "base/sequenced_task_runner.h" | 25 #include "base/sequenced_task_runner.h" |
| 27 #include "base/stl_util.h" | 26 #include "base/stl_util.h" |
| 28 #include "base/strings/string16.h" | 27 #include "base/strings/string16.h" |
| 29 #include "base/strings/string_util.h" | 28 #include "base/strings/string_util.h" |
| 29 #include "base/values.h" |
| 30 #include "chrome/browser/policy/policy_load_status.h" | 30 #include "chrome/browser/policy/policy_load_status.h" |
| 31 #include "chrome/browser/policy/preg_parser_win.h" | 31 #include "chrome/browser/policy/preg_parser_win.h" |
| 32 #include "components/json_schema/json_schema_constants.h" | |
| 33 #include "components/policy/core/common/policy_bundle.h" | 32 #include "components/policy/core/common/policy_bundle.h" |
| 34 #include "components/policy/core/common/policy_map.h" | 33 #include "components/policy/core/common/policy_map.h" |
| 35 #include "components/policy/core/common/policy_namespace.h" | 34 #include "components/policy/core/common/policy_namespace.h" |
| 36 #include "components/policy/core/common/registry_dict_win.h" | 35 #include "components/policy/core/common/registry_dict_win.h" |
| 37 #include "components/policy/core/common/schema.h" | 36 #include "components/policy/core/common/schema.h" |
| 38 | 37 |
| 39 namespace schema = json_schema_constants; | |
| 40 | |
| 41 namespace policy { | 38 namespace policy { |
| 42 | 39 |
| 43 namespace { | 40 namespace { |
| 44 | 41 |
| 45 const char kKeyMandatory[] = "policy"; | 42 const char kKeyMandatory[] = "policy"; |
| 46 const char kKeyRecommended[] = "recommended"; | 43 const char kKeyRecommended[] = "recommended"; |
| 47 const char kKeySchema[] = "schema"; | 44 const char kKeySchema[] = "schema"; |
| 48 const char kKeyThirdParty[] = "3rdparty"; | 45 const char kKeyThirdParty[] = "3rdparty"; |
| 49 | 46 |
| 50 // The GUID of the registry settings group policy extension. | 47 // The GUID of the registry settings group policy extension. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 | 154 |
| 158 virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE { | 155 virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE { |
| 159 return ::FreeGPOList(gpo_list); | 156 return ::FreeGPOList(gpo_list); |
| 160 } | 157 } |
| 161 }; | 158 }; |
| 162 | 159 |
| 163 // The default windows GPO list provider used for PolicyLoaderWin. | 160 // The default windows GPO list provider used for PolicyLoaderWin. |
| 164 static base::LazyInstance<WinGPOListProvider> g_win_gpo_list_provider = | 161 static base::LazyInstance<WinGPOListProvider> g_win_gpo_list_provider = |
| 165 LAZY_INSTANCE_INITIALIZER; | 162 LAZY_INSTANCE_INITIALIZER; |
| 166 | 163 |
| 167 std::string GetSchemaTypeForValueType(base::Value::Type value_type) { | |
| 168 switch (value_type) { | |
| 169 case base::Value::TYPE_DICTIONARY: | |
| 170 return json_schema_constants::kObject; | |
| 171 case base::Value::TYPE_INTEGER: | |
| 172 return json_schema_constants::kInteger; | |
| 173 case base::Value::TYPE_LIST: | |
| 174 return json_schema_constants::kArray; | |
| 175 case base::Value::TYPE_BOOLEAN: | |
| 176 return json_schema_constants::kBoolean; | |
| 177 case base::Value::TYPE_STRING: | |
| 178 return json_schema_constants::kString; | |
| 179 default: | |
| 180 break; | |
| 181 } | |
| 182 | |
| 183 NOTREACHED() << "Unsupported policy value type " << value_type; | |
| 184 return json_schema_constants::kNull; | |
| 185 } | |
| 186 | |
| 187 // Parses |gpo_dict| according to |schema| and writes the resulting policy | 164 // Parses |gpo_dict| according to |schema| and writes the resulting policy |
| 188 // settings to |policy| for the given |scope| and |level|. | 165 // settings to |policy| for the given |scope| and |level|. |
| 189 void ParsePolicy(const RegistryDict* gpo_dict, | 166 void ParsePolicy(const RegistryDict* gpo_dict, |
| 190 PolicyLevel level, | 167 PolicyLevel level, |
| 191 PolicyScope scope, | 168 PolicyScope scope, |
| 192 const base::DictionaryValue* schema, | 169 const Schema& schema, |
| 193 PolicyMap* policy) { | 170 PolicyMap* policy) { |
| 194 if (!gpo_dict) | 171 if (!gpo_dict) |
| 195 return; | 172 return; |
| 196 | 173 |
| 197 scoped_ptr<base::Value> policy_value(gpo_dict->ConvertToJSON(schema)); | 174 scoped_ptr<base::Value> policy_value(gpo_dict->ConvertToJSON(schema)); |
| 198 const base::DictionaryValue* policy_dict = NULL; | 175 const base::DictionaryValue* policy_dict = NULL; |
| 199 if (!policy_value->GetAsDictionary(&policy_dict) || !policy_dict) { | 176 if (!policy_value->GetAsDictionary(&policy_dict) || !policy_dict) { |
| 200 LOG(WARNING) << "Root policy object is not a dictionary!"; | 177 LOG(WARNING) << "Root policy object is not a dictionary!"; |
| 201 return; | 178 return; |
| 202 } | 179 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 is_initialized_ = true; | 233 is_initialized_ = true; |
| 257 SetupWatches(); | 234 SetupWatches(); |
| 258 } | 235 } |
| 259 | 236 |
| 260 scoped_ptr<PolicyBundle> PolicyLoaderWin::Load() { | 237 scoped_ptr<PolicyBundle> PolicyLoaderWin::Load() { |
| 261 // Reset the watches BEFORE reading the individual policies to avoid | 238 // Reset the watches BEFORE reading the individual policies to avoid |
| 262 // missing a change notification. | 239 // missing a change notification. |
| 263 if (is_initialized_) | 240 if (is_initialized_) |
| 264 SetupWatches(); | 241 SetupWatches(); |
| 265 | 242 |
| 266 if (chrome_policy_schema_.empty()) | |
| 267 BuildChromePolicySchema(); | |
| 268 | |
| 269 // Policy scope and corresponding hive. | 243 // Policy scope and corresponding hive. |
| 270 static const struct { | 244 static const struct { |
| 271 PolicyScope scope; | 245 PolicyScope scope; |
| 272 HKEY hive; | 246 HKEY hive; |
| 273 } kScopes[] = { | 247 } kScopes[] = { |
| 274 { POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE }, | 248 { POLICY_SCOPE_MACHINE, HKEY_LOCAL_MACHINE }, |
| 275 { POLICY_SCOPE_USER, HKEY_CURRENT_USER }, | 249 { POLICY_SCOPE_USER, HKEY_CURRENT_USER }, |
| 276 }; | 250 }; |
| 277 | 251 |
| 278 // Load policy data for the different scopes/levels and merge them. | 252 // Load policy data for the different scopes/levels and merge them. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 chrome_policy); | 293 chrome_policy); |
| 320 | 294 |
| 321 // Load 3rd-party policy. | 295 // Load 3rd-party policy. |
| 322 if (third_party_dict) | 296 if (third_party_dict) |
| 323 Load3rdPartyPolicy(third_party_dict.get(), scope, bundle.get()); | 297 Load3rdPartyPolicy(third_party_dict.get(), scope, bundle.get()); |
| 324 } | 298 } |
| 325 | 299 |
| 326 return bundle.Pass(); | 300 return bundle.Pass(); |
| 327 } | 301 } |
| 328 | 302 |
| 329 void PolicyLoaderWin::BuildChromePolicySchema() { | |
| 330 // TODO(joaodasilva): use the Schema directly instead of building this | |
| 331 // DictionaryValue. | |
| 332 scoped_ptr<base::DictionaryValue> properties(new base::DictionaryValue()); | |
| 333 const Schema* chrome_schema = | |
| 334 schema_map()->GetSchema(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); | |
| 335 for (Schema::Iterator it = chrome_schema->GetPropertiesIterator(); | |
| 336 !it.IsAtEnd(); it.Advance()) { | |
| 337 const std::string schema_type = | |
| 338 GetSchemaTypeForValueType(it.schema().type()); | |
| 339 scoped_ptr<base::DictionaryValue> entry_schema(new base::DictionaryValue()); | |
| 340 entry_schema->SetStringWithoutPathExpansion(json_schema_constants::kType, | |
| 341 schema_type); | |
| 342 | |
| 343 if (it.schema().type() == base::Value::TYPE_LIST) { | |
| 344 scoped_ptr<base::DictionaryValue> items_schema( | |
| 345 new base::DictionaryValue()); | |
| 346 items_schema->SetStringWithoutPathExpansion( | |
| 347 json_schema_constants::kType, json_schema_constants::kString); | |
| 348 entry_schema->SetWithoutPathExpansion(json_schema_constants::kItems, | |
| 349 items_schema.release()); | |
| 350 } | |
| 351 properties->SetWithoutPathExpansion(it.key(), entry_schema.release()); | |
| 352 } | |
| 353 chrome_policy_schema_.SetStringWithoutPathExpansion( | |
| 354 json_schema_constants::kType, json_schema_constants::kObject); | |
| 355 chrome_policy_schema_.SetWithoutPathExpansion( | |
| 356 json_schema_constants::kProperties, properties.release()); | |
| 357 } | |
| 358 | |
| 359 bool PolicyLoaderWin::ReadPRegFile(const base::FilePath& preg_file, | 303 bool PolicyLoaderWin::ReadPRegFile(const base::FilePath& preg_file, |
| 360 RegistryDict* policy, | 304 RegistryDict* policy, |
| 361 PolicyLoadStatusSample* status) { | 305 PolicyLoadStatusSample* status) { |
| 362 // The following deals with the minor annoyance that Wow64 FS redirection | 306 // The following deals with the minor annoyance that Wow64 FS redirection |
| 363 // might need to be turned off: This is the case if running as a 32-bit | 307 // might need to be turned off: This is the case if running as a 32-bit |
| 364 // process on a 64-bit system, in which case Wow64 FS redirection redirects | 308 // process on a 64-bit system, in which case Wow64 FS redirection redirects |
| 365 // access to the %WINDIR%/System32/GroupPolicy directory to | 309 // access to the %WINDIR%/System32/GroupPolicy directory to |
| 366 // %WINDIR%/SysWOW64/GroupPolicy, but the file is actually in the | 310 // %WINDIR%/SysWOW64/GroupPolicy, but the file is actually in the |
| 367 // system-native directory. | 311 // system-native directory. |
| 368 if (base::PathExists(preg_file)) { | 312 if (base::PathExists(preg_file)) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 } | 393 } |
| 450 | 394 |
| 451 return result; | 395 return result; |
| 452 } | 396 } |
| 453 | 397 |
| 454 void PolicyLoaderWin::LoadChromePolicy(const RegistryDict* gpo_dict, | 398 void PolicyLoaderWin::LoadChromePolicy(const RegistryDict* gpo_dict, |
| 455 PolicyLevel level, | 399 PolicyLevel level, |
| 456 PolicyScope scope, | 400 PolicyScope scope, |
| 457 PolicyMap* chrome_policy_map) { | 401 PolicyMap* chrome_policy_map) { |
| 458 PolicyMap policy; | 402 PolicyMap policy; |
| 459 ParsePolicy(gpo_dict, level, scope, &chrome_policy_schema_, &policy); | 403 const Schema* chrome_schema = |
| 404 schema_map()->GetSchema(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); |
| 405 ParsePolicy(gpo_dict, level, scope, *chrome_schema, &policy); |
| 460 chrome_policy_map->MergeFrom(policy); | 406 chrome_policy_map->MergeFrom(policy); |
| 461 } | 407 } |
| 462 | 408 |
| 463 void PolicyLoaderWin::Load3rdPartyPolicy(const RegistryDict* gpo_dict, | 409 void PolicyLoaderWin::Load3rdPartyPolicy(const RegistryDict* gpo_dict, |
| 464 PolicyScope scope, | 410 PolicyScope scope, |
| 465 PolicyBundle* bundle) { | 411 PolicyBundle* bundle) { |
| 466 // Map of known 3rd party policy domain name to their enum values. | 412 // Map of known 3rd party policy domain name to their enum values. |
| 467 static const struct { | 413 static const struct { |
| 468 const char* name; | 414 const char* name; |
| 469 PolicyDomain domain; | 415 PolicyDomain domain; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 484 const char* name = k3rdPartyDomains[i].name; | 430 const char* name = k3rdPartyDomains[i].name; |
| 485 const PolicyDomain domain = k3rdPartyDomains[i].domain; | 431 const PolicyDomain domain = k3rdPartyDomains[i].domain; |
| 486 const RegistryDict* domain_dict = gpo_dict->GetKey(name); | 432 const RegistryDict* domain_dict = gpo_dict->GetKey(name); |
| 487 if (!domain_dict) | 433 if (!domain_dict) |
| 488 continue; | 434 continue; |
| 489 | 435 |
| 490 for (RegistryDict::KeyMap::const_iterator component( | 436 for (RegistryDict::KeyMap::const_iterator component( |
| 491 domain_dict->keys().begin()); | 437 domain_dict->keys().begin()); |
| 492 component != domain_dict->keys().end(); | 438 component != domain_dict->keys().end(); |
| 493 ++component) { | 439 ++component) { |
| 494 // Load the schema. | 440 const PolicyNamespace policy_namespace(domain, component->first); |
| 495 const base::DictionaryValue* schema_dict = NULL; | 441 |
| 496 scoped_ptr<base::Value> schema; | 442 Schema schema; |
| 497 std::string schema_json; | 443 const Schema* schema_from_map = schema_map()->GetSchema(policy_namespace); |
| 498 const base::Value* schema_value = component->second->GetValue(kKeySchema); | 444 if (schema_from_map) |
| 499 if (schema_value && schema_value->GetAsString(&schema_json)) { | 445 schema = *schema_from_map; |
| 500 schema.reset(base::JSONReader::Read(schema_json)); | 446 if (!schema.valid()) { |
| 501 if (!schema || !schema->GetAsDictionary(&schema_dict)) { | 447 // TODO(joaodasilva): the schema should come from the schema_map(), but |
| 502 LOG(WARNING) << "Failed to parse 3rd-part policy schema for " | 448 // the Legacy Browser Support extension was launched when this loader |
| 503 << domain << "/" << component->first; | 449 // used a schema embedded in the registry. Remove this for M35. |
| 450 // http://crbug.com/325349 |
| 451 std::string schema_json; |
| 452 const base::Value* value = component->second->GetValue(kKeySchema); |
| 453 if (value && value->GetAsString(&schema_json)) { |
| 454 std::string error; |
| 455 schema = Schema::ParseWithBackwardsCompatibility( |
| 456 schema_json, &error, true); |
| 457 if (!schema.valid()) { |
| 458 LOG(WARNING) << "Invalid schema in the registry for " |
| 459 << name << "/" << component->first << ": " << error; |
| 460 } |
| 504 } | 461 } |
| 505 } | 462 } |
| 506 | 463 |
| 507 // Parse policy. | 464 // Parse policy. |
| 508 for (size_t j = 0; j < arraysize(kLevels); j++) { | 465 for (size_t j = 0; j < arraysize(kLevels); j++) { |
| 509 const RegistryDict* policy_dict = | 466 const RegistryDict* policy_dict = |
| 510 component->second->GetKey(kLevels[j].path); | 467 component->second->GetKey(kLevels[j].path); |
| 511 if (!policy_dict) | 468 if (!policy_dict) |
| 512 continue; | 469 continue; |
| 513 | 470 |
| 514 PolicyMap policy; | 471 PolicyMap policy; |
| 515 ParsePolicy(policy_dict, kLevels[j].level, scope, schema_dict, &policy); | 472 ParsePolicy(policy_dict, kLevels[j].level, scope, schema, &policy); |
| 516 PolicyNamespace policy_namespace(domain, component->first); | |
| 517 bundle->Get(policy_namespace).MergeFrom(policy); | 473 bundle->Get(policy_namespace).MergeFrom(policy); |
| 518 } | 474 } |
| 519 } | 475 } |
| 520 } | 476 } |
| 521 } | 477 } |
| 522 | 478 |
| 523 void PolicyLoaderWin::SetupWatches() { | 479 void PolicyLoaderWin::SetupWatches() { |
| 524 DCHECK(is_initialized_); | 480 DCHECK(is_initialized_); |
| 525 if (!user_policy_watcher_failed_ && | 481 if (!user_policy_watcher_failed_ && |
| 526 !user_policy_watcher_.GetWatchedObject() && | 482 !user_policy_watcher_.GetWatchedObject() && |
| (...skipping 13 matching lines...) Expand all Loading... |
| 540 | 496 |
| 541 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { | 497 void PolicyLoaderWin::OnObjectSignaled(HANDLE object) { |
| 542 DCHECK(object == user_policy_changed_event_.handle() || | 498 DCHECK(object == user_policy_changed_event_.handle() || |
| 543 object == machine_policy_changed_event_.handle()) | 499 object == machine_policy_changed_event_.handle()) |
| 544 << "unexpected object signaled policy reload, obj = " | 500 << "unexpected object signaled policy reload, obj = " |
| 545 << std::showbase << std::hex << object; | 501 << std::showbase << std::hex << object; |
| 546 Reload(false); | 502 Reload(false); |
| 547 } | 503 } |
| 548 | 504 |
| 549 } // namespace policy | 505 } // namespace policy |
| OLD | NEW |