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.
5 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
10 #include "base/file_util.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "chrome/browser/policy/proto/chromeos/install_attributes.pb.h"
15 #include "chromeos/cryptohome/cryptohome_util.h"
16 #include "chromeos/dbus/dbus_thread_manager.h"
17 #include "google_apis/gaia/gaia_auth_util.h"
21 namespace cryptohome_util = chromeos::cryptohome_util;
25 // Translates DeviceMode constants to strings used in the lockbox.
26 std::string GetDeviceModeString(DeviceMode mode) {
28 case DEVICE_MODE_CONSUMER:
29 return EnterpriseInstallAttributes::kConsumerDeviceMode;
30 case DEVICE_MODE_ENTERPRISE:
31 return EnterpriseInstallAttributes::kEnterpiseDeviceMode;
32 case DEVICE_MODE_RETAIL_KIOSK:
33 return EnterpriseInstallAttributes::kRetailKioskDeviceMode;
34 case DEVICE_MODE_CONSUMER_KIOSK:
35 return EnterpriseInstallAttributes::kConsumerKioskDeviceMode;
36 case DEVICE_MODE_PENDING:
37 case DEVICE_MODE_NOT_SET:
40 NOTREACHED() << "Invalid device mode: " << mode;
41 return EnterpriseInstallAttributes::kUnknownDeviceMode;
44 // Translates strings used in the lockbox to DeviceMode values.
45 DeviceMode GetDeviceModeFromString(
46 const std::string& mode) {
47 if (mode == EnterpriseInstallAttributes::kConsumerDeviceMode)
48 return DEVICE_MODE_CONSUMER;
49 else if (mode == EnterpriseInstallAttributes::kEnterpiseDeviceMode)
50 return DEVICE_MODE_ENTERPRISE;
51 else if (mode == EnterpriseInstallAttributes::kRetailKioskDeviceMode)
52 return DEVICE_MODE_RETAIL_KIOSK;
53 else if (mode == EnterpriseInstallAttributes::kConsumerKioskDeviceMode)
54 return DEVICE_MODE_CONSUMER_KIOSK;
55 NOTREACHED() << "Unknown device mode string: " << mode;
56 return DEVICE_MODE_NOT_SET;
59 bool ReadMapKey(const std::map<std::string, std::string>& map,
60 const std::string& key,
62 std::map<std::string, std::string>::const_iterator entry = map.find(key);
63 if (entry == map.end())
66 *value = entry->second;
72 const char EnterpriseInstallAttributes::kConsumerDeviceMode[] = "consumer";
73 const char EnterpriseInstallAttributes::kEnterpiseDeviceMode[] = "enterprise";
74 const char EnterpriseInstallAttributes::kRetailKioskDeviceMode[] = "kiosk";
75 const char EnterpriseInstallAttributes::kConsumerKioskDeviceMode[] =
77 const char EnterpriseInstallAttributes::kUnknownDeviceMode[] = "unknown";
79 const char EnterpriseInstallAttributes::kAttrEnterpriseDeviceId[] =
80 "enterprise.device_id";
81 const char EnterpriseInstallAttributes::kAttrEnterpriseDomain[] =
83 const char EnterpriseInstallAttributes::kAttrEnterpriseMode[] =
85 const char EnterpriseInstallAttributes::kAttrEnterpriseOwned[] =
87 const char EnterpriseInstallAttributes::kAttrEnterpriseUser[] =
89 const char EnterpriseInstallAttributes::kAttrConsumerKioskEnabled[] =
90 "consumer.app_kiosk_enabled";
92 EnterpriseInstallAttributes::EnterpriseInstallAttributes(
93 chromeos::CryptohomeClient* cryptohome_client)
94 : device_locked_(false),
95 registration_mode_(DEVICE_MODE_PENDING),
96 cryptohome_client_(cryptohome_client),
97 weak_ptr_factory_(this) {}
99 EnterpriseInstallAttributes::~EnterpriseInstallAttributes() {}
101 void EnterpriseInstallAttributes::ReadCacheFile(
102 const base::FilePath& cache_file) {
103 if (device_locked_ || !base::PathExists(cache_file))
106 device_locked_ = true;
109 int len = file_util::ReadFile(cache_file, buf, sizeof(buf));
110 if (len == -1 || len >= static_cast<int>(sizeof(buf))) {
111 PLOG(ERROR) << "Failed to read " << cache_file.value();
115 cryptohome::SerializedInstallAttributes install_attrs_proto;
116 if (!install_attrs_proto.ParseFromArray(buf, len)) {
117 LOG(ERROR) << "Failed to parse install attributes cache";
121 google::protobuf::RepeatedPtrField<
122 const cryptohome::SerializedInstallAttributes::Attribute>::iterator entry;
123 std::map<std::string, std::string> attr_map;
124 for (entry = install_attrs_proto.attributes().begin();
125 entry != install_attrs_proto.attributes().end();
127 // The protobuf values unfortunately contain terminating null characters, so
128 // we have to sanitize the value here.
129 attr_map.insert(std::make_pair(entry->name(),
130 std::string(entry->value().c_str())));
133 DecodeInstallAttributes(attr_map);
136 void EnterpriseInstallAttributes::ReadImmutableAttributes(
137 const base::Closure& callback) {
138 if (device_locked_) {
143 cryptohome_client_->InstallAttributesIsReady(
144 base::Bind(&EnterpriseInstallAttributes::ReadAttributesIfReady,
145 weak_ptr_factory_.GetWeakPtr(),
149 void EnterpriseInstallAttributes::ReadAttributesIfReady(
150 const base::Closure& callback,
151 chromeos::DBusMethodCallStatus call_status,
153 if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS && result) {
154 registration_mode_ = DEVICE_MODE_NOT_SET;
155 if (!cryptohome_util::InstallAttributesIsInvalid() &&
156 !cryptohome_util::InstallAttributesIsFirstInstall()) {
157 device_locked_ = true;
159 static const char* kEnterpriseAttributes[] = {
160 kAttrEnterpriseDeviceId,
161 kAttrEnterpriseDomain,
163 kAttrEnterpriseOwned,
165 kAttrConsumerKioskEnabled,
167 std::map<std::string, std::string> attr_map;
168 for (size_t i = 0; i < arraysize(kEnterpriseAttributes); ++i) {
170 if (cryptohome_util::InstallAttributesGet(kEnterpriseAttributes[i],
172 attr_map[kEnterpriseAttributes[i]] = value;
175 DecodeInstallAttributes(attr_map);
181 void EnterpriseInstallAttributes::LockDevice(
182 const std::string& user,
183 DeviceMode device_mode,
184 const std::string& device_id,
185 const LockResultCallback& callback) {
186 DCHECK(!callback.is_null());
187 CHECK_NE(device_mode, DEVICE_MODE_PENDING);
188 CHECK_NE(device_mode, DEVICE_MODE_NOT_SET);
190 // Check for existing lock first.
191 if (device_locked_) {
192 if (device_mode == DEVICE_MODE_CONSUMER_KIOSK) {
193 callback.Run((registration_mode_ == device_mode) ? LOCK_SUCCESS :
196 std::string domain = gaia::ExtractDomainName(user);
198 (!registration_domain_.empty() && domain == registration_domain_) ?
199 LOCK_SUCCESS : LOCK_WRONG_USER);
204 cryptohome_client_->InstallAttributesIsReady(
205 base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady,
206 weak_ptr_factory_.GetWeakPtr(),
213 void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady(
214 const std::string& user,
215 DeviceMode device_mode,
216 const std::string& device_id,
217 const LockResultCallback& callback,
218 chromeos::DBusMethodCallStatus call_status,
220 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) {
221 callback.Run(LOCK_NOT_READY);
225 // Clearing the TPM password seems to be always a good deal.
226 if (cryptohome_util::TpmIsEnabled() &&
227 !cryptohome_util::TpmIsBeingOwned() &&
228 cryptohome_util::TpmIsOwned()) {
229 cryptohome_client_->CallTpmClearStoredPasswordAndBlock();
232 // Make sure we really have a working InstallAttrs.
233 if (cryptohome_util::InstallAttributesIsInvalid()) {
234 LOG(ERROR) << "Install attributes invalid.";
235 callback.Run(LOCK_BACKEND_ERROR);
239 if (!cryptohome_util::InstallAttributesIsFirstInstall()) {
240 callback.Run(LOCK_WRONG_USER);
244 std::string mode = GetDeviceModeString(device_mode);
245 std::string registration_user;
247 registration_user = gaia::CanonicalizeEmail(user);
249 if (device_mode == DEVICE_MODE_CONSUMER_KIOSK) {
250 // Set values in the InstallAttrs and lock it.
251 if (!cryptohome_util::InstallAttributesSet(kAttrConsumerKioskEnabled,
253 LOG(ERROR) << "Failed writing attributes";
254 callback.Run(LOCK_BACKEND_ERROR);
258 std::string domain = gaia::ExtractDomainName(registration_user);
259 // Set values in the InstallAttrs and lock it.
260 if (!cryptohome_util::InstallAttributesSet(kAttrEnterpriseOwned, "true") ||
261 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseUser,
262 registration_user) ||
263 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDomain,
265 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseMode, mode) ||
266 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDeviceId,
268 LOG(ERROR) << "Failed writing attributes";
269 callback.Run(LOCK_BACKEND_ERROR);
274 if (!cryptohome_util::InstallAttributesFinalize() ||
275 cryptohome_util::InstallAttributesIsFirstInstall()) {
276 LOG(ERROR) << "Failed locking.";
277 callback.Run(LOCK_BACKEND_ERROR);
281 ReadImmutableAttributes(
282 base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes,
283 weak_ptr_factory_.GetWeakPtr(),
288 void EnterpriseInstallAttributes::OnReadImmutableAttributes(
289 const std::string& registration_user,
290 const LockResultCallback& callback) {
292 if (GetRegistrationUser() != registration_user) {
293 LOG(ERROR) << "Locked data doesn't match";
294 callback.Run(LOCK_BACKEND_ERROR);
298 callback.Run(LOCK_SUCCESS);
301 bool EnterpriseInstallAttributes::IsEnterpriseDevice() {
302 return device_locked_ && !registration_user_.empty();
305 bool EnterpriseInstallAttributes::IsConsumerKioskDevice() {
306 return device_locked_ && registration_mode_ == DEVICE_MODE_CONSUMER_KIOSK;
309 std::string EnterpriseInstallAttributes::GetRegistrationUser() {
311 return std::string();
313 return registration_user_;
316 std::string EnterpriseInstallAttributes::GetDomain() {
317 if (!IsEnterpriseDevice())
318 return std::string();
320 return registration_domain_;
323 std::string EnterpriseInstallAttributes::GetDeviceId() {
324 if (!IsEnterpriseDevice())
325 return std::string();
327 return registration_device_id_;
330 DeviceMode EnterpriseInstallAttributes::GetMode() {
331 return registration_mode_;
334 void EnterpriseInstallAttributes::DecodeInstallAttributes(
335 const std::map<std::string, std::string>& attr_map) {
336 std::string enterprise_owned;
337 std::string enterprise_user;
338 std::string consumer_kiosk_enabled;
339 if (ReadMapKey(attr_map, kAttrEnterpriseOwned, &enterprise_owned) &&
340 ReadMapKey(attr_map, kAttrEnterpriseUser, &enterprise_user) &&
341 enterprise_owned == "true" &&
342 !enterprise_user.empty()) {
343 registration_user_ = gaia::CanonicalizeEmail(enterprise_user);
345 // Initialize the mode to the legacy enterprise mode here and update
346 // below if more information is present.
347 registration_mode_ = DEVICE_MODE_ENTERPRISE;
349 // If we could extract basic setting we should try to extract the
350 // extended ones too. We try to set these to defaults as good as
351 // as possible if present, which could happen for device enrolled in
352 // pre 19 revisions of the code, before these new attributes were added.
353 if (ReadMapKey(attr_map, kAttrEnterpriseDomain, ®istration_domain_))
354 registration_domain_ = gaia::CanonicalizeDomain(registration_domain_);
356 registration_domain_ = gaia::ExtractDomainName(registration_user_);
358 ReadMapKey(attr_map, kAttrEnterpriseDeviceId, ®istration_device_id_);
361 if (ReadMapKey(attr_map, kAttrEnterpriseMode, &mode))
362 registration_mode_ = GetDeviceModeFromString(mode);
363 } else if (ReadMapKey(attr_map,
364 kAttrConsumerKioskEnabled,
365 &consumer_kiosk_enabled) &&
366 consumer_kiosk_enabled == "true") {
367 registration_mode_ = DEVICE_MODE_CONSUMER_KIOSK;
368 } else if (enterprise_user.empty() && enterprise_owned != "true") {
369 // |registration_user_| is empty on consumer devices.
370 registration_mode_ = DEVICE_MODE_CONSUMER;
374 } // namespace policy