Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / policy / enterprise_install_attributes.cc
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 <utility>
8
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"
18
19 namespace policy {
20
21 namespace cryptohome_util = chromeos::cryptohome_util;
22
23 namespace {
24
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_AUTOLAUNCH:
35       return EnterpriseInstallAttributes::kConsumerKioskDeviceMode;
36     case DEVICE_MODE_PENDING:
37     case DEVICE_MODE_NOT_SET:
38       break;
39   }
40   NOTREACHED() << "Invalid device mode: " << mode;
41   return EnterpriseInstallAttributes::kUnknownDeviceMode;
42 }
43
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_AUTOLAUNCH;
55   NOTREACHED() << "Unknown device mode string: " << mode;
56   return DEVICE_MODE_NOT_SET;
57 }
58
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;
65
66   *value = entry->second;
67   return true;
68 }
69
70 }  // namespace
71
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";
78
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";
91
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) {
98 }
99
100 EnterpriseInstallAttributes::~EnterpriseInstallAttributes() {}
101
102 void EnterpriseInstallAttributes::ReadCacheFile(
103     const base::FilePath& cache_file) {
104   if (device_locked_ || !base::PathExists(cache_file))
105     return;
106
107   device_locked_ = true;
108
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;
114   }
115
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;
120   }
121
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())));
132   }
133
134   DecodeInstallAttributes(attr_map);
135 }
136
137 void EnterpriseInstallAttributes::ReadImmutableAttributes(
138     const base::Closure& callback) {
139   if (device_locked_) {
140     callback.Run();
141     return;
142   }
143
144   cryptohome_client_->InstallAttributesIsReady(
145       base::Bind(&EnterpriseInstallAttributes::ReadAttributesIfReady,
146                  weak_ptr_factory_.GetWeakPtr(),
147                  callback));
148 }
149
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;
159
160       static const char* kEnterpriseAttributes[] = {
161         kAttrEnterpriseDeviceId,
162         kAttrEnterpriseDomain,
163         kAttrEnterpriseMode,
164         kAttrEnterpriseOwned,
165         kAttrEnterpriseUser,
166         kAttrConsumerKioskEnabled,
167       };
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;
174       }
175
176       DecodeInstallAttributes(attr_map);
177     }
178   }
179   callback.Run();
180 }
181
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);
190
191   // Check for existing lock first.
192   if (device_locked_) {
193     if (device_mode == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH) {
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);
201     }
202     return;
203   }
204
205   cryptohome_client_->InstallAttributesIsReady(
206       base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady,
207                  weak_ptr_factory_.GetWeakPtr(),
208                  user,
209                  device_mode,
210                  device_id,
211                  callback));
212 }
213
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;
224   }
225
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();
231   }
232
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;
238   }
239
240   if (!cryptohome_util::InstallAttributesIsFirstInstall()) {
241     callback.Run(LOCK_WRONG_USER);
242     return;
243   }
244
245   std::string mode = GetDeviceModeString(device_mode);
246   std::string registration_user;
247   if (!user.empty())
248     registration_user = gaia::CanonicalizeEmail(user);
249
250   if (device_mode == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH) {
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;
257     }
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;
272     }
273   }
274
275   if (!cryptohome_util::InstallAttributesFinalize() ||
276       cryptohome_util::InstallAttributesIsFirstInstall()) {
277     LOG(ERROR) << "Failed locking.";
278     callback.Run(LOCK_BACKEND_ERROR);
279     return;
280   }
281
282   ReadImmutableAttributes(
283       base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes,
284                  weak_ptr_factory_.GetWeakPtr(),
285                  registration_user,
286                  callback));
287 }
288
289 void EnterpriseInstallAttributes::OnReadImmutableAttributes(
290     const std::string& registration_user,
291     const LockResultCallback& callback) {
292
293   if (GetRegistrationUser() != registration_user) {
294     LOG(ERROR) << "Locked data doesn't match";
295     callback.Run(LOCK_BACKEND_ERROR);
296     return;
297   }
298
299   callback.Run(LOCK_SUCCESS);
300 }
301
302 bool EnterpriseInstallAttributes::IsEnterpriseDevice() {
303   return device_locked_ && !registration_user_.empty();
304 }
305
306 bool EnterpriseInstallAttributes::IsConsumerKioskDeviceWithAutoLaunch() {
307   return device_locked_ &&
308          registration_mode_ == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
309 }
310
311 std::string EnterpriseInstallAttributes::GetRegistrationUser() {
312   if (!device_locked_)
313     return std::string();
314
315   return registration_user_;
316 }
317
318 std::string EnterpriseInstallAttributes::GetDomain() {
319   if (!IsEnterpriseDevice())
320     return std::string();
321
322   return registration_domain_;
323 }
324
325 std::string EnterpriseInstallAttributes::GetDeviceId() {
326   if (!IsEnterpriseDevice())
327     return std::string();
328
329   return registration_device_id_;
330 }
331
332 DeviceMode EnterpriseInstallAttributes::GetMode() {
333   return registration_mode_;
334 }
335
336 void EnterpriseInstallAttributes::DecodeInstallAttributes(
337     const std::map<std::string, std::string>& attr_map) {
338   std::string enterprise_owned;
339   std::string enterprise_user;
340   std::string consumer_kiosk_enabled;
341   if (ReadMapKey(attr_map, kAttrEnterpriseOwned, &enterprise_owned) &&
342       ReadMapKey(attr_map, kAttrEnterpriseUser, &enterprise_user) &&
343       enterprise_owned == "true" &&
344       !enterprise_user.empty()) {
345     registration_user_ = gaia::CanonicalizeEmail(enterprise_user);
346
347     // Initialize the mode to the legacy enterprise mode here and update
348     // below if more information is present.
349     registration_mode_ = DEVICE_MODE_ENTERPRISE;
350
351     // If we could extract basic setting we should try to extract the
352     // extended ones too. We try to set these to defaults as good as
353     // as possible if present, which could happen for device enrolled in
354     // pre 19 revisions of the code, before these new attributes were added.
355     if (ReadMapKey(attr_map, kAttrEnterpriseDomain, &registration_domain_))
356       registration_domain_ = gaia::CanonicalizeDomain(registration_domain_);
357     else
358       registration_domain_ = gaia::ExtractDomainName(registration_user_);
359
360     ReadMapKey(attr_map, kAttrEnterpriseDeviceId, &registration_device_id_);
361
362     std::string mode;
363     if (ReadMapKey(attr_map, kAttrEnterpriseMode, &mode))
364       registration_mode_ = GetDeviceModeFromString(mode);
365   } else if (ReadMapKey(attr_map,
366                         kAttrConsumerKioskEnabled,
367                         &consumer_kiosk_enabled) &&
368              consumer_kiosk_enabled == "true") {
369     registration_mode_ = DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
370   } else if (enterprise_user.empty() && enterprise_owned != "true") {
371     // |registration_user_| is empty on consumer devices.
372     registration_mode_ = DEVICE_MODE_CONSUMER;
373   }
374 }
375
376 }  // namespace policy