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 std::string LoadSyncToken(base::FilePath profile_dir) {
79 base::FilePath token_file =
80 profile_dir.Append(chromeos::kManagedUserTokenFilename);
81 VLOG(1) << "Loading" << token_file.value();
82 if (!base::ReadFileToString(token_file, &token))
91 const char kSchemaVersion[] = "SchemaVersion";
92 const char kPasswordRevision[] = "PasswordRevision";
93 const char kSalt[] = "PasswordSalt";
94 const char kEncryptedPassword[] = "EncryptedPassword";
95 const char kRequirePasswordUpdate[] = "RequirePasswordUpdate";
96 const char kPasswordUpdateFile[] = "password.update";
97 const int kMinPasswordRevision = 1;
100 void SupervisedUserManager::RegisterPrefs(PrefRegistrySimple* registry) {
101 registry->RegisterListPref(kLocallyManagedUsersFirstRun);
102 registry->RegisterIntegerPref(kLocallyManagedUsersNextId, 0);
103 registry->RegisterStringPref(
104 kLocallyManagedUserCreationTransactionDisplayName, "");
105 registry->RegisterStringPref(
106 kLocallyManagedUserCreationTransactionUserId, "");
107 registry->RegisterDictionaryPref(kManagedUserSyncId);
108 registry->RegisterDictionaryPref(kManagedUserManagers);
109 registry->RegisterDictionaryPref(kManagedUserManagerNames);
110 registry->RegisterDictionaryPref(kManagedUserManagerDisplayEmails);
112 registry->RegisterDictionaryPref(kSupervisedUserPasswordSchema);
113 registry->RegisterDictionaryPref(kSupervisedUserPasswordSalt);
114 registry->RegisterDictionaryPref(kSupervisedUserPasswordRevision);
117 SupervisedUserManagerImpl::SupervisedUserManagerImpl(UserManagerImpl* owner)
119 cros_settings_(CrosSettings::Get()) {
120 // SupervisedUserManager instance should be used only on UI thread.
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
122 authentication_.reset(new SupervisedUserAuthentication(this));
125 SupervisedUserManagerImpl::~SupervisedUserManagerImpl() {
128 std::string SupervisedUserManagerImpl::GenerateUserId() {
129 int counter = g_browser_process->local_state()->
130 GetInteger(kLocallyManagedUsersNextId);
134 id = base::StringPrintf("%d@%s", counter,
135 UserManager::kLocallyManagedUserDomain);
137 user_exists = (NULL != owner_->FindUser(id));
138 DCHECK(!user_exists);
140 LOG(ERROR) << "Supervised user with id " << id << " already exists.";
142 } while (user_exists);
144 g_browser_process->local_state()->
145 SetInteger(kLocallyManagedUsersNextId, counter);
147 g_browser_process->local_state()->CommitPendingWrite();
151 bool SupervisedUserManagerImpl::HasSupervisedUsers(
152 const std::string& manager_id) const {
153 const UserList& users = owner_->GetUsers();
154 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
155 if ((*it)->GetType() == User::USER_TYPE_LOCALLY_MANAGED) {
156 if (manager_id == GetManagerUserId((*it)->email()))
163 const User* SupervisedUserManagerImpl::CreateUserRecord(
164 const std::string& manager_id,
165 const std::string& local_user_id,
166 const std::string& sync_user_id,
167 const base::string16& display_name) {
168 const User* user = FindByDisplayName(display_name);
172 const User* manager = owner_->FindUser(manager_id);
175 PrefService* local_state = g_browser_process->local_state();
177 User* new_user = User::CreateLocallyManagedUser(local_user_id);
179 owner_->AddUserRecord(new_user);
181 ListPrefUpdate prefs_new_users_update(local_state,
182 kLocallyManagedUsersFirstRun);
183 DictionaryPrefUpdate sync_id_update(local_state, kManagedUserSyncId);
184 DictionaryPrefUpdate manager_update(local_state, kManagedUserManagers);
185 DictionaryPrefUpdate manager_name_update(local_state,
186 kManagedUserManagerNames);
187 DictionaryPrefUpdate manager_email_update(local_state,
188 kManagedUserManagerDisplayEmails);
190 prefs_new_users_update->Insert(0, new base::StringValue(local_user_id));
192 sync_id_update->SetWithoutPathExpansion(local_user_id,
193 new base::StringValue(sync_user_id));
194 manager_update->SetWithoutPathExpansion(local_user_id,
195 new base::StringValue(manager->email()));
196 manager_name_update->SetWithoutPathExpansion(local_user_id,
197 new base::StringValue(manager->GetDisplayName()));
198 manager_email_update->SetWithoutPathExpansion(local_user_id,
199 new base::StringValue(manager->display_email()));
201 owner_->SaveUserDisplayName(local_user_id, display_name);
203 g_browser_process->local_state()->CommitPendingWrite();
207 std::string SupervisedUserManagerImpl::GetUserSyncId(const std::string& user_id)
210 GetUserStringValue(user_id, kManagedUserSyncId, &result);
214 base::string16 SupervisedUserManagerImpl::GetManagerDisplayName(
215 const std::string& user_id) const {
216 PrefService* local_state = g_browser_process->local_state();
217 const base::DictionaryValue* manager_names =
218 local_state->GetDictionary(kManagedUserManagerNames);
219 base::string16 result;
220 if (manager_names->GetStringWithoutPathExpansion(user_id, &result) &&
223 return base::UTF8ToUTF16(GetManagerDisplayEmail(user_id));
226 std::string SupervisedUserManagerImpl::GetManagerUserId(
227 const std::string& user_id) const {
229 GetUserStringValue(user_id, kManagedUserManagers, &result);
233 std::string SupervisedUserManagerImpl::GetManagerDisplayEmail(
234 const std::string& user_id) const {
236 if (GetUserStringValue(user_id, kManagedUserManagerDisplayEmails, &result) &&
239 return GetManagerUserId(user_id);
242 void SupervisedUserManagerImpl::GetPasswordInformation(
243 const std::string& user_id,
244 base::DictionaryValue* result) {
246 if (GetUserIntegerValue(user_id, kSupervisedUserPasswordSchema, &value))
247 result->SetIntegerWithoutPathExpansion(kSchemaVersion, value);
248 if (GetUserIntegerValue(user_id, kSupervisedUserPasswordRevision, &value))
249 result->SetIntegerWithoutPathExpansion(kPasswordRevision, value);
252 if (GetUserStringValue(user_id, kSupervisedUserPasswordSalt, &salt))
253 result->SetStringWithoutPathExpansion(kSalt, salt);
256 void SupervisedUserManagerImpl::SetPasswordInformation(
257 const std::string& user_id,
258 const base::DictionaryValue* password_info) {
260 if (password_info->GetIntegerWithoutPathExpansion(kSchemaVersion, &value))
261 SetUserIntegerValue(user_id, kSupervisedUserPasswordSchema, value);
262 if (password_info->GetIntegerWithoutPathExpansion(kPasswordRevision, &value))
263 SetUserIntegerValue(user_id, kSupervisedUserPasswordRevision, value);
266 if (password_info->GetStringWithoutPathExpansion(kSalt, &salt))
267 SetUserStringValue(user_id, kSupervisedUserPasswordSalt, salt);
268 g_browser_process->local_state()->CommitPendingWrite();
271 bool SupervisedUserManagerImpl::GetUserStringValue(
272 const std::string& user_id,
274 std::string* out_value) const {
275 PrefService* local_state = g_browser_process->local_state();
276 const base::DictionaryValue* dictionary = local_state->GetDictionary(key);
277 return dictionary->GetStringWithoutPathExpansion(user_id, out_value);
280 bool SupervisedUserManagerImpl::GetUserIntegerValue(
281 const std::string& user_id,
283 int* out_value) const {
284 PrefService* local_state = g_browser_process->local_state();
285 const base::DictionaryValue* dictionary = local_state->GetDictionary(key);
286 return dictionary->GetIntegerWithoutPathExpansion(user_id, out_value);
289 void SupervisedUserManagerImpl::SetUserStringValue(
290 const std::string& user_id,
292 const std::string& value) {
293 PrefService* local_state = g_browser_process->local_state();
294 DictionaryPrefUpdate update(local_state, key);
295 update->SetStringWithoutPathExpansion(user_id, value);
298 void SupervisedUserManagerImpl::SetUserIntegerValue(
299 const std::string& user_id,
302 PrefService* local_state = g_browser_process->local_state();
303 DictionaryPrefUpdate update(local_state, key);
304 update->SetIntegerWithoutPathExpansion(user_id, value);
307 const User* SupervisedUserManagerImpl::FindByDisplayName(
308 const base::string16& display_name) const {
309 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
310 const UserList& users = owner_->GetUsers();
311 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
312 if (((*it)->GetType() == User::USER_TYPE_LOCALLY_MANAGED) &&
313 ((*it)->display_name() == display_name)) {
320 const User* SupervisedUserManagerImpl::FindBySyncId(
321 const std::string& sync_id) const {
322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
323 const UserList& users = owner_->GetUsers();
324 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) {
325 if (((*it)->GetType() == User::USER_TYPE_LOCALLY_MANAGED) &&
326 (GetUserSyncId((*it)->email()) == sync_id)) {
333 void SupervisedUserManagerImpl::StartCreationTransaction(
334 const base::string16& display_name) {
335 g_browser_process->local_state()->
336 SetString(kLocallyManagedUserCreationTransactionDisplayName,
337 UTF16ToASCII(display_name));
338 g_browser_process->local_state()->CommitPendingWrite();
341 void SupervisedUserManagerImpl::SetCreationTransactionUserId(
342 const std::string& email) {
343 g_browser_process->local_state()->
344 SetString(kLocallyManagedUserCreationTransactionUserId,
346 g_browser_process->local_state()->CommitPendingWrite();
349 void SupervisedUserManagerImpl::CommitCreationTransaction() {
350 g_browser_process->local_state()->
351 ClearPref(kLocallyManagedUserCreationTransactionDisplayName);
352 g_browser_process->local_state()->
353 ClearPref(kLocallyManagedUserCreationTransactionUserId);
354 g_browser_process->local_state()->CommitPendingWrite();
357 bool SupervisedUserManagerImpl::HasFailedUserCreationTransaction() {
358 return !(g_browser_process->local_state()->
359 GetString(kLocallyManagedUserCreationTransactionDisplayName).
363 void SupervisedUserManagerImpl::RollbackUserCreationTransaction() {
364 PrefService* prefs = g_browser_process->local_state();
366 std::string display_name = prefs->
367 GetString(kLocallyManagedUserCreationTransactionDisplayName);
368 std::string user_id = prefs->
369 GetString(kLocallyManagedUserCreationTransactionUserId);
371 LOG(WARNING) << "Cleaning up transaction for "
372 << display_name << "/" << user_id;
374 if (user_id.empty()) {
375 // Not much to do - just remove transaction.
376 prefs->ClearPref(kLocallyManagedUserCreationTransactionDisplayName);
377 prefs->CommitPendingWrite();
381 if (gaia::ExtractDomainName(user_id) !=
382 UserManager::kLocallyManagedUserDomain) {
383 LOG(WARNING) << "Clean up transaction for non-locally managed user found :"
384 << user_id << ", will not remove data";
385 prefs->ClearPref(kLocallyManagedUserCreationTransactionDisplayName);
386 prefs->ClearPref(kLocallyManagedUserCreationTransactionUserId);
387 prefs->CommitPendingWrite();
390 owner_->RemoveNonOwnerUserInternal(user_id, NULL);
392 prefs->ClearPref(kLocallyManagedUserCreationTransactionDisplayName);
393 prefs->ClearPref(kLocallyManagedUserCreationTransactionUserId);
394 prefs->CommitPendingWrite();
397 void SupervisedUserManagerImpl::RemoveNonCryptohomeData(
398 const std::string& user_id) {
399 PrefService* prefs = g_browser_process->local_state();
400 ListPrefUpdate prefs_new_users_update(prefs, kLocallyManagedUsersFirstRun);
401 prefs_new_users_update->Remove(base::StringValue(user_id), NULL);
403 CleanPref(user_id, kManagedUserSyncId);
404 CleanPref(user_id, kManagedUserManagers);
405 CleanPref(user_id, kManagedUserManagerNames);
406 CleanPref(user_id, kManagedUserManagerDisplayEmails);
407 CleanPref(user_id, kSupervisedUserPasswordSalt);
408 CleanPref(user_id, kSupervisedUserPasswordSchema);
409 CleanPref(user_id, kSupervisedUserPasswordRevision);
412 void SupervisedUserManagerImpl::CleanPref(const std::string& user_id,
414 PrefService* prefs = g_browser_process->local_state();
415 DictionaryPrefUpdate dict_update(prefs, key);
416 dict_update->RemoveWithoutPathExpansion(user_id, NULL);
419 bool SupervisedUserManagerImpl::CheckForFirstRun(const std::string& user_id) {
420 ListPrefUpdate prefs_new_users_update(g_browser_process->local_state(),
421 kLocallyManagedUsersFirstRun);
422 return prefs_new_users_update->Remove(base::StringValue(user_id), NULL);
425 void SupervisedUserManagerImpl::UpdateManagerName(const std::string& manager_id,
426 const base::string16& new_display_name) {
427 PrefService* local_state = g_browser_process->local_state();
429 const base::DictionaryValue* manager_ids =
430 local_state->GetDictionary(kManagedUserManagers);
432 DictionaryPrefUpdate manager_name_update(local_state,
433 kManagedUserManagerNames);
434 for (base::DictionaryValue::Iterator it(*manager_ids); !it.IsAtEnd();
437 bool has_manager_id = it.value().GetAsString(&user_id);
438 DCHECK(has_manager_id);
439 if (user_id == manager_id) {
440 manager_name_update->SetWithoutPathExpansion(
442 new base::StringValue(new_display_name));
447 SupervisedUserAuthentication* SupervisedUserManagerImpl::GetAuthentication() {
448 return authentication_.get();
451 void SupervisedUserManagerImpl::LoadSupervisedUserToken(
453 const LoadTokenCallback& callback) {
454 // TODO(antrim): use profile->GetPath() once we sure it is safe.
455 base::FilePath profile_dir = ProfileHelper::GetProfilePathByUserIdHash(
456 UserManager::Get()->GetUserByProfile(profile)->username_hash());
457 PostTaskAndReplyWithResult(
458 content::BrowserThread::GetBlockingPool(),
460 base::Bind(&LoadSyncToken, profile_dir),
464 void SupervisedUserManagerImpl::ConfigureSyncWithToken(
466 const std::string& token) {
468 ManagedUserServiceFactory::GetForProfile(profile)->InitSync(token);
471 } // namespace chromeos