Home | History | Annotate | Download | only in settings
      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/settings/device_settings_service.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/stl_util.h"
     11 #include "base/time/time.h"
     12 #include "chrome/browser/chrome_notification_types.h"
     13 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
     14 #include "chrome/browser/chromeos/settings/owner_key_util.h"
     15 #include "chrome/browser/chromeos/settings/session_manager_operation.h"
     16 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
     17 #include "content/public/browser/browser_thread.h"
     18 #include "content/public/browser/notification_service.h"
     19 #include "content/public/browser/notification_source.h"
     20 #include "crypto/rsa_private_key.h"
     21 
     22 namespace em = enterprise_management;
     23 
     24 namespace {
     25 
     26 // Delay between load retries when there was a validation error.
     27 // NOTE: This code is here to mitigate clock loss on some devices where policy
     28 // loads will fail with a validation error caused by RTC clock bing reset when
     29 // the battery is drained.
     30 int kLoadRetryDelayMs = 1000 * 5;
     31 // Maximal number of retries before we give up. Calculated to allow for 10 min
     32 // of retry time.
     33 int kMaxLoadRetries = (1000 * 60 * 10) / kLoadRetryDelayMs;
     34 
     35 }  // namespace
     36 
     37 namespace chromeos {
     38 
     39 DeviceSettingsService::Observer::~Observer() {}
     40 
     41 static DeviceSettingsService* g_device_settings_service = NULL;
     42 
     43 // static
     44 void DeviceSettingsService::Initialize() {
     45   CHECK(!g_device_settings_service);
     46   g_device_settings_service = new DeviceSettingsService();
     47 }
     48 
     49 // static
     50 bool DeviceSettingsService::IsInitialized() {
     51   return g_device_settings_service;
     52 }
     53 
     54 // static
     55 void DeviceSettingsService::Shutdown() {
     56   DCHECK(g_device_settings_service);
     57   delete g_device_settings_service;
     58   g_device_settings_service = NULL;
     59 }
     60 
     61 // static
     62 DeviceSettingsService* DeviceSettingsService::Get() {
     63   CHECK(g_device_settings_service);
     64   return g_device_settings_service;
     65 }
     66 
     67 DeviceSettingsService::DeviceSettingsService()
     68     : session_manager_client_(NULL),
     69       store_status_(STORE_SUCCESS),
     70       load_retries_left_(kMaxLoadRetries),
     71       weak_factory_(this) {
     72 }
     73 
     74 DeviceSettingsService::~DeviceSettingsService() {
     75   DCHECK(pending_operations_.empty());
     76 }
     77 
     78 void DeviceSettingsService::SetSessionManager(
     79     SessionManagerClient* session_manager_client,
     80     scoped_refptr<OwnerKeyUtil> owner_key_util) {
     81   DCHECK(session_manager_client);
     82   DCHECK(owner_key_util.get());
     83   DCHECK(!session_manager_client_);
     84   DCHECK(!owner_key_util_.get());
     85 
     86   session_manager_client_ = session_manager_client;
     87   owner_key_util_ = owner_key_util;
     88 
     89   session_manager_client_->AddObserver(this);
     90 
     91   StartNextOperation();
     92 }
     93 
     94 void DeviceSettingsService::UnsetSessionManager() {
     95   STLDeleteContainerPointers(pending_operations_.begin(),
     96                              pending_operations_.end());
     97   pending_operations_.clear();
     98 
     99   if (session_manager_client_)
    100     session_manager_client_->RemoveObserver(this);
    101   session_manager_client_ = NULL;
    102   owner_key_util_ = NULL;
    103 }
    104 
    105 scoped_refptr<PublicKey> DeviceSettingsService::GetPublicKey() {
    106   return public_key_;
    107 }
    108 
    109 void DeviceSettingsService::Load() {
    110   EnqueueLoad(false);
    111 }
    112 
    113 void DeviceSettingsService::SignAndStore(
    114     scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,
    115     const base::Closure& callback) {
    116   scoped_ptr<em::PolicyData> new_policy = AssemblePolicy(*new_settings);
    117   if (!new_policy) {
    118     HandleError(STORE_POLICY_ERROR, callback);
    119     return;
    120   }
    121 
    122   EnqueueSignAndStore(new_policy.Pass(), callback);
    123 }
    124 
    125 void DeviceSettingsService::SetManagementSettings(
    126     em::PolicyData::ManagementMode management_mode,
    127     const std::string& request_token,
    128     const std::string& device_id,
    129     const base::Closure& callback) {
    130   if (!CheckManagementModeTransition(management_mode)) {
    131     LOG(ERROR) << "Invalid management mode transition: current mode = "
    132                << GetManagementMode() << ", new mode = " << management_mode;
    133     HandleError(STORE_POLICY_ERROR, callback);
    134     return;
    135   }
    136 
    137   scoped_ptr<em::PolicyData> policy = AssemblePolicy(*device_settings_);
    138   if (!policy) {
    139     HandleError(STORE_POLICY_ERROR, callback);
    140     return;
    141   }
    142 
    143   policy->set_management_mode(management_mode);
    144   policy->set_request_token(request_token);
    145   policy->set_device_id(device_id);
    146 
    147   EnqueueSignAndStore(policy.Pass(), callback);
    148 }
    149 
    150 void DeviceSettingsService::Store(scoped_ptr<em::PolicyFetchResponse> policy,
    151                                   const base::Closure& callback) {
    152   Enqueue(
    153       new StoreSettingsOperation(
    154           base::Bind(&DeviceSettingsService::HandleCompletedOperation,
    155                      weak_factory_.GetWeakPtr(),
    156                      callback),
    157           policy.Pass()));
    158 }
    159 
    160 DeviceSettingsService::OwnershipStatus
    161     DeviceSettingsService::GetOwnershipStatus() {
    162   if (public_key_)
    163     return public_key_->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
    164   return OWNERSHIP_UNKNOWN;
    165 }
    166 
    167 void DeviceSettingsService::GetOwnershipStatusAsync(
    168     const OwnershipStatusCallback& callback) {
    169   if (public_key_) {
    170     // If there is a key, report status immediately.
    171     base::MessageLoop::current()->PostTask(
    172         FROM_HERE, base::Bind(callback, GetOwnershipStatus()));
    173   } else {
    174     // If the key hasn't been loaded yet, enqueue the callback to be fired when
    175     // the next SessionManagerOperation completes. If no operation is pending,
    176     // start a load operation to fetch the key and report the result.
    177     pending_ownership_status_callbacks_.push_back(callback);
    178     if (pending_operations_.empty())
    179       EnqueueLoad(false);
    180   }
    181 }
    182 
    183 bool DeviceSettingsService::HasPrivateOwnerKey() {
    184   return delegate_ && delegate_->IsOwner();
    185 }
    186 
    187 void DeviceSettingsService::InitOwner(
    188     const std::string& username,
    189     const base::WeakPtr<PrivateKeyDelegate>& delegate) {
    190   // When InitOwner() is called twice with the same |username| it's
    191   // worth to reload settings since owner key may become available.
    192   if (!username_.empty() && username_ != username)
    193     return;
    194   username_ = username;
    195   delegate_ = delegate;
    196 
    197   EnsureReload(true);
    198 }
    199 
    200 const std::string& DeviceSettingsService::GetUsername() const {
    201   return username_;
    202 }
    203 
    204 void DeviceSettingsService::AddObserver(Observer* observer) {
    205   observers_.AddObserver(observer);
    206 }
    207 
    208 void DeviceSettingsService::RemoveObserver(Observer* observer) {
    209   observers_.RemoveObserver(observer);
    210 }
    211 
    212 void DeviceSettingsService::OwnerKeySet(bool success) {
    213   if (!success) {
    214     LOG(ERROR) << "Owner key change failed.";
    215     return;
    216   }
    217 
    218   public_key_ = NULL;
    219   EnsureReload(true);
    220 }
    221 
    222 void DeviceSettingsService::PropertyChangeComplete(bool success) {
    223   if (!success) {
    224     LOG(ERROR) << "Policy update failed.";
    225     return;
    226   }
    227 
    228   EnsureReload(false);
    229 }
    230 
    231 void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
    232   pending_operations_.push_back(operation);
    233   if (pending_operations_.front() == operation)
    234     StartNextOperation();
    235 }
    236 
    237 void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
    238   SessionManagerOperation* operation =
    239       new LoadSettingsOperation(
    240           base::Bind(&DeviceSettingsService::HandleCompletedOperation,
    241                      weak_factory_.GetWeakPtr(),
    242                      base::Closure()));
    243   operation->set_force_key_load(force_key_load);
    244   operation->set_username(username_);
    245   operation->set_delegate(delegate_);
    246   Enqueue(operation);
    247 }
    248 
    249 void DeviceSettingsService::EnqueueSignAndStore(
    250     scoped_ptr<em::PolicyData> policy,
    251     const base::Closure& callback) {
    252   SignAndStoreSettingsOperation* operation = new SignAndStoreSettingsOperation(
    253       base::Bind(&DeviceSettingsService::HandleCompletedOperation,
    254                  weak_factory_.GetWeakPtr(),
    255                  callback),
    256       policy.Pass());
    257   operation->set_delegate(delegate_);
    258   Enqueue(operation);
    259 }
    260 
    261 void DeviceSettingsService::EnsureReload(bool force_key_load) {
    262   if (!pending_operations_.empty()) {
    263     pending_operations_.front()->set_username(username_);
    264     pending_operations_.front()->set_delegate(delegate_);
    265     pending_operations_.front()->RestartLoad(force_key_load);
    266   } else {
    267     EnqueueLoad(force_key_load);
    268   }
    269 }
    270 
    271 void DeviceSettingsService::StartNextOperation() {
    272   if (!pending_operations_.empty() &&
    273       session_manager_client_ &&
    274       owner_key_util_.get()) {
    275     pending_operations_.front()->Start(
    276         session_manager_client_, owner_key_util_, public_key_);
    277   }
    278 }
    279 
    280 void DeviceSettingsService::HandleCompletedOperation(
    281     const base::Closure& callback,
    282     SessionManagerOperation* operation,
    283     Status status) {
    284   DCHECK_EQ(operation, pending_operations_.front());
    285   store_status_ = status;
    286 
    287   OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
    288   scoped_refptr<PublicKey> new_key(operation->public_key());
    289   if (new_key.get()) {
    290     ownership_status = new_key->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
    291   } else {
    292     NOTREACHED() << "Failed to determine key status.";
    293   }
    294 
    295   bool new_owner_key = false;
    296   if (public_key_.get() != new_key.get()) {
    297     public_key_ = new_key;
    298     new_owner_key = true;
    299   }
    300 
    301   if (status == STORE_SUCCESS) {
    302     policy_data_ = operation->policy_data().Pass();
    303     device_settings_ = operation->device_settings().Pass();
    304     load_retries_left_ = kMaxLoadRetries;
    305   } else if (status != STORE_KEY_UNAVAILABLE) {
    306     LOG(ERROR) << "Session manager operation failed: " << status;
    307     // Validation errors can be temporary if the rtc has gone on holiday for a
    308     // short while. So we will retry such loads for up to 10 minutes.
    309     if (status == STORE_TEMP_VALIDATION_ERROR) {
    310       if (load_retries_left_ > 0) {
    311         load_retries_left_--;
    312         LOG(ERROR) << "A re-load has been scheduled due to a validation error.";
    313         content::BrowserThread::PostDelayedTask(
    314             content::BrowserThread::UI,
    315             FROM_HERE,
    316             base::Bind(&DeviceSettingsService::Load, base::Unretained(this)),
    317             base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs));
    318       } else {
    319         // Once we've given up retrying, the validation error is not temporary
    320         // anymore.
    321         store_status_ = STORE_VALIDATION_ERROR;
    322       }
    323     }
    324   }
    325 
    326   if (new_owner_key) {
    327     FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
    328     content::NotificationService::current()->Notify(
    329         chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
    330         content::Source<DeviceSettingsService>(this),
    331         content::NotificationService::NoDetails());
    332   }
    333 
    334   FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
    335 
    336   std::vector<OwnershipStatusCallback> callbacks;
    337   callbacks.swap(pending_ownership_status_callbacks_);
    338   for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
    339        iter != callbacks.end(); ++iter) {
    340     iter->Run(ownership_status);
    341   }
    342 
    343   // The completion callback happens after the notification so clients can
    344   // filter self-triggered updates.
    345   if (!callback.is_null())
    346     callback.Run();
    347 
    348   // Only remove the pending operation here, so new operations triggered by any
    349   // of the callbacks above are queued up properly.
    350   pending_operations_.pop_front();
    351   delete operation;
    352 
    353   StartNextOperation();
    354 }
    355 
    356 void DeviceSettingsService::HandleError(Status status,
    357                                         const base::Closure& callback) {
    358   store_status_ = status;
    359 
    360   LOG(ERROR) << "Session manager operation failed: " << status;
    361 
    362   FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
    363 
    364   // The completion callback happens after the notification so clients can
    365   // filter self-triggered updates.
    366   if (!callback.is_null())
    367     callback.Run();
    368 }
    369 
    370 scoped_ptr<em::PolicyData> DeviceSettingsService::AssemblePolicy(
    371     const em::ChromeDeviceSettingsProto& settings) const {
    372   scoped_ptr<em::PolicyData> policy(new em::PolicyData());
    373   if (policy_data_) {
    374     // Preserve management settings.
    375     if (policy_data_->has_management_mode())
    376       policy->set_management_mode(policy_data_->management_mode());
    377     if (policy_data_->has_request_token())
    378       policy->set_request_token(policy_data_->request_token());
    379     if (policy_data_->has_device_id())
    380       policy->set_device_id(policy_data_->device_id());
    381   } else {
    382     // If there's no previous policy data, this is the first time the device
    383     // setting is set. We set the management mode to NOT_MANAGED initially.
    384     policy->set_management_mode(em::PolicyData::NOT_MANAGED);
    385   }
    386   policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
    387   policy->set_timestamp((base::Time::Now() - base::Time::UnixEpoch()).
    388                         InMilliseconds());
    389   policy->set_username(username_);
    390   if (!settings.SerializeToString(policy->mutable_policy_value()))
    391     return scoped_ptr<em::PolicyData>();
    392 
    393   return policy.Pass();
    394 }
    395 
    396 em::PolicyData::ManagementMode DeviceSettingsService::GetManagementMode()
    397     const {
    398   if (policy_data_ && policy_data_->has_management_mode())
    399     return policy_data_->management_mode();
    400   return em::PolicyData::NOT_MANAGED;
    401 }
    402 
    403 bool DeviceSettingsService::CheckManagementModeTransition(
    404     em::PolicyData::ManagementMode new_mode) const {
    405   em::PolicyData::ManagementMode current_mode = GetManagementMode();
    406 
    407   // Mode is not changed.
    408   if (current_mode == new_mode)
    409     return true;
    410 
    411   switch (current_mode) {
    412     case em::PolicyData::NOT_MANAGED:
    413       // For consumer management enrollment.
    414       return new_mode == em::PolicyData::CONSUMER_MANAGED;
    415 
    416     case em::PolicyData::ENTERPRISE_MANAGED:
    417       // Management mode cannot be set when it is currently ENTERPRISE_MANAGED.
    418       return false;
    419 
    420     case em::PolicyData::CONSUMER_MANAGED:
    421       // For consumer management unenrollment.
    422       return new_mode == em::PolicyData::NOT_MANAGED;
    423   }
    424 
    425   NOTREACHED();
    426   return false;
    427 }
    428 
    429 ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
    430   DeviceSettingsService::Initialize();
    431 }
    432 
    433 ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
    434   // Clean pending operations.
    435   DeviceSettingsService::Get()->UnsetSessionManager();
    436   DeviceSettingsService::Shutdown();
    437 }
    438 
    439 }  // namespace chromeos
    440