6a244620788ab910fac617c9ecb6e0eb7bc22f9a
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / supervised / supervised_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/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_ = new ExtendedAuthenticator(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