login_performer.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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/auth/login_performer.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "base/message_loop/message_loop.h" 10#include "base/metrics/histogram.h" 11#include "base/prefs/pref_service.h" 12#include "base/strings/utf_string_conversions.h" 13#include "base/threading/thread_restrictions.h" 14#include "chrome/browser/browser_process.h" 15#include "chrome/browser/chrome_notification_types.h" 16#include "chrome/browser/chromeos/boot_times_loader.h" 17#include "chrome/browser/chromeos/login/login_utils.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/managed/supervised_user_login_flow.h" 21#include "chrome/browser/chromeos/login/users/supervised_user_manager.h" 22#include "chrome/browser/chromeos/login/users/user_manager.h" 23#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 24#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" 25#include "chrome/browser/chromeos/profiles/profile_helper.h" 26#include "chrome/browser/chromeos/settings/cros_settings.h" 27#include "chrome/common/pref_names.h" 28#include "chromeos/dbus/dbus_thread_manager.h" 29#include "chromeos/dbus/session_manager_client.h" 30#include "chromeos/settings/cros_settings_names.h" 31#include "content/public/browser/browser_thread.h" 32#include "content/public/browser/notification_service.h" 33#include "content/public/browser/notification_types.h" 34#include "content/public/browser/user_metrics.h" 35#include "google_apis/gaia/gaia_auth_util.h" 36#include "grit/generated_resources.h" 37#include "net/cookies/cookie_monster.h" 38#include "net/cookies/cookie_store.h" 39#include "net/url_request/url_request_context.h" 40#include "net/url_request/url_request_context_getter.h" 41#include "ui/base/l10n/l10n_util.h" 42#include "ui/base/resource/resource_bundle.h" 43 44using base::UserMetricsAction; 45using content::BrowserThread; 46 47namespace chromeos { 48 49LoginPerformer::LoginPerformer(Delegate* delegate) 50 : online_attempt_host_(this), 51 last_login_failure_(LoginFailure::LoginFailureNone()), 52 delegate_(delegate), 53 password_changed_(false), 54 password_changed_callback_count_(0), 55 auth_mode_(AUTH_MODE_INTERNAL), 56 weak_factory_(this) { 57} 58 59LoginPerformer::~LoginPerformer() { 60 DVLOG(1) << "Deleting LoginPerformer"; 61 if (authenticator_.get()) 62 authenticator_->SetConsumer(NULL); 63 if (extended_authenticator_.get()) 64 extended_authenticator_->SetConsumer(NULL); 65} 66 67//////////////////////////////////////////////////////////////////////////////// 68// LoginPerformer, LoginStatusConsumer implementation: 69 70void LoginPerformer::OnLoginFailure(const LoginFailure& failure) { 71 content::RecordAction(UserMetricsAction("Login_Failure")); 72 UMA_HISTOGRAM_ENUMERATION("Login.FailureReason", failure.reason(), 73 LoginFailure::NUM_FAILURE_REASONS); 74 75 DVLOG(1) << "failure.reason " << failure.reason(); 76 DVLOG(1) << "failure.error.state " << failure.error().state(); 77 78 last_login_failure_ = failure; 79 if (delegate_) { 80 delegate_->OnLoginFailure(failure); 81 return; 82 } else { 83 // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS: 84 // happens during offline auth only. 85 NOTREACHED(); 86 } 87} 88 89void LoginPerformer::OnRetailModeLoginSuccess( 90 const UserContext& user_context) { 91 content::RecordAction( 92 UserMetricsAction("Login_DemoUserLoginSuccess")); 93 LoginStatusConsumer::OnRetailModeLoginSuccess(user_context); 94} 95 96void LoginPerformer::OnLoginSuccess(const UserContext& user_context) { 97 content::RecordAction(UserMetricsAction("Login_Success")); 98 VLOG(1) << "LoginSuccess hash: " << user_context.GetUserIDHash(); 99 DCHECK(delegate_); 100 // After delegate_->OnLoginSuccess(...) is called, delegate_ releases 101 // LoginPerformer ownership. LP now manages it's lifetime on its own. 102 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 103 delegate_->OnLoginSuccess(user_context); 104} 105 106void LoginPerformer::OnOffTheRecordLoginSuccess() { 107 content::RecordAction( 108 UserMetricsAction("Login_GuestLoginSuccess")); 109 110 if (delegate_) 111 delegate_->OnOffTheRecordLoginSuccess(); 112 else 113 NOTREACHED(); 114} 115 116void LoginPerformer::OnPasswordChangeDetected() { 117 password_changed_ = true; 118 password_changed_callback_count_++; 119 if (delegate_) { 120 delegate_->OnPasswordChangeDetected(); 121 } else { 122 NOTREACHED(); 123 } 124} 125 126void LoginPerformer::OnChecked(const std::string& username, bool success) { 127 if (!delegate_) { 128 // Delegate is reset in case of successful offline login. 129 // See ExistingUserConstoller::OnLoginSuccess(). 130 // Case when user has changed password and enters old password 131 // does not block user from sign in yet. 132 return; 133 } 134 delegate_->OnOnlineChecked(username, success); 135} 136 137//////////////////////////////////////////////////////////////////////////////// 138// LoginPerformer, public: 139 140void LoginPerformer::PerformLogin(const UserContext& user_context, 141 AuthorizationMode auth_mode) { 142 auth_mode_ = auth_mode; 143 user_context_ = user_context; 144 145 CrosSettings* cros_settings = CrosSettings::Get(); 146 147 // Whitelist check is always performed during initial login. 148 CrosSettingsProvider::TrustedStatus status = 149 cros_settings->PrepareTrustedValues( 150 base::Bind(&LoginPerformer::PerformLogin, 151 weak_factory_.GetWeakPtr(), 152 user_context_, auth_mode)); 153 // Must not proceed without signature verification. 154 if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) { 155 if (delegate_) 156 delegate_->PolicyLoadFailed(); 157 else 158 NOTREACHED(); 159 return; 160 } else if (status != CrosSettingsProvider::TRUSTED) { 161 // Value of AllowNewUser setting is still not verified. 162 // Another attempt will be invoked after verification completion. 163 return; 164 } 165 166 bool wildcard_match = false; 167 std::string email = gaia::CanonicalizeEmail(user_context.GetUserID()); 168 bool is_whitelisted = LoginUtils::IsWhitelisted(email, &wildcard_match); 169 if (is_whitelisted) { 170 switch (auth_mode_) { 171 case AUTH_MODE_EXTENSION: { 172 // On enterprise devices, reconfirm login permission with the server. 173 policy::BrowserPolicyConnectorChromeOS* connector = 174 g_browser_process->platform_part() 175 ->browser_policy_connector_chromeos(); 176 if (connector->IsEnterpriseManaged() && wildcard_match && 177 !connector->IsNonEnterpriseUser(email)) { 178 wildcard_login_checker_.reset(new policy::WildcardLoginChecker()); 179 wildcard_login_checker_->Start( 180 ProfileHelper::GetSigninProfile()->GetRequestContext(), 181 base::Bind(&LoginPerformer::OnlineWildcardLoginCheckCompleted, 182 weak_factory_.GetWeakPtr())); 183 } else { 184 StartLoginCompletion(); 185 } 186 break; 187 } 188 case AUTH_MODE_INTERNAL: 189 StartAuthentication(); 190 break; 191 } 192 } else { 193 if (delegate_) 194 delegate_->WhiteListCheckFailed(user_context.GetUserID()); 195 else 196 NOTREACHED(); 197 } 198} 199 200void LoginPerformer::LoginAsLocallyManagedUser( 201 const UserContext& user_context) { 202 DCHECK_EQ(UserManager::kLocallyManagedUserDomain, 203 gaia::ExtractDomainName(user_context.GetUserID())); 204 205 CrosSettings* cros_settings = CrosSettings::Get(); 206 CrosSettingsProvider::TrustedStatus status = 207 cros_settings->PrepareTrustedValues( 208 base::Bind(&LoginPerformer::LoginAsLocallyManagedUser, 209 weak_factory_.GetWeakPtr(), 210 user_context_)); 211 // Must not proceed without signature verification. 212 if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) { 213 if (delegate_) 214 delegate_->PolicyLoadFailed(); 215 else 216 NOTREACHED(); 217 return; 218 } else if (status != CrosSettingsProvider::TRUSTED) { 219 // Value of kAccountsPrefSupervisedUsersEnabled setting is still not 220 // verified. Another attempt will be invoked after verification completion. 221 return; 222 } 223 224 if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) { 225 LOG(ERROR) << "Login attempt of locally managed user detected."; 226 delegate_->WhiteListCheckFailed(user_context.GetUserID()); 227 return; 228 } 229 230 SupervisedUserLoginFlow* new_flow = 231 new SupervisedUserLoginFlow(user_context.GetUserID()); 232 new_flow->set_host( 233 UserManager::Get()->GetUserFlow(user_context.GetUserID())->host()); 234 UserManager::Get()->SetUserFlow(user_context.GetUserID(), new_flow); 235 236 SupervisedUserAuthentication* authentication = UserManager::Get()-> 237 GetSupervisedUserManager()->GetAuthentication(); 238 239 UserContext user_context_copy = authentication->TransformKey(user_context); 240 241 if (authentication->GetPasswordSchema(user_context.GetUserID()) == 242 SupervisedUserAuthentication::SCHEMA_SALT_HASHED) { 243 if (extended_authenticator_.get()) { 244 extended_authenticator_->SetConsumer(NULL); 245 } 246 extended_authenticator_ = new ExtendedAuthenticator(this); 247 // TODO(antrim) : Replace empty callback with explicit method. 248 // http://crbug.com/351268 249 BrowserThread::PostTask( 250 BrowserThread::UI, 251 FROM_HERE, 252 base::Bind(&ExtendedAuthenticator::AuthenticateToMount, 253 extended_authenticator_.get(), 254 user_context_copy, 255 ExtendedAuthenticator::ResultCallback())); 256 257 } else { 258 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); 259 BrowserThread::PostTask( 260 BrowserThread::UI, 261 FROM_HERE, 262 base::Bind(&Authenticator::LoginAsLocallyManagedUser, 263 authenticator_.get(), 264 user_context_copy)); 265 } 266} 267 268void LoginPerformer::LoginRetailMode() { 269 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); 270 BrowserThread::PostTask( 271 BrowserThread::UI, FROM_HERE, 272 base::Bind(&Authenticator::LoginRetailMode, authenticator_.get())); 273} 274 275void LoginPerformer::LoginOffTheRecord() { 276 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); 277 BrowserThread::PostTask( 278 BrowserThread::UI, FROM_HERE, 279 base::Bind(&Authenticator::LoginOffTheRecord, authenticator_.get())); 280} 281 282void LoginPerformer::LoginAsPublicAccount(const std::string& username) { 283 // Login is not allowed if policy could not be loaded for the account. 284 policy::BrowserPolicyConnectorChromeOS* connector = 285 g_browser_process->platform_part()->browser_policy_connector_chromeos(); 286 policy::DeviceLocalAccountPolicyService* policy_service = 287 connector->GetDeviceLocalAccountPolicyService(); 288 if (!policy_service || !policy_service->IsPolicyAvailableForUser(username)) { 289 DCHECK(delegate_); 290 if (delegate_) 291 delegate_->PolicyLoadFailed(); 292 return; 293 } 294 295 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); 296 BrowserThread::PostTask( 297 BrowserThread::UI, FROM_HERE, 298 base::Bind(&Authenticator::LoginAsPublicAccount, authenticator_.get(), 299 username)); 300} 301 302void LoginPerformer::LoginAsKioskAccount(const std::string& app_user_id, 303 bool use_guest_mount) { 304 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); 305 BrowserThread::PostTask( 306 BrowserThread::UI, FROM_HERE, 307 base::Bind(&Authenticator::LoginAsKioskAccount, authenticator_.get(), 308 app_user_id, use_guest_mount)); 309} 310 311void LoginPerformer::RecoverEncryptedData(const std::string& old_password) { 312 BrowserThread::PostTask( 313 BrowserThread::UI, FROM_HERE, 314 base::Bind(&Authenticator::RecoverEncryptedData, authenticator_.get(), 315 old_password)); 316} 317 318void LoginPerformer::ResyncEncryptedData() { 319 BrowserThread::PostTask( 320 BrowserThread::UI, FROM_HERE, 321 base::Bind(&Authenticator::ResyncEncryptedData, authenticator_.get())); 322} 323 324//////////////////////////////////////////////////////////////////////////////// 325// LoginPerformer, private: 326 327void LoginPerformer::StartLoginCompletion() { 328 DVLOG(1) << "Login completion started"; 329 BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false); 330 Profile* profile = ProfileHelper::GetSigninProfile(); 331 332 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); 333 BrowserThread::PostTask( 334 BrowserThread::UI, FROM_HERE, 335 base::Bind(&Authenticator::CompleteLogin, authenticator_.get(), 336 profile, 337 user_context_)); 338 user_context_.ClearSecrets(); 339} 340 341void LoginPerformer::StartAuthentication() { 342 DVLOG(1) << "Auth started"; 343 BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false); 344 Profile* profile = ProfileHelper::GetSigninProfile(); 345 if (delegate_) { 346 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); 347 BrowserThread::PostTask( 348 BrowserThread::UI, FROM_HERE, 349 base::Bind(&Authenticator::AuthenticateToLogin, authenticator_.get(), 350 profile, 351 user_context_)); 352 // Make unobtrusive online check. It helps to determine password change 353 // state in the case when offline login fails. 354 online_attempt_host_.Check(profile, user_context_); 355 } else { 356 NOTREACHED(); 357 } 358 user_context_.ClearSecrets(); 359} 360 361void LoginPerformer::OnlineWildcardLoginCheckCompleted( 362 policy::WildcardLoginChecker::Result result) { 363 if (result == policy::WildcardLoginChecker::RESULT_ALLOWED) { 364 StartLoginCompletion(); 365 } else { 366 if (delegate_) 367 delegate_->WhiteListCheckFailed(user_context_.GetUserID()); 368 } 369} 370 371} // namespace chromeos 372