| 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 "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/metrics/user_metrics.h" | |
| 12 #include "base/metrics/user_metrics_action.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 "chromeos/dbus/dbus_thread_manager.h" | |
| 17 #include "chromeos/dbus/session_manager_client.h" | |
| 18 #include "chromeos/login/user_names.h" | |
| 19 #include "chromeos/login_event_recorder.h" | |
| 20 #include "chromeos/settings/cros_settings_names.h" | |
| 21 #include "google_apis/gaia/gaia_auth_util.h" | |
| 22 #include "net/cookies/cookie_monster.h" | |
| 23 #include "net/cookies/cookie_store.h" | |
| 24 #include "net/url_request/url_request_context.h" | |
| 25 #include "net/url_request/url_request_context_getter.h" | |
| 26 | |
| 27 using base::UserMetricsAction; | |
| 28 | |
| 29 namespace chromeos { | |
| 30 | |
| 31 LoginPerformer::LoginPerformer(scoped_refptr<base::TaskRunner> task_runner, | |
| 32 Delegate* delegate) | |
| 33 : delegate_(delegate), | |
| 34 task_runner_(task_runner), | |
| 35 online_attempt_host_(this), | |
| 36 last_login_failure_(AuthFailure::AuthFailureNone()), | |
| 37 password_changed_(false), | |
| 38 password_changed_callback_count_(0), | |
| 39 auth_mode_(AUTH_MODE_INTERNAL), | |
| 40 weak_factory_(this) { | |
| 41 } | |
| 42 | |
| 43 LoginPerformer::~LoginPerformer() { | |
| 44 DVLOG(1) << "Deleting LoginPerformer"; | |
| 45 if (authenticator_.get()) | |
| 46 authenticator_->SetConsumer(NULL); | |
| 47 if (extended_authenticator_.get()) | |
| 48 extended_authenticator_->SetConsumer(NULL); | |
| 49 } | |
| 50 | |
| 51 //////////////////////////////////////////////////////////////////////////////// | |
| 52 // LoginPerformer, AuthStatusConsumer implementation: | |
| 53 | |
| 54 void LoginPerformer::OnAuthFailure(const AuthFailure& failure) { | |
| 55 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 56 base::RecordAction(UserMetricsAction("Login_Failure")); | |
| 57 | |
| 58 UMA_HISTOGRAM_ENUMERATION("Login.FailureReason", | |
| 59 failure.reason(), | |
| 60 AuthFailure::NUM_FAILURE_REASONS); | |
| 61 | |
| 62 DVLOG(1) << "failure.reason " << failure.reason(); | |
| 63 DVLOG(1) << "failure.error.state " << failure.error().state(); | |
| 64 | |
| 65 last_login_failure_ = failure; | |
| 66 if (delegate_) { | |
| 67 delegate_->OnAuthFailure(failure); | |
| 68 return; | |
| 69 } else { | |
| 70 // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS: | |
| 71 // happens during offline auth only. | |
| 72 NOTREACHED(); | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 void LoginPerformer::OnRetailModeAuthSuccess(const UserContext& user_context) { | |
| 77 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 78 base::RecordAction(UserMetricsAction("Login_DemoUserLoginSuccess")); | |
| 79 AuthStatusConsumer::OnRetailModeAuthSuccess(user_context); | |
| 80 } | |
| 81 | |
| 82 void LoginPerformer::OnAuthSuccess(const UserContext& user_context) { | |
| 83 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 84 base::RecordAction(UserMetricsAction("Login_Success")); | |
| 85 VLOG(1) << "LoginSuccess hash: " << user_context.GetUserIDHash(); | |
| 86 DCHECK(delegate_); | |
| 87 // After delegate_->OnAuthSuccess(...) is called, delegate_ releases | |
| 88 // LoginPerformer ownership. LP now manages it's lifetime on its own. | |
| 89 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
| 90 delegate_->OnAuthSuccess(user_context); | |
| 91 } | |
| 92 | |
| 93 void LoginPerformer::OnOffTheRecordAuthSuccess() { | |
| 94 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | |
| 95 base::RecordAction(UserMetricsAction("Login_GuestLoginSuccess")); | |
| 96 | |
| 97 if (delegate_) | |
| 98 delegate_->OnOffTheRecordAuthSuccess(); | |
| 99 else | |
| 100 NOTREACHED(); | |
| 101 } | |
| 102 | |
| 103 void LoginPerformer::OnPasswordChangeDetected() { | |
| 104 password_changed_ = true; | |
| 105 password_changed_callback_count_++; | |
| 106 if (delegate_) { | |
| 107 delegate_->OnPasswordChangeDetected(); | |
| 108 } else { | |
| 109 NOTREACHED(); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 void LoginPerformer::OnChecked(const std::string& user_id, bool success) { | |
| 114 if (!delegate_) { | |
| 115 // Delegate is reset in case of successful offline login. | |
| 116 // See ExistingUserConstoller::OnAuthSuccess(). | |
| 117 // Case when user has changed password and enters old password | |
| 118 // does not block user from sign in yet. | |
| 119 return; | |
| 120 } | |
| 121 delegate_->OnOnlineChecked(user_id, success); | |
| 122 } | |
| 123 | |
| 124 //////////////////////////////////////////////////////////////////////////////// | |
| 125 // LoginPerformer, public: | |
| 126 | |
| 127 void LoginPerformer::NotifyWhitelistCheckFailure() { | |
| 128 if (delegate_) | |
| 129 delegate_->WhiteListCheckFailed(user_context_.GetUserID()); | |
| 130 else | |
| 131 NOTREACHED(); | |
| 132 } | |
| 133 | |
| 134 void LoginPerformer::PerformLogin(const UserContext& user_context, | |
| 135 AuthorizationMode auth_mode) { | |
| 136 auth_mode_ = auth_mode; | |
| 137 user_context_ = user_context; | |
| 138 | |
| 139 if (RunTrustedCheck(base::Bind(&LoginPerformer::DoPerformLogin, | |
| 140 weak_factory_.GetWeakPtr(), | |
| 141 user_context_, | |
| 142 auth_mode))) { | |
| 143 return; | |
| 144 } | |
| 145 DoPerformLogin(user_context, auth_mode); | |
| 146 } | |
| 147 | |
| 148 void LoginPerformer::DoPerformLogin(const UserContext& user_context, | |
| 149 AuthorizationMode auth_mode) { | |
| 150 std::string email = gaia::CanonicalizeEmail(user_context.GetUserID()); | |
| 151 bool wildcard_match = false; | |
| 152 if (!IsUserWhitelisted(email, &wildcard_match)) { | |
| 153 NotifyWhitelistCheckFailure(); | |
| 154 return; | |
| 155 } | |
| 156 switch (auth_mode_) { | |
| 157 case AUTH_MODE_EXTENSION: { | |
| 158 RunOnlineWhitelistCheck( | |
| 159 email, | |
| 160 wildcard_match, | |
| 161 base::Bind(&LoginPerformer::StartLoginCompletion, | |
| 162 weak_factory_.GetWeakPtr()), | |
| 163 base::Bind(&LoginPerformer::NotifyWhitelistCheckFailure, | |
| 164 weak_factory_.GetWeakPtr())); | |
| 165 break; | |
| 166 } | |
| 167 case AUTH_MODE_INTERNAL: | |
| 168 StartAuthentication(); | |
| 169 break; | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 void LoginPerformer::LoginAsSupervisedUser(const UserContext& user_context) { | |
| 174 DCHECK_EQ(chromeos::login::kSupervisedUserDomain, | |
| 175 gaia::ExtractDomainName(user_context.GetUserID())); | |
| 176 | |
| 177 if (RunTrustedCheck(base::Bind(&LoginPerformer::LoginAsSupervisedUser, | |
| 178 weak_factory_.GetWeakPtr(), | |
| 179 user_context_))) { | |
| 180 return; | |
| 181 } | |
| 182 | |
| 183 if (!AreSupervisedUsersAllowed()) { | |
| 184 LOG(ERROR) << "Login attempt of supervised user detected."; | |
| 185 delegate_->WhiteListCheckFailed(user_context.GetUserID()); | |
| 186 return; | |
| 187 } | |
| 188 | |
| 189 SetupSupervisedUserFlow(user_context.GetUserID()); | |
| 190 UserContext user_context_copy = TransformSupervisedKey(user_context); | |
| 191 | |
| 192 if (UseExtendedAuthenticatorForSupervisedUser(user_context)) { | |
| 193 EnsureExtendedAuthenticator(); | |
| 194 // TODO(antrim) : Replace empty callback with explicit method. | |
| 195 // http://crbug.com/351268 | |
| 196 task_runner_->PostTask( | |
| 197 FROM_HERE, | |
| 198 base::Bind(&ExtendedAuthenticator::AuthenticateToMount, | |
| 199 extended_authenticator_.get(), | |
| 200 user_context_copy, | |
| 201 ExtendedAuthenticator::ResultCallback())); | |
| 202 | |
| 203 } else { | |
| 204 EnsureAuthenticator(); | |
| 205 task_runner_->PostTask(FROM_HERE, | |
| 206 base::Bind(&Authenticator::LoginAsSupervisedUser, | |
| 207 authenticator_.get(), | |
| 208 user_context_copy)); | |
| 209 } | |
| 210 } | |
| 211 | |
| 212 void LoginPerformer::LoginAsPublicSession(const UserContext& user_context) { | |
| 213 if (!CheckPolicyForUser(user_context.GetUserID())) { | |
| 214 DCHECK(delegate_); | |
| 215 if (delegate_) | |
| 216 delegate_->PolicyLoadFailed(); | |
| 217 return; | |
| 218 } | |
| 219 | |
| 220 EnsureAuthenticator(); | |
| 221 task_runner_->PostTask(FROM_HERE, | |
| 222 base::Bind(&Authenticator::LoginAsPublicSession, | |
| 223 authenticator_.get(), | |
| 224 user_context)); | |
| 225 } | |
| 226 | |
| 227 void LoginPerformer::LoginRetailMode() { | |
| 228 EnsureAuthenticator(); | |
| 229 task_runner_->PostTask( | |
| 230 FROM_HERE, | |
| 231 base::Bind(&Authenticator::LoginRetailMode, authenticator_.get())); | |
| 232 } | |
| 233 | |
| 234 void LoginPerformer::LoginOffTheRecord() { | |
| 235 EnsureAuthenticator(); | |
| 236 task_runner_->PostTask( | |
| 237 FROM_HERE, | |
| 238 base::Bind(&Authenticator::LoginOffTheRecord, authenticator_.get())); | |
| 239 } | |
| 240 | |
| 241 void LoginPerformer::LoginAsKioskAccount(const std::string& app_user_id, | |
| 242 bool use_guest_mount) { | |
| 243 EnsureAuthenticator(); | |
| 244 task_runner_->PostTask(FROM_HERE, | |
| 245 base::Bind(&Authenticator::LoginAsKioskAccount, | |
| 246 authenticator_.get(), | |
| 247 app_user_id, | |
| 248 use_guest_mount)); | |
| 249 } | |
| 250 | |
| 251 void LoginPerformer::RecoverEncryptedData(const std::string& old_password) { | |
| 252 task_runner_->PostTask(FROM_HERE, | |
| 253 base::Bind(&Authenticator::RecoverEncryptedData, | |
| 254 authenticator_.get(), | |
| 255 old_password)); | |
| 256 } | |
| 257 | |
| 258 void LoginPerformer::ResyncEncryptedData() { | |
| 259 task_runner_->PostTask( | |
| 260 FROM_HERE, | |
| 261 base::Bind(&Authenticator::ResyncEncryptedData, authenticator_.get())); | |
| 262 } | |
| 263 | |
| 264 //////////////////////////////////////////////////////////////////////////////// | |
| 265 // LoginPerformer, private: | |
| 266 | |
| 267 void LoginPerformer::EnsureExtendedAuthenticator() { | |
| 268 if (extended_authenticator_.get()) | |
| 269 extended_authenticator_->SetConsumer(NULL); | |
| 270 extended_authenticator_ = ExtendedAuthenticator::Create(this); | |
| 271 } | |
| 272 | |
| 273 void LoginPerformer::StartLoginCompletion() { | |
| 274 DVLOG(1) << "Login completion started"; | |
| 275 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker("AuthStarted", false); | |
| 276 content::BrowserContext* browser_context = GetSigninContext(); | |
| 277 EnsureAuthenticator(); | |
| 278 task_runner_->PostTask(FROM_HERE, | |
| 279 base::Bind(&chromeos::Authenticator::CompleteLogin, | |
| 280 authenticator_.get(), | |
| 281 browser_context, | |
| 282 user_context_)); | |
| 283 user_context_.ClearSecrets(); | |
| 284 } | |
| 285 | |
| 286 void LoginPerformer::StartAuthentication() { | |
| 287 DVLOG(1) << "Auth started"; | |
| 288 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker("AuthStarted", false); | |
| 289 if (delegate_) { | |
| 290 EnsureAuthenticator(); | |
| 291 content::BrowserContext* browser_context = GetSigninContext(); | |
| 292 task_runner_->PostTask(FROM_HERE, | |
| 293 base::Bind(&Authenticator::AuthenticateToLogin, | |
| 294 authenticator_.get(), | |
| 295 base::Unretained(browser_context), | |
| 296 user_context_)); | |
| 297 // Make unobtrusive online check. It helps to determine password change | |
| 298 // state in the case when offline login fails. | |
| 299 online_attempt_host_.Check(GetSigninRequestContext(), user_context_); | |
| 300 } else { | |
| 301 NOTREACHED(); | |
| 302 } | |
| 303 user_context_.ClearSecrets(); | |
| 304 } | |
| 305 | |
| 306 void LoginPerformer::EnsureAuthenticator() { | |
| 307 authenticator_ = CreateAuthenticator(); | |
| 308 } | |
| 309 } // namespace chromeos | |
| OLD | NEW |