blob: e48da55465a36d88a23bf96a424fd477cebe3378 [file] [log] [blame]
[email protected]3798a56a2012-08-30 09:03:461// 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
Yeunjoo Choi5097e9c2021-02-25 08:46:525#include "chrome/browser/ash/settings/session_manager_operation.h"
[email protected]3798a56a2012-08-30 09:03:466
dcheng7c802f02015-12-31 16:09:557#include <utility>
8
[email protected]3798a56a2012-08-30 09:03:469#include "base/bind.h"
danakjdb9ae7942020-11-11 16:01:3510#include "base/callback_helpers.h"
[email protected]57999812013-02-24 05:40:5211#include "base/files/file_path.h"
Hans Wennborgf6ad69c2020-06-18 18:02:3212#include "base/logging.h"
Gabriel Charette5ff87ce2017-05-16 18:03:4513#include "base/sequenced_task_runner.h"
[email protected]3798a56a2012-08-30 09:03:4614#include "base/stl_util.h"
Gabriel Charette44db1422018-08-06 11:19:3315#include "base/task/post_task.h"
16#include "base/task/task_traits.h"
Gabriel Charette055039132020-02-26 23:02:0617#include "base/task/thread_pool.h"
Francois Doray11b25d7ceb2018-10-05 20:34:1118#include "chrome/browser/net/nss_context.h"
ygorshenin39e36782014-08-29 13:09:5119#include "components/ownership/owner_key_util.h"
[email protected]76b4b152013-12-08 21:10:0420#include "components/policy/core/common/cloud/cloud_policy_constants.h"
Roman Sorokin1b1677d072017-10-16 12:27:4821#include "components/policy/proto/chrome_device_policy.pb.h"
brettw39d6ba42016-08-24 16:56:3822#include "components/policy/proto/device_management_backend.pb.h"
[email protected]3798a56a2012-08-30 09:03:4623#include "crypto/rsa_private_key.h"
24#include "crypto/signature_creator.h"
25
igorcovf305a942017-04-28 15:16:2326using RetrievePolicyResponseType =
27 chromeos::SessionManagerClient::RetrievePolicyResponseType;
ygorshenin39e36782014-08-29 13:09:5128using ownership::OwnerKeyUtil;
29using ownership::PublicKey;
30
[email protected]3798a56a2012-08-30 09:03:4631namespace em = enterprise_management;
32
Yeunjoo Choid461f872021-03-11 06:52:1933namespace ash {
[email protected]3798a56a2012-08-30 09:03:4634
Reilly Grant8f31d976172021-01-21 11:04:1435SessionManagerOperation::SessionManagerOperation(Callback callback)
36 : callback_(std::move(callback)) {}
[email protected]3798a56a2012-08-30 09:03:4637
38SessionManagerOperation::~SessionManagerOperation() {}
39
40void SessionManagerOperation::Start(
Yeunjoo Choid461f872021-03-11 06:52:1941 chromeos::SessionManagerClient* session_manager_client,
[email protected]3798a56a2012-08-30 09:03:4642 scoped_refptr<OwnerKeyUtil> owner_key_util,
[email protected]ea5a778a2014-06-16 12:28:3343 scoped_refptr<PublicKey> public_key) {
[email protected]3798a56a2012-08-30 09:03:4644 session_manager_client_ = session_manager_client;
45 owner_key_util_ = owner_key_util;
[email protected]ea5a778a2014-06-16 12:28:3346 public_key_ = public_key;
[email protected]3798a56a2012-08-30 09:03:4647 Run();
48}
49
50void SessionManagerOperation::RestartLoad(bool key_changed) {
51 if (key_changed)
emaxx8aaab6c2017-03-07 14:57:3352 public_key_ = nullptr;
[email protected]3798a56a2012-08-30 09:03:4653
54 if (!is_loading_)
55 return;
56
57 // Abort previous load operations.
58 weak_factory_.InvalidateWeakPtrs();
[email protected]594401ea2013-10-29 22:19:0659 // Mark as not loading to start loading again.
60 is_loading_ = false;
[email protected]3798a56a2012-08-30 09:03:4661 StartLoading();
62}
63
64void SessionManagerOperation::StartLoading() {
[email protected]594401ea2013-10-29 22:19:0665 if (is_loading_)
66 return;
[email protected]3798a56a2012-08-30 09:03:4667 is_loading_ = true;
tnagel8d2791ec2016-11-18 10:43:1368 if (cloud_validations_) {
Reilly Grant8f31d976172021-01-21 11:04:1469 EnsurePublicKey(
70 base::BindOnce(&SessionManagerOperation::RetrieveDeviceSettings,
71 weak_factory_.GetWeakPtr()));
tnagel8d2791ec2016-11-18 10:43:1372 } else {
73 RetrieveDeviceSettings();
74 }
[email protected]3798a56a2012-08-30 09:03:4675}
76
poromovafc9d60e2017-02-28 16:38:1077void SessionManagerOperation::LoadImmediately() {
Roman Sorokin716380f92018-04-19 10:10:4578 if (cloud_validations_) {
79 StorePublicKey(
Reilly Grant8f31d976172021-01-21 11:04:1480 base::BindOnce(&SessionManagerOperation::BlockingRetrieveDeviceSettings,
81 weak_factory_.GetWeakPtr()),
Roman Sorokin716380f92018-04-19 10:10:4582 LoadPublicKey(owner_key_util_, public_key_));
83 } else {
84 BlockingRetrieveDeviceSettings();
85 }
poromovafc9d60e2017-02-28 16:38:1086}
87
[email protected]3798a56a2012-08-30 09:03:4688void SessionManagerOperation::ReportResult(
89 DeviceSettingsService::Status status) {
Reilly Grant8f31d976172021-01-21 11:04:1490 std::move(callback_).Run(this, status);
[email protected]3798a56a2012-08-30 09:03:4691}
92
Reilly Grant8f31d976172021-01-21 11:04:1493void SessionManagerOperation::EnsurePublicKey(base::OnceClosure callback) {
emaxx8aaab6c2017-03-07 14:57:3394 if (force_key_load_ || !public_key_ || !public_key_->is_loaded()) {
Gabriel Charette055039132020-02-26 23:02:0695 base::ThreadPool::PostTaskAndReplyWithResult(
Francois Doray11b25d7ceb2018-10-05 20:34:1196 FROM_HERE,
Gabriel Charette055039132020-02-26 23:02:0697 {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
Francois Doray11b25d7ceb2018-10-05 20:34:1198 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
99 base::BindOnce(&SessionManagerOperation::LoadPublicKey, owner_key_util_,
100 force_key_load_ ? nullptr : public_key_),
101 base::BindOnce(&SessionManagerOperation::StorePublicKey,
Reilly Grant8f31d976172021-01-21 11:04:14102 weak_factory_.GetWeakPtr(), std::move(callback)));
[email protected]3798a56a2012-08-30 09:03:46103 } else {
Reilly Grant8f31d976172021-01-21 11:04:14104 std::move(callback).Run();
[email protected]3798a56a2012-08-30 09:03:46105 }
106}
107
108// static
[email protected]ea5a778a2014-06-16 12:28:33109scoped_refptr<PublicKey> SessionManagerOperation::LoadPublicKey(
[email protected]3798a56a2012-08-30 09:03:46110 scoped_refptr<OwnerKeyUtil> util,
[email protected]ea5a778a2014-06-16 12:28:33111 scoped_refptr<PublicKey> current_key) {
112 scoped_refptr<PublicKey> public_key(new PublicKey());
[email protected]3798a56a2012-08-30 09:03:46113
[email protected]ea5a778a2014-06-16 12:28:33114 // Keep already-existing public key.
emaxx8aaab6c2017-03-07 14:57:33115 if (current_key && current_key->is_loaded()) {
[email protected]ea5a778a2014-06-16 12:28:33116 public_key->data() = current_key->data();
[email protected]3798a56a2012-08-30 09:03:46117 }
[email protected]ea5a778a2014-06-16 12:28:33118 if (!public_key->is_loaded() && util->IsPublicKeyPresent()) {
119 if (!util->ImportPublicKey(&public_key->data()))
[email protected]3798a56a2012-08-30 09:03:46120 LOG(ERROR) << "Failed to load public owner key.";
121 }
122
[email protected]ea5a778a2014-06-16 12:28:33123 return public_key;
[email protected]3798a56a2012-08-30 09:03:46124}
125
Reilly Grant8f31d976172021-01-21 11:04:14126void SessionManagerOperation::StorePublicKey(base::OnceClosure callback,
[email protected]ea5a778a2014-06-16 12:28:33127 scoped_refptr<PublicKey> new_key) {
[email protected]3798a56a2012-08-30 09:03:46128 force_key_load_ = false;
[email protected]ea5a778a2014-06-16 12:28:33129 public_key_ = new_key;
[email protected]3798a56a2012-08-30 09:03:46130
emaxx8aaab6c2017-03-07 14:57:33131 if (!public_key_ || !public_key_->is_loaded()) {
[email protected]3798a56a2012-08-30 09:03:46132 ReportResult(DeviceSettingsService::STORE_KEY_UNAVAILABLE);
133 return;
134 }
135
Reilly Grant8f31d976172021-01-21 11:04:14136 std::move(callback).Run();
[email protected]3798a56a2012-08-30 09:03:46137}
138
139void SessionManagerOperation::RetrieveDeviceSettings() {
140 session_manager_client()->RetrieveDevicePolicy(
Hidehiko Abe86f38b0d2017-10-26 02:24:01141 base::BindOnce(&SessionManagerOperation::ValidateDeviceSettings,
142 weak_factory_.GetWeakPtr()));
[email protected]3798a56a2012-08-30 09:03:46143}
144
poromovafc9d60e2017-02-28 16:38:10145void SessionManagerOperation::BlockingRetrieveDeviceSettings() {
igorcovf305a942017-04-28 15:16:23146 std::string policy_blob;
147 RetrievePolicyResponseType response =
148 session_manager_client()->BlockingRetrieveDevicePolicy(&policy_blob);
Hidehiko Abe86f38b0d2017-10-26 02:24:01149 ValidateDeviceSettings(response, policy_blob);
poromovafc9d60e2017-02-28 16:38:10150}
151
[email protected]3798a56a2012-08-30 09:03:46152void SessionManagerOperation::ValidateDeviceSettings(
Hidehiko Abe86f38b0d2017-10-26 02:24:01153 RetrievePolicyResponseType response_type,
154 const std::string& policy_blob) {
[email protected]3798a56a2012-08-30 09:03:46155 if (policy_blob.empty()) {
156 ReportResult(DeviceSettingsService::STORE_NO_POLICY);
157 return;
158 }
159
tnagelefffaf02017-06-02 10:00:46160 std::unique_ptr<em::PolicyFetchResponse> policy =
Jinho Bang341ce5b02018-01-17 22:46:03161 std::make_unique<em::PolicyFetchResponse>();
igorcovf305a942017-04-28 15:16:23162 if (!policy->ParseFromString(policy_blob) || !policy->IsInitialized()) {
[email protected]3798a56a2012-08-30 09:03:46163 ReportResult(DeviceSettingsService::STORE_INVALID_POLICY);
164 return;
165 }
166
[email protected]6a6dd9d2013-10-19 18:16:59167 scoped_refptr<base::SequencedTaskRunner> background_task_runner =
Gabriel Charette055039132020-02-26 23:02:06168 base::ThreadPool::CreateSequencedTaskRunner(
169 {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
Francois Doray828fb5912017-08-01 15:25:15170 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
[email protected]6a6dd9d2013-10-19 18:16:59171
poromovafc9d60e2017-02-28 16:38:10172 std::unique_ptr<policy::DeviceCloudPolicyValidator> validator =
Lutz Justenbc2ee552018-04-12 13:27:38173 std::make_unique<policy::DeviceCloudPolicyValidator>(
174 std::move(policy), background_task_runner);
[email protected]3798a56a2012-08-30 09:03:46175
tnagel8d2791ec2016-11-18 10:43:13176 if (cloud_validations_) {
177 // Policy auto-generated by session manager doesn't include a timestamp, so
emaxx5a159852017-04-20 10:25:48178 // the timestamp shouldn't be verified in that case. Note that the timestamp
tnagel8d2791ec2016-11-18 10:43:13179 // is still verified during enrollment and when a new policy is fetched from
180 // the server.
181 //
182 // The two *_NOT_REQUIRED options are necessary because both the DM token
183 // and the device id are empty for a user logging in on an actual Chrome OS
184 // device that is not enterprise-managed. Note for devs: The strings are not
185 // empty when you test Chrome with target_os = "chromeos" on Linux!
186 validator->ValidateAgainstCurrentPolicy(
187 policy_data_.get(),
188 policy::CloudPolicyValidatorBase::TIMESTAMP_NOT_VALIDATED,
189 policy::CloudPolicyValidatorBase::DM_TOKEN_NOT_REQUIRED,
190 policy::CloudPolicyValidatorBase::DEVICE_ID_NOT_REQUIRED);
191
192 // We don't check the DMServer verification key below, because the signing
193 // key is validated when it is installed.
194 validator->ValidateSignature(public_key_->as_string());
195 }
196
[email protected]3798a56a2012-08-30 09:03:46197 validator->ValidatePolicyType(policy::dm_protocol::kChromeDevicePolicyType);
198 validator->ValidatePayload();
poromovafc9d60e2017-02-28 16:38:10199 if (force_immediate_load_) {
200 validator->RunValidation();
201 ReportValidatorStatus(validator.get());
202 } else {
emaxx18f3a622017-04-19 13:37:09203 policy::DeviceCloudPolicyValidator::StartValidation(
204 std::move(validator),
Sergey Poromov0022e0f2019-11-20 16:50:02205 base::BindOnce(&SessionManagerOperation::ReportValidatorStatus,
206 weak_factory_.GetWeakPtr()));
poromovafc9d60e2017-02-28 16:38:10207 }
[email protected]3798a56a2012-08-30 09:03:46208}
209
210void SessionManagerOperation::ReportValidatorStatus(
211 policy::DeviceCloudPolicyValidator* validator) {
[email protected]3798a56a2012-08-30 09:03:46212 if (validator->success()) {
dcheng7c802f02015-12-31 16:09:55213 policy_data_ = std::move(validator->policy_data());
214 device_settings_ = std::move(validator->payload());
tnagelefffaf02017-06-02 10:00:46215 ReportResult(DeviceSettingsService::STORE_SUCCESS);
[email protected]3798a56a2012-08-30 09:03:46216 } else {
Daniel Erata42858632018-09-28 18:20:51217 LOG(ERROR) << "Policy validation failed: " << validator->status() << " ("
218 << policy::DeviceCloudPolicyValidator::StatusToString(
219 validator->status())
220 << ")";
tnagelefffaf02017-06-02 10:00:46221 ReportResult(DeviceSettingsService::STORE_VALIDATION_ERROR);
[email protected]3798a56a2012-08-30 09:03:46222 }
[email protected]3798a56a2012-08-30 09:03:46223}
224
tnagel8d2791ec2016-11-18 10:43:13225LoadSettingsOperation::LoadSettingsOperation(bool force_key_load,
226 bool cloud_validations,
poromovafc9d60e2017-02-28 16:38:10227 bool force_immediate_load,
Reilly Grant8f31d976172021-01-21 11:04:14228 Callback callback)
229 : SessionManagerOperation(std::move(callback)) {
tnagel8d2791ec2016-11-18 10:43:13230 force_key_load_ = force_key_load;
231 cloud_validations_ = cloud_validations;
poromovafc9d60e2017-02-28 16:38:10232 force_immediate_load_ = force_immediate_load;
tnagel8d2791ec2016-11-18 10:43:13233}
[email protected]3798a56a2012-08-30 09:03:46234
235LoadSettingsOperation::~LoadSettingsOperation() {}
236
237void LoadSettingsOperation::Run() {
poromovafc9d60e2017-02-28 16:38:10238 if (force_immediate_load_)
239 LoadImmediately();
240 else
241 StartLoading();
[email protected]3798a56a2012-08-30 09:03:46242}
243
[email protected]ff9c5ecb2012-09-10 11:04:51244StoreSettingsOperation::StoreSettingsOperation(
Reilly Grant8f31d976172021-01-21 11:04:14245 Callback callback,
dcheng24002d02016-04-08 02:42:40246 std::unique_ptr<em::PolicyFetchResponse> policy)
Reilly Grant8f31d976172021-01-21 11:04:14247 : SessionManagerOperation(std::move(callback)), policy_(std::move(policy)) {
emaxx8aaab6c2017-03-07 14:57:33248 if (policy_->has_new_public_key())
249 force_key_load_ = true;
250}
[email protected]3798a56a2012-08-30 09:03:46251
252StoreSettingsOperation::~StoreSettingsOperation() {}
253
254void StoreSettingsOperation::Run() {
255 session_manager_client()->StoreDevicePolicy(
[email protected]ff9c5ecb2012-09-10 11:04:51256 policy_->SerializeAsString(),
Jan Wilken Dörrie59801692020-04-20 11:49:39257 base::BindOnce(&StoreSettingsOperation::HandleStoreResult,
258 weak_factory_.GetWeakPtr()));
[email protected]3798a56a2012-08-30 09:03:46259}
260
261void StoreSettingsOperation::HandleStoreResult(bool success) {
262 if (!success)
263 ReportResult(DeviceSettingsService::STORE_OPERATION_FAILED);
264 else
265 StartLoading();
266}
267
Yeunjoo Choid461f872021-03-11 06:52:19268} // namespace ash