1 // Copyright 2013 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/cloud/user_cloud_policy_store.h" 6 7 #include "base/files/file_util.h" 8 #include "base/files/scoped_temp_dir.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop_proxy.h" 11 #include "base/run_loop.h" 12 #include "components/policy/core/common/cloud/cloud_policy_constants.h" 13 #include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h" 14 #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" 15 #include "components/policy/core/common/cloud/policy_builder.h" 16 #include "components/policy/core/common/policy_switches.h" 17 #include "net/url_request/url_request_context_getter.h" 18 #include "policy/policy_constants.h" 19 #include "testing/gmock/include/gmock/gmock.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 using testing::AllOf; 23 using testing::Eq; 24 using testing::Mock; 25 using testing::Property; 26 using testing::Sequence; 27 28 namespace policy { 29 30 namespace { 31 32 void RunUntilIdle() { 33 base::RunLoop run_loop; 34 run_loop.RunUntilIdle(); 35 } 36 37 bool WriteStringToFile(const base::FilePath path, const std::string& data) { 38 if (!base::CreateDirectory(path.DirName())) { 39 DLOG(WARNING) << "Failed to create directory " << path.DirName().value(); 40 return false; 41 } 42 43 int size = data.size(); 44 if (base::WriteFile(path, data.c_str(), size) != size) { 45 DLOG(WARNING) << "Failed to write " << path.value(); 46 return false; 47 } 48 49 return true; 50 } 51 52 } // namespace 53 54 class UserCloudPolicyStoreTest : public testing::Test { 55 public: 56 UserCloudPolicyStoreTest() {} 57 58 virtual void SetUp() OVERRIDE { 59 ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir()); 60 store_.reset( 61 new UserCloudPolicyStore(policy_file(), 62 key_file(), 63 GetPolicyVerificationKey(), 64 loop_.message_loop_proxy())); 65 external_data_manager_.reset(new MockCloudExternalDataManager); 66 external_data_manager_->SetPolicyStore(store_.get()); 67 store_->SetSigninUsername(PolicyBuilder::kFakeUsername); 68 store_->AddObserver(&observer_); 69 70 // Install an initial public key, so that by default the validation of 71 // the stored/loaded policy blob succeeds (it looks like a new key 72 // provision). 73 policy_.SetDefaultInitialSigningKey(); 74 75 InitPolicyPayload(&policy_.payload()); 76 77 policy_.Build(); 78 } 79 80 virtual void TearDown() OVERRIDE { 81 store_->RemoveObserver(&observer_); 82 external_data_manager_.reset(); 83 store_.reset(); 84 RunUntilIdle(); 85 } 86 87 void InitPolicyPayload(enterprise_management::CloudPolicySettings* payload) { 88 payload->mutable_passwordmanagerenabled()->set_value(true); 89 payload->mutable_urlblacklist()->mutable_value()->add_entries( 90 "chromium.org"); 91 } 92 93 base::FilePath policy_file() { 94 return tmp_dir_.path().AppendASCII("policy"); 95 } 96 97 base::FilePath key_file() { 98 return tmp_dir_.path().AppendASCII("policy_key"); 99 } 100 101 // Verifies that store_->policy_map() has the appropriate entries. 102 void VerifyPolicyMap(CloudPolicyStore* store) { 103 EXPECT_EQ(2U, store->policy_map().size()); 104 const PolicyMap::Entry* entry = 105 store->policy_map().Get(key::kPasswordManagerEnabled); 106 ASSERT_TRUE(entry); 107 EXPECT_TRUE(base::FundamentalValue(true).Equals(entry->value)); 108 ASSERT_TRUE(store->policy_map().Get(key::kURLBlacklist)); 109 } 110 111 // Install an expectation on |observer_| for an error code. 112 void ExpectError(CloudPolicyStore* store, CloudPolicyStore::Status error) { 113 EXPECT_CALL(observer_, 114 OnStoreError(AllOf(Eq(store), 115 Property(&CloudPolicyStore::status, 116 Eq(error))))); 117 } 118 119 void StorePolicyAndEnsureLoaded( 120 const enterprise_management::PolicyFetchResponse& policy) { 121 Sequence s; 122 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s); 123 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s); 124 store_->Store(policy); 125 RunUntilIdle(); 126 Mock::VerifyAndClearExpectations(external_data_manager_.get()); 127 Mock::VerifyAndClearExpectations(&observer_); 128 ASSERT_TRUE(store_->policy()); 129 } 130 131 UserPolicyBuilder policy_; 132 MockCloudPolicyStoreObserver observer_; 133 scoped_ptr<UserCloudPolicyStore> store_; 134 scoped_ptr<MockCloudExternalDataManager> external_data_manager_; 135 136 // CloudPolicyValidator() requires a FILE thread so declare one here. Both 137 // |ui_thread_| and |file_thread_| share the same MessageLoop |loop_| so 138 // callers can use RunLoop to manage both virtual threads. 139 base::MessageLoopForUI loop_; 140 141 base::ScopedTempDir tmp_dir_; 142 143 DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyStoreTest); 144 }; 145 146 TEST_F(UserCloudPolicyStoreTest, LoadWithNoFile) { 147 EXPECT_FALSE(store_->policy()); 148 EXPECT_TRUE(store_->policy_map().empty()); 149 150 Sequence s; 151 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s); 152 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s); 153 store_->Load(); 154 RunUntilIdle(); 155 156 EXPECT_FALSE(store_->policy()); 157 EXPECT_TRUE(store_->policy_map().empty()); 158 } 159 160 TEST_F(UserCloudPolicyStoreTest, LoadWithInvalidFile) { 161 EXPECT_FALSE(store_->policy()); 162 EXPECT_TRUE(store_->policy_map().empty()); 163 164 // Create a bogus file. 165 ASSERT_TRUE(base::CreateDirectory(policy_file().DirName())); 166 std::string bogus_data = "bogus_data"; 167 int size = bogus_data.size(); 168 ASSERT_EQ(size, base::WriteFile(policy_file(), 169 bogus_data.c_str(), bogus_data.size())); 170 171 ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR); 172 store_->Load(); 173 RunUntilIdle(); 174 175 EXPECT_FALSE(store_->policy()); 176 EXPECT_TRUE(store_->policy_map().empty()); 177 } 178 179 TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithNoFile) { 180 EXPECT_FALSE(store_->policy()); 181 EXPECT_TRUE(store_->policy_map().empty()); 182 183 Sequence s; 184 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s); 185 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s); 186 store_->LoadImmediately(); // Should load without running the message loop. 187 188 EXPECT_FALSE(store_->policy()); 189 EXPECT_TRUE(store_->policy_map().empty()); 190 } 191 192 TEST_F(UserCloudPolicyStoreTest, LoadImmediatelyWithInvalidFile) { 193 EXPECT_FALSE(store_->policy()); 194 EXPECT_TRUE(store_->policy_map().empty()); 195 196 // Create a bogus file. 197 ASSERT_TRUE(base::CreateDirectory(policy_file().DirName())); 198 std::string bogus_data = "bogus_data"; 199 int size = bogus_data.size(); 200 ASSERT_EQ(size, base::WriteFile(policy_file(), 201 bogus_data.c_str(), bogus_data.size())); 202 203 ExpectError(store_.get(), CloudPolicyStore::STATUS_LOAD_ERROR); 204 store_->LoadImmediately(); // Should load without running the message loop. 205 206 EXPECT_FALSE(store_->policy()); 207 EXPECT_TRUE(store_->policy_map().empty()); 208 } 209 210 // Load file from cache with no key data - should give us a validation error. 211 TEST_F(UserCloudPolicyStoreTest, ShouldFailToLoadUnsignedPolicy) { 212 UserPolicyBuilder unsigned_builder; 213 unsigned_builder.UnsetSigningKey(); 214 InitPolicyPayload(&unsigned_builder.payload()); 215 unsigned_builder.Build(); 216 // Policy should be unsigned. 217 EXPECT_FALSE(unsigned_builder.policy().has_policy_data_signature()); 218 219 // Write policy to disk. 220 std::string data; 221 ASSERT_TRUE(unsigned_builder.policy().SerializeToString(&data)); 222 ASSERT_TRUE(base::CreateDirectory(policy_file().DirName())); 223 int size = data.size(); 224 ASSERT_EQ(size, base::WriteFile(policy_file(), data.c_str(), size)); 225 226 // Now make sure the data generates a validation error. 227 ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR); 228 store_->LoadImmediately(); // Should load without running the message loop. 229 Mock::VerifyAndClearExpectations(&observer_); 230 231 // Now mimic a new policy coming down - this should result in a new key 232 // being installed. 233 StorePolicyAndEnsureLoaded(policy_.policy()); 234 EXPECT_EQ(policy_.policy().new_public_key(), store_->policy_key()); 235 EXPECT_TRUE(store_->policy()->has_public_key_version()); 236 EXPECT_TRUE(base::PathExists(key_file())); 237 } 238 239 TEST_F(UserCloudPolicyStoreTest, Store) { 240 EXPECT_FALSE(store_->policy()); 241 EXPECT_TRUE(store_->policy_map().empty()); 242 243 // Store a simple policy and make sure it ends up as the currently active 244 // policy. 245 StorePolicyAndEnsureLoaded(policy_.policy()); 246 247 // Policy should be decoded and stored. 248 EXPECT_EQ(policy_.policy_data().SerializeAsString(), 249 store_->policy()->SerializeAsString()); 250 VerifyPolicyMap(store_.get()); 251 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 252 } 253 254 TEST_F(UserCloudPolicyStoreTest, StoreThenClear) { 255 EXPECT_FALSE(store_->policy()); 256 EXPECT_TRUE(store_->policy_map().empty()); 257 258 // Store a simple policy and make sure the file exists. 259 // policy. 260 StorePolicyAndEnsureLoaded(policy_.policy()); 261 EXPECT_FALSE(store_->policy_map().empty()); 262 263 // Policy file should exist. 264 ASSERT_TRUE(base::PathExists(policy_file())); 265 266 Sequence s2; 267 EXPECT_CALL(*external_data_manager_, OnPolicyStoreLoaded()).InSequence(s2); 268 EXPECT_CALL(observer_, OnStoreLoaded(store_.get())).InSequence(s2); 269 store_->Clear(); 270 RunUntilIdle(); 271 272 // Policy file should not exist. 273 ASSERT_TRUE(!base::PathExists(policy_file())); 274 275 // Policy should be gone. 276 EXPECT_FALSE(store_->policy()); 277 EXPECT_TRUE(store_->policy_map().empty()); 278 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 279 } 280 281 TEST_F(UserCloudPolicyStoreTest, StoreRotatedKey) { 282 EXPECT_FALSE(store_->policy()); 283 EXPECT_TRUE(store_->policy_map().empty()); 284 285 // Store a simple policy and make sure it ends up as the currently active 286 // policy. 287 StorePolicyAndEnsureLoaded(policy_.policy()); 288 EXPECT_FALSE(policy_.policy().has_new_public_key_signature()); 289 std::string original_policy_key = policy_.policy().new_public_key(); 290 EXPECT_EQ(original_policy_key, store_->policy_key()); 291 292 // Now do key rotation. 293 policy_.SetDefaultSigningKey(); 294 policy_.SetDefaultNewSigningKey(); 295 policy_.Build(); 296 EXPECT_TRUE(policy_.policy().has_new_public_key_signature()); 297 EXPECT_NE(original_policy_key, policy_.policy().new_public_key()); 298 StorePolicyAndEnsureLoaded(policy_.policy()); 299 EXPECT_EQ(policy_.policy().new_public_key(), store_->policy_key()); 300 } 301 302 TEST_F(UserCloudPolicyStoreTest, ProvisionKeyTwice) { 303 EXPECT_FALSE(store_->policy()); 304 EXPECT_TRUE(store_->policy_map().empty()); 305 306 // Store a simple policy and make sure it ends up as the currently active 307 // policy. 308 StorePolicyAndEnsureLoaded(policy_.policy()); 309 310 // Now try sending down policy signed with a different key (i.e. do key 311 // rotation with a key not signed with the original signing key). 312 policy_.UnsetSigningKey(); 313 policy_.SetDefaultNewSigningKey(); 314 policy_.Build(); 315 EXPECT_FALSE(policy_.policy().has_new_public_key_signature()); 316 317 ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR); 318 store_->Store(policy_.policy()); 319 RunUntilIdle(); 320 } 321 322 TEST_F(UserCloudPolicyStoreTest, StoreTwoTimes) { 323 EXPECT_FALSE(store_->policy()); 324 EXPECT_TRUE(store_->policy_map().empty()); 325 326 // Store a simple policy then store a second policy before the first one 327 // finishes validating, and make sure the second policy ends up as the active 328 // policy. 329 UserPolicyBuilder first_policy; 330 first_policy.SetDefaultInitialSigningKey(); 331 first_policy.payload().mutable_passwordmanagerenabled()->set_value(false); 332 first_policy.Build(); 333 StorePolicyAndEnsureLoaded(first_policy.policy()); 334 335 // Rebuild policy with the same signing key as |first_policy| (no rotation). 336 policy_.UnsetNewSigningKey(); 337 policy_.SetDefaultSigningKey(); 338 policy_.Build(); 339 ASSERT_FALSE(policy_.policy().has_new_public_key()); 340 StorePolicyAndEnsureLoaded(policy_.policy()); 341 342 // Policy should be decoded and stored. 343 EXPECT_EQ(policy_.policy_data().SerializeAsString(), 344 store_->policy()->SerializeAsString()); 345 VerifyPolicyMap(store_.get()); 346 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status()); 347 } 348 349 TEST_F(UserCloudPolicyStoreTest, StoreThenLoad) { 350 // Store a simple policy and make sure it can be read back in. 351 // policy. 352 StorePolicyAndEnsureLoaded(policy_.policy()); 353 EXPECT_FALSE(store_->policy_key().empty()); 354 355 // Now, make sure the policy can be read back in from a second store. 356 scoped_ptr<UserCloudPolicyStore> store2( 357 new UserCloudPolicyStore(policy_file(), 358 key_file(), 359 GetPolicyVerificationKey(), 360 loop_.message_loop_proxy())); 361 store2->SetSigninUsername(PolicyBuilder::kFakeUsername); 362 store2->AddObserver(&observer_); 363 EXPECT_CALL(observer_, OnStoreLoaded(store2.get())); 364 store2->Load(); 365 RunUntilIdle(); 366 367 ASSERT_TRUE(store2->policy()); 368 EXPECT_EQ(policy_.policy_data().SerializeAsString(), 369 store2->policy()->SerializeAsString()); 370 VerifyPolicyMap(store2.get()); 371 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store2->status()); 372 store2->RemoveObserver(&observer_); 373 // Make sure that we properly resurrected the keys. 374 EXPECT_EQ(store2->policy_key(), store_->policy_key()); 375 } 376 377 TEST_F(UserCloudPolicyStoreTest, StoreThenLoadImmediately) { 378 // Store a simple policy and make sure it can be read back in. 379 // policy. 380 StorePolicyAndEnsureLoaded(policy_.policy()); 381 382 // Now, make sure the policy can be read back in from a second store. 383 scoped_ptr<UserCloudPolicyStore> store2( 384 new UserCloudPolicyStore(policy_file(), 385 key_file(), 386 GetPolicyVerificationKey(), 387 loop_.message_loop_proxy())); 388 store2->SetSigninUsername(PolicyBuilder::kFakeUsername); 389 store2->AddObserver(&observer_); 390 EXPECT_CALL(observer_, OnStoreLoaded(store2.get())); 391 store2->LoadImmediately(); // Should load without running the message loop. 392 393 ASSERT_TRUE(store2->policy()); 394 EXPECT_EQ(policy_.policy_data().SerializeAsString(), 395 store2->policy()->SerializeAsString()); 396 VerifyPolicyMap(store2.get()); 397 EXPECT_EQ(CloudPolicyStore::STATUS_OK, store2->status()); 398 store2->RemoveObserver(&observer_); 399 } 400 401 TEST_F(UserCloudPolicyStoreTest, StoreValidationError) { 402 // Create an invalid policy (no policy type). 403 policy_.policy_data().clear_policy_type(); 404 policy_.Build(); 405 406 // Store policy. 407 ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR); 408 store_->Store(policy_.policy()); 409 RunUntilIdle(); 410 ASSERT_FALSE(store_->policy()); 411 } 412 413 TEST_F(UserCloudPolicyStoreTest, StoreUnsigned) { 414 // Create unsigned policy, try to store it, should get a validation error. 415 policy_.policy().mutable_policy_data_signature()->clear(); 416 417 // Store policy. 418 ExpectError(store_.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR); 419 store_->Store(policy_.policy()); 420 RunUntilIdle(); 421 ASSERT_FALSE(store_->policy()); 422 } 423 424 TEST_F(UserCloudPolicyStoreTest, LoadValidationError) { 425 // Force a validation error by changing the username after policy is stored. 426 StorePolicyAndEnsureLoaded(policy_.policy()); 427 428 // Sign out, and sign back in as a different user, and try to load the profile 429 // data (should fail due to mismatched username). 430 scoped_ptr<UserCloudPolicyStore> store2( 431 new UserCloudPolicyStore(policy_file(), 432 key_file(), 433 GetPolicyVerificationKey(), 434 loop_.message_loop_proxy())); 435 store2->SetSigninUsername("foobar (at) foobar.com"); 436 store2->AddObserver(&observer_); 437 ExpectError(store2.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR); 438 store2->Load(); 439 RunUntilIdle(); 440 441 ASSERT_FALSE(store2->policy()); 442 store2->RemoveObserver(&observer_); 443 444 // Sign out - we should be able to load the policy (don't check usernames 445 // when signed out). 446 scoped_ptr<UserCloudPolicyStore> store3( 447 new UserCloudPolicyStore(policy_file(), 448 key_file(), 449 GetPolicyVerificationKey(), 450 loop_.message_loop_proxy())); 451 store3->AddObserver(&observer_); 452 EXPECT_CALL(observer_, OnStoreLoaded(store3.get())); 453 store3->Load(); 454 RunUntilIdle(); 455 456 ASSERT_TRUE(store3->policy()); 457 store3->RemoveObserver(&observer_); 458 459 // Now start a signin as a different user - this should fail validation. 460 scoped_ptr<UserCloudPolicyStore> store4( 461 new UserCloudPolicyStore(policy_file(), 462 key_file(), 463 GetPolicyVerificationKey(), 464 loop_.message_loop_proxy())); 465 store4->SetSigninUsername("foobar (at) foobar.com"); 466 store4->AddObserver(&observer_); 467 ExpectError(store4.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR); 468 store4->Load(); 469 RunUntilIdle(); 470 471 ASSERT_FALSE(store4->policy()); 472 store4->RemoveObserver(&observer_); 473 } 474 475 TEST_F(UserCloudPolicyStoreTest, KeyRotation) { 476 // Make sure when we load data from disk with a different key, that we trigger 477 // a server-side key rotation. 478 StorePolicyAndEnsureLoaded(policy_.policy()); 479 ASSERT_TRUE(store_->policy()->has_public_key_version()); 480 481 std::string key_data; 482 enterprise_management::PolicySigningKey key; 483 ASSERT_TRUE(base::ReadFileToString(key_file(), &key_data)); 484 ASSERT_TRUE(key.ParseFromString(key_data)); 485 key.set_verification_key("different_key"); 486 key.SerializeToString(&key_data); 487 WriteStringToFile(key_file(), key_data); 488 489 // Now load this in a new store - this should trigger key rotation. The keys 490 // will still verify using the existing verification key. 491 scoped_ptr<UserCloudPolicyStore> store2( 492 new UserCloudPolicyStore(policy_file(), 493 key_file(), 494 GetPolicyVerificationKey(), 495 loop_.message_loop_proxy())); 496 store2->SetSigninUsername(PolicyBuilder::kFakeUsername); 497 store2->AddObserver(&observer_); 498 EXPECT_CALL(observer_, OnStoreLoaded(store2.get())); 499 store2->Load(); 500 RunUntilIdle(); 501 ASSERT_TRUE(store2->policy()); 502 ASSERT_FALSE(store2->policy()->has_public_key_version()); 503 store2->RemoveObserver(&observer_); 504 } 505 506 TEST_F(UserCloudPolicyStoreTest, InvalidCachedVerificationSignature) { 507 // Make sure that we reject code with an invalid key. 508 StorePolicyAndEnsureLoaded(policy_.policy()); 509 510 std::string key_data; 511 enterprise_management::PolicySigningKey key; 512 ASSERT_TRUE(base::ReadFileToString(key_file(), &key_data)); 513 ASSERT_TRUE(key.ParseFromString(key_data)); 514 key.set_signing_key_signature("different_key"); 515 key.SerializeToString(&key_data); 516 WriteStringToFile(key_file(), key_data); 517 518 // Now load this in a new store - this should cause a validation error because 519 // the key won't verify. 520 scoped_ptr<UserCloudPolicyStore> store2( 521 new UserCloudPolicyStore(policy_file(), 522 key_file(), 523 GetPolicyVerificationKey(), 524 loop_.message_loop_proxy())); 525 store2->SetSigninUsername(PolicyBuilder::kFakeUsername); 526 store2->AddObserver(&observer_); 527 ExpectError(store2.get(), CloudPolicyStore::STATUS_VALIDATION_ERROR); 528 store2->Load(); 529 RunUntilIdle(); 530 store2->RemoveObserver(&observer_); 531 } 532 533 } // namespace policy 534