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