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