| 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/parallel_authenticator.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/command_line.h" | |
| 10 #include "base/file_util.h" | |
| 11 #include "base/files/file_path.h" | |
| 12 #include "base/memory/scoped_ptr.h" | |
| 13 #include "base/message_loop/message_loop.h" | |
| 14 #include "base/strings/string_util.h" | |
| 15 #include "base/strings/stringprintf.h" | |
| 16 #include "chrome/browser/chromeos/login/mock_login_status_consumer.h" | |
| 17 #include "chrome/browser/chromeos/login/mock_url_fetchers.h" | |
| 18 #include "chrome/browser/chromeos/login/mock_user_manager.h" | |
| 19 #include "chrome/browser/chromeos/login/test_attempt_state.h" | |
| 20 #include "chrome/browser/chromeos/login/user.h" | |
| 21 #include "chrome/browser/chromeos/login/user_manager.h" | |
| 22 #include "chrome/browser/chromeos/settings/cros_settings.h" | |
| 23 #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" | |
| 24 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" | |
| 25 #include "chrome/test/base/testing_profile.h" | |
| 26 #include "chromeos/chromeos_switches.h" | |
| 27 #include "chromeos/cryptohome/mock_async_method_caller.h" | |
| 28 #include "chromeos/cryptohome/system_salt_getter.h" | |
| 29 #include "chromeos/dbus/fake_cryptohome_client.h" | |
| 30 #include "chromeos/dbus/fake_dbus_thread_manager.h" | |
| 31 #include "content/public/test/test_browser_thread_bundle.h" | |
| 32 #include "google_apis/gaia/mock_url_fetcher_factory.h" | |
| 33 #include "net/base/net_errors.h" | |
| 34 #include "net/url_request/url_request_status.h" | |
| 35 #include "testing/gmock/include/gmock/gmock.h" | |
| 36 #include "testing/gtest/include/gtest/gtest.h" | |
| 37 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 38 #include "url/gurl.h" | |
| 39 | |
| 40 using ::testing::Invoke; | |
| 41 using ::testing::Return; | |
| 42 using ::testing::_; | |
| 43 | |
| 44 namespace chromeos { | |
| 45 | |
| 46 class ParallelAuthenticatorTest : public testing::Test { | |
| 47 public: | |
| 48 ParallelAuthenticatorTest() | |
| 49 : username_("me@nowhere.org"), | |
| 50 password_("fakepass"), | |
| 51 hash_ascii_(ParallelAuthenticator::HashPassword( | |
| 52 password_, | |
| 53 SystemSaltGetter::ConvertRawSaltToHexString( | |
| 54 FakeCryptohomeClient::GetStubSystemSalt()))), | |
| 55 user_manager_enabler_(new MockUserManager), | |
| 56 mock_caller_(NULL) { | |
| 57 } | |
| 58 | |
| 59 virtual ~ParallelAuthenticatorTest() { | |
| 60 DCHECK(!mock_caller_); | |
| 61 } | |
| 62 | |
| 63 virtual void SetUp() { | |
| 64 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kLoginManager); | |
| 65 | |
| 66 mock_caller_ = new cryptohome::MockAsyncMethodCaller; | |
| 67 cryptohome::AsyncMethodCaller::InitializeForTesting(mock_caller_); | |
| 68 | |
| 69 FakeDBusThreadManager* fake_dbus_thread_manager = new FakeDBusThreadManager; | |
| 70 fake_cryptohome_client_ = new FakeCryptohomeClient; | |
| 71 fake_dbus_thread_manager->SetCryptohomeClient( | |
| 72 scoped_ptr<CryptohomeClient>(fake_cryptohome_client_)); | |
| 73 DBusThreadManager::InitializeForTesting(fake_dbus_thread_manager); | |
| 74 | |
| 75 SystemSaltGetter::Initialize(); | |
| 76 | |
| 77 auth_ = new ParallelAuthenticator(&consumer_); | |
| 78 state_.reset(new TestAttemptState(UserContext(username_, | |
| 79 password_, | |
| 80 std::string()), | |
| 81 "", | |
| 82 "", | |
| 83 User::USER_TYPE_REGULAR, | |
| 84 false)); | |
| 85 } | |
| 86 | |
| 87 // Tears down the test fixture. | |
| 88 virtual void TearDown() { | |
| 89 SystemSaltGetter::Shutdown(); | |
| 90 DBusThreadManager::Shutdown(); | |
| 91 | |
| 92 cryptohome::AsyncMethodCaller::Shutdown(); | |
| 93 mock_caller_ = NULL; | |
| 94 } | |
| 95 | |
| 96 base::FilePath PopulateTempFile(const char* data, int data_len) { | |
| 97 base::FilePath out; | |
| 98 FILE* tmp_file = base::CreateAndOpenTemporaryFile(&out); | |
| 99 EXPECT_NE(tmp_file, static_cast<FILE*>(NULL)); | |
| 100 EXPECT_EQ(base::WriteFile(out, data, data_len), data_len); | |
| 101 EXPECT_TRUE(base::CloseFile(tmp_file)); | |
| 102 return out; | |
| 103 } | |
| 104 | |
| 105 // Allow test to fail and exit gracefully, even if OnLoginFailure() | |
| 106 // wasn't supposed to happen. | |
| 107 void FailOnLoginFailure() { | |
| 108 ON_CALL(consumer_, OnLoginFailure(_)) | |
| 109 .WillByDefault(Invoke(MockConsumer::OnFailQuitAndFail)); | |
| 110 } | |
| 111 | |
| 112 // Allow test to fail and exit gracefully, even if | |
| 113 // OnRetailModeLoginSuccess() wasn't supposed to happen. | |
| 114 void FailOnRetailModeLoginSuccess() { | |
| 115 ON_CALL(consumer_, OnRetailModeLoginSuccess(_)) | |
| 116 .WillByDefault(Invoke(MockConsumer::OnRetailModeSuccessQuitAndFail)); | |
| 117 } | |
| 118 | |
| 119 // Allow test to fail and exit gracefully, even if OnLoginSuccess() | |
| 120 // wasn't supposed to happen. | |
| 121 void FailOnLoginSuccess() { | |
| 122 ON_CALL(consumer_, OnLoginSuccess(_)) | |
| 123 .WillByDefault(Invoke(MockConsumer::OnSuccessQuitAndFail)); | |
| 124 } | |
| 125 | |
| 126 // Allow test to fail and exit gracefully, even if | |
| 127 // OnOffTheRecordLoginSuccess() wasn't supposed to happen. | |
| 128 void FailOnGuestLoginSuccess() { | |
| 129 ON_CALL(consumer_, OnOffTheRecordLoginSuccess()) | |
| 130 .WillByDefault(Invoke(MockConsumer::OnGuestSuccessQuitAndFail)); | |
| 131 } | |
| 132 | |
| 133 void ExpectLoginFailure(const LoginFailure& failure) { | |
| 134 EXPECT_CALL(consumer_, OnLoginFailure(failure)) | |
| 135 .WillOnce(Invoke(MockConsumer::OnFailQuit)) | |
| 136 .RetiresOnSaturation(); | |
| 137 } | |
| 138 | |
| 139 void ExpectRetailModeLoginSuccess() { | |
| 140 EXPECT_CALL(consumer_, OnRetailModeLoginSuccess(_)) | |
| 141 .WillOnce(Invoke(MockConsumer::OnRetailModeSuccessQuit)) | |
| 142 .RetiresOnSaturation(); | |
| 143 } | |
| 144 | |
| 145 void ExpectLoginSuccess(const std::string& username, | |
| 146 const std::string& password, | |
| 147 const std::string& username_hash_, | |
| 148 bool pending) { | |
| 149 EXPECT_CALL(consumer_, OnLoginSuccess(UserContext( | |
| 150 username, | |
| 151 password, | |
| 152 std::string(), | |
| 153 username_hash_, | |
| 154 true, // using_oauth | |
| 155 UserContext::AUTH_FLOW_OFFLINE))) | |
| 156 .WillOnce(Invoke(MockConsumer::OnSuccessQuit)) | |
| 157 .RetiresOnSaturation(); | |
| 158 } | |
| 159 | |
| 160 void ExpectGuestLoginSuccess() { | |
| 161 EXPECT_CALL(consumer_, OnOffTheRecordLoginSuccess()) | |
| 162 .WillOnce(Invoke(MockConsumer::OnGuestSuccessQuit)) | |
| 163 .RetiresOnSaturation(); | |
| 164 } | |
| 165 | |
| 166 void ExpectPasswordChange() { | |
| 167 EXPECT_CALL(consumer_, OnPasswordChangeDetected()) | |
| 168 .WillOnce(Invoke(MockConsumer::OnMigrateQuit)) | |
| 169 .RetiresOnSaturation(); | |
| 170 } | |
| 171 | |
| 172 void RunResolve(ParallelAuthenticator* auth) { | |
| 173 auth->Resolve(); | |
| 174 base::MessageLoop::current()->RunUntilIdle(); | |
| 175 } | |
| 176 | |
| 177 void SetAttemptState(ParallelAuthenticator* auth, TestAttemptState* state) { | |
| 178 auth->set_attempt_state(state); | |
| 179 } | |
| 180 | |
| 181 ParallelAuthenticator::AuthState SetAndResolveState( | |
| 182 ParallelAuthenticator* auth, TestAttemptState* state) { | |
| 183 auth->set_attempt_state(state); | |
| 184 return auth->ResolveState(); | |
| 185 } | |
| 186 | |
| 187 void SetOwnerState(bool owner_check_finished, bool check_result) { | |
| 188 auth_->SetOwnerState(owner_check_finished, check_result); | |
| 189 } | |
| 190 | |
| 191 content::TestBrowserThreadBundle thread_bundle_; | |
| 192 | |
| 193 std::string username_; | |
| 194 std::string password_; | |
| 195 std::string username_hash_; | |
| 196 std::string hash_ascii_; | |
| 197 | |
| 198 ScopedDeviceSettingsTestHelper device_settings_test_helper_; | |
| 199 ScopedTestCrosSettings test_cros_settings_; | |
| 200 | |
| 201 ScopedUserManagerEnabler user_manager_enabler_; | |
| 202 | |
| 203 cryptohome::MockAsyncMethodCaller* mock_caller_; | |
| 204 | |
| 205 MockConsumer consumer_; | |
| 206 scoped_refptr<ParallelAuthenticator> auth_; | |
| 207 scoped_ptr<TestAttemptState> state_; | |
| 208 FakeCryptohomeClient* fake_cryptohome_client_; | |
| 209 }; | |
| 210 | |
| 211 TEST_F(ParallelAuthenticatorTest, OnLoginSuccess) { | |
| 212 EXPECT_CALL(consumer_, OnLoginSuccess(UserContext( | |
| 213 username_, | |
| 214 password_, | |
| 215 std::string(), | |
| 216 username_hash_, | |
| 217 true, // using oauth | |
| 218 UserContext::AUTH_FLOW_OFFLINE))) | |
| 219 .Times(1) | |
| 220 .RetiresOnSaturation(); | |
| 221 | |
| 222 SetAttemptState(auth_.get(), state_.release()); | |
| 223 auth_->OnLoginSuccess(); | |
| 224 } | |
| 225 | |
| 226 TEST_F(ParallelAuthenticatorTest, OnPasswordChangeDetected) { | |
| 227 EXPECT_CALL(consumer_, OnPasswordChangeDetected()) | |
| 228 .Times(1) | |
| 229 .RetiresOnSaturation(); | |
| 230 SetAttemptState(auth_.get(), state_.release()); | |
| 231 auth_->OnPasswordChangeDetected(); | |
| 232 } | |
| 233 | |
| 234 TEST_F(ParallelAuthenticatorTest, ResolveNothingDone) { | |
| 235 EXPECT_EQ(ParallelAuthenticator::CONTINUE, | |
| 236 SetAndResolveState(auth_.get(), state_.release())); | |
| 237 } | |
| 238 | |
| 239 | |
| 240 TEST_F(ParallelAuthenticatorTest, ResolvePossiblePwChangeToFailedMount) { | |
| 241 // Set up state as though a cryptohome mount attempt has occurred | |
| 242 // and been rejected. | |
| 243 state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); | |
| 244 | |
| 245 // When there is no online attempt and online results, POSSIBLE_PW_CHANGE | |
| 246 EXPECT_EQ(ParallelAuthenticator::FAILED_MOUNT, | |
| 247 SetAndResolveState(auth_.get(), state_.release())); | |
| 248 } | |
| 249 | |
| 250 TEST_F(ParallelAuthenticatorTest, ResolveNeedOldPw) { | |
| 251 // Set up state as though a cryptohome mount attempt has occurred | |
| 252 // and been rejected because of unmatched key; additionally, | |
| 253 // an online auth attempt has completed successfully. | |
| 254 state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); | |
| 255 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); | |
| 256 | |
| 257 EXPECT_EQ(ParallelAuthenticator::NEED_OLD_PW, | |
| 258 SetAndResolveState(auth_.get(), state_.release())); | |
| 259 } | |
| 260 | |
| 261 TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededDirectFailedMount) { | |
| 262 // Set up state as though a cryptohome mount attempt has occurred | |
| 263 // and succeeded but we are in safe mode and the current user is not owner. | |
| 264 // This is a high level test to verify the proper transitioning in this mode | |
| 265 // only. It is not testing that we properly verify that the user is an owner | |
| 266 // or that we really are in "safe-mode". | |
| 267 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); | |
| 268 SetOwnerState(true, false); | |
| 269 | |
| 270 EXPECT_EQ(ParallelAuthenticator::OWNER_REQUIRED, | |
| 271 SetAndResolveState(auth_.get(), state_.release())); | |
| 272 } | |
| 273 | |
| 274 TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededMount) { | |
| 275 // Set up state as though a cryptohome mount attempt has occurred | |
| 276 // and succeeded but we are in safe mode and the current user is not owner. | |
| 277 // This test will check that the "safe-mode" policy is not set and will let | |
| 278 // the mount finish successfully. | |
| 279 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); | |
| 280 SetOwnerState(false, false); | |
| 281 // and test that the mount has succeeded. | |
| 282 state_.reset(new TestAttemptState(UserContext(username_, | |
| 283 password_, | |
| 284 std::string()), | |
| 285 "", | |
| 286 "", | |
| 287 User::USER_TYPE_REGULAR, | |
| 288 false)); | |
| 289 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); | |
| 290 EXPECT_EQ(ParallelAuthenticator::OFFLINE_LOGIN, | |
| 291 SetAndResolveState(auth_.get(), state_.release())); | |
| 292 } | |
| 293 | |
| 294 TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededFailedMount) { | |
| 295 FailOnLoginSuccess(); // Set failing on success as the default... | |
| 296 LoginFailure failure = LoginFailure(LoginFailure::OWNER_REQUIRED); | |
| 297 ExpectLoginFailure(failure); | |
| 298 | |
| 299 fake_cryptohome_client_->set_unmount_result(true); | |
| 300 | |
| 301 CrosSettingsProvider* device_settings_provider; | |
| 302 StubCrosSettingsProvider stub_settings_provider; | |
| 303 // Set up state as though a cryptohome mount attempt has occurred | |
| 304 // and succeeded but we are in safe mode and the current user is not owner. | |
| 305 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); | |
| 306 SetOwnerState(false, false); | |
| 307 // Remove the real DeviceSettingsProvider and replace it with a stub. | |
| 308 device_settings_provider = | |
| 309 CrosSettings::Get()->GetProvider(chromeos::kReportDeviceVersionInfo); | |
| 310 EXPECT_TRUE(device_settings_provider != NULL); | |
| 311 EXPECT_TRUE( | |
| 312 CrosSettings::Get()->RemoveSettingsProvider(device_settings_provider)); | |
| 313 CrosSettings::Get()->AddSettingsProvider(&stub_settings_provider); | |
| 314 CrosSettings::Get()->SetBoolean(kPolicyMissingMitigationMode, true); | |
| 315 | |
| 316 // Initialize login state for this test to verify the login state is changed | |
| 317 // to SAFE_MODE. | |
| 318 LoginState::Initialize(); | |
| 319 | |
| 320 EXPECT_EQ(ParallelAuthenticator::CONTINUE, | |
| 321 SetAndResolveState(auth_.get(), state_.release())); | |
| 322 EXPECT_TRUE(LoginState::Get()->IsInSafeMode()); | |
| 323 | |
| 324 // Simulate TPM token ready event. | |
| 325 DeviceSettingsService::Get()->OnTPMTokenReady(); | |
| 326 | |
| 327 // Flush all the pending operations. The operations should induce an owner | |
| 328 // verification. | |
| 329 device_settings_test_helper_.Flush(); | |
| 330 // and test that the mount has succeeded. | |
| 331 state_.reset(new TestAttemptState(UserContext(username_, | |
| 332 password_, | |
| 333 std::string()), | |
| 334 "", | |
| 335 "", | |
| 336 User::USER_TYPE_REGULAR, | |
| 337 false)); | |
| 338 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); | |
| 339 EXPECT_EQ(ParallelAuthenticator::OWNER_REQUIRED, | |
| 340 SetAndResolveState(auth_.get(), state_.release())); | |
| 341 | |
| 342 // Unset global objects used by this test. | |
| 343 LoginState::Shutdown(); | |
| 344 EXPECT_TRUE( | |
| 345 CrosSettings::Get()->RemoveSettingsProvider(&stub_settings_provider)); | |
| 346 CrosSettings::Get()->AddSettingsProvider(device_settings_provider); | |
| 347 } | |
| 348 | |
| 349 TEST_F(ParallelAuthenticatorTest, DriveFailedMount) { | |
| 350 FailOnLoginSuccess(); | |
| 351 ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME)); | |
| 352 | |
| 353 // Set up state as though a cryptohome mount attempt has occurred | |
| 354 // and failed. | |
| 355 state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_NONE); | |
| 356 SetAttemptState(auth_.get(), state_.release()); | |
| 357 | |
| 358 RunResolve(auth_.get()); | |
| 359 } | |
| 360 | |
| 361 TEST_F(ParallelAuthenticatorTest, DriveGuestLogin) { | |
| 362 ExpectGuestLoginSuccess(); | |
| 363 FailOnLoginFailure(); | |
| 364 | |
| 365 // Set up mock async method caller to respond as though a tmpfs mount | |
| 366 // attempt has occurred and succeeded. | |
| 367 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); | |
| 368 EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) | |
| 369 .Times(1) | |
| 370 .RetiresOnSaturation(); | |
| 371 | |
| 372 auth_->LoginOffTheRecord(); | |
| 373 base::MessageLoop::current()->Run(); | |
| 374 } | |
| 375 | |
| 376 TEST_F(ParallelAuthenticatorTest, DriveGuestLoginButFail) { | |
| 377 FailOnGuestLoginSuccess(); | |
| 378 ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)); | |
| 379 | |
| 380 // Set up mock async method caller to respond as though a tmpfs mount | |
| 381 // attempt has occurred and failed. | |
| 382 mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE); | |
| 383 EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) | |
| 384 .Times(1) | |
| 385 .RetiresOnSaturation(); | |
| 386 | |
| 387 auth_->LoginOffTheRecord(); | |
| 388 base::MessageLoop::current()->Run(); | |
| 389 } | |
| 390 | |
| 391 TEST_F(ParallelAuthenticatorTest, DriveRetailModeUserLogin) { | |
| 392 ExpectRetailModeLoginSuccess(); | |
| 393 FailOnLoginFailure(); | |
| 394 | |
| 395 // Set up mock async method caller to respond as though a tmpfs mount | |
| 396 // attempt has occurred and succeeded. | |
| 397 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); | |
| 398 EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) | |
| 399 .Times(1) | |
| 400 .RetiresOnSaturation(); | |
| 401 | |
| 402 auth_->LoginRetailMode(); | |
| 403 base::MessageLoop::current()->Run(); | |
| 404 } | |
| 405 | |
| 406 TEST_F(ParallelAuthenticatorTest, DriveRetailModeLoginButFail) { | |
| 407 FailOnRetailModeLoginSuccess(); | |
| 408 ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)); | |
| 409 | |
| 410 // Set up mock async method caller to respond as though a tmpfs mount | |
| 411 // attempt has occurred and failed. | |
| 412 mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE); | |
| 413 EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) | |
| 414 .Times(1) | |
| 415 .RetiresOnSaturation(); | |
| 416 | |
| 417 auth_->LoginRetailMode(); | |
| 418 base::MessageLoop::current()->Run(); | |
| 419 } | |
| 420 | |
| 421 TEST_F(ParallelAuthenticatorTest, DriveDataResync) { | |
| 422 ExpectLoginSuccess(username_, | |
| 423 password_, | |
| 424 cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername, | |
| 425 false); | |
| 426 FailOnLoginFailure(); | |
| 427 | |
| 428 // Set up mock async method caller to respond successfully to a cryptohome | |
| 429 // remove attempt and a cryptohome create attempt (indicated by the | |
| 430 // |CREATE_IF_MISSING| flag to AsyncMount). | |
| 431 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); | |
| 432 EXPECT_CALL(*mock_caller_, AsyncRemove(username_, _)) | |
| 433 .Times(1) | |
| 434 .RetiresOnSaturation(); | |
| 435 EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_, | |
| 436 cryptohome::CREATE_IF_MISSING, _)) | |
| 437 .Times(1) | |
| 438 .RetiresOnSaturation(); | |
| 439 EXPECT_CALL(*mock_caller_, AsyncGetSanitizedUsername(username_, _)) | |
| 440 .Times(1) | |
| 441 .RetiresOnSaturation(); | |
| 442 | |
| 443 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); | |
| 444 SetAttemptState(auth_.get(), state_.release()); | |
| 445 | |
| 446 auth_->ResyncEncryptedData(); | |
| 447 base::MessageLoop::current()->Run(); | |
| 448 } | |
| 449 | |
| 450 TEST_F(ParallelAuthenticatorTest, DriveResyncFail) { | |
| 451 FailOnLoginSuccess(); | |
| 452 ExpectLoginFailure(LoginFailure(LoginFailure::DATA_REMOVAL_FAILED)); | |
| 453 | |
| 454 // Set up mock async method caller to fail a cryptohome remove attempt. | |
| 455 mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE); | |
| 456 EXPECT_CALL(*mock_caller_, AsyncRemove(username_, _)) | |
| 457 .Times(1) | |
| 458 .RetiresOnSaturation(); | |
| 459 | |
| 460 SetAttemptState(auth_.get(), state_.release()); | |
| 461 | |
| 462 auth_->ResyncEncryptedData(); | |
| 463 base::MessageLoop::current()->Run(); | |
| 464 } | |
| 465 | |
| 466 TEST_F(ParallelAuthenticatorTest, DriveRequestOldPassword) { | |
| 467 FailOnLoginSuccess(); | |
| 468 ExpectPasswordChange(); | |
| 469 | |
| 470 state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); | |
| 471 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); | |
| 472 SetAttemptState(auth_.get(), state_.release()); | |
| 473 | |
| 474 RunResolve(auth_.get()); | |
| 475 } | |
| 476 | |
| 477 TEST_F(ParallelAuthenticatorTest, DriveDataRecover) { | |
| 478 ExpectLoginSuccess(username_, | |
| 479 password_, | |
| 480 cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername, | |
| 481 false); | |
| 482 FailOnLoginFailure(); | |
| 483 | |
| 484 // Set up mock async method caller to respond successfully to a key migration. | |
| 485 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); | |
| 486 EXPECT_CALL(*mock_caller_, AsyncMigrateKey(username_, _, hash_ascii_, _)) | |
| 487 .Times(1) | |
| 488 .RetiresOnSaturation(); | |
| 489 EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_, | |
| 490 cryptohome::MOUNT_FLAGS_NONE, _)) | |
| 491 .Times(1) | |
| 492 .RetiresOnSaturation(); | |
| 493 EXPECT_CALL(*mock_caller_, AsyncGetSanitizedUsername(username_, _)) | |
| 494 .Times(1) | |
| 495 .RetiresOnSaturation(); | |
| 496 | |
| 497 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); | |
| 498 SetAttemptState(auth_.get(), state_.release()); | |
| 499 | |
| 500 auth_->RecoverEncryptedData(std::string()); | |
| 501 base::MessageLoop::current()->Run(); | |
| 502 } | |
| 503 | |
| 504 TEST_F(ParallelAuthenticatorTest, DriveDataRecoverButFail) { | |
| 505 FailOnLoginSuccess(); | |
| 506 ExpectPasswordChange(); | |
| 507 | |
| 508 // Set up mock async method caller to fail a key migration attempt, | |
| 509 // asserting that the wrong password was used. | |
| 510 mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); | |
| 511 EXPECT_CALL(*mock_caller_, AsyncMigrateKey(username_, _, hash_ascii_, _)) | |
| 512 .Times(1) | |
| 513 .RetiresOnSaturation(); | |
| 514 | |
| 515 SetAttemptState(auth_.get(), state_.release()); | |
| 516 | |
| 517 auth_->RecoverEncryptedData(std::string()); | |
| 518 base::MessageLoop::current()->Run(); | |
| 519 } | |
| 520 | |
| 521 TEST_F(ParallelAuthenticatorTest, ResolveNoMountToFailedMount) { | |
| 522 // Set up state as though a cryptohome mount attempt has occurred | |
| 523 // and been rejected because the user doesn't exist. | |
| 524 state_->PresetCryptohomeStatus(false, | |
| 525 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST); | |
| 526 | |
| 527 // When there is no online attempt and online results, NO_MOUNT will be | |
| 528 // resolved to FAILED_MOUNT. | |
| 529 EXPECT_EQ(ParallelAuthenticator::FAILED_MOUNT, | |
| 530 SetAndResolveState(auth_.get(), state_.release())); | |
| 531 } | |
| 532 | |
| 533 TEST_F(ParallelAuthenticatorTest, ResolveCreateNew) { | |
| 534 // Set up state as though a cryptohome mount attempt has occurred | |
| 535 // and been rejected because the user doesn't exist; additionally, | |
| 536 // an online auth attempt has completed successfully. | |
| 537 state_->PresetCryptohomeStatus(false, | |
| 538 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST); | |
| 539 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); | |
| 540 | |
| 541 EXPECT_EQ(ParallelAuthenticator::CREATE_NEW, | |
| 542 SetAndResolveState(auth_.get(), state_.release())); | |
| 543 } | |
| 544 | |
| 545 TEST_F(ParallelAuthenticatorTest, DriveCreateForNewUser) { | |
| 546 ExpectLoginSuccess(username_, | |
| 547 password_, | |
| 548 cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername, | |
| 549 false); | |
| 550 FailOnLoginFailure(); | |
| 551 | |
| 552 // Set up mock async method caller to respond successfully to a cryptohome | |
| 553 // create attempt (indicated by the |CREATE_IF_MISSING| flag to AsyncMount). | |
| 554 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); | |
| 555 EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_, | |
| 556 cryptohome::CREATE_IF_MISSING, _)) | |
| 557 .Times(1) | |
| 558 .RetiresOnSaturation(); | |
| 559 EXPECT_CALL(*mock_caller_, AsyncGetSanitizedUsername(username_, _)) | |
| 560 .Times(1) | |
| 561 .RetiresOnSaturation(); | |
| 562 | |
| 563 // Set up state as though a cryptohome mount attempt has occurred | |
| 564 // and been rejected because the user doesn't exist; additionally, | |
| 565 // an online auth attempt has completed successfully. | |
| 566 state_->PresetCryptohomeStatus(false, | |
| 567 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST); | |
| 568 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); | |
| 569 SetAttemptState(auth_.get(), state_.release()); | |
| 570 | |
| 571 RunResolve(auth_.get()); | |
| 572 } | |
| 573 | |
| 574 TEST_F(ParallelAuthenticatorTest, DriveOfflineLogin) { | |
| 575 ExpectLoginSuccess(username_, password_, username_hash_, false); | |
| 576 FailOnLoginFailure(); | |
| 577 | |
| 578 // Set up state as though a cryptohome mount attempt has occurred and | |
| 579 // succeeded. | |
| 580 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); | |
| 581 SetAttemptState(auth_.get(), state_.release()); | |
| 582 | |
| 583 RunResolve(auth_.get()); | |
| 584 } | |
| 585 | |
| 586 TEST_F(ParallelAuthenticatorTest, DriveOnlineLogin) { | |
| 587 ExpectLoginSuccess(username_, password_, username_hash_, false); | |
| 588 FailOnLoginFailure(); | |
| 589 | |
| 590 // Set up state as though a cryptohome mount attempt has occurred and | |
| 591 // succeeded. | |
| 592 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); | |
| 593 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); | |
| 594 SetAttemptState(auth_.get(), state_.release()); | |
| 595 | |
| 596 RunResolve(auth_.get()); | |
| 597 } | |
| 598 | |
| 599 TEST_F(ParallelAuthenticatorTest, DriveUnlock) { | |
| 600 ExpectLoginSuccess(username_, std::string(), std::string(), false); | |
| 601 FailOnLoginFailure(); | |
| 602 | |
| 603 // Set up mock async method caller to respond successfully to a cryptohome | |
| 604 // key-check attempt. | |
| 605 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); | |
| 606 EXPECT_CALL(*mock_caller_, AsyncCheckKey(username_, _, _)) | |
| 607 .Times(1) | |
| 608 .RetiresOnSaturation(); | |
| 609 | |
| 610 auth_->AuthenticateToUnlock(UserContext(username_, | |
| 611 std::string(), | |
| 612 std::string())); | |
| 613 base::MessageLoop::current()->Run(); | |
| 614 } | |
| 615 | |
| 616 } // namespace chromeos | |
| OLD | NEW |