| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/chromeos/login/parallel_authenticator.h" |
| |
| #include <string> |
| |
| #include "base/command_line.h" |
| #include "base/file_util.h" |
| #include "base/files/file_path.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "chrome/browser/chromeos/login/mock_login_status_consumer.h" |
| #include "chrome/browser/chromeos/login/mock_url_fetchers.h" |
| #include "chrome/browser/chromeos/login/mock_user_manager.h" |
| #include "chrome/browser/chromeos/login/test_attempt_state.h" |
| #include "chrome/browser/chromeos/login/user.h" |
| #include "chrome/browser/chromeos/login/user_manager.h" |
| #include "chrome/browser/chromeos/settings/cros_settings.h" |
| #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" |
| #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chromeos/chromeos_switches.h" |
| #include "chromeos/cryptohome/mock_async_method_caller.h" |
| #include "chromeos/cryptohome/system_salt_getter.h" |
| #include "chromeos/dbus/fake_cryptohome_client.h" |
| #include "chromeos/dbus/fake_dbus_thread_manager.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "google_apis/gaia/mock_url_fetcher_factory.h" |
| #include "net/base/net_errors.h" |
| #include "net/url_request/url_request_status.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/cros_system_api/dbus/service_constants.h" |
| #include "url/gurl.h" |
| |
| using ::testing::Invoke; |
| using ::testing::Return; |
| using ::testing::_; |
| |
| namespace chromeos { |
| |
| class ParallelAuthenticatorTest : public testing::Test { |
| public: |
| ParallelAuthenticatorTest() |
| : username_("me@nowhere.org"), |
| password_("fakepass"), |
| hash_ascii_(ParallelAuthenticator::HashPassword( |
| password_, |
| SystemSaltGetter::ConvertRawSaltToHexString( |
| FakeCryptohomeClient::GetStubSystemSalt()))), |
| user_manager_enabler_(new MockUserManager), |
| mock_caller_(NULL), |
| fake_dbus_thread_manager_(new FakeDBusThreadManager) { |
| } |
| |
| virtual ~ParallelAuthenticatorTest() { |
| DCHECK(!mock_caller_); |
| } |
| |
| virtual void SetUp() { |
| CommandLine::ForCurrentProcess()->AppendSwitch(switches::kLoginManager); |
| |
| mock_caller_ = new cryptohome::MockAsyncMethodCaller; |
| cryptohome::AsyncMethodCaller::InitializeForTesting(mock_caller_); |
| |
| // Ownership of fake_dbus_thread_manager_ is taken. |
| DBusThreadManager::InitializeForTesting(fake_dbus_thread_manager_); |
| SystemSaltGetter::Initialize(); |
| |
| auth_ = new ParallelAuthenticator(&consumer_); |
| state_.reset(new TestAttemptState(UserContext(username_, |
| password_, |
| std::string()), |
| "", |
| "", |
| User::USER_TYPE_REGULAR, |
| false)); |
| } |
| |
| // Tears down the test fixture. |
| virtual void TearDown() { |
| SystemSaltGetter::Shutdown(); |
| DBusThreadManager::Shutdown(); |
| |
| cryptohome::AsyncMethodCaller::Shutdown(); |
| mock_caller_ = NULL; |
| } |
| |
| base::FilePath PopulateTempFile(const char* data, int data_len) { |
| base::FilePath out; |
| FILE* tmp_file = file_util::CreateAndOpenTemporaryFile(&out); |
| EXPECT_NE(tmp_file, static_cast<FILE*>(NULL)); |
| EXPECT_EQ(file_util::WriteFile(out, data, data_len), data_len); |
| EXPECT_TRUE(file_util::CloseFile(tmp_file)); |
| return out; |
| } |
| |
| // Allow test to fail and exit gracefully, even if OnLoginFailure() |
| // wasn't supposed to happen. |
| void FailOnLoginFailure() { |
| ON_CALL(consumer_, OnLoginFailure(_)) |
| .WillByDefault(Invoke(MockConsumer::OnFailQuitAndFail)); |
| } |
| |
| // Allow test to fail and exit gracefully, even if |
| // OnRetailModeLoginSuccess() wasn't supposed to happen. |
| void FailOnRetailModeLoginSuccess() { |
| ON_CALL(consumer_, OnRetailModeLoginSuccess(_)) |
| .WillByDefault(Invoke(MockConsumer::OnRetailModeSuccessQuitAndFail)); |
| } |
| |
| // Allow test to fail and exit gracefully, even if OnLoginSuccess() |
| // wasn't supposed to happen. |
| void FailOnLoginSuccess() { |
| ON_CALL(consumer_, OnLoginSuccess(_)) |
| .WillByDefault(Invoke(MockConsumer::OnSuccessQuitAndFail)); |
| } |
| |
| // Allow test to fail and exit gracefully, even if |
| // OnOffTheRecordLoginSuccess() wasn't supposed to happen. |
| void FailOnGuestLoginSuccess() { |
| ON_CALL(consumer_, OnOffTheRecordLoginSuccess()) |
| .WillByDefault(Invoke(MockConsumer::OnGuestSuccessQuitAndFail)); |
| } |
| |
| void ExpectLoginFailure(const LoginFailure& failure) { |
| EXPECT_CALL(consumer_, OnLoginFailure(failure)) |
| .WillOnce(Invoke(MockConsumer::OnFailQuit)) |
| .RetiresOnSaturation(); |
| } |
| |
| void ExpectRetailModeLoginSuccess() { |
| EXPECT_CALL(consumer_, OnRetailModeLoginSuccess(_)) |
| .WillOnce(Invoke(MockConsumer::OnRetailModeSuccessQuit)) |
| .RetiresOnSaturation(); |
| } |
| |
| void ExpectLoginSuccess(const std::string& username, |
| const std::string& password, |
| const std::string& username_hash_, |
| bool pending) { |
| EXPECT_CALL(consumer_, OnLoginSuccess(UserContext(username, |
| password, |
| std::string(), |
| username_hash_, |
| true /* using_oauth */))) |
| .WillOnce(Invoke(MockConsumer::OnSuccessQuit)) |
| .RetiresOnSaturation(); |
| } |
| |
| void ExpectGuestLoginSuccess() { |
| EXPECT_CALL(consumer_, OnOffTheRecordLoginSuccess()) |
| .WillOnce(Invoke(MockConsumer::OnGuestSuccessQuit)) |
| .RetiresOnSaturation(); |
| } |
| |
| void ExpectPasswordChange() { |
| EXPECT_CALL(consumer_, OnPasswordChangeDetected()) |
| .WillOnce(Invoke(MockConsumer::OnMigrateQuit)) |
| .RetiresOnSaturation(); |
| } |
| |
| void RunResolve(ParallelAuthenticator* auth) { |
| auth->Resolve(); |
| base::MessageLoop::current()->RunUntilIdle(); |
| } |
| |
| void SetAttemptState(ParallelAuthenticator* auth, TestAttemptState* state) { |
| auth->set_attempt_state(state); |
| } |
| |
| ParallelAuthenticator::AuthState SetAndResolveState( |
| ParallelAuthenticator* auth, TestAttemptState* state) { |
| auth->set_attempt_state(state); |
| return auth->ResolveState(); |
| } |
| |
| void SetOwnerState(bool owner_check_finished, bool check_result) { |
| auth_->SetOwnerState(owner_check_finished, check_result); |
| } |
| |
| content::TestBrowserThreadBundle thread_bundle_; |
| |
| std::string username_; |
| std::string password_; |
| std::string username_hash_; |
| std::string hash_ascii_; |
| |
| ScopedDeviceSettingsTestHelper device_settings_test_helper_; |
| ScopedTestCrosSettings test_cros_settings_; |
| |
| ScopedUserManagerEnabler user_manager_enabler_; |
| |
| cryptohome::MockAsyncMethodCaller* mock_caller_; |
| |
| MockConsumer consumer_; |
| scoped_refptr<ParallelAuthenticator> auth_; |
| scoped_ptr<TestAttemptState> state_; |
| FakeDBusThreadManager* fake_dbus_thread_manager_; |
| }; |
| |
| TEST_F(ParallelAuthenticatorTest, OnLoginSuccess) { |
| EXPECT_CALL(consumer_, OnLoginSuccess(UserContext(username_, |
| password_, |
| std::string(), |
| username_hash_, |
| true /* using oauth */))) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| SetAttemptState(auth_.get(), state_.release()); |
| auth_->OnLoginSuccess(); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, OnPasswordChangeDetected) { |
| EXPECT_CALL(consumer_, OnPasswordChangeDetected()) |
| .Times(1) |
| .RetiresOnSaturation(); |
| SetAttemptState(auth_.get(), state_.release()); |
| auth_->OnPasswordChangeDetected(); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, ResolveNothingDone) { |
| EXPECT_EQ(ParallelAuthenticator::CONTINUE, |
| SetAndResolveState(auth_.get(), state_.release())); |
| } |
| |
| |
| TEST_F(ParallelAuthenticatorTest, ResolvePossiblePwChangeToFailedMount) { |
| // Set up state as though a cryptohome mount attempt has occurred |
| // and been rejected. |
| state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); |
| |
| // When there is no online attempt and online results, POSSIBLE_PW_CHANGE |
| EXPECT_EQ(ParallelAuthenticator::FAILED_MOUNT, |
| SetAndResolveState(auth_.get(), state_.release())); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, ResolveNeedOldPw) { |
| // Set up state as though a cryptohome mount attempt has occurred |
| // and been rejected because of unmatched key; additionally, |
| // an online auth attempt has completed successfully. |
| state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); |
| state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); |
| |
| EXPECT_EQ(ParallelAuthenticator::NEED_OLD_PW, |
| SetAndResolveState(auth_.get(), state_.release())); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededDirectFailedMount) { |
| // Set up state as though a cryptohome mount attempt has occurred |
| // and succeeded but we are in safe mode and the current user is not owner. |
| // This is a high level test to verify the proper transitioning in this mode |
| // only. It is not testing that we properly verify that the user is an owner |
| // or that we really are in "safe-mode". |
| state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); |
| SetOwnerState(true, false); |
| |
| EXPECT_EQ(ParallelAuthenticator::OWNER_REQUIRED, |
| SetAndResolveState(auth_.get(), state_.release())); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededMount) { |
| // Set up state as though a cryptohome mount attempt has occurred |
| // and succeeded but we are in safe mode and the current user is not owner. |
| // This test will check that the "safe-mode" policy is not set and will let |
| // the mount finish successfully. |
| state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); |
| SetOwnerState(false, false); |
| // and test that the mount has succeeded. |
| state_.reset(new TestAttemptState(UserContext(username_, |
| password_, |
| std::string()), |
| "", |
| "", |
| User::USER_TYPE_REGULAR, |
| false)); |
| state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_EQ(ParallelAuthenticator::OFFLINE_LOGIN, |
| SetAndResolveState(auth_.get(), state_.release())); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededFailedMount) { |
| FailOnLoginSuccess(); // Set failing on success as the default... |
| LoginFailure failure = LoginFailure(LoginFailure::OWNER_REQUIRED); |
| ExpectLoginFailure(failure); |
| |
| FakeCryptohomeClient* fake_cryptohome_client = |
| fake_dbus_thread_manager_->fake_cryptohome_client(); |
| fake_cryptohome_client->set_unmount_result(true); |
| |
| CrosSettingsProvider* device_settings_provider; |
| StubCrosSettingsProvider stub_settings_provider; |
| // Set up state as though a cryptohome mount attempt has occurred |
| // and succeeded but we are in safe mode and the current user is not owner. |
| state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); |
| SetOwnerState(false, false); |
| // Remove the real DeviceSettingsProvider and replace it with a stub. |
| device_settings_provider = |
| CrosSettings::Get()->GetProvider(chromeos::kReportDeviceVersionInfo); |
| EXPECT_TRUE(device_settings_provider != NULL); |
| EXPECT_TRUE( |
| CrosSettings::Get()->RemoveSettingsProvider(device_settings_provider)); |
| CrosSettings::Get()->AddSettingsProvider(&stub_settings_provider); |
| CrosSettings::Get()->SetBoolean(kPolicyMissingMitigationMode, true); |
| |
| // Initialize login state for this test to verify the login state is changed |
| // to SAFE_MODE. |
| LoginState::Initialize(); |
| |
| EXPECT_EQ(ParallelAuthenticator::CONTINUE, |
| SetAndResolveState(auth_.get(), state_.release())); |
| EXPECT_TRUE(LoginState::Get()->IsInSafeMode()); |
| |
| // Simulate certificates load event. The exact certificates loaded are not |
| // actually used by the DeviceSettingsService, so it is OK to pass an empty |
| // list. |
| DeviceSettingsService::Get()->OnCertificatesLoaded(net::CertificateList(), |
| true); |
| // Flush all the pending operations. The operations should induce an owner |
| // verification. |
| device_settings_test_helper_.Flush(); |
| // and test that the mount has succeeded. |
| state_.reset(new TestAttemptState(UserContext(username_, |
| password_, |
| std::string()), |
| "", |
| "", |
| User::USER_TYPE_REGULAR, |
| false)); |
| state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_EQ(ParallelAuthenticator::OWNER_REQUIRED, |
| SetAndResolveState(auth_.get(), state_.release())); |
| |
| // Unset global objects used by this test. |
| LoginState::Shutdown(); |
| EXPECT_TRUE( |
| CrosSettings::Get()->RemoveSettingsProvider(&stub_settings_provider)); |
| CrosSettings::Get()->AddSettingsProvider(device_settings_provider); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveFailedMount) { |
| FailOnLoginSuccess(); |
| ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME)); |
| |
| // Set up state as though a cryptohome mount attempt has occurred |
| // and failed. |
| state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_NONE); |
| SetAttemptState(auth_.get(), state_.release()); |
| |
| RunResolve(auth_.get()); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveGuestLogin) { |
| ExpectGuestLoginSuccess(); |
| FailOnLoginFailure(); |
| |
| // Set up mock async method caller to respond as though a tmpfs mount |
| // attempt has occurred and succeeded. |
| mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| auth_->LoginOffTheRecord(); |
| base::MessageLoop::current()->Run(); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveGuestLoginButFail) { |
| FailOnGuestLoginSuccess(); |
| ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)); |
| |
| // Set up mock async method caller to respond as though a tmpfs mount |
| // attempt has occurred and failed. |
| mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| auth_->LoginOffTheRecord(); |
| base::MessageLoop::current()->Run(); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveRetailModeUserLogin) { |
| ExpectRetailModeLoginSuccess(); |
| FailOnLoginFailure(); |
| |
| // Set up mock async method caller to respond as though a tmpfs mount |
| // attempt has occurred and succeeded. |
| mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| auth_->LoginRetailMode(); |
| base::MessageLoop::current()->Run(); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveRetailModeLoginButFail) { |
| FailOnRetailModeLoginSuccess(); |
| ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)); |
| |
| // Set up mock async method caller to respond as though a tmpfs mount |
| // attempt has occurred and failed. |
| mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| auth_->LoginRetailMode(); |
| base::MessageLoop::current()->Run(); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveDataResync) { |
| ExpectLoginSuccess(username_, |
| password_, |
| cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername, |
| false); |
| FailOnLoginFailure(); |
| |
| // Set up mock async method caller to respond successfully to a cryptohome |
| // remove attempt and a cryptohome create attempt (indicated by the |
| // |CREATE_IF_MISSING| flag to AsyncMount). |
| mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_CALL(*mock_caller_, AsyncRemove(username_, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_, |
| cryptohome::CREATE_IF_MISSING, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*mock_caller_, AsyncGetSanitizedUsername(username_, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); |
| SetAttemptState(auth_.get(), state_.release()); |
| |
| auth_->ResyncEncryptedData(); |
| base::MessageLoop::current()->Run(); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveResyncFail) { |
| FailOnLoginSuccess(); |
| ExpectLoginFailure(LoginFailure(LoginFailure::DATA_REMOVAL_FAILED)); |
| |
| // Set up mock async method caller to fail a cryptohome remove attempt. |
| mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_CALL(*mock_caller_, AsyncRemove(username_, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| SetAttemptState(auth_.get(), state_.release()); |
| |
| auth_->ResyncEncryptedData(); |
| base::MessageLoop::current()->Run(); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveRequestOldPassword) { |
| FailOnLoginSuccess(); |
| ExpectPasswordChange(); |
| |
| state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); |
| state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); |
| SetAttemptState(auth_.get(), state_.release()); |
| |
| RunResolve(auth_.get()); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveDataRecover) { |
| ExpectLoginSuccess(username_, |
| password_, |
| cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername, |
| false); |
| FailOnLoginFailure(); |
| |
| // Set up mock async method caller to respond successfully to a key migration. |
| mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_CALL(*mock_caller_, AsyncMigrateKey(username_, _, hash_ascii_, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_, |
| cryptohome::MOUNT_FLAGS_NONE, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*mock_caller_, AsyncGetSanitizedUsername(username_, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); |
| SetAttemptState(auth_.get(), state_.release()); |
| |
| auth_->RecoverEncryptedData(std::string()); |
| base::MessageLoop::current()->Run(); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveDataRecoverButFail) { |
| FailOnLoginSuccess(); |
| ExpectPasswordChange(); |
| |
| // Set up mock async method caller to fail a key migration attempt, |
| // asserting that the wrong password was used. |
| mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); |
| EXPECT_CALL(*mock_caller_, AsyncMigrateKey(username_, _, hash_ascii_, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| SetAttemptState(auth_.get(), state_.release()); |
| |
| auth_->RecoverEncryptedData(std::string()); |
| base::MessageLoop::current()->Run(); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, ResolveNoMountToFailedMount) { |
| // Set up state as though a cryptohome mount attempt has occurred |
| // and been rejected because the user doesn't exist. |
| state_->PresetCryptohomeStatus(false, |
| cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST); |
| |
| // When there is no online attempt and online results, NO_MOUNT will be |
| // resolved to FAILED_MOUNT. |
| EXPECT_EQ(ParallelAuthenticator::FAILED_MOUNT, |
| SetAndResolveState(auth_.get(), state_.release())); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, ResolveCreateNew) { |
| // Set up state as though a cryptohome mount attempt has occurred |
| // and been rejected because the user doesn't exist; additionally, |
| // an online auth attempt has completed successfully. |
| state_->PresetCryptohomeStatus(false, |
| cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST); |
| state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); |
| |
| EXPECT_EQ(ParallelAuthenticator::CREATE_NEW, |
| SetAndResolveState(auth_.get(), state_.release())); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveCreateForNewUser) { |
| ExpectLoginSuccess(username_, |
| password_, |
| cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername, |
| false); |
| FailOnLoginFailure(); |
| |
| // Set up mock async method caller to respond successfully to a cryptohome |
| // create attempt (indicated by the |CREATE_IF_MISSING| flag to AsyncMount). |
| mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_, |
| cryptohome::CREATE_IF_MISSING, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*mock_caller_, AsyncGetSanitizedUsername(username_, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| // Set up state as though a cryptohome mount attempt has occurred |
| // and been rejected because the user doesn't exist; additionally, |
| // an online auth attempt has completed successfully. |
| state_->PresetCryptohomeStatus(false, |
| cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST); |
| state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); |
| SetAttemptState(auth_.get(), state_.release()); |
| |
| RunResolve(auth_.get()); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveOfflineLogin) { |
| ExpectLoginSuccess(username_, password_, username_hash_, false); |
| FailOnLoginFailure(); |
| |
| // Set up state as though a cryptohome mount attempt has occurred and |
| // succeeded. |
| state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); |
| SetAttemptState(auth_.get(), state_.release()); |
| |
| RunResolve(auth_.get()); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveOnlineLogin) { |
| ExpectLoginSuccess(username_, password_, username_hash_, false); |
| FailOnLoginFailure(); |
| |
| // Set up state as though a cryptohome mount attempt has occurred and |
| // succeeded. |
| state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); |
| state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); |
| SetAttemptState(auth_.get(), state_.release()); |
| |
| RunResolve(auth_.get()); |
| } |
| |
| TEST_F(ParallelAuthenticatorTest, DriveUnlock) { |
| ExpectLoginSuccess(username_, std::string(), std::string(), false); |
| FailOnLoginFailure(); |
| |
| // Set up mock async method caller to respond successfully to a cryptohome |
| // key-check attempt. |
| mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); |
| EXPECT_CALL(*mock_caller_, AsyncCheckKey(username_, _, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| auth_->AuthenticateToUnlock(UserContext(username_, |
| std::string(), |
| std::string())); |
| base::MessageLoop::current()->Run(); |
| } |
| |
| } // namespace chromeos |