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