Home | History | Annotate | Download | only in users
      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.
      4 
      5 #include "chrome/browser/chromeos/login/users/supervised_user_manager_impl.h"
      6 
      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"
     29 
     30 using content::BrowserThread;
     31 
     32 namespace {
     33 
     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";
     37 
     38 // A map from supervised user id to manager user id.
     39 const char kSupervisedUserManagers[] = "ManagedUserManagers";
     40 
     41 // A map from supervised user id to manager display name.
     42 const char kSupervisedUserManagerNames[] = "ManagedUserManagerNames";
     43 
     44 // A map from supervised user id to manager display e-mail.
     45 const char kSupervisedUserManagerDisplayEmails[] =
     46     "ManagedUserManagerDisplayEmails";
     47 
     48 // A vector pref of the supervised accounts defined on this device, that had
     49 // not logged in yet.
     50 const char kSupervisedUsersFirstRun[] = "LocallyManagedUsersFirstRun";
     51 
     52 // A pref of the next id for supervised users generation.
     53 const char kSupervisedUsersNextId[] = "LocallyManagedUsersNextId";
     54 
     55 // A pref of the next id for supervised users generation.
     56 const char kSupervisedUserCreationTransactionDisplayName[] =
     57     "LocallyManagedUserCreationTransactionDisplayName";
     58 
     59 // A pref of the next id for supervised users generation.
     60 const char kSupervisedUserCreationTransactionUserId[] =
     61     "LocallyManagedUserCreationTransactionUserId";
     62 
     63 // A map from user id to password schema id.
     64 const char kSupervisedUserPasswordSchema[] =
     65     "SupervisedUserPasswordSchema";
     66 
     67 // A map from user id to password salt.
     68 const char kSupervisedUserPasswordSalt[] =
     69     "SupervisedUserPasswordSalt";
     70 
     71 // A map from user id to password revision.
     72 const char kSupervisedUserPasswordRevision[] =
     73     "SupervisedUserPasswordRevision";
     74 
     75 // A map from user id to flag indicating if password should be updated upon
     76 // signin.
     77 const char kSupervisedUserNeedPasswordUpdate[] =
     78     "SupervisedUserNeedPasswordUpdate";
     79 
     80 // A map from user id to flag indicating if cryptohome does not have signature
     81 // key.
     82 const char kSupervisedUserIncompleteKey[] = "SupervisedUserHasIncompleteKey";
     83 
     84 std::string LoadSyncToken(base::FilePath profile_dir) {
     85   std::string token;
     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))
     90     return std::string();
     91   return token;
     92 }
     93 
     94 } // namespace
     95 
     96 namespace chromeos {
     97 
     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";
    107 
    108 const char kPasswordUpdateFile[] = "password.update";
    109 const int kMinPasswordRevision = 1;
    110 
    111 // static
    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);
    123 
    124   registry->RegisterDictionaryPref(kSupervisedUserPasswordSchema);
    125   registry->RegisterDictionaryPref(kSupervisedUserPasswordSalt);
    126   registry->RegisterDictionaryPref(kSupervisedUserPasswordRevision);
    127 
    128   registry->RegisterDictionaryPref(kSupervisedUserNeedPasswordUpdate);
    129   registry->RegisterDictionaryPref(kSupervisedUserIncompleteKey);
    130 }
    131 
    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(BrowserThread::CurrentlyOn(BrowserThread::UI));
    137   authentication_.reset(new SupervisedUserAuthentication(this));
    138 }
    139 
    140 SupervisedUserManagerImpl::~SupervisedUserManagerImpl() {
    141 }
    142 
    143 std::string SupervisedUserManagerImpl::GenerateUserId() {
    144   int counter = g_browser_process->local_state()->
    145       GetInteger(kSupervisedUsersNextId);
    146   std::string id;
    147   bool user_exists;
    148   do {
    149     id = base::StringPrintf(
    150         "%d@%s", counter, chromeos::login::kSupervisedUserDomain);
    151     counter++;
    152     user_exists = (NULL != owner_->FindUser(id));
    153     DCHECK(!user_exists);
    154     if (user_exists) {
    155       LOG(ERROR) << "Supervised user with id " << id << " already exists.";
    156     }
    157   } while (user_exists);
    158 
    159   g_browser_process->local_state()->
    160       SetInteger(kSupervisedUsersNextId, counter);
    161 
    162   g_browser_process->local_state()->CommitPendingWrite();
    163   return id;
    164 }
    165 
    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();
    170        it != users.end();
    171        ++it) {
    172     if ((*it)->GetType() == user_manager::USER_TYPE_SUPERVISED) {
    173       if (manager_id == GetManagerUserId((*it)->email()))
    174         return true;
    175     }
    176   }
    177   return false;
    178 }
    179 
    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);
    186   DCHECK(!user);
    187   if (user)
    188     return user;
    189   const user_manager::User* manager = owner_->FindUser(manager_id);
    190   CHECK(manager);
    191 
    192   PrefService* local_state = g_browser_process->local_state();
    193 
    194   user_manager::User* new_user =
    195       user_manager::User::CreateSupervisedUser(local_user_id);
    196 
    197   owner_->AddUserRecord(new_user);
    198 
    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(
    206       local_state,
    207       kSupervisedUserManagerDisplayEmails);
    208 
    209   prefs_new_users_update->Insert(0, new base::StringValue(local_user_id));
    210 
    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()));
    219 
    220   owner_->SaveUserDisplayName(local_user_id, display_name);
    221 
    222   g_browser_process->local_state()->CommitPendingWrite();
    223   return new_user;
    224 }
    225 
    226 std::string SupervisedUserManagerImpl::GetUserSyncId(const std::string& user_id)
    227     const {
    228   std::string result;
    229   GetUserStringValue(user_id, kSupervisedUserSyncId, &result);
    230   return result;
    231 }
    232 
    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) &&
    240       !result.empty())
    241     return result;
    242   return base::UTF8ToUTF16(GetManagerDisplayEmail(user_id));
    243 }
    244 
    245 std::string SupervisedUserManagerImpl::GetManagerUserId(
    246       const std::string& user_id) const {
    247   std::string result;
    248   GetUserStringValue(user_id, kSupervisedUserManagers, &result);
    249   return result;
    250 }
    251 
    252 std::string SupervisedUserManagerImpl::GetManagerDisplayEmail(
    253       const std::string& user_id) const {
    254   std::string result;
    255   if (GetUserStringValue(user_id,
    256                          kSupervisedUserManagerDisplayEmails,
    257                          &result) &&
    258       !result.empty())
    259     return result;
    260   return GetManagerUserId(user_id);
    261 }
    262 
    263 void SupervisedUserManagerImpl::GetPasswordInformation(
    264     const std::string& user_id,
    265     base::DictionaryValue* result) {
    266   int value;
    267   if (GetUserIntegerValue(user_id, kSupervisedUserPasswordSchema, &value))
    268     result->SetIntegerWithoutPathExpansion(kSchemaVersion, value);
    269   if (GetUserIntegerValue(user_id, kSupervisedUserPasswordRevision, &value))
    270     result->SetIntegerWithoutPathExpansion(kPasswordRevision, value);
    271 
    272   bool flag;
    273   if (GetUserBooleanValue(user_id, kSupervisedUserNeedPasswordUpdate, &flag))
    274     result->SetBooleanWithoutPathExpansion(kRequirePasswordUpdate, flag);
    275   if (GetUserBooleanValue(user_id, kSupervisedUserIncompleteKey, &flag))
    276     result->SetBooleanWithoutPathExpansion(kHasIncompleteKey, flag);
    277 
    278   std::string salt;
    279   if (GetUserStringValue(user_id, kSupervisedUserPasswordSalt, &salt))
    280     result->SetStringWithoutPathExpansion(kSalt, salt);
    281 }
    282 
    283 void SupervisedUserManagerImpl::SetPasswordInformation(
    284       const std::string& user_id,
    285       const base::DictionaryValue* password_info) {
    286   int value;
    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);
    291 
    292   bool flag;
    293   if (password_info->GetBooleanWithoutPathExpansion(kRequirePasswordUpdate,
    294                                                     &flag)) {
    295     SetUserBooleanValue(user_id, kSupervisedUserNeedPasswordUpdate, flag);
    296   }
    297   if (password_info->GetBooleanWithoutPathExpansion(kHasIncompleteKey, &flag))
    298     SetUserBooleanValue(user_id, kSupervisedUserIncompleteKey, flag);
    299 
    300   std::string salt;
    301   if (password_info->GetStringWithoutPathExpansion(kSalt, &salt))
    302     SetUserStringValue(user_id, kSupervisedUserPasswordSalt, salt);
    303   g_browser_process->local_state()->CommitPendingWrite();
    304 }
    305 
    306 bool SupervisedUserManagerImpl::GetUserStringValue(
    307     const std::string& user_id,
    308     const char* key,
    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);
    313 }
    314 
    315 bool SupervisedUserManagerImpl::GetUserIntegerValue(
    316     const std::string& user_id,
    317     const char* key,
    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);
    322 }
    323 
    324 bool SupervisedUserManagerImpl::GetUserBooleanValue(const std::string& user_id,
    325                                                     const char* key,
    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);
    330 }
    331 
    332 void SupervisedUserManagerImpl::SetUserStringValue(
    333     const std::string& user_id,
    334     const char* key,
    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);
    339 }
    340 
    341 void SupervisedUserManagerImpl::SetUserIntegerValue(
    342     const std::string& user_id,
    343     const char* key,
    344     const int value) {
    345   PrefService* local_state = g_browser_process->local_state();
    346   DictionaryPrefUpdate update(local_state, key);
    347   update->SetIntegerWithoutPathExpansion(user_id, value);
    348 }
    349 
    350 void SupervisedUserManagerImpl::SetUserBooleanValue(const std::string& user_id,
    351                                                     const char* key,
    352                                                     const bool value) {
    353   PrefService* local_state = g_browser_process->local_state();
    354   DictionaryPrefUpdate update(local_state, key);
    355   update->SetBooleanWithoutPathExpansion(user_id, value);
    356 }
    357 
    358 const user_manager::User* SupervisedUserManagerImpl::FindByDisplayName(
    359     const base::string16& display_name) const {
    360   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    361   const user_manager::UserList& users = owner_->GetUsers();
    362   for (user_manager::UserList::const_iterator it = users.begin();
    363        it != users.end();
    364        ++it) {
    365     if (((*it)->GetType() == user_manager::USER_TYPE_SUPERVISED) &&
    366         ((*it)->display_name() == display_name)) {
    367       return *it;
    368     }
    369   }
    370   return NULL;
    371 }
    372 
    373 const user_manager::User* SupervisedUserManagerImpl::FindBySyncId(
    374     const std::string& sync_id) const {
    375   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    376   const user_manager::UserList& users = owner_->GetUsers();
    377   for (user_manager::UserList::const_iterator it = users.begin();
    378        it != users.end();
    379        ++it) {
    380     if (((*it)->GetType() == user_manager::USER_TYPE_SUPERVISED) &&
    381         (GetUserSyncId((*it)->email()) == sync_id)) {
    382       return *it;
    383     }
    384   }
    385   return NULL;
    386 }
    387 
    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();
    394 }
    395 
    396 void SupervisedUserManagerImpl::SetCreationTransactionUserId(
    397       const std::string& email) {
    398   g_browser_process->local_state()->
    399       SetString(kSupervisedUserCreationTransactionUserId,
    400                 email);
    401   g_browser_process->local_state()->CommitPendingWrite();
    402 }
    403 
    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();
    410 }
    411 
    412 bool SupervisedUserManagerImpl::HasFailedUserCreationTransaction() {
    413   return !(g_browser_process->local_state()->
    414                GetString(kSupervisedUserCreationTransactionDisplayName).
    415                    empty());
    416 }
    417 
    418 void SupervisedUserManagerImpl::RollbackUserCreationTransaction() {
    419   PrefService* prefs = g_browser_process->local_state();
    420 
    421   std::string display_name = prefs->
    422       GetString(kSupervisedUserCreationTransactionDisplayName);
    423   std::string user_id = prefs->
    424       GetString(kSupervisedUserCreationTransactionUserId);
    425 
    426   LOG(WARNING) << "Cleaning up transaction for "
    427                << display_name << "/" << user_id;
    428 
    429   if (user_id.empty()) {
    430     // Not much to do - just remove transaction.
    431     prefs->ClearPref(kSupervisedUserCreationTransactionDisplayName);
    432     prefs->CommitPendingWrite();
    433     return;
    434   }
    435 
    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();
    443     return;
    444   }
    445   owner_->RemoveNonOwnerUserInternal(user_id, NULL);
    446 
    447   prefs->ClearPref(kSupervisedUserCreationTransactionDisplayName);
    448   prefs->ClearPref(kSupervisedUserCreationTransactionUserId);
    449   prefs->CommitPendingWrite();
    450 }
    451 
    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);
    457 
    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);
    467 }
    468 
    469 void SupervisedUserManagerImpl::CleanPref(const std::string& user_id,
    470                                           const char* key) {
    471   PrefService* prefs = g_browser_process->local_state();
    472   DictionaryPrefUpdate dict_update(prefs, key);
    473   dict_update->RemoveWithoutPathExpansion(user_id, NULL);
    474 }
    475 
    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);
    480 }
    481 
    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();
    485 
    486   const base::DictionaryValue* manager_ids =
    487       local_state->GetDictionary(kSupervisedUserManagers);
    488 
    489   DictionaryPrefUpdate manager_name_update(local_state,
    490                                            kSupervisedUserManagerNames);
    491   for (base::DictionaryValue::Iterator it(*manager_ids); !it.IsAtEnd();
    492       it.Advance()) {
    493     std::string user_id;
    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(
    498           it.key(),
    499           new base::StringValue(new_display_name));
    500     }
    501   }
    502 }
    503 
    504 SupervisedUserAuthentication* SupervisedUserManagerImpl::GetAuthentication() {
    505   return authentication_.get();
    506 }
    507 
    508 void SupervisedUserManagerImpl::LoadSupervisedUserToken(
    509     Profile* profile,
    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       FROM_HERE,
    517       base::Bind(&LoadSyncToken, profile_dir),
    518       callback);
    519 }
    520 
    521 void SupervisedUserManagerImpl::ConfigureSyncWithToken(
    522     Profile* profile,
    523     const std::string& token) {
    524   if (!token.empty())
    525     SupervisedUserServiceFactory::GetForProfile(profile)->InitSync(token);
    526 }
    527 
    528 }  // namespace chromeos
    529