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