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