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/ownership/owner_settings_service.h"
15 #include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
16 #include "chrome/browser/chromeos/settings/cros_settings.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chromeos/cryptohome/async_method_caller.h"
19 #include "chromeos/cryptohome/system_salt_getter.h"
20 #include "chromeos/dbus/cryptohome_client.h"
21 #include "chromeos/dbus/dbus_thread_manager.h"
22 #include "chromeos/login/auth/auth_status_consumer.h"
23 #include "chromeos/login/auth/key.h"
24 #include "chromeos/login/auth/user_context.h"
25 #include "chromeos/login/login_state.h"
26 #include "chromeos/login/user_names.h"
27 #include "components/user_manager/user_manager.h"
28 #include "components/user_manager/user_type.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/notification_service.h"
31 #include "third_party/cros_system_api/dbus/service_constants.h"
33 using content::BrowserThread;
39 // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN.
40 // Returns the keys unmodified otherwise.
41 scoped_ptr<Key> TransformKeyIfNeeded(const Key& key,
42 const std::string& system_salt) {
43 scoped_ptr<Key> result(new Key(key));
44 if (result->GetKeyType() == Key::KEY_TYPE_PASSWORD_PLAIN)
45 result->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, system_salt);
50 // Records status and calls resolver->Resolve().
51 void TriggerResolve(AuthAttemptState* attempt,
52 scoped_refptr<ParallelAuthenticator> resolver,
54 cryptohome::MountError return_code) {
55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
56 attempt->RecordCryptohomeStatus(success, return_code);
60 // Records get hash status and calls resolver->Resolve().
61 void TriggerResolveHash(AuthAttemptState* attempt,
62 scoped_refptr<ParallelAuthenticator> resolver,
64 const std::string& username_hash) {
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
67 attempt->RecordUsernameHash(username_hash);
69 attempt->RecordUsernameHashFailed();
73 // Calls TriggerResolve while adding login time marker.
74 void TriggerResolveWithLoginTimeMarker(
75 const std::string& marker_name,
76 AuthAttemptState* attempt,
77 scoped_refptr<ParallelAuthenticator> resolver,
79 cryptohome::MountError return_code) {
80 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(marker_name, false);
81 TriggerResolve(attempt, resolver, success, return_code);
84 // Calls cryptohome's mount method.
85 void Mount(AuthAttemptState* attempt,
86 scoped_refptr<ParallelAuthenticator> resolver,
88 const std::string& system_salt) {
89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
90 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
91 "CryptohomeMount-Start", false);
92 // Set state that username_hash is requested here so that test implementation
93 // that returns directly would not generate 2 OnLoginSucces() calls.
94 attempt->UsernameHashRequested();
97 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt);
98 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMount(
99 attempt->user_context.GetUserID(),
102 base::Bind(&TriggerResolveWithLoginTimeMarker,
103 "CryptohomeMount-End",
106 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
107 attempt->user_context.GetUserID(),
108 base::Bind(&TriggerResolveHash,
113 // Calls cryptohome's mount method for guest.
114 void MountGuest(AuthAttemptState* attempt,
115 scoped_refptr<ParallelAuthenticator> resolver) {
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
117 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest(
118 base::Bind(&TriggerResolveWithLoginTimeMarker,
119 "CryptohomeMount-End",
124 // Calls cryptohome's mount method for guest and also get the user hash from
126 void MountGuestAndGetHash(AuthAttemptState* attempt,
127 scoped_refptr<ParallelAuthenticator> resolver) {
128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
129 attempt->UsernameHashRequested();
130 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest(
131 base::Bind(&TriggerResolveWithLoginTimeMarker,
132 "CryptohomeMount-End",
135 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
136 attempt->user_context.GetUserID(),
137 base::Bind(&TriggerResolveHash,
142 // Calls cryptohome's MountPublic method
143 void MountPublic(AuthAttemptState* attempt,
144 scoped_refptr<ParallelAuthenticator> resolver,
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
147 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountPublic(
148 attempt->user_context.GetUserID(),
150 base::Bind(&TriggerResolveWithLoginTimeMarker,
151 "CryptohomeMountPublic-End",
154 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
155 attempt->user_context.GetUserID(),
156 base::Bind(&TriggerResolveHash,
161 // Calls cryptohome's key migration method.
162 void Migrate(AuthAttemptState* attempt,
163 scoped_refptr<ParallelAuthenticator> resolver,
164 bool passing_old_hash,
165 const std::string& old_password,
166 const std::string& system_salt) {
167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
169 "CryptohomeMigrate-Start", false);
170 cryptohome::AsyncMethodCaller* caller =
171 cryptohome::AsyncMethodCaller::GetInstance();
173 // TODO(bartfab): Retrieve the hashing algorithm and salt to use for |old_key|
175 scoped_ptr<Key> old_key =
176 TransformKeyIfNeeded(Key(old_password), system_salt);
177 scoped_ptr<Key> new_key =
178 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt);
179 if (passing_old_hash) {
180 caller->AsyncMigrateKey(attempt->user_context.GetUserID(),
181 old_key->GetSecret(),
182 new_key->GetSecret(),
183 base::Bind(&TriggerResolveWithLoginTimeMarker,
184 "CryptohomeMount-End",
188 caller->AsyncMigrateKey(attempt->user_context.GetUserID(),
189 new_key->GetSecret(),
190 old_key->GetSecret(),
191 base::Bind(&TriggerResolveWithLoginTimeMarker,
192 "CryptohomeMount-End",
198 // Calls cryptohome's remove method.
199 void Remove(AuthAttemptState* attempt,
200 scoped_refptr<ParallelAuthenticator> resolver) {
201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
202 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
203 "CryptohomeRemove-Start", false);
204 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
205 attempt->user_context.GetUserID(),
206 base::Bind(&TriggerResolveWithLoginTimeMarker,
207 "CryptohomeRemove-End",
212 // Calls cryptohome's key check method.
213 void CheckKey(AuthAttemptState* attempt,
214 scoped_refptr<ParallelAuthenticator> resolver,
215 const std::string& system_salt) {
216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
217 scoped_ptr<Key> key =
218 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt);
219 cryptohome::AsyncMethodCaller::GetInstance()->AsyncCheckKey(
220 attempt->user_context.GetUserID(),
222 base::Bind(&TriggerResolve, attempt, resolver));
227 ParallelAuthenticator::ParallelAuthenticator(AuthStatusConsumer* consumer)
228 : Authenticator(consumer),
229 migrate_attempted_(false),
230 remove_attempted_(false),
231 resync_attempted_(false),
232 ephemeral_mount_attempted_(false),
233 check_key_attempted_(false),
234 already_reported_success_(false),
235 owner_is_verified_(false),
236 user_can_login_(false),
237 remove_user_data_on_failure_(false),
238 delayed_login_failure_(NULL) {
241 void ParallelAuthenticator::AuthenticateToLogin(
243 const UserContext& user_context) {
244 authentication_profile_ = profile;
245 current_state_.reset(
246 new AuthAttemptState(user_context,
247 user_manager::USER_TYPE_REGULAR,
249 false, // online_complete
250 !user_manager::UserManager::Get()->IsKnownUser(
251 user_context.GetUserID())));
252 // Reset the verified flag.
253 owner_is_verified_ = false;
255 SystemSaltGetter::Get()->GetSystemSalt(
257 current_state_.get(),
258 scoped_refptr<ParallelAuthenticator>(this),
259 cryptohome::MOUNT_FLAGS_NONE));
262 void ParallelAuthenticator::CompleteLogin(Profile* profile,
263 const UserContext& user_context) {
264 authentication_profile_ = profile;
265 current_state_.reset(
266 new AuthAttemptState(user_context,
267 user_manager::USER_TYPE_REGULAR,
269 false, // online_complete
270 !user_manager::UserManager::Get()->IsKnownUser(
271 user_context.GetUserID())));
273 // Reset the verified flag.
274 owner_is_verified_ = false;
276 SystemSaltGetter::Get()->GetSystemSalt(
278 current_state_.get(),
279 scoped_refptr<ParallelAuthenticator>(this),
280 cryptohome::MOUNT_FLAGS_NONE));
282 // For login completion from extension, we just need to resolve the current
283 // auth attempt state, the rest of OAuth related tasks will be done in
285 BrowserThread::PostTask(
286 BrowserThread::UI, FROM_HERE,
287 base::Bind(&ParallelAuthenticator::ResolveLoginCompletionStatus, this));
290 void ParallelAuthenticator::AuthenticateToUnlock(
291 const UserContext& user_context) {
292 current_state_.reset(new AuthAttemptState(user_context,
293 user_manager::USER_TYPE_REGULAR,
295 true, // online_complete
296 false)); // user_is_new
297 remove_user_data_on_failure_ = false;
298 check_key_attempted_ = true;
299 SystemSaltGetter::Get()->GetSystemSalt(
300 base::Bind(&CheckKey,
301 current_state_.get(),
302 scoped_refptr<ParallelAuthenticator>(this)));
305 void ParallelAuthenticator::LoginAsSupervisedUser(
306 const UserContext& user_context) {
307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
308 // TODO(nkostylev): Pass proper value for |user_is_new| or remove (not used).
309 current_state_.reset(
310 new AuthAttemptState(user_context,
311 user_manager::USER_TYPE_SUPERVISED,
313 false, // online_complete
314 false)); // user_is_new
315 remove_user_data_on_failure_ = false;
316 SystemSaltGetter::Get()->GetSystemSalt(
318 current_state_.get(),
319 scoped_refptr<ParallelAuthenticator>(this),
320 cryptohome::MOUNT_FLAGS_NONE));
323 void ParallelAuthenticator::LoginRetailMode() {
324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
325 // Note: |kRetailModeUserEMail| is used in other places to identify a retail
327 current_state_.reset(
328 new AuthAttemptState(UserContext(chromeos::login::kRetailModeUserName),
329 user_manager::USER_TYPE_RETAIL_MODE,
331 false, // online_complete
332 false)); // user_is_new
333 remove_user_data_on_failure_ = false;
334 ephemeral_mount_attempted_ = true;
335 MountGuestAndGetHash(current_state_.get(),
336 scoped_refptr<ParallelAuthenticator>(this));
339 void ParallelAuthenticator::LoginOffTheRecord() {
340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
341 current_state_.reset(
342 new AuthAttemptState(UserContext(chromeos::login::kGuestUserName),
343 user_manager::USER_TYPE_GUEST,
345 false, // online_complete
346 false)); // user_is_new
347 remove_user_data_on_failure_ = false;
348 ephemeral_mount_attempted_ = true;
349 MountGuest(current_state_.get(),
350 scoped_refptr<ParallelAuthenticator>(this));
353 void ParallelAuthenticator::LoginAsPublicSession(
354 const UserContext& user_context) {
355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
356 current_state_.reset(
357 new AuthAttemptState(user_context,
358 user_manager::USER_TYPE_PUBLIC_ACCOUNT,
360 false, // online_complete
361 false)); // user_is_new
362 remove_user_data_on_failure_ = false;
363 ephemeral_mount_attempted_ = true;
364 SystemSaltGetter::Get()->GetSystemSalt(
366 current_state_.get(),
367 scoped_refptr<ParallelAuthenticator>(this),
368 cryptohome::CREATE_IF_MISSING | cryptohome::ENSURE_EPHEMERAL));
371 void ParallelAuthenticator::LoginAsKioskAccount(
372 const std::string& app_user_id,
373 bool use_guest_mount) {
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
376 const std::string user_id =
377 use_guest_mount ? chromeos::login::kGuestUserName : app_user_id;
378 current_state_.reset(new AuthAttemptState(UserContext(user_id),
379 user_manager::USER_TYPE_KIOSK_APP,
381 false, // online_complete
382 false)); // user_is_new
384 remove_user_data_on_failure_ = true;
385 if (!use_guest_mount) {
386 MountPublic(current_state_.get(),
387 scoped_refptr<ParallelAuthenticator>(this),
388 cryptohome::CREATE_IF_MISSING);
390 ephemeral_mount_attempted_ = true;
391 MountGuestAndGetHash(current_state_.get(),
392 scoped_refptr<ParallelAuthenticator>(this));
396 void ParallelAuthenticator::OnRetailModeAuthSuccess() {
397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
398 VLOG(1) << "Retail mode login success";
399 // Send notification of success
400 AuthenticationNotificationDetails details(true);
401 content::NotificationService::current()->Notify(
402 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
403 content::NotificationService::AllSources(),
404 content::Details<AuthenticationNotificationDetails>(&details));
406 consumer_->OnRetailModeAuthSuccess(current_state_->user_context);
409 void ParallelAuthenticator::OnAuthSuccess() {
410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
411 VLOG(1) << "Login success";
412 // Send notification of success
413 AuthenticationNotificationDetails details(true);
414 content::NotificationService::current()->Notify(
415 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
416 content::NotificationService::AllSources(),
417 content::Details<AuthenticationNotificationDetails>(&details));
419 base::AutoLock for_this_block(success_lock_);
420 already_reported_success_ = true;
423 consumer_->OnAuthSuccess(current_state_->user_context);
426 void ParallelAuthenticator::OnOffTheRecordAuthSuccess() {
427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
428 // Send notification of success
429 AuthenticationNotificationDetails details(true);
430 content::NotificationService::current()->Notify(
431 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
432 content::NotificationService::AllSources(),
433 content::Details<AuthenticationNotificationDetails>(&details));
435 consumer_->OnOffTheRecordAuthSuccess();
438 void ParallelAuthenticator::OnPasswordChangeDetected() {
439 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
441 consumer_->OnPasswordChangeDetected();
444 void ParallelAuthenticator::OnAuthFailure(const AuthFailure& error) {
445 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
447 // OnAuthFailure will be called again with the same |error|
448 // after the cryptohome has been removed.
449 if (remove_user_data_on_failure_) {
450 delayed_login_failure_ = &error;
451 RemoveEncryptedData();
455 // Send notification of failure
456 AuthenticationNotificationDetails details(false);
457 content::NotificationService::current()->Notify(
458 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
459 content::NotificationService::AllSources(),
460 content::Details<AuthenticationNotificationDetails>(&details));
461 LOG(WARNING) << "Login failed: " << error.GetErrorString();
463 consumer_->OnAuthFailure(error);
466 void ParallelAuthenticator::RecoverEncryptedData(
467 const std::string& old_password) {
468 migrate_attempted_ = true;
469 current_state_->ResetCryptohomeStatus();
470 SystemSaltGetter::Get()->GetSystemSalt(
472 current_state_.get(),
473 scoped_refptr<ParallelAuthenticator>(this),
478 void ParallelAuthenticator::RemoveEncryptedData() {
479 remove_attempted_ = true;
480 current_state_->ResetCryptohomeStatus();
481 BrowserThread::PostTask(
482 BrowserThread::UI, FROM_HERE,
484 current_state_.get(),
485 scoped_refptr<ParallelAuthenticator>(this)));
488 void ParallelAuthenticator::ResyncEncryptedData() {
489 resync_attempted_ = true;
490 current_state_->ResetCryptohomeStatus();
491 BrowserThread::PostTask(
492 BrowserThread::UI, FROM_HERE,
494 current_state_.get(),
495 scoped_refptr<ParallelAuthenticator>(this)));
498 bool ParallelAuthenticator::VerifyOwner() {
499 if (owner_is_verified_)
501 // Check if policy data is fine and continue in safe mode if needed.
502 bool is_safe_mode = false;
503 CrosSettings::Get()->GetBoolean(kPolicyMissingMitigationMode, &is_safe_mode);
505 // Now we can continue with the login and report mount success.
506 user_can_login_ = true;
507 owner_is_verified_ = true;
511 const std::string& user_id = current_state_->user_context.GetUserID();
512 OwnerSettingsServiceFactory::GetInstance()->SetUsername(user_id);
514 // |IsOwnerForSafeModeAsync| expects logged in state to be
515 // LOGGED_IN_SAFE_MODE.
516 if (LoginState::IsInitialized()) {
517 LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_SAFE_MODE,
518 LoginState::LOGGED_IN_USER_NONE);
521 OwnerSettingsService::IsOwnerForSafeModeAsync(
523 current_state_->user_context.GetUserIDHash(),
524 base::Bind(&ParallelAuthenticator::OnOwnershipChecked, this));
528 void ParallelAuthenticator::OnOwnershipChecked(bool is_owner) {
529 // Now we can check if this user is the owner.
530 user_can_login_ = is_owner;
531 owner_is_verified_ = true;
535 void ParallelAuthenticator::Resolve() {
536 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
537 int mount_flags = cryptohome::MOUNT_FLAGS_NONE;
538 ParallelAuthenticator::AuthState state = ResolveState();
539 VLOG(1) << "Resolved state to: " << state;
542 case POSSIBLE_PW_CHANGE:
544 // These are intermediate states; we need more info from a request that
548 // In this case, whether login succeeded or not, we can't log
549 // the user in because their data is horked. So, override with
550 // the appropriate failure.
551 BrowserThread::PostTask(
554 base::Bind(&ParallelAuthenticator::OnAuthFailure,
556 AuthFailure(AuthFailure::COULD_NOT_MOUNT_CRYPTOHOME)));
559 // In this case, we tried to remove the user's old cryptohome at her
560 // request, and the remove failed.
561 remove_user_data_on_failure_ = false;
562 BrowserThread::PostTask(
565 base::Bind(&ParallelAuthenticator::OnAuthFailure,
567 AuthFailure(AuthFailure::DATA_REMOVAL_FAILED)));
570 // In this case, we tried to mount a tmpfs for guest and failed.
571 BrowserThread::PostTask(
574 base::Bind(&ParallelAuthenticator::OnAuthFailure,
576 AuthFailure(AuthFailure::COULD_NOT_MOUNT_TMPFS)));
579 // In this case, we tried to create/mount cryptohome and failed
580 // because of the critical TPM error.
581 // Chrome will notify user and request reboot.
582 BrowserThread::PostTask(BrowserThread::UI,
584 base::Bind(&ParallelAuthenticator::OnAuthFailure,
586 AuthFailure(AuthFailure::TPM_ERROR)));
588 case FAILED_USERNAME_HASH:
589 // In this case, we failed the GetSanitizedUsername request to
590 // cryptohomed. This can happen for any login attempt.
591 BrowserThread::PostTask(
594 base::Bind(&ParallelAuthenticator::OnAuthFailure,
596 AuthFailure(AuthFailure::USERNAME_HASH_FAILED)));
598 case REMOVED_DATA_AFTER_FAILURE:
599 remove_user_data_on_failure_ = false;
600 BrowserThread::PostTask(BrowserThread::UI,
602 base::Bind(&ParallelAuthenticator::OnAuthFailure,
604 *delayed_login_failure_));
607 mount_flags |= cryptohome::CREATE_IF_MISSING;
609 current_state_->ResetCryptohomeStatus();
610 SystemSaltGetter::Get()->GetSystemSalt(
612 current_state_.get(),
613 scoped_refptr<ParallelAuthenticator>(this),
617 BrowserThread::PostTask(
618 BrowserThread::UI, FROM_HERE,
619 base::Bind(&ParallelAuthenticator::OnPasswordChangeDetected, this));
624 NOTREACHED() << "Using obsolete ClientLogin code path.";
627 VLOG(2) << "Offline login";
633 VLOG(2) << "Online login";
634 BrowserThread::PostTask(
637 base::Bind(&ParallelAuthenticator::OnAuthSuccess, this));
640 VLOG(2) << "Retail mode login";
641 current_state_->user_context.SetIsUsingOAuth(false);
642 BrowserThread::PostTask(
645 base::Bind(&ParallelAuthenticator::OnRetailModeAuthSuccess, this));
648 BrowserThread::PostTask(
651 base::Bind(&ParallelAuthenticator::OnOffTheRecordAuthSuccess, this));
653 case KIOSK_ACCOUNT_LOGIN:
654 case PUBLIC_ACCOUNT_LOGIN:
655 current_state_->user_context.SetIsUsingOAuth(false);
656 BrowserThread::PostTask(
659 base::Bind(&ParallelAuthenticator::OnAuthSuccess, this));
661 case SUPERVISED_USER_LOGIN:
662 current_state_->user_context.SetIsUsingOAuth(false);
663 BrowserThread::PostTask(
666 base::Bind(&ParallelAuthenticator::OnAuthSuccess, this));
669 current_state_->ResetCryptohomeStatus();
670 BrowserThread::PostTask(BrowserThread::UI,
672 base::Bind(&ParallelAuthenticator::OnAuthFailure,
674 current_state_->online_outcome()));
676 case OWNER_REQUIRED: {
677 current_state_->ResetCryptohomeStatus();
678 bool success = false;
679 DBusThreadManager::Get()->GetCryptohomeClient()->Unmount(&success);
681 // Maybe we should reboot immediately here?
682 LOG(ERROR) << "Couldn't unmount users home!";
684 BrowserThread::PostTask(
687 base::Bind(&ParallelAuthenticator::OnAuthFailure,
689 AuthFailure(AuthFailure::OWNER_REQUIRED)));
698 ParallelAuthenticator::~ParallelAuthenticator() {}
700 ParallelAuthenticator::AuthState ParallelAuthenticator::ResolveState() {
701 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
702 // If we haven't mounted the user's home dir yet or
703 // haven't got sanitized username value, we can't be done.
704 // We never get past here if any of these two cryptohome ops is still pending.
705 // This is an important invariant.
706 if (!current_state_->cryptohome_complete() ||
707 !current_state_->username_hash_obtained()) {
711 AuthState state = CONTINUE;
713 if (current_state_->cryptohome_outcome() &&
714 current_state_->username_hash_valid()) {
715 state = ResolveCryptohomeSuccessState();
717 state = ResolveCryptohomeFailureState();
720 DCHECK(current_state_->cryptohome_complete()); // Ensure invariant holds.
721 migrate_attempted_ = false;
722 remove_attempted_ = false;
723 resync_attempted_ = false;
724 ephemeral_mount_attempted_ = false;
725 check_key_attempted_ = false;
727 if (state != POSSIBLE_PW_CHANGE &&
729 state != OFFLINE_LOGIN)
732 if (current_state_->online_complete()) {
733 if (current_state_->online_outcome().reason() == AuthFailure::NONE) {
734 // Online attempt succeeded as well, so combine the results.
735 return ResolveOnlineSuccessState(state);
737 NOTREACHED() << "Using obsolete ClientLogin code path.";
739 // if online isn't complete yet, just return the offline result.
743 ParallelAuthenticator::AuthState
744 ParallelAuthenticator::ResolveCryptohomeFailureState() {
745 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
746 if (remove_attempted_ || resync_attempted_)
747 return FAILED_REMOVE;
748 if (ephemeral_mount_attempted_)
750 if (migrate_attempted_)
752 if (check_key_attempted_)
755 if (current_state_->cryptohome_code() ==
756 cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
757 // Critical TPM error detected, reboot needed.
761 // Return intermediate states in the following case:
762 // when there is an online result to use;
763 // This is the case after user finishes Gaia login;
764 if (current_state_->online_complete()) {
765 if (current_state_->cryptohome_code() ==
766 cryptohome::MOUNT_ERROR_KEY_FAILURE) {
767 // If we tried a mount but they used the wrong key, we may need to
768 // ask the user for her old password. We'll only know once we've
769 // done the online check.
770 return POSSIBLE_PW_CHANGE;
772 if (current_state_->cryptohome_code() ==
773 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) {
774 // If we tried a mount but the user did not exist, then we should wait
775 // for online login to succeed and try again with the "create" flag set.
780 if (!current_state_->username_hash_valid())
781 return FAILED_USERNAME_HASH;
786 ParallelAuthenticator::AuthState
787 ParallelAuthenticator::ResolveCryptohomeSuccessState() {
788 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
789 if (resync_attempted_)
791 if (remove_attempted_)
792 return REMOVED_DATA_AFTER_FAILURE;
793 if (migrate_attempted_)
794 return RECOVER_MOUNT;
795 if (check_key_attempted_)
798 if (current_state_->user_type == user_manager::USER_TYPE_GUEST)
800 if (current_state_->user_type == user_manager::USER_TYPE_RETAIL_MODE)
802 if (current_state_->user_type == user_manager::USER_TYPE_PUBLIC_ACCOUNT)
803 return PUBLIC_ACCOUNT_LOGIN;
804 if (current_state_->user_type == user_manager::USER_TYPE_KIOSK_APP)
805 return KIOSK_ACCOUNT_LOGIN;
806 if (current_state_->user_type == user_manager::USER_TYPE_SUPERVISED)
807 return SUPERVISED_USER_LOGIN;
811 return user_can_login_ ? OFFLINE_LOGIN : OWNER_REQUIRED;
814 ParallelAuthenticator::AuthState
815 ParallelAuthenticator::ResolveOnlineSuccessState(
816 ParallelAuthenticator::AuthState offline_state) {
817 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
818 switch (offline_state) {
819 case POSSIBLE_PW_CHANGE:
827 return offline_state;
831 void ParallelAuthenticator::ResolveLoginCompletionStatus() {
832 // Shortcut online state resolution process.
833 current_state_->RecordOnlineLoginStatus(AuthFailure::AuthFailureNone());
837 void ParallelAuthenticator::SetOwnerState(bool owner_check_finished,
839 owner_is_verified_ = owner_check_finished;
840 user_can_login_ = check_result;
843 } // namespace chromeos