Home | History | Annotate | Download | only in policy
      1 // Copyright (c) 2011 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/policy/cloud_policy_controller.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/logging.h"
     10 #include "base/message_loop.h"
     11 #include "base/rand_util.h"
     12 #include "base/string_util.h"
     13 #include "chrome/browser/policy/cloud_policy_cache_base.h"
     14 #include "chrome/browser/policy/cloud_policy_subsystem.h"
     15 #include "chrome/browser/policy/device_management_backend.h"
     16 #include "chrome/browser/policy/device_management_service.h"
     17 #include "chrome/browser/policy/proto/device_management_constants.h"
     18 
     19 // Domain names that are known not to be managed.
     20 // We don't register the device when such a user logs in.
     21 static const char* kNonManagedDomains[] = {
     22   "@googlemail.com",
     23   "@gmail.com"
     24 };
     25 
     26 // Checks the domain part of the given username against the list of known
     27 // non-managed domain names. Returns false if |username| is empty or
     28 // in a domain known not to be managed.
     29 static bool CanBeInManagedDomain(const std::string& username) {
     30   if (username.empty()) {
     31     // This means incognito user in case of ChromiumOS and
     32     // no logged-in user in case of Chromium (SigninService).
     33     return false;
     34   }
     35   for (size_t i = 0; i < arraysize(kNonManagedDomains); i++) {
     36     if (EndsWith(username, kNonManagedDomains[i], true)) {
     37       return false;
     38     }
     39   }
     40   return true;
     41 }
     42 
     43 namespace policy {
     44 
     45 namespace em = enterprise_management;
     46 
     47 // The maximum ratio in percent of the policy refresh rate we use for adjusting
     48 // the policy refresh time instant. The rationale is to avoid load spikes from
     49 // many devices that were set up in sync for some reason.
     50 static const int kPolicyRefreshDeviationFactorPercent = 10;
     51 // Maximum deviation we are willing to accept.
     52 static const int64 kPolicyRefreshDeviationMaxInMilliseconds = 30 * 60 * 1000;
     53 
     54 // These are the base values for delays before retrying after an error. They
     55 // will be doubled each time they are used.
     56 static const int64 kPolicyRefreshErrorDelayInMilliseconds =
     57     5 * 60 * 1000;  // 5 minutes
     58 
     59 // Default value for the policy refresh rate.
     60 static const int kPolicyRefreshRateInMilliseconds =
     61     3 * 60 * 60 * 1000;  // 3 hours.
     62 
     63 CloudPolicyController::CloudPolicyController(
     64     DeviceManagementService* service,
     65     CloudPolicyCacheBase* cache,
     66     DeviceTokenFetcher* token_fetcher,
     67     CloudPolicyIdentityStrategy* identity_strategy,
     68     PolicyNotifier* notifier)
     69     : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
     70   Initialize(service,
     71              cache,
     72              token_fetcher,
     73              identity_strategy,
     74              notifier,
     75              kPolicyRefreshRateInMilliseconds,
     76              kPolicyRefreshDeviationFactorPercent,
     77              kPolicyRefreshDeviationMaxInMilliseconds,
     78              kPolicyRefreshErrorDelayInMilliseconds);
     79 }
     80 
     81 CloudPolicyController::~CloudPolicyController() {
     82   token_fetcher_->RemoveObserver(this);
     83   identity_strategy_->RemoveObserver(this);
     84   CancelDelayedWork();
     85 }
     86 
     87 void CloudPolicyController::SetRefreshRate(int64 refresh_rate_milliseconds) {
     88   policy_refresh_rate_ms_ = refresh_rate_milliseconds;
     89 
     90   // Reschedule the refresh task if necessary.
     91   if (state_ == STATE_POLICY_VALID)
     92     SetState(STATE_POLICY_VALID);
     93 }
     94 
     95 void CloudPolicyController::Retry() {
     96   CancelDelayedWork();
     97   DoWork();
     98 }
     99 
    100 void CloudPolicyController::StopAutoRetry() {
    101   CancelDelayedWork();
    102   backend_.reset();
    103 }
    104 
    105 void CloudPolicyController::HandlePolicyResponse(
    106     const em::DevicePolicyResponse& response) {
    107   if (response.response_size() > 0) {
    108     if (response.response_size() > 1) {
    109       LOG(WARNING) << "More than one policy in the response of the device "
    110                    << "management server, discarding.";
    111     }
    112     if (response.response(0).error_code() !=
    113         DeviceManagementBackend::kErrorServicePolicyNotFound) {
    114       cache_->SetPolicy(response.response(0));
    115       SetState(STATE_POLICY_VALID);
    116     } else {
    117       SetState(STATE_POLICY_UNAVAILABLE);
    118     }
    119   }
    120 }
    121 
    122 void CloudPolicyController::OnError(DeviceManagementBackend::ErrorCode code) {
    123   switch (code) {
    124     case DeviceManagementBackend::kErrorServiceDeviceNotFound:
    125     case DeviceManagementBackend::kErrorServiceManagementTokenInvalid: {
    126       LOG(WARNING) << "The device token was either invalid or unknown to the "
    127                    << "device manager, re-registering device.";
    128       // Will retry fetching a token but gracefully backing off.
    129       SetState(STATE_TOKEN_ERROR);
    130       break;
    131     }
    132     case DeviceManagementBackend::kErrorServiceManagementNotSupported: {
    133       VLOG(1) << "The device is no longer managed.";
    134       token_fetcher_->SetUnmanagedState();
    135       SetState(STATE_TOKEN_UNMANAGED);
    136       break;
    137     }
    138     case DeviceManagementBackend::kErrorServicePolicyNotFound:
    139     case DeviceManagementBackend::kErrorRequestInvalid:
    140     case DeviceManagementBackend::kErrorServiceActivationPending:
    141     case DeviceManagementBackend::kErrorResponseDecoding:
    142     case DeviceManagementBackend::kErrorHttpStatus: {
    143       VLOG(1) << "An error in the communication with the policy server occurred"
    144               << ", will retry in a few hours.";
    145       SetState(STATE_POLICY_UNAVAILABLE);
    146       break;
    147     }
    148     case DeviceManagementBackend::kErrorRequestFailed:
    149     case DeviceManagementBackend::kErrorTemporaryUnavailable: {
    150       VLOG(1) << "A temporary error in the communication with the policy server"
    151               << " occurred.";
    152       // Will retry last operation but gracefully backing off.
    153       SetState(STATE_POLICY_ERROR);
    154     }
    155   }
    156 }
    157 
    158 void CloudPolicyController::OnDeviceTokenAvailable() {
    159   identity_strategy_->OnDeviceTokenAvailable(token_fetcher_->GetDeviceToken());
    160 }
    161 
    162 void CloudPolicyController::OnDeviceTokenChanged() {
    163   if (identity_strategy_->GetDeviceToken().empty())
    164     SetState(STATE_TOKEN_UNAVAILABLE);
    165   else
    166     SetState(STATE_TOKEN_VALID);
    167 }
    168 
    169 void CloudPolicyController::OnCredentialsChanged() {
    170   effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_;
    171   SetState(STATE_TOKEN_UNAVAILABLE);
    172 }
    173 
    174 CloudPolicyController::CloudPolicyController(
    175     DeviceManagementService* service,
    176     CloudPolicyCacheBase* cache,
    177     DeviceTokenFetcher* token_fetcher,
    178     CloudPolicyIdentityStrategy* identity_strategy,
    179     PolicyNotifier* notifier,
    180     int64 policy_refresh_rate_ms,
    181     int policy_refresh_deviation_factor_percent,
    182     int64 policy_refresh_deviation_max_ms,
    183     int64 policy_refresh_error_delay_ms)
    184     : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
    185   Initialize(service,
    186              cache,
    187              token_fetcher,
    188              identity_strategy,
    189              notifier,
    190              policy_refresh_rate_ms,
    191              policy_refresh_deviation_factor_percent,
    192              policy_refresh_deviation_max_ms,
    193              policy_refresh_error_delay_ms);
    194 }
    195 
    196 void CloudPolicyController::Initialize(
    197     DeviceManagementService* service,
    198     CloudPolicyCacheBase* cache,
    199     DeviceTokenFetcher* token_fetcher,
    200     CloudPolicyIdentityStrategy* identity_strategy,
    201     PolicyNotifier* notifier,
    202     int64 policy_refresh_rate_ms,
    203     int policy_refresh_deviation_factor_percent,
    204     int64 policy_refresh_deviation_max_ms,
    205     int64 policy_refresh_error_delay_ms) {
    206   DCHECK(cache);
    207 
    208   service_ = service;
    209   cache_ = cache;
    210   token_fetcher_ = token_fetcher;
    211   identity_strategy_ = identity_strategy;
    212   notifier_ = notifier;
    213   state_ = STATE_TOKEN_UNAVAILABLE;
    214   delayed_work_task_ = NULL;
    215   policy_refresh_rate_ms_ = policy_refresh_rate_ms;
    216   policy_refresh_deviation_factor_percent_ =
    217       policy_refresh_deviation_factor_percent;
    218   policy_refresh_deviation_max_ms_ = policy_refresh_deviation_max_ms;
    219   policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
    220   effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms;
    221 
    222   token_fetcher_->AddObserver(this);
    223   identity_strategy_->AddObserver(this);
    224   if (!identity_strategy_->GetDeviceToken().empty())
    225     SetState(STATE_TOKEN_VALID);
    226   else
    227     SetState(STATE_TOKEN_UNAVAILABLE);
    228 }
    229 
    230 void CloudPolicyController::FetchToken() {
    231   std::string username;
    232   std::string auth_token;
    233   std::string device_id = identity_strategy_->GetDeviceID();
    234   std::string machine_id = identity_strategy_->GetMachineID();
    235   std::string machine_model = identity_strategy_->GetMachineModel();
    236   em::DeviceRegisterRequest_Type policy_type =
    237       identity_strategy_->GetPolicyRegisterType();
    238   if (identity_strategy_->GetCredentials(&username, &auth_token) &&
    239       CanBeInManagedDomain(username)) {
    240     token_fetcher_->FetchToken(auth_token, device_id, policy_type,
    241                                machine_id, machine_model);
    242   }
    243 }
    244 
    245 void CloudPolicyController::SendPolicyRequest() {
    246   backend_.reset(service_->CreateBackend());
    247   DCHECK(!identity_strategy_->GetDeviceToken().empty());
    248   em::DevicePolicyRequest policy_request;
    249   em::PolicyFetchRequest* fetch_request = policy_request.add_request();
    250   fetch_request->set_signature_type(em::PolicyFetchRequest::SHA1_RSA);
    251   fetch_request->set_policy_type(identity_strategy_->GetPolicyType());
    252   if (!cache_->is_unmanaged() &&
    253       !cache_->last_policy_refresh_time().is_null()) {
    254     base::TimeDelta timestamp =
    255         cache_->last_policy_refresh_time() - base::Time::UnixEpoch();
    256     fetch_request->set_timestamp(timestamp.InMilliseconds());
    257   }
    258   int key_version = 0;
    259   if (cache_->GetPublicKeyVersion(&key_version))
    260     fetch_request->set_public_key_version(key_version);
    261 
    262   backend_->ProcessPolicyRequest(identity_strategy_->GetDeviceToken(),
    263                                  identity_strategy_->GetDeviceID(),
    264                                  policy_request, this);
    265 }
    266 
    267 void CloudPolicyController::DoDelayedWork() {
    268   DCHECK(delayed_work_task_);
    269   delayed_work_task_ = NULL;
    270   DoWork();
    271 }
    272 
    273 void CloudPolicyController::DoWork() {
    274   switch (state_) {
    275     case STATE_TOKEN_UNAVAILABLE:
    276     case STATE_TOKEN_ERROR:
    277       FetchToken();
    278       return;
    279     case STATE_TOKEN_VALID:
    280     case STATE_POLICY_VALID:
    281     case STATE_POLICY_ERROR:
    282     case STATE_POLICY_UNAVAILABLE:
    283       SendPolicyRequest();
    284       return;
    285     case STATE_TOKEN_UNMANAGED:
    286       return;
    287   }
    288 
    289   NOTREACHED() << "Unhandled state" << state_;
    290 }
    291 
    292 void CloudPolicyController::CancelDelayedWork() {
    293   if (delayed_work_task_) {
    294     delayed_work_task_->Cancel();
    295     delayed_work_task_ = NULL;
    296   }
    297 }
    298 
    299 void CloudPolicyController::SetState(
    300     CloudPolicyController::ControllerState new_state) {
    301   state_ = new_state;
    302   backend_.reset();  // Discard any pending requests.
    303 
    304   base::Time now(base::Time::NowFromSystemTime());
    305   base::Time refresh_at;
    306   base::Time last_refresh(cache_->last_policy_refresh_time());
    307   if (last_refresh.is_null())
    308     last_refresh = now;
    309 
    310   // Determine when to take the next step.
    311   bool inform_notifier_done = false;
    312   switch (state_) {
    313     case STATE_TOKEN_UNMANAGED:
    314       notifier_->Inform(CloudPolicySubsystem::UNMANAGED,
    315                         CloudPolicySubsystem::NO_DETAILS,
    316                         PolicyNotifier::POLICY_CONTROLLER);
    317       break;
    318     case STATE_TOKEN_UNAVAILABLE:
    319       // The controller is not yet initialized and needs to immediately fetch
    320       // token and policy if present.
    321     case STATE_TOKEN_VALID:
    322       // Immediately try to fetch the token on initialization or policy after a
    323       // token update. Subsequent retries will respect the back-off strategy.
    324       refresh_at = now;
    325       // |notifier_| isn't informed about anything at this point, we wait for
    326       // the result of the next action first.
    327       break;
    328     case STATE_POLICY_VALID:
    329       // Delay is only reset if the policy fetch operation was successful. This
    330       // will ensure the server won't get overloaded with retries in case of
    331       // a bug on either side.
    332       effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_;
    333       refresh_at =
    334           last_refresh + base::TimeDelta::FromMilliseconds(GetRefreshDelay());
    335       notifier_->Inform(CloudPolicySubsystem::SUCCESS,
    336                         CloudPolicySubsystem::NO_DETAILS,
    337                         PolicyNotifier::POLICY_CONTROLLER);
    338       break;
    339     case STATE_TOKEN_ERROR:
    340       notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
    341                         CloudPolicySubsystem::BAD_DMTOKEN,
    342                         PolicyNotifier::POLICY_CONTROLLER);
    343       inform_notifier_done = true;
    344     case STATE_POLICY_ERROR:
    345       if (!inform_notifier_done) {
    346         notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
    347                           CloudPolicySubsystem::POLICY_NETWORK_ERROR,
    348                           PolicyNotifier::POLICY_CONTROLLER);
    349       }
    350       refresh_at = now + base::TimeDelta::FromMilliseconds(
    351                              effective_policy_refresh_error_delay_ms_);
    352       effective_policy_refresh_error_delay_ms_ =
    353           std::min(effective_policy_refresh_error_delay_ms_ * 2,
    354                    policy_refresh_rate_ms_);
    355       break;
    356     case STATE_POLICY_UNAVAILABLE:
    357       effective_policy_refresh_error_delay_ms_ = policy_refresh_rate_ms_;
    358       refresh_at = now + base::TimeDelta::FromMilliseconds(
    359                              effective_policy_refresh_error_delay_ms_);
    360       notifier_->Inform(CloudPolicySubsystem::NETWORK_ERROR,
    361                         CloudPolicySubsystem::POLICY_NETWORK_ERROR,
    362                         PolicyNotifier::POLICY_CONTROLLER);
    363       break;
    364   }
    365 
    366   // Update the delayed work task.
    367   CancelDelayedWork();
    368   if (!refresh_at.is_null()) {
    369     int64 delay = std::max<int64>((refresh_at - now).InMilliseconds(), 0);
    370     delayed_work_task_ = method_factory_.NewRunnableMethod(
    371         &CloudPolicyController::DoDelayedWork);
    372     MessageLoop::current()->PostDelayedTask(FROM_HERE, delayed_work_task_,
    373                                             delay);
    374   }
    375 }
    376 
    377 int64 CloudPolicyController::GetRefreshDelay() {
    378   int64 deviation = (policy_refresh_deviation_factor_percent_ *
    379                      policy_refresh_rate_ms_) / 100;
    380   deviation = std::min(deviation, policy_refresh_deviation_max_ms_);
    381   return policy_refresh_rate_ms_ - base::RandGenerator(deviation + 1);
    382 }
    383 
    384 }  // namespace policy
    385