device_settings_service.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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  Enqueue(
133      new SignAndStoreSettingsOperation(
134          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
135                     weak_factory_.GetWeakPtr(),
136                     callback),
137          new_policy.Pass()));
138}
139
140void DeviceSettingsService::SetManagementSettings(
141    em::PolicyData::ManagementMode management_mode,
142    const std::string& request_token,
143    const std::string& device_id,
144    const base::Closure& callback) {
145  // TODO(davidyu): Check for invalid management mode transition.
146  scoped_ptr<em::PolicyData> policy = AssemblePolicy(*device_settings_);
147  if (policy) {
148    policy->set_management_mode(management_mode);
149    policy->set_request_token(request_token);
150    policy->set_device_id(device_id);
151  }
152  Enqueue(
153      new SignAndStoreSettingsOperation(
154          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
155                     weak_factory_.GetWeakPtr(),
156                     callback),
157          policy.Pass()));
158}
159
160void DeviceSettingsService::Store(scoped_ptr<em::PolicyFetchResponse> policy,
161                                  const base::Closure& callback) {
162  Enqueue(
163      new StoreSettingsOperation(
164          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
165                     weak_factory_.GetWeakPtr(),
166                     callback),
167          policy.Pass()));
168}
169
170DeviceSettingsService::OwnershipStatus
171    DeviceSettingsService::GetOwnershipStatus() {
172  if (owner_key_.get())
173    return owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
174
175  return OWNERSHIP_UNKNOWN;
176}
177
178void DeviceSettingsService::GetOwnershipStatusAsync(
179    const OwnershipStatusCallback& callback) {
180  if (owner_key_.get()) {
181    // If there is a key, report status immediately.
182    base::MessageLoop::current()->PostTask(
183        FROM_HERE,
184        base::Bind(
185            callback,
186            owner_key_->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE));
187  } else {
188    // If the key hasn't been loaded yet, enqueue the callback to be fired when
189    // the next SessionManagerOperation completes. If no operation is pending,
190    // start a load operation to fetch the key and report the result.
191    pending_ownership_status_callbacks_.push_back(callback);
192    if (pending_operations_.empty())
193      EnqueueLoad(false);
194  }
195}
196
197bool DeviceSettingsService::HasPrivateOwnerKey() {
198  return owner_key_.get() && owner_key_->private_key();
199}
200
201void DeviceSettingsService::IsCurrentUserOwnerAsync(
202    const IsCurrentUserOwnerCallback& callback) {
203  if (owner_key_loaded_with_tpm_token_) {
204    // If the current owner key was loaded while the certificates were loaded,
205    // or the certificate loader is not initialized, in which case the private
206    // key cannot be set, report status immediately.
207    base::MessageLoop::current()->PostTask(
208        FROM_HERE,
209        base::Bind(callback, HasPrivateOwnerKey()));
210  } else {
211    // If the key hasn't been loaded with the known certificates, enqueue the
212    // callback to be fired when the next SessionManagerOperation completes in
213    // an environment where the certificates are loaded. There is no need to
214    // start a new operation, as the reload operation will be started when the
215    // certificates are loaded.
216    pending_is_current_user_owner_callbacks_.push_back(callback);
217  }
218}
219
220void DeviceSettingsService::SetUsername(const std::string& username) {
221  username_ = username;
222
223  // The private key may have become available, so force a key reload.
224  owner_key_ = NULL;
225  EnsureReload(true);
226}
227
228const std::string& DeviceSettingsService::GetUsername() const {
229  return username_;
230}
231
232void DeviceSettingsService::AddObserver(Observer* observer) {
233  observers_.AddObserver(observer);
234}
235
236void DeviceSettingsService::RemoveObserver(Observer* observer) {
237  observers_.RemoveObserver(observer);
238}
239
240void DeviceSettingsService::OwnerKeySet(bool success) {
241  if (!success) {
242    LOG(ERROR) << "Owner key change failed.";
243    return;
244  }
245
246  owner_key_ = NULL;
247  EnsureReload(true);
248}
249
250void DeviceSettingsService::PropertyChangeComplete(bool success) {
251  if (!success) {
252    LOG(ERROR) << "Policy update failed.";
253    return;
254  }
255
256  EnsureReload(false);
257}
258
259void DeviceSettingsService::OnTPMTokenReady() {
260  waiting_for_tpm_token_ = false;
261
262  // TPMTokenLoader initializes the TPM and NSS database which is necessary to
263  // determine ownership. Force a reload once we know these are initialized.
264  EnsureReload(true);
265}
266
267void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
268  pending_operations_.push_back(operation);
269  if (pending_operations_.front() == operation)
270    StartNextOperation();
271}
272
273void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
274  SessionManagerOperation* operation =
275      new LoadSettingsOperation(
276          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
277                     weak_factory_.GetWeakPtr(),
278                     base::Closure()));
279  operation->set_force_key_load(force_key_load);
280  Enqueue(operation);
281}
282
283void DeviceSettingsService::EnsureReload(bool force_key_load) {
284  if (!pending_operations_.empty())
285    pending_operations_.front()->RestartLoad(force_key_load);
286  else
287    EnqueueLoad(force_key_load);
288}
289
290void DeviceSettingsService::StartNextOperation() {
291  if (!pending_operations_.empty() &&
292      session_manager_client_ &&
293      owner_key_util_.get()) {
294    pending_operations_.front()->Start(session_manager_client_,
295                                       owner_key_util_, owner_key_);
296  }
297}
298
299void DeviceSettingsService::HandleCompletedOperation(
300    const base::Closure& callback,
301    SessionManagerOperation* operation,
302    Status status) {
303  DCHECK_EQ(operation, pending_operations_.front());
304  store_status_ = status;
305
306  OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
307  bool is_owner = false;
308  scoped_refptr<OwnerKey> new_key(operation->owner_key());
309  if (new_key.get()) {
310    ownership_status =
311        new_key->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
312    is_owner = (new_key->private_key() != NULL);
313  } else {
314    NOTREACHED() << "Failed to determine key status.";
315  }
316
317  bool new_owner_key = false;
318  if (owner_key_.get() != new_key.get()) {
319    owner_key_ = new_key;
320    new_owner_key = true;
321  }
322
323  if (status == STORE_SUCCESS) {
324    policy_data_ = operation->policy_data().Pass();
325    device_settings_ = operation->device_settings().Pass();
326    load_retries_left_ = kMaxLoadRetries;
327  } else if (status != STORE_KEY_UNAVAILABLE) {
328    LOG(ERROR) << "Session manager operation failed: " << status;
329    // Validation errors can be temprary if the rtc has went on holiday for a
330    // short while. So we will retry such loads for up to 10 minutes.
331    if (status == STORE_TEMP_VALIDATION_ERROR) {
332      if (load_retries_left_ > 0) {
333        load_retries_left_--;
334        LOG(ERROR) << "A re-load has been scheduled due to a validation error.";
335        content::BrowserThread::PostDelayedTask(
336            content::BrowserThread::UI,
337            FROM_HERE,
338            base::Bind(&DeviceSettingsService::Load, base::Unretained(this)),
339            base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs));
340      }
341    }
342  }
343
344  if (new_owner_key) {
345    FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
346    content::NotificationService::current()->Notify(
347        chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
348        content::Source<DeviceSettingsService>(this),
349        content::NotificationService::NoDetails());
350  }
351
352  FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
353
354  std::vector<OwnershipStatusCallback> callbacks;
355  callbacks.swap(pending_ownership_status_callbacks_);
356  for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
357       iter != callbacks.end(); ++iter) {
358    iter->Run(ownership_status);
359  }
360
361  if (!waiting_for_tpm_token_) {
362    owner_key_loaded_with_tpm_token_ = true;
363    std::vector<IsCurrentUserOwnerCallback> is_owner_callbacks;
364    is_owner_callbacks.swap(pending_is_current_user_owner_callbacks_);
365    for (std::vector<IsCurrentUserOwnerCallback>::iterator iter(
366             is_owner_callbacks.begin());
367         iter != is_owner_callbacks.end(); ++iter) {
368      iter->Run(is_owner);
369    }
370  }
371
372  // The completion callback happens after the notification so clients can
373  // filter self-triggered updates.
374  if (!callback.is_null())
375    callback.Run();
376
377  // Only remove the pending operation here, so new operations triggered by any
378  // of the callbacks above are queued up properly.
379  pending_operations_.pop_front();
380  delete operation;
381
382  StartNextOperation();
383}
384
385scoped_ptr<em::PolicyData> DeviceSettingsService::AssemblePolicy(
386    const em::ChromeDeviceSettingsProto& settings) {
387  scoped_ptr<em::PolicyData> policy(new em::PolicyData());
388  if (policy_data_) {
389    // Preserve management settings.
390    if (policy_data_->has_management_mode())
391      policy->set_management_mode(policy_data_->management_mode());
392    if (policy_data_->has_request_token())
393      policy->set_request_token(policy_data_->request_token());
394    if (policy_data_->has_device_id())
395      policy->set_device_id(policy_data_->device_id());
396  } else {
397    // If there's no previous policy data, this is the first time the device
398    // setting is set. We set the management mode to NOT_MANAGED initially.
399    policy->set_management_mode(em::PolicyData::NOT_MANAGED);
400  }
401  policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
402  policy->set_timestamp((base::Time::Now() - base::Time::UnixEpoch()).
403                        InMilliseconds());
404  policy->set_username(username_);
405  if (!settings.SerializeToString(policy->mutable_policy_value()))
406    return scoped_ptr<em::PolicyData>();
407
408  return policy.Pass();
409}
410
411ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
412  DeviceSettingsService::Initialize();
413}
414
415ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
416  // Clean pending operations.
417  DeviceSettingsService::Get()->UnsetSessionManager();
418  DeviceSettingsService::Shutdown();
419}
420
421}  // namespace chromeos
422