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.
5 #include "chrome/browser/chromeos/login/auth/parallel_authenticator.h"
8 #include "base/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/chromeos/boot_times_loader.h"
13 #include "chrome/browser/chromeos/login/auth/authentication_notification_details.h"
14 #include "chrome/browser/chromeos/login/auth/key.h"
15 #include "chrome/browser/chromeos/login/auth/login_status_consumer.h"
16 #include "chrome/browser/chromeos/login/auth/user_context.h"
17 #include "chrome/browser/chromeos/login/users/user.h"
18 #include "chrome/browser/chromeos/login/users/user_manager.h"
19 #include "chrome/browser/chromeos/ownership/owner_settings_service.h"
20 #include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
21 #include "chrome/browser/chromeos/settings/cros_settings.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chromeos/cryptohome/async_method_caller.h"
24 #include "chromeos/cryptohome/system_salt_getter.h"
25 #include "chromeos/dbus/cryptohome_client.h"
26 #include "chromeos/dbus/dbus_thread_manager.h"
27 #include "chromeos/login/login_state.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/notification_service.h"
30 #include "third_party/cros_system_api/dbus/service_constants.h"
32 using content::BrowserThread;
38 // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN.
39 // Returns the keys unmodified otherwise.
40 scoped_ptr<Key> TransformKeyIfNeeded(const Key& key,
41 const std::string& system_salt) {
42 scoped_ptr<Key> result(new Key(key));
43 if (result->GetKeyType() == Key::KEY_TYPE_PASSWORD_PLAIN)
44 result->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, system_salt);
49 // Records status and calls resolver->Resolve().
50 void TriggerResolve(AuthAttemptState* attempt,
51 scoped_refptr<ParallelAuthenticator> resolver,
53 cryptohome::MountError return_code) {
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
55 attempt->RecordCryptohomeStatus(success, return_code);
59 // Records get hash status and calls resolver->Resolve().
60 void TriggerResolveHash(AuthAttemptState* attempt,
61 scoped_refptr<ParallelAuthenticator> resolver,
63 const std::string& username_hash) {
64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
66 attempt->RecordUsernameHash(username_hash);
68 attempt->RecordUsernameHashFailed();
72 // Calls TriggerResolve while adding login time marker.
73 void TriggerResolveWithLoginTimeMarker(
74 const std::string& marker_name,
75 AuthAttemptState* attempt,
76 scoped_refptr<ParallelAuthenticator> resolver,
78 cryptohome::MountError return_code) {
79 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(marker_name, false);
80 TriggerResolve(attempt, resolver, success, return_code);
83 // Calls cryptohome's mount method.
84 void Mount(AuthAttemptState* attempt,
85 scoped_refptr<ParallelAuthenticator> resolver,
87 const std::string& system_salt) {
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
89 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
90 "CryptohomeMount-Start", false);
91 // Set state that username_hash is requested here so that test implementation
92 // that returns directly would not generate 2 OnLoginSucces() calls.
93 attempt->UsernameHashRequested();
96 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt);
97 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMount(
98 attempt->user_context.GetUserID(),
101 base::Bind(&TriggerResolveWithLoginTimeMarker,
102 "CryptohomeMount-End",
105 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
106 attempt->user_context.GetUserID(),
107 base::Bind(&TriggerResolveHash,
112 // Calls cryptohome's mount method for guest.
113 void MountGuest(AuthAttemptState* attempt,
114 scoped_refptr<ParallelAuthenticator> resolver) {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
116 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest(
117 base::Bind(&TriggerResolveWithLoginTimeMarker,
118 "CryptohomeMount-End",
123 // Calls cryptohome's mount method for guest and also get the user hash from
125 void MountGuestAndGetHash(AuthAttemptState* attempt,
126 scoped_refptr<ParallelAuthenticator> resolver) {
127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
128 attempt->UsernameHashRequested();
129 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest(
130 base::Bind(&TriggerResolveWithLoginTimeMarker,
131 "CryptohomeMount-End",
134 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
135 attempt->user_context.GetUserID(),
136 base::Bind(&TriggerResolveHash,
141 // Calls cryptohome's MountPublic method
142 void MountPublic(AuthAttemptState* attempt,
143 scoped_refptr<ParallelAuthenticator> resolver,
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
146 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountPublic(
147 attempt->user_context.GetUserID(),
149 base::Bind(&TriggerResolveWithLoginTimeMarker,
150 "CryptohomeMountPublic-End",
153 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
154 attempt->user_context.GetUserID(),
155 base::Bind(&TriggerResolveHash,
160 // Calls cryptohome's key migration method.
161 void Migrate(AuthAttemptState* attempt,
162 scoped_refptr<ParallelAuthenticator> resolver,
163 bool passing_old_hash,
164 const std::string& old_password,
165 const std::string& system_salt) {
166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
167 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
168 "CryptohomeMigrate-Start", false);
169 cryptohome::AsyncMethodCaller* caller =
170 cryptohome::AsyncMethodCaller::GetInstance();
172 // TODO(bartfab): Retrieve the hashing algorithm and salt to use for |old_key|
174 scoped_ptr<Key> old_key =
175 TransformKeyIfNeeded(Key(old_password), system_salt);
176 scoped_ptr<Key> new_key =
177 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt);
178 if (passing_old_hash) {
179 caller->AsyncMigrateKey(attempt->user_context.GetUserID(),
180 old_key->GetSecret(),
181 new_key->GetSecret(),
182 base::Bind(&TriggerResolveWithLoginTimeMarker,
183 "CryptohomeMount-End",
187 caller->AsyncMigrateKey(attempt->user_context.GetUserID(),
188 new_key->GetSecret(),
189 old_key->GetSecret(),
190 base::Bind(&TriggerResolveWithLoginTimeMarker,
191 "CryptohomeMount-End",
197 // Calls cryptohome's remove method.
198 void Remove(AuthAttemptState* attempt,
199 scoped_refptr<ParallelAuthenticator> resolver) {
200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
201 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
202 "CryptohomeRemove-Start", false);
203 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
204 attempt->user_context.GetUserID(),
205 base::Bind(&TriggerResolveWithLoginTimeMarker,
206 "CryptohomeRemove-End",
211 // Calls cryptohome's key check method.
212 void CheckKey(AuthAttemptState* attempt,
213 scoped_refptr<ParallelAuthenticator> resolver,
214 const std::string& system_salt) {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
216 scoped_ptr<Key> key =
217 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt);
218 cryptohome::AsyncMethodCaller::GetInstance()->AsyncCheckKey(
219 attempt->user_context.GetUserID(),
221 base::Bind(&TriggerResolve, attempt, resolver));
226 ParallelAuthenticator::ParallelAuthenticator(LoginStatusConsumer* consumer)
227 : Authenticator(consumer),
228 migrate_attempted_(false),
229 remove_attempted_(false),
230 resync_attempted_(false),
231 ephemeral_mount_attempted_(false),
232 check_key_attempted_(false),
233 already_reported_success_(false),
234 owner_is_verified_(false),
235 user_can_login_(false),
236 remove_user_data_on_failure_(false),
237 delayed_login_failure_(NULL) {
240 void ParallelAuthenticator::AuthenticateToLogin(
242 const UserContext& user_context) {
243 authentication_profile_ = profile;
244 current_state_.reset(new AuthAttemptState(
246 User::USER_TYPE_REGULAR,
248 false, // online_complete
249 !UserManager::Get()->IsKnownUser(user_context.GetUserID())));
250 // Reset the verified flag.
251 owner_is_verified_ = false;
253 SystemSaltGetter::Get()->GetSystemSalt(
255 current_state_.get(),
256 scoped_refptr<ParallelAuthenticator>(this),
257 cryptohome::MOUNT_FLAGS_NONE));
260 void ParallelAuthenticator::CompleteLogin(Profile* profile,
261 const UserContext& user_context) {
262 authentication_profile_ = profile;
263 current_state_.reset(new AuthAttemptState(
265 User::USER_TYPE_REGULAR,
267 false, // online_complete
268 !UserManager::Get()->IsKnownUser(user_context.GetUserID())));
270 // Reset the verified flag.
271 owner_is_verified_ = false;
273 SystemSaltGetter::Get()->GetSystemSalt(
275 current_state_.get(),
276 scoped_refptr<ParallelAuthenticator>(this),
277 cryptohome::MOUNT_FLAGS_NONE));
279 // For login completion from extension, we just need to resolve the current
280 // auth attempt state, the rest of OAuth related tasks will be done in
282 BrowserThread::PostTask(
283 BrowserThread::UI, FROM_HERE,
284 base::Bind(&ParallelAuthenticator::ResolveLoginCompletionStatus, this));
287 void ParallelAuthenticator::AuthenticateToUnlock(
288 const UserContext& user_context) {
289 current_state_.reset(new AuthAttemptState(user_context,
290 User::USER_TYPE_REGULAR,
292 true, // online_complete
293 false)); // user_is_new
294 remove_user_data_on_failure_ = false;
295 check_key_attempted_ = true;
296 SystemSaltGetter::Get()->GetSystemSalt(
297 base::Bind(&CheckKey,
298 current_state_.get(),
299 scoped_refptr<ParallelAuthenticator>(this)));
302 void ParallelAuthenticator::LoginAsLocallyManagedUser(
303 const UserContext& user_context) {
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
305 // TODO(nkostylev): Pass proper value for |user_is_new| or remove (not used).
306 current_state_.reset(
307 new AuthAttemptState(user_context,
308 User::USER_TYPE_LOCALLY_MANAGED,
310 false, // online_complete
311 false)); // user_is_new
312 remove_user_data_on_failure_ = false;
313 SystemSaltGetter::Get()->GetSystemSalt(
315 current_state_.get(),
316 scoped_refptr<ParallelAuthenticator>(this),
317 cryptohome::MOUNT_FLAGS_NONE));
320 void ParallelAuthenticator::LoginRetailMode() {
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
322 // Note: |kRetailModeUserEMail| is used in other places to identify a retail
324 current_state_.reset(new AuthAttemptState(
325 UserContext(UserManager::kRetailModeUserName),
326 User::USER_TYPE_RETAIL_MODE,
328 false, // online_complete
329 false)); // user_is_new
330 remove_user_data_on_failure_ = false;
331 ephemeral_mount_attempted_ = true;
332 MountGuestAndGetHash(current_state_.get(),
333 scoped_refptr<ParallelAuthenticator>(this));
336 void ParallelAuthenticator::LoginOffTheRecord() {
337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
338 current_state_.reset(new AuthAttemptState(
339 UserContext(UserManager::kGuestUserName),
340 User::USER_TYPE_GUEST,
342 false, // online_complete
343 false)); // user_is_new
344 remove_user_data_on_failure_ = false;
345 ephemeral_mount_attempted_ = true;
346 MountGuest(current_state_.get(),
347 scoped_refptr<ParallelAuthenticator>(this));
350 void ParallelAuthenticator::LoginAsPublicAccount(const std::string& username) {
351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
352 current_state_.reset(new AuthAttemptState(UserContext(username),
353 User::USER_TYPE_PUBLIC_ACCOUNT,
355 false, // online_complete
356 false)); // user_is_new
357 remove_user_data_on_failure_ = false;
358 ephemeral_mount_attempted_ = true;
359 SystemSaltGetter::Get()->GetSystemSalt(
361 current_state_.get(),
362 scoped_refptr<ParallelAuthenticator>(this),
363 cryptohome::CREATE_IF_MISSING | cryptohome::ENSURE_EPHEMERAL));
366 void ParallelAuthenticator::LoginAsKioskAccount(
367 const std::string& app_user_id,
368 bool use_guest_mount) {
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
371 const std::string user_id =
372 use_guest_mount ? UserManager::kGuestUserName : app_user_id;
373 current_state_.reset(new AuthAttemptState(UserContext(user_id),
374 User::USER_TYPE_KIOSK_APP,
376 false, // online_complete
377 false)); // user_is_new
379 remove_user_data_on_failure_ = true;
380 if (!use_guest_mount) {
381 MountPublic(current_state_.get(),
382 scoped_refptr<ParallelAuthenticator>(this),
383 cryptohome::CREATE_IF_MISSING);
385 ephemeral_mount_attempted_ = true;
386 MountGuestAndGetHash(current_state_.get(),
387 scoped_refptr<ParallelAuthenticator>(this));
391 void ParallelAuthenticator::OnRetailModeLoginSuccess() {
392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
393 VLOG(1) << "Retail mode login success";
394 // Send notification of success
395 AuthenticationNotificationDetails details(true);
396 content::NotificationService::current()->Notify(
397 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
398 content::NotificationService::AllSources(),
399 content::Details<AuthenticationNotificationDetails>(&details));
401 consumer_->OnRetailModeLoginSuccess(current_state_->user_context);
404 void ParallelAuthenticator::OnLoginSuccess() {
405 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
406 VLOG(1) << "Login success";
407 // Send notification of success
408 AuthenticationNotificationDetails details(true);
409 content::NotificationService::current()->Notify(
410 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
411 content::NotificationService::AllSources(),
412 content::Details<AuthenticationNotificationDetails>(&details));
414 base::AutoLock for_this_block(success_lock_);
415 already_reported_success_ = true;
418 consumer_->OnLoginSuccess(current_state_->user_context);
421 void ParallelAuthenticator::OnOffTheRecordLoginSuccess() {
422 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
423 // Send notification of success
424 AuthenticationNotificationDetails details(true);
425 content::NotificationService::current()->Notify(
426 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
427 content::NotificationService::AllSources(),
428 content::Details<AuthenticationNotificationDetails>(&details));
430 consumer_->OnOffTheRecordLoginSuccess();
433 void ParallelAuthenticator::OnPasswordChangeDetected() {
434 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
436 consumer_->OnPasswordChangeDetected();
439 void ParallelAuthenticator::OnLoginFailure(const LoginFailure& error) {
440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
442 // OnLoginFailure will be called again with the same |error|
443 // after the cryptohome has been removed.
444 if (remove_user_data_on_failure_) {
445 delayed_login_failure_ = &error;
446 RemoveEncryptedData();
450 // Send notification of failure
451 AuthenticationNotificationDetails details(false);
452 content::NotificationService::current()->Notify(
453 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
454 content::NotificationService::AllSources(),
455 content::Details<AuthenticationNotificationDetails>(&details));
456 LOG(WARNING) << "Login failed: " << error.GetErrorString();
458 consumer_->OnLoginFailure(error);
461 void ParallelAuthenticator::RecoverEncryptedData(
462 const std::string& old_password) {
463 migrate_attempted_ = true;
464 current_state_->ResetCryptohomeStatus();
465 SystemSaltGetter::Get()->GetSystemSalt(
467 current_state_.get(),
468 scoped_refptr<ParallelAuthenticator>(this),
473 void ParallelAuthenticator::RemoveEncryptedData() {
474 remove_attempted_ = true;
475 current_state_->ResetCryptohomeStatus();
476 BrowserThread::PostTask(
477 BrowserThread::UI, FROM_HERE,
479 current_state_.get(),
480 scoped_refptr<ParallelAuthenticator>(this)));
483 void ParallelAuthenticator::ResyncEncryptedData() {
484 resync_attempted_ = true;
485 current_state_->ResetCryptohomeStatus();
486 BrowserThread::PostTask(
487 BrowserThread::UI, FROM_HERE,
489 current_state_.get(),
490 scoped_refptr<ParallelAuthenticator>(this)));
493 bool ParallelAuthenticator::VerifyOwner() {
494 if (owner_is_verified_)
496 // Check if policy data is fine and continue in safe mode if needed.
497 bool is_safe_mode = false;
498 CrosSettings::Get()->GetBoolean(kPolicyMissingMitigationMode, &is_safe_mode);
500 // Now we can continue with the login and report mount success.
501 user_can_login_ = true;
502 owner_is_verified_ = true;
506 const std::string& user_id = current_state_->user_context.GetUserID();
507 OwnerSettingsServiceFactory::GetInstance()->SetUsername(user_id);
509 // This should trigger certificate loading, which is needed in order to
510 // correctly determine if the current user is the owner.
511 if (LoginState::IsInitialized()) {
512 LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_SAFE_MODE,
513 LoginState::LOGGED_IN_USER_NONE);
516 OwnerSettingsService::IsPrivateKeyExistAsync(
517 base::Bind(&ParallelAuthenticator::OnOwnershipChecked, this));
521 void ParallelAuthenticator::OnOwnershipChecked(bool is_owner) {
522 // Now we can check if this user is the owner.
523 user_can_login_ = is_owner;
524 owner_is_verified_ = true;
528 void ParallelAuthenticator::Resolve() {
529 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
530 int mount_flags = cryptohome::MOUNT_FLAGS_NONE;
531 ParallelAuthenticator::AuthState state = ResolveState();
532 VLOG(1) << "Resolved state to: " << state;
535 case POSSIBLE_PW_CHANGE:
537 // These are intermediate states; we need more info from a request that
541 // In this case, whether login succeeded or not, we can't log
542 // the user in because their data is horked. So, override with
543 // the appropriate failure.
544 BrowserThread::PostTask(
545 BrowserThread::UI, FROM_HERE,
546 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
547 LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME)));
550 // In this case, we tried to remove the user's old cryptohome at her
551 // request, and the remove failed.
552 remove_user_data_on_failure_ = false;
553 BrowserThread::PostTask(
554 BrowserThread::UI, FROM_HERE,
555 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
556 LoginFailure(LoginFailure::DATA_REMOVAL_FAILED)));
559 // In this case, we tried to mount a tmpfs for guest and failed.
560 BrowserThread::PostTask(
561 BrowserThread::UI, FROM_HERE,
562 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
563 LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)));
566 // In this case, we tried to create/mount cryptohome and failed
567 // because of the critical TPM error.
568 // Chrome will notify user and request reboot.
569 BrowserThread::PostTask(
570 BrowserThread::UI, FROM_HERE,
571 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
572 LoginFailure(LoginFailure::TPM_ERROR)));
574 case FAILED_USERNAME_HASH:
575 // In this case, we failed the GetSanitizedUsername request to
576 // cryptohomed. This can happen for any login attempt.
577 BrowserThread::PostTask(
578 BrowserThread::UI, FROM_HERE,
579 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
580 LoginFailure(LoginFailure::USERNAME_HASH_FAILED)));
582 case REMOVED_DATA_AFTER_FAILURE:
583 remove_user_data_on_failure_ = false;
584 BrowserThread::PostTask(
585 BrowserThread::UI, FROM_HERE,
586 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
587 *delayed_login_failure_));
590 mount_flags |= cryptohome::CREATE_IF_MISSING;
592 current_state_->ResetCryptohomeStatus();
593 SystemSaltGetter::Get()->GetSystemSalt(
595 current_state_.get(),
596 scoped_refptr<ParallelAuthenticator>(this),
600 BrowserThread::PostTask(
601 BrowserThread::UI, FROM_HERE,
602 base::Bind(&ParallelAuthenticator::OnPasswordChangeDetected, this));
607 NOTREACHED() << "Using obsolete ClientLogin code path.";
610 VLOG(2) << "Offline login";
616 VLOG(2) << "Online login";
617 BrowserThread::PostTask(
618 BrowserThread::UI, FROM_HERE,
619 base::Bind(&ParallelAuthenticator::OnLoginSuccess, this));
622 VLOG(2) << "Retail mode login";
623 current_state_->user_context.SetIsUsingOAuth(false);
624 BrowserThread::PostTask(
625 BrowserThread::UI, FROM_HERE,
626 base::Bind(&ParallelAuthenticator::OnRetailModeLoginSuccess, this));
629 BrowserThread::PostTask(
630 BrowserThread::UI, FROM_HERE,
631 base::Bind(&ParallelAuthenticator::OnOffTheRecordLoginSuccess, this));
633 case KIOSK_ACCOUNT_LOGIN:
634 case PUBLIC_ACCOUNT_LOGIN:
635 current_state_->user_context.SetIsUsingOAuth(false);
636 BrowserThread::PostTask(
637 BrowserThread::UI, FROM_HERE,
638 base::Bind(&ParallelAuthenticator::OnLoginSuccess, this));
640 case LOCALLY_MANAGED_USER_LOGIN:
641 current_state_->user_context.SetIsUsingOAuth(false);
642 BrowserThread::PostTask(
643 BrowserThread::UI, FROM_HERE,
644 base::Bind(&ParallelAuthenticator::OnLoginSuccess, this));
647 current_state_->ResetCryptohomeStatus();
648 BrowserThread::PostTask(BrowserThread::UI,
651 &ParallelAuthenticator::OnLoginFailure,
653 current_state_->online_outcome()));
655 case OWNER_REQUIRED: {
656 current_state_->ResetCryptohomeStatus();
657 bool success = false;
658 DBusThreadManager::Get()->GetCryptohomeClient()->Unmount(&success);
660 // Maybe we should reboot immediately here?
661 LOG(ERROR) << "Couldn't unmount users home!";
663 BrowserThread::PostTask(BrowserThread::UI,
666 &ParallelAuthenticator::OnLoginFailure,
668 LoginFailure(LoginFailure::OWNER_REQUIRED)));
677 ParallelAuthenticator::~ParallelAuthenticator() {}
679 ParallelAuthenticator::AuthState ParallelAuthenticator::ResolveState() {
680 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
681 // If we haven't mounted the user's home dir yet or
682 // haven't got sanitized username value, we can't be done.
683 // We never get past here if any of these two cryptohome ops is still pending.
684 // This is an important invariant.
685 if (!current_state_->cryptohome_complete() ||
686 !current_state_->username_hash_obtained()) {
690 AuthState state = CONTINUE;
692 if (current_state_->cryptohome_outcome() &&
693 current_state_->username_hash_valid()) {
694 state = ResolveCryptohomeSuccessState();
696 state = ResolveCryptohomeFailureState();
699 DCHECK(current_state_->cryptohome_complete()); // Ensure invariant holds.
700 migrate_attempted_ = false;
701 remove_attempted_ = false;
702 resync_attempted_ = false;
703 ephemeral_mount_attempted_ = false;
704 check_key_attempted_ = false;
706 if (state != POSSIBLE_PW_CHANGE &&
708 state != OFFLINE_LOGIN)
711 if (current_state_->online_complete()) {
712 if (current_state_->online_outcome().reason() == LoginFailure::NONE) {
713 // Online attempt succeeded as well, so combine the results.
714 return ResolveOnlineSuccessState(state);
716 NOTREACHED() << "Using obsolete ClientLogin code path.";
718 // if online isn't complete yet, just return the offline result.
722 ParallelAuthenticator::AuthState
723 ParallelAuthenticator::ResolveCryptohomeFailureState() {
724 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
725 if (remove_attempted_ || resync_attempted_)
726 return FAILED_REMOVE;
727 if (ephemeral_mount_attempted_)
729 if (migrate_attempted_)
731 if (check_key_attempted_)
734 if (current_state_->cryptohome_code() ==
735 cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
736 // Critical TPM error detected, reboot needed.
740 // Return intermediate states in the following case:
741 // when there is an online result to use;
742 // This is the case after user finishes Gaia login;
743 if (current_state_->online_complete()) {
744 if (current_state_->cryptohome_code() ==
745 cryptohome::MOUNT_ERROR_KEY_FAILURE) {
746 // If we tried a mount but they used the wrong key, we may need to
747 // ask the user for her old password. We'll only know once we've
748 // done the online check.
749 return POSSIBLE_PW_CHANGE;
751 if (current_state_->cryptohome_code() ==
752 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) {
753 // If we tried a mount but the user did not exist, then we should wait
754 // for online login to succeed and try again with the "create" flag set.
759 if (!current_state_->username_hash_valid())
760 return FAILED_USERNAME_HASH;
765 ParallelAuthenticator::AuthState
766 ParallelAuthenticator::ResolveCryptohomeSuccessState() {
767 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
768 if (resync_attempted_)
770 if (remove_attempted_)
771 return REMOVED_DATA_AFTER_FAILURE;
772 if (migrate_attempted_)
773 return RECOVER_MOUNT;
774 if (check_key_attempted_)
777 if (current_state_->user_type == User::USER_TYPE_GUEST)
779 if (current_state_->user_type == User::USER_TYPE_RETAIL_MODE)
781 if (current_state_->user_type == User::USER_TYPE_PUBLIC_ACCOUNT)
782 return PUBLIC_ACCOUNT_LOGIN;
783 if (current_state_->user_type == User::USER_TYPE_KIOSK_APP)
784 return KIOSK_ACCOUNT_LOGIN;
785 if (current_state_->user_type == User::USER_TYPE_LOCALLY_MANAGED)
786 return LOCALLY_MANAGED_USER_LOGIN;
790 return user_can_login_ ? OFFLINE_LOGIN : OWNER_REQUIRED;
793 ParallelAuthenticator::AuthState
794 ParallelAuthenticator::ResolveOnlineSuccessState(
795 ParallelAuthenticator::AuthState offline_state) {
796 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
797 switch (offline_state) {
798 case POSSIBLE_PW_CHANGE:
806 return offline_state;
810 void ParallelAuthenticator::ResolveLoginCompletionStatus() {
811 // Shortcut online state resolution process.
812 current_state_->RecordOnlineLoginStatus(LoginFailure::LoginFailureNone());
816 void ParallelAuthenticator::SetOwnerState(bool owner_check_finished,
818 owner_is_verified_ = owner_check_finished;
819 user_can_login_ = check_result;
822 } // namespace chromeos