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
3 // found in the LICENSE file.
4
5 #include "components/policy/core/common/policy_loader_win.h"
6
7 #include <windows.h>
8 #include <userenv.h>
9
10 #include <algorithm>
11 #include <cstring>
12 #include <functional>
13 #include <iterator>
14 #include <vector>
15
16 #include "base/base_paths.h"
17 #include "base/callback.h"
18 #include "base/files/file_path.h"
19 #include "base/files/file_util.h"
20 #include "base/files/scoped_temp_dir.h"
21 #include "base/json/json_writer.h"
22 #include "base/path_service.h"
23 #include "base/process/process.h"
24 #include "base/strings/string16.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_util.h"
27 #include "base/strings/stringprintf.h"
28 #include "base/strings/utf_string_conversions.h"
29 #include "base/sys_byteorder.h"
30 #include "base/win/registry.h"
31 #include "base/win/win_util.h"
32 #include "components/policy/core/common/async_policy_provider.h"
33 #include "components/policy/core/common/configuration_policy_provider_test.h"
34 #include "components/policy/core/common/external_data_fetcher.h"
35 #include "components/policy/core/common/policy_bundle.h"
36 #include "components/policy/core/common/policy_map.h"
37 #include "components/policy/core/common/preg_parser_win.h"
38 #include "components/policy/core/common/schema_map.h"
39 #include "testing/gtest/include/gtest/gtest.h"
40
41 using base::UTF8ToUTF16;
42 using base::UTF16ToUTF8;
43 using base::win::RegKey;
44
45 namespace policy {
46
47 namespace {
48
49 // Constants for registry key names.
50 const wchar_t kPathSep[] = L"\\";
51 const wchar_t kThirdParty[] = L"3rdparty";
52 const wchar_t kMandatory[] = L"policy";
53 const wchar_t kRecommended[] = L"recommended";
54 const char kSchema[] = "schema";
55 const wchar_t kTestPolicyKey[] = L"chrome.policy.key";
56
57 // Installs |value| in the given registry |path| and |hive|, under the key
58 // |name|. Returns false on errors.
59 // Some of the possible Value types are stored after a conversion (e.g. doubles
60 // are stored as strings), and can only be retrieved if a corresponding schema
61 // is written.
InstallValue(const base::Value & value,HKEY hive,const base::string16 & path,const base::string16 & name)62 bool InstallValue(const base::Value& value,
63 HKEY hive,
64 const base::string16& path,
65 const base::string16& name) {
66 // KEY_ALL_ACCESS causes the ctor to create the key if it does not exist yet.
67 RegKey key(hive, path.c_str(), KEY_ALL_ACCESS);
68 EXPECT_TRUE(key.Valid());
69 switch (value.GetType()) {
70 case base::Value::TYPE_NULL:
71 return key.WriteValue(name.c_str(), L"") == ERROR_SUCCESS;
72
73 case base::Value::TYPE_BOOLEAN: {
74 bool bool_value;
75 if (!value.GetAsBoolean(&bool_value))
76 return false;
77 return key.WriteValue(name.c_str(), bool_value ? 1 : 0) == ERROR_SUCCESS;
78 }
79
80 case base::Value::TYPE_INTEGER: {
81 int int_value;
82 if (!value.GetAsInteger(&int_value))
83 return false;
84 return key.WriteValue(name.c_str(), int_value) == ERROR_SUCCESS;
85 }
86
87 case base::Value::TYPE_DOUBLE: {
88 double double_value;
89 if (!value.GetAsDouble(&double_value))
90 return false;
91 base::string16 str_value =
92 UTF8ToUTF16(base::DoubleToString(double_value));
93 return key.WriteValue(name.c_str(), str_value.c_str()) == ERROR_SUCCESS;
94 }
95
96 case base::Value::TYPE_STRING: {
97 base::string16 str_value;
98 if (!value.GetAsString(&str_value))
99 return false;
100 return key.WriteValue(name.c_str(), str_value.c_str()) == ERROR_SUCCESS;
101 }
102
103 case base::Value::TYPE_DICTIONARY: {
104 const base::DictionaryValue* sub_dict = NULL;
105 if (!value.GetAsDictionary(&sub_dict))
106 return false;
107 for (base::DictionaryValue::Iterator it(*sub_dict);
108 !it.IsAtEnd(); it.Advance()) {
109 if (!InstallValue(it.value(), hive, path + kPathSep + name,
110 UTF8ToUTF16(it.key()))) {
111 return false;
112 }
113 }
114 return true;
115 }
116
117 case base::Value::TYPE_LIST: {
118 const base::ListValue* list = NULL;
119 if (!value.GetAsList(&list))
120 return false;
121 for (size_t i = 0; i < list->GetSize(); ++i) {
122 const base::Value* item;
123 if (!list->Get(i, &item))
124 return false;
125 if (!InstallValue(*item, hive, path + kPathSep + name,
126 base::UintToString16(i + 1))) {
127 return false;
128 }
129 }
130 return true;
131 }
132
133 case base::Value::TYPE_BINARY:
134 return false;
135 }
136 NOTREACHED();
137 return false;
138 }
139
140 // This class provides sandboxing and mocking for the parts of the Windows
141 // Registry implementing Group Policy. It prepares two temporary sandbox keys,
142 // one for HKLM and one for HKCU. A test's calls to the registry are redirected
143 // by Windows to these sandboxes, allowing the tests to manipulate and access
144 // policy as if it were active, but without actually changing the parts of the
145 // Registry that are managed by Group Policy.
146 class ScopedGroupPolicyRegistrySandbox {
147 public:
148 ScopedGroupPolicyRegistrySandbox();
149 ~ScopedGroupPolicyRegistrySandbox();
150
151 private:
152 void ActivateOverrides();
153 void RemoveOverrides();
154
155 // Deletes the sandbox keys.
156 void DeleteKeys();
157
158 std::wstring key_name_;
159
160 // Keys are created for the lifetime of a test to contain
161 // the sandboxed HKCU and HKLM hives, respectively.
162 RegKey temp_hkcu_hive_key_;
163 RegKey temp_hklm_hive_key_;
164
165 DISALLOW_COPY_AND_ASSIGN(ScopedGroupPolicyRegistrySandbox);
166 };
167
168 // A test harness that feeds policy via the Chrome GPO registry subtree.
169 class RegistryTestHarness : public PolicyProviderTestHarness,
170 public AppliedGPOListProvider {
171 public:
172 RegistryTestHarness(HKEY hive, PolicyScope scope);
173 virtual ~RegistryTestHarness();
174
175 // PolicyProviderTestHarness:
176 virtual void SetUp() OVERRIDE;
177
178 virtual ConfigurationPolicyProvider* CreateProvider(
179 SchemaRegistry* registry,
180 scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE;
181
182 virtual void InstallEmptyPolicy() OVERRIDE;
183 virtual void InstallStringPolicy(const std::string& policy_name,
184 const std::string& policy_value) OVERRIDE;
185 virtual void InstallIntegerPolicy(const std::string& policy_name,
186 int policy_value) OVERRIDE;
187 virtual void InstallBooleanPolicy(const std::string& policy_name,
188 bool policy_value) OVERRIDE;
189 virtual void InstallStringListPolicy(
190 const std::string& policy_name,
191 const base::ListValue* policy_value) OVERRIDE;
192 virtual void InstallDictionaryPolicy(
193 const std::string& policy_name,
194 const base::DictionaryValue* policy_value) OVERRIDE;
195 virtual void Install3rdPartyPolicy(
196 const base::DictionaryValue* policies) OVERRIDE;
197
198 // AppliedGPOListProvider:
199 virtual DWORD GetAppliedGPOList(DWORD flags,
200 LPCTSTR machine_name,
201 PSID sid_user,
202 GUID* extension_guid,
203 PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE;
204 virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE;
205
206 // Creates a harness instance that will install policy in HKCU or HKLM,
207 // respectively.
208 static PolicyProviderTestHarness* CreateHKCU();
209 static PolicyProviderTestHarness* CreateHKLM();
210
211 private:
212 HKEY hive_;
213
214 ScopedGroupPolicyRegistrySandbox registry_sandbox_;
215
216 DISALLOW_COPY_AND_ASSIGN(RegistryTestHarness);
217 };
218
219 // A test harness that generates PReg files for the provider to read.
220 class PRegTestHarness : public PolicyProviderTestHarness,
221 public AppliedGPOListProvider {
222 public:
223 PRegTestHarness();
224 virtual ~PRegTestHarness();
225
226 // PolicyProviderTestHarness:
227 virtual void SetUp() OVERRIDE;
228
229 virtual ConfigurationPolicyProvider* CreateProvider(
230 SchemaRegistry* registry,
231 scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE;
232
233 virtual void InstallEmptyPolicy() OVERRIDE;
234 virtual void InstallStringPolicy(const std::string& policy_name,
235 const std::string& policy_value) OVERRIDE;
236 virtual void InstallIntegerPolicy(const std::string& policy_name,
237 int policy_value) OVERRIDE;
238 virtual void InstallBooleanPolicy(const std::string& policy_name,
239 bool policy_value) OVERRIDE;
240 virtual void InstallStringListPolicy(
241 const std::string& policy_name,
242 const base::ListValue* policy_value) OVERRIDE;
243 virtual void InstallDictionaryPolicy(
244 const std::string& policy_name,
245 const base::DictionaryValue* policy_value) OVERRIDE;
246 virtual void Install3rdPartyPolicy(
247 const base::DictionaryValue* policies) OVERRIDE;
248
249 // AppliedGPOListProvider:
250 virtual DWORD GetAppliedGPOList(DWORD flags,
251 LPCTSTR machine_name,
252 PSID sid_user,
253 GUID* extension_guid,
254 PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE;
255 virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE;
256
257 // Creates a harness instance.
258 static PolicyProviderTestHarness* Create();
259
260 private:
261 // Helper to append a base::string16 to an uint8 buffer.
262 static void AppendChars(std::vector<uint8>* buffer,
263 const base::string16& chars);
264
265 // Appends a record with the given fields to the PReg file.
266 void AppendRecordToPRegFile(const base::string16& path,
267 const std::string& key,
268 DWORD type,
269 DWORD size,
270 uint8* data);
271
272 // Appends the given DWORD |value| for |path| + |key| to the PReg file.
273 void AppendDWORDToPRegFile(const base::string16& path,
274 const std::string& key,
275 DWORD value);
276
277 // Appends the given string |value| for |path| + |key| to the PReg file.
278 void AppendStringToPRegFile(const base::string16& path,
279 const std::string& key,
280 const std::string& value);
281
282 // Appends the given policy |value| for |path| + |key| to the PReg file,
283 // converting and recursing as necessary.
284 void AppendPolicyToPRegFile(const base::string16& path,
285 const std::string& key,
286 const base::Value* value);
287
288 base::ScopedTempDir temp_dir_;
289 base::FilePath preg_file_path_;
290 GROUP_POLICY_OBJECT gpo_;
291
292 DISALLOW_COPY_AND_ASSIGN(PRegTestHarness);
293 };
294
ScopedGroupPolicyRegistrySandbox()295 ScopedGroupPolicyRegistrySandbox::ScopedGroupPolicyRegistrySandbox() {
296 // Generate a unique registry key for the override for each test. This
297 // makes sure that tests executing in parallel won't delete each other's
298 // key, at DeleteKeys().
299 key_name_ = base::ASCIIToWide(base::StringPrintf(
300 "SOFTWARE\\chromium unittest %d",
301 base::Process::Current().pid()));
302 std::wstring hklm_key_name = key_name_ + L"\\HKLM";
303 std::wstring hkcu_key_name = key_name_ + L"\\HKCU";
304
305 // Create the subkeys to hold the overridden HKLM and HKCU
306 // policy settings.
307 temp_hklm_hive_key_.Create(HKEY_CURRENT_USER,
308 hklm_key_name.c_str(),
309 KEY_ALL_ACCESS);
310 temp_hkcu_hive_key_.Create(HKEY_CURRENT_USER,
311 hkcu_key_name.c_str(),
312 KEY_ALL_ACCESS);
313
314 ActivateOverrides();
315 }
316
~ScopedGroupPolicyRegistrySandbox()317 ScopedGroupPolicyRegistrySandbox::~ScopedGroupPolicyRegistrySandbox() {
318 RemoveOverrides();
319 DeleteKeys();
320 }
321
ActivateOverrides()322 void ScopedGroupPolicyRegistrySandbox::ActivateOverrides() {
323 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE,
324 temp_hklm_hive_key_.Handle()));
325 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER,
326 temp_hkcu_hive_key_.Handle()));
327 }
328
RemoveOverrides()329 void ScopedGroupPolicyRegistrySandbox::RemoveOverrides() {
330 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE, 0));
331 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER, 0));
332 }
333
DeleteKeys()334 void ScopedGroupPolicyRegistrySandbox::DeleteKeys() {
335 RegKey key(HKEY_CURRENT_USER, key_name_.c_str(), KEY_ALL_ACCESS);
336 ASSERT_TRUE(key.Valid());
337 key.DeleteKey(L"");
338 }
339
RegistryTestHarness(HKEY hive,PolicyScope scope)340 RegistryTestHarness::RegistryTestHarness(HKEY hive, PolicyScope scope)
341 : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, scope), hive_(hive) {}
342
~RegistryTestHarness()343 RegistryTestHarness::~RegistryTestHarness() {}
344
SetUp()345 void RegistryTestHarness::SetUp() {}
346
CreateProvider(SchemaRegistry * registry,scoped_refptr<base::SequencedTaskRunner> task_runner)347 ConfigurationPolicyProvider* RegistryTestHarness::CreateProvider(
348 SchemaRegistry* registry,
349 scoped_refptr<base::SequencedTaskRunner> task_runner) {
350 base::win::SetDomainStateForTesting(true);
351 scoped_ptr<AsyncPolicyLoader> loader(
352 new PolicyLoaderWin(task_runner, kTestPolicyKey, this));
353 return new AsyncPolicyProvider(registry, loader.Pass());
354 }
355
InstallEmptyPolicy()356 void RegistryTestHarness::InstallEmptyPolicy() {}
357
InstallStringPolicy(const std::string & policy_name,const std::string & policy_value)358 void RegistryTestHarness::InstallStringPolicy(
359 const std::string& policy_name,
360 const std::string& policy_value) {
361 RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS);
362 ASSERT_TRUE(key.Valid());
363 ASSERT_HRESULT_SUCCEEDED(key.WriteValue(UTF8ToUTF16(policy_name).c_str(),
364 UTF8ToUTF16(policy_value).c_str()));
365 }
366
InstallIntegerPolicy(const std::string & policy_name,int policy_value)367 void RegistryTestHarness::InstallIntegerPolicy(
368 const std::string& policy_name,
369 int policy_value) {
370 RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS);
371 ASSERT_TRUE(key.Valid());
372 key.WriteValue(UTF8ToUTF16(policy_name).c_str(),
373 static_cast<DWORD>(policy_value));
374 }
375
InstallBooleanPolicy(const std::string & policy_name,bool policy_value)376 void RegistryTestHarness::InstallBooleanPolicy(
377 const std::string& policy_name,
378 bool policy_value) {
379 RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS);
380 ASSERT_TRUE(key.Valid());
381 key.WriteValue(UTF8ToUTF16(policy_name).c_str(),
382 static_cast<DWORD>(policy_value));
383 }
384
InstallStringListPolicy(const std::string & policy_name,const base::ListValue * policy_value)385 void RegistryTestHarness::InstallStringListPolicy(
386 const std::string& policy_name,
387 const base::ListValue* policy_value) {
388 RegKey key(hive_,
389 (base::string16(kTestPolicyKey) + base::ASCIIToUTF16("\\") +
390 UTF8ToUTF16(policy_name)).c_str(),
391 KEY_ALL_ACCESS);
392 ASSERT_TRUE(key.Valid());
393 int index = 1;
394 for (base::ListValue::const_iterator element(policy_value->begin());
395 element != policy_value->end();
396 ++element) {
397 std::string element_value;
398 if (!(*element)->GetAsString(&element_value))
399 continue;
400 std::string name(base::IntToString(index++));
401 key.WriteValue(UTF8ToUTF16(name).c_str(),
402 UTF8ToUTF16(element_value).c_str());
403 }
404 }
405
InstallDictionaryPolicy(const std::string & policy_name,const base::DictionaryValue * policy_value)406 void RegistryTestHarness::InstallDictionaryPolicy(
407 const std::string& policy_name,
408 const base::DictionaryValue* policy_value) {
409 std::string json;
410 base::JSONWriter::Write(policy_value, &json);
411 RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS);
412 ASSERT_TRUE(key.Valid());
413 key.WriteValue(UTF8ToUTF16(policy_name).c_str(),
414 UTF8ToUTF16(json).c_str());
415 }
416
Install3rdPartyPolicy(const base::DictionaryValue * policies)417 void RegistryTestHarness::Install3rdPartyPolicy(
418 const base::DictionaryValue* policies) {
419 // The first level entries are domains, and the second level entries map
420 // components to their policy.
421 const base::string16 kPathPrefix =
422 base::string16(kTestPolicyKey) + kPathSep + kThirdParty + kPathSep;
423 for (base::DictionaryValue::Iterator domain(*policies);
424 !domain.IsAtEnd(); domain.Advance()) {
425 const base::DictionaryValue* components = NULL;
426 if (!domain.value().GetAsDictionary(&components)) {
427 ADD_FAILURE();
428 continue;
429 }
430 for (base::DictionaryValue::Iterator component(*components);
431 !component.IsAtEnd(); component.Advance()) {
432 const base::string16 path = kPathPrefix +
433 UTF8ToUTF16(domain.key()) + kPathSep + UTF8ToUTF16(component.key());
434 InstallValue(component.value(), hive_, path, kMandatory);
435 }
436 }
437 }
438
GetAppliedGPOList(DWORD flags,LPCTSTR machine_name,PSID sid_user,GUID * extension_guid,PGROUP_POLICY_OBJECT * gpo_list)439 DWORD RegistryTestHarness::GetAppliedGPOList(DWORD flags,
440 LPCTSTR machine_name,
441 PSID sid_user,
442 GUID* extension_guid,
443 PGROUP_POLICY_OBJECT* gpo_list) {
444 *gpo_list = NULL;
445 return ERROR_ACCESS_DENIED;
446 }
447
FreeGPOList(PGROUP_POLICY_OBJECT gpo_list)448 BOOL RegistryTestHarness::FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) {
449 return TRUE;
450 }
451
452 // static
CreateHKCU()453 PolicyProviderTestHarness* RegistryTestHarness::CreateHKCU() {
454 return new RegistryTestHarness(HKEY_CURRENT_USER, POLICY_SCOPE_USER);
455 }
456
457 // static
CreateHKLM()458 PolicyProviderTestHarness* RegistryTestHarness::CreateHKLM() {
459 return new RegistryTestHarness(HKEY_LOCAL_MACHINE, POLICY_SCOPE_MACHINE);
460 }
461
PRegTestHarness()462 PRegTestHarness::PRegTestHarness()
463 : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE) {}
464
~PRegTestHarness()465 PRegTestHarness::~PRegTestHarness() {}
466
SetUp()467 void PRegTestHarness::SetUp() {
468 base::win::SetDomainStateForTesting(false);
469 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
470 preg_file_path_ = temp_dir_.path().Append(PolicyLoaderWin::kPRegFileName);
471 ASSERT_TRUE(base::WriteFile(preg_file_path_,
472 preg_parser::kPRegFileHeader,
473 arraysize(preg_parser::kPRegFileHeader)));
474
475 memset(&gpo_, 0, sizeof(GROUP_POLICY_OBJECT));
476 gpo_.lpFileSysPath = const_cast<wchar_t*>(temp_dir_.path().value().c_str());
477 }
478
CreateProvider(SchemaRegistry * registry,scoped_refptr<base::SequencedTaskRunner> task_runner)479 ConfigurationPolicyProvider* PRegTestHarness::CreateProvider(
480 SchemaRegistry* registry,
481 scoped_refptr<base::SequencedTaskRunner> task_runner) {
482 scoped_ptr<AsyncPolicyLoader> loader(
483 new PolicyLoaderWin(task_runner, kTestPolicyKey, this));
484 return new AsyncPolicyProvider(registry, loader.Pass());
485 }
486
InstallEmptyPolicy()487 void PRegTestHarness::InstallEmptyPolicy() {}
488
InstallStringPolicy(const std::string & policy_name,const std::string & policy_value)489 void PRegTestHarness::InstallStringPolicy(const std::string& policy_name,
490 const std::string& policy_value) {
491 AppendStringToPRegFile(kTestPolicyKey, policy_name, policy_value);
492 }
493
InstallIntegerPolicy(const std::string & policy_name,int policy_value)494 void PRegTestHarness::InstallIntegerPolicy(const std::string& policy_name,
495 int policy_value) {
496 AppendDWORDToPRegFile(kTestPolicyKey, policy_name, policy_value);
497 }
498
InstallBooleanPolicy(const std::string & policy_name,bool policy_value)499 void PRegTestHarness::InstallBooleanPolicy(const std::string& policy_name,
500 bool policy_value) {
501 AppendDWORDToPRegFile(kTestPolicyKey, policy_name, policy_value);
502 }
503
InstallStringListPolicy(const std::string & policy_name,const base::ListValue * policy_value)504 void PRegTestHarness::InstallStringListPolicy(
505 const std::string& policy_name,
506 const base::ListValue* policy_value) {
507 AppendPolicyToPRegFile(kTestPolicyKey, policy_name, policy_value);
508 }
509
InstallDictionaryPolicy(const std::string & policy_name,const base::DictionaryValue * policy_value)510 void PRegTestHarness::InstallDictionaryPolicy(
511 const std::string& policy_name,
512 const base::DictionaryValue* policy_value) {
513 std::string json;
514 base::JSONWriter::Write(policy_value, &json);
515 AppendStringToPRegFile(kTestPolicyKey, policy_name, json);
516 }
517
Install3rdPartyPolicy(const base::DictionaryValue * policies)518 void PRegTestHarness::Install3rdPartyPolicy(
519 const base::DictionaryValue* policies) {
520 // The first level entries are domains, and the second level entries map
521 // components to their policy.
522 const base::string16 kPathPrefix =
523 base::string16(kTestPolicyKey) + kPathSep + kThirdParty + kPathSep;
524 for (base::DictionaryValue::Iterator domain(*policies);
525 !domain.IsAtEnd(); domain.Advance()) {
526 const base::DictionaryValue* components = NULL;
527 if (!domain.value().GetAsDictionary(&components)) {
528 ADD_FAILURE();
529 continue;
530 }
531 const base::string16 domain_path = kPathPrefix + UTF8ToUTF16(domain.key());
532 for (base::DictionaryValue::Iterator component(*components);
533 !component.IsAtEnd(); component.Advance()) {
534 const base::string16 component_path =
535 domain_path + kPathSep + UTF8ToUTF16(component.key());
536 AppendPolicyToPRegFile(component_path, UTF16ToUTF8(kMandatory),
537 &component.value());
538 }
539 }
540 }
541
GetAppliedGPOList(DWORD flags,LPCTSTR machine_name,PSID sid_user,GUID * extension_guid,PGROUP_POLICY_OBJECT * gpo_list)542 DWORD PRegTestHarness::GetAppliedGPOList(DWORD flags,
543 LPCTSTR machine_name,
544 PSID sid_user,
545 GUID* extension_guid,
546 PGROUP_POLICY_OBJECT* gpo_list) {
547 *gpo_list = flags & GPO_LIST_FLAG_MACHINE ? &gpo_ : NULL;
548 return ERROR_SUCCESS;
549 }
550
FreeGPOList(PGROUP_POLICY_OBJECT gpo_list)551 BOOL PRegTestHarness::FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) {
552 return TRUE;
553 }
554
555 // static
Create()556 PolicyProviderTestHarness* PRegTestHarness::Create() {
557 return new PRegTestHarness();
558 }
559
560 // static
AppendChars(std::vector<uint8> * buffer,const base::string16 & chars)561 void PRegTestHarness::AppendChars(std::vector<uint8>* buffer,
562 const base::string16& chars) {
563 for (base::string16::const_iterator c(chars.begin()); c != chars.end(); ++c) {
564 buffer->push_back(*c & 0xff);
565 buffer->push_back((*c >> 8) & 0xff);
566 }
567 }
568
AppendRecordToPRegFile(const base::string16 & path,const std::string & key,DWORD type,DWORD size,uint8 * data)569 void PRegTestHarness::AppendRecordToPRegFile(const base::string16& path,
570 const std::string& key,
571 DWORD type,
572 DWORD size,
573 uint8* data) {
574 std::vector<uint8> buffer;
575 AppendChars(&buffer, L"[");
576 AppendChars(&buffer, path);
577 AppendChars(&buffer, base::string16(L"\0;", 2));
578 AppendChars(&buffer, UTF8ToUTF16(key));
579 AppendChars(&buffer, base::string16(L"\0;", 2));
580 type = base::ByteSwapToLE32(type);
581 uint8* type_data = reinterpret_cast<uint8*>(&type);
582 buffer.insert(buffer.end(), type_data, type_data + sizeof(DWORD));
583 AppendChars(&buffer, L";");
584 size = base::ByteSwapToLE32(size);
585 uint8* size_data = reinterpret_cast<uint8*>(&size);
586 buffer.insert(buffer.end(), size_data, size_data + sizeof(DWORD));
587 AppendChars(&buffer, L";");
588 buffer.insert(buffer.end(), data, data + size);
589 AppendChars(&buffer, L"]");
590
591 ASSERT_EQ(buffer.size(),
592 base::AppendToFile(
593 preg_file_path_,
594 reinterpret_cast<const char*>(vector_as_array(&buffer)),
595 buffer.size()));
596 }
597
AppendDWORDToPRegFile(const base::string16 & path,const std::string & key,DWORD value)598 void PRegTestHarness::AppendDWORDToPRegFile(const base::string16& path,
599 const std::string& key,
600 DWORD value) {
601 value = base::ByteSwapToLE32(value);
602 AppendRecordToPRegFile(path, key, REG_DWORD, sizeof(DWORD),
603 reinterpret_cast<uint8*>(&value));
604 }
605
AppendStringToPRegFile(const base::string16 & path,const std::string & key,const std::string & value)606 void PRegTestHarness::AppendStringToPRegFile(const base::string16& path,
607 const std::string& key,
608 const std::string& value) {
609 base::string16 string16_value(UTF8ToUTF16(value));
610 std::vector<base::char16> data;
611 std::transform(string16_value.begin(), string16_value.end(),
612 std::back_inserter(data), std::ptr_fun(base::ByteSwapToLE16));
613 data.push_back(base::ByteSwapToLE16(L'\0'));
614
615 AppendRecordToPRegFile(path, key, REG_SZ, data.size() * sizeof(base::char16),
616 reinterpret_cast<uint8*>(vector_as_array(&data)));
617 }
618
AppendPolicyToPRegFile(const base::string16 & path,const std::string & key,const base::Value * value)619 void PRegTestHarness::AppendPolicyToPRegFile(const base::string16& path,
620 const std::string& key,
621 const base::Value* value) {
622 switch (value->GetType()) {
623 case base::Value::TYPE_BOOLEAN: {
624 bool boolean_value = false;
625 ASSERT_TRUE(value->GetAsBoolean(&boolean_value));
626 AppendDWORDToPRegFile(path, key, boolean_value);
627 break;
628 }
629 case base::Value::TYPE_INTEGER: {
630 int int_value = 0;
631 ASSERT_TRUE(value->GetAsInteger(&int_value));
632 AppendDWORDToPRegFile(path, key, int_value);
633 break;
634 }
635 case base::Value::TYPE_DOUBLE: {
636 double double_value = 0;
637 ASSERT_TRUE(value->GetAsDouble(&double_value));
638 AppendStringToPRegFile(path, key, base::DoubleToString(double_value));
639 break;
640 }
641 case base::Value::TYPE_STRING: {
642 std::string string_value;
643 ASSERT_TRUE(value->GetAsString(&string_value));
644 AppendStringToPRegFile(path, key, string_value);
645 break;
646 }
647 case base::Value::TYPE_DICTIONARY: {
648 base::string16 subpath = path + kPathSep + UTF8ToUTF16(key);
649 const base::DictionaryValue* dict = NULL;
650 ASSERT_TRUE(value->GetAsDictionary(&dict));
651 for (base::DictionaryValue::Iterator entry(*dict); !entry.IsAtEnd();
652 entry.Advance()) {
653 AppendPolicyToPRegFile(subpath, entry.key(), &entry.value());
654 }
655 break;
656 }
657 case base::Value::TYPE_LIST: {
658 base::string16 subpath = path + kPathSep + UTF8ToUTF16(key);
659 const base::ListValue* list = NULL;
660 ASSERT_TRUE(value->GetAsList(&list));
661 for (size_t i = 0; i < list->GetSize(); ++i) {
662 const base::Value* entry = NULL;
663 ASSERT_TRUE(list->Get(i, &entry));
664 AppendPolicyToPRegFile(subpath, base::IntToString(i + 1), entry);
665 }
666 break;
667 }
668 case base::Value::TYPE_BINARY:
669 case base::Value::TYPE_NULL: {
670 ADD_FAILURE();
671 break;
672 }
673 }
674 }
675
676 } // namespace
677
678 // Instantiate abstract test case for basic policy reading tests.
679 INSTANTIATE_TEST_CASE_P(
680 PolicyProviderWinTest,
681 ConfigurationPolicyProviderTest,
682 testing::Values(RegistryTestHarness::CreateHKCU,
683 RegistryTestHarness::CreateHKLM,
684 PRegTestHarness::Create));
685
686 // Instantiate abstract test case for 3rd party policy reading tests.
687 INSTANTIATE_TEST_CASE_P(
688 ThirdPartyPolicyProviderWinTest,
689 Configuration3rdPartyPolicyProviderTest,
690 testing::Values(RegistryTestHarness::CreateHKCU,
691 RegistryTestHarness::CreateHKLM,
692 PRegTestHarness::Create));
693
694 // Test cases for windows policy provider specific functionality.
695 class PolicyLoaderWinTest : public PolicyTestBase,
696 public AppliedGPOListProvider {
697 protected:
698 // The policy key this tests places data under. This must match the data
699 // files in chrome/test/data/policy/gpo.
700 static const base::char16 kTestPolicyKey[];
701
PolicyLoaderWinTest()702 PolicyLoaderWinTest()
703 : gpo_list_(NULL),
704 gpo_list_status_(ERROR_ACCESS_DENIED) {}
~PolicyLoaderWinTest()705 virtual ~PolicyLoaderWinTest() {}
706
SetUp()707 virtual void SetUp() OVERRIDE {
708 base::win::SetDomainStateForTesting(false);
709 PolicyTestBase::SetUp();
710
711 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir_));
712 test_data_dir_ = test_data_dir_.AppendASCII("chrome")
713 .AppendASCII("test")
714 .AppendASCII("data")
715 .AppendASCII("policy")
716 .AppendASCII("gpo");
717 }
718
719 // AppliedGPOListProvider:
GetAppliedGPOList(DWORD flags,LPCTSTR machine_name,PSID sid_user,GUID * extension_guid,PGROUP_POLICY_OBJECT * gpo_list)720 virtual DWORD GetAppliedGPOList(DWORD flags,
721 LPCTSTR machine_name,
722 PSID sid_user,
723 GUID* extension_guid,
724 PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE {
725 *gpo_list = gpo_list_;
726 return gpo_list_status_;
727 }
FreeGPOList(PGROUP_POLICY_OBJECT gpo_list)728 virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE {
729 return TRUE;
730 }
731
InitGPO(GROUP_POLICY_OBJECT * gpo,DWORD options,const base::FilePath & path,GROUP_POLICY_OBJECT * next,GROUP_POLICY_OBJECT * prev)732 void InitGPO(GROUP_POLICY_OBJECT* gpo,
733 DWORD options,
734 const base::FilePath& path,
735 GROUP_POLICY_OBJECT* next,
736 GROUP_POLICY_OBJECT* prev) {
737 memset(gpo, 0, sizeof(GROUP_POLICY_OBJECT));
738 gpo->dwOptions = options;
739 gpo->lpFileSysPath = const_cast<wchar_t*>(path.value().c_str());
740 gpo->pNext = next;
741 gpo->pPrev = prev;
742 }
743
Matches(const PolicyBundle & expected)744 bool Matches(const PolicyBundle& expected) {
745 PolicyLoaderWin loader(loop_.message_loop_proxy(), kTestPolicyKey, this);
746 scoped_ptr<PolicyBundle> loaded(
747 loader.InitialLoad(schema_registry_.schema_map()));
748 return loaded->Equals(expected);
749 }
750
InstallRegistrySentinel()751 void InstallRegistrySentinel() {
752 RegKey hklm_key(HKEY_CURRENT_USER, kTestPolicyKey, KEY_ALL_ACCESS);
753 ASSERT_TRUE(hklm_key.Valid());
754 hklm_key.WriteValue(
755 UTF8ToUTF16(test_keys::kKeyString).c_str(),
756 UTF8ToUTF16("registry").c_str());
757 }
758
MatchesRegistrySentinel()759 bool MatchesRegistrySentinel() {
760 base::DictionaryValue expected_policy;
761 expected_policy.SetString(test_keys::kKeyString, "registry");
762 PolicyBundle expected;
763 expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
764 .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
765 return Matches(expected);
766 }
767
MatchesTestBundle()768 bool MatchesTestBundle() {
769 base::DictionaryValue expected_policy;
770 expected_policy.SetBoolean(test_keys::kKeyBoolean, true);
771 expected_policy.SetString(test_keys::kKeyString, "GPO");
772 expected_policy.SetInteger(test_keys::kKeyInteger, 42);
773 scoped_ptr<base::ListValue> list(new base::ListValue());
774 list->AppendString("GPO 1");
775 list->AppendString("GPO 2");
776 expected_policy.Set(test_keys::kKeyStringList, list.release());
777 PolicyBundle expected;
778 expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
779 .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY,
780 POLICY_SCOPE_MACHINE);
781 return Matches(expected);
782 }
783
784 ScopedGroupPolicyRegistrySandbox registry_sandbox_;
785 PGROUP_POLICY_OBJECT gpo_list_;
786 DWORD gpo_list_status_;
787 base::FilePath test_data_dir_;
788 };
789
790 const base::char16 PolicyLoaderWinTest::kTestPolicyKey[] =
791 L"SOFTWARE\\Policies\\Chromium";
792
TEST_F(PolicyLoaderWinTest,HKLMOverHKCU)793 TEST_F(PolicyLoaderWinTest, HKLMOverHKCU) {
794 RegKey hklm_key(HKEY_LOCAL_MACHINE, kTestPolicyKey, KEY_ALL_ACCESS);
795 ASSERT_TRUE(hklm_key.Valid());
796 hklm_key.WriteValue(UTF8ToUTF16(test_keys::kKeyString).c_str(),
797 UTF8ToUTF16("hklm").c_str());
798 RegKey hkcu_key(HKEY_CURRENT_USER, kTestPolicyKey, KEY_ALL_ACCESS);
799 ASSERT_TRUE(hkcu_key.Valid());
800 hkcu_key.WriteValue(UTF8ToUTF16(test_keys::kKeyString).c_str(),
801 UTF8ToUTF16("hkcu").c_str());
802
803 PolicyBundle expected;
804 expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
805 .Set(test_keys::kKeyString,
806 POLICY_LEVEL_MANDATORY,
807 POLICY_SCOPE_MACHINE,
808 new base::StringValue("hklm"),
809 NULL);
810 EXPECT_TRUE(Matches(expected));
811 }
812
TEST_F(PolicyLoaderWinTest,Merge3rdPartyPolicies)813 TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) {
814 // Policy for the same extension will be provided at the 4 level/scope
815 // combinations, to verify that they overlap as expected.
816 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "merge");
817 ASSERT_TRUE(RegisterSchema(
818 ns,
819 "{"
820 " \"type\": \"object\","
821 " \"properties\": {"
822 " \"a\": { \"type\": \"string\" },"
823 " \"b\": { \"type\": \"string\" },"
824 " \"c\": { \"type\": \"string\" },"
825 " \"d\": { \"type\": \"string\" }"
826 " }"
827 "}"));
828
829 const base::string16 kPathSuffix =
830 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\merge");
831
832 const char kUserMandatory[] = "user-mandatory";
833 const char kUserRecommended[] = "user-recommended";
834 const char kMachineMandatory[] = "machine-mandatory";
835 const char kMachineRecommended[] = "machine-recommended";
836
837 base::DictionaryValue policy;
838 policy.SetString("a", kMachineMandatory);
839 EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE,
840 kPathSuffix, kMandatory));
841 policy.SetString("a", kUserMandatory);
842 policy.SetString("b", kUserMandatory);
843 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER,
844 kPathSuffix, kMandatory));
845 policy.SetString("a", kMachineRecommended);
846 policy.SetString("b", kMachineRecommended);
847 policy.SetString("c", kMachineRecommended);
848 EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE,
849 kPathSuffix, kRecommended));
850 policy.SetString("a", kUserRecommended);
851 policy.SetString("b", kUserRecommended);
852 policy.SetString("c", kUserRecommended);
853 policy.SetString("d", kUserRecommended);
854 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER,
855 kPathSuffix, kRecommended));
856
857 PolicyBundle expected;
858 PolicyMap& expected_policy = expected.Get(ns);
859 expected_policy.Set("a",
860 POLICY_LEVEL_MANDATORY,
861 POLICY_SCOPE_MACHINE,
862 new base::StringValue(kMachineMandatory),
863 NULL);
864 expected_policy.Set("b",
865 POLICY_LEVEL_MANDATORY,
866 POLICY_SCOPE_USER,
867 new base::StringValue(kUserMandatory),
868 NULL);
869 expected_policy.Set("c",
870 POLICY_LEVEL_RECOMMENDED,
871 POLICY_SCOPE_MACHINE,
872 new base::StringValue(kMachineRecommended),
873 NULL);
874 expected_policy.Set("d",
875 POLICY_LEVEL_RECOMMENDED,
876 POLICY_SCOPE_USER,
877 new base::StringValue(kUserRecommended),
878 NULL);
879 EXPECT_TRUE(Matches(expected));
880 }
881
TEST_F(PolicyLoaderWinTest,LoadStringEncodedValues)882 TEST_F(PolicyLoaderWinTest, LoadStringEncodedValues) {
883 // Create a dictionary with all the types that can be stored encoded in a
884 // string.
885 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "string");
886 ASSERT_TRUE(RegisterSchema(
887 ns,
888 "{"
889 " \"type\": \"object\","
890 " \"id\": \"MainType\","
891 " \"properties\": {"
892 " \"null\": { \"type\": \"null\" },"
893 " \"bool\": { \"type\": \"boolean\" },"
894 " \"int\": { \"type\": \"integer\" },"
895 " \"double\": { \"type\": \"number\" },"
896 " \"list\": {"
897 " \"type\": \"array\","
898 " \"items\": { \"$ref\": \"MainType\" }"
899 " },"
900 " \"dict\": { \"$ref\": \"MainType\" }"
901 " }"
902 "}"));
903
904 base::DictionaryValue policy;
905 policy.Set("null", base::Value::CreateNullValue());
906 policy.SetBoolean("bool", true);
907 policy.SetInteger("int", -123);
908 policy.SetDouble("double", 456.78e9);
909 base::ListValue list;
910 list.Append(policy.DeepCopy());
911 list.Append(policy.DeepCopy());
912 policy.Set("list", list.DeepCopy());
913 // Encode |policy| before adding the "dict" entry.
914 std::string encoded_dict;
915 base::JSONWriter::Write(&policy, &encoded_dict);
916 ASSERT_FALSE(encoded_dict.empty());
917 policy.Set("dict", policy.DeepCopy());
918 std::string encoded_list;
919 base::JSONWriter::Write(&list, &encoded_list);
920 ASSERT_FALSE(encoded_list.empty());
921 base::DictionaryValue encoded_policy;
922 encoded_policy.SetString("null", "");
923 encoded_policy.SetString("bool", "1");
924 encoded_policy.SetString("int", "-123");
925 encoded_policy.SetString("double", "456.78e9");
926 encoded_policy.SetString("list", encoded_list);
927 encoded_policy.SetString("dict", encoded_dict);
928
929 const base::string16 kPathSuffix =
930 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\string");
931 EXPECT_TRUE(
932 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory));
933
934 PolicyBundle expected;
935 expected.Get(ns).LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
936 EXPECT_TRUE(Matches(expected));
937 }
938
TEST_F(PolicyLoaderWinTest,LoadIntegerEncodedValues)939 TEST_F(PolicyLoaderWinTest, LoadIntegerEncodedValues) {
940 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "int");
941 ASSERT_TRUE(RegisterSchema(
942 ns,
943 "{"
944 " \"type\": \"object\","
945 " \"properties\": {"
946 " \"bool\": { \"type\": \"boolean\" },"
947 " \"int\": { \"type\": \"integer\" },"
948 " \"double\": { \"type\": \"number\" }"
949 " }"
950 "}"));
951
952 base::DictionaryValue encoded_policy;
953 encoded_policy.SetInteger("bool", 1);
954 encoded_policy.SetInteger("int", 123);
955 encoded_policy.SetInteger("double", 456);
956
957 const base::string16 kPathSuffix =
958 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\int");
959 EXPECT_TRUE(
960 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory));
961
962 base::DictionaryValue policy;
963 policy.SetBoolean("bool", true);
964 policy.SetInteger("int", 123);
965 policy.SetDouble("double", 456.0);
966 PolicyBundle expected;
967 expected.Get(ns).LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
968 EXPECT_TRUE(Matches(expected));
969 }
970
TEST_F(PolicyLoaderWinTest,DefaultPropertySchemaType)971 TEST_F(PolicyLoaderWinTest, DefaultPropertySchemaType) {
972 // Build a schema for an "object" with a default schema for its properties.
973 // Note that the top-level object can't have "additionalProperties", so
974 // a "policy" property is used instead.
975 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "test");
976 ASSERT_TRUE(RegisterSchema(
977 ns,
978 "{"
979 " \"type\": \"object\","
980 " \"properties\": {"
981 " \"policy\": {"
982 " \"type\": \"object\","
983 " \"properties\": {"
984 " \"special-int1\": { \"type\": \"integer\" },"
985 " \"special-int2\": { \"type\": \"integer\" }"
986 " },"
987 " \"additionalProperties\": { \"type\": \"number\" }"
988 " }"
989 " }"
990 "}"));
991
992 // Write some test values.
993 base::DictionaryValue policy;
994 // These special values have a specific schema for them.
995 policy.SetInteger("special-int1", 123);
996 policy.SetString("special-int2", "-456");
997 // Other values default to be loaded as doubles.
998 policy.SetInteger("double1", 789.0);
999 policy.SetString("double2", "123.456e7");
1000 policy.SetString("invalid", "omg");
1001 base::DictionaryValue all_policies;
1002 all_policies.Set("policy", policy.DeepCopy());
1003
1004 const base::string16 kPathSuffix =
1005 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\test");
1006 EXPECT_TRUE(
1007 InstallValue(all_policies, HKEY_CURRENT_USER, kPathSuffix, kMandatory));
1008
1009 base::DictionaryValue expected_policy;
1010 expected_policy.SetInteger("special-int1", 123);
1011 expected_policy.SetInteger("special-int2", -456);
1012 expected_policy.SetDouble("double1", 789.0);
1013 expected_policy.SetDouble("double2", 123.456e7);
1014 base::DictionaryValue expected_policies;
1015 expected_policies.Set("policy", expected_policy.DeepCopy());
1016 PolicyBundle expected;
1017 expected.Get(ns).LoadFrom(
1018 &expected_policies, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
1019 EXPECT_TRUE(Matches(expected));
1020 }
1021
TEST_F(PolicyLoaderWinTest,AppliedPolicyNotPresent)1022 TEST_F(PolicyLoaderWinTest, AppliedPolicyNotPresent) {
1023 InstallRegistrySentinel();
1024 gpo_list_ = NULL;
1025 gpo_list_status_ = ERROR_SUCCESS;
1026
1027 PolicyBundle empty;
1028 EXPECT_TRUE(Matches(empty));
1029 }
1030
TEST_F(PolicyLoaderWinTest,AppliedPolicyEmpty)1031 TEST_F(PolicyLoaderWinTest, AppliedPolicyEmpty) {
1032 InstallRegistrySentinel();
1033 base::FilePath gpo_dir(test_data_dir_.AppendASCII("empty"));
1034 GROUP_POLICY_OBJECT gpo;
1035 InitGPO(&gpo, 0, gpo_dir, NULL, NULL);
1036 gpo_list_ = &gpo;
1037 gpo_list_status_ = ERROR_SUCCESS;
1038
1039 PolicyBundle empty;
1040 EXPECT_TRUE(Matches(empty));
1041 }
1042
TEST_F(PolicyLoaderWinTest,AppliedPolicyInDomain)1043 TEST_F(PolicyLoaderWinTest, AppliedPolicyInDomain) {
1044 base::win::SetDomainStateForTesting(true);
1045 InstallRegistrySentinel();
1046 base::FilePath gpo_dir(test_data_dir_.AppendASCII("empty"));
1047 GROUP_POLICY_OBJECT gpo;
1048 InitGPO(&gpo, 0, gpo_dir, NULL, NULL);
1049 gpo_list_ = &gpo;
1050 gpo_list_status_ = ERROR_SUCCESS;
1051
1052 PolicyBundle empty;
1053 EXPECT_TRUE(MatchesRegistrySentinel());
1054 }
1055
TEST_F(PolicyLoaderWinTest,AppliedPolicyNonExistingFile)1056 TEST_F(PolicyLoaderWinTest, AppliedPolicyNonExistingFile) {
1057 InstallRegistrySentinel();
1058 GROUP_POLICY_OBJECT gpo;
1059 InitGPO(&gpo, 0, test_data_dir_, NULL, NULL);
1060 gpo_list_ = &gpo;
1061 gpo_list_status_ = ERROR_SUCCESS;
1062
1063 EXPECT_TRUE(MatchesRegistrySentinel());
1064 }
1065
TEST_F(PolicyLoaderWinTest,AppliedPolicyBadPath)1066 TEST_F(PolicyLoaderWinTest, AppliedPolicyBadPath) {
1067 InstallRegistrySentinel();
1068 base::FilePath gpo_dir(test_data_dir_.AppendASCII("bad"));
1069 GROUP_POLICY_OBJECT gpo;
1070 InitGPO(&gpo, 0, gpo_dir, NULL, NULL);
1071 gpo_list_ = &gpo;
1072 gpo_list_status_ = ERROR_SUCCESS;
1073
1074 EXPECT_TRUE(MatchesRegistrySentinel());
1075 }
1076
TEST_F(PolicyLoaderWinTest,AppliedPolicyPresent)1077 TEST_F(PolicyLoaderWinTest, AppliedPolicyPresent) {
1078 InstallRegistrySentinel();
1079 base::FilePath gpo_dir(test_data_dir_.AppendASCII("test1"));
1080 GROUP_POLICY_OBJECT gpo;
1081 InitGPO(&gpo, 0, gpo_dir, NULL, NULL);
1082 gpo_list_ = &gpo;
1083 gpo_list_status_ = ERROR_SUCCESS;
1084
1085 EXPECT_TRUE(MatchesTestBundle());
1086 }
1087
TEST_F(PolicyLoaderWinTest,AppliedPolicyMerged)1088 TEST_F(PolicyLoaderWinTest, AppliedPolicyMerged) {
1089 InstallRegistrySentinel();
1090 base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test2"));
1091 base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test1"));
1092 GROUP_POLICY_OBJECT gpo1;
1093 GROUP_POLICY_OBJECT gpo2;
1094 InitGPO(&gpo1, 0, gpo1_dir, &gpo2, NULL);
1095 InitGPO(&gpo2, 0, gpo2_dir, NULL, &gpo1);
1096 gpo_list_ = &gpo1;
1097 gpo_list_status_ = ERROR_SUCCESS;
1098
1099 EXPECT_TRUE(MatchesTestBundle());
1100 }
1101
TEST_F(PolicyLoaderWinTest,AppliedPolicyDisabled)1102 TEST_F(PolicyLoaderWinTest, AppliedPolicyDisabled) {
1103 InstallRegistrySentinel();
1104 base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test1"));
1105 base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test2"));
1106 GROUP_POLICY_OBJECT gpo1;
1107 GROUP_POLICY_OBJECT gpo2;
1108 InitGPO(&gpo1, 0, gpo1_dir, &gpo2, NULL);
1109 InitGPO(&gpo2, GPO_FLAG_DISABLE, gpo2_dir, NULL, &gpo1);
1110 gpo_list_ = &gpo1;
1111 gpo_list_status_ = ERROR_SUCCESS;
1112
1113 EXPECT_TRUE(MatchesTestBundle());
1114 }
1115
TEST_F(PolicyLoaderWinTest,AppliedPolicyForcedPolicy)1116 TEST_F(PolicyLoaderWinTest, AppliedPolicyForcedPolicy) {
1117 InstallRegistrySentinel();
1118 base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test1"));
1119 base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test2"));
1120 GROUP_POLICY_OBJECT gpo1;
1121 GROUP_POLICY_OBJECT gpo2;
1122 InitGPO(&gpo1, GPO_FLAG_FORCE, gpo1_dir, &gpo2, NULL);
1123 InitGPO(&gpo2, 0, gpo2_dir, NULL, &gpo1);
1124 gpo_list_ = &gpo1;
1125 gpo_list_status_ = ERROR_SUCCESS;
1126
1127 EXPECT_TRUE(MatchesTestBundle());
1128 }
1129
TEST_F(PolicyLoaderWinTest,AppliedPolicyUNCPath)1130 TEST_F(PolicyLoaderWinTest, AppliedPolicyUNCPath) {
1131 InstallRegistrySentinel();
1132 base::FilePath gpo_dir(test_data_dir_.AppendASCII("test1"));
1133 base::FilePath unc_path(L"\\\\some_share\\GPO");
1134 GROUP_POLICY_OBJECT gpo1;
1135 GROUP_POLICY_OBJECT gpo2;
1136 InitGPO(&gpo1, 0, gpo_dir, &gpo2, NULL);
1137 InitGPO(&gpo2, 0, unc_path, NULL, &gpo1);
1138 gpo_list_ = &gpo1;
1139 gpo_list_status_ = ERROR_SUCCESS;
1140
1141 EXPECT_TRUE(MatchesRegistrySentinel());
1142 }
1143
TEST_F(PolicyLoaderWinTest,LoadExtensionPolicyAlternativeSpelling)1144 TEST_F(PolicyLoaderWinTest, LoadExtensionPolicyAlternativeSpelling) {
1145 base::FilePath gpo_dir(
1146 test_data_dir_.AppendASCII("extension_alternative_spelling"));
1147 GROUP_POLICY_OBJECT gpo;
1148 InitGPO(&gpo, 0, gpo_dir, NULL, NULL);
1149 gpo_list_ = &gpo;
1150 gpo_list_status_ = ERROR_SUCCESS;
1151
1152 const char kTestSchema[] =
1153 "{"
1154 " \"type\": \"object\","
1155 " \"properties\": {"
1156 " \"policy 1\": { \"type\": \"integer\" },"
1157 " \"policy 2\": { \"type\": \"integer\" }"
1158 " }"
1159 "}";
1160 const PolicyNamespace ns_a(
1161 POLICY_DOMAIN_EXTENSIONS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
1162 const PolicyNamespace ns_b(
1163 POLICY_DOMAIN_EXTENSIONS, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
1164 ASSERT_TRUE(RegisterSchema(ns_a, kTestSchema));
1165 ASSERT_TRUE(RegisterSchema(ns_b, kTestSchema));
1166
1167 PolicyBundle expected;
1168 base::DictionaryValue expected_a;
1169 expected_a.SetInteger("policy 1", 3);
1170 expected_a.SetInteger("policy 2", 3);
1171 expected.Get(ns_a).LoadFrom(
1172 &expected_a, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
1173 base::DictionaryValue expected_b;
1174 expected_b.SetInteger("policy 1", 2);
1175 expected.Get(ns_b).LoadFrom(
1176 &expected_b, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
1177 EXPECT_TRUE(Matches(expected));
1178 }
1179
TEST_F(PolicyLoaderWinTest,LBSSupport)1180 TEST_F(PolicyLoaderWinTest, LBSSupport) {
1181 const PolicyNamespace ns(
1182 POLICY_DOMAIN_EXTENSIONS, "heildphpnddilhkemkielfhnkaagiabh");
1183 schema_registry_.RegisterComponent(ns, Schema());
1184
1185 const char kIncompleteSchema[] =
1186 "{"
1187 " \"type\": \"object\","
1188 " \"properties\": {"
1189 " \"url_list\": { \"type\": \"array\" },"
1190 " \"url_greylist\": { \"type\": \"array\" }"
1191 " }"
1192 "}";
1193
1194 const base::string16 kPathSuffix =
1195 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions");
1196
1197 base::ListValue list;
1198 list.AppendString("youtube.com");
1199 base::DictionaryValue policy;
1200 policy.Set("url_list", list.DeepCopy());
1201 policy.SetString("alternative_browser_path", "c:\\legacy\\browser.exe");
1202 base::DictionaryValue root;
1203 root.Set(base::UTF16ToUTF8(kMandatory), policy.DeepCopy());
1204 root.SetString(kSchema, kIncompleteSchema);
1205 EXPECT_TRUE(InstallValue(root, HKEY_LOCAL_MACHINE,
1206 kPathSuffix, base::ASCIIToUTF16(ns.component_id)));
1207
1208 PolicyBundle expected;
1209 PolicyMap& expected_policy = expected.Get(ns);
1210 expected_policy.Set("alternative_browser_path",
1211 POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
1212 new base::StringValue("c:\\legacy\\browser.exe"), NULL);
1213 expected_policy.Set("url_list", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
1214 list.DeepCopy(), NULL);
1215 EXPECT_TRUE(Matches(expected));
1216 }
1217
1218 } // namespace policy
1219