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.
5 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_controller.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/managed/supervised_user_authentication.h"
18 #include "chrome/browser/chromeos/login/mount_manager.h"
19 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
20 #include "chrome/browser/chromeos/login/user.h"
21 #include "chrome/browser/chromeos/login/user_manager.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/dbus/dbus_thread_manager.h"
26 #include "chromeos/dbus/session_manager_client.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/user_metrics.h"
29 #include "crypto/random.h"
30 #include "google_apis/gaia/google_service_auth_error.h"
36 const int kMasterKeySize
= 32;
37 const int kUserCreationTimeoutSeconds
= 30; // 30 seconds.
39 bool StoreManagedUserFiles(const std::string
& token
,
40 const base::FilePath
& base_path
) {
41 if (!base::SysInfo::IsRunningOnChromeOS()) {
42 // If running on desktop, cryptohome stub does not create home directory.
43 base::CreateDirectory(base_path
);
45 base::FilePath token_file
= base_path
.Append(kManagedUserTokenFilename
);
46 int bytes
= file_util::WriteFile(token_file
, token
.c_str(), token
.length());
53 const int LocallyManagedUserCreationController::kDummyAvatarIndex
= -111;
55 LocallyManagedUserCreationController::StatusConsumer::~StatusConsumer() {}
57 LocallyManagedUserCreationController::UserCreationContext::UserCreationContext()
58 : avatar_index(kDummyAvatarIndex
),
59 token_acquired(false),
60 token_succesfully_written(false),
61 creation_type(NEW_USER
),
62 manager_profile(NULL
) {}
64 LocallyManagedUserCreationController::UserCreationContext::
65 ~UserCreationContext() {}
68 LocallyManagedUserCreationController
*
69 LocallyManagedUserCreationController::current_controller_
= NULL
;
71 LocallyManagedUserCreationController::LocallyManagedUserCreationController(
72 LocallyManagedUserCreationController::StatusConsumer
* consumer
,
73 const std::string
& manager_id
)
74 : consumer_(consumer
),
76 DCHECK(!current_controller_
) << "More than one controller exist.";
77 current_controller_
= this;
78 creation_context_
.reset(
79 new LocallyManagedUserCreationController::UserCreationContext());
80 creation_context_
->manager_id
= manager_id
;
83 LocallyManagedUserCreationController::~LocallyManagedUserCreationController() {
84 current_controller_
= NULL
;
87 void LocallyManagedUserCreationController::SetUpCreation(
88 const base::string16
& display_name
,
89 const std::string
& password
,
91 DCHECK(creation_context_
);
92 creation_context_
->display_name
= display_name
;
93 creation_context_
->password
= password
;
94 creation_context_
->avatar_index
= avatar_index
;
97 void LocallyManagedUserCreationController::StartImport(
98 const base::string16
& display_name
,
99 const std::string
& password
,
101 const std::string
& sync_id
,
102 const std::string
& master_key
) {
103 DCHECK(creation_context_
);
104 creation_context_
->creation_type
= USER_IMPORT
;
105 creation_context_
->display_name
= display_name
;
106 creation_context_
->password
= password
;
107 creation_context_
->avatar_index
= avatar_index
;
108 creation_context_
->sync_user_id
= sync_id
;
109 creation_context_
->master_key
= master_key
;
113 void LocallyManagedUserCreationController::SetManagerProfile(
114 Profile
* manager_profile
) {
115 creation_context_
->manager_profile
= manager_profile
;
118 void LocallyManagedUserCreationController::StartCreation() {
119 DCHECK(creation_context_
);
120 VLOG(1) << "Starting supervised user creation";
122 ProfileSyncService
* sync_service
=
123 ProfileSyncServiceFactory::GetInstance()->GetForProfile(
124 creation_context_
->manager_profile
);
125 ProfileSyncService::SyncStatusSummary status
=
126 sync_service
->QuerySyncStatusSummary();
128 if (status
== ProfileSyncService::DATATYPES_NOT_INITIALIZED
)
129 consumer_
->OnLongCreationWarning();
131 timeout_timer_
.Start(
132 FROM_HERE
, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds
),
134 &LocallyManagedUserCreationController::CreationTimedOut
);
135 SupervisedUserManager
* manager
=
136 UserManager::Get()->GetSupervisedUserManager();
137 manager
->StartCreationTransaction(creation_context_
->display_name
);
139 creation_context_
->local_user_id
= manager
->GenerateUserId();
141 if (creation_context_
->creation_type
== NEW_USER
) {
142 creation_context_
->sync_user_id
=
143 ManagedUserRegistrationUtility::GenerateNewManagedUserId();
146 manager
->CreateUserRecord(
147 creation_context_
->manager_id
,
148 creation_context_
->local_user_id
,
149 creation_context_
->sync_user_id
,
150 creation_context_
->display_name
);
152 manager
->SetCreationTransactionUserId(creation_context_
->local_user_id
);
153 SupervisedUserAuthentication
* authentication
= manager
->GetAuthentication();
154 if (authentication
->FillDataForNewUser(creation_context_
->local_user_id
,
155 creation_context_
->password
,
156 &creation_context_
->password_data
)) {
157 authentication
->StorePasswordData(creation_context_
->local_user_id
,
158 creation_context_
->password_data
);
160 VLOG(1) << "Creating cryptohome";
161 authenticator_
= new ManagedUserAuthenticator(this);
162 authenticator_
->AuthenticateToCreate(creation_context_
->local_user_id
,
163 authentication
->TransformPassword(
164 creation_context_
->local_user_id
,
165 creation_context_
->password
));
168 void LocallyManagedUserCreationController::OnAuthenticationFailure(
169 ManagedUserAuthenticator::AuthState error
) {
170 timeout_timer_
.Stop();
171 ErrorCode code
= NO_ERROR
;
173 case ManagedUserAuthenticator::NO_MOUNT
:
174 code
= CRYPTOHOME_NO_MOUNT
;
176 case ManagedUserAuthenticator::FAILED_MOUNT
:
177 code
= CRYPTOHOME_FAILED_MOUNT
;
179 case ManagedUserAuthenticator::FAILED_TPM
:
180 code
= CRYPTOHOME_FAILED_TPM
;
186 consumer_
->OnCreationError(code
);
189 void LocallyManagedUserCreationController::OnMountSuccess(
190 const std::string
& mount_hash
) {
191 creation_context_
->mount_hash
= mount_hash
;
193 if (creation_context_
->creation_type
== NEW_USER
) {
194 // Generate master password.
195 char master_key_bytes
[kMasterKeySize
];
196 crypto::RandBytes(&master_key_bytes
, sizeof(master_key_bytes
));
197 creation_context_
->master_key
= StringToLowerASCII(base::HexEncode(
198 reinterpret_cast<const void*>(master_key_bytes
),
199 sizeof(master_key_bytes
)));
202 VLOG(1) << "Adding master key";
203 SupervisedUserAuthentication
* authentication
= UserManager::Get()->
204 GetSupervisedUserManager()->GetAuthentication();
206 authenticator_
->AddMasterKey(creation_context_
->local_user_id
,
207 authentication
->TransformPassword(
208 creation_context_
->local_user_id
,
209 creation_context_
->password
),
210 creation_context_
->master_key
);
213 void LocallyManagedUserCreationController::OnAddKeySuccess() {
214 creation_context_
->registration_utility
=
215 ManagedUserRegistrationUtility::Create(
216 creation_context_
->manager_profile
);
218 VLOG(1) << "Creating user on server";
219 // TODO(antrim) : add password data to sync once API is ready.
220 // http://crbug.com/316168
221 ManagedUserRegistrationInfo
info(creation_context_
->display_name
,
222 creation_context_
->avatar_index
);
223 info
.master_key
= creation_context_
->master_key
;
224 timeout_timer_
.Stop();
225 creation_context_
->registration_utility
->Register(
226 creation_context_
->sync_user_id
,
228 base::Bind(&LocallyManagedUserCreationController::RegistrationCallback
,
229 weak_factory_
.GetWeakPtr()));
232 void LocallyManagedUserCreationController::RegistrationCallback(
233 const GoogleServiceAuthError
& error
,
234 const std::string
& token
) {
235 if (error
.state() == GoogleServiceAuthError::NONE
) {
236 timeout_timer_
.Start(
237 FROM_HERE
, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds
),
239 &LocallyManagedUserCreationController::CreationTimedOut
);
242 LOG(ERROR
) << "Managed user creation failed. Error code " << error
.state();
244 consumer_
->OnCreationError(CLOUD_SERVER_ERROR
);
248 void LocallyManagedUserCreationController::CreationTimedOut() {
249 LOG(ERROR
) << "Supervised user creation timed out.";
251 consumer_
->OnCreationTimeout();
254 void LocallyManagedUserCreationController::FinishCreation() {
255 chrome::AttemptUserExit();
258 void LocallyManagedUserCreationController::CancelCreation() {
259 creation_context_
->registration_utility
.reset();
260 chrome::AttemptUserExit();
263 std::string
LocallyManagedUserCreationController::GetManagedUserId() {
264 DCHECK(creation_context_
);
265 return creation_context_
->local_user_id
;
268 void LocallyManagedUserCreationController::TokenFetched(
269 const std::string
& token
) {
270 creation_context_
->token_acquired
= true;
271 creation_context_
->token
= token
;
273 PostTaskAndReplyWithResult(
274 content::BrowserThread::GetBlockingPool(),
276 base::Bind(&StoreManagedUserFiles
,
277 creation_context_
->token
,
278 MountManager::GetHomeDir(creation_context_
->mount_hash
)),
280 &LocallyManagedUserCreationController::OnManagedUserFilesStored
,
281 weak_factory_
.GetWeakPtr()));
284 void LocallyManagedUserCreationController::OnManagedUserFilesStored(
286 timeout_timer_
.Stop();
288 content::RecordAction(
289 base::UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
293 consumer_
->OnCreationError(TOKEN_WRITE_FAILED
);
296 // Assume that new token is valid. It will be automatically invalidated if
297 // sync service fails to use it.
298 UserManager::Get()->SaveUserOAuthStatus(creation_context_
->local_user_id
,
299 User::OAUTH2_TOKEN_STATUS_VALID
);
300 UserManager::Get()->GetSupervisedUserManager()->
301 CommitCreationTransaction();
303 consumer_
->OnCreationSuccess();
306 } // namespace chromeos