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/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 // 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) {
100 EnterpriseInstallAttributes::~EnterpriseInstallAttributes() {}
102 void EnterpriseInstallAttributes::ReadCacheFile(
103 const base::FilePath
& cache_file
) {
104 if (device_locked_
|| !base::PathExists(cache_file
))
107 device_locked_
= true;
110 int len
= base::ReadFile(cache_file
, buf
, sizeof(buf
));
111 if (len
== -1 || len
>= static_cast<int>(sizeof(buf
))) {
112 PLOG(ERROR
) << "Failed to read " << cache_file
.value();
116 cryptohome::SerializedInstallAttributes install_attrs_proto
;
117 if (!install_attrs_proto
.ParseFromArray(buf
, len
)) {
118 LOG(ERROR
) << "Failed to parse install attributes cache";
122 google::protobuf::RepeatedPtrField
<
123 const cryptohome::SerializedInstallAttributes::Attribute
>::iterator entry
;
124 std::map
<std::string
, std::string
> attr_map
;
125 for (entry
= install_attrs_proto
.attributes().begin();
126 entry
!= install_attrs_proto
.attributes().end();
128 // The protobuf values unfortunately contain terminating null characters, so
129 // we have to sanitize the value here.
130 attr_map
.insert(std::make_pair(entry
->name(),
131 std::string(entry
->value().c_str())));
134 DecodeInstallAttributes(attr_map
);
137 void EnterpriseInstallAttributes::ReadImmutableAttributes(
138 const base::Closure
& callback
) {
139 if (device_locked_
) {
144 cryptohome_client_
->InstallAttributesIsReady(
145 base::Bind(&EnterpriseInstallAttributes::ReadAttributesIfReady
,
146 weak_ptr_factory_
.GetWeakPtr(),
150 void EnterpriseInstallAttributes::ReadAttributesIfReady(
151 const base::Closure
& callback
,
152 chromeos::DBusMethodCallStatus call_status
,
154 if (call_status
== chromeos::DBUS_METHOD_CALL_SUCCESS
&& result
) {
155 registration_mode_
= DEVICE_MODE_NOT_SET
;
156 if (!cryptohome_util::InstallAttributesIsInvalid() &&
157 !cryptohome_util::InstallAttributesIsFirstInstall()) {
158 device_locked_
= true;
160 static const char* kEnterpriseAttributes
[] = {
161 kAttrEnterpriseDeviceId
,
162 kAttrEnterpriseDomain
,
164 kAttrEnterpriseOwned
,
166 kAttrConsumerKioskEnabled
,
168 std::map
<std::string
, std::string
> attr_map
;
169 for (size_t i
= 0; i
< arraysize(kEnterpriseAttributes
); ++i
) {
171 if (cryptohome_util::InstallAttributesGet(kEnterpriseAttributes
[i
],
173 attr_map
[kEnterpriseAttributes
[i
]] = value
;
176 DecodeInstallAttributes(attr_map
);
182 void EnterpriseInstallAttributes::LockDevice(
183 const std::string
& user
,
184 DeviceMode device_mode
,
185 const std::string
& device_id
,
186 const LockResultCallback
& callback
) {
187 DCHECK(!callback
.is_null());
188 CHECK_NE(device_mode
, DEVICE_MODE_PENDING
);
189 CHECK_NE(device_mode
, DEVICE_MODE_NOT_SET
);
191 // Check for existing lock first.
192 if (device_locked_
) {
193 if (device_mode
== DEVICE_MODE_CONSUMER_KIOSK
) {
194 callback
.Run((registration_mode_
== device_mode
) ? LOCK_SUCCESS
:
197 std::string domain
= gaia::ExtractDomainName(user
);
199 (!registration_domain_
.empty() && domain
== registration_domain_
) ?
200 LOCK_SUCCESS
: LOCK_WRONG_USER
);
205 cryptohome_client_
->InstallAttributesIsReady(
206 base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady
,
207 weak_ptr_factory_
.GetWeakPtr(),
214 void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady(
215 const std::string
& user
,
216 DeviceMode device_mode
,
217 const std::string
& device_id
,
218 const LockResultCallback
& callback
,
219 chromeos::DBusMethodCallStatus call_status
,
221 if (call_status
!= chromeos::DBUS_METHOD_CALL_SUCCESS
|| !result
) {
222 callback
.Run(LOCK_NOT_READY
);
226 // Clearing the TPM password seems to be always a good deal.
227 if (cryptohome_util::TpmIsEnabled() &&
228 !cryptohome_util::TpmIsBeingOwned() &&
229 cryptohome_util::TpmIsOwned()) {
230 cryptohome_client_
->CallTpmClearStoredPasswordAndBlock();
233 // Make sure we really have a working InstallAttrs.
234 if (cryptohome_util::InstallAttributesIsInvalid()) {
235 LOG(ERROR
) << "Install attributes invalid.";
236 callback
.Run(LOCK_BACKEND_ERROR
);
240 if (!cryptohome_util::InstallAttributesIsFirstInstall()) {
241 callback
.Run(LOCK_WRONG_USER
);
245 std::string mode
= GetDeviceModeString(device_mode
);
246 std::string registration_user
;
248 registration_user
= gaia::CanonicalizeEmail(user
);
250 if (device_mode
== DEVICE_MODE_CONSUMER_KIOSK
) {
251 // Set values in the InstallAttrs and lock it.
252 if (!cryptohome_util::InstallAttributesSet(kAttrConsumerKioskEnabled
,
254 LOG(ERROR
) << "Failed writing attributes";
255 callback
.Run(LOCK_BACKEND_ERROR
);
259 std::string domain
= gaia::ExtractDomainName(registration_user
);
260 // Set values in the InstallAttrs and lock it.
261 if (!cryptohome_util::InstallAttributesSet(kAttrEnterpriseOwned
, "true") ||
262 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseUser
,
263 registration_user
) ||
264 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDomain
,
266 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseMode
, mode
) ||
267 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDeviceId
,
269 LOG(ERROR
) << "Failed writing attributes";
270 callback
.Run(LOCK_BACKEND_ERROR
);
275 if (!cryptohome_util::InstallAttributesFinalize() ||
276 cryptohome_util::InstallAttributesIsFirstInstall()) {
277 LOG(ERROR
) << "Failed locking.";
278 callback
.Run(LOCK_BACKEND_ERROR
);
282 ReadImmutableAttributes(
283 base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes
,
284 weak_ptr_factory_
.GetWeakPtr(),
289 void EnterpriseInstallAttributes::OnReadImmutableAttributes(
290 const std::string
& registration_user
,
291 const LockResultCallback
& callback
) {
293 if (GetRegistrationUser() != registration_user
) {
294 LOG(ERROR
) << "Locked data doesn't match";
295 callback
.Run(LOCK_BACKEND_ERROR
);
299 callback
.Run(LOCK_SUCCESS
);
302 bool EnterpriseInstallAttributes::IsEnterpriseDevice() {
303 return device_locked_
&& !registration_user_
.empty();
306 bool EnterpriseInstallAttributes::IsConsumerKioskDevice() {
307 return device_locked_
&& registration_mode_
== DEVICE_MODE_CONSUMER_KIOSK
;
310 std::string
EnterpriseInstallAttributes::GetRegistrationUser() {
312 return std::string();
314 return registration_user_
;
317 std::string
EnterpriseInstallAttributes::GetDomain() {
318 if (!IsEnterpriseDevice())
319 return std::string();
321 return registration_domain_
;
324 std::string
EnterpriseInstallAttributes::GetDeviceId() {
325 if (!IsEnterpriseDevice())
326 return std::string();
328 return registration_device_id_
;
331 DeviceMode
EnterpriseInstallAttributes::GetMode() {
332 return registration_mode_
;
335 void EnterpriseInstallAttributes::DecodeInstallAttributes(
336 const std::map
<std::string
, std::string
>& attr_map
) {
337 std::string enterprise_owned
;
338 std::string enterprise_user
;
339 std::string consumer_kiosk_enabled
;
340 if (ReadMapKey(attr_map
, kAttrEnterpriseOwned
, &enterprise_owned
) &&
341 ReadMapKey(attr_map
, kAttrEnterpriseUser
, &enterprise_user
) &&
342 enterprise_owned
== "true" &&
343 !enterprise_user
.empty()) {
344 registration_user_
= gaia::CanonicalizeEmail(enterprise_user
);
346 // Initialize the mode to the legacy enterprise mode here and update
347 // below if more information is present.
348 registration_mode_
= DEVICE_MODE_ENTERPRISE
;
350 // If we could extract basic setting we should try to extract the
351 // extended ones too. We try to set these to defaults as good as
352 // as possible if present, which could happen for device enrolled in
353 // pre 19 revisions of the code, before these new attributes were added.
354 if (ReadMapKey(attr_map
, kAttrEnterpriseDomain
, ®istration_domain_
))
355 registration_domain_
= gaia::CanonicalizeDomain(registration_domain_
);
357 registration_domain_
= gaia::ExtractDomainName(registration_user_
);
359 ReadMapKey(attr_map
, kAttrEnterpriseDeviceId
, ®istration_device_id_
);
362 if (ReadMapKey(attr_map
, kAttrEnterpriseMode
, &mode
))
363 registration_mode_
= GetDeviceModeFromString(mode
);
364 } else if (ReadMapKey(attr_map
,
365 kAttrConsumerKioskEnabled
,
366 &consumer_kiosk_enabled
) &&
367 consumer_kiosk_enabled
== "true") {
368 registration_mode_
= DEVICE_MODE_CONSUMER_KIOSK
;
369 } else if (enterprise_user
.empty() && enterprise_owned
!= "true") {
370 // |registration_user_| is empty on consumer devices.
371 registration_mode_
= DEVICE_MODE_CONSUMER
;
375 } // namespace policy