device_settings_service.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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
22namespace em = enterprise_management;
23
24namespace {
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.
30int kLoadRetryDelayMs = 1000 * 5;
31// Maximal number of retries before we give up. Calculated to allow for 10 min
32// of retry time.
33int kMaxLoadRetries = (1000 * 60 * 10) / kLoadRetryDelayMs;
34
35}  // namespace
36
37namespace chromeos {
38
39OwnerKey::OwnerKey(scoped_ptr<std::vector<uint8> > public_key,
40                   scoped_ptr<crypto::RSAPrivateKey> private_key)
41    : public_key_(public_key.Pass()),
42      private_key_(private_key.Pass()) {}
43
44OwnerKey::~OwnerKey() {}
45
46DeviceSettingsService::Observer::~Observer() {}
47
48static DeviceSettingsService* g_device_settings_service = NULL;
49
50// static
51void DeviceSettingsService::Initialize() {
52  CHECK(!g_device_settings_service);
53  g_device_settings_service = new DeviceSettingsService();
54}
55
56// static
57bool DeviceSettingsService::IsInitialized() {
58  return g_device_settings_service;
59}
60
61// static
62void DeviceSettingsService::Shutdown() {
63  DCHECK(g_device_settings_service);
64  delete g_device_settings_service;
65  g_device_settings_service = NULL;
66}
67
68// static
69DeviceSettingsService* DeviceSettingsService::Get() {
70  CHECK(g_device_settings_service);
71  return g_device_settings_service;
72}
73
74DeviceSettingsService::DeviceSettingsService()
75    : session_manager_client_(NULL),
76      store_status_(STORE_SUCCESS),
77      waiting_for_tpm_token_(true),
78      owner_key_loaded_with_tpm_token_(false),
79      load_retries_left_(kMaxLoadRetries),
80      weak_factory_(this) {
81  if (TPMTokenLoader::IsInitialized()) {
82    waiting_for_tpm_token_ = !TPMTokenLoader::Get()->IsTPMTokenReady();
83    TPMTokenLoader::Get()->AddObserver(this);
84  }
85}
86
87DeviceSettingsService::~DeviceSettingsService() {
88  DCHECK(pending_operations_.empty());
89  if (TPMTokenLoader::IsInitialized())
90    TPMTokenLoader::Get()->RemoveObserver(this);
91}
92
93void DeviceSettingsService::SetSessionManager(
94    SessionManagerClient* session_manager_client,
95    scoped_refptr<OwnerKeyUtil> owner_key_util) {
96  DCHECK(session_manager_client);
97  DCHECK(owner_key_util.get());
98  DCHECK(!session_manager_client_);
99  DCHECK(!owner_key_util_.get());
100
101  session_manager_client_ = session_manager_client;
102  owner_key_util_ = owner_key_util;
103
104  session_manager_client_->AddObserver(this);
105
106  StartNextOperation();
107}
108
109void DeviceSettingsService::UnsetSessionManager() {
110  STLDeleteContainerPointers(pending_operations_.begin(),
111                             pending_operations_.end());
112  pending_operations_.clear();
113
114  if (session_manager_client_)
115    session_manager_client_->RemoveObserver(this);
116  session_manager_client_ = NULL;
117  owner_key_util_ = NULL;
118}
119
120scoped_refptr<OwnerKey> DeviceSettingsService::GetOwnerKey() {
121  return owner_key_;
122}
123
124void DeviceSettingsService::Load() {
125  EnqueueLoad(false);
126}
127
128void DeviceSettingsService::SignAndStore(
129    scoped_ptr<em::ChromeDeviceSettingsProto> new_settings,
130    const base::Closure& callback) {
131  scoped_ptr<em::PolicyData> new_policy = AssemblePolicy(*new_settings);
132  if (!new_policy) {
133    HandleError(STORE_POLICY_ERROR, callback);
134    return;
135  }
136
137  Enqueue(
138      new SignAndStoreSettingsOperation(
139          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
140                     weak_factory_.GetWeakPtr(),
141                     callback),
142          new_policy.Pass()));
143}
144
145void DeviceSettingsService::SetManagementSettings(
146    em::PolicyData::ManagementMode management_mode,
147    const std::string& request_token,
148    const std::string& device_id,
149    const base::Closure& callback) {
150  if (!CheckManagementModeTransition(management_mode)) {
151    LOG(ERROR) << "Invalid management mode transition: current mode = "
152               << GetManagementMode() << ", new mode = " << management_mode;
153    HandleError(STORE_POLICY_ERROR, callback);
154    return;
155  }
156
157  scoped_ptr<em::PolicyData> policy = AssemblePolicy(*device_settings_);
158  if (!policy) {
159    HandleError(STORE_POLICY_ERROR, callback);
160    return;
161  }
162
163  policy->set_management_mode(management_mode);
164  policy->set_request_token(request_token);
165  policy->set_device_id(device_id);
166
167  Enqueue(
168      new SignAndStoreSettingsOperation(
169          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
170                     weak_factory_.GetWeakPtr(),
171                     callback),
172          policy.Pass()));
173}
174
175void DeviceSettingsService::Store(scoped_ptr<em::PolicyFetchResponse> policy,
176                                  const base::Closure& callback) {
177  Enqueue(
178      new StoreSettingsOperation(
179          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
180                     weak_factory_.GetWeakPtr(),
181                     callback),
182          policy.Pass()));
183}
184
185DeviceSettingsService::OwnershipStatus
186    DeviceSettingsService::GetOwnershipStatus() {
187  if (owner_key_.get())
188    return owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
189
190  return OWNERSHIP_UNKNOWN;
191}
192
193void DeviceSettingsService::GetOwnershipStatusAsync(
194    const OwnershipStatusCallback& callback) {
195  if (owner_key_.get()) {
196    // If there is a key, report status immediately.
197    base::MessageLoop::current()->PostTask(
198        FROM_HERE,
199        base::Bind(
200            callback,
201            owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE));
202  } else {
203    // If the key hasn't been loaded yet, enqueue the callback to be fired when
204    // the next SessionManagerOperation completes. If no operation is pending,
205    // start a load operation to fetch the key and report the result.
206    pending_ownership_status_callbacks_.push_back(callback);
207    if (pending_operations_.empty())
208      EnqueueLoad(false);
209  }
210}
211
212bool DeviceSettingsService::HasPrivateOwnerKey() {
213  return owner_key_.get() && owner_key_->private_key();
214}
215
216void DeviceSettingsService::IsCurrentUserOwnerAsync(
217    const IsCurrentUserOwnerCallback& callback) {
218  if (owner_key_loaded_with_tpm_token_) {
219    // If the current owner key was loaded while the certificates were loaded,
220    // or the certificate loader is not initialized, in which case the private
221    // key cannot be set, report status immediately.
222    base::MessageLoop::current()->PostTask(
223        FROM_HERE,
224        base::Bind(callback, HasPrivateOwnerKey()));
225  } else {
226    // If the key hasn't been loaded with the known certificates, enqueue the
227    // callback to be fired when the next SessionManagerOperation completes in
228    // an environment where the certificates are loaded. There is no need to
229    // start a new operation, as the reload operation will be started when the
230    // certificates are loaded.
231    pending_is_current_user_owner_callbacks_.push_back(callback);
232  }
233}
234
235void DeviceSettingsService::SetUsername(const std::string& username) {
236  username_ = username;
237
238  // The private key may have become available, so force a key reload.
239  owner_key_ = NULL;
240  EnsureReload(true);
241}
242
243const std::string& DeviceSettingsService::GetUsername() const {
244  return username_;
245}
246
247void DeviceSettingsService::AddObserver(Observer* observer) {
248  observers_.AddObserver(observer);
249}
250
251void DeviceSettingsService::RemoveObserver(Observer* observer) {
252  observers_.RemoveObserver(observer);
253}
254
255void DeviceSettingsService::OwnerKeySet(bool success) {
256  if (!success) {
257    LOG(ERROR) << "Owner key change failed.";
258    return;
259  }
260
261  owner_key_ = NULL;
262  EnsureReload(true);
263}
264
265void DeviceSettingsService::PropertyChangeComplete(bool success) {
266  if (!success) {
267    LOG(ERROR) << "Policy update failed.";
268    return;
269  }
270
271  EnsureReload(false);
272}
273
274void DeviceSettingsService::OnTPMTokenReady() {
275  waiting_for_tpm_token_ = false;
276
277  // TPMTokenLoader initializes the TPM and NSS database which is necessary to
278  // determine ownership. Force a reload once we know these are initialized.
279  EnsureReload(true);
280}
281
282void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
283  pending_operations_.push_back(operation);
284  if (pending_operations_.front() == operation)
285    StartNextOperation();
286}
287
288void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
289  SessionManagerOperation* operation =
290      new LoadSettingsOperation(
291          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
292                     weak_factory_.GetWeakPtr(),
293                     base::Closure()));
294  operation->set_force_key_load(force_key_load);
295  Enqueue(operation);
296}
297
298void DeviceSettingsService::EnsureReload(bool force_key_load) {
299  if (!pending_operations_.empty())
300    pending_operations_.front()->RestartLoad(force_key_load);
301  else
302    EnqueueLoad(force_key_load);
303}
304
305void DeviceSettingsService::StartNextOperation() {
306  if (!pending_operations_.empty() &&
307      session_manager_client_ &&
308      owner_key_util_.get()) {
309    pending_operations_.front()->Start(session_manager_client_,
310                                       owner_key_util_, owner_key_);
311  }
312}
313
314void DeviceSettingsService::HandleCompletedOperation(
315    const base::Closure& callback,
316    SessionManagerOperation* operation,
317    Status status) {
318  DCHECK_EQ(operation, pending_operations_.front());
319  store_status_ = status;
320
321  OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
322  bool is_owner = false;
323  scoped_refptr<OwnerKey> new_key(operation->owner_key());
324  if (new_key.get()) {
325    ownership_status =
326        new_key->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
327    is_owner = (new_key->private_key() != NULL);
328  } else {
329    NOTREACHED() << "Failed to determine key status.";
330  }
331
332  bool new_owner_key = false;
333  if (owner_key_.get() != new_key.get()) {
334    owner_key_ = new_key;
335    new_owner_key = true;
336  }
337
338  if (status == STORE_SUCCESS) {
339    policy_data_ = operation->policy_data().Pass();
340    device_settings_ = operation->device_settings().Pass();
341    load_retries_left_ = kMaxLoadRetries;
342  } else if (status != STORE_KEY_UNAVAILABLE) {
343    LOG(ERROR) << "Session manager operation failed: " << status;
344    // Validation errors can be temprary if the rtc has went on holiday for a
345    // short while. So we will retry such loads for up to 10 minutes.
346    if (status == STORE_TEMP_VALIDATION_ERROR) {
347      if (load_retries_left_ > 0) {
348        load_retries_left_--;
349        LOG(ERROR) << "A re-load has been scheduled due to a validation error.";
350        content::BrowserThread::PostDelayedTask(
351            content::BrowserThread::UI,
352            FROM_HERE,
353            base::Bind(&DeviceSettingsService::Load, base::Unretained(this)),
354            base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs));
355      }
356    }
357  }
358
359  if (new_owner_key) {
360    FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
361    content::NotificationService::current()->Notify(
362        chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
363        content::Source<DeviceSettingsService>(this),
364        content::NotificationService::NoDetails());
365  }
366
367  FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
368
369  std::vector<OwnershipStatusCallback> callbacks;
370  callbacks.swap(pending_ownership_status_callbacks_);
371  for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
372       iter != callbacks.end(); ++iter) {
373    iter->Run(ownership_status);
374  }
375
376  if (!waiting_for_tpm_token_) {
377    owner_key_loaded_with_tpm_token_ = true;
378    std::vector<IsCurrentUserOwnerCallback> is_owner_callbacks;
379    is_owner_callbacks.swap(pending_is_current_user_owner_callbacks_);
380    for (std::vector<IsCurrentUserOwnerCallback>::iterator iter(
381             is_owner_callbacks.begin());
382         iter != is_owner_callbacks.end(); ++iter) {
383      iter->Run(is_owner);
384    }
385  }
386
387  // The completion callback happens after the notification so clients can
388  // filter self-triggered updates.
389  if (!callback.is_null())
390    callback.Run();
391
392  // Only remove the pending operation here, so new operations triggered by any
393  // of the callbacks above are queued up properly.
394  pending_operations_.pop_front();
395  delete operation;
396
397  StartNextOperation();
398}
399
400void DeviceSettingsService::HandleError(Status status,
401                                        const base::Closure& callback) {
402  store_status_ = status;
403
404  LOG(ERROR) << "Session manager operation failed: " << status;
405
406  FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
407
408  // The completion callback happens after the notification so clients can
409  // filter self-triggered updates.
410  if (!callback.is_null())
411    callback.Run();
412}
413
414scoped_ptr<em::PolicyData> DeviceSettingsService::AssemblePolicy(
415    const em::ChromeDeviceSettingsProto& settings) const {
416  scoped_ptr<em::PolicyData> policy(new em::PolicyData());
417  if (policy_data_) {
418    // Preserve management settings.
419    if (policy_data_->has_management_mode())
420      policy->set_management_mode(policy_data_->management_mode());
421    if (policy_data_->has_request_token())
422      policy->set_request_token(policy_data_->request_token());
423    if (policy_data_->has_device_id())
424      policy->set_device_id(policy_data_->device_id());
425  } else {
426    // If there's no previous policy data, this is the first time the device
427    // setting is set. We set the management mode to NOT_MANAGED initially.
428    policy->set_management_mode(em::PolicyData::NOT_MANAGED);
429  }
430  policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
431  policy->set_timestamp((base::Time::Now() - base::Time::UnixEpoch()).
432                        InMilliseconds());
433  policy->set_username(username_);
434  if (!settings.SerializeToString(policy->mutable_policy_value()))
435    return scoped_ptr<em::PolicyData>();
436
437  return policy.Pass();
438}
439
440em::PolicyData::ManagementMode DeviceSettingsService::GetManagementMode()
441    const {
442  if (policy_data_ && policy_data_->has_management_mode())
443    return policy_data_->management_mode();
444  return em::PolicyData::NOT_MANAGED;
445}
446
447bool DeviceSettingsService::CheckManagementModeTransition(
448    em::PolicyData::ManagementMode new_mode) const {
449  em::PolicyData::ManagementMode current_mode = GetManagementMode();
450
451  // Mode is not changed.
452  if (current_mode == new_mode)
453    return true;
454
455  switch (current_mode) {
456    case em::PolicyData::NOT_MANAGED:
457      // For consumer management enrollment.
458      return new_mode == em::PolicyData::CONSUMER_MANAGED;
459
460    case em::PolicyData::ENTERPRISE_MANAGED:
461      // Management mode cannot be set when it is currently ENTERPRISE_MANAGED.
462      return false;
463
464    case em::PolicyData::CONSUMER_MANAGED:
465      // For consumer management unenrollment.
466      return new_mode == em::PolicyData::NOT_MANAGED;
467  }
468
469  NOTREACHED();
470  return false;
471}
472
473ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
474  DeviceSettingsService::Initialize();
475}
476
477ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
478  // Clean pending operations.
479  DeviceSettingsService::Get()->UnsetSessionManager();
480  DeviceSettingsService::Shutdown();
481}
482
483}  // namespace chromeos
484