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/files/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 bool ReadMapKey(const std::map<std::string, std::string>& map, 26 const std::string& key, 27 std::string* value) { 28 std::map<std::string, std::string>::const_iterator entry = map.find(key); 29 if (entry == map.end()) 30 return false; 31 32 *value = entry->second; 33 return true; 34 } 35 36 } // namespace 37 38 // static 39 std::string 40 EnterpriseInstallAttributes::GetEnterpriseOwnedInstallAttributesBlobForTesting( 41 const std::string& user_name) { 42 cryptohome::SerializedInstallAttributes install_attrs_proto; 43 cryptohome::SerializedInstallAttributes::Attribute* attribute = NULL; 44 45 attribute = install_attrs_proto.add_attributes(); 46 attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseOwned); 47 attribute->set_value("true"); 48 49 attribute = install_attrs_proto.add_attributes(); 50 attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseUser); 51 attribute->set_value(user_name); 52 53 return install_attrs_proto.SerializeAsString(); 54 } 55 56 EnterpriseInstallAttributes::EnterpriseInstallAttributes( 57 chromeos::CryptohomeClient* cryptohome_client) 58 : device_locked_(false), 59 registration_mode_(DEVICE_MODE_PENDING), 60 cryptohome_client_(cryptohome_client), 61 weak_ptr_factory_(this) { 62 } 63 64 EnterpriseInstallAttributes::~EnterpriseInstallAttributes() {} 65 66 void EnterpriseInstallAttributes::ReadCacheFile( 67 const base::FilePath& cache_file) { 68 if (device_locked_ || !base::PathExists(cache_file)) 69 return; 70 71 device_locked_ = true; 72 73 char buf[16384]; 74 int len = base::ReadFile(cache_file, buf, sizeof(buf)); 75 if (len == -1 || len >= static_cast<int>(sizeof(buf))) { 76 PLOG(ERROR) << "Failed to read " << cache_file.value(); 77 return; 78 } 79 80 cryptohome::SerializedInstallAttributes install_attrs_proto; 81 if (!install_attrs_proto.ParseFromArray(buf, len)) { 82 LOG(ERROR) << "Failed to parse install attributes cache"; 83 return; 84 } 85 86 google::protobuf::RepeatedPtrField< 87 const cryptohome::SerializedInstallAttributes::Attribute>::iterator entry; 88 std::map<std::string, std::string> attr_map; 89 for (entry = install_attrs_proto.attributes().begin(); 90 entry != install_attrs_proto.attributes().end(); 91 ++entry) { 92 // The protobuf values unfortunately contain terminating null characters, so 93 // we have to sanitize the value here. 94 attr_map.insert(std::make_pair(entry->name(), 95 std::string(entry->value().c_str()))); 96 } 97 98 DecodeInstallAttributes(attr_map); 99 } 100 101 void EnterpriseInstallAttributes::ReadImmutableAttributes( 102 const base::Closure& callback) { 103 if (device_locked_) { 104 callback.Run(); 105 return; 106 } 107 108 cryptohome_client_->InstallAttributesIsReady( 109 base::Bind(&EnterpriseInstallAttributes::ReadAttributesIfReady, 110 weak_ptr_factory_.GetWeakPtr(), 111 callback)); 112 } 113 114 void EnterpriseInstallAttributes::ReadAttributesIfReady( 115 const base::Closure& callback, 116 chromeos::DBusMethodCallStatus call_status, 117 bool result) { 118 if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS && result) { 119 registration_mode_ = DEVICE_MODE_NOT_SET; 120 if (!cryptohome_util::InstallAttributesIsInvalid() && 121 !cryptohome_util::InstallAttributesIsFirstInstall()) { 122 device_locked_ = true; 123 124 static const char* kEnterpriseAttributes[] = { 125 kAttrEnterpriseDeviceId, 126 kAttrEnterpriseDomain, 127 kAttrEnterpriseMode, 128 kAttrEnterpriseOwned, 129 kAttrEnterpriseUser, 130 kAttrConsumerKioskEnabled, 131 }; 132 std::map<std::string, std::string> attr_map; 133 for (size_t i = 0; i < arraysize(kEnterpriseAttributes); ++i) { 134 std::string value; 135 if (cryptohome_util::InstallAttributesGet(kEnterpriseAttributes[i], 136 &value)) 137 attr_map[kEnterpriseAttributes[i]] = value; 138 } 139 140 DecodeInstallAttributes(attr_map); 141 } 142 } 143 callback.Run(); 144 } 145 146 void EnterpriseInstallAttributes::LockDevice( 147 const std::string& user, 148 DeviceMode device_mode, 149 const std::string& device_id, 150 const LockResultCallback& callback) { 151 DCHECK(!callback.is_null()); 152 CHECK_NE(device_mode, DEVICE_MODE_PENDING); 153 CHECK_NE(device_mode, DEVICE_MODE_NOT_SET); 154 155 // Check for existing lock first. 156 if (device_locked_) { 157 if (device_mode == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH) { 158 callback.Run((registration_mode_ == device_mode) ? LOCK_SUCCESS : 159 LOCK_NOT_READY); 160 } else { 161 std::string domain = gaia::ExtractDomainName(user); 162 callback.Run( 163 (!registration_domain_.empty() && domain == registration_domain_) ? 164 LOCK_SUCCESS : LOCK_WRONG_USER); 165 } 166 return; 167 } 168 169 cryptohome_client_->InstallAttributesIsReady( 170 base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady, 171 weak_ptr_factory_.GetWeakPtr(), 172 user, 173 device_mode, 174 device_id, 175 callback)); 176 } 177 178 void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady( 179 const std::string& user, 180 DeviceMode device_mode, 181 const std::string& device_id, 182 const LockResultCallback& callback, 183 chromeos::DBusMethodCallStatus call_status, 184 bool result) { 185 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) { 186 callback.Run(LOCK_NOT_READY); 187 return; 188 } 189 190 // Clearing the TPM password seems to be always a good deal. 191 if (cryptohome_util::TpmIsEnabled() && 192 !cryptohome_util::TpmIsBeingOwned() && 193 cryptohome_util::TpmIsOwned()) { 194 cryptohome_client_->CallTpmClearStoredPasswordAndBlock(); 195 } 196 197 // Make sure we really have a working InstallAttrs. 198 if (cryptohome_util::InstallAttributesIsInvalid()) { 199 LOG(ERROR) << "Install attributes invalid."; 200 callback.Run(LOCK_BACKEND_ERROR); 201 return; 202 } 203 204 if (!cryptohome_util::InstallAttributesIsFirstInstall()) { 205 callback.Run(LOCK_BACKEND_ERROR); 206 return; 207 } 208 209 std::string mode = GetDeviceModeString(device_mode); 210 std::string registration_user; 211 if (!user.empty()) 212 registration_user = gaia::CanonicalizeEmail(user); 213 214 if (device_mode == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH) { 215 // Set values in the InstallAttrs and lock it. 216 if (!cryptohome_util::InstallAttributesSet(kAttrConsumerKioskEnabled, 217 "true")) { 218 LOG(ERROR) << "Failed writing attributes"; 219 callback.Run(LOCK_BACKEND_ERROR); 220 return; 221 } 222 } else { 223 std::string domain = gaia::ExtractDomainName(registration_user); 224 // Set values in the InstallAttrs and lock it. 225 if (!cryptohome_util::InstallAttributesSet(kAttrEnterpriseOwned, "true") || 226 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseUser, 227 registration_user) || 228 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDomain, 229 domain) || 230 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseMode, mode) || 231 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDeviceId, 232 device_id)) { 233 LOG(ERROR) << "Failed writing attributes"; 234 callback.Run(LOCK_BACKEND_ERROR); 235 return; 236 } 237 } 238 239 if (!cryptohome_util::InstallAttributesFinalize() || 240 cryptohome_util::InstallAttributesIsFirstInstall()) { 241 LOG(ERROR) << "Failed locking."; 242 callback.Run(LOCK_BACKEND_ERROR); 243 return; 244 } 245 246 ReadImmutableAttributes( 247 base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes, 248 weak_ptr_factory_.GetWeakPtr(), 249 registration_user, 250 callback)); 251 } 252 253 void EnterpriseInstallAttributes::OnReadImmutableAttributes( 254 const std::string& registration_user, 255 const LockResultCallback& callback) { 256 257 if (GetRegistrationUser() != registration_user) { 258 LOG(ERROR) << "Locked data doesn't match"; 259 callback.Run(LOCK_BACKEND_ERROR); 260 return; 261 } 262 263 callback.Run(LOCK_SUCCESS); 264 } 265 266 bool EnterpriseInstallAttributes::IsEnterpriseDevice() { 267 return device_locked_ && !registration_user_.empty(); 268 } 269 270 bool EnterpriseInstallAttributes::IsConsumerKioskDeviceWithAutoLaunch() { 271 return device_locked_ && 272 registration_mode_ == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH; 273 } 274 275 std::string EnterpriseInstallAttributes::GetRegistrationUser() { 276 if (!device_locked_) 277 return std::string(); 278 279 return registration_user_; 280 } 281 282 std::string EnterpriseInstallAttributes::GetDomain() { 283 if (!IsEnterpriseDevice()) 284 return std::string(); 285 286 return registration_domain_; 287 } 288 289 std::string EnterpriseInstallAttributes::GetDeviceId() { 290 if (!IsEnterpriseDevice()) 291 return std::string(); 292 293 return registration_device_id_; 294 } 295 296 DeviceMode EnterpriseInstallAttributes::GetMode() { 297 return registration_mode_; 298 } 299 300 // Warning: The values for these keys (but not the keys themselves) are stored 301 // in the protobuf with a trailing zero. Also note that some of these constants 302 // have been copied to login_manager/device_policy_service.cc. Please make sure 303 // that all changes to the constants are reflected there as well. 304 const char EnterpriseInstallAttributes::kConsumerDeviceMode[] = "consumer"; 305 const char EnterpriseInstallAttributes::kEnterpriseDeviceMode[] = "enterprise"; 306 const char EnterpriseInstallAttributes::kRetailKioskDeviceMode[] = "kiosk"; 307 const char EnterpriseInstallAttributes::kConsumerKioskDeviceMode[] = 308 "consumer_kiosk"; 309 const char EnterpriseInstallAttributes::kUnknownDeviceMode[] = "unknown"; 310 311 const char EnterpriseInstallAttributes::kAttrEnterpriseDeviceId[] = 312 "enterprise.device_id"; 313 const char EnterpriseInstallAttributes::kAttrEnterpriseDomain[] = 314 "enterprise.domain"; 315 const char EnterpriseInstallAttributes::kAttrEnterpriseMode[] = 316 "enterprise.mode"; 317 const char EnterpriseInstallAttributes::kAttrEnterpriseOwned[] = 318 "enterprise.owned"; 319 const char EnterpriseInstallAttributes::kAttrEnterpriseUser[] = 320 "enterprise.user"; 321 const char EnterpriseInstallAttributes::kAttrConsumerKioskEnabled[] = 322 "consumer.app_kiosk_enabled"; 323 324 std::string EnterpriseInstallAttributes::GetDeviceModeString(DeviceMode mode) { 325 switch (mode) { 326 case DEVICE_MODE_CONSUMER: 327 return EnterpriseInstallAttributes::kConsumerDeviceMode; 328 case DEVICE_MODE_ENTERPRISE: 329 return EnterpriseInstallAttributes::kEnterpriseDeviceMode; 330 case DEVICE_MODE_RETAIL_KIOSK: 331 return EnterpriseInstallAttributes::kRetailKioskDeviceMode; 332 case DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH: 333 return EnterpriseInstallAttributes::kConsumerKioskDeviceMode; 334 case DEVICE_MODE_PENDING: 335 case DEVICE_MODE_NOT_SET: 336 break; 337 } 338 NOTREACHED() << "Invalid device mode: " << mode; 339 return EnterpriseInstallAttributes::kUnknownDeviceMode; 340 } 341 342 DeviceMode EnterpriseInstallAttributes::GetDeviceModeFromString( 343 const std::string& mode) { 344 if (mode == EnterpriseInstallAttributes::kConsumerDeviceMode) 345 return DEVICE_MODE_CONSUMER; 346 else if (mode == EnterpriseInstallAttributes::kEnterpriseDeviceMode) 347 return DEVICE_MODE_ENTERPRISE; 348 else if (mode == EnterpriseInstallAttributes::kRetailKioskDeviceMode) 349 return DEVICE_MODE_RETAIL_KIOSK; 350 else if (mode == EnterpriseInstallAttributes::kConsumerKioskDeviceMode) 351 return DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH; 352 NOTREACHED() << "Unknown device mode string: " << mode; 353 return DEVICE_MODE_NOT_SET; 354 } 355 356 void EnterpriseInstallAttributes::DecodeInstallAttributes( 357 const std::map<std::string, std::string>& attr_map) { 358 std::string enterprise_owned; 359 std::string enterprise_user; 360 std::string consumer_kiosk_enabled; 361 if (ReadMapKey(attr_map, kAttrEnterpriseOwned, &enterprise_owned) && 362 ReadMapKey(attr_map, kAttrEnterpriseUser, &enterprise_user) && 363 enterprise_owned == "true" && 364 !enterprise_user.empty()) { 365 registration_user_ = gaia::CanonicalizeEmail(enterprise_user); 366 367 // Initialize the mode to the legacy enterprise mode here and update 368 // below if more information is present. 369 registration_mode_ = DEVICE_MODE_ENTERPRISE; 370 371 // If we could extract basic setting we should try to extract the 372 // extended ones too. We try to set these to defaults as good as 373 // as possible if present, which could happen for device enrolled in 374 // pre 19 revisions of the code, before these new attributes were added. 375 if (ReadMapKey(attr_map, kAttrEnterpriseDomain, ®istration_domain_)) 376 registration_domain_ = gaia::CanonicalizeDomain(registration_domain_); 377 else 378 registration_domain_ = gaia::ExtractDomainName(registration_user_); 379 380 ReadMapKey(attr_map, kAttrEnterpriseDeviceId, ®istration_device_id_); 381 382 std::string mode; 383 if (ReadMapKey(attr_map, kAttrEnterpriseMode, &mode)) 384 registration_mode_ = GetDeviceModeFromString(mode); 385 } else if (ReadMapKey(attr_map, 386 kAttrConsumerKioskEnabled, 387 &consumer_kiosk_enabled) && 388 consumer_kiosk_enabled == "true") { 389 registration_mode_ = DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH; 390 } else if (enterprise_user.empty() && enterprise_owned != "true") { 391 // |registration_user_| is empty on consumer devices. 392 registration_mode_ = DEVICE_MODE_CONSUMER; 393 } 394 } 395 396 } // namespace policy 397