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