Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: chrome/browser/chromeos/policy/enterprise_install_attributes.cc

Issue 2382833002: Rename policy::EnterpriseInstallAttributes to chromeos::InstallAttributes. (Closed)
Patch Set: Add missing #includes. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/policy/enterprise_install_attributes.h"
6
7 #include <stddef.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/files/file_util.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/metrics/histogram_base.h"
17 #include "base/metrics/histogram_macros.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/time/time.h"
21 #include "chrome/browser/chromeos/policy/proto/install_attributes.pb.h"
22 #include "chromeos/cryptohome/cryptohome_util.h"
23 #include "chromeos/dbus/dbus_thread_manager.h"
24 #include "google_apis/gaia/gaia_auth_util.h"
25
26 namespace policy {
27
28 namespace cryptohome_util = chromeos::cryptohome_util;
29
30 namespace {
31
32 // Number of TPM lock state query retries during consistency check.
33 int kDbusRetryCount = 12;
34
35 // Interval of TPM lock state query retries during consistency check.
36 int kDbusRetryIntervalInSeconds = 5;
37
38 bool ReadMapKey(const std::map<std::string, std::string>& map,
39 const std::string& key,
40 std::string* value) {
41 std::map<std::string, std::string>::const_iterator entry = map.find(key);
42 if (entry == map.end())
43 return false;
44
45 *value = entry->second;
46 return true;
47 }
48
49 } // namespace
50
51 // static
52 std::string
53 EnterpriseInstallAttributes::GetEnterpriseOwnedInstallAttributesBlobForTesting(
54 const std::string& user_name) {
55 cryptohome::SerializedInstallAttributes install_attrs_proto;
56 cryptohome::SerializedInstallAttributes::Attribute* attribute = NULL;
57
58 attribute = install_attrs_proto.add_attributes();
59 attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseOwned);
60 attribute->set_value("true");
61
62 attribute = install_attrs_proto.add_attributes();
63 attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseUser);
64 attribute->set_value(user_name);
65
66 return install_attrs_proto.SerializeAsString();
67 }
68
69 EnterpriseInstallAttributes::EnterpriseInstallAttributes(
70 chromeos::CryptohomeClient* cryptohome_client)
71 : device_locked_(false),
72 consistency_check_running_(false),
73 device_lock_running_(false),
74 registration_mode_(DEVICE_MODE_PENDING),
75 cryptohome_client_(cryptohome_client),
76 weak_ptr_factory_(this) {
77 }
78
79 EnterpriseInstallAttributes::~EnterpriseInstallAttributes() {}
80
81 void EnterpriseInstallAttributes::Init(const base::FilePath& cache_file) {
82 DCHECK(!device_locked_);
83
84 // Mark the consistency check as running to ensure that LockDevice() is
85 // blocked, but wait for the cryptohome service to be available before
86 // actually calling TriggerConsistencyCheck().
87 consistency_check_running_ = true;
88 cryptohome_client_->WaitForServiceToBeAvailable(base::Bind(
89 &EnterpriseInstallAttributes::OnCryptohomeServiceInitiallyAvailable,
90 weak_ptr_factory_.GetWeakPtr()));
91
92 if (!base::PathExists(cache_file))
93 return;
94
95 device_locked_ = true;
96
97 char buf[16384];
98 int len = base::ReadFile(cache_file, buf, sizeof(buf));
99 if (len == -1 || len >= static_cast<int>(sizeof(buf))) {
100 PLOG(ERROR) << "Failed to read " << cache_file.value();
101 return;
102 }
103
104 cryptohome::SerializedInstallAttributes install_attrs_proto;
105 if (!install_attrs_proto.ParseFromArray(buf, len)) {
106 LOG(ERROR) << "Failed to parse install attributes cache.";
107 return;
108 }
109
110 google::protobuf::RepeatedPtrField<
111 const cryptohome::SerializedInstallAttributes::Attribute>::iterator entry;
112 std::map<std::string, std::string> attr_map;
113 for (entry = install_attrs_proto.attributes().begin();
114 entry != install_attrs_proto.attributes().end();
115 ++entry) {
116 // The protobuf values unfortunately contain terminating null characters, so
117 // we have to sanitize the value here.
118 attr_map.insert(std::make_pair(entry->name(),
119 std::string(entry->value().c_str())));
120 }
121
122 DecodeInstallAttributes(attr_map);
123 }
124
125 void EnterpriseInstallAttributes::ReadImmutableAttributes(
126 const base::Closure& callback) {
127 if (device_locked_) {
128 callback.Run();
129 return;
130 }
131
132 cryptohome_client_->InstallAttributesIsReady(
133 base::Bind(&EnterpriseInstallAttributes::ReadAttributesIfReady,
134 weak_ptr_factory_.GetWeakPtr(),
135 callback));
136 }
137
138 void EnterpriseInstallAttributes::ReadAttributesIfReady(
139 const base::Closure& callback,
140 chromeos::DBusMethodCallStatus call_status,
141 bool result) {
142 if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS && result) {
143 registration_mode_ = DEVICE_MODE_NOT_SET;
144 if (!cryptohome_util::InstallAttributesIsInvalid() &&
145 !cryptohome_util::InstallAttributesIsFirstInstall()) {
146 device_locked_ = true;
147
148 static const char* const kEnterpriseAttributes[] = {
149 kAttrEnterpriseDeviceId,
150 kAttrEnterpriseDomain,
151 kAttrEnterpriseMode,
152 kAttrEnterpriseOwned,
153 kAttrEnterpriseUser,
154 kAttrConsumerKioskEnabled,
155 };
156 std::map<std::string, std::string> attr_map;
157 for (size_t i = 0; i < arraysize(kEnterpriseAttributes); ++i) {
158 std::string value;
159 if (cryptohome_util::InstallAttributesGet(kEnterpriseAttributes[i],
160 &value))
161 attr_map[kEnterpriseAttributes[i]] = value;
162 }
163
164 DecodeInstallAttributes(attr_map);
165 }
166 }
167 callback.Run();
168 }
169
170 void EnterpriseInstallAttributes::LockDevice(
171 const std::string& user,
172 DeviceMode device_mode,
173 const std::string& device_id,
174 const LockResultCallback& callback) {
175 DCHECK(!callback.is_null());
176 CHECK_EQ(device_lock_running_, false);
177 CHECK_NE(device_mode, DEVICE_MODE_PENDING);
178 CHECK_NE(device_mode, DEVICE_MODE_NOT_SET);
179
180 // Check for existing lock first.
181 if (device_locked_) {
182 if (device_mode != registration_mode_) {
183 callback.Run(LOCK_WRONG_MODE);
184 return;
185 }
186
187 switch (registration_mode_) {
188 case DEVICE_MODE_ENTERPRISE:
189 case DEVICE_MODE_LEGACY_RETAIL_MODE: {
190 // Check domain match for enterprise devices.
191 std::string domain = gaia::ExtractDomainName(user);
192 if (registration_domain_.empty() || domain != registration_domain_) {
193 callback.Run(LOCK_WRONG_DOMAIN);
194 return;
195 }
196 break;
197 }
198 case DEVICE_MODE_NOT_SET:
199 case DEVICE_MODE_PENDING:
200 // This case can't happen due to the CHECK_NE asserts above.
201 NOTREACHED();
202 break;
203 case DEVICE_MODE_CONSUMER:
204 case DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH:
205 // The user parameter is ignored for consumer devices.
206 break;
207 }
208
209 // Already locked in the right mode, signal success.
210 callback.Run(LOCK_SUCCESS);
211 return;
212 }
213
214 // In case the consistency check is still running, postpone the device locking
215 // until it has finished. This should not introduce additional delay since
216 // device locking must wait for TPM initialization anyways.
217 if (consistency_check_running_) {
218 CHECK(post_check_action_.is_null());
219 post_check_action_ = base::Bind(&EnterpriseInstallAttributes::LockDevice,
220 weak_ptr_factory_.GetWeakPtr(),
221 user,
222 device_mode,
223 device_id,
224 callback);
225 return;
226 }
227
228 device_lock_running_ = true;
229 cryptohome_client_->InstallAttributesIsReady(
230 base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady,
231 weak_ptr_factory_.GetWeakPtr(),
232 user,
233 device_mode,
234 device_id,
235 callback));
236 }
237
238 void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady(
239 const std::string& user,
240 DeviceMode device_mode,
241 const std::string& device_id,
242 const LockResultCallback& callback,
243 chromeos::DBusMethodCallStatus call_status,
244 bool result) {
245 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) {
246 device_lock_running_ = false;
247 callback.Run(LOCK_NOT_READY);
248 return;
249 }
250
251 // Clearing the TPM password seems to be always a good deal.
252 if (cryptohome_util::TpmIsEnabled() &&
253 !cryptohome_util::TpmIsBeingOwned() &&
254 cryptohome_util::TpmIsOwned()) {
255 cryptohome_client_->CallTpmClearStoredPasswordAndBlock();
256 }
257
258 // Make sure we really have a working InstallAttrs.
259 if (cryptohome_util::InstallAttributesIsInvalid()) {
260 LOG(ERROR) << "Install attributes invalid.";
261 device_lock_running_ = false;
262 callback.Run(LOCK_BACKEND_INVALID);
263 return;
264 }
265
266 if (!cryptohome_util::InstallAttributesIsFirstInstall()) {
267 LOG(ERROR) << "Install attributes already installed.";
268 device_lock_running_ = false;
269 callback.Run(LOCK_ALREADY_LOCKED);
270 return;
271 }
272
273 std::string mode = GetDeviceModeString(device_mode);
274 std::string registration_user;
275 if (!user.empty())
276 registration_user = gaia::CanonicalizeEmail(user);
277
278 if (device_mode == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH) {
279 // Set values in the InstallAttrs and lock it.
280 if (!cryptohome_util::InstallAttributesSet(kAttrConsumerKioskEnabled,
281 "true")) {
282 LOG(ERROR) << "Failed writing attributes.";
283 device_lock_running_ = false;
284 callback.Run(LOCK_SET_ERROR);
285 return;
286 }
287 } else {
288 std::string domain = gaia::ExtractDomainName(registration_user);
289 // Set values in the InstallAttrs and lock it.
290 if (!cryptohome_util::InstallAttributesSet(kAttrEnterpriseOwned, "true") ||
291 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseUser,
292 registration_user) ||
293 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDomain,
294 domain) ||
295 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseMode, mode) ||
296 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDeviceId,
297 device_id)) {
298 LOG(ERROR) << "Failed writing attributes.";
299 device_lock_running_ = false;
300 callback.Run(LOCK_SET_ERROR);
301 return;
302 }
303 }
304
305 if (!cryptohome_util::InstallAttributesFinalize() ||
306 cryptohome_util::InstallAttributesIsFirstInstall()) {
307 LOG(ERROR) << "Failed locking.";
308 device_lock_running_ = false;
309 callback.Run(LOCK_FINALIZE_ERROR);
310 return;
311 }
312
313 ReadImmutableAttributes(
314 base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes,
315 weak_ptr_factory_.GetWeakPtr(),
316 registration_user,
317 callback));
318 }
319
320 void EnterpriseInstallAttributes::OnReadImmutableAttributes(
321 const std::string& registration_user,
322 const LockResultCallback& callback) {
323
324 if (GetRegistrationUser() != registration_user) {
325 LOG(ERROR) << "Locked data doesn't match.";
326 device_lock_running_ = false;
327 callback.Run(LOCK_READBACK_ERROR);
328 return;
329 }
330
331 device_lock_running_ = false;
332 callback.Run(LOCK_SUCCESS);
333 }
334
335 bool EnterpriseInstallAttributes::IsEnterpriseDevice() const {
336 return device_locked_ && !registration_user_.empty();
337 }
338
339 bool EnterpriseInstallAttributes::IsConsumerKioskDeviceWithAutoLaunch() {
340 return device_locked_ &&
341 registration_mode_ == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
342 }
343
344 std::string EnterpriseInstallAttributes::GetDomain() const {
345 if (!IsEnterpriseDevice())
346 return std::string();
347
348 return registration_domain_;
349 }
350
351 std::string EnterpriseInstallAttributes::GetDeviceId() {
352 if (!IsEnterpriseDevice())
353 return std::string();
354
355 return registration_device_id_;
356 }
357
358 DeviceMode EnterpriseInstallAttributes::GetMode() {
359 return registration_mode_;
360 }
361
362 void EnterpriseInstallAttributes::TriggerConsistencyCheck(int dbus_retries) {
363 cryptohome_client_->TpmIsOwned(
364 base::Bind(&EnterpriseInstallAttributes::OnTpmOwnerCheckCompleted,
365 weak_ptr_factory_.GetWeakPtr(),
366 dbus_retries));
367 }
368
369 void EnterpriseInstallAttributes::OnTpmOwnerCheckCompleted(
370 int dbus_retries_remaining,
371 chromeos::DBusMethodCallStatus call_status,
372 bool result) {
373 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS &&
374 dbus_retries_remaining) {
375 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
376 FROM_HERE,
377 base::Bind(&EnterpriseInstallAttributes::TriggerConsistencyCheck,
378 weak_ptr_factory_.GetWeakPtr(), dbus_retries_remaining - 1),
379 base::TimeDelta::FromSeconds(kDbusRetryIntervalInSeconds));
380 return;
381 }
382
383 base::HistogramBase::Sample state = device_locked_;
384 state |= 0x2 * (registration_mode_ == DEVICE_MODE_ENTERPRISE);
385 if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS)
386 state |= 0x4 * result;
387 else
388 state = 0x8; // This case is not a bit mask.
389 UMA_HISTOGRAM_ENUMERATION("Enterprise.AttributesTPMConsistency", state, 9);
390
391 // Run any action (LockDevice call) that might have queued behind the
392 // consistency check.
393 consistency_check_running_ = false;
394 if (!post_check_action_.is_null()) {
395 post_check_action_.Run();
396 post_check_action_.Reset();
397 }
398 }
399
400 // Warning: The values for these keys (but not the keys themselves) are stored
401 // in the protobuf with a trailing zero. Also note that some of these constants
402 // have been copied to login_manager/device_policy_service.cc. Please make sure
403 // that all changes to the constants are reflected there as well.
404 const char EnterpriseInstallAttributes::kConsumerDeviceMode[] = "consumer";
405 const char EnterpriseInstallAttributes::kEnterpriseDeviceMode[] = "enterprise";
406 const char EnterpriseInstallAttributes::kLegacyRetailDeviceMode[] = "kiosk";
407 const char EnterpriseInstallAttributes::kConsumerKioskDeviceMode[] =
408 "consumer_kiosk";
409 const char EnterpriseInstallAttributes::kUnknownDeviceMode[] = "unknown";
410
411 const char EnterpriseInstallAttributes::kAttrEnterpriseDeviceId[] =
412 "enterprise.device_id";
413 const char EnterpriseInstallAttributes::kAttrEnterpriseDomain[] =
414 "enterprise.domain";
415 const char EnterpriseInstallAttributes::kAttrEnterpriseMode[] =
416 "enterprise.mode";
417 const char EnterpriseInstallAttributes::kAttrEnterpriseOwned[] =
418 "enterprise.owned";
419 const char EnterpriseInstallAttributes::kAttrEnterpriseUser[] =
420 "enterprise.user";
421 const char EnterpriseInstallAttributes::kAttrConsumerKioskEnabled[] =
422 "consumer.app_kiosk_enabled";
423
424 void EnterpriseInstallAttributes::OnCryptohomeServiceInitiallyAvailable(
425 bool service_is_ready) {
426 if (!service_is_ready)
427 LOG(ERROR) << "Failed waiting for cryptohome D-Bus service availability.";
428
429 // Start the consistency check even if we failed to wait for availability;
430 // hopefully the service will become available eventually.
431 TriggerConsistencyCheck(kDbusRetryCount);
432 }
433
434 std::string EnterpriseInstallAttributes::GetDeviceModeString(DeviceMode mode) {
435 switch (mode) {
436 case DEVICE_MODE_CONSUMER:
437 return EnterpriseInstallAttributes::kConsumerDeviceMode;
438 case DEVICE_MODE_ENTERPRISE:
439 return EnterpriseInstallAttributes::kEnterpriseDeviceMode;
440 case DEVICE_MODE_LEGACY_RETAIL_MODE:
441 return EnterpriseInstallAttributes::kLegacyRetailDeviceMode;
442 case DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH:
443 return EnterpriseInstallAttributes::kConsumerKioskDeviceMode;
444 case DEVICE_MODE_PENDING:
445 case DEVICE_MODE_NOT_SET:
446 break;
447 }
448 NOTREACHED() << "Invalid device mode: " << mode;
449 return EnterpriseInstallAttributes::kUnknownDeviceMode;
450 }
451
452 DeviceMode EnterpriseInstallAttributes::GetDeviceModeFromString(
453 const std::string& mode) {
454 if (mode == EnterpriseInstallAttributes::kConsumerDeviceMode)
455 return DEVICE_MODE_CONSUMER;
456 else if (mode == EnterpriseInstallAttributes::kEnterpriseDeviceMode)
457 return DEVICE_MODE_ENTERPRISE;
458 else if (mode == EnterpriseInstallAttributes::kLegacyRetailDeviceMode)
459 return DEVICE_MODE_LEGACY_RETAIL_MODE;
460 else if (mode == EnterpriseInstallAttributes::kConsumerKioskDeviceMode)
461 return DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
462 NOTREACHED() << "Unknown device mode string: " << mode;
463 return DEVICE_MODE_NOT_SET;
464 }
465
466 void EnterpriseInstallAttributes::DecodeInstallAttributes(
467 const std::map<std::string, std::string>& attr_map) {
468 std::string enterprise_owned;
469 std::string enterprise_user;
470 std::string consumer_kiosk_enabled;
471 if (ReadMapKey(attr_map, kAttrEnterpriseOwned, &enterprise_owned) &&
472 ReadMapKey(attr_map, kAttrEnterpriseUser, &enterprise_user) &&
473 enterprise_owned == "true" &&
474 !enterprise_user.empty()) {
475 registration_user_ = gaia::CanonicalizeEmail(enterprise_user);
476
477 // Initialize the mode to the legacy enterprise mode here and update
478 // below if more information is present.
479 registration_mode_ = DEVICE_MODE_ENTERPRISE;
480
481 // If we could extract basic setting we should try to extract the
482 // extended ones too. We try to set these to defaults as good as
483 // as possible if present, which could happen for device enrolled in
484 // pre 19 revisions of the code, before these new attributes were added.
485 if (ReadMapKey(attr_map, kAttrEnterpriseDomain, &registration_domain_))
486 registration_domain_ = gaia::CanonicalizeDomain(registration_domain_);
487 else
488 registration_domain_ = gaia::ExtractDomainName(registration_user_);
489
490 ReadMapKey(attr_map, kAttrEnterpriseDeviceId, &registration_device_id_);
491
492 std::string mode;
493 if (ReadMapKey(attr_map, kAttrEnterpriseMode, &mode))
494 registration_mode_ = GetDeviceModeFromString(mode);
495 } else if (ReadMapKey(attr_map,
496 kAttrConsumerKioskEnabled,
497 &consumer_kiosk_enabled) &&
498 consumer_kiosk_enabled == "true") {
499 registration_mode_ = DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
500 } else if (enterprise_user.empty() && enterprise_owned != "true") {
501 // |registration_user_| is empty on consumer devices.
502 registration_mode_ = DEVICE_MODE_CONSUMER;
503 }
504 }
505
506 std::string EnterpriseInstallAttributes::GetRegistrationUser() const {
507 if (!device_locked_)
508 return std::string();
509
510 return registration_user_;
511 }
512
513 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698