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