• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
CanBeInManagedDomain(const std::string & username)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 
CloudPolicyController(DeviceManagementService * service,CloudPolicyCacheBase * cache,DeviceTokenFetcher * token_fetcher,CloudPolicyIdentityStrategy * identity_strategy,PolicyNotifier * notifier)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 
~CloudPolicyController()81 CloudPolicyController::~CloudPolicyController() {
82   token_fetcher_->RemoveObserver(this);
83   identity_strategy_->RemoveObserver(this);
84   CancelDelayedWork();
85 }
86 
SetRefreshRate(int64 refresh_rate_milliseconds)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 
Retry()95 void CloudPolicyController::Retry() {
96   CancelDelayedWork();
97   DoWork();
98 }
99 
StopAutoRetry()100 void CloudPolicyController::StopAutoRetry() {
101   CancelDelayedWork();
102   backend_.reset();
103 }
104 
HandlePolicyResponse(const em::DevicePolicyResponse & response)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 
OnError(DeviceManagementBackend::ErrorCode code)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 
OnDeviceTokenAvailable()158 void CloudPolicyController::OnDeviceTokenAvailable() {
159   identity_strategy_->OnDeviceTokenAvailable(token_fetcher_->GetDeviceToken());
160 }
161 
OnDeviceTokenChanged()162 void CloudPolicyController::OnDeviceTokenChanged() {
163   if (identity_strategy_->GetDeviceToken().empty())
164     SetState(STATE_TOKEN_UNAVAILABLE);
165   else
166     SetState(STATE_TOKEN_VALID);
167 }
168 
OnCredentialsChanged()169 void CloudPolicyController::OnCredentialsChanged() {
170   effective_policy_refresh_error_delay_ms_ = policy_refresh_error_delay_ms_;
171   SetState(STATE_TOKEN_UNAVAILABLE);
172 }
173 
CloudPolicyController(DeviceManagementService * service,CloudPolicyCacheBase * cache,DeviceTokenFetcher * token_fetcher,CloudPolicyIdentityStrategy * identity_strategy,PolicyNotifier * notifier,int64 policy_refresh_rate_ms,int policy_refresh_deviation_factor_percent,int64 policy_refresh_deviation_max_ms,int64 policy_refresh_error_delay_ms)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 
Initialize(DeviceManagementService * service,CloudPolicyCacheBase * cache,DeviceTokenFetcher * token_fetcher,CloudPolicyIdentityStrategy * identity_strategy,PolicyNotifier * notifier,int64 policy_refresh_rate_ms,int policy_refresh_deviation_factor_percent,int64 policy_refresh_deviation_max_ms,int64 policy_refresh_error_delay_ms)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 
FetchToken()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 
SendPolicyRequest()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 
DoDelayedWork()267 void CloudPolicyController::DoDelayedWork() {
268   DCHECK(delayed_work_task_);
269   delayed_work_task_ = NULL;
270   DoWork();
271 }
272 
DoWork()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 
CancelDelayedWork()292 void CloudPolicyController::CancelDelayedWork() {
293   if (delayed_work_task_) {
294     delayed_work_task_->Cancel();
295     delayed_work_task_ = NULL;
296   }
297 }
298 
SetState(CloudPolicyController::ControllerState new_state)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 
GetRefreshDelay()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