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_library.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 { 22 23 // Translates DeviceMode constants to strings used in the lockbox. 24 std::string GetDeviceModeString(DeviceMode mode) { 25 switch (mode) { 26 case DEVICE_MODE_CONSUMER: 27 return EnterpriseInstallAttributes::kConsumerDeviceMode; 28 case DEVICE_MODE_ENTERPRISE: 29 return EnterpriseInstallAttributes::kEnterpiseDeviceMode; 30 case DEVICE_MODE_RETAIL_KIOSK: 31 return EnterpriseInstallAttributes::kRetailKioskDeviceMode; 32 case DEVICE_MODE_CONSUMER_KIOSK: 33 return EnterpriseInstallAttributes::kConsumerKioskDeviceMode; 34 case DEVICE_MODE_PENDING: 35 case DEVICE_MODE_NOT_SET: 36 break; 37 } 38 NOTREACHED() << "Invalid device mode: " << mode; 39 return EnterpriseInstallAttributes::kUnknownDeviceMode; 40 } 41 42 // Translates strings used in the lockbox to DeviceMode values. 43 DeviceMode GetDeviceModeFromString( 44 const std::string& mode) { 45 if (mode == EnterpriseInstallAttributes::kConsumerDeviceMode) 46 return DEVICE_MODE_CONSUMER; 47 else if (mode == EnterpriseInstallAttributes::kEnterpiseDeviceMode) 48 return DEVICE_MODE_ENTERPRISE; 49 else if (mode == EnterpriseInstallAttributes::kRetailKioskDeviceMode) 50 return DEVICE_MODE_RETAIL_KIOSK; 51 else if (mode == EnterpriseInstallAttributes::kConsumerKioskDeviceMode) 52 return DEVICE_MODE_CONSUMER_KIOSK; 53 NOTREACHED() << "Unknown device mode string: " << mode; 54 return DEVICE_MODE_NOT_SET; 55 } 56 57 bool ReadMapKey(const std::map<std::string, std::string>& map, 58 const std::string& key, 59 std::string* value) { 60 std::map<std::string, std::string>::const_iterator entry = map.find(key); 61 if (entry == map.end()) 62 return false; 63 64 *value = entry->second; 65 return true; 66 } 67 68 } // namespace 69 70 const char EnterpriseInstallAttributes::kConsumerDeviceMode[] = "consumer"; 71 const char EnterpriseInstallAttributes::kEnterpiseDeviceMode[] = "enterprise"; 72 const char EnterpriseInstallAttributes::kRetailKioskDeviceMode[] = "kiosk"; 73 const char EnterpriseInstallAttributes::kConsumerKioskDeviceMode[] = 74 "consumer_kiosk"; 75 const char EnterpriseInstallAttributes::kUnknownDeviceMode[] = "unknown"; 76 77 const char EnterpriseInstallAttributes::kAttrEnterpriseDeviceId[] = 78 "enterprise.device_id"; 79 const char EnterpriseInstallAttributes::kAttrEnterpriseDomain[] = 80 "enterprise.domain"; 81 const char EnterpriseInstallAttributes::kAttrEnterpriseMode[] = 82 "enterprise.mode"; 83 const char EnterpriseInstallAttributes::kAttrEnterpriseOwned[] = 84 "enterprise.owned"; 85 const char EnterpriseInstallAttributes::kAttrEnterpriseUser[] = 86 "enterprise.user"; 87 const char EnterpriseInstallAttributes::kAttrConsumerKioskEnabled[] = 88 "consumer.app_kiosk_enabled"; 89 90 EnterpriseInstallAttributes::EnterpriseInstallAttributes( 91 chromeos::CryptohomeLibrary* cryptohome, 92 chromeos::CryptohomeClient* cryptohome_client) 93 : device_locked_(false), 94 registration_mode_(DEVICE_MODE_PENDING), 95 cryptohome_(cryptohome), 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_->InstallAttributesIsInvalid() && 156 !cryptohome_->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_->InstallAttributesGet(kEnterpriseAttributes[i], &value)) 171 attr_map[kEnterpriseAttributes[i]] = value; 172 } 173 174 DecodeInstallAttributes(attr_map); 175 } 176 } 177 callback.Run(); 178 } 179 180 void EnterpriseInstallAttributes::LockDevice( 181 const std::string& user, 182 DeviceMode device_mode, 183 const std::string& device_id, 184 const LockResultCallback& callback) { 185 DCHECK(!callback.is_null()); 186 CHECK_NE(device_mode, DEVICE_MODE_PENDING); 187 CHECK_NE(device_mode, DEVICE_MODE_NOT_SET); 188 189 // Check for existing lock first. 190 if (device_locked_) { 191 if (device_mode == DEVICE_MODE_CONSUMER_KIOSK) { 192 callback.Run((registration_mode_ == device_mode) ? LOCK_SUCCESS : 193 LOCK_NOT_READY); 194 } else { 195 std::string domain = gaia::ExtractDomainName(user); 196 callback.Run( 197 (!registration_domain_.empty() && domain == registration_domain_) ? 198 LOCK_SUCCESS : LOCK_WRONG_USER); 199 } 200 return; 201 } 202 203 cryptohome_client_->InstallAttributesIsReady( 204 base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady, 205 weak_ptr_factory_.GetWeakPtr(), 206 user, 207 device_mode, 208 device_id, 209 callback)); 210 } 211 212 void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady( 213 const std::string& user, 214 DeviceMode device_mode, 215 const std::string& device_id, 216 const LockResultCallback& callback, 217 chromeos::DBusMethodCallStatus call_status, 218 bool result) { 219 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) { 220 callback.Run(LOCK_NOT_READY); 221 return; 222 } 223 224 // Clearing the TPM password seems to be always a good deal. 225 if (cryptohome_->TpmIsEnabled() && 226 !cryptohome_->TpmIsBeingOwned() && 227 cryptohome_->TpmIsOwned()) { 228 cryptohome_->TpmClearStoredPassword(); 229 } 230 231 // Make sure we really have a working InstallAttrs. 232 if (cryptohome_->InstallAttributesIsInvalid()) { 233 LOG(ERROR) << "Install attributes invalid."; 234 callback.Run(LOCK_BACKEND_ERROR); 235 return; 236 } 237 238 if (!cryptohome_->InstallAttributesIsFirstInstall()) { 239 callback.Run(LOCK_WRONG_USER); 240 return; 241 } 242 243 std::string mode = GetDeviceModeString(device_mode); 244 245 if (device_mode == DEVICE_MODE_CONSUMER_KIOSK) { 246 // Set values in the InstallAttrs and lock it. 247 if (!cryptohome_->InstallAttributesSet(kAttrConsumerKioskEnabled, "true")) { 248 LOG(ERROR) << "Failed writing attributes"; 249 callback.Run(LOCK_BACKEND_ERROR); 250 return; 251 } 252 } else { 253 std::string domain = gaia::ExtractDomainName(user); 254 // Set values in the InstallAttrs and lock it. 255 if (!cryptohome_->InstallAttributesSet(kAttrEnterpriseOwned, "true") || 256 !cryptohome_->InstallAttributesSet(kAttrEnterpriseUser, user) || 257 !cryptohome_->InstallAttributesSet(kAttrEnterpriseDomain, domain) || 258 !cryptohome_->InstallAttributesSet(kAttrEnterpriseMode, mode) || 259 !cryptohome_->InstallAttributesSet(kAttrEnterpriseDeviceId, 260 device_id)) { 261 LOG(ERROR) << "Failed writing attributes"; 262 callback.Run(LOCK_BACKEND_ERROR); 263 return; 264 } 265 } 266 267 if (!cryptohome_->InstallAttributesFinalize() || 268 cryptohome_->InstallAttributesIsFirstInstall()) { 269 LOG(ERROR) << "Failed locking."; 270 callback.Run(LOCK_BACKEND_ERROR); 271 return; 272 } 273 274 ReadImmutableAttributes( 275 base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes, 276 weak_ptr_factory_.GetWeakPtr(), 277 user, 278 callback)); 279 } 280 281 void EnterpriseInstallAttributes::OnReadImmutableAttributes( 282 const std::string& user, 283 const LockResultCallback& callback) { 284 285 if (GetRegistrationUser() != user) { 286 LOG(ERROR) << "Locked data doesn't match"; 287 callback.Run(LOCK_BACKEND_ERROR); 288 return; 289 } 290 291 callback.Run(LOCK_SUCCESS); 292 } 293 294 bool EnterpriseInstallAttributes::IsEnterpriseDevice() { 295 return device_locked_ && !registration_user_.empty(); 296 } 297 298 bool EnterpriseInstallAttributes::IsConsumerKioskDevice() { 299 return device_locked_ && registration_mode_ == DEVICE_MODE_CONSUMER_KIOSK; 300 } 301 302 std::string EnterpriseInstallAttributes::GetRegistrationUser() { 303 if (!device_locked_) 304 return std::string(); 305 306 return registration_user_; 307 } 308 309 std::string EnterpriseInstallAttributes::GetDomain() { 310 if (!IsEnterpriseDevice()) 311 return std::string(); 312 313 return registration_domain_; 314 } 315 316 std::string EnterpriseInstallAttributes::GetDeviceId() { 317 if (!IsEnterpriseDevice()) 318 return std::string(); 319 320 return registration_device_id_; 321 } 322 323 DeviceMode EnterpriseInstallAttributes::GetMode() { 324 return registration_mode_; 325 } 326 327 void EnterpriseInstallAttributes::DecodeInstallAttributes( 328 const std::map<std::string, std::string>& attr_map) { 329 std::string enterprise_owned; 330 std::string enterprise_user; 331 std::string consumer_kiosk_enabled; 332 if (ReadMapKey(attr_map, kAttrEnterpriseOwned, &enterprise_owned) && 333 ReadMapKey(attr_map, kAttrEnterpriseUser, &enterprise_user) && 334 enterprise_owned == "true" && 335 !enterprise_user.empty()) { 336 registration_user_ = gaia::CanonicalizeEmail(enterprise_user); 337 338 // Initialize the mode to the legacy enterprise mode here and update 339 // below if more information is present. 340 registration_mode_ = DEVICE_MODE_ENTERPRISE; 341 342 // If we could extract basic setting we should try to extract the 343 // extended ones too. We try to set these to defaults as good as 344 // as possible if present, which could happen for device enrolled in 345 // pre 19 revisions of the code, before these new attributes were added. 346 if (ReadMapKey(attr_map, kAttrEnterpriseDomain, ®istration_domain_)) 347 registration_domain_ = gaia::CanonicalizeDomain(registration_domain_); 348 else 349 registration_domain_ = gaia::ExtractDomainName(registration_user_); 350 351 ReadMapKey(attr_map, kAttrEnterpriseDeviceId, ®istration_device_id_); 352 353 std::string mode; 354 if (ReadMapKey(attr_map, kAttrEnterpriseMode, &mode)) 355 registration_mode_ = GetDeviceModeFromString(mode); 356 } else if (ReadMapKey(attr_map, 357 kAttrConsumerKioskEnabled, 358 &consumer_kiosk_enabled) && 359 consumer_kiosk_enabled == "true") { 360 registration_mode_ = DEVICE_MODE_CONSUMER_KIOSK; 361 } else if (enterprise_user.empty() && enterprise_owned != "true") { 362 // |registration_user_| is empty on consumer devices. 363 registration_mode_ = DEVICE_MODE_CONSUMER; 364 } 365 } 366 367 } // namespace policy 368