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/prefs/pref_registry_simple.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
16 #include "chrome/browser/chromeos/login/user_manager_impl.h"
17 #include "chromeos/settings/cros_settings_names.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "google_apis/gaia/gaia_auth_util.h"
21 using content::BrowserThread
;
25 // Names for pref keys in Local State.
26 // A map from locally managed user local user id to sync user id.
27 const char kManagedUserSyncId
[] =
30 // A map from locally managed user id to manager user id.
31 const char kManagedUserManagers
[] =
32 "ManagedUserManagers";
34 // A map from locally managed user id to manager display name.
35 const char kManagedUserManagerNames
[] =
36 "ManagedUserManagerNames";
38 // A map from locally managed user id to manager display e-mail.
39 const char kManagedUserManagerDisplayEmails
[] =
40 "ManagedUserManagerDisplayEmails";
42 // A vector pref of the locally managed accounts defined on this device, that
43 // had not logged in yet.
44 const char kLocallyManagedUsersFirstRun
[] = "LocallyManagedUsersFirstRun";
46 // A pref of the next id for locally managed users generation.
47 const char kLocallyManagedUsersNextId
[] =
48 "LocallyManagedUsersNextId";
50 // A pref of the next id for locally managed users generation.
51 const char kLocallyManagedUserCreationTransactionDisplayName
[] =
52 "LocallyManagedUserCreationTransactionDisplayName";
54 // A pref of the next id for locally managed users generation.
55 const char kLocallyManagedUserCreationTransactionUserId
[] =
56 "LocallyManagedUserCreationTransactionUserId";
58 // A map from user id to password schema id.
59 const char kSupervisedUserPasswordSchema
[] =
60 "SupervisedUserPasswordSchema";
62 // A map from user id to password salt.
63 const char kSupervisedUserPasswordSalt
[] =
64 "SupervisedUserPasswordSalt";
66 // A map from user id to password revision.
67 const char kSupervisedUserPasswordRevision
[] =
68 "SupervisedUserPasswordRevision";
74 const char kSchemaVersion
[] = "SchemaVersion";
75 const char kPasswordRevision
[] = "PasswordRevision";
76 const char kSalt
[] = "PasswordSalt";
77 const char kEncryptedPassword
[] = "EncryptedPassword";
78 const int kMinPasswordRevision
= 1;
81 void SupervisedUserManager::RegisterPrefs(PrefRegistrySimple
* registry
) {
82 registry
->RegisterListPref(kLocallyManagedUsersFirstRun
);
83 registry
->RegisterIntegerPref(kLocallyManagedUsersNextId
, 0);
84 registry
->RegisterStringPref(
85 kLocallyManagedUserCreationTransactionDisplayName
, "");
86 registry
->RegisterStringPref(
87 kLocallyManagedUserCreationTransactionUserId
, "");
88 registry
->RegisterDictionaryPref(kManagedUserSyncId
);
89 registry
->RegisterDictionaryPref(kManagedUserManagers
);
90 registry
->RegisterDictionaryPref(kManagedUserManagerNames
);
91 registry
->RegisterDictionaryPref(kManagedUserManagerDisplayEmails
);
93 registry
->RegisterDictionaryPref(kSupervisedUserPasswordSchema
);
94 registry
->RegisterDictionaryPref(kSupervisedUserPasswordSalt
);
95 registry
->RegisterDictionaryPref(kSupervisedUserPasswordRevision
);
98 SupervisedUserManagerImpl::SupervisedUserManagerImpl(UserManagerImpl
* owner
)
100 cros_settings_(CrosSettings::Get()) {
101 // SupervisedUserManager instance should be used only on UI thread.
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
103 authentication_
.reset(new SupervisedUserAuthentication(this));
106 SupervisedUserManagerImpl::~SupervisedUserManagerImpl() {
109 std::string
SupervisedUserManagerImpl::GenerateUserId() {
110 int counter
= g_browser_process
->local_state()->
111 GetInteger(kLocallyManagedUsersNextId
);
115 id
= base::StringPrintf("%d@%s", counter
,
116 UserManager::kLocallyManagedUserDomain
);
118 user_exists
= (NULL
!= owner_
->FindUser(id
));
119 DCHECK(!user_exists
);
121 LOG(ERROR
) << "Supervised user with id " << id
<< " already exists.";
123 } while (user_exists
);
125 g_browser_process
->local_state()->
126 SetInteger(kLocallyManagedUsersNextId
, counter
);
128 g_browser_process
->local_state()->CommitPendingWrite();
132 const User
* SupervisedUserManagerImpl::CreateUserRecord(
133 const std::string
& manager_id
,
134 const std::string
& local_user_id
,
135 const std::string
& sync_user_id
,
136 const base::string16
& display_name
) {
137 const User
* user
= FindByDisplayName(display_name
);
141 const User
* manager
= owner_
->FindUser(manager_id
);
144 PrefService
* local_state
= g_browser_process
->local_state();
146 User
* new_user
= User::CreateLocallyManagedUser(local_user_id
);
148 owner_
->AddUserRecord(new_user
);
150 ListPrefUpdate
prefs_new_users_update(local_state
,
151 kLocallyManagedUsersFirstRun
);
152 DictionaryPrefUpdate
sync_id_update(local_state
, kManagedUserSyncId
);
153 DictionaryPrefUpdate
manager_update(local_state
, kManagedUserManagers
);
154 DictionaryPrefUpdate
manager_name_update(local_state
,
155 kManagedUserManagerNames
);
156 DictionaryPrefUpdate
manager_email_update(local_state
,
157 kManagedUserManagerDisplayEmails
);
159 prefs_new_users_update
->Insert(0, new base::StringValue(local_user_id
));
161 sync_id_update
->SetWithoutPathExpansion(local_user_id
,
162 new base::StringValue(sync_user_id
));
163 manager_update
->SetWithoutPathExpansion(local_user_id
,
164 new base::StringValue(manager
->email()));
165 manager_name_update
->SetWithoutPathExpansion(local_user_id
,
166 new base::StringValue(manager
->GetDisplayName()));
167 manager_email_update
->SetWithoutPathExpansion(local_user_id
,
168 new base::StringValue(manager
->display_email()));
170 owner_
->SaveUserDisplayName(local_user_id
, display_name
);
172 g_browser_process
->local_state()->CommitPendingWrite();
176 std::string
SupervisedUserManagerImpl::GetUserSyncId(const std::string
& user_id
)
179 GetUserStringValue(user_id
, kManagedUserSyncId
, &result
);
183 base::string16
SupervisedUserManagerImpl::GetManagerDisplayName(
184 const std::string
& user_id
) const {
185 PrefService
* local_state
= g_browser_process
->local_state();
186 const base::DictionaryValue
* manager_names
=
187 local_state
->GetDictionary(kManagedUserManagerNames
);
188 base::string16 result
;
189 if (manager_names
->GetStringWithoutPathExpansion(user_id
, &result
) &&
192 return base::UTF8ToUTF16(GetManagerDisplayEmail(user_id
));
195 std::string
SupervisedUserManagerImpl::GetManagerUserId(
196 const std::string
& user_id
) const {
198 GetUserStringValue(user_id
, kManagedUserManagers
, &result
);
202 std::string
SupervisedUserManagerImpl::GetManagerDisplayEmail(
203 const std::string
& user_id
) const {
205 if (GetUserStringValue(user_id
, kManagedUserManagerDisplayEmails
, &result
) &&
208 return GetManagerUserId(user_id
);
211 void SupervisedUserManagerImpl::GetPasswordInformation(
212 const std::string
& user_id
,
213 base::DictionaryValue
* result
) {
215 if (GetUserIntegerValue(user_id
, kSupervisedUserPasswordSchema
, &value
))
216 result
->SetIntegerWithoutPathExpansion(kSchemaVersion
, value
);
217 if (GetUserIntegerValue(user_id
, kSupervisedUserPasswordRevision
, &value
))
218 result
->SetIntegerWithoutPathExpansion(kPasswordRevision
, value
);
221 if (GetUserStringValue(user_id
, kSupervisedUserPasswordSalt
, &salt
))
222 result
->SetStringWithoutPathExpansion(kSalt
, salt
);
225 void SupervisedUserManagerImpl::SetPasswordInformation(
226 const std::string
& user_id
,
227 const base::DictionaryValue
* password_info
) {
229 if (password_info
->GetIntegerWithoutPathExpansion(kSchemaVersion
, &value
))
230 SetUserIntegerValue(user_id
, kSupervisedUserPasswordSchema
, value
);
231 if (password_info
->GetIntegerWithoutPathExpansion(kPasswordRevision
, &value
))
232 SetUserIntegerValue(user_id
, kSupervisedUserPasswordRevision
, value
);
235 if (password_info
->GetStringWithoutPathExpansion(kSalt
, &salt
))
236 SetUserStringValue(user_id
, kSupervisedUserPasswordSalt
, salt
);
237 g_browser_process
->local_state()->CommitPendingWrite();
240 bool SupervisedUserManagerImpl::GetUserStringValue(
241 const std::string
& user_id
,
243 std::string
* out_value
) const {
244 PrefService
* local_state
= g_browser_process
->local_state();
245 const base::DictionaryValue
* dictionary
= local_state
->GetDictionary(key
);
246 return dictionary
->GetStringWithoutPathExpansion(user_id
, out_value
);
249 bool SupervisedUserManagerImpl::GetUserIntegerValue(
250 const std::string
& user_id
,
252 int* out_value
) const {
253 PrefService
* local_state
= g_browser_process
->local_state();
254 const base::DictionaryValue
* dictionary
= local_state
->GetDictionary(key
);
255 return dictionary
->GetIntegerWithoutPathExpansion(user_id
, out_value
);
258 void SupervisedUserManagerImpl::SetUserStringValue(
259 const std::string
& user_id
,
261 const std::string
& value
) {
262 PrefService
* local_state
= g_browser_process
->local_state();
263 DictionaryPrefUpdate
update(local_state
, key
);
264 update
->SetStringWithoutPathExpansion(user_id
, value
);
267 void SupervisedUserManagerImpl::SetUserIntegerValue(
268 const std::string
& user_id
,
271 PrefService
* local_state
= g_browser_process
->local_state();
272 DictionaryPrefUpdate
update(local_state
, key
);
273 update
->SetIntegerWithoutPathExpansion(user_id
, value
);
276 const User
* SupervisedUserManagerImpl::FindByDisplayName(
277 const base::string16
& display_name
) const {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
279 const UserList
& users
= owner_
->GetUsers();
280 for (UserList::const_iterator it
= users
.begin(); it
!= users
.end(); ++it
) {
281 if (((*it
)->GetType() == User::USER_TYPE_LOCALLY_MANAGED
) &&
282 ((*it
)->display_name() == display_name
)) {
289 const User
* SupervisedUserManagerImpl::FindBySyncId(
290 const std::string
& sync_id
) const {
291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
292 const UserList
& users
= owner_
->GetUsers();
293 for (UserList::const_iterator it
= users
.begin(); it
!= users
.end(); ++it
) {
294 if (((*it
)->GetType() == User::USER_TYPE_LOCALLY_MANAGED
) &&
295 (GetUserSyncId((*it
)->email()) == sync_id
)) {
302 void SupervisedUserManagerImpl::StartCreationTransaction(
303 const base::string16
& display_name
) {
304 g_browser_process
->local_state()->
305 SetString(kLocallyManagedUserCreationTransactionDisplayName
,
306 UTF16ToASCII(display_name
));
307 g_browser_process
->local_state()->CommitPendingWrite();
310 void SupervisedUserManagerImpl::SetCreationTransactionUserId(
311 const std::string
& email
) {
312 g_browser_process
->local_state()->
313 SetString(kLocallyManagedUserCreationTransactionUserId
,
315 g_browser_process
->local_state()->CommitPendingWrite();
318 void SupervisedUserManagerImpl::CommitCreationTransaction() {
319 g_browser_process
->local_state()->
320 ClearPref(kLocallyManagedUserCreationTransactionDisplayName
);
321 g_browser_process
->local_state()->
322 ClearPref(kLocallyManagedUserCreationTransactionUserId
);
323 g_browser_process
->local_state()->CommitPendingWrite();
326 bool SupervisedUserManagerImpl::HasFailedUserCreationTransaction() {
327 return !(g_browser_process
->local_state()->
328 GetString(kLocallyManagedUserCreationTransactionDisplayName
).
332 void SupervisedUserManagerImpl::RollbackUserCreationTransaction() {
333 PrefService
* prefs
= g_browser_process
->local_state();
335 std::string display_name
= prefs
->
336 GetString(kLocallyManagedUserCreationTransactionDisplayName
);
337 std::string user_id
= prefs
->
338 GetString(kLocallyManagedUserCreationTransactionUserId
);
340 LOG(WARNING
) << "Cleaning up transaction for "
341 << display_name
<< "/" << user_id
;
343 if (user_id
.empty()) {
344 // Not much to do - just remove transaction.
345 prefs
->ClearPref(kLocallyManagedUserCreationTransactionDisplayName
);
346 prefs
->CommitPendingWrite();
350 if (gaia::ExtractDomainName(user_id
) !=
351 UserManager::kLocallyManagedUserDomain
) {
352 LOG(WARNING
) << "Clean up transaction for non-locally managed user found :"
353 << user_id
<< ", will not remove data";
354 prefs
->ClearPref(kLocallyManagedUserCreationTransactionDisplayName
);
355 prefs
->ClearPref(kLocallyManagedUserCreationTransactionUserId
);
356 prefs
->CommitPendingWrite();
359 owner_
->RemoveNonOwnerUserInternal(user_id
, NULL
);
361 prefs
->ClearPref(kLocallyManagedUserCreationTransactionDisplayName
);
362 prefs
->ClearPref(kLocallyManagedUserCreationTransactionUserId
);
363 prefs
->CommitPendingWrite();
366 void SupervisedUserManagerImpl::RemoveNonCryptohomeData(
367 const std::string
& user_id
) {
368 PrefService
* prefs
= g_browser_process
->local_state();
369 ListPrefUpdate
prefs_new_users_update(prefs
, kLocallyManagedUsersFirstRun
);
370 prefs_new_users_update
->Remove(base::StringValue(user_id
), NULL
);
372 CleanPref(user_id
, kManagedUserSyncId
);
373 CleanPref(user_id
, kManagedUserManagers
);
374 CleanPref(user_id
, kManagedUserManagerNames
);
375 CleanPref(user_id
, kManagedUserManagerDisplayEmails
);
376 CleanPref(user_id
, kSupervisedUserPasswordSalt
);
377 CleanPref(user_id
, kSupervisedUserPasswordSchema
);
378 CleanPref(user_id
, kSupervisedUserPasswordRevision
);
381 void SupervisedUserManagerImpl::CleanPref(const std::string
& user_id
,
383 PrefService
* prefs
= g_browser_process
->local_state();
384 DictionaryPrefUpdate
dict_update(prefs
, key
);
385 dict_update
->RemoveWithoutPathExpansion(user_id
, NULL
);
388 bool SupervisedUserManagerImpl::CheckForFirstRun(const std::string
& user_id
) {
389 ListPrefUpdate
prefs_new_users_update(g_browser_process
->local_state(),
390 kLocallyManagedUsersFirstRun
);
391 return prefs_new_users_update
->Remove(base::StringValue(user_id
), NULL
);
394 void SupervisedUserManagerImpl::UpdateManagerName(const std::string
& manager_id
,
395 const base::string16
& new_display_name
) {
396 PrefService
* local_state
= g_browser_process
->local_state();
398 const base::DictionaryValue
* manager_ids
=
399 local_state
->GetDictionary(kManagedUserManagers
);
401 DictionaryPrefUpdate
manager_name_update(local_state
,
402 kManagedUserManagerNames
);
403 for (base::DictionaryValue::Iterator
it(*manager_ids
); !it
.IsAtEnd();
406 bool has_manager_id
= it
.value().GetAsString(&user_id
);
407 DCHECK(has_manager_id
);
408 if (user_id
== manager_id
) {
409 manager_name_update
->SetWithoutPathExpansion(
411 new base::StringValue(new_display_name
));
416 SupervisedUserAuthentication
* SupervisedUserManagerImpl::GetAuthentication() {
417 return authentication_
.get();
420 } // namespace chromeos