Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: chrome/browser/chromeos/login/auth/parallel_authenticator.cc

Issue 495563003: Move ParallelAuthnticator to chromeos and rename it to CryptohomeAuthenticator (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 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/auth/parallel_authenticator.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "chrome/browser/chromeos/ownership/owner_settings_service.h"
12 #include "chrome/browser/chromeos/settings/cros_settings.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "chromeos/cryptohome/async_method_caller.h"
15 #include "chromeos/cryptohome/system_salt_getter.h"
16 #include "chromeos/dbus/cryptohome_client.h"
17 #include "chromeos/dbus/dbus_thread_manager.h"
18 #include "chromeos/login/auth/auth_status_consumer.h"
19 #include "chromeos/login/auth/key.h"
20 #include "chromeos/login/auth/user_context.h"
21 #include "chromeos/login/login_state.h"
22 #include "chromeos/login/user_names.h"
23 #include "chromeos/login_event_recorder.h"
24 #include "components/user_manager/user_manager.h"
25 #include "components/user_manager/user_type.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "third_party/cros_system_api/dbus/service_constants.h"
28
29 using content::BrowserThread;
30
31 namespace chromeos {
32
33 namespace {
34
35 // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN.
36 // Returns the keys unmodified otherwise.
37 scoped_ptr<Key> TransformKeyIfNeeded(const Key& key,
38 const std::string& system_salt) {
39 scoped_ptr<Key> result(new Key(key));
40 if (result->GetKeyType() == Key::KEY_TYPE_PASSWORD_PLAIN)
41 result->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, system_salt);
42
43 return result.Pass();
44 }
45
46 // Records status and calls resolver->Resolve().
47 void TriggerResolve(AuthAttemptState* attempt,
48 scoped_refptr<ParallelAuthenticator> resolver,
49 bool success,
50 cryptohome::MountError return_code) {
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
52 attempt->RecordCryptohomeStatus(success, return_code);
53 resolver->Resolve();
54 }
55
56 // Records get hash status and calls resolver->Resolve().
57 void TriggerResolveHash(AuthAttemptState* attempt,
58 scoped_refptr<ParallelAuthenticator> resolver,
59 bool success,
60 const std::string& username_hash) {
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
62 if (success)
63 attempt->RecordUsernameHash(username_hash);
64 else
65 attempt->RecordUsernameHashFailed();
66 resolver->Resolve();
67 }
68
69 // Calls TriggerResolve while adding login time marker.
70 void TriggerResolveWithLoginTimeMarker(
71 const std::string& marker_name,
72 AuthAttemptState* attempt,
73 scoped_refptr<ParallelAuthenticator> resolver,
74 bool success,
75 cryptohome::MountError return_code) {
76 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(marker_name, false);
77 TriggerResolve(attempt, resolver, success, return_code);
78 }
79
80 // Calls cryptohome's mount method.
81 void Mount(AuthAttemptState* attempt,
82 scoped_refptr<ParallelAuthenticator> resolver,
83 int flags,
84 const std::string& system_salt) {
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
86 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(
87 "CryptohomeMount-Start", false);
88 // Set state that username_hash is requested here so that test implementation
89 // that returns directly would not generate 2 OnLoginSucces() calls.
90 attempt->UsernameHashRequested();
91
92 scoped_ptr<Key> key =
93 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt);
94 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMount(
95 attempt->user_context.GetUserID(),
96 key->GetSecret(),
97 flags,
98 base::Bind(&TriggerResolveWithLoginTimeMarker,
99 "CryptohomeMount-End",
100 attempt,
101 resolver));
102 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
103 attempt->user_context.GetUserID(),
104 base::Bind(&TriggerResolveHash,
105 attempt,
106 resolver));
107 }
108
109 // Calls cryptohome's mount method for guest.
110 void MountGuest(AuthAttemptState* attempt,
111 scoped_refptr<ParallelAuthenticator> resolver) {
112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
113 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest(
114 base::Bind(&TriggerResolveWithLoginTimeMarker,
115 "CryptohomeMount-End",
116 attempt,
117 resolver));
118 }
119
120 // Calls cryptohome's mount method for guest and also get the user hash from
121 // cryptohome.
122 void MountGuestAndGetHash(AuthAttemptState* attempt,
123 scoped_refptr<ParallelAuthenticator> resolver) {
124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
125 attempt->UsernameHashRequested();
126 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest(
127 base::Bind(&TriggerResolveWithLoginTimeMarker,
128 "CryptohomeMount-End",
129 attempt,
130 resolver));
131 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
132 attempt->user_context.GetUserID(),
133 base::Bind(&TriggerResolveHash,
134 attempt,
135 resolver));
136 }
137
138 // Calls cryptohome's MountPublic method
139 void MountPublic(AuthAttemptState* attempt,
140 scoped_refptr<ParallelAuthenticator> resolver,
141 int flags) {
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
143 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountPublic(
144 attempt->user_context.GetUserID(),
145 flags,
146 base::Bind(&TriggerResolveWithLoginTimeMarker,
147 "CryptohomeMountPublic-End",
148 attempt,
149 resolver));
150 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
151 attempt->user_context.GetUserID(),
152 base::Bind(&TriggerResolveHash,
153 attempt,
154 resolver));
155 }
156
157 // Calls cryptohome's key migration method.
158 void Migrate(AuthAttemptState* attempt,
159 scoped_refptr<ParallelAuthenticator> resolver,
160 bool passing_old_hash,
161 const std::string& old_password,
162 const std::string& system_salt) {
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
164 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(
165 "CryptohomeMigrate-Start", false);
166 cryptohome::AsyncMethodCaller* caller =
167 cryptohome::AsyncMethodCaller::GetInstance();
168
169 // TODO(bartfab): Retrieve the hashing algorithm and salt to use for |old_key|
170 // from cryptohomed.
171 scoped_ptr<Key> old_key =
172 TransformKeyIfNeeded(Key(old_password), system_salt);
173 scoped_ptr<Key> new_key =
174 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt);
175 if (passing_old_hash) {
176 caller->AsyncMigrateKey(attempt->user_context.GetUserID(),
177 old_key->GetSecret(),
178 new_key->GetSecret(),
179 base::Bind(&TriggerResolveWithLoginTimeMarker,
180 "CryptohomeMount-End",
181 attempt,
182 resolver));
183 } else {
184 caller->AsyncMigrateKey(attempt->user_context.GetUserID(),
185 new_key->GetSecret(),
186 old_key->GetSecret(),
187 base::Bind(&TriggerResolveWithLoginTimeMarker,
188 "CryptohomeMount-End",
189 attempt,
190 resolver));
191 }
192 }
193
194 // Calls cryptohome's remove method.
195 void Remove(AuthAttemptState* attempt,
196 scoped_refptr<ParallelAuthenticator> resolver) {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
198 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(
199 "CryptohomeRemove-Start", false);
200 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
201 attempt->user_context.GetUserID(),
202 base::Bind(&TriggerResolveWithLoginTimeMarker,
203 "CryptohomeRemove-End",
204 attempt,
205 resolver));
206 }
207
208 // Calls cryptohome's key check method.
209 void CheckKey(AuthAttemptState* attempt,
210 scoped_refptr<ParallelAuthenticator> resolver,
211 const std::string& system_salt) {
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
213 scoped_ptr<Key> key =
214 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt);
215 cryptohome::AsyncMethodCaller::GetInstance()->AsyncCheckKey(
216 attempt->user_context.GetUserID(),
217 key->GetSecret(),
218 base::Bind(&TriggerResolve, attempt, resolver));
219 }
220
221 } // namespace
222
223 ParallelAuthenticator::ParallelAuthenticator(AuthStatusConsumer* consumer)
224 : Authenticator(consumer),
225 migrate_attempted_(false),
226 remove_attempted_(false),
227 resync_attempted_(false),
228 ephemeral_mount_attempted_(false),
229 check_key_attempted_(false),
230 already_reported_success_(false),
231 owner_is_verified_(false),
232 user_can_login_(false),
233 remove_user_data_on_failure_(false),
234 delayed_login_failure_(NULL) {
235 }
236
237 void ParallelAuthenticator::AuthenticateToLogin(
238 Profile* profile,
239 const UserContext& user_context) {
240 authentication_profile_ = profile;
241 current_state_.reset(
242 new AuthAttemptState(user_context,
243 user_manager::USER_TYPE_REGULAR,
244 false, // unlock
245 false, // online_complete
246 !user_manager::UserManager::Get()->IsKnownUser(
247 user_context.GetUserID())));
248 // Reset the verified flag.
249 owner_is_verified_ = false;
250
251 SystemSaltGetter::Get()->GetSystemSalt(
252 base::Bind(&Mount,
253 current_state_.get(),
254 scoped_refptr<ParallelAuthenticator>(this),
255 cryptohome::MOUNT_FLAGS_NONE));
256 }
257
258 void ParallelAuthenticator::CompleteLogin(Profile* profile,
259 const UserContext& user_context) {
260 authentication_profile_ = profile;
261 current_state_.reset(
262 new AuthAttemptState(user_context,
263 user_manager::USER_TYPE_REGULAR,
264 true, // unlock
265 false, // online_complete
266 !user_manager::UserManager::Get()->IsKnownUser(
267 user_context.GetUserID())));
268
269 // Reset the verified flag.
270 owner_is_verified_ = false;
271
272 SystemSaltGetter::Get()->GetSystemSalt(
273 base::Bind(&Mount,
274 current_state_.get(),
275 scoped_refptr<ParallelAuthenticator>(this),
276 cryptohome::MOUNT_FLAGS_NONE));
277
278 // For login completion from extension, we just need to resolve the current
279 // auth attempt state, the rest of OAuth related tasks will be done in
280 // parallel.
281 BrowserThread::PostTask(
282 BrowserThread::UI, FROM_HERE,
283 base::Bind(&ParallelAuthenticator::ResolveLoginCompletionStatus, this));
284 }
285
286 void ParallelAuthenticator::AuthenticateToUnlock(
287 const UserContext& user_context) {
288 current_state_.reset(new AuthAttemptState(user_context,
289 user_manager::USER_TYPE_REGULAR,
290 true, // unlock
291 true, // online_complete
292 false)); // user_is_new
293 remove_user_data_on_failure_ = false;
294 check_key_attempted_ = true;
295 SystemSaltGetter::Get()->GetSystemSalt(
296 base::Bind(&CheckKey,
297 current_state_.get(),
298 scoped_refptr<ParallelAuthenticator>(this)));
299 }
300
301 void ParallelAuthenticator::LoginAsSupervisedUser(
302 const UserContext& user_context) {
303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
304 // TODO(nkostylev): Pass proper value for |user_is_new| or remove (not used).
305 current_state_.reset(
306 new AuthAttemptState(user_context,
307 user_manager::USER_TYPE_SUPERVISED,
308 false, // unlock
309 false, // online_complete
310 false)); // user_is_new
311 remove_user_data_on_failure_ = false;
312 SystemSaltGetter::Get()->GetSystemSalt(
313 base::Bind(&Mount,
314 current_state_.get(),
315 scoped_refptr<ParallelAuthenticator>(this),
316 cryptohome::MOUNT_FLAGS_NONE));
317 }
318
319 void ParallelAuthenticator::LoginRetailMode() {
320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
321 // Note: |kRetailModeUserEMail| is used in other places to identify a retail
322 // mode session.
323 current_state_.reset(
324 new AuthAttemptState(UserContext(chromeos::login::kRetailModeUserName),
325 user_manager::USER_TYPE_RETAIL_MODE,
326 false, // unlock
327 false, // online_complete
328 false)); // user_is_new
329 remove_user_data_on_failure_ = false;
330 ephemeral_mount_attempted_ = true;
331 MountGuestAndGetHash(current_state_.get(),
332 scoped_refptr<ParallelAuthenticator>(this));
333 }
334
335 void ParallelAuthenticator::LoginOffTheRecord() {
336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
337 current_state_.reset(
338 new AuthAttemptState(UserContext(chromeos::login::kGuestUserName),
339 user_manager::USER_TYPE_GUEST,
340 false, // unlock
341 false, // online_complete
342 false)); // user_is_new
343 remove_user_data_on_failure_ = false;
344 ephemeral_mount_attempted_ = true;
345 MountGuest(current_state_.get(),
346 scoped_refptr<ParallelAuthenticator>(this));
347 }
348
349 void ParallelAuthenticator::LoginAsPublicSession(
350 const UserContext& user_context) {
351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
352 current_state_.reset(
353 new AuthAttemptState(user_context,
354 user_manager::USER_TYPE_PUBLIC_ACCOUNT,
355 false, // unlock
356 false, // online_complete
357 false)); // user_is_new
358 remove_user_data_on_failure_ = false;
359 ephemeral_mount_attempted_ = true;
360 SystemSaltGetter::Get()->GetSystemSalt(
361 base::Bind(&Mount,
362 current_state_.get(),
363 scoped_refptr<ParallelAuthenticator>(this),
364 cryptohome::CREATE_IF_MISSING | cryptohome::ENSURE_EPHEMERAL));
365 }
366
367 void ParallelAuthenticator::LoginAsKioskAccount(
368 const std::string& app_user_id,
369 bool use_guest_mount) {
370 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
371
372 const std::string user_id =
373 use_guest_mount ? chromeos::login::kGuestUserName : app_user_id;
374 current_state_.reset(new AuthAttemptState(UserContext(user_id),
375 user_manager::USER_TYPE_KIOSK_APP,
376 false, // unlock
377 false, // online_complete
378 false)); // user_is_new
379
380 remove_user_data_on_failure_ = true;
381 if (!use_guest_mount) {
382 MountPublic(current_state_.get(),
383 scoped_refptr<ParallelAuthenticator>(this),
384 cryptohome::CREATE_IF_MISSING);
385 } else {
386 ephemeral_mount_attempted_ = true;
387 MountGuestAndGetHash(current_state_.get(),
388 scoped_refptr<ParallelAuthenticator>(this));
389 }
390 }
391
392 void ParallelAuthenticator::OnRetailModeAuthSuccess() {
393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
394 VLOG(1) << "Retail mode login success";
395 chromeos::LoginEventRecorder::Get()->RecordAuthenticationSuccess();
396 if (consumer_)
397 consumer_->OnRetailModeAuthSuccess(current_state_->user_context);
398 }
399
400 void ParallelAuthenticator::OnAuthSuccess() {
401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
402 VLOG(1) << "Login success";
403 // Send notification of success
404 chromeos::LoginEventRecorder::Get()->RecordAuthenticationSuccess();
405 {
406 base::AutoLock for_this_block(success_lock_);
407 already_reported_success_ = true;
408 }
409 if (consumer_)
410 consumer_->OnAuthSuccess(current_state_->user_context);
411 }
412
413 void ParallelAuthenticator::OnOffTheRecordAuthSuccess() {
414 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
415 chromeos::LoginEventRecorder::Get()->RecordAuthenticationSuccess();
416 if (consumer_)
417 consumer_->OnOffTheRecordAuthSuccess();
418 }
419
420 void ParallelAuthenticator::OnPasswordChangeDetected() {
421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
422 if (consumer_)
423 consumer_->OnPasswordChangeDetected();
424 }
425
426 void ParallelAuthenticator::OnAuthFailure(const AuthFailure& error) {
427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
428
429 // OnAuthFailure will be called again with the same |error|
430 // after the cryptohome has been removed.
431 if (remove_user_data_on_failure_) {
432 delayed_login_failure_ = &error;
433 RemoveEncryptedData();
434 return;
435 }
436 chromeos::LoginEventRecorder::Get()->RecordAuthenticationFailure();
437 LOG(WARNING) << "Login failed: " << error.GetErrorString();
438 if (consumer_)
439 consumer_->OnAuthFailure(error);
440 }
441
442 void ParallelAuthenticator::RecoverEncryptedData(
443 const std::string& old_password) {
444 migrate_attempted_ = true;
445 current_state_->ResetCryptohomeStatus();
446 SystemSaltGetter::Get()->GetSystemSalt(
447 base::Bind(&Migrate,
448 current_state_.get(),
449 scoped_refptr<ParallelAuthenticator>(this),
450 true,
451 old_password));
452 }
453
454 void ParallelAuthenticator::RemoveEncryptedData() {
455 remove_attempted_ = true;
456 current_state_->ResetCryptohomeStatus();
457 BrowserThread::PostTask(
458 BrowserThread::UI, FROM_HERE,
459 base::Bind(&Remove,
460 current_state_.get(),
461 scoped_refptr<ParallelAuthenticator>(this)));
462 }
463
464 void ParallelAuthenticator::ResyncEncryptedData() {
465 resync_attempted_ = true;
466 current_state_->ResetCryptohomeStatus();
467 BrowserThread::PostTask(
468 BrowserThread::UI, FROM_HERE,
469 base::Bind(&Remove,
470 current_state_.get(),
471 scoped_refptr<ParallelAuthenticator>(this)));
472 }
473
474 bool ParallelAuthenticator::VerifyOwner() {
475 if (owner_is_verified_)
476 return true;
477 // Check if policy data is fine and continue in safe mode if needed.
478 bool is_safe_mode = false;
479 CrosSettings::Get()->GetBoolean(kPolicyMissingMitigationMode, &is_safe_mode);
480 if (!is_safe_mode) {
481 // Now we can continue with the login and report mount success.
482 user_can_login_ = true;
483 owner_is_verified_ = true;
484 return true;
485 }
486
487 const std::string& user_id = current_state_->user_context.GetUserID();
488
489 // |IsOwnerForSafeModeAsync| expects logged in state to be
490 // LOGGED_IN_SAFE_MODE.
491 if (LoginState::IsInitialized()) {
492 LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_SAFE_MODE,
493 LoginState::LOGGED_IN_USER_NONE);
494 }
495
496 OwnerSettingsService::IsOwnerForSafeModeAsync(
497 user_id,
498 current_state_->user_context.GetUserIDHash(),
499 base::Bind(&ParallelAuthenticator::OnOwnershipChecked, this));
500 return false;
501 }
502
503 void ParallelAuthenticator::OnOwnershipChecked(bool is_owner) {
504 // Now we can check if this user is the owner.
505 user_can_login_ = is_owner;
506 owner_is_verified_ = true;
507 Resolve();
508 }
509
510 void ParallelAuthenticator::Resolve() {
511 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
512 int mount_flags = cryptohome::MOUNT_FLAGS_NONE;
513 ParallelAuthenticator::AuthState state = ResolveState();
514 VLOG(1) << "Resolved state to: " << state;
515 switch (state) {
516 case CONTINUE:
517 case POSSIBLE_PW_CHANGE:
518 case NO_MOUNT:
519 // These are intermediate states; we need more info from a request that
520 // is still pending.
521 break;
522 case FAILED_MOUNT:
523 // In this case, whether login succeeded or not, we can't log
524 // the user in because their data is horked. So, override with
525 // the appropriate failure.
526 BrowserThread::PostTask(
527 BrowserThread::UI,
528 FROM_HERE,
529 base::Bind(&ParallelAuthenticator::OnAuthFailure,
530 this,
531 AuthFailure(AuthFailure::COULD_NOT_MOUNT_CRYPTOHOME)));
532 break;
533 case FAILED_REMOVE:
534 // In this case, we tried to remove the user's old cryptohome at her
535 // request, and the remove failed.
536 remove_user_data_on_failure_ = false;
537 BrowserThread::PostTask(
538 BrowserThread::UI,
539 FROM_HERE,
540 base::Bind(&ParallelAuthenticator::OnAuthFailure,
541 this,
542 AuthFailure(AuthFailure::DATA_REMOVAL_FAILED)));
543 break;
544 case FAILED_TMPFS:
545 // In this case, we tried to mount a tmpfs for guest and failed.
546 BrowserThread::PostTask(
547 BrowserThread::UI,
548 FROM_HERE,
549 base::Bind(&ParallelAuthenticator::OnAuthFailure,
550 this,
551 AuthFailure(AuthFailure::COULD_NOT_MOUNT_TMPFS)));
552 break;
553 case FAILED_TPM:
554 // In this case, we tried to create/mount cryptohome and failed
555 // because of the critical TPM error.
556 // Chrome will notify user and request reboot.
557 BrowserThread::PostTask(BrowserThread::UI,
558 FROM_HERE,
559 base::Bind(&ParallelAuthenticator::OnAuthFailure,
560 this,
561 AuthFailure(AuthFailure::TPM_ERROR)));
562 break;
563 case FAILED_USERNAME_HASH:
564 // In this case, we failed the GetSanitizedUsername request to
565 // cryptohomed. This can happen for any login attempt.
566 BrowserThread::PostTask(
567 BrowserThread::UI,
568 FROM_HERE,
569 base::Bind(&ParallelAuthenticator::OnAuthFailure,
570 this,
571 AuthFailure(AuthFailure::USERNAME_HASH_FAILED)));
572 break;
573 case REMOVED_DATA_AFTER_FAILURE:
574 remove_user_data_on_failure_ = false;
575 BrowserThread::PostTask(BrowserThread::UI,
576 FROM_HERE,
577 base::Bind(&ParallelAuthenticator::OnAuthFailure,
578 this,
579 *delayed_login_failure_));
580 break;
581 case CREATE_NEW:
582 mount_flags |= cryptohome::CREATE_IF_MISSING;
583 case RECOVER_MOUNT:
584 current_state_->ResetCryptohomeStatus();
585 SystemSaltGetter::Get()->GetSystemSalt(
586 base::Bind(&Mount,
587 current_state_.get(),
588 scoped_refptr<ParallelAuthenticator>(this),
589 mount_flags));
590 break;
591 case NEED_OLD_PW:
592 BrowserThread::PostTask(
593 BrowserThread::UI, FROM_HERE,
594 base::Bind(&ParallelAuthenticator::OnPasswordChangeDetected, this));
595 break;
596 case ONLINE_FAILED:
597 case NEED_NEW_PW:
598 case HAVE_NEW_PW:
599 NOTREACHED() << "Using obsolete ClientLogin code path.";
600 break;
601 case OFFLINE_LOGIN:
602 VLOG(2) << "Offline login";
603 // Fall through.
604 case UNLOCK:
605 VLOG(2) << "Unlock";
606 // Fall through.
607 case ONLINE_LOGIN:
608 VLOG(2) << "Online login";
609 BrowserThread::PostTask(
610 BrowserThread::UI,
611 FROM_HERE,
612 base::Bind(&ParallelAuthenticator::OnAuthSuccess, this));
613 break;
614 case DEMO_LOGIN:
615 VLOG(2) << "Retail mode login";
616 current_state_->user_context.SetIsUsingOAuth(false);
617 BrowserThread::PostTask(
618 BrowserThread::UI,
619 FROM_HERE,
620 base::Bind(&ParallelAuthenticator::OnRetailModeAuthSuccess, this));
621 break;
622 case GUEST_LOGIN:
623 BrowserThread::PostTask(
624 BrowserThread::UI,
625 FROM_HERE,
626 base::Bind(&ParallelAuthenticator::OnOffTheRecordAuthSuccess, this));
627 break;
628 case KIOSK_ACCOUNT_LOGIN:
629 case PUBLIC_ACCOUNT_LOGIN:
630 current_state_->user_context.SetIsUsingOAuth(false);
631 BrowserThread::PostTask(
632 BrowserThread::UI,
633 FROM_HERE,
634 base::Bind(&ParallelAuthenticator::OnAuthSuccess, this));
635 break;
636 case SUPERVISED_USER_LOGIN:
637 current_state_->user_context.SetIsUsingOAuth(false);
638 BrowserThread::PostTask(
639 BrowserThread::UI,
640 FROM_HERE,
641 base::Bind(&ParallelAuthenticator::OnAuthSuccess, this));
642 break;
643 case LOGIN_FAILED:
644 current_state_->ResetCryptohomeStatus();
645 BrowserThread::PostTask(BrowserThread::UI,
646 FROM_HERE,
647 base::Bind(&ParallelAuthenticator::OnAuthFailure,
648 this,
649 current_state_->online_outcome()));
650 break;
651 case OWNER_REQUIRED: {
652 current_state_->ResetCryptohomeStatus();
653 bool success = false;
654 DBusThreadManager::Get()->GetCryptohomeClient()->Unmount(&success);
655 if (!success) {
656 // Maybe we should reboot immediately here?
657 LOG(ERROR) << "Couldn't unmount users home!";
658 }
659 BrowserThread::PostTask(
660 BrowserThread::UI,
661 FROM_HERE,
662 base::Bind(&ParallelAuthenticator::OnAuthFailure,
663 this,
664 AuthFailure(AuthFailure::OWNER_REQUIRED)));
665 break;
666 }
667 default:
668 NOTREACHED();
669 break;
670 }
671 }
672
673 ParallelAuthenticator::~ParallelAuthenticator() {}
674
675 ParallelAuthenticator::AuthState ParallelAuthenticator::ResolveState() {
676 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
677 // If we haven't mounted the user's home dir yet or
678 // haven't got sanitized username value, we can't be done.
679 // We never get past here if any of these two cryptohome ops is still pending.
680 // This is an important invariant.
681 if (!current_state_->cryptohome_complete() ||
682 !current_state_->username_hash_obtained()) {
683 return CONTINUE;
684 }
685
686 AuthState state = CONTINUE;
687
688 if (current_state_->cryptohome_outcome() &&
689 current_state_->username_hash_valid()) {
690 state = ResolveCryptohomeSuccessState();
691 } else {
692 state = ResolveCryptohomeFailureState();
693 }
694
695 DCHECK(current_state_->cryptohome_complete()); // Ensure invariant holds.
696 migrate_attempted_ = false;
697 remove_attempted_ = false;
698 resync_attempted_ = false;
699 ephemeral_mount_attempted_ = false;
700 check_key_attempted_ = false;
701
702 if (state != POSSIBLE_PW_CHANGE &&
703 state != NO_MOUNT &&
704 state != OFFLINE_LOGIN)
705 return state;
706
707 if (current_state_->online_complete()) {
708 if (current_state_->online_outcome().reason() == AuthFailure::NONE) {
709 // Online attempt succeeded as well, so combine the results.
710 return ResolveOnlineSuccessState(state);
711 }
712 NOTREACHED() << "Using obsolete ClientLogin code path.";
713 }
714 // if online isn't complete yet, just return the offline result.
715 return state;
716 }
717
718 ParallelAuthenticator::AuthState
719 ParallelAuthenticator::ResolveCryptohomeFailureState() {
720 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
721 if (remove_attempted_ || resync_attempted_)
722 return FAILED_REMOVE;
723 if (ephemeral_mount_attempted_)
724 return FAILED_TMPFS;
725 if (migrate_attempted_)
726 return NEED_OLD_PW;
727 if (check_key_attempted_)
728 return LOGIN_FAILED;
729
730 if (current_state_->cryptohome_code() ==
731 cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
732 // Critical TPM error detected, reboot needed.
733 return FAILED_TPM;
734 }
735
736 // Return intermediate states in the following case:
737 // when there is an online result to use;
738 // This is the case after user finishes Gaia login;
739 if (current_state_->online_complete()) {
740 if (current_state_->cryptohome_code() ==
741 cryptohome::MOUNT_ERROR_KEY_FAILURE) {
742 // If we tried a mount but they used the wrong key, we may need to
743 // ask the user for her old password. We'll only know once we've
744 // done the online check.
745 return POSSIBLE_PW_CHANGE;
746 }
747 if (current_state_->cryptohome_code() ==
748 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) {
749 // If we tried a mount but the user did not exist, then we should wait
750 // for online login to succeed and try again with the "create" flag set.
751 return NO_MOUNT;
752 }
753 }
754
755 if (!current_state_->username_hash_valid())
756 return FAILED_USERNAME_HASH;
757
758 return FAILED_MOUNT;
759 }
760
761 ParallelAuthenticator::AuthState
762 ParallelAuthenticator::ResolveCryptohomeSuccessState() {
763 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
764 if (resync_attempted_)
765 return CREATE_NEW;
766 if (remove_attempted_)
767 return REMOVED_DATA_AFTER_FAILURE;
768 if (migrate_attempted_)
769 return RECOVER_MOUNT;
770 if (check_key_attempted_)
771 return UNLOCK;
772
773 if (current_state_->user_type == user_manager::USER_TYPE_GUEST)
774 return GUEST_LOGIN;
775 if (current_state_->user_type == user_manager::USER_TYPE_RETAIL_MODE)
776 return DEMO_LOGIN;
777 if (current_state_->user_type == user_manager::USER_TYPE_PUBLIC_ACCOUNT)
778 return PUBLIC_ACCOUNT_LOGIN;
779 if (current_state_->user_type == user_manager::USER_TYPE_KIOSK_APP)
780 return KIOSK_ACCOUNT_LOGIN;
781 if (current_state_->user_type == user_manager::USER_TYPE_SUPERVISED)
782 return SUPERVISED_USER_LOGIN;
783
784 if (!VerifyOwner())
785 return CONTINUE;
786 return user_can_login_ ? OFFLINE_LOGIN : OWNER_REQUIRED;
787 }
788
789 ParallelAuthenticator::AuthState
790 ParallelAuthenticator::ResolveOnlineSuccessState(
791 ParallelAuthenticator::AuthState offline_state) {
792 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
793 switch (offline_state) {
794 case POSSIBLE_PW_CHANGE:
795 return NEED_OLD_PW;
796 case NO_MOUNT:
797 return CREATE_NEW;
798 case OFFLINE_LOGIN:
799 return ONLINE_LOGIN;
800 default:
801 NOTREACHED();
802 return offline_state;
803 }
804 }
805
806 void ParallelAuthenticator::ResolveLoginCompletionStatus() {
807 // Shortcut online state resolution process.
808 current_state_->RecordOnlineLoginStatus(AuthFailure::AuthFailureNone());
809 Resolve();
810 }
811
812 void ParallelAuthenticator::SetOwnerState(bool owner_check_finished,
813 bool check_result) {
814 owner_is_verified_ = owner_check_finished;
815 user_can_login_ = check_result;
816 }
817
818 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698