Home | History | Annotate | Download | only in policy
      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