session_manager_operation.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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/login/users/user.h"
15#include "chrome/browser/chromeos/login/users/user_manager.h"
16#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
17#include "chrome/browser/chromeos/settings/owner_key_util.h"
18#include "chrome/browser/net/nss_context.h"
19#include "components/policy/core/common/cloud/cloud_policy_constants.h"
20#include "content/public/browser/browser_thread.h"
21#include "crypto/rsa_private_key.h"
22#include "crypto/signature_creator.h"
23#include "policy/proto/device_management_backend.pb.h"
24
25namespace em = enterprise_management;
26
27namespace chromeos {
28
29SessionManagerOperation::SessionManagerOperation(const Callback& callback)
30    : session_manager_client_(NULL),
31      weak_factory_(this),
32      callback_(callback),
33      force_key_load_(false),
34      slot_(NULL),
35      is_loading_(false) {}
36
37SessionManagerOperation::~SessionManagerOperation() {}
38
39void SessionManagerOperation::Start(
40    SessionManagerClient* session_manager_client,
41    scoped_refptr<OwnerKeyUtil> owner_key_util,
42    scoped_refptr<OwnerKey> owner_key) {
43  session_manager_client_ = session_manager_client;
44  owner_key_util_ = owner_key_util;
45  owner_key_ = owner_key;
46  Run();
47}
48
49void SessionManagerOperation::RestartLoad(bool key_changed) {
50  if (key_changed)
51    owner_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  EnsureOwnerKey(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::EnsureOwnerKey(const base::Closure& callback) {
77  if (force_key_load_ || !owner_key_.get() || !owner_key_->public_key()) {
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::LoadOwnerKey,
86                   owner_key_util_,
87                   owner_key_,
88                   slot_),
89        base::Bind(&SessionManagerOperation::StoreOwnerKey,
90                   weak_factory_.GetWeakPtr(),
91                   callback));
92  } else {
93    callback.Run();
94  }
95}
96
97// static
98scoped_refptr<OwnerKey> SessionManagerOperation::LoadOwnerKey(
99    scoped_refptr<OwnerKeyUtil> util,
100    scoped_refptr<OwnerKey> current_key,
101    PK11SlotInfo* slot) {
102  scoped_ptr<std::vector<uint8> > public_key;
103  scoped_ptr<crypto::RSAPrivateKey> private_key;
104
105  // Keep any already-existing keys.
106  if (current_key.get()) {
107    if (current_key->public_key())
108      public_key.reset(new std::vector<uint8>(*current_key->public_key()));
109    if (current_key->private_key())
110      private_key.reset(current_key->private_key()->Copy());
111  }
112
113  if (!public_key.get() && util->IsPublicKeyPresent()) {
114    public_key.reset(new std::vector<uint8>());
115    if (!util->ImportPublicKey(public_key.get()))
116      LOG(ERROR) << "Failed to load public owner key.";
117  }
118
119  if (public_key.get() && !private_key.get()) {
120    private_key.reset(util->FindPrivateKeyInSlot(*public_key, slot));
121    if (!private_key.get())
122      VLOG(1) << "Failed to load private owner key.";
123  }
124
125  return new OwnerKey(public_key.Pass(), private_key.Pass());
126}
127
128void SessionManagerOperation::StoreOwnerKey(const base::Closure& callback,
129                                            scoped_refptr<OwnerKey> new_key) {
130  force_key_load_ = false;
131  owner_key_ = new_key;
132
133  if (!owner_key_.get() || !owner_key_->public_key()) {
134    ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
135    return;
136  }
137
138  callback.Run();
139}
140
141void SessionManagerOperation::RetrieveDeviceSettings() {
142  session_manager_client()->RetrieveDevicePolicy(
143      base::Bind(&SessionManagerOperation::ValidateDeviceSettings,
144                 weak_factory_.GetWeakPtr()));
145}
146
147void SessionManagerOperation::ValidateDeviceSettings(
148    const std::string& policy_blob) {
149  scoped_ptr<em::PolicyFetchResponse> policy(new em::PolicyFetchResponse());
150  if (policy_blob.empty()) {
151    ReportResult(DeviceSettingsService::STORE_NO_POLICY);
152    return;
153  }
154
155  if (!policy->ParseFromString(policy_blob) ||
156      !policy->IsInitialized()) {
157    ReportResult(DeviceSettingsService::STORE_INVALID_POLICY);
158    return;
159  }
160
161  base::SequencedWorkerPool* pool =
162      content::BrowserThread::GetBlockingPool();
163  scoped_refptr<base::SequencedTaskRunner> background_task_runner =
164      pool->GetSequencedTaskRunnerWithShutdownBehavior(
165          pool->GetSequenceToken(),
166          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
167
168  policy::DeviceCloudPolicyValidator* validator =
169      policy::DeviceCloudPolicyValidator::Create(policy.Pass(),
170                                                 background_task_runner);
171
172
173  // Policy auto-generated by session manager doesn't include a timestamp, so
174  // the timestamp shouldn't be verified in that case.
175  //
176  // Additionally, offline devices can get their clock set backwards in time
177  // under some hardware conditions; checking the timestamp now could likely
178  // find a value in the future, and prevent the user from signing-in or
179  // starting guest mode. Tlsdate will eventually fix the clock when the device
180  // is back online, but the network configuration may come from device ONC.
181  //
182  // To prevent all of these issues the timestamp is just not verified when
183  // loading the device policy from the cache. Note that the timestamp is still
184  // verified during enrollment and when a new policy is fetched from the
185  // server.
186  validator->ValidateAgainstCurrentPolicy(
187      policy_data_.get(),
188      policy::CloudPolicyValidatorBase::TIMESTAMP_NOT_REQUIRED,
189      policy::CloudPolicyValidatorBase::DM_TOKEN_NOT_REQUIRED);
190  validator->ValidatePolicyType(policy::dm_protocol::kChromeDevicePolicyType);
191  validator->ValidatePayload();
192  // We don't check the DMServer verification key below, because the signing
193  // key is validated when it is installed.
194  validator->ValidateSignature(owner_key_->public_key_as_string(),
195                               std::string(),  // No key validation check.
196                               std::string(),
197                               false);
198  validator->StartValidation(
199      base::Bind(&SessionManagerOperation::ReportValidatorStatus,
200                 weak_factory_.GetWeakPtr()));
201}
202
203void SessionManagerOperation::ReportValidatorStatus(
204    policy::DeviceCloudPolicyValidator* validator) {
205  DeviceSettingsService::Status status =
206      DeviceSettingsService::STORE_VALIDATION_ERROR;
207  if (validator->success()) {
208    status = DeviceSettingsService::STORE_SUCCESS;
209    policy_data_ = validator->policy_data().Pass();
210    device_settings_ = validator->payload().Pass();
211  } else {
212    LOG(ERROR) << "Policy validation failed: " << validator->status();
213
214    // Those are mostly caused by RTC loss and are recoverable.
215    if (validator->status() ==
216        policy::DeviceCloudPolicyValidator::VALIDATION_BAD_TIMESTAMP) {
217      status = DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR;
218    }
219  }
220
221  ReportResult(status);
222}
223
224LoadSettingsOperation::LoadSettingsOperation(const Callback& callback)
225    : SessionManagerOperation(callback) {}
226
227LoadSettingsOperation::~LoadSettingsOperation() {}
228
229void LoadSettingsOperation::Run() {
230  StartLoading();
231}
232
233StoreSettingsOperation::StoreSettingsOperation(
234    const Callback& callback,
235    scoped_ptr<em::PolicyFetchResponse> policy)
236    : SessionManagerOperation(callback),
237      policy_(policy.Pass()),
238      weak_factory_(this) {}
239
240StoreSettingsOperation::~StoreSettingsOperation() {}
241
242void StoreSettingsOperation::Run() {
243  session_manager_client()->StoreDevicePolicy(
244      policy_->SerializeAsString(),
245      base::Bind(&StoreSettingsOperation::HandleStoreResult,
246                 weak_factory_.GetWeakPtr()));
247}
248
249void StoreSettingsOperation::HandleStoreResult(bool success) {
250  if (!success)
251    ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED);
252  else
253    StartLoading();
254}
255
256SignAndStoreSettingsOperation::SignAndStoreSettingsOperation(
257    const Callback& callback,
258    scoped_ptr<em::PolicyData> new_policy)
259    : SessionManagerOperation(callback),
260      new_policy_(new_policy.Pass()),
261      weak_factory_(this) {
262  DCHECK(new_policy_);
263}
264
265SignAndStoreSettingsOperation::~SignAndStoreSettingsOperation() {}
266
267void SignAndStoreSettingsOperation::Run() {
268  EnsureOwnerKey(base::Bind(&SignAndStoreSettingsOperation::StartSigning,
269                            weak_factory_.GetWeakPtr()));
270}
271
272void SignAndStoreSettingsOperation::StartSigning() {
273  if (!owner_key().get() ||
274      !owner_key()->private_key() ||
275      new_policy_->username().empty()) {
276    ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
277    return;
278  }
279
280  base::PostTaskAndReplyWithResult(
281      content::BrowserThread::GetBlockingPool(),
282      FROM_HERE,
283      base::Bind(&SignAndStoreSettingsOperation::AssembleAndSignPolicy,
284                 base::Passed(&new_policy_), owner_key()),
285      base::Bind(&SignAndStoreSettingsOperation::StoreDeviceSettingsBlob,
286                 weak_factory_.GetWeakPtr()));
287}
288
289// static
290std::string SignAndStoreSettingsOperation::AssembleAndSignPolicy(
291    scoped_ptr<em::PolicyData> policy,
292    scoped_refptr<OwnerKey> owner_key) {
293  // Assemble the policy.
294  em::PolicyFetchResponse policy_response;
295  if (!policy->SerializeToString(policy_response.mutable_policy_data())) {
296    LOG(ERROR) << "Failed to encode policy payload.";
297    return std::string();
298  }
299
300  // Generate the signature.
301  scoped_ptr<crypto::SignatureCreator> signature_creator(
302      crypto::SignatureCreator::Create(owner_key->private_key()));
303  signature_creator->Update(
304      reinterpret_cast<const uint8*>(policy_response.policy_data().c_str()),
305      policy_response.policy_data().size());
306  std::vector<uint8> signature_bytes;
307  std::string policy_blob;
308  if (!signature_creator->Final(&signature_bytes)) {
309    LOG(ERROR) << "Failed to create policy signature.";
310    return std::string();
311  }
312
313  policy_response.mutable_policy_data_signature()->assign(
314      reinterpret_cast<const char*>(vector_as_array(&signature_bytes)),
315      signature_bytes.size());
316  return policy_response.SerializeAsString();
317}
318
319void SignAndStoreSettingsOperation::StoreDeviceSettingsBlob(
320    std::string device_settings_blob) {
321  if (device_settings_blob.empty()) {
322    ReportResult(DeviceSettingsService::STORE_POLICY_ERROR);
323    return;
324  }
325
326  session_manager_client()->StoreDevicePolicy(
327      device_settings_blob,
328      base::Bind(&SignAndStoreSettingsOperation::HandleStoreResult,
329                 weak_factory_.GetWeakPtr()));
330}
331
332void SignAndStoreSettingsOperation::HandleStoreResult(bool success) {
333  if (!success)
334    ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED);
335  else
336    StartLoading();
337}
338
339}  // namespace chromeos
340