1 // Copyright 2013 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/supervised_user_manager_impl.h"
7 #include "base/file_util.h"
8 #include "base/files/file_path.h"
9 #include "base/prefs/pref_registry_simple.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/prefs/scoped_user_pref_update.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "base/values.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
19 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
20 #include "chrome/browser/chromeos/login/user_manager_impl.h"
21 #include "chrome/browser/chromeos/profiles/profile_helper.h"
22 #include "chrome/browser/managed_mode/managed_user_service.h"
23 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
24 #include "chromeos/settings/cros_settings_names.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "google_apis/gaia/gaia_auth_util.h"
28 using content::BrowserThread
;
32 // Names for pref keys in Local State.
33 // A map from locally managed user local user id to sync user id.
34 const char kManagedUserSyncId
[] =
37 // A map from locally managed user id to manager user id.
38 const char kManagedUserManagers
[] =
39 "ManagedUserManagers";
41 // A map from locally managed user id to manager display name.
42 const char kManagedUserManagerNames
[] =
43 "ManagedUserManagerNames";
45 // A map from locally managed user id to manager display e-mail.
46 const char kManagedUserManagerDisplayEmails
[] =
47 "ManagedUserManagerDisplayEmails";
49 // A vector pref of the locally managed accounts defined on this device, that
50 // had not logged in yet.
51 const char kLocallyManagedUsersFirstRun
[] = "LocallyManagedUsersFirstRun";
53 // A pref of the next id for locally managed users generation.
54 const char kLocallyManagedUsersNextId
[] =
55 "LocallyManagedUsersNextId";
57 // A pref of the next id for locally managed users generation.
58 const char kLocallyManagedUserCreationTransactionDisplayName
[] =
59 "LocallyManagedUserCreationTransactionDisplayName";
61 // A pref of the next id for locally managed users generation.
62 const char kLocallyManagedUserCreationTransactionUserId
[] =
63 "LocallyManagedUserCreationTransactionUserId";
65 // A map from user id to password schema id.
66 const char kSupervisedUserPasswordSchema
[] =
67 "SupervisedUserPasswordSchema";
69 // A map from user id to password salt.
70 const char kSupervisedUserPasswordSalt
[] =
71 "SupervisedUserPasswordSalt";
73 // A map from user id to password revision.
74 const char kSupervisedUserPasswordRevision
[] =
75 "SupervisedUserPasswordRevision";
77 // A map from user id to flag indicating if password should be updated upon
79 const char kSupervisedUserNeedPasswordUpdate
[] =
80 "SupervisedUserNeedPasswordUpdate";
82 // A map from user id to flag indicating if cryptohome does not have signature
84 const char kSupervisedUserIncompleteKey
[] = "SupervisedUserHasIncompleteKey";
86 std::string
LoadSyncToken(base::FilePath profile_dir
) {
88 base::FilePath token_file
=
89 profile_dir
.Append(chromeos::kManagedUserTokenFilename
);
90 VLOG(1) << "Loading" << token_file
.value();
91 if (!base::ReadFileToString(token_file
, &token
))
100 const char kSchemaVersion
[] = "SchemaVersion";
101 const char kPasswordRevision
[] = "PasswordRevision";
102 const char kSalt
[] = "PasswordSalt";
103 const char kPasswordSignature
[] = "PasswordSignature";
104 const char kEncryptedPassword
[] = "EncryptedPassword";
105 const char kRequirePasswordUpdate
[] = "RequirePasswordUpdate";
106 const char kHasIncompleteKey
[] = "HasIncompleteKey";
107 const char kPasswordEncryptionKey
[] = "password.hmac.encryption";
108 const char kPasswordSignatureKey
[] = "password.hmac.signature";
110 const char kPasswordUpdateFile
[] = "password.update";
111 const int kMinPasswordRevision
= 1;
114 void SupervisedUserManager::RegisterPrefs(PrefRegistrySimple
* registry
) {
115 registry
->RegisterListPref(kLocallyManagedUsersFirstRun
);
116 registry
->RegisterIntegerPref(kLocallyManagedUsersNextId
, 0);
117 registry
->RegisterStringPref(
118 kLocallyManagedUserCreationTransactionDisplayName
, "");
119 registry
->RegisterStringPref(
120 kLocallyManagedUserCreationTransactionUserId
, "");
121 registry
->RegisterDictionaryPref(kManagedUserSyncId
);
122 registry
->RegisterDictionaryPref(kManagedUserManagers
);
123 registry
->RegisterDictionaryPref(kManagedUserManagerNames
);
124 registry
->RegisterDictionaryPref(kManagedUserManagerDisplayEmails
);
126 registry
->RegisterDictionaryPref(kSupervisedUserPasswordSchema
);
127 registry
->RegisterDictionaryPref(kSupervisedUserPasswordSalt
);
128 registry
->RegisterDictionaryPref(kSupervisedUserPasswordRevision
);
130 registry
->RegisterDictionaryPref(kSupervisedUserNeedPasswordUpdate
);
131 registry
->RegisterDictionaryPref(kSupervisedUserIncompleteKey
);
134 SupervisedUserManagerImpl::SupervisedUserManagerImpl(UserManagerImpl
* owner
)
136 cros_settings_(CrosSettings::Get()) {
137 // SupervisedUserManager instance should be used only on UI thread.
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
139 authentication_
.reset(new SupervisedUserAuthentication(this));
142 SupervisedUserManagerImpl::~SupervisedUserManagerImpl() {
145 std::string
SupervisedUserManagerImpl::GenerateUserId() {
146 int counter
= g_browser_process
->local_state()->
147 GetInteger(kLocallyManagedUsersNextId
);
151 id
= base::StringPrintf("%d@%s", counter
,
152 UserManager::kLocallyManagedUserDomain
);
154 user_exists
= (NULL
!= owner_
->FindUser(id
));
155 DCHECK(!user_exists
);
157 LOG(ERROR
) << "Supervised user with id " << id
<< " already exists.";
159 } while (user_exists
);
161 g_browser_process
->local_state()->
162 SetInteger(kLocallyManagedUsersNextId
, counter
);
164 g_browser_process
->local_state()->CommitPendingWrite();
168 bool SupervisedUserManagerImpl::HasSupervisedUsers(
169 const std::string
& manager_id
) const {
170 const UserList
& users
= owner_
->GetUsers();
171 for (UserList::const_iterator it
= users
.begin(); it
!= users
.end(); ++it
) {
172 if ((*it
)->GetType() == User::USER_TYPE_LOCALLY_MANAGED
) {
173 if (manager_id
== GetManagerUserId((*it
)->email()))
180 const User
* SupervisedUserManagerImpl::CreateUserRecord(
181 const std::string
& manager_id
,
182 const std::string
& local_user_id
,
183 const std::string
& sync_user_id
,
184 const base::string16
& display_name
) {
185 const User
* user
= FindByDisplayName(display_name
);
189 const User
* manager
= owner_
->FindUser(manager_id
);
192 PrefService
* local_state
= g_browser_process
->local_state();
194 User
* new_user
= User::CreateLocallyManagedUser(local_user_id
);
196 owner_
->AddUserRecord(new_user
);
198 ListPrefUpdate
prefs_new_users_update(local_state
,
199 kLocallyManagedUsersFirstRun
);
200 DictionaryPrefUpdate
sync_id_update(local_state
, kManagedUserSyncId
);
201 DictionaryPrefUpdate
manager_update(local_state
, kManagedUserManagers
);
202 DictionaryPrefUpdate
manager_name_update(local_state
,
203 kManagedUserManagerNames
);
204 DictionaryPrefUpdate
manager_email_update(local_state
,
205 kManagedUserManagerDisplayEmails
);
207 prefs_new_users_update
->Insert(0, new base::StringValue(local_user_id
));
209 sync_id_update
->SetWithoutPathExpansion(local_user_id
,
210 new base::StringValue(sync_user_id
));
211 manager_update
->SetWithoutPathExpansion(local_user_id
,
212 new base::StringValue(manager
->email()));
213 manager_name_update
->SetWithoutPathExpansion(local_user_id
,
214 new base::StringValue(manager
->GetDisplayName()));
215 manager_email_update
->SetWithoutPathExpansion(local_user_id
,
216 new base::StringValue(manager
->display_email()));
218 owner_
->SaveUserDisplayName(local_user_id
, display_name
);
220 g_browser_process
->local_state()->CommitPendingWrite();
224 std::string
SupervisedUserManagerImpl::GetUserSyncId(const std::string
& user_id
)
227 GetUserStringValue(user_id
, kManagedUserSyncId
, &result
);
231 base::string16
SupervisedUserManagerImpl::GetManagerDisplayName(
232 const std::string
& user_id
) const {
233 PrefService
* local_state
= g_browser_process
->local_state();
234 const base::DictionaryValue
* manager_names
=
235 local_state
->GetDictionary(kManagedUserManagerNames
);
236 base::string16 result
;
237 if (manager_names
->GetStringWithoutPathExpansion(user_id
, &result
) &&
240 return base::UTF8ToUTF16(GetManagerDisplayEmail(user_id
));
243 std::string
SupervisedUserManagerImpl::GetManagerUserId(
244 const std::string
& user_id
) const {
246 GetUserStringValue(user_id
, kManagedUserManagers
, &result
);
250 std::string
SupervisedUserManagerImpl::GetManagerDisplayEmail(
251 const std::string
& user_id
) const {
253 if (GetUserStringValue(user_id
, kManagedUserManagerDisplayEmails
, &result
) &&
256 return GetManagerUserId(user_id
);
259 void SupervisedUserManagerImpl::GetPasswordInformation(
260 const std::string
& user_id
,
261 base::DictionaryValue
* result
) {
263 if (GetUserIntegerValue(user_id
, kSupervisedUserPasswordSchema
, &value
))
264 result
->SetIntegerWithoutPathExpansion(kSchemaVersion
, value
);
265 if (GetUserIntegerValue(user_id
, kSupervisedUserPasswordRevision
, &value
))
266 result
->SetIntegerWithoutPathExpansion(kPasswordRevision
, value
);
269 if (GetUserBooleanValue(user_id
, kSupervisedUserNeedPasswordUpdate
, &flag
))
270 result
->SetBooleanWithoutPathExpansion(kRequirePasswordUpdate
, flag
);
271 if (GetUserBooleanValue(user_id
, kSupervisedUserIncompleteKey
, &flag
))
272 result
->SetBooleanWithoutPathExpansion(kHasIncompleteKey
, flag
);
275 if (GetUserStringValue(user_id
, kSupervisedUserPasswordSalt
, &salt
))
276 result
->SetStringWithoutPathExpansion(kSalt
, salt
);
279 void SupervisedUserManagerImpl::SetPasswordInformation(
280 const std::string
& user_id
,
281 const base::DictionaryValue
* password_info
) {
283 if (password_info
->GetIntegerWithoutPathExpansion(kSchemaVersion
, &value
))
284 SetUserIntegerValue(user_id
, kSupervisedUserPasswordSchema
, value
);
285 if (password_info
->GetIntegerWithoutPathExpansion(kPasswordRevision
, &value
))
286 SetUserIntegerValue(user_id
, kSupervisedUserPasswordRevision
, value
);
289 if (password_info
->GetBooleanWithoutPathExpansion(kRequirePasswordUpdate
,
291 SetUserBooleanValue(user_id
, kSupervisedUserNeedPasswordUpdate
, flag
);
293 if (password_info
->GetBooleanWithoutPathExpansion(kHasIncompleteKey
, &flag
))
294 SetUserBooleanValue(user_id
, kSupervisedUserIncompleteKey
, flag
);
297 if (password_info
->GetStringWithoutPathExpansion(kSalt
, &salt
))
298 SetUserStringValue(user_id
, kSupervisedUserPasswordSalt
, salt
);
299 g_browser_process
->local_state()->CommitPendingWrite();
302 bool SupervisedUserManagerImpl::GetUserStringValue(
303 const std::string
& user_id
,
305 std::string
* out_value
) const {
306 PrefService
* local_state
= g_browser_process
->local_state();
307 const base::DictionaryValue
* dictionary
= local_state
->GetDictionary(key
);
308 return dictionary
->GetStringWithoutPathExpansion(user_id
, out_value
);
311 bool SupervisedUserManagerImpl::GetUserIntegerValue(
312 const std::string
& user_id
,
314 int* out_value
) const {
315 PrefService
* local_state
= g_browser_process
->local_state();
316 const base::DictionaryValue
* dictionary
= local_state
->GetDictionary(key
);
317 return dictionary
->GetIntegerWithoutPathExpansion(user_id
, out_value
);
320 bool SupervisedUserManagerImpl::GetUserBooleanValue(const std::string
& user_id
,
322 bool* out_value
) const {
323 PrefService
* local_state
= g_browser_process
->local_state();
324 const base::DictionaryValue
* dictionary
= local_state
->GetDictionary(key
);
325 return dictionary
->GetBooleanWithoutPathExpansion(user_id
, out_value
);
328 void SupervisedUserManagerImpl::SetUserStringValue(
329 const std::string
& user_id
,
331 const std::string
& value
) {
332 PrefService
* local_state
= g_browser_process
->local_state();
333 DictionaryPrefUpdate
update(local_state
, key
);
334 update
->SetStringWithoutPathExpansion(user_id
, value
);
337 void SupervisedUserManagerImpl::SetUserIntegerValue(
338 const std::string
& user_id
,
341 PrefService
* local_state
= g_browser_process
->local_state();
342 DictionaryPrefUpdate
update(local_state
, key
);
343 update
->SetIntegerWithoutPathExpansion(user_id
, value
);
346 void SupervisedUserManagerImpl::SetUserBooleanValue(const std::string
& user_id
,
349 PrefService
* local_state
= g_browser_process
->local_state();
350 DictionaryPrefUpdate
update(local_state
, key
);
351 update
->SetBooleanWithoutPathExpansion(user_id
, value
);
354 const User
* SupervisedUserManagerImpl::FindByDisplayName(
355 const base::string16
& display_name
) const {
356 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
357 const UserList
& users
= owner_
->GetUsers();
358 for (UserList::const_iterator it
= users
.begin(); it
!= users
.end(); ++it
) {
359 if (((*it
)->GetType() == User::USER_TYPE_LOCALLY_MANAGED
) &&
360 ((*it
)->display_name() == display_name
)) {
367 const User
* SupervisedUserManagerImpl::FindBySyncId(
368 const std::string
& sync_id
) const {
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
370 const UserList
& users
= owner_
->GetUsers();
371 for (UserList::const_iterator it
= users
.begin(); it
!= users
.end(); ++it
) {
372 if (((*it
)->GetType() == User::USER_TYPE_LOCALLY_MANAGED
) &&
373 (GetUserSyncId((*it
)->email()) == sync_id
)) {
380 void SupervisedUserManagerImpl::StartCreationTransaction(
381 const base::string16
& display_name
) {
382 g_browser_process
->local_state()->
383 SetString(kLocallyManagedUserCreationTransactionDisplayName
,
384 base::UTF16ToASCII(display_name
));
385 g_browser_process
->local_state()->CommitPendingWrite();
388 void SupervisedUserManagerImpl::SetCreationTransactionUserId(
389 const std::string
& email
) {
390 g_browser_process
->local_state()->
391 SetString(kLocallyManagedUserCreationTransactionUserId
,
393 g_browser_process
->local_state()->CommitPendingWrite();
396 void SupervisedUserManagerImpl::CommitCreationTransaction() {
397 g_browser_process
->local_state()->
398 ClearPref(kLocallyManagedUserCreationTransactionDisplayName
);
399 g_browser_process
->local_state()->
400 ClearPref(kLocallyManagedUserCreationTransactionUserId
);
401 g_browser_process
->local_state()->CommitPendingWrite();
404 bool SupervisedUserManagerImpl::HasFailedUserCreationTransaction() {
405 return !(g_browser_process
->local_state()->
406 GetString(kLocallyManagedUserCreationTransactionDisplayName
).
410 void SupervisedUserManagerImpl::RollbackUserCreationTransaction() {
411 PrefService
* prefs
= g_browser_process
->local_state();
413 std::string display_name
= prefs
->
414 GetString(kLocallyManagedUserCreationTransactionDisplayName
);
415 std::string user_id
= prefs
->
416 GetString(kLocallyManagedUserCreationTransactionUserId
);
418 LOG(WARNING
) << "Cleaning up transaction for "
419 << display_name
<< "/" << user_id
;
421 if (user_id
.empty()) {
422 // Not much to do - just remove transaction.
423 prefs
->ClearPref(kLocallyManagedUserCreationTransactionDisplayName
);
424 prefs
->CommitPendingWrite();
428 if (gaia::ExtractDomainName(user_id
) !=
429 UserManager::kLocallyManagedUserDomain
) {
430 LOG(WARNING
) << "Clean up transaction for non-locally managed user found :"
431 << user_id
<< ", will not remove data";
432 prefs
->ClearPref(kLocallyManagedUserCreationTransactionDisplayName
);
433 prefs
->ClearPref(kLocallyManagedUserCreationTransactionUserId
);
434 prefs
->CommitPendingWrite();
437 owner_
->RemoveNonOwnerUserInternal(user_id
, NULL
);
439 prefs
->ClearPref(kLocallyManagedUserCreationTransactionDisplayName
);
440 prefs
->ClearPref(kLocallyManagedUserCreationTransactionUserId
);
441 prefs
->CommitPendingWrite();
444 void SupervisedUserManagerImpl::RemoveNonCryptohomeData(
445 const std::string
& user_id
) {
446 PrefService
* prefs
= g_browser_process
->local_state();
447 ListPrefUpdate
prefs_new_users_update(prefs
, kLocallyManagedUsersFirstRun
);
448 prefs_new_users_update
->Remove(base::StringValue(user_id
), NULL
);
450 CleanPref(user_id
, kManagedUserSyncId
);
451 CleanPref(user_id
, kManagedUserManagers
);
452 CleanPref(user_id
, kManagedUserManagerNames
);
453 CleanPref(user_id
, kManagedUserManagerDisplayEmails
);
454 CleanPref(user_id
, kSupervisedUserPasswordSalt
);
455 CleanPref(user_id
, kSupervisedUserPasswordSchema
);
456 CleanPref(user_id
, kSupervisedUserPasswordRevision
);
457 CleanPref(user_id
, kSupervisedUserNeedPasswordUpdate
);
458 CleanPref(user_id
, kSupervisedUserIncompleteKey
);
461 void SupervisedUserManagerImpl::CleanPref(const std::string
& user_id
,
463 PrefService
* prefs
= g_browser_process
->local_state();
464 DictionaryPrefUpdate
dict_update(prefs
, key
);
465 dict_update
->RemoveWithoutPathExpansion(user_id
, NULL
);
468 bool SupervisedUserManagerImpl::CheckForFirstRun(const std::string
& user_id
) {
469 ListPrefUpdate
prefs_new_users_update(g_browser_process
->local_state(),
470 kLocallyManagedUsersFirstRun
);
471 return prefs_new_users_update
->Remove(base::StringValue(user_id
), NULL
);
474 void SupervisedUserManagerImpl::UpdateManagerName(const std::string
& manager_id
,
475 const base::string16
& new_display_name
) {
476 PrefService
* local_state
= g_browser_process
->local_state();
478 const base::DictionaryValue
* manager_ids
=
479 local_state
->GetDictionary(kManagedUserManagers
);
481 DictionaryPrefUpdate
manager_name_update(local_state
,
482 kManagedUserManagerNames
);
483 for (base::DictionaryValue::Iterator
it(*manager_ids
); !it
.IsAtEnd();
486 bool has_manager_id
= it
.value().GetAsString(&user_id
);
487 DCHECK(has_manager_id
);
488 if (user_id
== manager_id
) {
489 manager_name_update
->SetWithoutPathExpansion(
491 new base::StringValue(new_display_name
));
496 SupervisedUserAuthentication
* SupervisedUserManagerImpl::GetAuthentication() {
497 return authentication_
.get();
500 void SupervisedUserManagerImpl::LoadSupervisedUserToken(
502 const LoadTokenCallback
& callback
) {
503 // TODO(antrim): use profile->GetPath() once we sure it is safe.
504 base::FilePath profile_dir
= ProfileHelper::GetProfilePathByUserIdHash(
505 UserManager::Get()->GetUserByProfile(profile
)->username_hash());
506 PostTaskAndReplyWithResult(
507 content::BrowserThread::GetBlockingPool(),
509 base::Bind(&LoadSyncToken
, profile_dir
),
513 void SupervisedUserManagerImpl::ConfigureSyncWithToken(
515 const std::string
& token
) {
517 ManagedUserServiceFactory::GetForProfile(profile
)->InitSync(token
);
520 } // namespace chromeos