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/multi_profile_user_controller.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/prefs/pref_change_registrar.h"
     10 #include "base/prefs/pref_registry_simple.h"
     11 #include "base/prefs/pref_service.h"
     12 #include "base/prefs/scoped_user_pref_update.h"
     13 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller_delegate.h"
     14 #include "chrome/browser/chromeos/policy/policy_cert_service.h"
     15 #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
     16 #include "chrome/browser/chromeos/profiles/profile_helper.h"
     17 #include "chrome/browser/prefs/pref_service_syncable.h"
     18 #include "chrome/browser/profiles/profile.h"
     19 #include "chrome/common/pref_names.h"
     20 #include "components/user_manager/user.h"
     21 #include "components/user_manager/user_manager.h"
     22 #include "google_apis/gaia/gaia_auth_util.h"
     23 
     24 namespace chromeos {
     25 
     26 namespace {
     27 
     28 std::string SanitizeBehaviorValue(const std::string& value) {
     29   if (value == MultiProfileUserController::kBehaviorUnrestricted ||
     30       value == MultiProfileUserController::kBehaviorPrimaryOnly ||
     31       value == MultiProfileUserController::kBehaviorNotAllowed) {
     32     return value;
     33   }
     34 
     35   return std::string(MultiProfileUserController::kBehaviorUnrestricted);
     36 }
     37 
     38 bool SetUserAllowedReason(
     39     MultiProfileUserController::UserAllowedInSessionReason* reason,
     40     MultiProfileUserController::UserAllowedInSessionReason value) {
     41   if (reason)
     42     *reason = value;
     43   return value == MultiProfileUserController::ALLOWED;
     44 }
     45 
     46 }  // namespace
     47 
     48 // static
     49 const char MultiProfileUserController::kBehaviorUnrestricted[] = "unrestricted";
     50 const char MultiProfileUserController::kBehaviorPrimaryOnly[] = "primary-only";
     51 const char MultiProfileUserController::kBehaviorNotAllowed[] = "not-allowed";
     52 
     53 // Note: this policy value is not a real one an is only returned locally for
     54 // owner users instead of default one kBehaviorUnrestricted.
     55 const char MultiProfileUserController::kBehaviorOwnerPrimaryOnly[] =
     56     "owner-primary-only";
     57 
     58 MultiProfileUserController::MultiProfileUserController(
     59     MultiProfileUserControllerDelegate* delegate,
     60     PrefService* local_state)
     61     : delegate_(delegate),
     62       local_state_(local_state) {
     63 }
     64 
     65 MultiProfileUserController::~MultiProfileUserController() {}
     66 
     67 // static
     68 void MultiProfileUserController::RegisterPrefs(
     69     PrefRegistrySimple* registry) {
     70   registry->RegisterDictionaryPref(prefs::kCachedMultiProfileUserBehavior);
     71 }
     72 
     73 // static
     74 void MultiProfileUserController::RegisterProfilePrefs(
     75     user_prefs::PrefRegistrySyncable* registry) {
     76   registry->RegisterStringPref(
     77       prefs::kMultiProfileUserBehavior,
     78       kBehaviorUnrestricted,
     79       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
     80   registry->RegisterBooleanPref(
     81       prefs::kMultiProfileNeverShowIntro,
     82       false,
     83       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
     84   registry->RegisterBooleanPref(
     85       prefs::kMultiProfileWarningShowDismissed,
     86       false,
     87       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
     88 }
     89 
     90 // static
     91 MultiProfileUserController::UserAllowedInSessionReason
     92 MultiProfileUserController::GetPrimaryUserPolicy() {
     93   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
     94   CHECK(user_manager);
     95 
     96   const user_manager::User* user = user_manager->GetPrimaryUser();
     97   if (!user)
     98     return ALLOWED;
     99 
    100   // Don't allow any secondary profiles if the primary profile is tainted.
    101   if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user->email())) {
    102     // Check directly in local_state before checking if the primary user has
    103     // a PolicyCertService. His profile may have been tainted previously though
    104     // he didn't get a PolicyCertService created for this session.
    105     return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED;
    106   }
    107 
    108   Profile* profile = ProfileHelper::Get()->GetProfileByUser(user);
    109   if (!profile)
    110     return ALLOWED;
    111 
    112   // If the primary profile already has policy certificates installed but
    113   // hasn't used them yet then it can become tainted at any time during this
    114   // session disable secondary profiles in this case too.
    115   policy::PolicyCertService* service =
    116       policy::PolicyCertServiceFactory::GetForProfile(profile);
    117   if (service && service->has_policy_certificates())
    118     return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED;
    119 
    120   // No user is allowed if the primary user policy forbids it.
    121   const std::string behavior = profile->GetPrefs()->GetString(
    122       prefs::kMultiProfileUserBehavior);
    123   if (behavior == kBehaviorNotAllowed)
    124     return NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS;
    125 
    126   return ALLOWED;
    127 }
    128 
    129 bool MultiProfileUserController::IsUserAllowedInSession(
    130     const std::string& user_email,
    131     MultiProfileUserController::UserAllowedInSessionReason* reason) const {
    132   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
    133   CHECK(user_manager);
    134 
    135   const user_manager::User* primary_user = user_manager->GetPrimaryUser();
    136   std::string primary_user_email;
    137   if (primary_user)
    138     primary_user_email = primary_user->email();
    139 
    140   // Always allow if there is no primary user or user being checked is the
    141   // primary user.
    142   if (primary_user_email.empty() || primary_user_email == user_email)
    143     return SetUserAllowedReason(reason, ALLOWED);
    144 
    145   // Owner is not allowed to be secondary user.
    146   if (user_manager->GetOwnerEmail() == user_email)
    147     return SetUserAllowedReason(reason, NOT_ALLOWED_OWNER_AS_SECONDARY);
    148 
    149   // Don't allow profiles potentially tainted by data fetched with policy-pushed
    150   // certificates to join a multiprofile session.
    151   if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user_email))
    152     return SetUserAllowedReason(reason, NOT_ALLOWED_POLICY_CERT_TAINTED);
    153 
    154   UserAllowedInSessionReason primary_user_policy = GetPrimaryUserPolicy();
    155   if (primary_user_policy != ALLOWED)
    156     return SetUserAllowedReason(reason, primary_user_policy);
    157 
    158   // The user must have 'unrestricted' policy to be a secondary user.
    159   const std::string behavior = GetCachedValue(user_email);
    160   return SetUserAllowedReason(
    161       reason,
    162       behavior == kBehaviorUnrestricted ? ALLOWED : NOT_ALLOWED_POLICY_FORBIDS);
    163 }
    164 
    165 void MultiProfileUserController::StartObserving(Profile* user_profile) {
    166   // Profile name could be empty during tests.
    167   if (user_profile->GetProfileName().empty())
    168     return;
    169 
    170   scoped_ptr<PrefChangeRegistrar> registrar(new PrefChangeRegistrar);
    171   registrar->Init(user_profile->GetPrefs());
    172   registrar->Add(
    173       prefs::kMultiProfileUserBehavior,
    174       base::Bind(&MultiProfileUserController::OnUserPrefChanged,
    175                  base::Unretained(this),
    176                  user_profile));
    177   pref_watchers_.push_back(registrar.release());
    178 
    179   OnUserPrefChanged(user_profile);
    180 }
    181 
    182 void MultiProfileUserController::RemoveCachedValues(
    183     const std::string& user_email) {
    184   DictionaryPrefUpdate update(local_state_,
    185                               prefs::kCachedMultiProfileUserBehavior);
    186   update->RemoveWithoutPathExpansion(user_email, NULL);
    187   policy::PolicyCertServiceFactory::ClearUsedPolicyCertificates(user_email);
    188 }
    189 
    190 std::string MultiProfileUserController::GetCachedValue(
    191     const std::string& user_email) const {
    192   const base::DictionaryValue* dict =
    193       local_state_->GetDictionary(prefs::kCachedMultiProfileUserBehavior);
    194   std::string value;
    195   if (dict && dict->GetStringWithoutPathExpansion(user_email, &value))
    196     return SanitizeBehaviorValue(value);
    197 
    198   return std::string(kBehaviorUnrestricted);
    199 }
    200 
    201 void MultiProfileUserController::SetCachedValue(
    202     const std::string& user_email,
    203     const std::string& behavior) {
    204   DictionaryPrefUpdate update(local_state_,
    205                               prefs::kCachedMultiProfileUserBehavior);
    206   update->SetStringWithoutPathExpansion(user_email,
    207                                         SanitizeBehaviorValue(behavior));
    208 }
    209 
    210 void MultiProfileUserController::CheckSessionUsers() {
    211   const user_manager::UserList& users =
    212       user_manager::UserManager::Get()->GetLoggedInUsers();
    213   for (user_manager::UserList::const_iterator it = users.begin();
    214        it != users.end();
    215        ++it) {
    216     if (!IsUserAllowedInSession((*it)->email(), NULL)) {
    217       delegate_->OnUserNotAllowed((*it)->email());
    218       return;
    219     }
    220   }
    221 }
    222 
    223 void MultiProfileUserController::OnUserPrefChanged(
    224     Profile* user_profile) {
    225   std::string user_email = user_profile->GetProfileName();
    226   CHECK(!user_email.empty());
    227   user_email = gaia::CanonicalizeEmail(user_email);
    228 
    229   PrefService* prefs = user_profile->GetPrefs();
    230   if (prefs->FindPreference(prefs::kMultiProfileUserBehavior)
    231           ->IsDefaultValue()) {
    232     // Migration code to clear cached default behavior.
    233     // TODO(xiyuan): Remove this after M35.
    234     DictionaryPrefUpdate update(local_state_,
    235                                 prefs::kCachedMultiProfileUserBehavior);
    236     update->RemoveWithoutPathExpansion(user_email, NULL);
    237   } else {
    238     const std::string behavior =
    239         prefs->GetString(prefs::kMultiProfileUserBehavior);
    240     SetCachedValue(user_email, behavior);
    241   }
    242 
    243   CheckSessionUsers();
    244 }
    245 
    246 }  // namespace chromeos
    247