Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / managed / managed_user_creation_controller_new.cc
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/managed/managed_user_creation_controller_new.h"
6
7 #include "base/base64.h"
8 #include "base/bind.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"
35
36 namespace chromeos {
37
38 namespace {
39
40 const int kUserCreationTimeoutSeconds = 30;  // 30 seconds.
41
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);
47   }
48   base::FilePath token_file = base_path.Append(kSupervisedUserTokenFilename);
49   int bytes = base::WriteFile(token_file, token.c_str(), token.length());
50   return bytes >= 0;
51 }
52
53 }  // namespace
54
55 ManagedUserCreationControllerNew::ManagedUserCreationControllerNew(
56     ManagedUserCreationControllerNew::StatusConsumer* consumer,
57     const std::string& manager_id)
58     : ManagedUserCreationController(consumer),
59       stage_(STAGE_INITIAL),
60       weak_factory_(this) {
61   creation_context_.reset(
62       new ManagedUserCreationControllerNew::UserCreationContext());
63   creation_context_->manager_id = manager_id;
64 }
65
66 ManagedUserCreationControllerNew::~ManagedUserCreationControllerNew() {}
67
68 ManagedUserCreationControllerNew::UserCreationContext::UserCreationContext() {}
69
70 ManagedUserCreationControllerNew::UserCreationContext::~UserCreationContext() {}
71
72 void ManagedUserCreationControllerNew::SetManagerProfile(
73     Profile* manager_profile) {
74   creation_context_->manager_profile = manager_profile;
75 }
76
77 Profile* ManagedUserCreationControllerNew::GetManagerProfile() {
78   return creation_context_->manager_profile;
79 }
80
81 void ManagedUserCreationControllerNew::StartCreation(
82     const base::string16& display_name,
83     const std::string& password,
84     int avatar_index) {
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;
90   StartCreationImpl();
91 }
92
93 void ManagedUserCreationControllerNew::StartImport(
94     const base::string16& display_name,
95     const std::string& password,
96     int avatar_index,
97     const std::string& sync_id,
98     const std::string& master_key) {
99   DCHECK(creation_context_);
100   creation_context_->creation_type = USER_IMPORT_OLD;
101
102   creation_context_->display_name = display_name;
103   creation_context_->password = password;
104   creation_context_->avatar_index = avatar_index;
105
106   creation_context_->sync_user_id = sync_id;
107
108   creation_context_->master_key = master_key;
109   StartCreationImpl();
110 }
111
112 void ManagedUserCreationControllerNew::StartImport(
113     const base::string16& display_name,
114     int avatar_index,
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;
122
123   creation_context_->display_name = display_name;
124
125   creation_context_->avatar_index = avatar_index;
126
127   creation_context_->sync_user_id = sync_id;
128
129   creation_context_->master_key = master_key;
130
131   password_data->GetStringWithoutPathExpansion(
132       kEncryptedPassword, &creation_context_->salted_password);
133
134   creation_context_->signature_key = signature_key;
135   creation_context_->encryption_key = encryption_key;
136
137   creation_context_->password_data.MergeDictionary(password_data);
138
139   StartCreationImpl();
140 }
141
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";
147
148   SupervisedUserManager* manager =
149       UserManager::Get()->GetSupervisedUserManager();
150   manager->StartCreationTransaction(creation_context_->display_name);
151
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();
156   }
157
158   manager->SetCreationTransactionUserId(creation_context_->local_user_id);
159
160   stage_ = TRANSACTION_STARTED;
161
162   manager->CreateUserRecord(creation_context_->manager_id,
163                             creation_context_->local_user_id,
164                             creation_context_->sync_user_id,
165                             creation_context_->display_name);
166
167   SupervisedUserAuthentication* authentication =
168       UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
169
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();
177     }
178
179     base::DictionaryValue extra;
180     authentication->FillDataForNewUser(creation_context_->local_user_id,
181                                        creation_context_->password,
182                                        &creation_context_->password_data,
183                                        &extra);
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);
190   }
191
192   authentication->StorePasswordData(creation_context_->local_user_id,
193                                     creation_context_->password_data);
194   stage_ = KEYS_GENERATED;
195
196   VLOG(1) << " Phase 2 : Create cryptohome";
197
198   timeout_timer_.Start(
199       FROM_HERE,
200       base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds),
201       this,
202       &ManagedUserCreationControllerNew::CreationTimedOut);
203   authenticator_ = new ExtendedAuthenticator(this);
204   UserContext user_context;
205   user_context.SetKey(Key(creation_context_->master_key));
206   authenticator_->TransformKeyIfNeeded(
207       user_context,
208       base::Bind(&ManagedUserCreationControllerNew::OnKeyTransformedIfNeeded,
209                  weak_factory_.GetWeakPtr()));
210 }
211
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();
216
217   // Create home dir with two keys.
218   std::vector<cryptohome::KeyDefinition> keys;
219
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);
225
226   keys.push_back(master_key);
227   authenticator_->CreateMount(
228       creation_context_->local_user_id,
229       keys,
230       base::Bind(&ManagedUserCreationControllerNew::OnMountSuccess,
231                  weak_factory_.GetWeakPtr()));
232 }
233
234 void ManagedUserCreationControllerNew::OnAuthenticationFailure(
235     ExtendedAuthenticator::AuthState error) {
236   timeout_timer_.Stop();
237   ErrorCode code = NO_ERROR;
238   switch (error) {
239     case ManagedUserAuthenticator::NO_MOUNT:
240       code = CRYPTOHOME_NO_MOUNT;
241       break;
242     case ManagedUserAuthenticator::FAILED_MOUNT:
243       code = CRYPTOHOME_FAILED_MOUNT;
244       break;
245     case ManagedUserAuthenticator::FAILED_TPM:
246       code = CRYPTOHOME_FAILED_TPM;
247       break;
248     default:
249       NOTREACHED();
250   }
251   stage_ = STAGE_ERROR;
252   if (consumer_)
253     consumer_->OnCreationError(code);
254 }
255
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";
261
262   creation_context_->mount_hash = mount_hash;
263
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);
274
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);
280   context.SetKey(key);
281   context.SetIsUsingOAuth(false);
282
283   authenticator_->AddKey(
284       context,
285       password_key,
286       true,
287       base::Bind(&ManagedUserCreationControllerNew::OnAddKeySuccess,
288                  weak_factory_.GetWeakPtr()));
289 }
290
291 void ManagedUserCreationControllerNew::OnAddKeySuccess() {
292   DCHECK(creation_context_);
293   DCHECK_EQ(KEYS_GENERATED, stage_);
294   stage_ = CRYPTOHOME_CREATED;
295
296   VLOG(1) << " Phase 3 : Create/update user on chrome.com/manage";
297
298   ProfileSyncService* sync_service =
299       ProfileSyncServiceFactory::GetInstance()->GetForProfile(
300           creation_context_->manager_profile);
301   ProfileSyncService::SyncStatusSummary status =
302       sync_service->QuerySyncStatusSummary();
303
304   if (status == ProfileSyncService::DATATYPES_NOT_INITIALIZED)
305     consumer_->OnLongCreationWarning();
306
307   creation_context_->registration_utility =
308       SupervisedUserRegistrationUtility::Create(
309           creation_context_->manager_profile);
310
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;
316
317   info.password_data.MergeDictionary(&creation_context_->password_data);
318
319   // Registration utility will update user data if user already exist.
320   creation_context_->registration_utility->Register(
321       creation_context_->sync_user_id,
322       info,
323       base::Bind(&ManagedUserCreationControllerNew::RegistrationCallback,
324                  weak_factory_.GetWeakPtr()));
325 }
326
327 void ManagedUserCreationControllerNew::RegistrationCallback(
328     const GoogleServiceAuthError& error,
329     const std::string& token) {
330   DCHECK(creation_context_);
331   DCHECK_EQ(CRYPTOHOME_CREATED, stage_);
332
333   stage_ = DASHBOARD_CREATED;
334
335   if (error.state() == GoogleServiceAuthError::NONE) {
336     creation_context_->token = token;
337
338     PostTaskAndReplyWithResult(
339         content::BrowserThread::GetBlockingPool(),
340         FROM_HERE,
341         base::Bind(&StoreManagedUserFiles,
342                    creation_context_->token,
343                    MountManager::GetHomeDir(creation_context_->mount_hash)),
344         base::Bind(&ManagedUserCreationControllerNew::OnManagedUserFilesStored,
345                    weak_factory_.GetWeakPtr()));
346   } else {
347     stage_ = STAGE_ERROR;
348     LOG(ERROR) << "Managed user creation failed. Error code " << error.state();
349     if (consumer_)
350       consumer_->OnCreationError(CLOUD_SERVER_ERROR);
351   }
352 }
353
354 void ManagedUserCreationControllerNew::OnManagedUserFilesStored(bool success) {
355   DCHECK(creation_context_);
356   DCHECK_EQ(DASHBOARD_CREATED, stage_);
357
358   if (!success) {
359     stage_ = STAGE_ERROR;
360     if (consumer_)
361       consumer_->OnCreationError(TOKEN_WRITE_FAILED);
362     return;
363   }
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);
368
369   stage_ = TOKEN_WRITTEN;
370
371   timeout_timer_.Stop();
372   UserManager::Get()->GetSupervisedUserManager()->CommitCreationTransaction();
373   content::RecordAction(
374       base::UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
375
376   stage_ = TRANSACTION_COMMITTED;
377
378   if (consumer_)
379     consumer_->OnCreationSuccess();
380 }
381
382 void ManagedUserCreationControllerNew::CreationTimedOut() {
383   LOG(ERROR) << "Supervised user creation timed out. stage = " << stage_;
384   if (consumer_)
385     consumer_->OnCreationTimeout();
386 }
387
388 void ManagedUserCreationControllerNew::FinishCreation() {
389   chrome::AttemptUserExit();
390 }
391
392 void ManagedUserCreationControllerNew::CancelCreation() {
393   creation_context_->registration_utility.reset();
394   chrome::AttemptUserExit();
395 }
396
397 std::string ManagedUserCreationControllerNew::GetManagedUserId() {
398   DCHECK(creation_context_);
399   return creation_context_->local_user_id;
400 }
401
402 }  // namespace chromeos