1// Copyright (c) 2011 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#include <vector> 9 10#include "base/file_path.h" 11#include "base/file_util.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/message_loop.h" 14#include "base/path_service.h" 15#include "base/string_util.h" 16#include "base/stringprintf.h" 17#include "chrome/browser/chromeos/cros/mock_cryptohome_library.h" 18#include "chrome/browser/chromeos/cros/mock_library_loader.h" 19#include "chrome/browser/chromeos/login/mock_auth_response_handler.h" 20#include "chrome/browser/chromeos/login/mock_login_status_consumer.h" 21#include "chrome/browser/chromeos/login/mock_url_fetchers.h" 22#include "chrome/browser/chromeos/login/test_attempt_state.h" 23#include "chrome/common/chrome_paths.h" 24#include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h" 25#include "chrome/common/net/url_fetcher.h" 26#include "chrome/test/testing_profile.h" 27#include "chrome/test/thread_test_helper.h" 28#include "content/browser/browser_thread.h" 29#include "googleurl/src/gurl.h" 30#include "net/base/net_errors.h" 31#include "net/url_request/url_request_status.h" 32#include "testing/gmock/include/gmock/gmock.h" 33#include "testing/gtest/include/gtest/gtest.h" 34 35using namespace file_util; 36using ::testing::AnyNumber; 37using ::testing::DoAll; 38using ::testing::Invoke; 39using ::testing::Return; 40using ::testing::SetArgumentPointee; 41using ::testing::_; 42 43namespace chromeos { 44class ResolveChecker : public ThreadTestHelper { 45 public: 46 ResolveChecker(TestAttemptState* state, 47 ParallelAuthenticator* auth, 48 ParallelAuthenticator::AuthState expected) 49 : ThreadTestHelper(BrowserThread::IO), 50 state_(state), 51 auth_(auth), 52 expected_(expected) { 53 } 54 ~ResolveChecker() {} 55 56 virtual void RunTest() { 57 auth_->set_attempt_state(state_); 58 set_test_result(expected_ == auth_->ResolveState()); 59 } 60 61 private: 62 TestAttemptState* state_; 63 ParallelAuthenticator* auth_; 64 ParallelAuthenticator::AuthState expected_; 65}; 66 67class ParallelAuthenticatorTest : public ::testing::Test { 68 public: 69 ParallelAuthenticatorTest() 70 : message_loop_(MessageLoop::TYPE_UI), 71 ui_thread_(BrowserThread::UI, &message_loop_), 72 file_thread_(BrowserThread::FILE), 73 io_thread_(BrowserThread::IO), 74 username_("me@nowhere.org"), 75 password_("fakepass") { 76 hash_ascii_.assign("0a010000000000a0"); 77 hash_ascii_.append(std::string(16, '0')); 78 } 79 80 ~ParallelAuthenticatorTest() {} 81 82 virtual void SetUp() { 83 chromeos::CrosLibrary::TestApi* test_api = 84 chromeos::CrosLibrary::Get()->GetTestApi(); 85 86 loader_ = new MockLibraryLoader(); 87 ON_CALL(*loader_, Load(_)) 88 .WillByDefault(Return(true)); 89 EXPECT_CALL(*loader_, Load(_)) 90 .Times(AnyNumber()); 91 92 test_api->SetLibraryLoader(loader_, true); 93 94 mock_library_ = new MockCryptohomeLibrary(); 95 test_api->SetCryptohomeLibrary(mock_library_, true); 96 file_thread_.Start(); 97 io_thread_.Start(); 98 99 auth_ = new ParallelAuthenticator(&consumer_); 100 state_.reset(new TestAttemptState(username_, 101 password_, 102 hash_ascii_, 103 "", 104 "", 105 false)); 106 } 107 108 // Tears down the test fixture. 109 virtual void TearDown() { 110 // Prevent bogus gMock leak check from firing. 111 chromeos::CrosLibrary::TestApi* test_api = 112 chromeos::CrosLibrary::Get()->GetTestApi(); 113 test_api->SetLibraryLoader(NULL, false); 114 test_api->SetCryptohomeLibrary(NULL, false); 115 } 116 117 FilePath PopulateTempFile(const char* data, int data_len) { 118 FilePath out; 119 FILE* tmp_file = CreateAndOpenTemporaryFile(&out); 120 EXPECT_NE(tmp_file, static_cast<FILE*>(NULL)); 121 EXPECT_EQ(WriteFile(out, data, data_len), data_len); 122 EXPECT_TRUE(CloseFile(tmp_file)); 123 return out; 124 } 125 126 FilePath FakeLocalaccountFile(const std::string& ascii) { 127 FilePath exe_dir; 128 FilePath local_account_file; 129 PathService::Get(base::DIR_EXE, &exe_dir); 130 FILE* tmp_file = CreateAndOpenTemporaryFileInDir(exe_dir, 131 &local_account_file); 132 int ascii_len = ascii.length(); 133 EXPECT_NE(tmp_file, static_cast<FILE*>(NULL)); 134 EXPECT_EQ(WriteFile(local_account_file, ascii.c_str(), ascii_len), 135 ascii_len); 136 EXPECT_TRUE(CloseFile(tmp_file)); 137 return local_account_file; 138 } 139 140 void ReadLocalaccountFile(ParallelAuthenticator* auth, 141 const std::string& filename) { 142 BrowserThread::PostTask( 143 BrowserThread::FILE, FROM_HERE, 144 NewRunnableMethod(auth, 145 &ParallelAuthenticator::LoadLocalaccount, 146 filename)); 147 file_thread_.Stop(); 148 file_thread_.Start(); 149 } 150 151 // Allow test to fail and exit gracefully, even if OnLoginFailure() 152 // wasn't supposed to happen. 153 void FailOnLoginFailure() { 154 ON_CALL(consumer_, OnLoginFailure(_)) 155 .WillByDefault(Invoke(MockConsumer::OnFailQuitAndFail)); 156 } 157 158 // Allow test to fail and exit gracefully, even if OnLoginSuccess() 159 // wasn't supposed to happen. 160 void FailOnLoginSuccess() { 161 ON_CALL(consumer_, OnLoginSuccess(_, _, _, _)) 162 .WillByDefault(Invoke(MockConsumer::OnSuccessQuitAndFail)); 163 } 164 165 // Allow test to fail and exit gracefully, even if 166 // OnOffTheRecordLoginSuccess() wasn't supposed to happen. 167 void FailOnGuestLoginSuccess() { 168 ON_CALL(consumer_, OnOffTheRecordLoginSuccess()) 169 .WillByDefault(Invoke(MockConsumer::OnGuestSuccessQuitAndFail)); 170 } 171 172 void ExpectLoginFailure(const LoginFailure& failure) { 173 EXPECT_CALL(consumer_, OnLoginFailure(failure)) 174 .WillOnce(Invoke(MockConsumer::OnFailQuit)) 175 .RetiresOnSaturation(); 176 } 177 178 void ExpectLoginSuccess(const std::string& username, 179 const std::string& password, 180 const GaiaAuthConsumer::ClientLoginResult& result, 181 bool pending) { 182 EXPECT_CALL(consumer_, OnLoginSuccess(username, password, result, pending)) 183 .WillOnce(Invoke(MockConsumer::OnSuccessQuit)) 184 .RetiresOnSaturation(); 185 } 186 187 void ExpectGuestLoginSuccess() { 188 EXPECT_CALL(consumer_, OnOffTheRecordLoginSuccess()) 189 .WillOnce(Invoke(MockConsumer::OnGuestSuccessQuit)) 190 .RetiresOnSaturation(); 191 } 192 193 void ExpectPasswordChange() { 194 EXPECT_CALL(consumer_, OnPasswordChangeDetected(result_)) 195 .WillOnce(Invoke(MockConsumer::OnMigrateQuit)) 196 .RetiresOnSaturation(); 197 } 198 199 void RunResolve(ParallelAuthenticator* auth, MessageLoop* loop) { 200 BrowserThread::PostTask( 201 BrowserThread::IO, FROM_HERE, 202 NewRunnableMethod(auth, &ParallelAuthenticator::Resolve)); 203 loop->Run(); 204 } 205 206 void SetAttemptState(ParallelAuthenticator* auth, TestAttemptState* state) { 207 auth->set_attempt_state(state); 208 } 209 210 MessageLoop message_loop_; 211 BrowserThread ui_thread_; 212 BrowserThread file_thread_; 213 BrowserThread io_thread_; 214 215 std::string username_; 216 std::string password_; 217 std::string hash_ascii_; 218 GaiaAuthConsumer::ClientLoginResult result_; 219 220 // Mocks, destroyed by CrosLibrary class. 221 MockCryptohomeLibrary* mock_library_; 222 MockLibraryLoader* loader_; 223 224 MockConsumer consumer_; 225 scoped_refptr<ParallelAuthenticator> auth_; 226 scoped_ptr<TestAttemptState> state_; 227}; 228 229TEST_F(ParallelAuthenticatorTest, SaltToAscii) { 230 unsigned char fake_salt[8] = { 0 }; 231 fake_salt[0] = 10; 232 fake_salt[1] = 1; 233 fake_salt[7] = 10 << 4; 234 std::vector<unsigned char> salt_v(fake_salt, fake_salt + sizeof(fake_salt)); 235 236 ON_CALL(*mock_library_, GetSystemSalt()) 237 .WillByDefault(Return(salt_v)); 238 EXPECT_CALL(*mock_library_, GetSystemSalt()) 239 .Times(1) 240 .RetiresOnSaturation(); 241 242 EXPECT_EQ("0a010000000000a0", auth_->SaltAsAscii()); 243} 244 245TEST_F(ParallelAuthenticatorTest, ReadLocalaccount) { 246 FilePath tmp_file_path = FakeLocalaccountFile(username_); 247 248 ReadLocalaccountFile(auth_.get(), tmp_file_path.BaseName().value()); 249 EXPECT_EQ(auth_->localaccount_, username_); 250 Delete(tmp_file_path, false); 251} 252 253TEST_F(ParallelAuthenticatorTest, ReadLocalaccountTrailingWS) { 254 FilePath tmp_file_path = 255 FakeLocalaccountFile(base::StringPrintf("%s\n", username_.c_str())); 256 257 ReadLocalaccountFile(auth_.get(), tmp_file_path.BaseName().value()); 258 EXPECT_EQ(auth_->localaccount_, username_); 259 Delete(tmp_file_path, false); 260} 261 262TEST_F(ParallelAuthenticatorTest, ReadNoLocalaccount) { 263 FilePath tmp_file_path = FakeLocalaccountFile(username_); 264 EXPECT_TRUE(Delete(tmp_file_path, false)); // Ensure non-existent file. 265 266 ReadLocalaccountFile(auth_.get(), tmp_file_path.BaseName().value()); 267 EXPECT_EQ(auth_->localaccount_, std::string()); 268} 269 270TEST_F(ParallelAuthenticatorTest, OnLoginSuccess) { 271 EXPECT_CALL(consumer_, OnLoginSuccess(username_, password_, result_, false)) 272 .Times(1) 273 .RetiresOnSaturation(); 274 275 SetAttemptState(auth_, state_.release()); 276 auth_->OnLoginSuccess(result_, false); 277} 278 279TEST_F(ParallelAuthenticatorTest, OnPasswordChangeDetected) { 280 EXPECT_CALL(consumer_, OnPasswordChangeDetected(result_)) 281 .Times(1) 282 .RetiresOnSaturation(); 283 SetAttemptState(auth_, state_.release()); 284 auth_->OnPasswordChangeDetected(result_); 285} 286 287TEST_F(ParallelAuthenticatorTest, ResolveNothingDone) { 288 scoped_refptr<ResolveChecker> checker( 289 new ResolveChecker(state_.release(), 290 auth_.get(), 291 ParallelAuthenticator::CONTINUE)); 292 EXPECT_TRUE(checker->Run()); 293} 294 295TEST_F(ParallelAuthenticatorTest, ResolvePossiblePwChange) { 296 // Set up state as though a cryptohome mount attempt has occurred 297 // and been rejected. 298 state_->PresetCryptohomeStatus(false, 299 chromeos::kCryptohomeMountErrorKeyFailure); 300 scoped_refptr<ResolveChecker> checker( 301 new ResolveChecker(state_.release(), 302 auth_.get(), 303 ParallelAuthenticator::POSSIBLE_PW_CHANGE)); 304 EXPECT_TRUE(checker->Run()); 305} 306 307TEST_F(ParallelAuthenticatorTest, DriveFailedMount) { 308 FailOnLoginSuccess(); 309 ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME)); 310 311 // Set up state as though a cryptohome mount attempt has occurred 312 // and failed. 313 state_->PresetCryptohomeStatus(false, 0); 314 SetAttemptState(auth_, state_.release()); 315 316 RunResolve(auth_.get(), &message_loop_); 317} 318 319TEST_F(ParallelAuthenticatorTest, DriveGuestLogin) { 320 ExpectGuestLoginSuccess(); 321 FailOnLoginFailure(); 322 323 // Set up mock cryptohome library to respond as though a tmpfs mount 324 // attempt has occurred and succeeded. 325 mock_library_->SetUp(true, 0); 326 EXPECT_CALL(*mock_library_, AsyncMountForBwsi(_)) 327 .Times(1) 328 .RetiresOnSaturation(); 329 330 auth_->LoginOffTheRecord(); 331 message_loop_.Run(); 332} 333 334TEST_F(ParallelAuthenticatorTest, DriveGuestLoginButFail) { 335 FailOnGuestLoginSuccess(); 336 ExpectLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)); 337 338 // Set up mock cryptohome library to respond as though a tmpfs mount 339 // attempt has occurred and failed. 340 mock_library_->SetUp(false, 0); 341 EXPECT_CALL(*mock_library_, AsyncMountForBwsi(_)) 342 .Times(1) 343 .RetiresOnSaturation(); 344 345 auth_->LoginOffTheRecord(); 346 message_loop_.Run(); 347} 348 349TEST_F(ParallelAuthenticatorTest, DriveDataResync) { 350 ExpectLoginSuccess(username_, password_, result_, false); 351 FailOnLoginFailure(); 352 353 // Set up mock cryptohome library to respond successfully to a cryptohome 354 // remove attempt and a cryptohome create attempt (specified by the |true| 355 // argument to AsyncMount). 356 mock_library_->SetUp(true, 0); 357 EXPECT_CALL(*mock_library_, AsyncRemove(username_, _)) 358 .Times(1) 359 .RetiresOnSaturation(); 360 EXPECT_CALL(*mock_library_, AsyncMount(username_, hash_ascii_, true, _)) 361 .Times(1) 362 .RetiresOnSaturation(); 363 364 state_->PresetOnlineLoginStatus(result_, LoginFailure::None()); 365 SetAttemptState(auth_, state_.release()); 366 367 auth_->ResyncEncryptedData(result_); 368 message_loop_.Run(); 369} 370 371TEST_F(ParallelAuthenticatorTest, DriveResyncFail) { 372 FailOnLoginSuccess(); 373 ExpectLoginFailure(LoginFailure(LoginFailure::DATA_REMOVAL_FAILED)); 374 375 // Set up mock cryptohome library to fail a cryptohome remove attempt. 376 mock_library_->SetUp(false, 0); 377 EXPECT_CALL(*mock_library_, AsyncRemove(username_, _)) 378 .Times(1) 379 .RetiresOnSaturation(); 380 381 SetAttemptState(auth_, state_.release()); 382 383 auth_->ResyncEncryptedData(result_); 384 message_loop_.Run(); 385} 386 387TEST_F(ParallelAuthenticatorTest, DriveRequestOldPassword) { 388 FailOnLoginSuccess(); 389 ExpectPasswordChange(); 390 391 state_->PresetCryptohomeStatus(false, 392 chromeos::kCryptohomeMountErrorKeyFailure); 393 state_->PresetOnlineLoginStatus(result_, LoginFailure::None()); 394 SetAttemptState(auth_, state_.release()); 395 396 RunResolve(auth_.get(), &message_loop_); 397} 398 399TEST_F(ParallelAuthenticatorTest, DriveDataRecover) { 400 ExpectLoginSuccess(username_, password_, result_, false); 401 FailOnLoginFailure(); 402 403 // Set up mock cryptohome library to respond successfully to a key migration. 404 mock_library_->SetUp(true, 0); 405 EXPECT_CALL(*mock_library_, AsyncMigrateKey(username_, _, hash_ascii_, _)) 406 .Times(1) 407 .RetiresOnSaturation(); 408 EXPECT_CALL(*mock_library_, AsyncMount(username_, hash_ascii_, false, _)) 409 .Times(1) 410 .RetiresOnSaturation(); 411 EXPECT_CALL(*mock_library_, GetSystemSalt()) 412 .WillOnce(Return(CryptohomeBlob(2, 0))) 413 .RetiresOnSaturation(); 414 415 state_->PresetOnlineLoginStatus(result_, LoginFailure::None()); 416 SetAttemptState(auth_, state_.release()); 417 418 auth_->RecoverEncryptedData(std::string(), result_); 419 message_loop_.Run(); 420} 421 422TEST_F(ParallelAuthenticatorTest, DriveDataRecoverButFail) { 423 FailOnLoginSuccess(); 424 ExpectPasswordChange(); 425 426 // Set up mock cryptohome library to fail a key migration attempt, 427 // asserting that the wrong password was used. 428 mock_library_->SetUp(false, chromeos::kCryptohomeMountErrorKeyFailure); 429 EXPECT_CALL(*mock_library_, AsyncMigrateKey(username_, _, hash_ascii_, _)) 430 .Times(1) 431 .RetiresOnSaturation(); 432 EXPECT_CALL(*mock_library_, GetSystemSalt()) 433 .WillOnce(Return(CryptohomeBlob(2, 0))) 434 .RetiresOnSaturation(); 435 436 SetAttemptState(auth_, state_.release()); 437 438 auth_->RecoverEncryptedData(std::string(), result_); 439 message_loop_.Run(); 440} 441 442TEST_F(ParallelAuthenticatorTest, ResolveNoMount) { 443 // Set up state as though a cryptohome mount attempt has occurred 444 // and been rejected because the user doesn't exist. 445 state_->PresetCryptohomeStatus( 446 false, 447 chromeos::kCryptohomeMountErrorUserDoesNotExist); 448 scoped_refptr<ResolveChecker> checker( 449 new ResolveChecker(state_.release(), 450 auth_.get(), 451 ParallelAuthenticator::NO_MOUNT)); 452 EXPECT_TRUE(checker->Run()); 453} 454 455TEST_F(ParallelAuthenticatorTest, ResolveCreateNew) { 456 // Set up state as though a cryptohome mount attempt has occurred 457 // and been rejected because the user doesn't exist; additionally, 458 // an online auth attempt has completed successfully. 459 state_->PresetCryptohomeStatus( 460 false, 461 chromeos::kCryptohomeMountErrorUserDoesNotExist); 462 state_->PresetOnlineLoginStatus(GaiaAuthConsumer::ClientLoginResult(), 463 LoginFailure::None()); 464 scoped_refptr<ResolveChecker> checker( 465 new ResolveChecker(state_.release(), 466 auth_.get(), 467 ParallelAuthenticator::CREATE_NEW)); 468 EXPECT_TRUE(checker->Run()); 469} 470 471TEST_F(ParallelAuthenticatorTest, DriveCreateForNewUser) { 472 ExpectLoginSuccess(username_, password_, result_, false); 473 FailOnLoginFailure(); 474 475 // Set up mock cryptohome library to respond successfully to a cryptohome 476 // create attempt (specified by the |true| argument to AsyncMount). 477 mock_library_->SetUp(true, 0); 478 EXPECT_CALL(*mock_library_, AsyncMount(username_, hash_ascii_, true, _)) 479 .Times(1) 480 .RetiresOnSaturation(); 481 482 // Set up state as though a cryptohome mount attempt has occurred 483 // and been rejected because the user doesn't exist; additionally, 484 // an online auth attempt has completed successfully. 485 state_->PresetCryptohomeStatus( 486 false, 487 chromeos::kCryptohomeMountErrorUserDoesNotExist); 488 state_->PresetOnlineLoginStatus(GaiaAuthConsumer::ClientLoginResult(), 489 LoginFailure::None()); 490 SetAttemptState(auth_, state_.release()); 491 492 RunResolve(auth_.get(), &message_loop_); 493} 494 495TEST_F(ParallelAuthenticatorTest, DriveOfflineLogin) { 496 ExpectLoginSuccess(username_, password_, result_, false); 497 FailOnLoginFailure(); 498 499 // Set up state as though a cryptohome mount attempt has occurred and 500 // succeeded. 501 state_->PresetCryptohomeStatus(true, 0); 502 GoogleServiceAuthError error = 503 GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET); 504 state_->PresetOnlineLoginStatus(result_, 505 LoginFailure::FromNetworkAuthFailure(error)); 506 SetAttemptState(auth_, state_.release()); 507 508 RunResolve(auth_.get(), &message_loop_); 509} 510 511TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginDelayedOnline) { 512 ExpectLoginSuccess(username_, password_, result_, true); 513 FailOnLoginFailure(); 514 515 // Set up state as though a cryptohome mount attempt has occurred and 516 // succeeded. 517 state_->PresetCryptohomeStatus(true, 0); 518 // state_ is released further down. 519 SetAttemptState(auth_, state_.get()); 520 RunResolve(auth_.get(), &message_loop_); 521 522 // Offline login has completed, so now we "complete" the online request. 523 GoogleServiceAuthError error( 524 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 525 LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error); 526 state_.release()->PresetOnlineLoginStatus(result_, failure); 527 ExpectLoginFailure(failure); 528 529 RunResolve(auth_.get(), &message_loop_); 530} 531 532TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginGetNewPassword) { 533 ExpectLoginSuccess(username_, password_, result_, true); 534 FailOnLoginFailure(); 535 536 // Set up mock cryptohome library to respond successfully to a key migration. 537 mock_library_->SetUp(true, 0); 538 EXPECT_CALL(*mock_library_, AsyncMigrateKey(username_, 539 state_->ascii_hash, 540 _, 541 _)) 542 .Times(1) 543 .RetiresOnSaturation(); 544 EXPECT_CALL(*mock_library_, GetSystemSalt()) 545 .WillOnce(Return(CryptohomeBlob(2, 0))) 546 .RetiresOnSaturation(); 547 548 // Set up state as though a cryptohome mount attempt has occurred and 549 // succeeded; also, an online request that never made it. 550 state_->PresetCryptohomeStatus(true, 0); 551 // state_ is released further down. 552 SetAttemptState(auth_, state_.get()); 553 RunResolve(auth_.get(), &message_loop_); 554 555 // Offline login has completed, so now we "complete" the online request. 556 GoogleServiceAuthError error( 557 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 558 LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error); 559 state_.release()->PresetOnlineLoginStatus(result_, failure); 560 ExpectLoginFailure(failure); 561 562 RunResolve(auth_.get(), &message_loop_); 563 564 // After the request below completes, OnLoginSuccess gets called again. 565 ExpectLoginSuccess(username_, password_, result_, false); 566 567 MockFactory<SuccessFetcher> factory; 568 URLFetcher::set_factory(&factory); 569 TestingProfile profile; 570 571 auth_->RetryAuth(&profile, 572 username_, 573 std::string(), 574 std::string(), 575 std::string()); 576 message_loop_.Run(); 577} 578 579TEST_F(ParallelAuthenticatorTest, DriveOfflineLoginGetCaptchad) { 580 ExpectLoginSuccess(username_, password_, result_, true); 581 FailOnLoginFailure(); 582 EXPECT_CALL(*mock_library_, GetSystemSalt()) 583 .WillOnce(Return(CryptohomeBlob(2, 0))) 584 .RetiresOnSaturation(); 585 586 // Set up state as though a cryptohome mount attempt has occurred and 587 // succeeded; also, an online request that never made it. 588 state_->PresetCryptohomeStatus(true, 0); 589 // state_ is released further down. 590 SetAttemptState(auth_, state_.get()); 591 RunResolve(auth_.get(), &message_loop_); 592 593 // Offline login has completed, so now we "complete" the online request. 594 GoogleServiceAuthError error( 595 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 596 LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error); 597 state_.release()->PresetOnlineLoginStatus(result_, failure); 598 ExpectLoginFailure(failure); 599 600 RunResolve(auth_.get(), &message_loop_); 601 602 // After the request below completes, OnLoginSuccess gets called again. 603 failure = LoginFailure::FromNetworkAuthFailure( 604 GoogleServiceAuthError::FromCaptchaChallenge( 605 CaptchaFetcher::GetCaptchaToken(), 606 GURL(CaptchaFetcher::GetCaptchaUrl()), 607 GURL(CaptchaFetcher::GetUnlockUrl()))); 608 ExpectLoginFailure(failure); 609 610 MockFactory<CaptchaFetcher> factory; 611 URLFetcher::set_factory(&factory); 612 TestingProfile profile; 613 614 auth_->RetryAuth(&profile, 615 username_, 616 std::string(), 617 std::string(), 618 std::string()); 619 message_loop_.Run(); 620} 621 622TEST_F(ParallelAuthenticatorTest, DriveOnlineLogin) { 623 GaiaAuthConsumer::ClientLoginResult success("sid", "lsid", "", ""); 624 ExpectLoginSuccess(username_, password_, success, false); 625 FailOnLoginFailure(); 626 627 // Set up state as though a cryptohome mount attempt has occurred and 628 // succeeded. 629 state_->PresetCryptohomeStatus(true, 0); 630 state_->PresetOnlineLoginStatus(success, LoginFailure::None()); 631 SetAttemptState(auth_, state_.release()); 632 633 RunResolve(auth_.get(), &message_loop_); 634} 635 636TEST_F(ParallelAuthenticatorTest, DriveNeedNewPassword) { 637 FailOnLoginSuccess(); // Set failing on success as the default... 638 // ...but expect ONE successful login first. 639 ExpectLoginSuccess(username_, password_, result_, true); 640 GoogleServiceAuthError error( 641 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 642 LoginFailure failure = LoginFailure::FromNetworkAuthFailure(error); 643 ExpectLoginFailure(failure); 644 645 // Set up state as though a cryptohome mount attempt has occurred and 646 // succeeded. 647 state_->PresetCryptohomeStatus(true, 0); 648 state_->PresetOnlineLoginStatus(result_, failure); 649 SetAttemptState(auth_, state_.release()); 650 651 RunResolve(auth_.get(), &message_loop_); 652} 653 654TEST_F(ParallelAuthenticatorTest, DriveLocalLogin) { 655 ExpectGuestLoginSuccess(); 656 FailOnLoginFailure(); 657 658 // Set up mock cryptohome library to respond as though a tmpfs mount 659 // attempt has occurred and succeeded. 660 mock_library_->SetUp(true, 0); 661 EXPECT_CALL(*mock_library_, AsyncMountForBwsi(_)) 662 .Times(1) 663 .RetiresOnSaturation(); 664 665 // Pre-set test state as though an online login attempt failed to complete, 666 // and that a cryptohome mount attempt failed because the user doesn't exist. 667 GoogleServiceAuthError error = 668 GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET); 669 LoginFailure failure = 670 LoginFailure::FromNetworkAuthFailure(error); 671 state_->PresetOnlineLoginStatus(result_, failure); 672 state_->PresetCryptohomeStatus( 673 false, 674 chromeos::kCryptohomeMountErrorUserDoesNotExist); 675 SetAttemptState(auth_, state_.release()); 676 677 // Deal with getting the localaccount file 678 FilePath tmp_file_path = FakeLocalaccountFile(username_); 679 ReadLocalaccountFile(auth_.get(), tmp_file_path.BaseName().value()); 680 681 RunResolve(auth_.get(), &message_loop_); 682 683 Delete(tmp_file_path, false); 684} 685 686TEST_F(ParallelAuthenticatorTest, DriveUnlock) { 687 ExpectLoginSuccess(username_, std::string(), result_, false); 688 FailOnLoginFailure(); 689 690 // Set up mock cryptohome library to respond successfully to a cryptohome 691 // key-check attempt. 692 mock_library_->SetUp(true, 0); 693 EXPECT_CALL(*mock_library_, AsyncCheckKey(username_, _, _)) 694 .Times(1) 695 .RetiresOnSaturation(); 696 EXPECT_CALL(*mock_library_, GetSystemSalt()) 697 .WillOnce(Return(CryptohomeBlob(2, 0))) 698 .RetiresOnSaturation(); 699 700 auth_->AuthenticateToUnlock(username_, ""); 701 message_loop_.Run(); 702} 703 704TEST_F(ParallelAuthenticatorTest, DriveLocalUnlock) { 705 ExpectLoginSuccess(username_, std::string(), result_, false); 706 FailOnLoginFailure(); 707 708 // Set up mock cryptohome library to fail a cryptohome key-check 709 // attempt. 710 mock_library_->SetUp(false, 0); 711 EXPECT_CALL(*mock_library_, AsyncCheckKey(username_, _, _)) 712 .Times(1) 713 .RetiresOnSaturation(); 714 EXPECT_CALL(*mock_library_, GetSystemSalt()) 715 .WillOnce(Return(CryptohomeBlob(2, 0))) 716 .RetiresOnSaturation(); 717 718 // Deal with getting the localaccount file 719 FilePath tmp_file_path = FakeLocalaccountFile(username_); 720 ReadLocalaccountFile(auth_.get(), tmp_file_path.BaseName().value()); 721 722 auth_->AuthenticateToUnlock(username_, ""); 723 message_loop_.Run(); 724 725 Delete(tmp_file_path, false); 726} 727 728} // namespace chromeos 729