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