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