parallel_authenticator_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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.h" 13#include "base/string_util.h" 14#include "base/stringprintf.h" 15#include "chrome/browser/chromeos/cros/cros_library.h" 16#include "chrome/browser/chromeos/cros/mock_cert_library.h" 17#include "chrome/browser/chromeos/cros/mock_cryptohome_library.h" 18#include "chrome/browser/chromeos/login/mock_login_status_consumer.h" 19#include "chrome/browser/chromeos/login/mock_url_fetchers.h" 20#include "chrome/browser/chromeos/login/mock_user_manager.h" 21#include "chrome/browser/chromeos/login/test_attempt_state.h" 22#include "chrome/browser/chromeos/login/user.h" 23#include "chrome/browser/chromeos/settings/cros_settings.h" 24#include "chrome/browser/chromeos/settings/device_settings_test_helper.h" 25#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" 26#include "chrome/test/base/testing_profile.h" 27#include "chromeos/cryptohome/mock_async_method_caller.h" 28#include "chromeos/dbus/mock_cryptohome_client.h" 29#include "chromeos/dbus/mock_dbus_thread_manager.h" 30#include "content/public/test/test_browser_thread.h" 31#include "google_apis/gaia/mock_url_fetcher_factory.h" 32#include "googleurl/src/gurl.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 39using ::testing::AnyNumber; 40using ::testing::DoAll; 41using ::testing::Invoke; 42using ::testing::Return; 43using ::testing::SetArgPointee; 44using ::testing::_; 45using content::BrowserThread; 46 47namespace chromeos { 48 49class TestOnlineAttempt : public OnlineAttempt { 50 public: 51 TestOnlineAttempt(AuthAttemptState* state, 52 AuthAttemptStateResolver* resolver) 53 : OnlineAttempt(state, resolver) { 54 } 55}; 56 57class ParallelAuthenticatorTest : public testing::Test { 58 public: 59 ParallelAuthenticatorTest() 60 : message_loop_(MessageLoop::TYPE_UI), 61 ui_thread_(BrowserThread::UI, &message_loop_), 62 file_thread_(BrowserThread::FILE, &message_loop_), 63 io_thread_(BrowserThread::IO), 64 username_("me@nowhere.org"), 65 password_("fakepass") { 66 hash_ascii_.assign("0a010000000000a0"); 67 hash_ascii_.append(std::string(16, '0')); 68 } 69 70 virtual ~ParallelAuthenticatorTest() { 71 DCHECK(!mock_caller_); 72 } 73 74 virtual void SetUp() { 75 mock_caller_ = new cryptohome::MockAsyncMethodCaller; 76 cryptohome::AsyncMethodCaller::InitializeForTesting(mock_caller_); 77 78 chromeos::CrosLibrary::TestApi* test_api = 79 chromeos::CrosLibrary::Get()->GetTestApi(); 80 81 mock_cryptohome_library_ = new MockCryptohomeLibrary(); 82 test_api->SetCryptohomeLibrary(mock_cryptohome_library_, true); 83 84 mock_cert_library_ = new MockCertLibrary(); 85 EXPECT_CALL(*mock_cert_library_, LoadKeyStore()).Times(AnyNumber()); 86 test_api->SetCertLibrary(mock_cert_library_, true); 87 88 io_thread_.Start(); 89 90 auth_ = new ParallelAuthenticator(&consumer_); 91 auth_->set_using_oauth(false); 92 state_.reset(new TestAttemptState(UserCredentials(username_, 93 password_, 94 std::string()), 95 hash_ascii_, 96 "", 97 "", 98 User::USER_TYPE_REGULAR, 99 false)); 100 } 101 102 // Tears down the test fixture. 103 virtual void TearDown() { 104 // Prevent bogus gMock leak check from firing. 105 chromeos::CrosLibrary::TestApi* test_api = 106 chromeos::CrosLibrary::Get()->GetTestApi(); 107 test_api->SetCryptohomeLibrary(NULL, false); 108 109 cryptohome::AsyncMethodCaller::Shutdown(); 110 mock_caller_ = NULL; 111 } 112 113 base::FilePath PopulateTempFile(const char* data, int data_len) { 114 base::FilePath out; 115 FILE* tmp_file = file_util::CreateAndOpenTemporaryFile(&out); 116 EXPECT_NE(tmp_file, static_cast<FILE*>(NULL)); 117 EXPECT_EQ(file_util::WriteFile(out, data, data_len), data_len); 118 EXPECT_TRUE(file_util::CloseFile(tmp_file)); 119 return out; 120 } 121 122 // Allow test to fail and exit gracefully, even if OnLoginFailure() 123 // wasn't supposed to happen. 124 void FailOnLoginFailure() { 125 ON_CALL(consumer_, OnLoginFailure(_)) 126 .WillByDefault(Invoke(MockConsumer::OnFailQuitAndFail)); 127 } 128 129 // Allow test to fail and exit gracefully, even if 130 // OnRetailModeLoginSuccess() wasn't supposed to happen. 131 void FailOnRetailModeLoginSuccess() { 132 ON_CALL(consumer_, OnRetailModeLoginSuccess()) 133 .WillByDefault(Invoke(MockConsumer::OnRetailModeSuccessQuitAndFail)); 134 } 135 136 // Allow test to fail and exit gracefully, even if OnLoginSuccess() 137 // wasn't supposed to happen. 138 void FailOnLoginSuccess() { 139 ON_CALL(consumer_, OnLoginSuccess(_, _, _)) 140 .WillByDefault(Invoke(MockConsumer::OnSuccessQuitAndFail)); 141 } 142 143 // Allow test to fail and exit gracefully, even if 144 // OnOffTheRecordLoginSuccess() wasn't supposed to happen. 145 void FailOnGuestLoginSuccess() { 146 ON_CALL(consumer_, OnOffTheRecordLoginSuccess()) 147 .WillByDefault(Invoke(MockConsumer::OnGuestSuccessQuitAndFail)); 148 } 149 150 void ExpectLoginFailure(const LoginFailure& failure) { 151 EXPECT_CALL(consumer_, OnLoginFailure(failure)) 152 .WillOnce(Invoke(MockConsumer::OnFailQuit)) 153 .RetiresOnSaturation(); 154 } 155 156 void ExpectRetailModeLoginSuccess() { 157 EXPECT_CALL(consumer_, OnRetailModeLoginSuccess()) 158 .WillOnce(Invoke(MockConsumer::OnRetailModeSuccessQuit)) 159 .RetiresOnSaturation(); 160 } 161 162 void ExpectLoginSuccess(const std::string& username, 163 const std::string& password, 164 bool pending) { 165 EXPECT_CALL(consumer_, OnLoginSuccess(UserCredentials(username, 166 password, 167 std::string()), 168 pending, 169 false)) 170 .WillOnce(Invoke(MockConsumer::OnSuccessQuit)) 171 .RetiresOnSaturation(); 172 } 173 174 void ExpectGuestLoginSuccess() { 175 EXPECT_CALL(consumer_, OnOffTheRecordLoginSuccess()) 176 .WillOnce(Invoke(MockConsumer::OnGuestSuccessQuit)) 177 .RetiresOnSaturation(); 178 } 179 180 void ExpectPasswordChange() { 181 EXPECT_CALL(consumer_, OnPasswordChangeDetected()) 182 .WillOnce(Invoke(MockConsumer::OnMigrateQuit)) 183 .RetiresOnSaturation(); 184 } 185 186 void RunResolve(ParallelAuthenticator* auth) { 187 auth->Resolve(); 188 message_loop_.RunUntilIdle(); 189 } 190 191 void SetAttemptState(ParallelAuthenticator* auth, TestAttemptState* state) { 192 auth->set_attempt_state(state); 193 } 194 195 ParallelAuthenticator::AuthState SetAndResolveState( 196 ParallelAuthenticator* auth, TestAttemptState* state) { 197 auth->set_attempt_state(state); 198 return auth->ResolveState(); 199 } 200 201 void SetOwnerState(bool owner_check_finished, bool check_result) { 202 auth_->SetOwnerState(owner_check_finished, check_result); 203 } 204 205 void FakeOnlineAttempt() { 206 auth_->set_online_attempt(new TestOnlineAttempt(state_.get(), auth_.get())); 207 } 208 209 MessageLoop message_loop_; 210 content::TestBrowserThread ui_thread_; 211 content::TestBrowserThread file_thread_; 212 content::TestBrowserThread io_thread_; 213 214 std::string username_; 215 std::string password_; 216 std::string hash_ascii_; 217 218 ScopedDeviceSettingsTestHelper device_settings_test_helper_; 219 220 // Initializes / shuts down a stub CrosLibrary. 221 ScopedStubCrosEnabler stub_cros_enabler_; 222 223 // Mocks, destroyed by CrosLibrary class. 224 MockCertLibrary* mock_cert_library_; 225 MockCryptohomeLibrary* mock_cryptohome_library_; 226 ScopedMockUserManagerEnabler mock_user_manager_; 227 228 cryptohome::MockAsyncMethodCaller* mock_caller_; 229 230 MockConsumer consumer_; 231 scoped_refptr<ParallelAuthenticator> auth_; 232 scoped_ptr<TestAttemptState> state_; 233}; 234 235TEST_F(ParallelAuthenticatorTest, OnLoginSuccess) { 236 EXPECT_CALL(consumer_, OnLoginSuccess(UserCredentials(username_, 237 password_, 238 std::string()), 239 false, false)) 240 .Times(1) 241 .RetiresOnSaturation(); 242 243 SetAttemptState(auth_, state_.release()); 244 auth_->OnLoginSuccess(false); 245} 246 247TEST_F(ParallelAuthenticatorTest, OnPasswordChangeDetected) { 248 EXPECT_CALL(consumer_, OnPasswordChangeDetected()) 249 .Times(1) 250 .RetiresOnSaturation(); 251 SetAttemptState(auth_, state_.release()); 252 auth_->OnPasswordChangeDetected(); 253} 254 255TEST_F(ParallelAuthenticatorTest, ResolveNothingDone) { 256 EXPECT_EQ(ParallelAuthenticator::CONTINUE, 257 SetAndResolveState(auth_, state_.release())); 258} 259 260TEST_F(ParallelAuthenticatorTest, ResolvePossiblePwChange) { 261 // Set a fake online attempt so that we return intermediate cryptohome state. 262 FakeOnlineAttempt(); 263 264 // Set up state as though a cryptohome mount attempt has occurred 265 // and been rejected. 266 state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); 267 268 EXPECT_EQ(ParallelAuthenticator::POSSIBLE_PW_CHANGE, 269 SetAndResolveState(auth_, state_.release())); 270} 271 272TEST_F(ParallelAuthenticatorTest, ResolvePossiblePwChangeToFailedMount) { 273 // Set up state as though a cryptohome mount attempt has occurred 274 // and been rejected. 275 state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); 276 277 // When there is no online attempt and online results, POSSIBLE_PW_CHANGE 278 EXPECT_EQ(ParallelAuthenticator::FAILED_MOUNT, 279 SetAndResolveState(auth_, state_.release())); 280} 281 282TEST_F(ParallelAuthenticatorTest, ResolveNeedOldPw) { 283 // Set up state as though a cryptohome mount attempt has occurred 284 // and been rejected because of unmatched key; additionally, 285 // an online auth attempt has completed successfully. 286 state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); 287 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); 288 289 EXPECT_EQ(ParallelAuthenticator::NEED_OLD_PW, 290 SetAndResolveState(auth_, state_.release())); 291} 292 293TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededDirectFailedMount) { 294 // Set up state as though a cryptohome mount attempt has occurred 295 // and succeeded but we are in safe mode and the current user is not owner. 296 // This is a high level test to verify the proper transitioning in this mode 297 // only. It is not testing that we properly verify that the user is an owner 298 // or that we really are in "safe-mode". 299 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 300 SetOwnerState(true, false); 301 302 EXPECT_EQ(ParallelAuthenticator::OWNER_REQUIRED, 303 SetAndResolveState(auth_, state_.release())); 304} 305 306TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededMount) { 307 // Set up state as though a cryptohome mount attempt has occurred 308 // and succeeded but we are in safe mode and the current user is not owner. 309 // This test will check that the "safe-mode" policy is not set and will let 310 // the mount finish successfully. 311 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 312 SetOwnerState(false, false); 313 // and test that the mount has succeeded. 314 state_.reset(new TestAttemptState(UserCredentials(username_, 315 password_, 316 std::string()), 317 hash_ascii_, 318 "", 319 "", 320 User::USER_TYPE_REGULAR, 321 false)); 322 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 323 EXPECT_EQ(ParallelAuthenticator::OFFLINE_LOGIN, 324 SetAndResolveState(auth_, state_.release())); 325} 326 327TEST_F(ParallelAuthenticatorTest, ResolveOwnerNeededFailedMount) { 328 FailOnLoginSuccess(); // Set failing on success as the default... 329 LoginFailure failure = LoginFailure(LoginFailure::OWNER_REQUIRED); 330 ExpectLoginFailure(failure); 331 332 MockDBusThreadManager* mock_dbus_thread_manager = 333 new MockDBusThreadManager; 334 EXPECT_CALL(*mock_dbus_thread_manager, GetSystemBus()) 335 .WillRepeatedly(Return(reinterpret_cast<dbus::Bus*>(NULL))); 336 DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager); 337 EXPECT_CALL(*mock_dbus_thread_manager->mock_cryptohome_client(), Unmount(_)) 338 .WillOnce(DoAll(SetArgPointee<0>(true), Return(true))); 339 340 CrosSettingsProvider* device_settings_provider; 341 StubCrosSettingsProvider stub_settings_provider; 342 // Set up state as though a cryptohome mount attempt has occurred 343 // and succeeded but we are in safe mode and the current user is not owner. 344 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 345 SetOwnerState(false, false); 346 // Remove the real DeviceSettingsProvider and replace it with a stub. 347 device_settings_provider = 348 CrosSettings::Get()->GetProvider(chromeos::kReportDeviceVersionInfo); 349 EXPECT_TRUE(device_settings_provider != NULL); 350 EXPECT_TRUE( 351 CrosSettings::Get()->RemoveSettingsProvider(device_settings_provider)); 352 CrosSettings::Get()->AddSettingsProvider(&stub_settings_provider); 353 CrosSettings::Get()->SetBoolean(kPolicyMissingMitigationMode, true); 354 355 EXPECT_EQ(ParallelAuthenticator::CONTINUE, 356 SetAndResolveState(auth_, state_.release())); 357 // Let the owner verification run. 358 device_settings_test_helper_.Flush(); 359 // and test that the mount has succeeded. 360 state_.reset(new TestAttemptState(UserCredentials(username_, 361 password_, 362 std::string()), 363 hash_ascii_, 364 "", 365 "", 366 User::USER_TYPE_REGULAR, 367 false)); 368 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 369 EXPECT_EQ(ParallelAuthenticator::OWNER_REQUIRED, 370 SetAndResolveState(auth_, state_.release())); 371 372 EXPECT_TRUE( 373 CrosSettings::Get()->RemoveSettingsProvider(&stub_settings_provider)); 374 CrosSettings::Get()->AddSettingsProvider(device_settings_provider); 375 DBusThreadManager::Get()->Shutdown(); 376} 377 378TEST_F(ParallelAuthenticatorTest, DriveFailedMount) { 379 FailOnLoginSuccess(); 380 ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME)); 381 382 // Set up state as though a cryptohome mount attempt has occurred 383 // and failed. 384 state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_NONE); 385 SetAttemptState(auth_, state_.release()); 386 387 RunResolve(auth_.get()); 388} 389 390TEST_F(ParallelAuthenticatorTest, DriveGuestLogin) { 391 ExpectGuestLoginSuccess(); 392 FailOnLoginFailure(); 393 394 // Set up mock cryptohome library to respond as though a tmpfs mount 395 // attempt has occurred and succeeded. 396 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); 397 EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) 398 .Times(1) 399 .RetiresOnSaturation(); 400 401 auth_->LoginOffTheRecord(); 402 message_loop_.Run(); 403} 404 405TEST_F(ParallelAuthenticatorTest, DriveGuestLoginButFail) { 406 FailOnGuestLoginSuccess(); 407 ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)); 408 409 // Set up mock cryptohome library to respond as though a tmpfs mount 410 // attempt has occurred and failed. 411 mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE); 412 EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) 413 .Times(1) 414 .RetiresOnSaturation(); 415 416 auth_->LoginOffTheRecord(); 417 message_loop_.Run(); 418} 419 420TEST_F(ParallelAuthenticatorTest, DriveRetailModeUserLogin) { 421 ExpectRetailModeLoginSuccess(); 422 FailOnLoginFailure(); 423 424 // Set up mock cryptohome library to respond as though a tmpfs mount 425 // attempt has occurred and succeeded. 426 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); 427 EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) 428 .Times(1) 429 .RetiresOnSaturation(); 430 431 auth_->LoginRetailMode(); 432 message_loop_.Run(); 433} 434 435TEST_F(ParallelAuthenticatorTest, DriveRetailModeLoginButFail) { 436 FailOnRetailModeLoginSuccess(); 437 ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)); 438 439 // Set up mock cryptohome library to respond as though a tmpfs mount 440 // attempt has occurred and failed. 441 mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE); 442 EXPECT_CALL(*mock_caller_, AsyncMountGuest(_)) 443 .Times(1) 444 .RetiresOnSaturation(); 445 446 auth_->LoginRetailMode(); 447 message_loop_.Run(); 448} 449 450TEST_F(ParallelAuthenticatorTest, DriveDataResync) { 451 ExpectLoginSuccess(username_, password_, false); 452 FailOnLoginFailure(); 453 454 // Set up mock cryptohome library to respond successfully to a cryptohome 455 // remove attempt and a cryptohome create attempt (indicated by the 456 // |CREATE_IF_MISSING| flag to AsyncMount). 457 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); 458 EXPECT_CALL(*mock_caller_, AsyncRemove(username_, _)) 459 .Times(1) 460 .RetiresOnSaturation(); 461 EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_, 462 cryptohome::CREATE_IF_MISSING, _)) 463 .Times(1) 464 .RetiresOnSaturation(); 465 466 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); 467 SetAttemptState(auth_, state_.release()); 468 469 auth_->ResyncEncryptedData(); 470 message_loop_.Run(); 471} 472 473TEST_F(ParallelAuthenticatorTest, DriveResyncFail) { 474 FailOnLoginSuccess(); 475 ExpectLoginFailure(LoginFailure(LoginFailure::DATA_REMOVAL_FAILED)); 476 477 // Set up mock cryptohome library to fail a cryptohome remove attempt. 478 mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_NONE); 479 EXPECT_CALL(*mock_caller_, AsyncRemove(username_, _)) 480 .Times(1) 481 .RetiresOnSaturation(); 482 483 SetAttemptState(auth_, state_.release()); 484 485 auth_->ResyncEncryptedData(); 486 message_loop_.Run(); 487} 488 489TEST_F(ParallelAuthenticatorTest, DriveRequestOldPassword) { 490 FailOnLoginSuccess(); 491 ExpectPasswordChange(); 492 493 state_->PresetCryptohomeStatus(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); 494 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); 495 SetAttemptState(auth_, state_.release()); 496 497 RunResolve(auth_.get()); 498} 499 500TEST_F(ParallelAuthenticatorTest, DriveDataRecover) { 501 ExpectLoginSuccess(username_, password_, false); 502 FailOnLoginFailure(); 503 504 // Set up mock cryptohome library to respond successfully to a key migration. 505 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); 506 EXPECT_CALL(*mock_caller_, AsyncMigrateKey(username_, _, hash_ascii_, _)) 507 .Times(1) 508 .RetiresOnSaturation(); 509 EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_, 510 cryptohome::MOUNT_FLAGS_NONE, _)) 511 .Times(1) 512 .RetiresOnSaturation(); 513 EXPECT_CALL(*mock_cryptohome_library_, GetSystemSalt()) 514 .WillOnce(Return(std::string())) 515 .RetiresOnSaturation(); 516 517 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); 518 SetAttemptState(auth_, state_.release()); 519 520 auth_->RecoverEncryptedData(std::string()); 521 message_loop_.Run(); 522} 523 524TEST_F(ParallelAuthenticatorTest, DriveDataRecoverButFail) { 525 FailOnLoginSuccess(); 526 ExpectPasswordChange(); 527 528 // Set up mock cryptohome library to fail a key migration attempt, 529 // asserting that the wrong password was used. 530 mock_caller_->SetUp(false, cryptohome::MOUNT_ERROR_KEY_FAILURE); 531 EXPECT_CALL(*mock_caller_, AsyncMigrateKey(username_, _, hash_ascii_, _)) 532 .Times(1) 533 .RetiresOnSaturation(); 534 EXPECT_CALL(*mock_cryptohome_library_, GetSystemSalt()) 535 .WillOnce(Return(std::string())) 536 .RetiresOnSaturation(); 537 538 SetAttemptState(auth_, state_.release()); 539 540 auth_->RecoverEncryptedData(std::string()); 541 message_loop_.Run(); 542} 543 544TEST_F(ParallelAuthenticatorTest, ResolveNoMount) { 545 // Set a fake online attempt so that we return intermediate cryptohome state. 546 FakeOnlineAttempt(); 547 548 // Set up state as though a cryptohome mount attempt has occurred 549 // and been rejected because the user doesn't exist. 550 state_->PresetCryptohomeStatus(false, 551 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST); 552 553 EXPECT_EQ(ParallelAuthenticator::NO_MOUNT, 554 SetAndResolveState(auth_, state_.release())); 555} 556 557TEST_F(ParallelAuthenticatorTest, ResolveNoMountToFailedMount) { 558 // Set up state as though a cryptohome mount attempt has occurred 559 // and been rejected because the user doesn't exist. 560 state_->PresetCryptohomeStatus(false, 561 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST); 562 563 // When there is no online attempt and online results, NO_MOUNT will be 564 // resolved to FAILED_MOUNT. 565 EXPECT_EQ(ParallelAuthenticator::FAILED_MOUNT, 566 SetAndResolveState(auth_, state_.release())); 567} 568 569TEST_F(ParallelAuthenticatorTest, ResolveCreateNew) { 570 // Set up state as though a cryptohome mount attempt has occurred 571 // and been rejected because the user doesn't exist; additionally, 572 // an online auth attempt has completed successfully. 573 state_->PresetCryptohomeStatus(false, 574 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST); 575 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); 576 577 EXPECT_EQ(ParallelAuthenticator::CREATE_NEW, 578 SetAndResolveState(auth_, state_.release())); 579} 580 581TEST_F(ParallelAuthenticatorTest, DriveCreateForNewUser) { 582 ExpectLoginSuccess(username_, password_, false); 583 FailOnLoginFailure(); 584 585 // Set up mock cryptohome library to respond successfully to a cryptohome 586 // create attempt (indicated by the |CREATE_IF_MISSING| flag to AsyncMount). 587 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); 588 EXPECT_CALL(*mock_caller_, AsyncMount(username_, hash_ascii_, 589 cryptohome::CREATE_IF_MISSING, _)) 590 .Times(1) 591 .RetiresOnSaturation(); 592 593 // Set up state as though a cryptohome mount attempt has occurred 594 // and been rejected because the user doesn't exist; additionally, 595 // an online auth attempt has completed successfully. 596 state_->PresetCryptohomeStatus(false, 597 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST); 598 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); 599 SetAttemptState(auth_, state_.release()); 600 601 RunResolve(auth_.get()); 602} 603 604TEST_F(ParallelAuthenticatorTest, DriveOfflineLogin) { 605 ExpectLoginSuccess(username_, password_, false); 606 FailOnLoginFailure(); 607 608 // Set up state as though a cryptohome mount attempt has occurred and 609 // succeeded. 610 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 611 GoogleServiceAuthError error = 612 GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET); 613 state_->PresetOnlineLoginStatus(LoginFailure::FromNetworkAuthFailure(error)); 614 SetAttemptState(auth_, state_.release()); 615 616 RunResolve(auth_.get()); 617} 618 619TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginDelayedOnline) { 620 ExpectLoginSuccess(username_, password_, true); 621 FailOnLoginFailure(); 622 623 // Set up state as though a cryptohome mount attempt has occurred and 624 // succeeded. 625 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 626 // state_ is released further down. 627 SetAttemptState(auth_, state_.get()); 628 RunResolve(auth_.get()); 629 630 // Offline login has completed, so now we "complete" the online request. 631 GoogleServiceAuthError error( 632 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 633 LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error); 634 state_.release()->PresetOnlineLoginStatus(failure); 635 ExpectLoginFailure(failure); 636 637 RunResolve(auth_.get()); 638} 639 640TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginGetNewPassword) { 641 ExpectLoginSuccess(username_, password_, true); 642 FailOnLoginFailure(); 643 644 // Set up mock cryptohome library to respond successfully to a key migration. 645 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); 646 EXPECT_CALL(*mock_caller_, AsyncMigrateKey(username_, 647 state_->ascii_hash, 648 _, 649 _)) 650 .Times(1) 651 .RetiresOnSaturation(); 652 EXPECT_CALL(*mock_cryptohome_library_, GetSystemSalt()) 653 .WillOnce(Return(std::string())) 654 .RetiresOnSaturation(); 655 656 // Set up state as though a cryptohome mount attempt has occurred and 657 // succeeded; also, an online request that never made it. 658 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 659 // state_ is released further down. 660 SetAttemptState(auth_, state_.get()); 661 RunResolve(auth_.get()); 662 663 // Offline login has completed, so now we "complete" the online request. 664 GoogleServiceAuthError error( 665 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 666 LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error); 667 state_.release()->PresetOnlineLoginStatus(failure); 668 ExpectLoginFailure(failure); 669 670 RunResolve(auth_.get()); 671 672 // After the request below completes, OnLoginSuccess gets called again. 673 ExpectLoginSuccess(username_, password_, false); 674 675 MockURLFetcherFactory<SuccessFetcher> factory; 676 TestingProfile profile; 677 678 auth_->RetryAuth(&profile, 679 UserCredentials(username_, 680 std::string(), 681 std::string()), 682 std::string(), 683 std::string()); 684 message_loop_.Run(); 685 message_loop_.RunUntilIdle(); 686} 687 688TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginGetCaptchad) { 689 ExpectLoginSuccess(username_, password_, true); 690 FailOnLoginFailure(); 691 EXPECT_CALL(*mock_cryptohome_library_, GetSystemSalt()) 692 .WillOnce(Return(std::string())) 693 .RetiresOnSaturation(); 694 695 // Set up state as though a cryptohome mount attempt has occurred and 696 // succeeded; also, an online request that never made it. 697 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 698 // state_ is released further down. 699 SetAttemptState(auth_, state_.get()); 700 RunResolve(auth_.get()); 701 702 // Offline login has completed, so now we "complete" the online request. 703 GoogleServiceAuthError error( 704 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 705 LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error); 706 state_.release()->PresetOnlineLoginStatus(failure); 707 ExpectLoginFailure(failure); 708 709 RunResolve(auth_.get()); 710 711 // After the request below completes, OnLoginSuccess gets called again. 712 failure = LoginFailure::FromNetworkAuthFailure( 713 GoogleServiceAuthError::FromClientLoginCaptchaChallenge( 714 CaptchaFetcher::GetCaptchaToken(), 715 GURL(CaptchaFetcher::GetCaptchaUrl()), 716 GURL(CaptchaFetcher::GetUnlockUrl()))); 717 ExpectLoginFailure(failure); 718 719 MockURLFetcherFactory<CaptchaFetcher> factory; 720 TestingProfile profile; 721 722 auth_->RetryAuth(&profile, 723 UserCredentials(username_, 724 std::string(), 725 std::string()), 726 std::string(), 727 std::string()); 728 message_loop_.Run(); 729 message_loop_.RunUntilIdle(); 730} 731 732TEST_F(ParallelAuthenticatorTest, DriveOnlineLogin) { 733 ExpectLoginSuccess(username_, password_, false); 734 FailOnLoginFailure(); 735 736 // Set up state as though a cryptohome mount attempt has occurred and 737 // succeeded. 738 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 739 state_->PresetOnlineLoginStatus(LoginFailure::LoginFailureNone()); 740 SetAttemptState(auth_, state_.release()); 741 742 RunResolve(auth_.get()); 743} 744 745// http://crbug.com/106538 746TEST_F(ParallelAuthenticatorTest, DISABLED_DriveNeedNewPassword) { 747 FailOnLoginSuccess(); // Set failing on success as the default... 748 // ...but expect ONE successful login first. 749 ExpectLoginSuccess(username_, password_, true); 750 GoogleServiceAuthError error( 751 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 752 LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error); 753 ExpectLoginFailure(failure); 754 755 // Set up state as though a cryptohome mount attempt has occurred and 756 // succeeded. 757 state_->PresetCryptohomeStatus(true, cryptohome::MOUNT_ERROR_NONE); 758 state_->PresetOnlineLoginStatus(failure); 759 SetAttemptState(auth_, state_.release()); 760 761 RunResolve(auth_.get()); 762} 763 764TEST_F(ParallelAuthenticatorTest, DriveUnlock) { 765 ExpectLoginSuccess(username_, std::string(), false); 766 FailOnLoginFailure(); 767 768 // Set up mock cryptohome library to respond successfully to a cryptohome 769 // key-check attempt. 770 mock_caller_->SetUp(true, cryptohome::MOUNT_ERROR_NONE); 771 EXPECT_CALL(*mock_caller_, AsyncCheckKey(username_, _, _)) 772 .Times(1) 773 .RetiresOnSaturation(); 774 EXPECT_CALL(*mock_cryptohome_library_, GetSystemSalt()) 775 .WillOnce(Return(std::string())) 776 .RetiresOnSaturation(); 777 778 auth_->AuthenticateToUnlock(UserCredentials(username_, 779 std::string(), 780 std::string())); 781 message_loop_.Run(); 782} 783 784} // namespace chromeos 785