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