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