session_manager_operation.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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/session_manager_operation.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/files/file_path.h" 10#include "base/message_loop/message_loop.h" 11#include "base/stl_util.h" 12#include "base/task_runner_util.h" 13#include "base/threading/sequenced_worker_pool.h" 14#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" 15#include "chrome/browser/chromeos/settings/owner_key_util.h" 16#include "chrome/browser/net/nss_context.h" 17#include "components/policy/core/common/cloud/cloud_policy_constants.h" 18#include "content/public/browser/browser_thread.h" 19#include "crypto/rsa_private_key.h" 20#include "crypto/signature_creator.h" 21#include "policy/proto/device_management_backend.pb.h" 22 23namespace em = enterprise_management; 24 25namespace chromeos { 26 27SessionManagerOperation::SessionManagerOperation(const Callback& callback) 28 : session_manager_client_(NULL), 29 weak_factory_(this), 30 callback_(callback), 31 force_key_load_(false), 32 is_loading_(false) {} 33 34SessionManagerOperation::~SessionManagerOperation() {} 35 36void SessionManagerOperation::Start( 37 SessionManagerClient* session_manager_client, 38 scoped_refptr<OwnerKeyUtil> owner_key_util, 39 scoped_refptr<PublicKey> public_key) { 40 session_manager_client_ = session_manager_client; 41 owner_key_util_ = owner_key_util; 42 public_key_ = public_key; 43 Run(); 44} 45 46void SessionManagerOperation::RestartLoad(bool key_changed) { 47 if (key_changed) 48 public_key_ = NULL; 49 50 if (!is_loading_) 51 return; 52 53 // Abort previous load operations. 54 weak_factory_.InvalidateWeakPtrs(); 55 // Mark as not loading to start loading again. 56 is_loading_ = false; 57 StartLoading(); 58} 59 60void SessionManagerOperation::StartLoading() { 61 if (is_loading_) 62 return; 63 is_loading_ = true; 64 EnsurePublicKey(base::Bind(&SessionManagerOperation::RetrieveDeviceSettings, 65 weak_factory_.GetWeakPtr())); 66} 67 68void SessionManagerOperation::ReportResult( 69 DeviceSettingsService::Status status) { 70 callback_.Run(this, status); 71} 72 73void SessionManagerOperation::EnsurePublicKey(const base::Closure& callback) { 74 if (force_key_load_ || !public_key_ || !public_key_->is_loaded()) { 75 scoped_refptr<base::TaskRunner> task_runner = 76 content::BrowserThread::GetBlockingPool() 77 ->GetTaskRunnerWithShutdownBehavior( 78 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 79 base::PostTaskAndReplyWithResult( 80 task_runner.get(), 81 FROM_HERE, 82 base::Bind(&SessionManagerOperation::LoadPublicKey, 83 owner_key_util_, 84 public_key_), 85 base::Bind(&SessionManagerOperation::StorePublicKey, 86 weak_factory_.GetWeakPtr(), 87 callback)); 88 } else { 89 callback.Run(); 90 } 91} 92 93// static 94scoped_refptr<PublicKey> SessionManagerOperation::LoadPublicKey( 95 scoped_refptr<OwnerKeyUtil> util, 96 scoped_refptr<PublicKey> current_key) { 97 scoped_refptr<PublicKey> public_key(new PublicKey()); 98 99 // Keep already-existing public key. 100 if (current_key && current_key->is_loaded()) { 101 public_key->data() = current_key->data(); 102 } 103 if (!public_key->is_loaded() && util->IsPublicKeyPresent()) { 104 if (!util->ImportPublicKey(&public_key->data())) 105 LOG(ERROR) << "Failed to load public owner key."; 106 } 107 108 return public_key; 109} 110 111void SessionManagerOperation::StorePublicKey(const base::Closure& callback, 112 scoped_refptr<PublicKey> new_key) { 113 force_key_load_ = false; 114 public_key_ = new_key; 115 116 if (!public_key_ || !public_key_->is_loaded()) { 117 ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE); 118 return; 119 } 120 121 callback.Run(); 122} 123 124void SessionManagerOperation::RetrieveDeviceSettings() { 125 session_manager_client()->RetrieveDevicePolicy( 126 base::Bind(&SessionManagerOperation::ValidateDeviceSettings, 127 weak_factory_.GetWeakPtr())); 128} 129 130void SessionManagerOperation::ValidateDeviceSettings( 131 const std::string& policy_blob) { 132 scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse()); 133 if (policy_blob.empty()) { 134 ReportResult(DeviceSettingsService::STORE_NO_POLICY); 135 return; 136 } 137 138 if (!policy->ParseFromString(policy_blob) || 139 !policy->IsInitialized()) { 140 ReportResult(DeviceSettingsService::STORE_INVALID_POLICY); 141 return; 142 } 143 144 base::SequencedWorkerPool* pool = 145 content::BrowserThread::GetBlockingPool(); 146 scoped_refptr<base::SequencedTaskRunner> background_task_runner = 147 pool->GetSequencedTaskRunnerWithShutdownBehavior( 148 pool->GetSequenceToken(), 149 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 150 151 policy::DeviceCloudPolicyValidator* validator = 152 policy::DeviceCloudPolicyValidator::Create(policy.Pass(), 153 background_task_runner); 154 155 156 // Policy auto-generated by session manager doesn't include a timestamp, so 157 // the timestamp shouldn't be verified in that case. 158 // 159 // Additionally, offline devices can get their clock set backwards in time 160 // under some hardware conditions; checking the timestamp now could likely 161 // find a value in the future, and prevent the user from signing-in or 162 // starting guest mode. Tlsdate will eventually fix the clock when the device 163 // is back online, but the network configuration may come from device ONC. 164 // 165 // To prevent all of these issues the timestamp is just not verified when 166 // loading the device policy from the cache. Note that the timestamp is still 167 // verified during enrollment and when a new policy is fetched from the 168 // server. 169 validator->ValidateAgainstCurrentPolicy( 170 policy_data_.get(), 171 policy::CloudPolicyValidatorBase::TIMESTAMP_NOT_REQUIRED, 172 policy::CloudPolicyValidatorBase::DM_TOKEN_NOT_REQUIRED); 173 validator->ValidatePolicyType(policy::dm_protocol::kChromeDevicePolicyType); 174 validator->ValidatePayload(); 175 // We don't check the DMServer verification key below, because the signing 176 // key is validated when it is installed. 177 validator->ValidateSignature(public_key_->as_string(), 178 std::string(), // No key validation check. 179 std::string(), 180 false); 181 validator->StartValidation( 182 base::Bind(&SessionManagerOperation::ReportValidatorStatus, 183 weak_factory_.GetWeakPtr())); 184} 185 186void SessionManagerOperation::ReportValidatorStatus( 187 policy::DeviceCloudPolicyValidator* validator) { 188 DeviceSettingsService::Status status = 189 DeviceSettingsService::STORE_VALIDATION_ERROR; 190 if (validator->success()) { 191 status = DeviceSettingsService::STORE_SUCCESS; 192 policy_data_ = validator->policy_data().Pass(); 193 device_settings_ = validator->payload().Pass(); 194 } else { 195 LOG(ERROR) << "Policy validation failed: " << validator->status(); 196 197 // Those are mostly caused by RTC loss and are recoverable. 198 if (validator->status() == 199 policy::DeviceCloudPolicyValidator::VALIDATION_BAD_TIMESTAMP) { 200 status = DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR; 201 } 202 } 203 204 ReportResult(status); 205} 206 207LoadSettingsOperation::LoadSettingsOperation(const Callback& callback) 208 : SessionManagerOperation(callback) {} 209 210LoadSettingsOperation::~LoadSettingsOperation() {} 211 212void LoadSettingsOperation::Run() { 213 StartLoading(); 214} 215 216StoreSettingsOperation::StoreSettingsOperation( 217 const Callback& callback, 218 scoped_ptr<em::PolicyFetchResponse> policy) 219 : SessionManagerOperation(callback), 220 policy_(policy.Pass()), 221 weak_factory_(this) {} 222 223StoreSettingsOperation::~StoreSettingsOperation() {} 224 225void StoreSettingsOperation::Run() { 226 session_manager_client()->StoreDevicePolicy( 227 policy_->SerializeAsString(), 228 base::Bind(&StoreSettingsOperation::HandleStoreResult, 229 weak_factory_.GetWeakPtr())); 230} 231 232void StoreSettingsOperation::HandleStoreResult(bool success) { 233 if (!success) 234 ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED); 235 else 236 StartLoading(); 237} 238 239SignAndStoreSettingsOperation::SignAndStoreSettingsOperation( 240 const Callback& callback, 241 scoped_ptr<em::PolicyData> new_policy) 242 : SessionManagerOperation(callback), 243 new_policy_(new_policy.Pass()), 244 weak_factory_(this) { 245 DCHECK(new_policy_); 246} 247 248SignAndStoreSettingsOperation::~SignAndStoreSettingsOperation() {} 249 250void SignAndStoreSettingsOperation::Run() { 251 if (!delegate_) { 252 ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE); 253 return; 254 } 255 delegate_->IsOwnerAsync( 256 base::Bind(&SignAndStoreSettingsOperation::StartSigning, 257 weak_factory_.GetWeakPtr())); 258} 259 260void SignAndStoreSettingsOperation::StartSigning(bool is_owner) { 261 if (!delegate_ || !is_owner) { 262 ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE); 263 return; 264 } 265 266 bool rv = delegate_->AssembleAndSignPolicyAsync( 267 new_policy_.Pass(), 268 base::Bind(&SignAndStoreSettingsOperation::StoreDeviceSettingsBlob, 269 weak_factory_.GetWeakPtr())); 270 if (!rv) { 271 ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE); 272 return; 273 } 274} 275 276void SignAndStoreSettingsOperation::StoreDeviceSettingsBlob( 277 std::string device_settings_blob) { 278 if (device_settings_blob.empty()) { 279 ReportResult(DeviceSettingsService::STORE_POLICY_ERROR); 280 return; 281 } 282 283 session_manager_client()->StoreDevicePolicy( 284 device_settings_blob, 285 base::Bind(&SignAndStoreSettingsOperation::HandleStoreResult, 286 weak_factory_.GetWeakPtr())); 287} 288 289void SignAndStoreSettingsOperation::HandleStoreResult(bool success) { 290 if (!success) 291 ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED); 292 else 293 StartLoading(); 294} 295 296} // namespace chromeos 297