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.
21static 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.
29static 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
43namespace policy {
44
45namespace 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.
50static const int kPolicyRefreshDeviationFactorPercent = 10;
51// Maximum deviation we are willing to accept.
52static 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.
56static const int64 kPolicyRefreshErrorDelayInMilliseconds =
57    5 * 60 * 1000;  // 5 minutes
58
59// Default value for the policy refresh rate.
60static const int kPolicyRefreshRateInMilliseconds =
61    3 * 60 * 60 * 1000;  // 3 hours.
62
63CloudPolicyController::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
81CloudPolicyController::~CloudPolicyController() {
82  token_fetcher_->RemoveObserver(this);
83  identity_strategy_->RemoveObserver(this);
84  CancelDelayedWork();
85}
86
87void 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
95void CloudPolicyController::Retry() {
96  CancelDelayedWork();
97  DoWork();
98}
99
100void CloudPolicyController::StopAutoRetry() {
101  CancelDelayedWork();
102  backend_.reset();
103}
104
105void 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
122void 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
158void CloudPolicyController::OnDeviceTokenAvailable() {
159  identity_strategy_->OnDeviceTokenAvailable(token_fetcher_->GetDeviceToken());
160}
161
162void CloudPolicyController::OnDeviceTokenChanged() {
163  if (identity_strategy_->GetDeviceToken().empty())
164    SetState(STATE_TOKEN_UNAVAILABLE);
165  else
166    SetState(STATE_TOKEN_VALID);
167}
168
169void CloudPolicyController::OnCredentialsChanged() {
170  effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_;
171  SetState(STATE_TOKEN_UNAVAILABLE);
172}
173
174CloudPolicyController::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
196void 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
230void 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
245void 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
267void CloudPolicyController::DoDelayedWork() {
268  DCHECK(delayed_work_task_);
269  delayed_work_task_ = NULL;
270  DoWork();
271}
272
273void 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
292void CloudPolicyController::CancelDelayedWork() {
293  if (delayed_work_task_) {
294    delayed_work_task_->Cancel();
295    delayed_work_task_ = NULL;
296  }
297}
298
299void 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
377int64 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