PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/chrome/browser/chromeos/policy/pre_signin_policy_fetcher.cc

http://github.com/chromium/chromium
C++ | 341 lines | 257 code | 48 blank | 36 comment | 24 complexity | a8c14b00ef4089ff1d32fad87b0cc191 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, BSD-2-Clause, LGPL-2.1, MPL-2.0, 0BSD, EPL-1.0, MPL-2.0-no-copyleft-exception, GPL-2.0, BitTorrent-1.0, CPL-1.0, LGPL-3.0, Unlicense, BSD-3-Clause, CC0-1.0, JSON, MIT, GPL-3.0, CC-BY-SA-3.0, AGPL-1.0
  1. // Copyright (c) 2017 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. #include "chrome/browser/chromeos/policy/pre_signin_policy_fetcher.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/callback.h"
  8. #include "base/files/file_path.h"
  9. #include "base/location.h"
  10. #include "base/logging.h"
  11. #include "base/path_service.h"
  12. #include "base/sequenced_task_runner.h"
  13. #include "base/task/task_traits.h"
  14. #include "base/task/thread_pool.h"
  15. #include "base/time/time.h"
  16. #include "chromeos/cryptohome/cryptohome_parameters.h"
  17. #include "chromeos/cryptohome/cryptohome_util.h"
  18. #include "chromeos/cryptohome/homedir_methods.h"
  19. #include "chromeos/dbus/constants/dbus_paths.h"
  20. #include "chromeos/dbus/cryptohome/cryptohome_client.h"
  21. #include "chromeos/dbus/dbus_thread_manager.h"
  22. #include "components/policy/core/common/cloud/cloud_policy_constants.h"
  23. #include "components/policy/proto/device_management_backend.pb.h"
  24. #include "google_apis/gaia/gaia_auth_util.h"
  25. namespace em = enterprise_management;
  26. namespace policy {
  27. namespace {
  28. // We will abort fresh policy fetch after this time and use cached policy.
  29. const int kPolicyFetchTimeoutSecs = 10;
  30. // Traits for the tasks posted on base::ThreadPool in pre-signin policy fetch.
  31. // As this blocks signin, the tasks have user-visible priority.
  32. constexpr base::TaskTraits kTaskTraits = {base::MayBlock(),
  33. base::TaskPriority::USER_VISIBLE};
  34. } // namespace
  35. PreSigninPolicyFetcher::PreSigninPolicyFetcher(
  36. chromeos::CryptohomeClient* cryptohome_client,
  37. chromeos::SessionManagerClient* session_manager_client,
  38. std::unique_ptr<CloudPolicyClient> cloud_policy_client,
  39. bool is_active_directory_managed,
  40. const AccountId& account_id,
  41. const cryptohome::KeyDefinition& auth_key)
  42. : cryptohome_client_(cryptohome_client),
  43. session_manager_client_(session_manager_client),
  44. cloud_policy_client_(std::move(cloud_policy_client)),
  45. is_active_directory_managed_(is_active_directory_managed),
  46. account_id_(account_id),
  47. auth_key_(auth_key),
  48. task_runner_(base::ThreadPool::CreateSequencedTaskRunner(kTaskTraits)) {
  49. DCHECK(account_id_.GetAccountType() != AccountType::ACTIVE_DIRECTORY ||
  50. is_active_directory_managed_);
  51. }
  52. PreSigninPolicyFetcher ::~PreSigninPolicyFetcher() {}
  53. void PreSigninPolicyFetcher::FetchPolicy(PolicyFetchResultCallback callback) {
  54. DCHECK(callback_.is_null());
  55. callback_ = std::move(callback);
  56. cryptohome::AuthorizationRequest auth;
  57. cryptohome::Key* key = auth.mutable_key();
  58. if (!auth_key_.label.empty()) {
  59. key->mutable_data()->set_label(auth_key_.label);
  60. }
  61. key->set_secret(auth_key_.secret);
  62. cryptohome::MountRequest mount;
  63. mount.set_hidden_mount(true);
  64. chromeos::CryptohomeClient::Get()->MountEx(
  65. cryptohome::CreateAccountIdentifierFromAccountId(account_id_), auth,
  66. mount,
  67. base::BindOnce(&PreSigninPolicyFetcher::OnMountTemporaryUserHome,
  68. weak_ptr_factory_.GetWeakPtr()));
  69. }
  70. bool PreSigninPolicyFetcher::ForceTimeoutForTesting() {
  71. if (!policy_fetch_timeout_.IsRunning())
  72. return false;
  73. policy_fetch_timeout_.Stop();
  74. OnPolicyFetchTimeout();
  75. return true;
  76. }
  77. void PreSigninPolicyFetcher::OnMountTemporaryUserHome(
  78. base::Optional<cryptohome::BaseReply> reply) {
  79. if (MountExReplyToMountError(reply) != cryptohome::MOUNT_ERROR_NONE) {
  80. LOG(ERROR) << "Temporary user home mount failed.";
  81. NotifyCallback(PolicyFetchResult::ERROR, nullptr);
  82. return;
  83. }
  84. session_manager_client_->RetrievePolicyForUserWithoutSession(
  85. cryptohome::CreateAccountIdentifierFromAccountId(account_id_),
  86. base::BindOnce(&PreSigninPolicyFetcher::OnCachedPolicyRetrieved,
  87. weak_ptr_factory_.GetWeakPtr()));
  88. }
  89. void PreSigninPolicyFetcher::OnCachedPolicyRetrieved(
  90. RetrievePolicyResponseType retrieve_policy_response,
  91. const std::string& policy_blob) {
  92. // We only need the cached policy key if there was policy and if the device is
  93. // not joined to Active Directory (policy blobs from Active Directory servers
  94. // are not signed).
  95. if (!policy_blob.empty() && !is_active_directory_managed_) {
  96. base::FilePath policy_key_dir;
  97. CHECK(base::PathService::Get(chromeos::dbus_paths::DIR_USER_POLICY_KEYS,
  98. &policy_key_dir));
  99. cached_policy_key_loader_ = std::make_unique<CachedPolicyKeyLoaderChromeOS>(
  100. cryptohome_client_, task_runner_, account_id_, policy_key_dir);
  101. cached_policy_key_loader_->EnsurePolicyKeyLoaded(base::BindOnce(
  102. &PreSigninPolicyFetcher::OnPolicyKeyLoaded,
  103. weak_ptr_factory_.GetWeakPtr(), retrieve_policy_response, policy_blob));
  104. } else {
  105. // Skip and pretend we've loaded policy key. We won't need it anyway,
  106. // because there is no policy to validate or because it's not signed (Active
  107. // Directory).
  108. OnPolicyKeyLoaded(retrieve_policy_response, policy_blob);
  109. }
  110. }
  111. void PreSigninPolicyFetcher::OnPolicyKeyLoaded(
  112. RetrievePolicyResponseType retrieve_policy_response,
  113. const std::string& policy_blob) {
  114. cryptohome_client_->UnmountEx(
  115. cryptohome::UnmountRequest(),
  116. base::BindOnce(&PreSigninPolicyFetcher::OnUnmountTemporaryUserHome,
  117. weak_ptr_factory_.GetWeakPtr(), retrieve_policy_response,
  118. policy_blob));
  119. }
  120. void PreSigninPolicyFetcher::OnUnmountTemporaryUserHome(
  121. RetrievePolicyResponseType retrieve_policy_response,
  122. const std::string& policy_blob,
  123. base::Optional<cryptohome::BaseReply> reply) {
  124. if (BaseReplyToMountError(reply) != cryptohome::MOUNT_ERROR_NONE) {
  125. // The temporary userhome mount could not be unmounted. Log an error and
  126. // continue, and hope that the unmount will be successful on the next mount
  127. // (temporary user homes are automatically unmounted by cryptohomed on every
  128. // mount request).
  129. LOG(ERROR) << "Couldn't unmount temporary mount point";
  130. }
  131. if (retrieve_policy_response != RetrievePolicyResponseType::SUCCESS) {
  132. NotifyCallback(PolicyFetchResult::ERROR, nullptr);
  133. return;
  134. }
  135. if (policy_blob.empty()) {
  136. VLOG(1) << "No cached policy.";
  137. NotifyCallback(PolicyFetchResult::NO_POLICY, nullptr);
  138. return;
  139. }
  140. // Parse policy.
  141. auto policy = std::make_unique<em::PolicyFetchResponse>();
  142. if (!policy->ParseFromString(policy_blob)) {
  143. NotifyCallback(PolicyFetchResult::ERROR, nullptr);
  144. return;
  145. }
  146. // Before validating, check that we have a cached policy key. This does not
  147. // apply to Active Directory joined devices (cached policy is unsigned there).
  148. if (!is_active_directory_managed_ &&
  149. cached_policy_key_loader_->cached_policy_key().empty()) {
  150. LOG(ERROR) << "No cached policy key loaded.";
  151. NotifyCallback(PolicyFetchResult::ERROR, nullptr);
  152. return;
  153. }
  154. // Validate policy from session_manager.
  155. UserCloudPolicyValidator::StartValidation(
  156. CreateValidatorForCachedPolicy(std::move(policy)),
  157. base::BindOnce(&PreSigninPolicyFetcher::OnCachedPolicyValidated,
  158. weak_ptr_factory_.GetWeakPtr()));
  159. }
  160. void PreSigninPolicyFetcher::OnCachedPolicyValidated(
  161. UserCloudPolicyValidator* validator) {
  162. if (!validator->success()) {
  163. NotifyCallback(PolicyFetchResult::ERROR, nullptr);
  164. return;
  165. }
  166. policy_data_ = std::move(validator->policy_data());
  167. policy_payload_ = std::move(validator->payload());
  168. if (is_active_directory_managed_) {
  169. // For AD, we don't support fresh policy fetch at the moment. Simply exit
  170. // with cached policy.
  171. NotifyCallback(PolicyFetchResult::SUCCESS, std::move(policy_payload_));
  172. return;
  173. }
  174. // Try to retrieve fresh policy.
  175. std::vector<std::string> user_affiliation_ids(
  176. policy_data_->user_affiliation_ids().begin(),
  177. policy_data_->user_affiliation_ids().end());
  178. cloud_policy_client_->SetupRegistration(policy_data_->request_token(),
  179. policy_data_->device_id(),
  180. user_affiliation_ids);
  181. cloud_policy_client_->AddPolicyTypeToFetch(
  182. dm_protocol::kChromeUserPolicyType,
  183. std::string() /* settings_entity_id */);
  184. if (policy_data_->has_public_key_version()) {
  185. cloud_policy_client_->set_public_key_version(
  186. policy_data_->public_key_version());
  187. }
  188. cloud_policy_client_->AddObserver(this);
  189. // Start a timer that will limit how long we wait for fresh policy.
  190. policy_fetch_timeout_.Start(
  191. FROM_HERE, base::TimeDelta::FromSeconds(kPolicyFetchTimeoutSecs),
  192. base::BindOnce(&PreSigninPolicyFetcher::OnPolicyFetchTimeout,
  193. weak_ptr_factory_.GetWeakPtr()));
  194. cloud_policy_client_->FetchPolicy();
  195. }
  196. void PreSigninPolicyFetcher::OnPolicyFetched(CloudPolicyClient* client) {
  197. policy_fetch_timeout_.Stop();
  198. const em::PolicyFetchResponse* fetched_policy =
  199. cloud_policy_client_->GetPolicyFor(
  200. dm_protocol::kChromeUserPolicyType,
  201. std::string() /* settings_entity_id */);
  202. if (!fetched_policy || !fetched_policy->has_policy_data()) {
  203. // policy_payload_ still holds cached policy loaded from session_manager.
  204. NotifyCallback(PolicyFetchResult::SUCCESS, std::move(policy_payload_));
  205. return;
  206. }
  207. // Make a copy because there's currently no way to transfer ownership out of
  208. // CloudPolicyClient.
  209. auto fetched_policy_copy =
  210. std::make_unique<em::PolicyFetchResponse>(*fetched_policy);
  211. // Validate fresh policy.
  212. UserCloudPolicyValidator::StartValidation(
  213. CreateValidatorForFetchedPolicy(std::move(fetched_policy_copy)),
  214. base::BindOnce(&PreSigninPolicyFetcher::OnFetchedPolicyValidated,
  215. weak_ptr_factory_.GetWeakPtr()));
  216. }
  217. void PreSigninPolicyFetcher::OnRegistrationStateChanged(
  218. CloudPolicyClient* client) {
  219. // Ignored.
  220. }
  221. void PreSigninPolicyFetcher::OnClientError(CloudPolicyClient* client) {
  222. policy_fetch_timeout_.Stop();
  223. VLOG(1) << "Fresh policy fetch failed.";
  224. // policy_payload_ still holds cached policy loaded from session_manager.
  225. NotifyCallback(PolicyFetchResult::SUCCESS, std::move(policy_payload_));
  226. }
  227. void PreSigninPolicyFetcher::OnPolicyFetchTimeout() {
  228. VLOG(1) << "Fresh policy fetch timed out.";
  229. // Invalidate all weak pointrs so OnPolicyFetched is not called back anymore.
  230. weak_ptr_factory_.InvalidateWeakPtrs();
  231. NotifyCallback(PolicyFetchResult::SUCCESS, std::move(policy_payload_));
  232. }
  233. void PreSigninPolicyFetcher::OnFetchedPolicyValidated(
  234. UserCloudPolicyValidator* validator) {
  235. if (!validator->success()) {
  236. VLOG(1) << "Validation of fetched policy failed.";
  237. // Return the cached policy.
  238. NotifyCallback(PolicyFetchResult::SUCCESS, std::move(policy_payload_));
  239. return;
  240. }
  241. policy_data_ = std::move(validator->policy_data());
  242. policy_payload_ = std::move(validator->payload());
  243. NotifyCallback(PolicyFetchResult::SUCCESS, std::move(policy_payload_));
  244. }
  245. void PreSigninPolicyFetcher::NotifyCallback(
  246. PolicyFetchResult result,
  247. std::unique_ptr<em::CloudPolicySettings> policy_payload) {
  248. // Clean up instances created during the policy fetch procedure.
  249. cached_policy_key_loader_.reset();
  250. policy_data_.reset();
  251. if (cloud_policy_client_) {
  252. cloud_policy_client_->RemoveObserver(this);
  253. }
  254. DCHECK(callback_);
  255. std::move(callback_).Run(result, std::move(policy_payload));
  256. }
  257. std::unique_ptr<UserCloudPolicyValidator>
  258. PreSigninPolicyFetcher::CreateValidatorForCachedPolicy(
  259. std::unique_ptr<em::PolicyFetchResponse> policy) {
  260. auto validator = std::make_unique<UserCloudPolicyValidator>(std::move(policy),
  261. task_runner_);
  262. validator->ValidatePolicyType(dm_protocol::kChromeUserPolicyType);
  263. validator->ValidatePayload();
  264. if (!is_active_directory_managed_) {
  265. // Also validate the user and the signature (except for authpolicy).
  266. validator->ValidateUser(account_id_);
  267. validator->ValidateSignature(
  268. cached_policy_key_loader_->cached_policy_key());
  269. }
  270. return validator;
  271. }
  272. std::unique_ptr<UserCloudPolicyValidator>
  273. PreSigninPolicyFetcher::CreateValidatorForFetchedPolicy(
  274. std::unique_ptr<em::PolicyFetchResponse> policy) {
  275. // Configure the validator to validate based on cached policy.
  276. auto validator = std::make_unique<UserCloudPolicyValidator>(std::move(policy),
  277. task_runner_);
  278. validator->ValidatePolicyType(dm_protocol::kChromeUserPolicyType);
  279. validator->ValidateAgainstCurrentPolicy(
  280. policy_data_.get(), CloudPolicyValidatorBase::TIMESTAMP_VALIDATED,
  281. CloudPolicyValidatorBase::DM_TOKEN_REQUIRED,
  282. CloudPolicyValidatorBase::DEVICE_ID_REQUIRED);
  283. validator->ValidatePayload();
  284. if (!is_active_directory_managed_) {
  285. // Also validate the signature.
  286. const std::string domain = gaia::ExtractDomainName(
  287. gaia::CanonicalizeEmail(account_id_.GetUserEmail()));
  288. validator->ValidateSignatureAllowingRotation(
  289. cached_policy_key_loader_->cached_policy_key(), domain);
  290. }
  291. return validator;
  292. }
  293. } // namespace policy