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.
5 #include "chrome/browser/chromeos/login/managed/managed_user_creation_controller_new.h"
7 #include "base/base64.h"
9 #include "base/file_util.h"
10 #include "base/files/file_path.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/auth/key.h"
18 #include "chrome/browser/chromeos/login/auth/mount_manager.h"
19 #include "chrome/browser/chromeos/login/auth/user_context.h"
20 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
21 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
22 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
23 #include "chrome/browser/chromeos/login/users/user.h"
24 #include "chrome/browser/chromeos/login/users/user_manager.h"
25 #include "chrome/browser/lifetime/application_lifetime.h"
26 #include "chrome/browser/sync/profile_sync_service.h"
27 #include "chrome/browser/sync/profile_sync_service_factory.h"
28 #include "chromeos/cryptohome/cryptohome_parameters.h"
29 #include "chromeos/dbus/dbus_thread_manager.h"
30 #include "chromeos/dbus/session_manager_client.h"
31 #include "content/public/browser/browser_thread.h"
32 #include "content/public/browser/user_metrics.h"
33 #include "crypto/random.h"
34 #include "google_apis/gaia/google_service_auth_error.h"
40 const int kUserCreationTimeoutSeconds = 30; // 30 seconds.
42 bool StoreManagedUserFiles(const std::string& token,
43 const base::FilePath& base_path) {
44 if (!base::SysInfo::IsRunningOnChromeOS()) {
45 // If running on desktop, cryptohome stub does not create home directory.
46 base::CreateDirectory(base_path);
48 base::FilePath token_file = base_path.Append(kSupervisedUserTokenFilename);
49 int bytes = base::WriteFile(token_file, token.c_str(), token.length());
55 ManagedUserCreationControllerNew::ManagedUserCreationControllerNew(
56 ManagedUserCreationControllerNew::StatusConsumer* consumer,
57 const std::string& manager_id)
58 : ManagedUserCreationController(consumer),
59 stage_(STAGE_INITIAL),
61 creation_context_.reset(
62 new ManagedUserCreationControllerNew::UserCreationContext());
63 creation_context_->manager_id = manager_id;
66 ManagedUserCreationControllerNew::~ManagedUserCreationControllerNew() {}
68 ManagedUserCreationControllerNew::UserCreationContext::UserCreationContext() {}
70 ManagedUserCreationControllerNew::UserCreationContext::~UserCreationContext() {}
72 void ManagedUserCreationControllerNew::SetManagerProfile(
73 Profile* manager_profile) {
74 creation_context_->manager_profile = manager_profile;
77 Profile* ManagedUserCreationControllerNew::GetManagerProfile() {
78 return creation_context_->manager_profile;
81 void ManagedUserCreationControllerNew::StartCreation(
82 const base::string16& display_name,
83 const std::string& password,
85 DCHECK(creation_context_);
86 creation_context_->creation_type = NEW_USER;
87 creation_context_->display_name = display_name;
88 creation_context_->password = password;
89 creation_context_->avatar_index = avatar_index;
93 void ManagedUserCreationControllerNew::StartImport(
94 const base::string16& display_name,
95 const std::string& password,
97 const std::string& sync_id,
98 const std::string& master_key) {
99 DCHECK(creation_context_);
100 creation_context_->creation_type = USER_IMPORT_OLD;
102 creation_context_->display_name = display_name;
103 creation_context_->password = password;
104 creation_context_->avatar_index = avatar_index;
106 creation_context_->sync_user_id = sync_id;
108 creation_context_->master_key = master_key;
112 void ManagedUserCreationControllerNew::StartImport(
113 const base::string16& display_name,
115 const std::string& sync_id,
116 const std::string& master_key,
117 const base::DictionaryValue* password_data,
118 const std::string& encryption_key,
119 const std::string& signature_key) {
120 DCHECK(creation_context_);
121 creation_context_->creation_type = USER_IMPORT_NEW;
123 creation_context_->display_name = display_name;
125 creation_context_->avatar_index = avatar_index;
127 creation_context_->sync_user_id = sync_id;
129 creation_context_->master_key = master_key;
131 password_data->GetStringWithoutPathExpansion(
132 kEncryptedPassword, &creation_context_->salted_password);
134 creation_context_->signature_key = signature_key;
135 creation_context_->encryption_key = encryption_key;
137 creation_context_->password_data.MergeDictionary(password_data);
142 void ManagedUserCreationControllerNew::StartCreationImpl() {
143 DCHECK(creation_context_);
144 DCHECK_EQ(STAGE_INITIAL, stage_);
145 VLOG(1) << "Starting supervised user creation";
146 VLOG(1) << " Phase 1 : Prepare keys";
148 SupervisedUserManager* manager =
149 UserManager::Get()->GetSupervisedUserManager();
150 manager->StartCreationTransaction(creation_context_->display_name);
152 creation_context_->local_user_id = manager->GenerateUserId();
153 if (creation_context_->creation_type == NEW_USER) {
154 creation_context_->sync_user_id =
155 SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId();
158 manager->SetCreationTransactionUserId(creation_context_->local_user_id);
160 stage_ = TRANSACTION_STARTED;
162 manager->CreateUserRecord(creation_context_->manager_id,
163 creation_context_->local_user_id,
164 creation_context_->sync_user_id,
165 creation_context_->display_name);
167 SupervisedUserAuthentication* authentication =
168 UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
170 // When importing M35+ users we need only to store data, for all other cases
171 // we need to create some keys.
172 if (creation_context_->creation_type != USER_IMPORT_NEW) {
173 // Of all required keys old imported users have only master key.
174 // Otherwise they are the same as newly created users in terms of keys.
175 if (creation_context_->creation_type == NEW_USER) {
176 creation_context_->master_key = authentication->GenerateMasterKey();
179 base::DictionaryValue extra;
180 authentication->FillDataForNewUser(creation_context_->local_user_id,
181 creation_context_->password,
182 &creation_context_->password_data,
184 creation_context_->password_data.GetStringWithoutPathExpansion(
185 kEncryptedPassword, &creation_context_->salted_password);
186 extra.GetStringWithoutPathExpansion(kPasswordEncryptionKey,
187 &creation_context_->encryption_key);
188 extra.GetStringWithoutPathExpansion(kPasswordSignatureKey,
189 &creation_context_->signature_key);
192 authentication->StorePasswordData(creation_context_->local_user_id,
193 creation_context_->password_data);
194 stage_ = KEYS_GENERATED;
196 VLOG(1) << " Phase 2 : Create cryptohome";
198 timeout_timer_.Start(
200 base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds),
202 &ManagedUserCreationControllerNew::CreationTimedOut);
203 authenticator_ = new ExtendedAuthenticator(this);
204 UserContext user_context;
205 user_context.SetKey(Key(creation_context_->master_key));
206 authenticator_->TransformKeyIfNeeded(
208 base::Bind(&ManagedUserCreationControllerNew::OnKeyTransformedIfNeeded,
209 weak_factory_.GetWeakPtr()));
212 void ManagedUserCreationControllerNew::OnKeyTransformedIfNeeded(
213 const UserContext& user_context) {
214 VLOG(1) << " Phase 2.1 : Got hashed master key";
215 creation_context_->salted_master_key = user_context.GetKey()->GetSecret();
217 // Create home dir with two keys.
218 std::vector<cryptohome::KeyDefinition> keys;
220 // Main key is the master key. Just as keys for plain GAIA users, it is salted
221 // with system salt. It has all usual privileges.
222 cryptohome::KeyDefinition master_key(creation_context_->salted_master_key,
223 kCryptohomeMasterKeyLabel,
224 cryptohome::PRIV_DEFAULT);
226 keys.push_back(master_key);
227 authenticator_->CreateMount(
228 creation_context_->local_user_id,
230 base::Bind(&ManagedUserCreationControllerNew::OnMountSuccess,
231 weak_factory_.GetWeakPtr()));
234 void ManagedUserCreationControllerNew::OnAuthenticationFailure(
235 ExtendedAuthenticator::AuthState error) {
236 timeout_timer_.Stop();
237 ErrorCode code = NO_ERROR;
239 case ManagedUserAuthenticator::NO_MOUNT:
240 code = CRYPTOHOME_NO_MOUNT;
242 case ManagedUserAuthenticator::FAILED_MOUNT:
243 code = CRYPTOHOME_FAILED_MOUNT;
245 case ManagedUserAuthenticator::FAILED_TPM:
246 code = CRYPTOHOME_FAILED_TPM;
251 stage_ = STAGE_ERROR;
253 consumer_->OnCreationError(code);
256 void ManagedUserCreationControllerNew::OnMountSuccess(
257 const std::string& mount_hash) {
258 DCHECK(creation_context_);
259 DCHECK_EQ(KEYS_GENERATED, stage_);
260 VLOG(1) << " Phase 2.2 : Created home dir with master key";
262 creation_context_->mount_hash = mount_hash;
264 // Plain text password, hashed and salted with individual salt.
265 // It can be used for mounting homedir, and can be replaced only when signed.
266 cryptohome::KeyDefinition password_key(
267 creation_context_->salted_password,
268 kCryptohomeSupervisedUserKeyLabel,
269 kCryptohomeSupervisedUserKeyPrivileges);
270 base::Base64Decode(creation_context_->encryption_key,
271 &password_key.encryption_key);
272 base::Base64Decode(creation_context_->signature_key,
273 &password_key.signature_key);
275 Key key(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234,
276 std::string(), // The salt is stored elsewhere.
277 creation_context_->salted_master_key);
278 key.SetLabel(kCryptohomeMasterKeyLabel);
279 UserContext context(creation_context_->local_user_id);
281 context.SetIsUsingOAuth(false);
283 authenticator_->AddKey(
287 base::Bind(&ManagedUserCreationControllerNew::OnAddKeySuccess,
288 weak_factory_.GetWeakPtr()));
291 void ManagedUserCreationControllerNew::OnAddKeySuccess() {
292 DCHECK(creation_context_);
293 DCHECK_EQ(KEYS_GENERATED, stage_);
294 stage_ = CRYPTOHOME_CREATED;
296 VLOG(1) << " Phase 3 : Create/update user on chrome.com/manage";
298 ProfileSyncService* sync_service =
299 ProfileSyncServiceFactory::GetInstance()->GetForProfile(
300 creation_context_->manager_profile);
301 ProfileSyncService::SyncStatusSummary status =
302 sync_service->QuerySyncStatusSummary();
304 if (status == ProfileSyncService::DATATYPES_NOT_INITIALIZED)
305 consumer_->OnLongCreationWarning();
307 creation_context_->registration_utility =
308 SupervisedUserRegistrationUtility::Create(
309 creation_context_->manager_profile);
311 SupervisedUserRegistrationInfo info(creation_context_->display_name,
312 creation_context_->avatar_index);
313 info.master_key = creation_context_->master_key;
314 info.password_signature_key = creation_context_->signature_key;
315 info.password_encryption_key = creation_context_->encryption_key;
317 info.password_data.MergeDictionary(&creation_context_->password_data);
319 // Registration utility will update user data if user already exist.
320 creation_context_->registration_utility->Register(
321 creation_context_->sync_user_id,
323 base::Bind(&ManagedUserCreationControllerNew::RegistrationCallback,
324 weak_factory_.GetWeakPtr()));
327 void ManagedUserCreationControllerNew::RegistrationCallback(
328 const GoogleServiceAuthError& error,
329 const std::string& token) {
330 DCHECK(creation_context_);
331 DCHECK_EQ(CRYPTOHOME_CREATED, stage_);
333 stage_ = DASHBOARD_CREATED;
335 if (error.state() == GoogleServiceAuthError::NONE) {
336 creation_context_->token = token;
338 PostTaskAndReplyWithResult(
339 content::BrowserThread::GetBlockingPool(),
341 base::Bind(&StoreManagedUserFiles,
342 creation_context_->token,
343 MountManager::GetHomeDir(creation_context_->mount_hash)),
344 base::Bind(&ManagedUserCreationControllerNew::OnManagedUserFilesStored,
345 weak_factory_.GetWeakPtr()));
347 stage_ = STAGE_ERROR;
348 LOG(ERROR) << "Managed user creation failed. Error code " << error.state();
350 consumer_->OnCreationError(CLOUD_SERVER_ERROR);
354 void ManagedUserCreationControllerNew::OnManagedUserFilesStored(bool success) {
355 DCHECK(creation_context_);
356 DCHECK_EQ(DASHBOARD_CREATED, stage_);
359 stage_ = STAGE_ERROR;
361 consumer_->OnCreationError(TOKEN_WRITE_FAILED);
364 // Assume that new token is valid. It will be automatically invalidated if
365 // sync service fails to use it.
366 UserManager::Get()->SaveUserOAuthStatus(creation_context_->local_user_id,
367 User::OAUTH2_TOKEN_STATUS_VALID);
369 stage_ = TOKEN_WRITTEN;
371 timeout_timer_.Stop();
372 UserManager::Get()->GetSupervisedUserManager()->CommitCreationTransaction();
373 content::RecordAction(
374 base::UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
376 stage_ = TRANSACTION_COMMITTED;
379 consumer_->OnCreationSuccess();
382 void ManagedUserCreationControllerNew::CreationTimedOut() {
383 LOG(ERROR) << "Supervised user creation timed out. stage = " << stage_;
385 consumer_->OnCreationTimeout();
388 void ManagedUserCreationControllerNew::FinishCreation() {
389 chrome::AttemptUserExit();
392 void ManagedUserCreationControllerNew::CancelCreation() {
393 creation_context_->registration_utility.reset();
394 chrome::AttemptUserExit();
397 std::string ManagedUserCreationControllerNew::GetManagedUserId() {
398 DCHECK(creation_context_);
399 return creation_context_->local_user_id;
402 } // namespace chromeos