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