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 "chrome/browser/chromeos/policy/auto_enrollment_client.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/prefs/pref_service.h" 11 #include "base/prefs/testing_pref_service.h" 12 #include "base/values.h" 13 #include "chrome/browser/browser_process.h" 14 #include "chrome/browser/policy/cloud/mock_device_management_service.h" 15 #include "chrome/common/pref_names.h" 16 #include "chrome/test/base/scoped_testing_local_state.h" 17 #include "chrome/test/base/testing_browser_process.h" 18 #include "content/public/test/test_browser_thread_bundle.h" 19 #include "crypto/sha2.h" 20 #include "testing/gmock/include/gmock/gmock.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 23 namespace em = enterprise_management; 24 25 namespace policy { 26 27 namespace { 28 29 const char* kSerial = "serial"; 30 const char* kSerialHash = 31 "\x01\x44\xb1\xde\xfc\xf7\x56\x10\x87\x01\x5f\x8d\x83\x0d\x65\xb1" 32 "\x6f\x02\x4a\xd7\xeb\x92\x45\xfc\xd4\xe4\x37\xa1\x55\x2b\x13\x8a"; 33 34 using ::testing::InSequence; 35 using ::testing::SaveArg; 36 using ::testing::_; 37 38 class AutoEnrollmentClientTest : public testing::Test { 39 protected: 40 AutoEnrollmentClientTest() 41 : scoped_testing_local_state_( 42 TestingBrowserProcess::GetGlobal()), 43 local_state_(scoped_testing_local_state_.Get()), 44 service_(NULL), 45 completion_callback_count_(0) {} 46 47 virtual void SetUp() OVERRIDE { 48 CreateClient(kSerial, 4, 8); 49 ASSERT_FALSE(local_state_->GetUserPref(prefs::kShouldAutoEnroll)); 50 ASSERT_FALSE(local_state_->GetUserPref(prefs::kAutoEnrollmentPowerLimit)); 51 } 52 53 void CreateClient(const std::string& serial, 54 int power_initial, 55 int power_limit) { 56 service_ = new MockDeviceManagementService(); 57 EXPECT_CALL(*service_, StartJob(_, _, _, _, _, _, _)) 58 .WillRepeatedly(SaveArg<6>(&last_request_)); 59 base::Closure callback = 60 base::Bind(&AutoEnrollmentClientTest::CompletionCallback, 61 base::Unretained(this)); 62 client_.reset(new AutoEnrollmentClient(callback, 63 service_, 64 local_state_, 65 serial, 66 power_initial, 67 power_limit)); 68 } 69 70 void CompletionCallback() { 71 completion_callback_count_++; 72 } 73 74 void ServerWillFail(DeviceManagementStatus error) { 75 em::DeviceManagementResponse dummy_response; 76 EXPECT_CALL(*service_, 77 CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT)) 78 .WillOnce(service_->FailJob(error)); 79 } 80 81 void ServerWillReply(int64 modulus, bool with_hashes, bool with_serial_hash) { 82 em::DeviceManagementResponse response; 83 em::DeviceAutoEnrollmentResponse* enrollment_response = 84 response.mutable_auto_enrollment_response(); 85 if (modulus >= 0) 86 enrollment_response->set_expected_modulus(modulus); 87 if (with_hashes) { 88 for (size_t i = 0; i < 10; ++i) { 89 std::string serial = "serial X"; 90 serial[7] = '0' + i; 91 std::string hash = crypto::SHA256HashString(serial); 92 enrollment_response->mutable_hash()->Add()->assign(hash); 93 } 94 } 95 if (with_serial_hash) { 96 enrollment_response->mutable_hash()->Add()->assign(kSerialHash, 97 crypto::kSHA256Length); 98 } 99 EXPECT_CALL(*service_, 100 CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT)) 101 .WillOnce(service_->SucceedJob(response)); 102 } 103 104 void ServerWillReplyAsync(MockDeviceManagementJob** job) { 105 EXPECT_CALL(*service_, 106 CreateJob(DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT)) 107 .WillOnce(service_->CreateAsyncJob(job)); 108 } 109 110 bool HasCachedDecision() { 111 return local_state_->GetUserPref(prefs::kShouldAutoEnroll); 112 } 113 114 void VerifyCachedResult(bool should_enroll, int power_limit) { 115 base::FundamentalValue value_should_enroll(should_enroll); 116 base::FundamentalValue value_power_limit(power_limit); 117 EXPECT_TRUE(Value::Equals( 118 &value_should_enroll, 119 local_state_->GetUserPref(prefs::kShouldAutoEnroll))); 120 EXPECT_TRUE(Value::Equals( 121 &value_power_limit, 122 local_state_->GetUserPref(prefs::kAutoEnrollmentPowerLimit))); 123 } 124 125 const em::DeviceAutoEnrollmentRequest& auto_enrollment_request() { 126 return last_request_.auto_enrollment_request(); 127 } 128 129 content::TestBrowserThreadBundle browser_threads_; 130 ScopedTestingLocalState scoped_testing_local_state_; 131 TestingPrefServiceSimple* local_state_; 132 MockDeviceManagementService* service_; 133 scoped_ptr<AutoEnrollmentClient> client_; 134 em::DeviceManagementRequest last_request_; 135 int completion_callback_count_; 136 137 private: 138 DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentClientTest); 139 }; 140 141 TEST_F(AutoEnrollmentClientTest, NetworkFailure) { 142 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE); 143 client_->Start(); 144 EXPECT_FALSE(client_->should_auto_enroll()); 145 EXPECT_EQ(0, completion_callback_count_); 146 EXPECT_FALSE(HasCachedDecision()); 147 } 148 149 TEST_F(AutoEnrollmentClientTest, EmptyReply) { 150 ServerWillReply(-1, false, false); 151 client_->Start(); 152 EXPECT_FALSE(client_->should_auto_enroll()); 153 EXPECT_EQ(1, completion_callback_count_); 154 VerifyCachedResult(false, 8); 155 } 156 157 TEST_F(AutoEnrollmentClientTest, ClientUploadsRightBits) { 158 ServerWillReply(-1, false, false); 159 client_->Start(); 160 EXPECT_FALSE(client_->should_auto_enroll()); 161 EXPECT_EQ(1, completion_callback_count_); 162 163 EXPECT_TRUE(auto_enrollment_request().has_remainder()); 164 EXPECT_TRUE(auto_enrollment_request().has_modulus()); 165 EXPECT_EQ(16, auto_enrollment_request().modulus()); 166 EXPECT_EQ(kSerialHash[31] & 0xf, auto_enrollment_request().remainder()); 167 VerifyCachedResult(false, 8); 168 } 169 170 TEST_F(AutoEnrollmentClientTest, AskForMoreThenFail) { 171 InSequence sequence; 172 ServerWillReply(32, false, false); 173 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE); 174 client_->Start(); 175 EXPECT_FALSE(client_->should_auto_enroll()); 176 EXPECT_EQ(0, completion_callback_count_); 177 EXPECT_FALSE(HasCachedDecision()); 178 } 179 180 TEST_F(AutoEnrollmentClientTest, AskForMoreThenEvenMore) { 181 InSequence sequence; 182 ServerWillReply(32, false, false); 183 ServerWillReply(64, false, false); 184 client_->Start(); 185 EXPECT_FALSE(client_->should_auto_enroll()); 186 EXPECT_EQ(1, completion_callback_count_); 187 EXPECT_FALSE(HasCachedDecision()); 188 } 189 190 TEST_F(AutoEnrollmentClientTest, AskForLess) { 191 InSequence sequence; 192 ServerWillReply(8, false, false); 193 ServerWillReply(-1, true, true); 194 client_->Start(); 195 EXPECT_TRUE(client_->should_auto_enroll()); 196 EXPECT_EQ(1, completion_callback_count_); 197 VerifyCachedResult(true, 8); 198 } 199 200 TEST_F(AutoEnrollmentClientTest, AskForSame) { 201 InSequence sequence; 202 ServerWillReply(16, false, false); 203 ServerWillReply(-1, true, true); 204 client_->Start(); 205 EXPECT_TRUE(client_->should_auto_enroll()); 206 EXPECT_EQ(1, completion_callback_count_); 207 VerifyCachedResult(true, 8); 208 } 209 210 TEST_F(AutoEnrollmentClientTest, AskForSameTwice) { 211 InSequence sequence; 212 ServerWillReply(16, false, false); 213 ServerWillReply(16, false, false); 214 client_->Start(); 215 EXPECT_FALSE(client_->should_auto_enroll()); 216 EXPECT_EQ(1, completion_callback_count_); 217 EXPECT_FALSE(HasCachedDecision()); 218 } 219 220 TEST_F(AutoEnrollmentClientTest, AskForTooMuch) { 221 ServerWillReply(512, false, false); 222 client_->Start(); 223 EXPECT_FALSE(client_->should_auto_enroll()); 224 EXPECT_EQ(1, completion_callback_count_); 225 EXPECT_FALSE(HasCachedDecision()); 226 } 227 228 TEST_F(AutoEnrollmentClientTest, AskNonPowerOf2) { 229 InSequence sequence; 230 ServerWillReply(100, false, false); 231 ServerWillReply(-1, false, false); 232 client_->Start(); 233 EXPECT_FALSE(client_->should_auto_enroll()); 234 EXPECT_EQ(1, completion_callback_count_); 235 EXPECT_TRUE(auto_enrollment_request().has_remainder()); 236 EXPECT_TRUE(auto_enrollment_request().has_modulus()); 237 EXPECT_EQ(128, auto_enrollment_request().modulus()); 238 EXPECT_EQ(kSerialHash[31] & 0x7f, auto_enrollment_request().remainder()); 239 VerifyCachedResult(false, 8); 240 } 241 242 TEST_F(AutoEnrollmentClientTest, ConsumerDevice) { 243 ServerWillReply(-1, true, false); 244 client_->Start(); 245 EXPECT_FALSE(client_->should_auto_enroll()); 246 EXPECT_EQ(1, completion_callback_count_); 247 VerifyCachedResult(false, 8); 248 249 // Network changes don't trigger retries after obtaining a response from 250 // the server. 251 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 252 EXPECT_EQ(1, completion_callback_count_); 253 } 254 255 TEST_F(AutoEnrollmentClientTest, EnterpriseDevice) { 256 ServerWillReply(-1, true, true); 257 client_->Start(); 258 EXPECT_TRUE(client_->should_auto_enroll()); 259 EXPECT_EQ(1, completion_callback_count_); 260 VerifyCachedResult(true, 8); 261 262 // Network changes don't trigger retries after obtaining a response from 263 // the server. 264 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 265 EXPECT_EQ(1, completion_callback_count_); 266 } 267 268 TEST_F(AutoEnrollmentClientTest, NoSerial) { 269 CreateClient("", 4, 8); 270 client_->Start(); 271 EXPECT_FALSE(client_->should_auto_enroll()); 272 EXPECT_EQ(1, completion_callback_count_); 273 EXPECT_FALSE(HasCachedDecision()); 274 } 275 276 TEST_F(AutoEnrollmentClientTest, NoBitsUploaded) { 277 CreateClient(kSerial, 0, 0); 278 ServerWillReply(-1, false, false); 279 client_->Start(); 280 EXPECT_FALSE(client_->should_auto_enroll()); 281 EXPECT_EQ(1, completion_callback_count_); 282 EXPECT_TRUE(auto_enrollment_request().has_remainder()); 283 EXPECT_TRUE(auto_enrollment_request().has_modulus()); 284 EXPECT_EQ(1, auto_enrollment_request().modulus()); 285 EXPECT_EQ(0, auto_enrollment_request().remainder()); 286 VerifyCachedResult(false, 0); 287 } 288 289 TEST_F(AutoEnrollmentClientTest, ManyBitsUploaded) { 290 int64 bottom62 = GG_INT64_C(0x14e437a1552b138a); 291 for (int i = 0; i <= 62; ++i) { 292 completion_callback_count_ = 0; 293 CreateClient(kSerial, i, i); 294 ServerWillReply(-1, false, false); 295 client_->Start(); 296 EXPECT_FALSE(client_->should_auto_enroll()); 297 EXPECT_EQ(1, completion_callback_count_); 298 EXPECT_TRUE(auto_enrollment_request().has_remainder()); 299 EXPECT_TRUE(auto_enrollment_request().has_modulus()); 300 EXPECT_EQ(GG_INT64_C(1) << i, auto_enrollment_request().modulus()); 301 EXPECT_EQ(bottom62 % (GG_INT64_C(1) << i), 302 auto_enrollment_request().remainder()); 303 VerifyCachedResult(false, i); 304 } 305 } 306 307 TEST_F(AutoEnrollmentClientTest, MoreThan32BitsUploaded) { 308 CreateClient(kSerial, 10, 37); 309 InSequence sequence; 310 ServerWillReply(GG_INT64_C(1) << 37, false, false); 311 ServerWillReply(-1, true, true); 312 client_->Start(); 313 EXPECT_TRUE(client_->should_auto_enroll()); 314 EXPECT_EQ(1, completion_callback_count_); 315 VerifyCachedResult(true, 37); 316 } 317 318 TEST_F(AutoEnrollmentClientTest, ReuseCachedDecision) { 319 EXPECT_CALL(*service_, CreateJob(_)).Times(0); 320 local_state_->SetUserPref(prefs::kShouldAutoEnroll, 321 Value::CreateBooleanValue(true)); 322 local_state_->SetUserPref(prefs::kAutoEnrollmentPowerLimit, 323 Value::CreateIntegerValue(8)); 324 client_->Start(); 325 EXPECT_TRUE(client_->should_auto_enroll()); 326 EXPECT_EQ(1, completion_callback_count_); 327 AutoEnrollmentClient::CancelAutoEnrollment(); 328 client_->Start(); 329 EXPECT_FALSE(client_->should_auto_enroll()); 330 EXPECT_EQ(2, completion_callback_count_); 331 } 332 333 TEST_F(AutoEnrollmentClientTest, RetryIfPowerLargerThanCached) { 334 local_state_->SetUserPref(prefs::kShouldAutoEnroll, 335 Value::CreateBooleanValue(false)); 336 local_state_->SetUserPref(prefs::kAutoEnrollmentPowerLimit, 337 Value::CreateIntegerValue(8)); 338 CreateClient(kSerial, 5, 10); 339 ServerWillReply(-1, true, true); 340 client_->Start(); 341 EXPECT_TRUE(client_->should_auto_enroll()); 342 EXPECT_EQ(1, completion_callback_count_); 343 } 344 345 TEST_F(AutoEnrollmentClientTest, NetworkChangeRetryAfterErrors) { 346 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE); 347 client_->Start(); 348 EXPECT_FALSE(client_->should_auto_enroll()); 349 // Don't invoke the callback if there was a network failure. 350 EXPECT_EQ(0, completion_callback_count_); 351 EXPECT_FALSE(HasCachedDecision()); 352 353 // The client doesn't retry if no new connection became available. 354 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE); 355 EXPECT_FALSE(client_->should_auto_enroll()); 356 EXPECT_EQ(0, completion_callback_count_); 357 EXPECT_FALSE(HasCachedDecision()); 358 359 // Retry once the network is back. 360 ServerWillReply(-1, true, true); 361 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 362 EXPECT_TRUE(client_->should_auto_enroll()); 363 EXPECT_EQ(1, completion_callback_count_); 364 EXPECT_TRUE(HasCachedDecision()); 365 366 // Subsequent network changes don't trigger retries. 367 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE); 368 client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 369 EXPECT_TRUE(client_->should_auto_enroll()); 370 EXPECT_EQ(1, completion_callback_count_); 371 EXPECT_TRUE(HasCachedDecision()); 372 } 373 374 TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonWithPendingRequest) { 375 MockDeviceManagementJob* job = NULL; 376 ServerWillReplyAsync(&job); 377 EXPECT_FALSE(job); 378 client_->Start(); 379 ASSERT_TRUE(job); 380 EXPECT_EQ(0, completion_callback_count_); 381 382 // Cancel while a request is in flight. 383 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 384 client_.release()->CancelAndDeleteSoon(); 385 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 386 387 // The client cleans itself up once a reply is received. 388 job->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE, 389 em::DeviceManagementResponse()); 390 // The DeleteSoon task has been posted: 391 EXPECT_FALSE(base::MessageLoop::current()->IsIdleForTesting()); 392 EXPECT_EQ(0, completion_callback_count_); 393 } 394 395 TEST_F(AutoEnrollmentClientTest, NetworkChangedAfterCancelAndDeleteSoon) { 396 MockDeviceManagementJob* job = NULL; 397 ServerWillReplyAsync(&job); 398 EXPECT_FALSE(job); 399 client_->Start(); 400 ASSERT_TRUE(job); 401 EXPECT_EQ(0, completion_callback_count_); 402 403 // Cancel while a request is in flight. 404 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 405 AutoEnrollmentClient* client = client_.release(); 406 client->CancelAndDeleteSoon(); 407 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 408 409 // Network change events are ignored while a request is pending. 410 client->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 411 EXPECT_EQ(0, completion_callback_count_); 412 413 // The client cleans itself up once a reply is received. 414 job->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE, 415 em::DeviceManagementResponse()); 416 // The DeleteSoon task has been posted: 417 EXPECT_FALSE(base::MessageLoop::current()->IsIdleForTesting()); 418 EXPECT_EQ(0, completion_callback_count_); 419 420 // Network changes that have been posted before are also ignored: 421 client->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); 422 EXPECT_EQ(0, completion_callback_count_); 423 } 424 425 TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterCompletion) { 426 ServerWillReply(-1, true, true); 427 client_->Start(); 428 EXPECT_EQ(1, completion_callback_count_); 429 EXPECT_TRUE(client_->should_auto_enroll()); 430 431 // The client will delete itself immediately if there are no pending 432 // requests. 433 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 434 client_.release()->CancelAndDeleteSoon(); 435 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 436 } 437 438 TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterNetworkFailure) { 439 ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE); 440 client_->Start(); 441 EXPECT_EQ(0, completion_callback_count_); 442 EXPECT_FALSE(client_->should_auto_enroll()); 443 444 // The client will delete itself immediately if there are no pending 445 // requests. 446 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 447 client_.release()->CancelAndDeleteSoon(); 448 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); 449 } 450 451 } // namespace 452 453 } // namespace policy 454