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 "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
13 #include "chrome/browser/chromeos/settings/owner_key_util.h"
14 #include "chrome/browser/chromeos/settings/session_manager_operation.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_source.h"
18 #include "crypto/rsa_private_key.h"
19 #include "policy/proto/device_management_backend.pb.h"
20
21 namespace em = enterprise_management;
22
23 namespace {
24
25 // Delay between load retries when there was a validation error.
26 // NOTE: This code is here to mitigate clock loss on some devices where policy
27 // loads will fail with a validation error caused by RTC clock bing reset when
28 // the battery is drained.
29 int kLoadRetryDelayMs = 1000 * 5;
30 // Maximal number of retries before we give up. Calculated to allow for 10 min
31 // of retry time.
32 int kMaxLoadRetries = (1000 * 60 * 10) / kLoadRetryDelayMs;
33
34 } // namespace
35
36 namespace chromeos {
37
OwnerKey(scoped_ptr<std::vector<uint8>> public_key,scoped_ptr<crypto::RSAPrivateKey> private_key)38 OwnerKey::OwnerKey(scoped_ptr<std::vector<uint8> > public_key,
39 scoped_ptr<crypto::RSAPrivateKey> private_key)
40 : public_key_(public_key.Pass()),
41 private_key_(private_key.Pass()) {}
42
~OwnerKey()43 OwnerKey::~OwnerKey() {}
44
~Observer()45 DeviceSettingsService::Observer::~Observer() {}
46
47 static DeviceSettingsService* g_device_settings_service = NULL;
48
49 // static
Initialize()50 void DeviceSettingsService::Initialize() {
51 CHECK(!g_device_settings_service);
52 g_device_settings_service = new DeviceSettingsService();
53 }
54
55 // static
IsInitialized()56 bool DeviceSettingsService::IsInitialized() {
57 return g_device_settings_service;
58 }
59
60 // static
Shutdown()61 void DeviceSettingsService::Shutdown() {
62 DCHECK(g_device_settings_service);
63 delete g_device_settings_service;
64 g_device_settings_service = NULL;
65 }
66
67 // static
Get()68 DeviceSettingsService* DeviceSettingsService::Get() {
69 CHECK(g_device_settings_service);
70 return g_device_settings_service;
71 }
72
DeviceSettingsService()73 DeviceSettingsService::DeviceSettingsService()
74 : session_manager_client_(NULL),
75 weak_factory_(this),
76 store_status_(STORE_SUCCESS),
77 certificates_loaded_(false),
78 owner_key_loaded_with_certificates_(false),
79 load_retries_left_(kMaxLoadRetries) {
80 if (CertLoader::IsInitialized()) {
81 certificates_loaded_ = CertLoader::Get()->certificates_loaded();
82 CertLoader::Get()->AddObserver(this);
83 }
84 }
85
~DeviceSettingsService()86 DeviceSettingsService::~DeviceSettingsService() {
87 DCHECK(pending_operations_.empty());
88 if (CertLoader::IsInitialized())
89 CertLoader::Get()->RemoveObserver(this);
90 }
91
SetSessionManager(SessionManagerClient * session_manager_client,scoped_refptr<OwnerKeyUtil> owner_key_util)92 void DeviceSettingsService::SetSessionManager(
93 SessionManagerClient* session_manager_client,
94 scoped_refptr<OwnerKeyUtil> owner_key_util) {
95 DCHECK(session_manager_client);
96 DCHECK(owner_key_util.get());
97 DCHECK(!session_manager_client_);
98 DCHECK(!owner_key_util_.get());
99
100 session_manager_client_ = session_manager_client;
101 owner_key_util_ = owner_key_util;
102
103 session_manager_client_->AddObserver(this);
104
105 StartNextOperation();
106 }
107
UnsetSessionManager()108 void DeviceSettingsService::UnsetSessionManager() {
109 STLDeleteContainerPointers(pending_operations_.begin(),
110 pending_operations_.end());
111 pending_operations_.clear();
112
113 if (session_manager_client_)
114 session_manager_client_->RemoveObserver(this);
115 session_manager_client_ = NULL;
116 owner_key_util_ = NULL;
117 }
118
GetOwnerKey()119 scoped_refptr<OwnerKey> DeviceSettingsService::GetOwnerKey() {
120 return owner_key_;
121 }
122
Load()123 void DeviceSettingsService::Load() {
124 EnqueueLoad(false);
125 }
126
SignAndStore(scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,const base::Closure & callback)127 void DeviceSettingsService::SignAndStore(
128 scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,
129 const base::Closure& callback) {
130 Enqueue(
131 new SignAndStoreSettingsOperation(
132 base::Bind(&DeviceSettingsService::HandleCompletedOperation,
133 weak_factory_.GetWeakPtr(),
134 callback),
135 new_settings.Pass(),
136 username_));
137 }
138
Store(scoped_ptr<em::PolicyFetchResponse> policy,const base::Closure & callback)139 void DeviceSettingsService::Store(scoped_ptr<em::PolicyFetchResponse> policy,
140 const base::Closure& callback) {
141 Enqueue(
142 new StoreSettingsOperation(
143 base::Bind(&DeviceSettingsService::HandleCompletedOperation,
144 weak_factory_.GetWeakPtr(),
145 callback),
146 policy.Pass()));
147 }
148
149 DeviceSettingsService::OwnershipStatus
GetOwnershipStatus()150 DeviceSettingsService::GetOwnershipStatus() {
151 if (owner_key_.get())
152 return owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
153
154 return OWNERSHIP_UNKNOWN;
155 }
156
GetOwnershipStatusAsync(const OwnershipStatusCallback & callback)157 void DeviceSettingsService::GetOwnershipStatusAsync(
158 const OwnershipStatusCallback& callback) {
159 if (owner_key_.get()) {
160 // If there is a key, report status immediately.
161 base::MessageLoop::current()->PostTask(
162 FROM_HERE,
163 base::Bind(
164 callback,
165 owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE));
166 } else {
167 // If the key hasn't been loaded yet, enqueue the callback to be fired when
168 // the next SessionManagerOperation completes. If no operation is pending,
169 // start a load operation to fetch the key and report the result.
170 pending_ownership_status_callbacks_.push_back(callback);
171 if (pending_operations_.empty())
172 EnqueueLoad(false);
173 }
174 }
175
HasPrivateOwnerKey()176 bool DeviceSettingsService::HasPrivateOwnerKey() {
177 return owner_key_.get() && owner_key_->private_key();
178 }
179
IsCurrentUserOwnerAsync(const IsCurrentUserOwnerCallback & callback)180 void DeviceSettingsService::IsCurrentUserOwnerAsync(
181 const IsCurrentUserOwnerCallback& callback) {
182 if (owner_key_loaded_with_certificates_) {
183 // If the current owner key was loaded while the certificates were loaded,
184 // or the certificate loader is not initialized, in which case the private
185 // key cannot be set, report status immediately.
186 base::MessageLoop::current()->PostTask(
187 FROM_HERE,
188 base::Bind(callback, HasPrivateOwnerKey()));
189 } else {
190 // If the key hasn't been loaded with the known certificates, enqueue the
191 // callback to be fired when the next SessionManagerOperation completes in
192 // an environment where the certificates are loaded. There is no need to
193 // start a new operation, as the reload operation will be started when the
194 // certificates are loaded.
195 pending_is_current_user_owner_callbacks_.push_back(callback);
196 }
197 }
198
SetUsername(const std::string & username)199 void DeviceSettingsService::SetUsername(const std::string& username) {
200 username_ = username;
201
202 // The private key may have become available, so force a key reload.
203 owner_key_ = NULL;
204 EnsureReload(true);
205 }
206
GetUsername() const207 const std::string& DeviceSettingsService::GetUsername() const {
208 return username_;
209 }
210
AddObserver(Observer * observer)211 void DeviceSettingsService::AddObserver(Observer* observer) {
212 observers_.AddObserver(observer);
213 }
214
RemoveObserver(Observer * observer)215 void DeviceSettingsService::RemoveObserver(Observer* observer) {
216 observers_.RemoveObserver(observer);
217 }
218
OwnerKeySet(bool success)219 void DeviceSettingsService::OwnerKeySet(bool success) {
220 if (!success) {
221 LOG(ERROR) << "Owner key change failed.";
222 return;
223 }
224
225 owner_key_ = NULL;
226 EnsureReload(true);
227 }
228
PropertyChangeComplete(bool success)229 void DeviceSettingsService::PropertyChangeComplete(bool success) {
230 if (!success) {
231 LOG(ERROR) << "Policy update failed.";
232 return;
233 }
234
235 EnsureReload(false);
236 }
237
OnCertificatesLoaded(const net::CertificateList & cert_list,bool initial_load)238 void DeviceSettingsService::OnCertificatesLoaded(
239 const net::CertificateList& cert_list,
240 bool initial_load) {
241 certificates_loaded_ = true;
242 // CertLoader initializes the TPM and NSS database which is necessary to
243 // determine ownership. Force a reload once we know these are initialized.
244 EnsureReload(true);
245 }
246
Enqueue(SessionManagerOperation * operation)247 void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
248 pending_operations_.push_back(operation);
249 if (pending_operations_.front() == operation)
250 StartNextOperation();
251 }
252
EnqueueLoad(bool force_key_load)253 void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
254 SessionManagerOperation* operation =
255 new LoadSettingsOperation(
256 base::Bind(&DeviceSettingsService::HandleCompletedOperation,
257 weak_factory_.GetWeakPtr(),
258 base::Closure()));
259 operation->set_force_key_load(force_key_load);
260 Enqueue(operation);
261 }
262
EnsureReload(bool force_key_load)263 void DeviceSettingsService::EnsureReload(bool force_key_load) {
264 if (!pending_operations_.empty())
265 pending_operations_.front()->RestartLoad(force_key_load);
266 else
267 EnqueueLoad(force_key_load);
268 }
269
StartNextOperation()270 void DeviceSettingsService::StartNextOperation() {
271 if (!pending_operations_.empty() &&
272 session_manager_client_ &&
273 owner_key_util_.get()) {
274 pending_operations_.front()->Start(session_manager_client_,
275 owner_key_util_, owner_key_);
276 }
277 }
278
HandleCompletedOperation(const base::Closure & callback,SessionManagerOperation * operation,Status status)279 void DeviceSettingsService::HandleCompletedOperation(
280 const base::Closure& callback,
281 SessionManagerOperation* operation,
282 Status status) {
283 DCHECK_EQ(operation, pending_operations_.front());
284 store_status_ = status;
285
286 OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
287 bool is_owner = false;
288 scoped_refptr<OwnerKey> new_key(operation->owner_key());
289 if (new_key.get()) {
290 ownership_status =
291 new_key->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
292 is_owner = (new_key->private_key() != NULL);
293 } else {
294 NOTREACHED() << "Failed to determine key status.";
295 }
296
297 bool new_owner_key = false;
298 if (owner_key_.get() != new_key.get()) {
299 owner_key_ = new_key;
300 new_owner_key = true;
301 }
302
303 if (status == STORE_SUCCESS) {
304 policy_data_ = operation->policy_data().Pass();
305 device_settings_ = operation->device_settings().Pass();
306 load_retries_left_ = kMaxLoadRetries;
307 } else if (status != STORE_KEY_UNAVAILABLE) {
308 LOG(ERROR) << "Session manager operation failed: " << status;
309 // Validation errors can be temprary if the rtc has went on holiday for a
310 // short while. So we will retry such loads for up to 10 minutes.
311 if (status == STORE_TEMP_VALIDATION_ERROR) {
312 if (load_retries_left_ > 0) {
313 load_retries_left_--;
314 LOG(ERROR) << "A re-load has been scheduled due to a validation error.";
315 content::BrowserThread::PostDelayedTask(
316 content::BrowserThread::UI,
317 FROM_HERE,
318 base::Bind(&DeviceSettingsService::Load, base::Unretained(this)),
319 base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs));
320 }
321 }
322 }
323
324 if (new_owner_key) {
325 FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
326 content::NotificationService::current()->Notify(
327 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
328 content::Source<DeviceSettingsService>(this),
329 content::NotificationService::NoDetails());
330 }
331
332 FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
333
334 std::vector<OwnershipStatusCallback> callbacks;
335 callbacks.swap(pending_ownership_status_callbacks_);
336 for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
337 iter != callbacks.end(); ++iter) {
338 iter->Run(ownership_status);
339 }
340
341 if (certificates_loaded_) {
342 owner_key_loaded_with_certificates_ = true;
343 std::vector<IsCurrentUserOwnerCallback> is_owner_callbacks;
344 is_owner_callbacks.swap(pending_is_current_user_owner_callbacks_);
345 for (std::vector<IsCurrentUserOwnerCallback>::iterator iter(
346 is_owner_callbacks.begin());
347 iter != is_owner_callbacks.end(); ++iter) {
348 iter->Run(is_owner);
349 }
350 }
351
352 // The completion callback happens after the notification so clients can
353 // filter self-triggered updates.
354 if (!callback.is_null())
355 callback.Run();
356
357 // Only remove the pending operation here, so new operations triggered by any
358 // of the callbacks above are queued up properly.
359 pending_operations_.pop_front();
360 delete operation;
361
362 StartNextOperation();
363 }
364
ScopedTestDeviceSettingsService()365 ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
366 DeviceSettingsService::Initialize();
367 }
368
~ScopedTestDeviceSettingsService()369 ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
370 DeviceSettingsService::Shutdown();
371 }
372
373 } // namespace chromeos
374