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/files/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/chromeos/policy/proto/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 bool ReadMapKey(const std::map
<std::string
, std::string
>& map
,
26 const std::string
& key
,
28 std::map
<std::string
, std::string
>::const_iterator entry
= map
.find(key
);
29 if (entry
== map
.end())
32 *value
= entry
->second
;
40 EnterpriseInstallAttributes::GetEnterpriseOwnedInstallAttributesBlobForTesting(
41 const std::string
& user_name
) {
42 cryptohome::SerializedInstallAttributes install_attrs_proto
;
43 cryptohome::SerializedInstallAttributes::Attribute
* attribute
= NULL
;
45 attribute
= install_attrs_proto
.add_attributes();
46 attribute
->set_name(EnterpriseInstallAttributes::kAttrEnterpriseOwned
);
47 attribute
->set_value("true");
49 attribute
= install_attrs_proto
.add_attributes();
50 attribute
->set_name(EnterpriseInstallAttributes::kAttrEnterpriseUser
);
51 attribute
->set_value(user_name
);
53 return install_attrs_proto
.SerializeAsString();
56 EnterpriseInstallAttributes::EnterpriseInstallAttributes(
57 chromeos::CryptohomeClient
* cryptohome_client
)
58 : device_locked_(false),
59 registration_mode_(DEVICE_MODE_PENDING
),
60 cryptohome_client_(cryptohome_client
),
61 weak_ptr_factory_(this) {
64 EnterpriseInstallAttributes::~EnterpriseInstallAttributes() {}
66 void EnterpriseInstallAttributes::ReadCacheFile(
67 const base::FilePath
& cache_file
) {
68 if (device_locked_
|| !base::PathExists(cache_file
))
71 device_locked_
= true;
74 int len
= base::ReadFile(cache_file
, buf
, sizeof(buf
));
75 if (len
== -1 || len
>= static_cast<int>(sizeof(buf
))) {
76 PLOG(ERROR
) << "Failed to read " << cache_file
.value();
80 cryptohome::SerializedInstallAttributes install_attrs_proto
;
81 if (!install_attrs_proto
.ParseFromArray(buf
, len
)) {
82 LOG(ERROR
) << "Failed to parse install attributes cache";
86 google::protobuf::RepeatedPtrField
<
87 const cryptohome::SerializedInstallAttributes::Attribute
>::iterator entry
;
88 std::map
<std::string
, std::string
> attr_map
;
89 for (entry
= install_attrs_proto
.attributes().begin();
90 entry
!= install_attrs_proto
.attributes().end();
92 // The protobuf values unfortunately contain terminating null characters, so
93 // we have to sanitize the value here.
94 attr_map
.insert(std::make_pair(entry
->name(),
95 std::string(entry
->value().c_str())));
98 DecodeInstallAttributes(attr_map
);
101 void EnterpriseInstallAttributes::ReadImmutableAttributes(
102 const base::Closure
& callback
) {
103 if (device_locked_
) {
108 cryptohome_client_
->InstallAttributesIsReady(
109 base::Bind(&EnterpriseInstallAttributes::ReadAttributesIfReady
,
110 weak_ptr_factory_
.GetWeakPtr(),
114 void EnterpriseInstallAttributes::ReadAttributesIfReady(
115 const base::Closure
& callback
,
116 chromeos::DBusMethodCallStatus call_status
,
118 if (call_status
== chromeos::DBUS_METHOD_CALL_SUCCESS
&& result
) {
119 registration_mode_
= DEVICE_MODE_NOT_SET
;
120 if (!cryptohome_util::InstallAttributesIsInvalid() &&
121 !cryptohome_util::InstallAttributesIsFirstInstall()) {
122 device_locked_
= true;
124 static const char* const kEnterpriseAttributes
[] = {
125 kAttrEnterpriseDeviceId
,
126 kAttrEnterpriseDomain
,
128 kAttrEnterpriseOwned
,
130 kAttrConsumerKioskEnabled
,
132 std::map
<std::string
, std::string
> attr_map
;
133 for (size_t i
= 0; i
< arraysize(kEnterpriseAttributes
); ++i
) {
135 if (cryptohome_util::InstallAttributesGet(kEnterpriseAttributes
[i
],
137 attr_map
[kEnterpriseAttributes
[i
]] = value
;
140 DecodeInstallAttributes(attr_map
);
146 void EnterpriseInstallAttributes::LockDevice(
147 const std::string
& user
,
148 DeviceMode device_mode
,
149 const std::string
& device_id
,
150 const LockResultCallback
& callback
) {
151 DCHECK(!callback
.is_null());
152 CHECK_NE(device_mode
, DEVICE_MODE_PENDING
);
153 CHECK_NE(device_mode
, DEVICE_MODE_NOT_SET
);
155 // Check for existing lock first.
156 if (device_locked_
) {
157 if (device_mode
== DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH
) {
158 callback
.Run((registration_mode_
== device_mode
) ? LOCK_SUCCESS
:
161 std::string domain
= gaia::ExtractDomainName(user
);
163 (!registration_domain_
.empty() && domain
== registration_domain_
) ?
164 LOCK_SUCCESS
: LOCK_WRONG_DOMAIN
);
169 cryptohome_client_
->InstallAttributesIsReady(
170 base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady
,
171 weak_ptr_factory_
.GetWeakPtr(),
178 void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady(
179 const std::string
& user
,
180 DeviceMode device_mode
,
181 const std::string
& device_id
,
182 const LockResultCallback
& callback
,
183 chromeos::DBusMethodCallStatus call_status
,
185 if (call_status
!= chromeos::DBUS_METHOD_CALL_SUCCESS
|| !result
) {
186 callback
.Run(LOCK_NOT_READY
);
190 // Clearing the TPM password seems to be always a good deal.
191 if (cryptohome_util::TpmIsEnabled() &&
192 !cryptohome_util::TpmIsBeingOwned() &&
193 cryptohome_util::TpmIsOwned()) {
194 cryptohome_client_
->CallTpmClearStoredPasswordAndBlock();
197 // Make sure we really have a working InstallAttrs.
198 if (cryptohome_util::InstallAttributesIsInvalid()) {
199 LOG(ERROR
) << "Install attributes invalid.";
200 callback
.Run(LOCK_BACKEND_INVALID
);
204 if (!cryptohome_util::InstallAttributesIsFirstInstall()) {
205 LOG(ERROR
) << "Install attributes already installed.";
206 callback
.Run(LOCK_ALREADY_LOCKED
);
210 std::string mode
= GetDeviceModeString(device_mode
);
211 std::string registration_user
;
213 registration_user
= gaia::CanonicalizeEmail(user
);
215 if (device_mode
== DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH
) {
216 // Set values in the InstallAttrs and lock it.
217 if (!cryptohome_util::InstallAttributesSet(kAttrConsumerKioskEnabled
,
219 LOG(ERROR
) << "Failed writing attributes.";
220 callback
.Run(LOCK_SET_ERROR
);
224 std::string domain
= gaia::ExtractDomainName(registration_user
);
225 // Set values in the InstallAttrs and lock it.
226 if (!cryptohome_util::InstallAttributesSet(kAttrEnterpriseOwned
, "true") ||
227 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseUser
,
228 registration_user
) ||
229 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDomain
,
231 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseMode
, mode
) ||
232 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDeviceId
,
234 LOG(ERROR
) << "Failed writing attributes.";
235 callback
.Run(LOCK_SET_ERROR
);
240 if (!cryptohome_util::InstallAttributesFinalize() ||
241 cryptohome_util::InstallAttributesIsFirstInstall()) {
242 LOG(ERROR
) << "Failed locking.";
243 callback
.Run(LOCK_FINALIZE_ERROR
);
247 ReadImmutableAttributes(
248 base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes
,
249 weak_ptr_factory_
.GetWeakPtr(),
254 void EnterpriseInstallAttributes::OnReadImmutableAttributes(
255 const std::string
& registration_user
,
256 const LockResultCallback
& callback
) {
258 if (GetRegistrationUser() != registration_user
) {
259 LOG(ERROR
) << "Locked data doesn't match.";
260 callback
.Run(LOCK_READBACK_ERROR
);
264 callback
.Run(LOCK_SUCCESS
);
267 bool EnterpriseInstallAttributes::IsEnterpriseDevice() {
268 return device_locked_
&& !registration_user_
.empty();
271 bool EnterpriseInstallAttributes::IsConsumerKioskDeviceWithAutoLaunch() {
272 return device_locked_
&&
273 registration_mode_
== DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH
;
276 std::string
EnterpriseInstallAttributes::GetRegistrationUser() {
278 return std::string();
280 return registration_user_
;
283 std::string
EnterpriseInstallAttributes::GetDomain() {
284 if (!IsEnterpriseDevice())
285 return std::string();
287 return registration_domain_
;
290 std::string
EnterpriseInstallAttributes::GetDeviceId() {
291 if (!IsEnterpriseDevice())
292 return std::string();
294 return registration_device_id_
;
297 DeviceMode
EnterpriseInstallAttributes::GetMode() {
298 return registration_mode_
;
301 // Warning: The values for these keys (but not the keys themselves) are stored
302 // in the protobuf with a trailing zero. Also note that some of these constants
303 // have been copied to login_manager/device_policy_service.cc. Please make sure
304 // that all changes to the constants are reflected there as well.
305 const char EnterpriseInstallAttributes::kConsumerDeviceMode
[] = "consumer";
306 const char EnterpriseInstallAttributes::kEnterpriseDeviceMode
[] = "enterprise";
307 const char EnterpriseInstallAttributes::kRetailKioskDeviceMode
[] = "kiosk";
308 const char EnterpriseInstallAttributes::kConsumerKioskDeviceMode
[] =
310 const char EnterpriseInstallAttributes::kUnknownDeviceMode
[] = "unknown";
312 const char EnterpriseInstallAttributes::kAttrEnterpriseDeviceId
[] =
313 "enterprise.device_id";
314 const char EnterpriseInstallAttributes::kAttrEnterpriseDomain
[] =
316 const char EnterpriseInstallAttributes::kAttrEnterpriseMode
[] =
318 const char EnterpriseInstallAttributes::kAttrEnterpriseOwned
[] =
320 const char EnterpriseInstallAttributes::kAttrEnterpriseUser
[] =
322 const char EnterpriseInstallAttributes::kAttrConsumerKioskEnabled
[] =
323 "consumer.app_kiosk_enabled";
325 std::string
EnterpriseInstallAttributes::GetDeviceModeString(DeviceMode mode
) {
327 case DEVICE_MODE_CONSUMER
:
328 return EnterpriseInstallAttributes::kConsumerDeviceMode
;
329 case DEVICE_MODE_ENTERPRISE
:
330 return EnterpriseInstallAttributes::kEnterpriseDeviceMode
;
331 case DEVICE_MODE_RETAIL_KIOSK
:
332 return EnterpriseInstallAttributes::kRetailKioskDeviceMode
;
333 case DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH
:
334 return EnterpriseInstallAttributes::kConsumerKioskDeviceMode
;
335 case DEVICE_MODE_PENDING
:
336 case DEVICE_MODE_NOT_SET
:
339 NOTREACHED() << "Invalid device mode: " << mode
;
340 return EnterpriseInstallAttributes::kUnknownDeviceMode
;
343 DeviceMode
EnterpriseInstallAttributes::GetDeviceModeFromString(
344 const std::string
& mode
) {
345 if (mode
== EnterpriseInstallAttributes::kConsumerDeviceMode
)
346 return DEVICE_MODE_CONSUMER
;
347 else if (mode
== EnterpriseInstallAttributes::kEnterpriseDeviceMode
)
348 return DEVICE_MODE_ENTERPRISE
;
349 else if (mode
== EnterpriseInstallAttributes::kRetailKioskDeviceMode
)
350 return DEVICE_MODE_RETAIL_KIOSK
;
351 else if (mode
== EnterpriseInstallAttributes::kConsumerKioskDeviceMode
)
352 return DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH
;
353 NOTREACHED() << "Unknown device mode string: " << mode
;
354 return DEVICE_MODE_NOT_SET
;
357 void EnterpriseInstallAttributes::DecodeInstallAttributes(
358 const std::map
<std::string
, std::string
>& attr_map
) {
359 std::string enterprise_owned
;
360 std::string enterprise_user
;
361 std::string consumer_kiosk_enabled
;
362 if (ReadMapKey(attr_map
, kAttrEnterpriseOwned
, &enterprise_owned
) &&
363 ReadMapKey(attr_map
, kAttrEnterpriseUser
, &enterprise_user
) &&
364 enterprise_owned
== "true" &&
365 !enterprise_user
.empty()) {
366 registration_user_
= gaia::CanonicalizeEmail(enterprise_user
);
368 // Initialize the mode to the legacy enterprise mode here and update
369 // below if more information is present.
370 registration_mode_
= DEVICE_MODE_ENTERPRISE
;
372 // If we could extract basic setting we should try to extract the
373 // extended ones too. We try to set these to defaults as good as
374 // as possible if present, which could happen for device enrolled in
375 // pre 19 revisions of the code, before these new attributes were added.
376 if (ReadMapKey(attr_map
, kAttrEnterpriseDomain
, ®istration_domain_
))
377 registration_domain_
= gaia::CanonicalizeDomain(registration_domain_
);
379 registration_domain_
= gaia::ExtractDomainName(registration_user_
);
381 ReadMapKey(attr_map
, kAttrEnterpriseDeviceId
, ®istration_device_id_
);
384 if (ReadMapKey(attr_map
, kAttrEnterpriseMode
, &mode
))
385 registration_mode_
= GetDeviceModeFromString(mode
);
386 } else if (ReadMapKey(attr_map
,
387 kAttrConsumerKioskEnabled
,
388 &consumer_kiosk_enabled
) &&
389 consumer_kiosk_enabled
== "true") {
390 registration_mode_
= DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH
;
391 } else if (enterprise_user
.empty() && enterprise_owned
!= "true") {
392 // |registration_user_| is empty on consumer devices.
393 registration_mode_
= DEVICE_MODE_CONSUMER
;
397 } // namespace policy