Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / policy / enterprise_install_attributes.cc
blobbc78b5813f07cfdb4605fa681a17802b52cc43be
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"
7 #include <utility>
9 #include "base/bind.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"
19 namespace policy {
21 namespace cryptohome_util = chromeos::cryptohome_util;
23 namespace {
25 // Translates DeviceMode constants to strings used in the lockbox.
26 std::string GetDeviceModeString(DeviceMode mode) {
27 switch (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:
38 break;
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,
61 std::string* value) {
62 std::map<std::string, std::string>::const_iterator entry = map.find(key);
63 if (entry == map.end())
64 return false;
66 *value = entry->second;
67 return true;
70 } // namespace
72 const char EnterpriseInstallAttributes::kConsumerDeviceMode[] = "consumer";
73 const char EnterpriseInstallAttributes::kEnterpiseDeviceMode[] = "enterprise";
74 const char EnterpriseInstallAttributes::kRetailKioskDeviceMode[] = "kiosk";
75 const char EnterpriseInstallAttributes::kConsumerKioskDeviceMode[] =
76 "consumer_kiosk";
77 const char EnterpriseInstallAttributes::kUnknownDeviceMode[] = "unknown";
79 const char EnterpriseInstallAttributes::kAttrEnterpriseDeviceId[] =
80 "enterprise.device_id";
81 const char EnterpriseInstallAttributes::kAttrEnterpriseDomain[] =
82 "enterprise.domain";
83 const char EnterpriseInstallAttributes::kAttrEnterpriseMode[] =
84 "enterprise.mode";
85 const char EnterpriseInstallAttributes::kAttrEnterpriseOwned[] =
86 "enterprise.owned";
87 const char EnterpriseInstallAttributes::kAttrEnterpriseUser[] =
88 "enterprise.user";
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))
105 return;
107 device_locked_ = true;
109 char buf[16384];
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();
113 return;
116 cryptohome::SerializedInstallAttributes install_attrs_proto;
117 if (!install_attrs_proto.ParseFromArray(buf, len)) {
118 LOG(ERROR) << "Failed to parse install attributes cache";
119 return;
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();
127 ++entry) {
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_) {
140 callback.Run();
141 return;
144 cryptohome_client_->InstallAttributesIsReady(
145 base::Bind(&EnterpriseInstallAttributes::ReadAttributesIfReady,
146 weak_ptr_factory_.GetWeakPtr(),
147 callback));
150 void EnterpriseInstallAttributes::ReadAttributesIfReady(
151 const base::Closure& callback,
152 chromeos::DBusMethodCallStatus call_status,
153 bool result) {
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,
163 kAttrEnterpriseMode,
164 kAttrEnterpriseOwned,
165 kAttrEnterpriseUser,
166 kAttrConsumerKioskEnabled,
168 std::map<std::string, std::string> attr_map;
169 for (size_t i = 0; i < arraysize(kEnterpriseAttributes); ++i) {
170 std::string value;
171 if (cryptohome_util::InstallAttributesGet(kEnterpriseAttributes[i],
172 &value))
173 attr_map[kEnterpriseAttributes[i]] = value;
176 DecodeInstallAttributes(attr_map);
179 callback.Run();
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 :
195 LOCK_NOT_READY);
196 } else {
197 std::string domain = gaia::ExtractDomainName(user);
198 callback.Run(
199 (!registration_domain_.empty() && domain == registration_domain_) ?
200 LOCK_SUCCESS : LOCK_WRONG_USER);
202 return;
205 cryptohome_client_->InstallAttributesIsReady(
206 base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady,
207 weak_ptr_factory_.GetWeakPtr(),
208 user,
209 device_mode,
210 device_id,
211 callback));
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,
220 bool result) {
221 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) {
222 callback.Run(LOCK_NOT_READY);
223 return;
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);
237 return;
240 if (!cryptohome_util::InstallAttributesIsFirstInstall()) {
241 callback.Run(LOCK_WRONG_USER);
242 return;
245 std::string mode = GetDeviceModeString(device_mode);
246 std::string registration_user;
247 if (!user.empty())
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,
253 "true")) {
254 LOG(ERROR) << "Failed writing attributes";
255 callback.Run(LOCK_BACKEND_ERROR);
256 return;
258 } else {
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,
265 domain) ||
266 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseMode, mode) ||
267 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDeviceId,
268 device_id)) {
269 LOG(ERROR) << "Failed writing attributes";
270 callback.Run(LOCK_BACKEND_ERROR);
271 return;
275 if (!cryptohome_util::InstallAttributesFinalize() ||
276 cryptohome_util::InstallAttributesIsFirstInstall()) {
277 LOG(ERROR) << "Failed locking.";
278 callback.Run(LOCK_BACKEND_ERROR);
279 return;
282 ReadImmutableAttributes(
283 base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes,
284 weak_ptr_factory_.GetWeakPtr(),
285 registration_user,
286 callback));
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);
296 return;
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() {
311 if (!device_locked_)
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, &registration_domain_))
355 registration_domain_ = gaia::CanonicalizeDomain(registration_domain_);
356 else
357 registration_domain_ = gaia::ExtractDomainName(registration_user_);
359 ReadMapKey(attr_map, kAttrEnterpriseDeviceId, &registration_device_id_);
361 std::string mode;
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