1 // Copyright 2016 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/policy/active_directory_policy_manager.h"
6
7 #include <string>
8 #include <utility>
9
10 #include "base/logging.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/chromeos/authpolicy/authpolicy_helper.h"
13 #include "chrome/browser/chromeos/login/users/affiliation.h"
14 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
15 #include "chrome/browser/net/system_network_context_manager.h"
16 #include "chromeos/cryptohome/cryptohome_parameters.h"
17 #include "chromeos/dbus/login_manager/policy_descriptor.pb.h"
18 #include "chromeos/network/onc/variable_expander.h"
19 #include "components/policy/core/common/cloud/cloud_external_data_manager.h"
20 #include "components/policy/core/common/cloud/component_cloud_policy_store.h"
21 #include "components/policy/core/common/policy_bundle.h"
22 #include "components/policy/core/common/policy_namespace.h"
23 #include "components/policy/policy_constants.h"
24 #include "services/network/public/cpp/shared_url_loader_factory.h"
25
26 namespace em = enterprise_management;
27
28 namespace policy {
29 namespace {
30
31 // List of policies where variables like ${MACHINE_NAME} should be expanded.
32 constexpr const char* kPoliciesToExpand[] = {key::kNativePrinters,
33 key::kPrinters};
34
35 // Fetch policy every 90 minutes which matches the Windows default:
36 // https://technet.microsoft.com/en-us/library/cc940895.aspx
37 constexpr base::TimeDelta kFetchInterval = base::TimeDelta::FromMinutes(90);
38
RunRefreshCallback(base::OnceCallback<void (bool success)> callback,authpolicy::ErrorType error)39 void RunRefreshCallback(base::OnceCallback<void(bool success)> callback,
40 authpolicy::ErrorType error) {
41 std::move(callback).Run(error == authpolicy::ERROR_NONE);
42 }
43
44 } // namespace
45
46 ActiveDirectoryPolicyManager::~ActiveDirectoryPolicyManager() = default;
47
Init(SchemaRegistry * registry)48 void ActiveDirectoryPolicyManager::Init(SchemaRegistry* registry) {
49 ConfigurationPolicyProvider::Init(registry);
50
51 store_->AddObserver(this);
52 if (!store_->is_initialized()) {
53 store_->Load();
54 }
55
56 // Does nothing if |store_| hasn't yet initialized.
57 PublishPolicy();
58
59 scheduler_ = std::make_unique<PolicyScheduler>(
60 base::BindRepeating(&ActiveDirectoryPolicyManager::DoPolicyFetch,
61 weak_ptr_factory_.GetWeakPtr()),
62 base::BindRepeating(&ActiveDirectoryPolicyManager::OnPolicyFetched,
63 weak_ptr_factory_.GetWeakPtr()),
64 kFetchInterval);
65
66 if (external_data_manager_) {
67 // Use the system network context here instead of a context derived from the
68 // Profile because Connect() is called before the profile is fully
69 // initialized (required so we can perform the initial policy load).
70 // Note: The network context can be null for tests and for device policy.
71 external_data_manager_->Connect(
72 g_browser_process->system_network_context_manager()
73 ? g_browser_process->system_network_context_manager()
74 ->GetSharedURLLoaderFactory()
75 : nullptr);
76 }
77
78 authpolicy_helper_ = std::make_unique<chromeos::AuthPolicyHelper>();
79 }
80
Shutdown()81 void ActiveDirectoryPolicyManager::Shutdown() {
82 if (external_data_manager_)
83 external_data_manager_->Disconnect();
84 extension_policy_service_.reset();
85 store_->RemoveObserver(this);
86 ConfigurationPolicyProvider::Shutdown();
87 }
88
IsInitializationComplete(PolicyDomain domain) const89 bool ActiveDirectoryPolicyManager::IsInitializationComplete(
90 PolicyDomain domain) const {
91 if (domain == POLICY_DOMAIN_CHROME)
92 return store_->is_initialized();
93 if (domain == extension_policy_domain_) {
94 return extension_policy_service_ &&
95 extension_policy_service_->policy() != nullptr;
96 }
97 return true;
98 }
99
IsFirstPolicyLoadComplete(PolicyDomain domain) const100 bool ActiveDirectoryPolicyManager::IsFirstPolicyLoadComplete(
101 PolicyDomain domain) const {
102 if (domain == POLICY_DOMAIN_CHROME)
103 return store()->first_policies_loaded();
104 if (domain == extension_policy_domain_) {
105 return extension_policy_service_ &&
106 extension_policy_service_->policy() != nullptr;
107 }
108 return true;
109 }
110
RefreshPolicies()111 void ActiveDirectoryPolicyManager::RefreshPolicies() {
112 scheduler_->ScheduleTaskNow();
113 }
114
OnStoreLoaded(CloudPolicyStore * cloud_policy_store)115 void ActiveDirectoryPolicyManager::OnStoreLoaded(
116 CloudPolicyStore* cloud_policy_store) {
117 DCHECK_EQ(store_.get(), cloud_policy_store);
118 PublishPolicy();
119 if (fetch_ever_completed_) {
120 // Policy is guaranteed to be up to date with the previous fetch result
121 // because OnPolicyFetched() cancels any potentially running Load()
122 // operations.
123 CancelWaitForInitialPolicy();
124 }
125 }
126
OnStoreError(CloudPolicyStore * cloud_policy_store)127 void ActiveDirectoryPolicyManager::OnStoreError(
128 CloudPolicyStore* cloud_policy_store) {
129 DCHECK_EQ(store_.get(), cloud_policy_store);
130 // Publish policy (even though it hasn't changed) in order to signal load
131 // complete on the ConfigurationPolicyProvider interface. Technically, this is
132 // only required on the first load, but doesn't hurt in any case.
133 PublishPolicy();
134 if (fetch_ever_completed_) {
135 CancelWaitForInitialPolicy();
136 }
137 }
138
ActiveDirectoryPolicyManager(std::unique_ptr<CloudPolicyStore> store,std::unique_ptr<CloudExternalDataManager> external_data_manager,PolicyDomain extension_policy_domain)139 ActiveDirectoryPolicyManager::ActiveDirectoryPolicyManager(
140 std::unique_ptr<CloudPolicyStore> store,
141 std::unique_ptr<CloudExternalDataManager> external_data_manager,
142 PolicyDomain extension_policy_domain)
143 : store_(std::move(store)),
144 external_data_manager_(std::move(external_data_manager)),
145 extension_policy_domain_(extension_policy_domain) {
146 DCHECK(extension_policy_domain_ == POLICY_DOMAIN_EXTENSIONS ||
147 extension_policy_domain_ == POLICY_DOMAIN_SIGNIN_EXTENSIONS);
148 }
149
OnComponentActiveDirectoryPolicyUpdated()150 void ActiveDirectoryPolicyManager::OnComponentActiveDirectoryPolicyUpdated() {
151 PublishPolicy();
152 }
153
PublishPolicy()154 void ActiveDirectoryPolicyManager::PublishPolicy() {
155 if (!store_->is_initialized())
156 return;
157 OnPublishPolicy();
158
159 std::unique_ptr<PolicyBundle> bundle = std::make_unique<PolicyBundle>();
160 PolicyMap& policy_map =
161 bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
162 policy_map.CopyFrom(store_->policy_map());
163 if (extension_policy_service_ && extension_policy_service_->policy())
164 bundle->MergeFrom(*extension_policy_service_->policy());
165
166 // Overwrite the source which is POLICY_SOURCE_CLOUD by default.
167 // TODO(tnagel): Rename CloudPolicyStore to PolicyStore and make the source
168 // configurable, then drop PolicyMap::SetSourceForAll().
169 policy_map.SetSourceForAll(POLICY_SOURCE_ACTIVE_DIRECTORY);
170 SetEnterpriseUsersDefaults(&policy_map);
171
172 // Expand e.g. ${MACHINE_NAME} for a selected set of policies.
173 ExpandVariables(&policy_map);
174
175 // Policy is ready, send it off.
176 UpdatePolicy(std::move(bundle));
177 }
178
CreateExtensionPolicyService(PolicyScope scope,login_manager::PolicyAccountType account_type,const AccountId & account_id,SchemaRegistry * schema_registry)179 void ActiveDirectoryPolicyManager::CreateExtensionPolicyService(
180 PolicyScope scope,
181 login_manager::PolicyAccountType account_type,
182 const AccountId& account_id,
183 SchemaRegistry* schema_registry) {
184 std::string cryptohome_id;
185 if (!account_id.empty())
186 cryptohome_id = cryptohome::Identification(account_id).id();
187
188 // Create the service for sign-in extensions (device scope) or user profile
189 // extensions (user scope).
190 DCHECK(!extension_policy_service_);
191 extension_policy_service_ =
192 std::make_unique<ComponentActiveDirectoryPolicyService>(
193 scope, extension_policy_domain_, account_type, cryptohome_id, this,
194 schema_registry);
195 }
196
OnPolicyFetched(bool success)197 void ActiveDirectoryPolicyManager::OnPolicyFetched(bool success) {
198 fetch_ever_completed_ = true;
199 // In case of failure try to proceed with cached policy.
200 if (!success && store()->is_initialized())
201 CancelWaitForInitialPolicy();
202 // Load/retrieve independently of success or failure to keep in sync with the
203 // state in session manager. This cancels any potentially running Load()
204 // operations thus it is guaranteed that at the next OnStoreLoaded()
205 // invocation the policy is up-to-date with what was fetched.
206 store_->Load();
207 if (extension_policy_service_)
208 extension_policy_service_->RetrievePolicies();
209 }
210
ExpandVariables(PolicyMap * policy_map)211 void ActiveDirectoryPolicyManager::ExpandVariables(PolicyMap* policy_map) {
212 const em::PolicyData* policy = store_->policy();
213 if (!policy || policy_map->empty())
214 return;
215 if (policy->machine_name().empty()) {
216 LOG(ERROR) << "Cannot expand machine_name (empty string in policy)";
217 return;
218 }
219
220 chromeos::VariableExpander expander(
221 {{"MACHINE_NAME", policy->machine_name()}});
222 for (const char* policy_name : kPoliciesToExpand) {
223 base::Value* value = policy_map->GetMutableValue(policy_name);
224 if (value) {
225 if (!expander.ExpandValue(value)) {
226 LOG(ERROR) << "Failed to expand at least one variable in policy "
227 << policy_name;
228 }
229 }
230 }
231 }
232
UserActiveDirectoryPolicyManager(const AccountId & account_id,bool policy_required,base::TimeDelta initial_policy_fetch_timeout,base::OnceClosure exit_session,std::unique_ptr<CloudPolicyStore> store,std::unique_ptr<CloudExternalDataManager> external_data_manager)233 UserActiveDirectoryPolicyManager::UserActiveDirectoryPolicyManager(
234 const AccountId& account_id,
235 bool policy_required,
236 base::TimeDelta initial_policy_fetch_timeout,
237 base::OnceClosure exit_session,
238 std::unique_ptr<CloudPolicyStore> store,
239 std::unique_ptr<CloudExternalDataManager> external_data_manager)
240 : ActiveDirectoryPolicyManager(
241 std::move(store),
242 std::move(external_data_manager),
243 POLICY_DOMAIN_EXTENSIONS /* extension_policy_domain */),
244 account_id_(account_id),
245 policy_required_(policy_required),
246 waiting_for_initial_policy_fetch_(
247 !initial_policy_fetch_timeout.is_zero()),
248 exit_session_(std::move(exit_session)) {
249 DCHECK(!initial_policy_fetch_timeout.is_max());
250 // Delaying initialization complete is intended for user policy only.
251 if (waiting_for_initial_policy_fetch_) {
252 initial_policy_timeout_.Start(
253 FROM_HERE, initial_policy_fetch_timeout,
254 base::BindOnce(
255 &UserActiveDirectoryPolicyManager::OnBlockingFetchTimeout,
256 weak_ptr_factory_.GetWeakPtr()));
257 }
258 }
259
260 UserActiveDirectoryPolicyManager::~UserActiveDirectoryPolicyManager() = default;
261
Init(SchemaRegistry * registry)262 void UserActiveDirectoryPolicyManager::Init(SchemaRegistry* registry) {
263 DCHECK(store()->is_initialized() || waiting_for_initial_policy_fetch_ ||
264 !policy_required_ /* policy may not be required in tests */);
265 if (store()->is_initialized() && !store()->has_policy() && policy_required_) {
266 // Exit the session in case of immediate load if policy is required.
267 LOG(ERROR) << "Policy from forced immediate load could not be obtained. "
268 << "Aborting profile initialization";
269 if (exit_session_)
270 std::move(exit_session_).Run();
271 }
272 ActiveDirectoryPolicyManager::Init(registry);
273
274 // Create the extension policy handler here. This is different from the device
275 // policy manager, which can't do this in Init() because it needs to wait for
276 // the sign-in profile's schema registry.
277 CreateExtensionPolicyService(POLICY_SCOPE_USER,
278 login_manager::ACCOUNT_TYPE_USER, account_id_,
279 registry);
280 }
281
IsInitializationComplete(PolicyDomain domain) const282 bool UserActiveDirectoryPolicyManager::IsInitializationComplete(
283 PolicyDomain domain) const {
284 if (waiting_for_initial_policy_fetch_)
285 return false;
286
287 return ActiveDirectoryPolicyManager::IsInitializationComplete(domain);
288 }
289
ForceTimeoutForTesting()290 void UserActiveDirectoryPolicyManager::ForceTimeoutForTesting() {
291 DCHECK(initial_policy_timeout_.IsRunning());
292 // Stop the timer to mimic what happens when a real timer fires, then invoke
293 // the timer callback directly.
294 initial_policy_timeout_.Stop();
295 OnBlockingFetchTimeout();
296 }
297
DoPolicyFetch(PolicyScheduler::TaskCallback callback)298 void UserActiveDirectoryPolicyManager::DoPolicyFetch(
299 PolicyScheduler::TaskCallback callback) {
300 authpolicy_helper()->RefreshUserPolicy(
301 account_id_, base::BindOnce(&RunRefreshCallback, std::move(callback)));
302 }
303
CancelWaitForInitialPolicy()304 void UserActiveDirectoryPolicyManager::CancelWaitForInitialPolicy() {
305 if (!waiting_for_initial_policy_fetch_)
306 return;
307
308 initial_policy_timeout_.Stop();
309
310 // If the conditions to continue profile initialization are not met, the user
311 // session is exited and initialization is not set as completed.
312 if (!store()->has_policy() && policy_required_) {
313 // If there's no policy at all (not even cached), but policy is required,
314 // the user session must not continue.
315 LOG(ERROR) << "Policy could not be obtained. "
316 << "Aborting profile initialization";
317 if (exit_session_)
318 std::move(exit_session_).Run();
319 return;
320 }
321
322 // Set initialization complete.
323 waiting_for_initial_policy_fetch_ = false;
324
325 // Publish policy (even though it hasn't changed) in order to signal load
326 // complete on the ConfigurationPolicyProvider interface.
327 PublishPolicy();
328 }
329
OnPublishPolicy()330 void UserActiveDirectoryPolicyManager::OnPublishPolicy() {
331 const em::PolicyData* policy_data = store()->policy();
332 if (!policy_data)
333 return;
334
335 // Update user affiliation IDs.
336 chromeos::AffiliationIDSet set_of_user_affiliation_ids(
337 policy_data->user_affiliation_ids().begin(),
338 policy_data->user_affiliation_ids().end());
339
340 chromeos::ChromeUserManager::Get()->SetUserAffiliation(
341 account_id_, set_of_user_affiliation_ids);
342 }
343
OnBlockingFetchTimeout()344 void UserActiveDirectoryPolicyManager::OnBlockingFetchTimeout() {
345 DCHECK(waiting_for_initial_policy_fetch_);
346 LOG(WARNING) << "Timed out while waiting for the policy fetch. "
347 << "The session will start with the cached policy.";
348 if ((fetch_ever_completed_ && !store()->is_initialized()) ||
349 (!fetch_ever_completed_ && !store()->has_policy())) {
350 // Waiting for store to load if policy was fetched. Or for policy fetch to
351 // complete if there is no cached policy.
352 return;
353 }
354 CancelWaitForInitialPolicy();
355 }
356
DeviceActiveDirectoryPolicyManager(std::unique_ptr<CloudPolicyStore> store)357 DeviceActiveDirectoryPolicyManager::DeviceActiveDirectoryPolicyManager(
358 std::unique_ptr<CloudPolicyStore> store)
359 : ActiveDirectoryPolicyManager(
360 std::move(store),
361 nullptr /* external_data_manager */,
362 POLICY_DOMAIN_SIGNIN_EXTENSIONS /* extension_policy_domain */) {}
363
Shutdown()364 void DeviceActiveDirectoryPolicyManager::Shutdown() {
365 ActiveDirectoryPolicyManager::Shutdown();
366 signin_profile_forwarding_schema_registry_.reset();
367 }
368
SetSigninProfileSchemaRegistry(SchemaRegistry * schema_registry)369 void DeviceActiveDirectoryPolicyManager::SetSigninProfileSchemaRegistry(
370 SchemaRegistry* schema_registry) {
371 DCHECK(!signin_profile_forwarding_schema_registry_);
372 signin_profile_forwarding_schema_registry_ =
373 std::make_unique<ForwardingSchemaRegistry>(schema_registry);
374
375 CreateExtensionPolicyService(
376 POLICY_SCOPE_MACHINE, login_manager::ACCOUNT_TYPE_DEVICE,
377 EmptyAccountId(), signin_profile_forwarding_schema_registry_.get());
378 }
379
380 DeviceActiveDirectoryPolicyManager::~DeviceActiveDirectoryPolicyManager() =
381 default;
382
DoPolicyFetch(base::OnceCallback<void (bool success)> callback)383 void DeviceActiveDirectoryPolicyManager::DoPolicyFetch(
384 base::OnceCallback<void(bool success)> callback) {
385 authpolicy_helper()->RefreshDevicePolicy(
386 base::BindOnce(&RunRefreshCallback, std::move(callback)));
387 }
388
389 } // namespace policy
390