device_settings_service.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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::InitOwner(const std::string& username,
236                                      crypto::ScopedPK11Slot slot) {
237  if (!username_.empty())
238    return;
239
240  username_ = username;
241  slot_ = slot.Pass();
242
243  // The private key may have become available, so force a key reload.
244  owner_key_ = NULL;
245  EnsureReload(true);
246}
247
248const std::string& DeviceSettingsService::GetUsername() const {
249  return username_;
250}
251
252void DeviceSettingsService::AddObserver(Observer* observer) {
253  observers_.AddObserver(observer);
254}
255
256void DeviceSettingsService::RemoveObserver(Observer* observer) {
257  observers_.RemoveObserver(observer);
258}
259
260void DeviceSettingsService::OwnerKeySet(bool success) {
261  if (!success) {
262    LOG(ERROR) << "Owner key change failed.";
263    return;
264  }
265
266  owner_key_ = NULL;
267  EnsureReload(true);
268}
269
270void DeviceSettingsService::PropertyChangeComplete(bool success) {
271  if (!success) {
272    LOG(ERROR) << "Policy update failed.";
273    return;
274  }
275
276  EnsureReload(false);
277}
278
279void DeviceSettingsService::OnTPMTokenReady() {
280  waiting_for_tpm_token_ = false;
281
282  // TPMTokenLoader initializes the TPM and NSS database which is necessary to
283  // determine ownership. Force a reload once we know these are initialized.
284  EnsureReload(true);
285}
286
287void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) {
288  pending_operations_.push_back(operation);
289  if (pending_operations_.front() == operation)
290    StartNextOperation();
291}
292
293void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
294  SessionManagerOperation* operation =
295      new LoadSettingsOperation(
296          base::Bind(&DeviceSettingsService::HandleCompletedOperation,
297                     weak_factory_.GetWeakPtr(),
298                     base::Closure()));
299  operation->set_force_key_load(force_key_load);
300  operation->set_username(username_);
301  operation->set_slot(slot_.get());
302  Enqueue(operation);
303}
304
305void DeviceSettingsService::EnsureReload(bool force_key_load) {
306  if (!pending_operations_.empty()) {
307    pending_operations_.front()->set_username(username_);
308    pending_operations_.front()->set_slot(slot_.get());
309    pending_operations_.front()->RestartLoad(force_key_load);
310  } else {
311    EnqueueLoad(force_key_load);
312  }
313}
314
315void DeviceSettingsService::StartNextOperation() {
316  if (!pending_operations_.empty() &&
317      session_manager_client_ &&
318      owner_key_util_.get()) {
319    pending_operations_.front()->Start(session_manager_client_,
320                                       owner_key_util_, owner_key_);
321  }
322}
323
324void DeviceSettingsService::HandleCompletedOperation(
325    const base::Closure& callback,
326    SessionManagerOperation* operation,
327    Status status) {
328  DCHECK_EQ(operation, pending_operations_.front());
329  store_status_ = status;
330
331  OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN;
332  bool is_owner = false;
333  scoped_refptr<OwnerKey> new_key(operation->owner_key());
334  if (new_key.get()) {
335    ownership_status =
336        new_key->public_key() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE;
337    is_owner = (new_key->private_key() != NULL);
338  } else {
339    NOTREACHED() << "Failed to determine key status.";
340  }
341
342  bool new_owner_key = false;
343  if (owner_key_.get() != new_key.get()) {
344    owner_key_ = new_key;
345    new_owner_key = true;
346  }
347
348  if (status == STORE_SUCCESS) {
349    policy_data_ = operation->policy_data().Pass();
350    device_settings_ = operation->device_settings().Pass();
351    load_retries_left_ = kMaxLoadRetries;
352  } else if (status != STORE_KEY_UNAVAILABLE) {
353    LOG(ERROR) << "Session manager operation failed: " << status;
354    // Validation errors can be temporary if the rtc has gone on holiday for a
355    // short while. So we will retry such loads for up to 10 minutes.
356    if (status == STORE_TEMP_VALIDATION_ERROR) {
357      if (load_retries_left_ > 0) {
358        load_retries_left_--;
359        LOG(ERROR) << "A re-load has been scheduled due to a validation error.";
360        content::BrowserThread::PostDelayedTask(
361            content::BrowserThread::UI,
362            FROM_HERE,
363            base::Bind(&DeviceSettingsService::Load, base::Unretained(this)),
364            base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs));
365      } else {
366        // Once we've given up retrying, the validation error is not temporary
367        // anymore.
368        store_status_ = STORE_VALIDATION_ERROR;
369      }
370    }
371  }
372
373  if (new_owner_key) {
374    FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged());
375    content::NotificationService::current()->Notify(
376        chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
377        content::Source<DeviceSettingsService>(this),
378        content::NotificationService::NoDetails());
379  }
380
381  FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
382
383  std::vector<OwnershipStatusCallback> callbacks;
384  callbacks.swap(pending_ownership_status_callbacks_);
385  for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin());
386       iter != callbacks.end(); ++iter) {
387    iter->Run(ownership_status);
388  }
389
390  if (!waiting_for_tpm_token_) {
391    owner_key_loaded_with_tpm_token_ = true;
392    std::vector<IsCurrentUserOwnerCallback> is_owner_callbacks;
393    is_owner_callbacks.swap(pending_is_current_user_owner_callbacks_);
394    for (std::vector<IsCurrentUserOwnerCallback>::iterator iter(
395             is_owner_callbacks.begin());
396         iter != is_owner_callbacks.end(); ++iter) {
397      iter->Run(is_owner);
398    }
399  }
400
401  // The completion callback happens after the notification so clients can
402  // filter self-triggered updates.
403  if (!callback.is_null())
404    callback.Run();
405
406  // Only remove the pending operation here, so new operations triggered by any
407  // of the callbacks above are queued up properly.
408  pending_operations_.pop_front();
409  delete operation;
410
411  StartNextOperation();
412}
413
414void DeviceSettingsService::HandleError(Status status,
415                                        const base::Closure& callback) {
416  store_status_ = status;
417
418  LOG(ERROR) << "Session manager operation failed: " << status;
419
420  FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated());
421
422  // The completion callback happens after the notification so clients can
423  // filter self-triggered updates.
424  if (!callback.is_null())
425    callback.Run();
426}
427
428scoped_ptr<em::PolicyData> DeviceSettingsService::AssemblePolicy(
429    const em::ChromeDeviceSettingsProto& settings) const {
430  scoped_ptr<em::PolicyData> policy(new em::PolicyData());
431  if (policy_data_) {
432    // Preserve management settings.
433    if (policy_data_->has_management_mode())
434      policy->set_management_mode(policy_data_->management_mode());
435    if (policy_data_->has_request_token())
436      policy->set_request_token(policy_data_->request_token());
437    if (policy_data_->has_device_id())
438      policy->set_device_id(policy_data_->device_id());
439  } else {
440    // If there's no previous policy data, this is the first time the device
441    // setting is set. We set the management mode to NOT_MANAGED initially.
442    policy->set_management_mode(em::PolicyData::NOT_MANAGED);
443  }
444  policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType);
445  policy->set_timestamp((base::Time::Now() - base::Time::UnixEpoch()).
446                        InMilliseconds());
447  policy->set_username(username_);
448  if (!settings.SerializeToString(policy->mutable_policy_value()))
449    return scoped_ptr<em::PolicyData>();
450
451  return policy.Pass();
452}
453
454em::PolicyData::ManagementMode DeviceSettingsService::GetManagementMode()
455    const {
456  if (policy_data_ && policy_data_->has_management_mode())
457    return policy_data_->management_mode();
458  return em::PolicyData::NOT_MANAGED;
459}
460
461bool DeviceSettingsService::CheckManagementModeTransition(
462    em::PolicyData::ManagementMode new_mode) const {
463  em::PolicyData::ManagementMode current_mode = GetManagementMode();
464
465  // Mode is not changed.
466  if (current_mode == new_mode)
467    return true;
468
469  switch (current_mode) {
470    case em::PolicyData::NOT_MANAGED:
471      // For consumer management enrollment.
472      return new_mode == em::PolicyData::CONSUMER_MANAGED;
473
474    case em::PolicyData::ENTERPRISE_MANAGED:
475      // Management mode cannot be set when it is currently ENTERPRISE_MANAGED.
476      return false;
477
478    case em::PolicyData::CONSUMER_MANAGED:
479      // For consumer management unenrollment.
480      return new_mode == em::PolicyData::NOT_MANAGED;
481  }
482
483  NOTREACHED();
484  return false;
485}
486
487ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() {
488  DeviceSettingsService::Initialize();
489}
490
491ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() {
492  // Clean pending operations.
493  DeviceSettingsService::Get()->UnsetSessionManager();
494  DeviceSettingsService::Shutdown();
495}
496
497}  // namespace chromeos
498