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