- add sources.
[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/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"
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:
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;
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 EnterpriseInstallAttributes::~EnterpriseInstallAttributes() {}
100
101 void EnterpriseInstallAttributes::ReadCacheFile(
102     const base::FilePath& cache_file) {
103   if (device_locked_ || !base::PathExists(cache_file))
104     return;
105
106   device_locked_ = true;
107
108   char buf[16384];
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();
112     return;
113   }
114
115   cryptohome::SerializedInstallAttributes install_attrs_proto;
116   if (!install_attrs_proto.ParseFromArray(buf, len)) {
117     LOG(ERROR) << "Failed to parse install attributes cache";
118     return;
119   }
120
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();
126        ++entry) {
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())));
131   }
132
133   DecodeInstallAttributes(attr_map);
134 }
135
136 void EnterpriseInstallAttributes::ReadImmutableAttributes(
137     const base::Closure& callback) {
138   if (device_locked_) {
139     callback.Run();
140     return;
141   }
142
143   cryptohome_client_->InstallAttributesIsReady(
144       base::Bind(&EnterpriseInstallAttributes::ReadAttributesIfReady,
145                  weak_ptr_factory_.GetWeakPtr(),
146                  callback));
147 }
148
149 void EnterpriseInstallAttributes::ReadAttributesIfReady(
150     const base::Closure& callback,
151     chromeos::DBusMethodCallStatus call_status,
152     bool result) {
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;
158
159       static const char* kEnterpriseAttributes[] = {
160         kAttrEnterpriseDeviceId,
161         kAttrEnterpriseDomain,
162         kAttrEnterpriseMode,
163         kAttrEnterpriseOwned,
164         kAttrEnterpriseUser,
165         kAttrConsumerKioskEnabled,
166       };
167       std::map<std::string, std::string> attr_map;
168       for (size_t i = 0; i < arraysize(kEnterpriseAttributes); ++i) {
169         std::string value;
170         if (cryptohome_util::InstallAttributesGet(kEnterpriseAttributes[i],
171                                                   &value))
172           attr_map[kEnterpriseAttributes[i]] = value;
173       }
174
175       DecodeInstallAttributes(attr_map);
176     }
177   }
178   callback.Run();
179 }
180
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);
189
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 :
194                                                          LOCK_NOT_READY);
195     } else {
196       std::string domain = gaia::ExtractDomainName(user);
197       callback.Run(
198           (!registration_domain_.empty() && domain == registration_domain_) ?
199               LOCK_SUCCESS : LOCK_WRONG_USER);
200     }
201     return;
202   }
203
204   cryptohome_client_->InstallAttributesIsReady(
205       base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady,
206                  weak_ptr_factory_.GetWeakPtr(),
207                  user,
208                  device_mode,
209                  device_id,
210                  callback));
211 }
212
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,
219     bool result) {
220   if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) {
221     callback.Run(LOCK_NOT_READY);
222     return;
223   }
224
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();
230   }
231
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);
236     return;
237   }
238
239   if (!cryptohome_util::InstallAttributesIsFirstInstall()) {
240     callback.Run(LOCK_WRONG_USER);
241     return;
242   }
243
244   std::string mode = GetDeviceModeString(device_mode);
245   std::string registration_user;
246   if (!user.empty())
247     registration_user = gaia::CanonicalizeEmail(user);
248
249   if (device_mode == DEVICE_MODE_CONSUMER_KIOSK) {
250     // Set values in the InstallAttrs and lock it.
251     if (!cryptohome_util::InstallAttributesSet(kAttrConsumerKioskEnabled,
252                                                "true")) {
253       LOG(ERROR) << "Failed writing attributes";
254       callback.Run(LOCK_BACKEND_ERROR);
255       return;
256     }
257   } else {
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,
264                                                domain) ||
265         !cryptohome_util::InstallAttributesSet(kAttrEnterpriseMode, mode) ||
266         !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDeviceId,
267                                                device_id)) {
268       LOG(ERROR) << "Failed writing attributes";
269       callback.Run(LOCK_BACKEND_ERROR);
270       return;
271     }
272   }
273
274   if (!cryptohome_util::InstallAttributesFinalize() ||
275       cryptohome_util::InstallAttributesIsFirstInstall()) {
276     LOG(ERROR) << "Failed locking.";
277     callback.Run(LOCK_BACKEND_ERROR);
278     return;
279   }
280
281   ReadImmutableAttributes(
282       base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes,
283                  weak_ptr_factory_.GetWeakPtr(),
284                  registration_user,
285                  callback));
286 }
287
288 void EnterpriseInstallAttributes::OnReadImmutableAttributes(
289     const std::string& registration_user,
290     const LockResultCallback& callback) {
291
292   if (GetRegistrationUser() != registration_user) {
293     LOG(ERROR) << "Locked data doesn't match";
294     callback.Run(LOCK_BACKEND_ERROR);
295     return;
296   }
297
298   callback.Run(LOCK_SUCCESS);
299 }
300
301 bool EnterpriseInstallAttributes::IsEnterpriseDevice() {
302   return device_locked_ && !registration_user_.empty();
303 }
304
305 bool EnterpriseInstallAttributes::IsConsumerKioskDevice() {
306   return device_locked_ && registration_mode_ == DEVICE_MODE_CONSUMER_KIOSK;
307 }
308
309 std::string EnterpriseInstallAttributes::GetRegistrationUser() {
310   if (!device_locked_)
311     return std::string();
312
313   return registration_user_;
314 }
315
316 std::string EnterpriseInstallAttributes::GetDomain() {
317   if (!IsEnterpriseDevice())
318     return std::string();
319
320   return registration_domain_;
321 }
322
323 std::string EnterpriseInstallAttributes::GetDeviceId() {
324   if (!IsEnterpriseDevice())
325     return std::string();
326
327   return registration_device_id_;
328 }
329
330 DeviceMode EnterpriseInstallAttributes::GetMode() {
331   return registration_mode_;
332 }
333
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);
344
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;
348
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, &registration_domain_))
354       registration_domain_ = gaia::CanonicalizeDomain(registration_domain_);
355     else
356       registration_domain_ = gaia::ExtractDomainName(registration_user_);
357
358     ReadMapKey(attr_map, kAttrEnterpriseDeviceId, &registration_device_id_);
359
360     std::string mode;
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;
371   }
372 }
373
374 }  // namespace policy