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/users/supervised_user_manager_impl.h"
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.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/supervised/supervised_user_authentication.h"
19 #include "chrome/browser/chromeos/login/supervised/supervised_user_constants.h"
20 #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
21 #include "chrome/browser/chromeos/profiles/profile_helper.h"
22 #include "chrome/browser/supervised_user/supervised_user_service.h"
23 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
24 #include "chromeos/login/user_names.h"
25 #include "chromeos/settings/cros_settings_names.h"
26 #include "components/user_manager/user_type.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "google_apis/gaia/gaia_auth_util.h"
30 using content::BrowserThread
;
34 // Names for pref keys in Local State.
35 // A map from supervised user local user id to sync user id.
36 const char kSupervisedUserSyncId
[] = "ManagedUserSyncId";
38 // A map from supervised user id to manager user id.
39 const char kSupervisedUserManagers
[] = "ManagedUserManagers";
41 // A map from supervised user id to manager display name.
42 const char kSupervisedUserManagerNames
[] = "ManagedUserManagerNames";
44 // A map from supervised user id to manager display e-mail.
45 const char kSupervisedUserManagerDisplayEmails
[] =
46 "ManagedUserManagerDisplayEmails";
48 // A vector pref of the supervised accounts defined on this device, that had
50 const char kSupervisedUsersFirstRun
[] = "LocallyManagedUsersFirstRun";
52 // A pref of the next id for supervised users generation.
53 const char kSupervisedUsersNextId
[] = "LocallyManagedUsersNextId";
55 // A pref of the next id for supervised users generation.
56 const char kSupervisedUserCreationTransactionDisplayName
[] =
57 "LocallyManagedUserCreationTransactionDisplayName";
59 // A pref of the next id for supervised users generation.
60 const char kSupervisedUserCreationTransactionUserId
[] =
61 "LocallyManagedUserCreationTransactionUserId";
63 // A map from user id to password schema id.
64 const char kSupervisedUserPasswordSchema
[] =
65 "SupervisedUserPasswordSchema";
67 // A map from user id to password salt.
68 const char kSupervisedUserPasswordSalt
[] =
69 "SupervisedUserPasswordSalt";
71 // A map from user id to password revision.
72 const char kSupervisedUserPasswordRevision
[] =
73 "SupervisedUserPasswordRevision";
75 // A map from user id to flag indicating if password should be updated upon
77 const char kSupervisedUserNeedPasswordUpdate
[] =
78 "SupervisedUserNeedPasswordUpdate";
80 // A map from user id to flag indicating if cryptohome does not have signature
82 const char kSupervisedUserIncompleteKey
[] = "SupervisedUserHasIncompleteKey";
84 std::string
LoadSyncToken(base::FilePath profile_dir
) {
86 base::FilePath token_file
=
87 profile_dir
.Append(chromeos::kSupervisedUserTokenFilename
);
88 VLOG(1) << "Loading" << token_file
.value();
89 if (!base::ReadFileToString(token_file
, &token
))
98 const char kSchemaVersion
[] = "SchemaVersion";
99 const char kPasswordRevision
[] = "PasswordRevision";
100 const char kSalt
[] = "PasswordSalt";
101 const char kPasswordSignature
[] = "PasswordSignature";
102 const char kEncryptedPassword
[] = "EncryptedPassword";
103 const char kRequirePasswordUpdate
[] = "RequirePasswordUpdate";
104 const char kHasIncompleteKey
[] = "HasIncompleteKey";
105 const char kPasswordEncryptionKey
[] = "password.hmac.encryption";
106 const char kPasswordSignatureKey
[] = "password.hmac.signature";
108 const char kPasswordUpdateFile
[] = "password.update";
109 const int kMinPasswordRevision
= 1;
112 void SupervisedUserManager::RegisterPrefs(PrefRegistrySimple
* registry
) {
113 registry
->RegisterListPref(kSupervisedUsersFirstRun
);
114 registry
->RegisterIntegerPref(kSupervisedUsersNextId
, 0);
115 registry
->RegisterStringPref(
116 kSupervisedUserCreationTransactionDisplayName
, "");
117 registry
->RegisterStringPref(
118 kSupervisedUserCreationTransactionUserId
, "");
119 registry
->RegisterDictionaryPref(kSupervisedUserSyncId
);
120 registry
->RegisterDictionaryPref(kSupervisedUserManagers
);
121 registry
->RegisterDictionaryPref(kSupervisedUserManagerNames
);
122 registry
->RegisterDictionaryPref(kSupervisedUserManagerDisplayEmails
);
124 registry
->RegisterDictionaryPref(kSupervisedUserPasswordSchema
);
125 registry
->RegisterDictionaryPref(kSupervisedUserPasswordSalt
);
126 registry
->RegisterDictionaryPref(kSupervisedUserPasswordRevision
);
128 registry
->RegisterDictionaryPref(kSupervisedUserNeedPasswordUpdate
);
129 registry
->RegisterDictionaryPref(kSupervisedUserIncompleteKey
);
132 SupervisedUserManagerImpl::SupervisedUserManagerImpl(
133 ChromeUserManagerImpl
* owner
)
134 : owner_(owner
), cros_settings_(CrosSettings::Get()) {
135 // SupervisedUserManager instance should be used only on UI thread.
136 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
137 authentication_
.reset(new SupervisedUserAuthentication(this));
140 SupervisedUserManagerImpl::~SupervisedUserManagerImpl() {
143 std::string
SupervisedUserManagerImpl::GenerateUserId() {
144 int counter
= g_browser_process
->local_state()->
145 GetInteger(kSupervisedUsersNextId
);
149 id
= base::StringPrintf(
150 "%d@%s", counter
, chromeos::login::kSupervisedUserDomain
);
152 user_exists
= (NULL
!= owner_
->FindUser(id
));
153 DCHECK(!user_exists
);
155 LOG(ERROR
) << "Supervised user with id " << id
<< " already exists.";
157 } while (user_exists
);
159 g_browser_process
->local_state()->
160 SetInteger(kSupervisedUsersNextId
, counter
);
162 g_browser_process
->local_state()->CommitPendingWrite();
166 bool SupervisedUserManagerImpl::HasSupervisedUsers(
167 const std::string
& manager_id
) const {
168 const user_manager::UserList
& users
= owner_
->GetUsers();
169 for (user_manager::UserList::const_iterator it
= users
.begin();
172 if ((*it
)->GetType() == user_manager::USER_TYPE_SUPERVISED
) {
173 if (manager_id
== GetManagerUserId((*it
)->email()))
180 const user_manager::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_manager::User
* user
= FindByDisplayName(display_name
);
189 const user_manager::User
* manager
= owner_
->FindUser(manager_id
);
192 PrefService
* local_state
= g_browser_process
->local_state();
194 user_manager::User
* new_user
=
195 user_manager::User::CreateSupervisedUser(local_user_id
);
197 owner_
->AddUserRecord(new_user
);
199 ListPrefUpdate
prefs_new_users_update(local_state
,
200 kSupervisedUsersFirstRun
);
201 DictionaryPrefUpdate
sync_id_update(local_state
, kSupervisedUserSyncId
);
202 DictionaryPrefUpdate
manager_update(local_state
, kSupervisedUserManagers
);
203 DictionaryPrefUpdate
manager_name_update(local_state
,
204 kSupervisedUserManagerNames
);
205 DictionaryPrefUpdate
manager_email_update(
207 kSupervisedUserManagerDisplayEmails
);
209 prefs_new_users_update
->Insert(0, new base::StringValue(local_user_id
));
211 sync_id_update
->SetWithoutPathExpansion(local_user_id
,
212 new base::StringValue(sync_user_id
));
213 manager_update
->SetWithoutPathExpansion(local_user_id
,
214 new base::StringValue(manager
->email()));
215 manager_name_update
->SetWithoutPathExpansion(local_user_id
,
216 new base::StringValue(manager
->GetDisplayName()));
217 manager_email_update
->SetWithoutPathExpansion(local_user_id
,
218 new base::StringValue(manager
->display_email()));
220 owner_
->SaveUserDisplayName(local_user_id
, display_name
);
222 g_browser_process
->local_state()->CommitPendingWrite();
226 std::string
SupervisedUserManagerImpl::GetUserSyncId(const std::string
& user_id
)
229 GetUserStringValue(user_id
, kSupervisedUserSyncId
, &result
);
233 base::string16
SupervisedUserManagerImpl::GetManagerDisplayName(
234 const std::string
& user_id
) const {
235 PrefService
* local_state
= g_browser_process
->local_state();
236 const base::DictionaryValue
* manager_names
=
237 local_state
->GetDictionary(kSupervisedUserManagerNames
);
238 base::string16 result
;
239 if (manager_names
->GetStringWithoutPathExpansion(user_id
, &result
) &&
242 return base::UTF8ToUTF16(GetManagerDisplayEmail(user_id
));
245 std::string
SupervisedUserManagerImpl::GetManagerUserId(
246 const std::string
& user_id
) const {
248 GetUserStringValue(user_id
, kSupervisedUserManagers
, &result
);
252 std::string
SupervisedUserManagerImpl::GetManagerDisplayEmail(
253 const std::string
& user_id
) const {
255 if (GetUserStringValue(user_id
,
256 kSupervisedUserManagerDisplayEmails
,
260 return GetManagerUserId(user_id
);
263 void SupervisedUserManagerImpl::GetPasswordInformation(
264 const std::string
& user_id
,
265 base::DictionaryValue
* result
) {
267 if (GetUserIntegerValue(user_id
, kSupervisedUserPasswordSchema
, &value
))
268 result
->SetIntegerWithoutPathExpansion(kSchemaVersion
, value
);
269 if (GetUserIntegerValue(user_id
, kSupervisedUserPasswordRevision
, &value
))
270 result
->SetIntegerWithoutPathExpansion(kPasswordRevision
, value
);
273 if (GetUserBooleanValue(user_id
, kSupervisedUserNeedPasswordUpdate
, &flag
))
274 result
->SetBooleanWithoutPathExpansion(kRequirePasswordUpdate
, flag
);
275 if (GetUserBooleanValue(user_id
, kSupervisedUserIncompleteKey
, &flag
))
276 result
->SetBooleanWithoutPathExpansion(kHasIncompleteKey
, flag
);
279 if (GetUserStringValue(user_id
, kSupervisedUserPasswordSalt
, &salt
))
280 result
->SetStringWithoutPathExpansion(kSalt
, salt
);
283 void SupervisedUserManagerImpl::SetPasswordInformation(
284 const std::string
& user_id
,
285 const base::DictionaryValue
* password_info
) {
287 if (password_info
->GetIntegerWithoutPathExpansion(kSchemaVersion
, &value
))
288 SetUserIntegerValue(user_id
, kSupervisedUserPasswordSchema
, value
);
289 if (password_info
->GetIntegerWithoutPathExpansion(kPasswordRevision
, &value
))
290 SetUserIntegerValue(user_id
, kSupervisedUserPasswordRevision
, value
);
293 if (password_info
->GetBooleanWithoutPathExpansion(kRequirePasswordUpdate
,
295 SetUserBooleanValue(user_id
, kSupervisedUserNeedPasswordUpdate
, flag
);
297 if (password_info
->GetBooleanWithoutPathExpansion(kHasIncompleteKey
, &flag
))
298 SetUserBooleanValue(user_id
, kSupervisedUserIncompleteKey
, flag
);
301 if (password_info
->GetStringWithoutPathExpansion(kSalt
, &salt
))
302 SetUserStringValue(user_id
, kSupervisedUserPasswordSalt
, salt
);
303 g_browser_process
->local_state()->CommitPendingWrite();
306 bool SupervisedUserManagerImpl::GetUserStringValue(
307 const std::string
& user_id
,
309 std::string
* out_value
) const {
310 PrefService
* local_state
= g_browser_process
->local_state();
311 const base::DictionaryValue
* dictionary
= local_state
->GetDictionary(key
);
312 return dictionary
->GetStringWithoutPathExpansion(user_id
, out_value
);
315 bool SupervisedUserManagerImpl::GetUserIntegerValue(
316 const std::string
& user_id
,
318 int* out_value
) const {
319 PrefService
* local_state
= g_browser_process
->local_state();
320 const base::DictionaryValue
* dictionary
= local_state
->GetDictionary(key
);
321 return dictionary
->GetIntegerWithoutPathExpansion(user_id
, out_value
);
324 bool SupervisedUserManagerImpl::GetUserBooleanValue(const std::string
& user_id
,
326 bool* out_value
) const {
327 PrefService
* local_state
= g_browser_process
->local_state();
328 const base::DictionaryValue
* dictionary
= local_state
->GetDictionary(key
);
329 return dictionary
->GetBooleanWithoutPathExpansion(user_id
, out_value
);
332 void SupervisedUserManagerImpl::SetUserStringValue(
333 const std::string
& user_id
,
335 const std::string
& value
) {
336 PrefService
* local_state
= g_browser_process
->local_state();
337 DictionaryPrefUpdate
update(local_state
, key
);
338 update
->SetStringWithoutPathExpansion(user_id
, value
);
341 void SupervisedUserManagerImpl::SetUserIntegerValue(
342 const std::string
& user_id
,
345 PrefService
* local_state
= g_browser_process
->local_state();
346 DictionaryPrefUpdate
update(local_state
, key
);
347 update
->SetIntegerWithoutPathExpansion(user_id
, value
);
350 void SupervisedUserManagerImpl::SetUserBooleanValue(const std::string
& user_id
,
353 PrefService
* local_state
= g_browser_process
->local_state();
354 DictionaryPrefUpdate
update(local_state
, key
);
355 update
->SetBooleanWithoutPathExpansion(user_id
, value
);
358 const user_manager::User
* SupervisedUserManagerImpl::FindByDisplayName(
359 const base::string16
& display_name
) const {
360 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
361 const user_manager::UserList
& users
= owner_
->GetUsers();
362 for (user_manager::UserList::const_iterator it
= users
.begin();
365 if (((*it
)->GetType() == user_manager::USER_TYPE_SUPERVISED
) &&
366 ((*it
)->display_name() == display_name
)) {
373 const user_manager::User
* SupervisedUserManagerImpl::FindBySyncId(
374 const std::string
& sync_id
) const {
375 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
376 const user_manager::UserList
& users
= owner_
->GetUsers();
377 for (user_manager::UserList::const_iterator it
= users
.begin();
380 if (((*it
)->GetType() == user_manager::USER_TYPE_SUPERVISED
) &&
381 (GetUserSyncId((*it
)->email()) == sync_id
)) {
388 void SupervisedUserManagerImpl::StartCreationTransaction(
389 const base::string16
& display_name
) {
390 g_browser_process
->local_state()->
391 SetString(kSupervisedUserCreationTransactionDisplayName
,
392 base::UTF16ToASCII(display_name
));
393 g_browser_process
->local_state()->CommitPendingWrite();
396 void SupervisedUserManagerImpl::SetCreationTransactionUserId(
397 const std::string
& email
) {
398 g_browser_process
->local_state()->
399 SetString(kSupervisedUserCreationTransactionUserId
,
401 g_browser_process
->local_state()->CommitPendingWrite();
404 void SupervisedUserManagerImpl::CommitCreationTransaction() {
405 g_browser_process
->local_state()->
406 ClearPref(kSupervisedUserCreationTransactionDisplayName
);
407 g_browser_process
->local_state()->
408 ClearPref(kSupervisedUserCreationTransactionUserId
);
409 g_browser_process
->local_state()->CommitPendingWrite();
412 bool SupervisedUserManagerImpl::HasFailedUserCreationTransaction() {
413 return !(g_browser_process
->local_state()->
414 GetString(kSupervisedUserCreationTransactionDisplayName
).
418 void SupervisedUserManagerImpl::RollbackUserCreationTransaction() {
419 PrefService
* prefs
= g_browser_process
->local_state();
421 std::string display_name
= prefs
->
422 GetString(kSupervisedUserCreationTransactionDisplayName
);
423 std::string user_id
= prefs
->
424 GetString(kSupervisedUserCreationTransactionUserId
);
426 LOG(WARNING
) << "Cleaning up transaction for "
427 << display_name
<< "/" << user_id
;
429 if (user_id
.empty()) {
430 // Not much to do - just remove transaction.
431 prefs
->ClearPref(kSupervisedUserCreationTransactionDisplayName
);
432 prefs
->CommitPendingWrite();
436 if (gaia::ExtractDomainName(user_id
) !=
437 chromeos::login::kSupervisedUserDomain
) {
438 LOG(WARNING
) << "Clean up transaction for non-supervised user found :"
439 << user_id
<< ", will not remove data";
440 prefs
->ClearPref(kSupervisedUserCreationTransactionDisplayName
);
441 prefs
->ClearPref(kSupervisedUserCreationTransactionUserId
);
442 prefs
->CommitPendingWrite();
445 owner_
->RemoveNonOwnerUserInternal(user_id
, NULL
);
447 prefs
->ClearPref(kSupervisedUserCreationTransactionDisplayName
);
448 prefs
->ClearPref(kSupervisedUserCreationTransactionUserId
);
449 prefs
->CommitPendingWrite();
452 void SupervisedUserManagerImpl::RemoveNonCryptohomeData(
453 const std::string
& user_id
) {
454 PrefService
* prefs
= g_browser_process
->local_state();
455 ListPrefUpdate
prefs_new_users_update(prefs
, kSupervisedUsersFirstRun
);
456 prefs_new_users_update
->Remove(base::StringValue(user_id
), NULL
);
458 CleanPref(user_id
, kSupervisedUserSyncId
);
459 CleanPref(user_id
, kSupervisedUserManagers
);
460 CleanPref(user_id
, kSupervisedUserManagerNames
);
461 CleanPref(user_id
, kSupervisedUserManagerDisplayEmails
);
462 CleanPref(user_id
, kSupervisedUserPasswordSalt
);
463 CleanPref(user_id
, kSupervisedUserPasswordSchema
);
464 CleanPref(user_id
, kSupervisedUserPasswordRevision
);
465 CleanPref(user_id
, kSupervisedUserNeedPasswordUpdate
);
466 CleanPref(user_id
, kSupervisedUserIncompleteKey
);
469 void SupervisedUserManagerImpl::CleanPref(const std::string
& user_id
,
471 PrefService
* prefs
= g_browser_process
->local_state();
472 DictionaryPrefUpdate
dict_update(prefs
, key
);
473 dict_update
->RemoveWithoutPathExpansion(user_id
, NULL
);
476 bool SupervisedUserManagerImpl::CheckForFirstRun(const std::string
& user_id
) {
477 ListPrefUpdate
prefs_new_users_update(g_browser_process
->local_state(),
478 kSupervisedUsersFirstRun
);
479 return prefs_new_users_update
->Remove(base::StringValue(user_id
), NULL
);
482 void SupervisedUserManagerImpl::UpdateManagerName(const std::string
& manager_id
,
483 const base::string16
& new_display_name
) {
484 PrefService
* local_state
= g_browser_process
->local_state();
486 const base::DictionaryValue
* manager_ids
=
487 local_state
->GetDictionary(kSupervisedUserManagers
);
489 DictionaryPrefUpdate
manager_name_update(local_state
,
490 kSupervisedUserManagerNames
);
491 for (base::DictionaryValue::Iterator
it(*manager_ids
); !it
.IsAtEnd();
494 bool has_manager_id
= it
.value().GetAsString(&user_id
);
495 DCHECK(has_manager_id
);
496 if (user_id
== manager_id
) {
497 manager_name_update
->SetWithoutPathExpansion(
499 new base::StringValue(new_display_name
));
504 SupervisedUserAuthentication
* SupervisedUserManagerImpl::GetAuthentication() {
505 return authentication_
.get();
508 void SupervisedUserManagerImpl::LoadSupervisedUserToken(
510 const LoadTokenCallback
& callback
) {
511 // TODO(antrim): use profile->GetPath() once we sure it is safe.
512 base::FilePath profile_dir
= ProfileHelper::GetProfilePathByUserIdHash(
513 ProfileHelper::Get()->GetUserByProfile(profile
)->username_hash());
514 PostTaskAndReplyWithResult(
515 content::BrowserThread::GetBlockingPool()
516 ->GetTaskRunnerWithShutdownBehavior(
517 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN
)
519 FROM_HERE
, base::Bind(&LoadSyncToken
, profile_dir
), callback
);
522 void SupervisedUserManagerImpl::ConfigureSyncWithToken(
524 const std::string
& token
) {
526 SupervisedUserServiceFactory::GetForProfile(profile
)->InitSync(token
);
529 } // namespace chromeos