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 |