device_settings_service.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 39DeviceSettingsService::Observer::~Observer() {} 40 41static DeviceSettingsService* g_device_settings_service = NULL; 42 43// static 44void DeviceSettingsService::Initialize() { 45 CHECK(!g_device_settings_service); 46 g_device_settings_service = new DeviceSettingsService(); 47} 48 49// static 50bool DeviceSettingsService::IsInitialized() { 51 return g_device_settings_service; 52} 53 54// static 55void DeviceSettingsService::Shutdown() { 56 DCHECK(g_device_settings_service); 57 delete g_device_settings_service; 58 g_device_settings_service = NULL; 59} 60 61// static 62DeviceSettingsService* DeviceSettingsService::Get() { 63 CHECK(g_device_settings_service); 64 return g_device_settings_service; 65} 66 67DeviceSettingsService::DeviceSettingsService() 68 : session_manager_client_(NULL), 69 store_status_(STORE_SUCCESS), 70 load_retries_left_(kMaxLoadRetries), 71 weak_factory_(this) { 72} 73 74DeviceSettingsService::~DeviceSettingsService() { 75 DCHECK(pending_operations_.empty()); 76} 77 78void DeviceSettingsService::SetSessionManager( 79 SessionManagerClient* session_manager_client, 80 scoped_refptr<OwnerKeyUtil> owner_key_util) { 81 DCHECK(session_manager_client); 82 DCHECK(owner_key_util.get()); 83 DCHECK(!session_manager_client_); 84 DCHECK(!owner_key_util_.get()); 85 86 session_manager_client_ = session_manager_client; 87 owner_key_util_ = owner_key_util; 88 89 session_manager_client_->AddObserver(this); 90 91 StartNextOperation(); 92} 93 94void DeviceSettingsService::UnsetSessionManager() { 95 STLDeleteContainerPointers(pending_operations_.begin(), 96 pending_operations_.end()); 97 pending_operations_.clear(); 98 99 if (session_manager_client_) 100 session_manager_client_->RemoveObserver(this); 101 session_manager_client_ = NULL; 102 owner_key_util_ = NULL; 103} 104 105scoped_refptr<PublicKey> DeviceSettingsService::GetPublicKey() { 106 return public_key_; 107} 108 109void DeviceSettingsService::Load() { 110 EnqueueLoad(false); 111} 112 113void DeviceSettingsService::SignAndStore( 114 scoped_ptr<em::ChromeDeviceSettingsProto> new_settings, 115 const base::Closure& callback) { 116 scoped_ptr<em::PolicyData> new_policy = AssemblePolicy(*new_settings); 117 if (!new_policy) { 118 HandleError(STORE_POLICY_ERROR, callback); 119 return; 120 } 121 122 EnqueueSignAndStore(new_policy.Pass(), callback); 123} 124 125void DeviceSettingsService::SetManagementSettings( 126 em::PolicyData::ManagementMode management_mode, 127 const std::string& request_token, 128 const std::string& device_id, 129 const base::Closure& callback) { 130 if (!CheckManagementModeTransition(management_mode)) { 131 LOG(ERROR) << "Invalid management mode transition: current mode = " 132 << GetManagementMode() << ", new mode = " << management_mode; 133 HandleError(STORE_POLICY_ERROR, callback); 134 return; 135 } 136 137 scoped_ptr<em::PolicyData> policy = AssemblePolicy(*device_settings_); 138 if (!policy) { 139 HandleError(STORE_POLICY_ERROR, callback); 140 return; 141 } 142 143 policy->set_management_mode(management_mode); 144 policy->set_request_token(request_token); 145 policy->set_device_id(device_id); 146 147 EnqueueSignAndStore(policy.Pass(), callback); 148} 149 150void DeviceSettingsService::Store(scoped_ptr<em::PolicyFetchResponse> policy, 151 const base::Closure& callback) { 152 Enqueue( 153 new StoreSettingsOperation( 154 base::Bind(&DeviceSettingsService::HandleCompletedOperation, 155 weak_factory_.GetWeakPtr(), 156 callback), 157 policy.Pass())); 158} 159 160DeviceSettingsService::OwnershipStatus 161 DeviceSettingsService::GetOwnershipStatus() { 162 if (public_key_) 163 return public_key_->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE; 164 return OWNERSHIP_UNKNOWN; 165} 166 167void DeviceSettingsService::GetOwnershipStatusAsync( 168 const OwnershipStatusCallback& callback) { 169 if (public_key_) { 170 // If there is a key, report status immediately. 171 base::MessageLoop::current()->PostTask( 172 FROM_HERE, base::Bind(callback, GetOwnershipStatus())); 173 } else { 174 // If the key hasn't been loaded yet, enqueue the callback to be fired when 175 // the next SessionManagerOperation completes. If no operation is pending, 176 // start a load operation to fetch the key and report the result. 177 pending_ownership_status_callbacks_.push_back(callback); 178 if (pending_operations_.empty()) 179 EnqueueLoad(false); 180 } 181} 182 183bool DeviceSettingsService::HasPrivateOwnerKey() { 184 return delegate_ && delegate_->IsOwner(); 185} 186 187void DeviceSettingsService::InitOwner( 188 const std::string& username, 189 const base::WeakPtr<PrivateKeyDelegate>& delegate) { 190 if (!username_.empty()) 191 return; 192 username_ = username; 193 delegate_ = delegate; 194 195 EnsureReload(true); 196} 197 198const std::string& DeviceSettingsService::GetUsername() const { 199 return username_; 200} 201 202void DeviceSettingsService::AddObserver(Observer* observer) { 203 observers_.AddObserver(observer); 204} 205 206void DeviceSettingsService::RemoveObserver(Observer* observer) { 207 observers_.RemoveObserver(observer); 208} 209 210void DeviceSettingsService::OwnerKeySet(bool success) { 211 if (!success) { 212 LOG(ERROR) << "Owner key change failed."; 213 return; 214 } 215 216 public_key_ = NULL; 217 EnsureReload(true); 218} 219 220void DeviceSettingsService::PropertyChangeComplete(bool success) { 221 if (!success) { 222 LOG(ERROR) << "Policy update failed."; 223 return; 224 } 225 226 EnsureReload(false); 227} 228 229void DeviceSettingsService::Enqueue(SessionManagerOperation* operation) { 230 pending_operations_.push_back(operation); 231 if (pending_operations_.front() == operation) 232 StartNextOperation(); 233} 234 235void DeviceSettingsService::EnqueueLoad(bool force_key_load) { 236 SessionManagerOperation* operation = 237 new LoadSettingsOperation( 238 base::Bind(&DeviceSettingsService::HandleCompletedOperation, 239 weak_factory_.GetWeakPtr(), 240 base::Closure())); 241 operation->set_force_key_load(force_key_load); 242 operation->set_username(username_); 243 operation->set_delegate(delegate_); 244 Enqueue(operation); 245} 246 247void DeviceSettingsService::EnqueueSignAndStore( 248 scoped_ptr<em::PolicyData> policy, 249 const base::Closure& callback) { 250 SignAndStoreSettingsOperation* operation = new SignAndStoreSettingsOperation( 251 base::Bind(&DeviceSettingsService::HandleCompletedOperation, 252 weak_factory_.GetWeakPtr(), 253 callback), 254 policy.Pass()); 255 operation->set_delegate(delegate_); 256 Enqueue(operation); 257} 258 259void DeviceSettingsService::EnsureReload(bool force_key_load) { 260 if (!pending_operations_.empty()) { 261 pending_operations_.front()->set_username(username_); 262 pending_operations_.front()->set_delegate(delegate_); 263 pending_operations_.front()->RestartLoad(force_key_load); 264 } else { 265 EnqueueLoad(force_key_load); 266 } 267} 268 269void DeviceSettingsService::StartNextOperation() { 270 if (!pending_operations_.empty() && 271 session_manager_client_ && 272 owner_key_util_.get()) { 273 pending_operations_.front()->Start( 274 session_manager_client_, owner_key_util_, public_key_); 275 } 276} 277 278void DeviceSettingsService::HandleCompletedOperation( 279 const base::Closure& callback, 280 SessionManagerOperation* operation, 281 Status status) { 282 DCHECK_EQ(operation, pending_operations_.front()); 283 store_status_ = status; 284 285 OwnershipStatus ownership_status = OWNERSHIP_UNKNOWN; 286 scoped_refptr<PublicKey> new_key(operation->public_key()); 287 if (new_key.get()) { 288 ownership_status = new_key->is_loaded() ? OWNERSHIP_TAKEN : OWNERSHIP_NONE; 289 } else { 290 NOTREACHED() << "Failed to determine key status."; 291 } 292 293 bool new_owner_key = false; 294 if (public_key_.get() != new_key.get()) { 295 public_key_ = new_key; 296 new_owner_key = true; 297 } 298 299 if (status == STORE_SUCCESS) { 300 policy_data_ = operation->policy_data().Pass(); 301 device_settings_ = operation->device_settings().Pass(); 302 load_retries_left_ = kMaxLoadRetries; 303 } else if (status != STORE_KEY_UNAVAILABLE) { 304 LOG(ERROR) << "Session manager operation failed: " << status; 305 // Validation errors can be temporary if the rtc has gone on holiday for a 306 // short while. So we will retry such loads for up to 10 minutes. 307 if (status == STORE_TEMP_VALIDATION_ERROR) { 308 if (load_retries_left_ > 0) { 309 load_retries_left_--; 310 LOG(ERROR) << "A re-load has been scheduled due to a validation error."; 311 content::BrowserThread::PostDelayedTask( 312 content::BrowserThread::UI, 313 FROM_HERE, 314 base::Bind(&DeviceSettingsService::Load, base::Unretained(this)), 315 base::TimeDelta::FromMilliseconds(kLoadRetryDelayMs)); 316 } else { 317 // Once we've given up retrying, the validation error is not temporary 318 // anymore. 319 store_status_ = STORE_VALIDATION_ERROR; 320 } 321 } 322 } 323 324 if (new_owner_key) { 325 FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged()); 326 content::NotificationService::current()->Notify( 327 chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED, 328 content::Source<DeviceSettingsService>(this), 329 content::NotificationService::NoDetails()); 330 } 331 332 FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated()); 333 334 std::vector<OwnershipStatusCallback> callbacks; 335 callbacks.swap(pending_ownership_status_callbacks_); 336 for (std::vector<OwnershipStatusCallback>::iterator iter(callbacks.begin()); 337 iter != callbacks.end(); ++iter) { 338 iter->Run(ownership_status); 339 } 340 341 // The completion callback happens after the notification so clients can 342 // filter self-triggered updates. 343 if (!callback.is_null()) 344 callback.Run(); 345 346 // Only remove the pending operation here, so new operations triggered by any 347 // of the callbacks above are queued up properly. 348 pending_operations_.pop_front(); 349 delete operation; 350 351 StartNextOperation(); 352} 353 354void DeviceSettingsService::HandleError(Status status, 355 const base::Closure& callback) { 356 store_status_ = status; 357 358 LOG(ERROR) << "Session manager operation failed: " << status; 359 360 FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated()); 361 362 // The completion callback happens after the notification so clients can 363 // filter self-triggered updates. 364 if (!callback.is_null()) 365 callback.Run(); 366} 367 368scoped_ptr<em::PolicyData> DeviceSettingsService::AssemblePolicy( 369 const em::ChromeDeviceSettingsProto& settings) const { 370 scoped_ptr<em::PolicyData> policy(new em::PolicyData()); 371 if (policy_data_) { 372 // Preserve management settings. 373 if (policy_data_->has_management_mode()) 374 policy->set_management_mode(policy_data_->management_mode()); 375 if (policy_data_->has_request_token()) 376 policy->set_request_token(policy_data_->request_token()); 377 if (policy_data_->has_device_id()) 378 policy->set_device_id(policy_data_->device_id()); 379 } else { 380 // If there's no previous policy data, this is the first time the device 381 // setting is set. We set the management mode to NOT_MANAGED initially. 382 policy->set_management_mode(em::PolicyData::NOT_MANAGED); 383 } 384 policy->set_policy_type(policy::dm_protocol::kChromeDevicePolicyType); 385 policy->set_timestamp((base::Time::Now() - base::Time::UnixEpoch()). 386 InMilliseconds()); 387 policy->set_username(username_); 388 if (!settings.SerializeToString(policy->mutable_policy_value())) 389 return scoped_ptr<em::PolicyData>(); 390 391 return policy.Pass(); 392} 393 394em::PolicyData::ManagementMode DeviceSettingsService::GetManagementMode() 395 const { 396 if (policy_data_ && policy_data_->has_management_mode()) 397 return policy_data_->management_mode(); 398 return em::PolicyData::NOT_MANAGED; 399} 400 401bool DeviceSettingsService::CheckManagementModeTransition( 402 em::PolicyData::ManagementMode new_mode) const { 403 em::PolicyData::ManagementMode current_mode = GetManagementMode(); 404 405 // Mode is not changed. 406 if (current_mode == new_mode) 407 return true; 408 409 switch (current_mode) { 410 case em::PolicyData::NOT_MANAGED: 411 // For consumer management enrollment. 412 return new_mode == em::PolicyData::CONSUMER_MANAGED; 413 414 case em::PolicyData::ENTERPRISE_MANAGED: 415 // Management mode cannot be set when it is currently ENTERPRISE_MANAGED. 416 return false; 417 418 case em::PolicyData::CONSUMER_MANAGED: 419 // For consumer management unenrollment. 420 return new_mode == em::PolicyData::NOT_MANAGED; 421 } 422 423 NOTREACHED(); 424 return false; 425} 426 427ScopedTestDeviceSettingsService::ScopedTestDeviceSettingsService() { 428 DeviceSettingsService::Initialize(); 429} 430 431ScopedTestDeviceSettingsService::~ScopedTestDeviceSettingsService() { 432 // Clean pending operations. 433 DeviceSettingsService::Get()->UnsetSessionManager(); 434 DeviceSettingsService::Shutdown(); 435} 436 437} // namespace chromeos 438