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