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/login/managed/locally_managed_user_creation_controller.h" 6 7 #include "base/bind.h" 8 #include "base/file_util.h" 9 #include "base/files/file_path.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_util.h" 12 #include "base/sys_info.h" 13 #include "base/task_runner_util.h" 14 #include "base/threading/sequenced_worker_pool.h" 15 #include "base/values.h" 16 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h" 17 #include "chrome/browser/chromeos/login/mount_manager.h" 18 #include "chrome/browser/chromeos/login/supervised_user_manager.h" 19 #include "chrome/browser/chromeos/login/user.h" 20 #include "chrome/browser/chromeos/login/user_manager.h" 21 #include "chrome/browser/lifetime/application_lifetime.h" 22 #include "chrome/browser/sync/profile_sync_service.h" 23 #include "chrome/browser/sync/profile_sync_service_factory.h" 24 #include "chromeos/dbus/dbus_thread_manager.h" 25 #include "chromeos/dbus/session_manager_client.h" 26 #include "content/public/browser/browser_thread.h" 27 #include "content/public/browser/user_metrics.h" 28 #include "crypto/random.h" 29 #include "google_apis/gaia/google_service_auth_error.h" 30 31 namespace chromeos { 32 33 namespace { 34 35 const int kMasterKeySize = 32; 36 const int kUserCreationTimeoutSeconds = 30; // 30 seconds. 37 38 bool StoreManagedUserFiles(const std::string& token, 39 const base::FilePath& base_path) { 40 if (!base::SysInfo::IsRunningOnChromeOS()) { 41 // If running on desktop, cryptohome stub does not create home directory. 42 base::CreateDirectory(base_path); 43 } 44 base::FilePath token_file = base_path.Append(kManagedUserTokenFilename); 45 int bytes = file_util::WriteFile(token_file, token.c_str(), token.length()); 46 return bytes >= 0; 47 } 48 49 } // namespace 50 51 // static 52 const int LocallyManagedUserCreationController::kDummyAvatarIndex = -111; 53 54 LocallyManagedUserCreationController::StatusConsumer::~StatusConsumer() {} 55 56 LocallyManagedUserCreationController::UserCreationContext::UserCreationContext() 57 : avatar_index(kDummyAvatarIndex), 58 token_acquired(false), 59 token_succesfully_written(false), 60 creation_type(NEW_USER), 61 manager_profile(NULL) {} 62 63 LocallyManagedUserCreationController::UserCreationContext:: 64 ~UserCreationContext() {} 65 66 // static 67 LocallyManagedUserCreationController* 68 LocallyManagedUserCreationController::current_controller_ = NULL; 69 70 LocallyManagedUserCreationController::LocallyManagedUserCreationController( 71 LocallyManagedUserCreationController::StatusConsumer* consumer, 72 const std::string& manager_id) 73 : consumer_(consumer), 74 weak_factory_(this) { 75 DCHECK(!current_controller_) << "More than one controller exist."; 76 current_controller_ = this; 77 creation_context_.reset( 78 new LocallyManagedUserCreationController::UserCreationContext()); 79 creation_context_->manager_id = manager_id; 80 } 81 82 LocallyManagedUserCreationController::~LocallyManagedUserCreationController() { 83 current_controller_ = NULL; 84 } 85 86 void LocallyManagedUserCreationController::SetUpCreation( 87 const base::string16& display_name, 88 const std::string& password, 89 int avatar_index) { 90 DCHECK(creation_context_); 91 creation_context_->display_name = display_name; 92 creation_context_->password = password; 93 creation_context_->avatar_index = avatar_index; 94 } 95 96 void LocallyManagedUserCreationController::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; 104 creation_context_->display_name = display_name; 105 creation_context_->password = password; 106 creation_context_->avatar_index = avatar_index; 107 creation_context_->sync_user_id = sync_id; 108 creation_context_->master_key = master_key; 109 StartCreation(); 110 } 111 112 void LocallyManagedUserCreationController::SetManagerProfile( 113 Profile* manager_profile) { 114 creation_context_->manager_profile = manager_profile; 115 } 116 117 void LocallyManagedUserCreationController::StartCreation() { 118 DCHECK(creation_context_); 119 VLOG(1) << "Starting supervised user creation"; 120 121 ProfileSyncService* sync_service = 122 ProfileSyncServiceFactory::GetInstance()->GetForProfile( 123 creation_context_->manager_profile); 124 ProfileSyncService::SyncStatusSummary status = 125 sync_service->QuerySyncStatusSummary(); 126 127 if (status == ProfileSyncService::DATATYPES_NOT_INITIALIZED) 128 consumer_->OnLongCreationWarning(); 129 130 timeout_timer_.Start( 131 FROM_HERE, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds), 132 this, 133 &LocallyManagedUserCreationController::CreationTimedOut); 134 SupervisedUserManager* manager = 135 UserManager::Get()->GetSupervisedUserManager(); 136 manager->StartCreationTransaction(creation_context_->display_name); 137 138 creation_context_->local_user_id = manager->GenerateUserId(); 139 140 if (creation_context_->creation_type == NEW_USER) { 141 creation_context_->sync_user_id = 142 ManagedUserRegistrationUtility::GenerateNewManagedUserId(); 143 } 144 145 manager->CreateUserRecord( 146 creation_context_->manager_id, 147 creation_context_->local_user_id, 148 creation_context_->sync_user_id, 149 creation_context_->display_name); 150 151 manager->SetCreationTransactionUserId(creation_context_->local_user_id); 152 VLOG(1) << "Creating cryptohome"; 153 authenticator_ = new ManagedUserAuthenticator(this); 154 authenticator_->AuthenticateToCreate(creation_context_->local_user_id, 155 creation_context_->password); 156 } 157 158 void LocallyManagedUserCreationController::OnAuthenticationFailure( 159 ManagedUserAuthenticator::AuthState error) { 160 timeout_timer_.Stop(); 161 ErrorCode code = NO_ERROR; 162 switch (error) { 163 case ManagedUserAuthenticator::NO_MOUNT: 164 code = CRYPTOHOME_NO_MOUNT; 165 break; 166 case ManagedUserAuthenticator::FAILED_MOUNT: 167 code = CRYPTOHOME_FAILED_MOUNT; 168 break; 169 case ManagedUserAuthenticator::FAILED_TPM: 170 code = CRYPTOHOME_FAILED_TPM; 171 break; 172 default: 173 NOTREACHED(); 174 } 175 if (consumer_) 176 consumer_->OnCreationError(code); 177 } 178 179 void LocallyManagedUserCreationController::OnMountSuccess( 180 const std::string& mount_hash) { 181 creation_context_->mount_hash = mount_hash; 182 183 if (creation_context_->creation_type == NEW_USER) { 184 // Generate master password. 185 char master_key_bytes[kMasterKeySize]; 186 crypto::RandBytes(&master_key_bytes, sizeof(master_key_bytes)); 187 creation_context_->master_key = StringToLowerASCII(base::HexEncode( 188 reinterpret_cast<const void*>(master_key_bytes), 189 sizeof(master_key_bytes))); 190 } 191 192 VLOG(1) << "Adding master key"; 193 authenticator_->AddMasterKey(creation_context_->local_user_id, 194 creation_context_->password, 195 creation_context_->master_key); 196 } 197 198 void LocallyManagedUserCreationController::OnAddKeySuccess() { 199 creation_context_->registration_utility = 200 ManagedUserRegistrationUtility::Create( 201 creation_context_->manager_profile); 202 203 VLOG(1) << "Creating user on server"; 204 ManagedUserRegistrationInfo info(creation_context_->display_name, 205 creation_context_->avatar_index); 206 info.master_key = creation_context_->master_key; 207 timeout_timer_.Stop(); 208 creation_context_->registration_utility->Register( 209 creation_context_->sync_user_id, 210 info, 211 base::Bind(&LocallyManagedUserCreationController::RegistrationCallback, 212 weak_factory_.GetWeakPtr())); 213 } 214 215 void LocallyManagedUserCreationController::RegistrationCallback( 216 const GoogleServiceAuthError& error, 217 const std::string& token) { 218 if (error.state() == GoogleServiceAuthError::NONE) { 219 timeout_timer_.Start( 220 FROM_HERE, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds), 221 this, 222 &LocallyManagedUserCreationController::CreationTimedOut); 223 TokenFetched(token); 224 } else { 225 LOG(ERROR) << "Managed user creation failed. Error code " << error.state(); 226 if (consumer_) 227 consumer_->OnCreationError(CLOUD_SERVER_ERROR); 228 } 229 } 230 231 void LocallyManagedUserCreationController::CreationTimedOut() { 232 LOG(ERROR) << "Supervised user creation timed out."; 233 if (consumer_) 234 consumer_->OnCreationTimeout(); 235 } 236 237 void LocallyManagedUserCreationController::FinishCreation() { 238 chrome::AttemptUserExit(); 239 } 240 241 void LocallyManagedUserCreationController::CancelCreation() { 242 creation_context_->registration_utility.reset(); 243 chrome::AttemptUserExit(); 244 } 245 246 std::string LocallyManagedUserCreationController::GetManagedUserId() { 247 DCHECK(creation_context_); 248 return creation_context_->local_user_id; 249 } 250 251 void LocallyManagedUserCreationController::TokenFetched( 252 const std::string& token) { 253 creation_context_->token_acquired = true; 254 creation_context_->token = token; 255 256 PostTaskAndReplyWithResult( 257 content::BrowserThread::GetBlockingPool(), 258 FROM_HERE, 259 base::Bind(&StoreManagedUserFiles, 260 creation_context_->token, 261 MountManager::GetHomeDir(creation_context_->mount_hash)), 262 base::Bind( 263 &LocallyManagedUserCreationController::OnManagedUserFilesStored, 264 weak_factory_.GetWeakPtr())); 265 } 266 267 void LocallyManagedUserCreationController::OnManagedUserFilesStored( 268 bool success) { 269 timeout_timer_.Stop(); 270 271 content::RecordAction( 272 content::UserMetricsAction("ManagedMode_LocallyManagedUserCreated")); 273 274 if (!success) { 275 if (consumer_) 276 consumer_->OnCreationError(TOKEN_WRITE_FAILED); 277 return; 278 } 279 // Assume that new token is valid. It will be automatically invalidated if 280 // sync service fails to use it. 281 UserManager::Get()->SaveUserOAuthStatus(creation_context_->local_user_id, 282 User::OAUTH2_TOKEN_STATUS_VALID); 283 UserManager::Get()->GetSupervisedUserManager()-> 284 CommitCreationTransaction(); 285 if (consumer_) 286 consumer_->OnCreationSuccess(); 287 } 288 289 } // namespace chromeos 290