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
~Observer()39 DeviceSettingsService::Observer::~Observer() {}
40
41 static DeviceSettingsService* g_device_settings_service = NULL;
42
43 // static
Initialize()44 void DeviceSettingsService::Initialize() {
45 CHECK(!g_device_settings_service);
46 g_device_settings_service = new DeviceSettingsService();
47 }
48
49 // static
IsInitialized()50 bool DeviceSettingsService::IsInitialized() {
51 return g_device_settings_service;
52 }
53
54 // static
Shutdown()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
Get()62 DeviceSettingsService* DeviceSettingsService::Get() {
63 CHECK(g_device_settings_service);
64 return g_device_settings_service;
65 }
66
DeviceSettingsService()67 DeviceSettingsService::DeviceSettingsService()
68 : session_manager_client_(NULL),
69 store_status_(STORE_SUCCESS),
70 load_retries_left_(kMaxLoadRetries),
71 weak_factory_(this) {
72 }
73
~DeviceSettingsService()74 DeviceSettingsService::~DeviceSettingsService() {
75 DCHECK(pending_operations_.empty());
76 }
77
SetSessionManager(SessionManagerClient * session_manager_client,scoped_refptr<OwnerKeyUtil> owner_key_util)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
UnsetSessionManager()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
GetPublicKey()105 scoped_refptr<PublicKey> DeviceSettingsService::GetPublicKey() {
106 return public_key_;
107 }
108
Load()109 void DeviceSettingsService::Load() {
110 EnqueueLoad(false);
111 }
112
SignAndStore(scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,const base::Closure & callback)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
SetManagementSettings(em::PolicyData::ManagementMode management_mode,const std::string & request_token,const std::string & device_id,const base::Closure & callback)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
Store(scoped_ptr<em::PolicyFetchResponse> policy,const base::Closure & callback)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
GetOwnershipStatus()161 DeviceSettingsService::GetOwnershipStatus() {
162 if (public_key_)
163 return public_key_->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
164 return OWNERSHIP_UNKNOWN;
165 }
166
GetOwnershipStatusAsync(const OwnershipStatusCallback & callback)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
HasPrivateOwnerKey()183 bool DeviceSettingsService::HasPrivateOwnerKey() {
184 return delegate_ && delegate_->IsOwner();
185 }
186
InitOwner(const std::string & username,const base::WeakPtr<PrivateKeyDelegate> & delegate)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
GetUsername() const200 const std::string& DeviceSettingsService::GetUsername() const {
201 return username_;
202 }
203
AddObserver(Observer * observer)204 void DeviceSettingsService::AddObserver(Observer* observer) {
205 observers_.AddObserver(observer);
206 }
207
RemoveObserver(Observer * observer)208 void DeviceSettingsService::RemoveObserver(Observer* observer) {
209 observers_.RemoveObserver(observer);
210 }
211
OwnerKeySet(bool success)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
PropertyChangeComplete(bool success)222 void DeviceSettingsService::PropertyChangeComplete(bool success) {
223 if (!success) {
224 LOG(ERROR) << "Policy update failed.";
225 return;
226 }
227
228 EnsureReload(false);
229 }
230
Enqueue(SessionManagerOperation * operation)231 void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
232 pending_operations_.push_back(operation);
233 if (pending_operations_.front() == operation)
234 StartNextOperation();
235 }
236
EnqueueLoad(bool force_key_load)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
EnqueueSignAndStore(scoped_ptr<em::PolicyData> policy,const base::Closure & callback)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
EnsureReload(bool force_key_load)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
StartNextOperation()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
HandleCompletedOperation(const base::Closure & callback,SessionManagerOperation * operation,Status status)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
HandleError(Status status,const base::Closure & callback)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
AssemblePolicy(const em::ChromeDeviceSettingsProto & settings) const370 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
GetManagementMode() const396 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
CheckManagementModeTransition(em::PolicyData::ManagementMode new_mode) const403 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
ScopedTestDeviceSettingsService()429 ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
430 DeviceSettingsService::Initialize();
431 }
432
~ScopedTestDeviceSettingsService()433 ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
434 // Clean pending operations.
435 DeviceSettingsService::Get()->UnsetSessionManager();
436 DeviceSettingsService::Shutdown();
437 }
438
439 } // namespace chromeos
440