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 |