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: 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 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) { 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) { 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::IsConsumerKioskDevice() { 307 return device_locked_ && registration_mode_ == DEVICE_MODE_CONSUMER_KIOSK; 308 } 309 310 std::string EnterpriseInstallAttributes::GetRegistrationUser() { 311 if (!device_locked_) 312 return std::string(); 313 314 return registration_user_; 315 } 316 317 std::string EnterpriseInstallAttributes::GetDomain() { 318 if (!IsEnterpriseDevice()) 319 return std::string(); 320 321 return registration_domain_; 322 } 323 324 std::string EnterpriseInstallAttributes::GetDeviceId() { 325 if (!IsEnterpriseDevice()) 326 return std::string(); 327 328 return registration_device_id_; 329 } 330 331 DeviceMode EnterpriseInstallAttributes::GetMode() { 332 return registration_mode_; 333 } 334 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); 345 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; 349 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_); 356 else 357 registration_domain_ = gaia::ExtractDomainName(registration_user_); 358 359 ReadMapKey(attr_map, kAttrEnterpriseDeviceId, ®istration_device_id_); 360 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; 372 } 373 } 374 375 } // namespace policy 376