1 // Copyright 2014 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/login/supervised/supervised_user_creation_controller_new.h" 6 7 #include "base/base64.h" 8 #include "base/bind.h" 9 #include "base/files/file_path.h" 10 #include "base/files/file_util.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_util.h" 13 #include "base/sys_info.h" 14 #include "base/task_runner_util.h" 15 #include "base/threading/sequenced_worker_pool.h" 16 #include "base/values.h" 17 #include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h" 18 #include "chrome/browser/chromeos/login/supervised/supervised_user_constants.h" 19 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" 20 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h" 21 #include "chrome/browser/chromeos/profiles/profile_helper.h" 22 #include "chrome/browser/lifetime/application_lifetime.h" 23 #include "chrome/browser/sync/profile_sync_service.h" 24 #include "chrome/browser/sync/profile_sync_service_factory.h" 25 #include "chromeos/cryptohome/cryptohome_parameters.h" 26 #include "chromeos/dbus/dbus_thread_manager.h" 27 #include "chromeos/dbus/session_manager_client.h" 28 #include "chromeos/login/auth/key.h" 29 #include "chromeos/login/auth/user_context.h" 30 #include "components/user_manager/user.h" 31 #include "components/user_manager/user_manager.h" 32 #include "content/public/browser/browser_thread.h" 33 #include "content/public/browser/user_metrics.h" 34 #include "crypto/random.h" 35 #include "google_apis/gaia/google_service_auth_error.h" 36 37 namespace chromeos { 38 39 namespace { 40 41 const int kUserCreationTimeoutSeconds = 30; // 30 seconds. 42 43 bool StoreSupervisedUserFiles(const std::string& token, 44 const base::FilePath& base_path) { 45 if (!base::SysInfo::IsRunningOnChromeOS()) { 46 // If running on desktop, cryptohome stub does not create home directory. 47 base::CreateDirectory(base_path); 48 } 49 base::FilePath token_file = base_path.Append(kSupervisedUserTokenFilename); 50 int bytes = base::WriteFile(token_file, token.c_str(), token.length()); 51 return bytes >= 0; 52 } 53 54 } // namespace 55 56 SupervisedUserCreationControllerNew::SupervisedUserCreationControllerNew( 57 SupervisedUserCreationControllerNew::StatusConsumer* consumer, 58 const std::string& manager_id) 59 : SupervisedUserCreationController(consumer), 60 stage_(STAGE_INITIAL), 61 weak_factory_(this) { 62 creation_context_.reset( 63 new SupervisedUserCreationControllerNew::UserCreationContext()); 64 creation_context_->manager_id = manager_id; 65 } 66 67 SupervisedUserCreationControllerNew::~SupervisedUserCreationControllerNew() {} 68 69 SupervisedUserCreationControllerNew::UserCreationContext:: 70 UserCreationContext() {} 71 72 SupervisedUserCreationControllerNew::UserCreationContext:: 73 ~UserCreationContext() {} 74 75 void SupervisedUserCreationControllerNew::SetManagerProfile( 76 Profile* manager_profile) { 77 creation_context_->manager_profile = manager_profile; 78 } 79 80 Profile* SupervisedUserCreationControllerNew::GetManagerProfile() { 81 return creation_context_->manager_profile; 82 } 83 84 void SupervisedUserCreationControllerNew::StartCreation( 85 const base::string16& display_name, 86 const std::string& password, 87 int avatar_index) { 88 DCHECK(creation_context_); 89 creation_context_->creation_type = NEW_USER; 90 creation_context_->display_name = display_name; 91 creation_context_->password = password; 92 creation_context_->avatar_index = avatar_index; 93 StartCreationImpl(); 94 } 95 96 void SupervisedUserCreationControllerNew::StartImport( 97 const base::string16& display_name, 98 const std::string& password, 99 int avatar_index, 100 const std::string& sync_id, 101 const std::string& master_key) { 102 DCHECK(creation_context_); 103 creation_context_->creation_type = USER_IMPORT_OLD; 104 105 creation_context_->display_name = display_name; 106 creation_context_->password = password; 107 creation_context_->avatar_index = avatar_index; 108 109 creation_context_->sync_user_id = sync_id; 110 111 creation_context_->master_key = master_key; 112 StartCreationImpl(); 113 } 114 115 void SupervisedUserCreationControllerNew::StartImport( 116 const base::string16& display_name, 117 int avatar_index, 118 const std::string& sync_id, 119 const std::string& master_key, 120 const base::DictionaryValue* password_data, 121 const std::string& encryption_key, 122 const std::string& signature_key) { 123 DCHECK(creation_context_); 124 creation_context_->creation_type = USER_IMPORT_NEW; 125 126 creation_context_->display_name = display_name; 127 128 creation_context_->avatar_index = avatar_index; 129 130 creation_context_->sync_user_id = sync_id; 131 132 creation_context_->master_key = master_key; 133 134 password_data->GetStringWithoutPathExpansion( 135 kEncryptedPassword, &creation_context_->salted_password); 136 137 creation_context_->signature_key = signature_key; 138 creation_context_->encryption_key = encryption_key; 139 140 creation_context_->password_data.MergeDictionary(password_data); 141 142 StartCreationImpl(); 143 } 144 145 void SupervisedUserCreationControllerNew::StartCreationImpl() { 146 DCHECK(creation_context_); 147 DCHECK_EQ(STAGE_INITIAL, stage_); 148 VLOG(1) << "Starting supervised user creation"; 149 VLOG(1) << " Phase 1 : Prepare keys"; 150 151 SupervisedUserManager* manager = 152 ChromeUserManager::Get()->GetSupervisedUserManager(); 153 manager->StartCreationTransaction(creation_context_->display_name); 154 155 creation_context_->local_user_id = manager->GenerateUserId(); 156 if (creation_context_->creation_type == NEW_USER) { 157 creation_context_->sync_user_id = 158 SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId(); 159 } 160 161 manager->SetCreationTransactionUserId(creation_context_->local_user_id); 162 163 stage_ = TRANSACTION_STARTED; 164 165 manager->CreateUserRecord(creation_context_->manager_id, 166 creation_context_->local_user_id, 167 creation_context_->sync_user_id, 168 creation_context_->display_name); 169 170 SupervisedUserAuthentication* authentication = 171 ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication(); 172 173 // When importing M35+ users we need only to store data, for all other cases 174 // we need to create some keys. 175 if (creation_context_->creation_type != USER_IMPORT_NEW) { 176 // Of all required keys old imported users have only master key. 177 // Otherwise they are the same as newly created users in terms of keys. 178 if (creation_context_->creation_type == NEW_USER) { 179 creation_context_->master_key = authentication->GenerateMasterKey(); 180 } 181 182 base::DictionaryValue extra; 183 authentication->FillDataForNewUser(creation_context_->local_user_id, 184 creation_context_->password, 185 &creation_context_->password_data, 186 &extra); 187 creation_context_->password_data.GetStringWithoutPathExpansion( 188 kEncryptedPassword, &creation_context_->salted_password); 189 extra.GetStringWithoutPathExpansion(kPasswordEncryptionKey, 190 &creation_context_->encryption_key); 191 extra.GetStringWithoutPathExpansion(kPasswordSignatureKey, 192 &creation_context_->signature_key); 193 } 194 195 authentication->StorePasswordData(creation_context_->local_user_id, 196 creation_context_->password_data); 197 stage_ = KEYS_GENERATED; 198 199 VLOG(1) << " Phase 2 : Create cryptohome"; 200 201 timeout_timer_.Start( 202 FROM_HERE, 203 base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds), 204 this, 205 &SupervisedUserCreationControllerNew::CreationTimedOut); 206 authenticator_ = ExtendedAuthenticator::Create(this); 207 UserContext user_context; 208 user_context.SetKey(Key(creation_context_->master_key)); 209 authenticator_->TransformKeyIfNeeded( 210 user_context, 211 base::Bind(&SupervisedUserCreationControllerNew::OnKeyTransformedIfNeeded, 212 weak_factory_.GetWeakPtr())); 213 } 214 215 void SupervisedUserCreationControllerNew::OnKeyTransformedIfNeeded( 216 const UserContext& user_context) { 217 VLOG(1) << " Phase 2.1 : Got hashed master key"; 218 creation_context_->salted_master_key = user_context.GetKey()->GetSecret(); 219 220 // Create home dir with two keys. 221 std::vector<cryptohome::KeyDefinition> keys; 222 223 // Main key is the master key. Just as keys for plain GAIA users, it is salted 224 // with system salt. It has all usual privileges. 225 cryptohome::KeyDefinition master_key(creation_context_->salted_master_key, 226 kCryptohomeMasterKeyLabel, 227 cryptohome::PRIV_DEFAULT); 228 229 keys.push_back(master_key); 230 authenticator_->CreateMount( 231 creation_context_->local_user_id, 232 keys, 233 base::Bind(&SupervisedUserCreationControllerNew::OnMountSuccess, 234 weak_factory_.GetWeakPtr())); 235 } 236 237 void SupervisedUserCreationControllerNew::OnAuthenticationFailure( 238 ExtendedAuthenticator::AuthState error) { 239 timeout_timer_.Stop(); 240 ErrorCode code = NO_ERROR; 241 switch (error) { 242 case SupervisedUserAuthenticator::NO_MOUNT: 243 code = CRYPTOHOME_NO_MOUNT; 244 break; 245 case SupervisedUserAuthenticator::FAILED_MOUNT: 246 code = CRYPTOHOME_FAILED_MOUNT; 247 break; 248 case SupervisedUserAuthenticator::FAILED_TPM: 249 code = CRYPTOHOME_FAILED_TPM; 250 break; 251 default: 252 NOTREACHED(); 253 } 254 stage_ = STAGE_ERROR; 255 if (consumer_) 256 consumer_->OnCreationError(code); 257 } 258 259 void SupervisedUserCreationControllerNew::OnMountSuccess( 260 const std::string& mount_hash) { 261 DCHECK(creation_context_); 262 DCHECK_EQ(KEYS_GENERATED, stage_); 263 VLOG(1) << " Phase 2.2 : Created home dir with master key"; 264 265 creation_context_->mount_hash = mount_hash; 266 267 // Plain text password, hashed and salted with individual salt. 268 // It can be used for mounting homedir, and can be replaced only when signed. 269 cryptohome::KeyDefinition password_key( 270 creation_context_->salted_password, 271 kCryptohomeSupervisedUserKeyLabel, 272 kCryptohomeSupervisedUserKeyPrivileges); 273 std::string encryption_key; 274 base::Base64Decode(creation_context_->encryption_key, &encryption_key); 275 password_key.authorization_data.push_back( 276 cryptohome::KeyDefinition::AuthorizationData(true /* encrypt */, 277 false /* sign */, 278 encryption_key)); 279 std::string signature_key; 280 base::Base64Decode(creation_context_->signature_key, &signature_key); 281 password_key.authorization_data.push_back( 282 cryptohome::KeyDefinition::AuthorizationData(false /* encrypt */, 283 true /* sign */, 284 signature_key)); 285 286 Key key(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234, 287 std::string(), // The salt is stored elsewhere. 288 creation_context_->salted_master_key); 289 key.SetLabel(kCryptohomeMasterKeyLabel); 290 UserContext context(creation_context_->local_user_id); 291 context.SetKey(key); 292 context.SetIsUsingOAuth(false); 293 294 authenticator_->AddKey( 295 context, 296 password_key, 297 true, 298 base::Bind(&SupervisedUserCreationControllerNew::OnAddKeySuccess, 299 weak_factory_.GetWeakPtr())); 300 } 301 302 void SupervisedUserCreationControllerNew::OnAddKeySuccess() { 303 DCHECK(creation_context_); 304 DCHECK_EQ(KEYS_GENERATED, stage_); 305 stage_ = CRYPTOHOME_CREATED; 306 307 VLOG(1) << " Phase 3 : Create/update user on chrome.com/manage"; 308 309 ProfileSyncService* sync_service = 310 ProfileSyncServiceFactory::GetInstance()->GetForProfile( 311 creation_context_->manager_profile); 312 ProfileSyncService::SyncStatusSummary status = 313 sync_service->QuerySyncStatusSummary(); 314 315 if (status == ProfileSyncService::DATATYPES_NOT_INITIALIZED) 316 consumer_->OnLongCreationWarning(); 317 318 creation_context_->registration_utility = 319 SupervisedUserRegistrationUtility::Create( 320 creation_context_->manager_profile); 321 322 SupervisedUserRegistrationInfo info(creation_context_->display_name, 323 creation_context_->avatar_index); 324 info.master_key = creation_context_->master_key; 325 info.password_signature_key = creation_context_->signature_key; 326 info.password_encryption_key = creation_context_->encryption_key; 327 328 info.password_data.MergeDictionary(&creation_context_->password_data); 329 330 // Registration utility will update user data if user already exist. 331 creation_context_->registration_utility->Register( 332 creation_context_->sync_user_id, 333 info, 334 base::Bind(&SupervisedUserCreationControllerNew::RegistrationCallback, 335 weak_factory_.GetWeakPtr())); 336 } 337 338 void SupervisedUserCreationControllerNew::RegistrationCallback( 339 const GoogleServiceAuthError& error, 340 const std::string& token) { 341 DCHECK(creation_context_); 342 DCHECK_EQ(CRYPTOHOME_CREATED, stage_); 343 344 stage_ = DASHBOARD_CREATED; 345 346 if (error.state() == GoogleServiceAuthError::NONE) { 347 creation_context_->token = token; 348 349 PostTaskAndReplyWithResult( 350 content::BrowserThread::GetBlockingPool(), 351 FROM_HERE, 352 base::Bind(&StoreSupervisedUserFiles, 353 creation_context_->token, 354 ProfileHelper::GetProfilePathByUserIdHash( 355 creation_context_->mount_hash)), 356 base::Bind( 357 &SupervisedUserCreationControllerNew::OnSupervisedUserFilesStored, 358 weak_factory_.GetWeakPtr())); 359 } else { 360 stage_ = STAGE_ERROR; 361 LOG(ERROR) << "Supervised user creation failed. Error code " 362 << error.state(); 363 if (consumer_) 364 consumer_->OnCreationError(CLOUD_SERVER_ERROR); 365 } 366 } 367 368 void SupervisedUserCreationControllerNew::OnSupervisedUserFilesStored( 369 bool success) { 370 DCHECK(creation_context_); 371 DCHECK_EQ(DASHBOARD_CREATED, stage_); 372 373 if (!success) { 374 stage_ = STAGE_ERROR; 375 if (consumer_) 376 consumer_->OnCreationError(TOKEN_WRITE_FAILED); 377 return; 378 } 379 // Assume that new token is valid. It will be automatically invalidated if 380 // sync service fails to use it. 381 user_manager::UserManager::Get()->SaveUserOAuthStatus( 382 creation_context_->local_user_id, 383 user_manager::User::OAUTH2_TOKEN_STATUS_VALID); 384 385 stage_ = TOKEN_WRITTEN; 386 387 timeout_timer_.Stop(); 388 ChromeUserManager::Get() 389 ->GetSupervisedUserManager() 390 ->CommitCreationTransaction(); 391 content::RecordAction( 392 base::UserMetricsAction("ManagedMode_LocallyManagedUserCreated")); 393 394 stage_ = TRANSACTION_COMMITTED; 395 396 if (consumer_) 397 consumer_->OnCreationSuccess(); 398 } 399 400 void SupervisedUserCreationControllerNew::CreationTimedOut() { 401 LOG(ERROR) << "Supervised user creation timed out. stage = " << stage_; 402 if (consumer_) 403 consumer_->OnCreationTimeout(); 404 } 405 406 void SupervisedUserCreationControllerNew::FinishCreation() { 407 chrome::AttemptUserExit(); 408 } 409 410 void SupervisedUserCreationControllerNew::CancelCreation() { 411 creation_context_->registration_utility.reset(); 412 chrome::AttemptUserExit(); 413 } 414 415 std::string SupervisedUserCreationControllerNew::GetSupervisedUserId() { 416 DCHECK(creation_context_); 417 return creation_context_->local_user_id; 418 } 419 420 } // namespace chromeos 421