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