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