Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / chromeos / login / parallel_authenticator.cc
blobba7e6f4ca6a4d5b07803a5bd06b6e30c8559b8d1
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.
5 #include "chrome/browser/chromeos/login/parallel_authenticator.h"
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 "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/chromeos/boot_times_loader.h"
15 #include "chrome/browser/chromeos/login/authentication_notification_details.h"
16 #include "chrome/browser/chromeos/login/login_status_consumer.h"
17 #include "chrome/browser/chromeos/login/user.h"
18 #include "chrome/browser/chromeos/login/user_manager.h"
19 #include "chrome/browser/chromeos/settings/cros_settings.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chromeos/cryptohome/async_method_caller.h"
22 #include "chromeos/cryptohome/system_salt_getter.h"
23 #include "chromeos/dbus/cryptohome_client.h"
24 #include "chromeos/dbus/dbus_thread_manager.h"
25 #include "chromeos/login/login_state.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/notification_service.h"
28 #include "crypto/sha2.h"
29 #include "google_apis/gaia/gaia_auth_util.h"
30 #include "third_party/cros_system_api/dbus/service_constants.h"
32 using content::BrowserThread;
34 namespace chromeos {
36 namespace {
38 // Length of password hashed with SHA-256.
39 const int kPasswordHashLength = 32;
41 // Records status and calls resolver->Resolve().
42 void TriggerResolve(AuthAttemptState* attempt,
43 scoped_refptr<ParallelAuthenticator> resolver,
44 bool success,
45 cryptohome::MountError return_code) {
46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
47 attempt->RecordCryptohomeStatus(success, return_code);
48 resolver->Resolve();
51 // Records get hash status and calls resolver->Resolve().
52 void TriggerResolveHash(AuthAttemptState* attempt,
53 scoped_refptr<ParallelAuthenticator> resolver,
54 bool success,
55 const std::string& username_hash) {
56 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
57 if (success)
58 attempt->RecordUsernameHash(username_hash);
59 else
60 attempt->RecordUsernameHashFailed();
61 resolver->Resolve();
64 // Calls TriggerResolve while adding login time marker.
65 void TriggerResolveWithLoginTimeMarker(
66 const std::string& marker_name,
67 AuthAttemptState* attempt,
68 scoped_refptr<ParallelAuthenticator> resolver,
69 bool success,
70 cryptohome::MountError return_code) {
71 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(marker_name, false);
72 TriggerResolve(attempt, resolver, success, return_code);
75 // Calls cryptohome's mount method.
76 void Mount(AuthAttemptState* attempt,
77 scoped_refptr<ParallelAuthenticator> resolver,
78 int flags,
79 const std::string& system_salt) {
80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
81 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
82 "CryptohomeMount-Start", false);
83 // Set state that username_hash is requested here so that test implementation
84 // that returns directly would not generate 2 OnLoginSucces() calls.
85 attempt->UsernameHashRequested();
86 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMount(
87 attempt->user_context.username,
88 ParallelAuthenticator::HashPassword(attempt->user_context.password,
89 system_salt),
90 flags,
91 base::Bind(&TriggerResolveWithLoginTimeMarker,
92 "CryptohomeMount-End",
93 attempt,
94 resolver));
95 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
96 attempt->user_context.username,
97 base::Bind(&TriggerResolveHash,
98 attempt,
99 resolver));
102 // Calls cryptohome's mount method for guest.
103 void MountGuest(AuthAttemptState* attempt,
104 scoped_refptr<ParallelAuthenticator> resolver) {
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
106 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest(
107 base::Bind(&TriggerResolveWithLoginTimeMarker,
108 "CryptohomeMount-End",
109 attempt,
110 resolver));
113 // Calls cryptohome's mount method for guest and also get the user hash from
114 // cryptohome.
115 void MountGuestAndGetHash(AuthAttemptState* attempt,
116 scoped_refptr<ParallelAuthenticator> resolver) {
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
118 attempt->UsernameHashRequested();
119 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest(
120 base::Bind(&TriggerResolveWithLoginTimeMarker,
121 "CryptohomeMount-End",
122 attempt,
123 resolver));
124 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
125 attempt->user_context.username,
126 base::Bind(&TriggerResolveHash,
127 attempt,
128 resolver));
131 // Calls cryptohome's MountPublic method
132 void MountPublic(AuthAttemptState* attempt,
133 scoped_refptr<ParallelAuthenticator> resolver,
134 int flags) {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
136 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountPublic(
137 attempt->user_context.username,
138 flags,
139 base::Bind(&TriggerResolveWithLoginTimeMarker,
140 "CryptohomeMountPublic-End",
141 attempt,
142 resolver));
143 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
144 attempt->user_context.username,
145 base::Bind(&TriggerResolveHash,
146 attempt,
147 resolver));
150 // Calls cryptohome's key migration method.
151 void Migrate(AuthAttemptState* attempt,
152 scoped_refptr<ParallelAuthenticator> resolver,
153 bool passing_old_hash,
154 const std::string& old_password,
155 const std::string& system_salt) {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
157 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
158 "CryptohomeMigrate-Start", false);
159 cryptohome::AsyncMethodCaller* caller =
160 cryptohome::AsyncMethodCaller::GetInstance();
161 if (passing_old_hash) {
162 caller->AsyncMigrateKey(
163 attempt->user_context.username,
164 ParallelAuthenticator::HashPassword(old_password, system_salt),
165 ParallelAuthenticator::HashPassword(attempt->user_context.password,
166 system_salt),
167 base::Bind(&TriggerResolveWithLoginTimeMarker,
168 "CryptohomeMount-End",
169 attempt,
170 resolver));
171 } else {
172 caller->AsyncMigrateKey(
173 attempt->user_context.username,
174 ParallelAuthenticator::HashPassword(attempt->user_context.password,
175 system_salt),
176 ParallelAuthenticator::HashPassword(old_password, system_salt),
177 base::Bind(&TriggerResolveWithLoginTimeMarker,
178 "CryptohomeMount-End",
179 attempt,
180 resolver));
184 // Calls cryptohome's remove method.
185 void Remove(AuthAttemptState* attempt,
186 scoped_refptr<ParallelAuthenticator> resolver) {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
188 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker(
189 "CryptohomeRemove-Start", false);
190 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
191 attempt->user_context.username,
192 base::Bind(&TriggerResolveWithLoginTimeMarker,
193 "CryptohomeRemove-End",
194 attempt,
195 resolver));
198 // Calls cryptohome's key check method.
199 void CheckKey(AuthAttemptState* attempt,
200 scoped_refptr<ParallelAuthenticator> resolver,
201 const std::string& system_salt) {
202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
203 cryptohome::AsyncMethodCaller::GetInstance()->AsyncCheckKey(
204 attempt->user_context.username,
205 ParallelAuthenticator::HashPassword(attempt->user_context.password,
206 system_salt),
207 base::Bind(&TriggerResolve, attempt, resolver));
210 } // namespace
212 ParallelAuthenticator::ParallelAuthenticator(LoginStatusConsumer* consumer)
213 : Authenticator(consumer),
214 migrate_attempted_(false),
215 remove_attempted_(false),
216 resync_attempted_(false),
217 ephemeral_mount_attempted_(false),
218 check_key_attempted_(false),
219 already_reported_success_(false),
220 owner_is_verified_(false),
221 user_can_login_(false),
222 remove_user_data_on_failure_(false),
223 delayed_login_failure_(NULL) {
226 void ParallelAuthenticator::AuthenticateToLogin(
227 Profile* profile,
228 const UserContext& user_context) {
229 std::string canonicalized = gaia::CanonicalizeEmail(user_context.username);
230 authentication_profile_ = profile;
231 current_state_.reset(
232 new AuthAttemptState(
233 UserContext(canonicalized,
234 user_context.password,
235 user_context.auth_code),
236 std::string(), // login_token, not used.
237 std::string(), // login_captcha, not used.
238 User::USER_TYPE_REGULAR,
239 !UserManager::Get()->IsKnownUser(canonicalized)));
240 // Reset the verified flag.
241 owner_is_verified_ = false;
243 SystemSaltGetter::Get()->GetSystemSalt(
244 base::Bind(&Mount,
245 current_state_.get(),
246 scoped_refptr<ParallelAuthenticator>(this),
247 cryptohome::MOUNT_FLAGS_NONE));
250 void ParallelAuthenticator::CompleteLogin(Profile* profile,
251 const UserContext& user_context) {
252 std::string canonicalized = gaia::CanonicalizeEmail(user_context.username);
253 authentication_profile_ = profile;
254 current_state_.reset(
255 new AuthAttemptState(
256 UserContext(canonicalized,
257 user_context.password,
258 user_context.auth_code,
259 user_context.username_hash,
260 user_context.using_oauth,
261 user_context.auth_flow),
262 !UserManager::Get()->IsKnownUser(canonicalized)));
264 // Reset the verified flag.
265 owner_is_verified_ = false;
267 SystemSaltGetter::Get()->GetSystemSalt(
268 base::Bind(&Mount,
269 current_state_.get(),
270 scoped_refptr<ParallelAuthenticator>(this),
271 cryptohome::MOUNT_FLAGS_NONE));
273 // For login completion from extension, we just need to resolve the current
274 // auth attempt state, the rest of OAuth related tasks will be done in
275 // parallel.
276 BrowserThread::PostTask(
277 BrowserThread::UI, FROM_HERE,
278 base::Bind(&ParallelAuthenticator::ResolveLoginCompletionStatus, this));
281 void ParallelAuthenticator::AuthenticateToUnlock(
282 const UserContext& user_context) {
283 current_state_.reset(
284 new AuthAttemptState(
285 gaia::CanonicalizeEmail(user_context.username),
286 user_context.password));
287 remove_user_data_on_failure_ = false;
288 check_key_attempted_ = true;
289 SystemSaltGetter::Get()->GetSystemSalt(
290 base::Bind(&CheckKey,
291 current_state_.get(),
292 scoped_refptr<ParallelAuthenticator>(this)));
295 void ParallelAuthenticator::LoginAsLocallyManagedUser(
296 const UserContext& user_context) {
297 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
298 // TODO(nkostylev): Pass proper value for |user_is_new| or remove (not used).
299 current_state_.reset(
300 new AuthAttemptState(user_context,
301 "", // login_token
302 "", // login_captcha
303 User::USER_TYPE_LOCALLY_MANAGED,
304 false));
305 remove_user_data_on_failure_ = false;
306 SystemSaltGetter::Get()->GetSystemSalt(
307 base::Bind(&Mount,
308 current_state_.get(),
309 scoped_refptr<ParallelAuthenticator>(this),
310 cryptohome::MOUNT_FLAGS_NONE));
313 void ParallelAuthenticator::LoginRetailMode() {
314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
315 // Note: |kRetailModeUserEMail| is used in other places to identify a retail
316 // mode session.
317 current_state_.reset(new AuthAttemptState(
318 UserContext(UserManager::kRetailModeUserName,
319 std::string(), // password
320 std::string()), // auth_code
321 std::string(), // login_token
322 std::string(), // login_captcha
323 User::USER_TYPE_RETAIL_MODE,
324 false));
325 remove_user_data_on_failure_ = false;
326 ephemeral_mount_attempted_ = true;
327 MountGuest(current_state_.get(),
328 scoped_refptr<ParallelAuthenticator>(this));
331 void ParallelAuthenticator::LoginOffTheRecord() {
332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
333 current_state_.reset(new AuthAttemptState(
334 UserContext(UserManager::kGuestUserName, // username
335 std::string(), // password
336 std::string()), // auth_code
337 std::string(), // login_token
338 std::string(), // login_captcha
339 User::USER_TYPE_GUEST,
340 false));
341 remove_user_data_on_failure_ = false;
342 ephemeral_mount_attempted_ = true;
343 MountGuest(current_state_.get(),
344 scoped_refptr<ParallelAuthenticator>(this));
347 void ParallelAuthenticator::LoginAsPublicAccount(const std::string& username) {
348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
349 current_state_.reset(new AuthAttemptState(
350 UserContext(username,
351 std::string(), // password
352 std::string()), // auth_code
353 std::string(), // login_token
354 std::string(), // login_captcha
355 User::USER_TYPE_PUBLIC_ACCOUNT,
356 false));
357 remove_user_data_on_failure_ = false;
358 ephemeral_mount_attempted_ = true;
359 SystemSaltGetter::Get()->GetSystemSalt(
360 base::Bind(&Mount,
361 current_state_.get(),
362 scoped_refptr<ParallelAuthenticator>(this),
363 cryptohome::CREATE_IF_MISSING | cryptohome::ENSURE_EPHEMERAL));
366 void ParallelAuthenticator::LoginAsKioskAccount(
367 const std::string& app_user_id,
368 bool use_guest_mount) {
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
371 const std::string user_id =
372 use_guest_mount ? UserManager::kGuestUserName : app_user_id;
373 current_state_.reset(new AuthAttemptState(
374 UserContext(user_id,
375 std::string(), // password
376 std::string()), // auth_code
377 std::string(), // login_token
378 std::string(), // login_captcha
379 User::USER_TYPE_KIOSK_APP,
380 false));
382 remove_user_data_on_failure_ = true;
383 if (!use_guest_mount) {
384 MountPublic(current_state_.get(),
385 scoped_refptr<ParallelAuthenticator>(this),
386 cryptohome::CREATE_IF_MISSING);
387 } else {
388 ephemeral_mount_attempted_ = true;
389 MountGuestAndGetHash(current_state_.get(),
390 scoped_refptr<ParallelAuthenticator>(this));
394 void ParallelAuthenticator::OnRetailModeLoginSuccess() {
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
396 VLOG(1) << "Retail mode login success";
397 // Send notification of success
398 AuthenticationNotificationDetails details(true);
399 content::NotificationService::current()->Notify(
400 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
401 content::NotificationService::AllSources(),
402 content::Details<AuthenticationNotificationDetails>(&details));
403 if (consumer_)
404 consumer_->OnRetailModeLoginSuccess(current_state_->user_context);
407 void ParallelAuthenticator::OnLoginSuccess() {
408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
409 VLOG(1) << "Login success";
410 // Send notification of success
411 AuthenticationNotificationDetails details(true);
412 content::NotificationService::current()->Notify(
413 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
414 content::NotificationService::AllSources(),
415 content::Details<AuthenticationNotificationDetails>(&details));
417 base::AutoLock for_this_block(success_lock_);
418 already_reported_success_ = true;
420 if (consumer_)
421 consumer_->OnLoginSuccess(current_state_->user_context);
424 void ParallelAuthenticator::OnOffTheRecordLoginSuccess() {
425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
426 // Send notification of success
427 AuthenticationNotificationDetails details(true);
428 content::NotificationService::current()->Notify(
429 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
430 content::NotificationService::AllSources(),
431 content::Details<AuthenticationNotificationDetails>(&details));
432 if (consumer_)
433 consumer_->OnOffTheRecordLoginSuccess();
436 void ParallelAuthenticator::OnPasswordChangeDetected() {
437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
438 if (consumer_)
439 consumer_->OnPasswordChangeDetected();
442 void ParallelAuthenticator::OnLoginFailure(const LoginFailure& error) {
443 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
445 // OnLoginFailure will be called again with the same |error|
446 // after the cryptohome has been removed.
447 if (remove_user_data_on_failure_) {
448 delayed_login_failure_ = &error;
449 RemoveEncryptedData();
450 return;
453 // Send notification of failure
454 AuthenticationNotificationDetails details(false);
455 content::NotificationService::current()->Notify(
456 chrome::NOTIFICATION_LOGIN_AUTHENTICATION,
457 content::NotificationService::AllSources(),
458 content::Details<AuthenticationNotificationDetails>(&details));
459 LOG(WARNING) << "Login failed: " << error.GetErrorString();
460 if (consumer_)
461 consumer_->OnLoginFailure(error);
464 void ParallelAuthenticator::RecoverEncryptedData(
465 const std::string& old_password) {
466 migrate_attempted_ = true;
467 current_state_->ResetCryptohomeStatus();
468 SystemSaltGetter::Get()->GetSystemSalt(
469 base::Bind(&Migrate,
470 current_state_.get(),
471 scoped_refptr<ParallelAuthenticator>(this),
472 true,
473 old_password));
476 void ParallelAuthenticator::RemoveEncryptedData() {
477 remove_attempted_ = true;
478 current_state_->ResetCryptohomeStatus();
479 BrowserThread::PostTask(
480 BrowserThread::UI, FROM_HERE,
481 base::Bind(&Remove,
482 current_state_.get(),
483 scoped_refptr<ParallelAuthenticator>(this)));
486 void ParallelAuthenticator::ResyncEncryptedData() {
487 resync_attempted_ = true;
488 current_state_->ResetCryptohomeStatus();
489 BrowserThread::PostTask(
490 BrowserThread::UI, FROM_HERE,
491 base::Bind(&Remove,
492 current_state_.get(),
493 scoped_refptr<ParallelAuthenticator>(this)));
496 bool ParallelAuthenticator::VerifyOwner() {
497 if (owner_is_verified_)
498 return true;
499 // Check if policy data is fine and continue in safe mode if needed.
500 bool is_safe_mode = false;
501 CrosSettings::Get()->GetBoolean(kPolicyMissingMitigationMode, &is_safe_mode);
502 if (!is_safe_mode) {
503 // Now we can continue with the login and report mount success.
504 user_can_login_ = true;
505 owner_is_verified_ = true;
506 return true;
508 // Now we can continue reading the private key.
509 DeviceSettingsService::Get()->SetUsername(
510 current_state_->user_context.username);
511 // This should trigger certificate loading, which is needed in order to
512 // correctly determine if the current user is the owner.
513 if (LoginState::IsInitialized()) {
514 LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_SAFE_MODE,
515 LoginState::LOGGED_IN_USER_NONE);
517 DeviceSettingsService::Get()->IsCurrentUserOwnerAsync(
518 base::Bind(&ParallelAuthenticator::OnOwnershipChecked, this));
519 return false;
522 void ParallelAuthenticator::OnOwnershipChecked(bool is_owner) {
523 // Now we can check if this user is the owner.
524 user_can_login_ = is_owner;
525 owner_is_verified_ = true;
526 Resolve();
529 void ParallelAuthenticator::Resolve() {
530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
531 int mount_flags = cryptohome::MOUNT_FLAGS_NONE;
532 ParallelAuthenticator::AuthState state = ResolveState();
533 VLOG(1) << "Resolved state to: " << state;
534 switch (state) {
535 case CONTINUE:
536 case POSSIBLE_PW_CHANGE:
537 case NO_MOUNT:
538 // These are intermediate states; we need more info from a request that
539 // is still pending.
540 break;
541 case FAILED_MOUNT:
542 // In this case, whether login succeeded or not, we can't log
543 // the user in because their data is horked. So, override with
544 // the appropriate failure.
545 BrowserThread::PostTask(
546 BrowserThread::UI, FROM_HERE,
547 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
548 LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME)));
549 break;
550 case FAILED_REMOVE:
551 // In this case, we tried to remove the user's old cryptohome at her
552 // request, and the remove failed.
553 remove_user_data_on_failure_ = false;
554 BrowserThread::PostTask(
555 BrowserThread::UI, FROM_HERE,
556 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
557 LoginFailure(LoginFailure::DATA_REMOVAL_FAILED)));
558 break;
559 case FAILED_TMPFS:
560 // In this case, we tried to mount a tmpfs for guest and failed.
561 BrowserThread::PostTask(
562 BrowserThread::UI, FROM_HERE,
563 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
564 LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)));
565 break;
566 case FAILED_TPM:
567 // In this case, we tried to create/mount cryptohome and failed
568 // because of the critical TPM error.
569 // Chrome will notify user and request reboot.
570 BrowserThread::PostTask(
571 BrowserThread::UI, FROM_HERE,
572 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
573 LoginFailure(LoginFailure::TPM_ERROR)));
574 break;
575 case FAILED_USERNAME_HASH:
576 // In this case, we failed the GetSanitizedUsername request to
577 // cryptohomed. This can happen for any login attempt.
578 BrowserThread::PostTask(
579 BrowserThread::UI, FROM_HERE,
580 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
581 LoginFailure(LoginFailure::USERNAME_HASH_FAILED)));
582 break;
583 case REMOVED_DATA_AFTER_FAILURE:
584 remove_user_data_on_failure_ = false;
585 BrowserThread::PostTask(
586 BrowserThread::UI, FROM_HERE,
587 base::Bind(&ParallelAuthenticator::OnLoginFailure, this,
588 *delayed_login_failure_));
589 break;
590 case CREATE_NEW:
591 mount_flags |= cryptohome::CREATE_IF_MISSING;
592 case RECOVER_MOUNT:
593 current_state_->ResetCryptohomeStatus();
594 SystemSaltGetter::Get()->GetSystemSalt(
595 base::Bind(&Mount,
596 current_state_.get(),
597 scoped_refptr<ParallelAuthenticator>(this),
598 mount_flags));
599 break;
600 case NEED_OLD_PW:
601 BrowserThread::PostTask(
602 BrowserThread::UI, FROM_HERE,
603 base::Bind(&ParallelAuthenticator::OnPasswordChangeDetected, this));
604 break;
605 case ONLINE_FAILED:
606 case NEED_NEW_PW:
607 case HAVE_NEW_PW:
608 NOTREACHED() << "Using obsolete ClientLogin code path.";
609 break;
610 case OFFLINE_LOGIN:
611 VLOG(2) << "Offline login";
612 // Fall through.
613 case UNLOCK:
614 VLOG(2) << "Unlock";
615 // Fall through.
616 case ONLINE_LOGIN:
617 VLOG(2) << "Online login";
618 BrowserThread::PostTask(
619 BrowserThread::UI, FROM_HERE,
620 base::Bind(&ParallelAuthenticator::OnLoginSuccess, this));
621 break;
622 case DEMO_LOGIN:
623 VLOG(2) << "Retail mode login";
624 current_state_->user_context.using_oauth = false;
625 BrowserThread::PostTask(
626 BrowserThread::UI, FROM_HERE,
627 base::Bind(&ParallelAuthenticator::OnRetailModeLoginSuccess, this));
628 break;
629 case GUEST_LOGIN:
630 BrowserThread::PostTask(
631 BrowserThread::UI, FROM_HERE,
632 base::Bind(&ParallelAuthenticator::OnOffTheRecordLoginSuccess, this));
633 break;
634 case KIOSK_ACCOUNT_LOGIN:
635 case PUBLIC_ACCOUNT_LOGIN:
636 current_state_->user_context.using_oauth = false;
637 BrowserThread::PostTask(
638 BrowserThread::UI, FROM_HERE,
639 base::Bind(&ParallelAuthenticator::OnLoginSuccess, this));
640 break;
641 case LOCALLY_MANAGED_USER_LOGIN:
642 current_state_->user_context.using_oauth = false;
643 BrowserThread::PostTask(
644 BrowserThread::UI, FROM_HERE,
645 base::Bind(&ParallelAuthenticator::OnLoginSuccess, this));
646 break;
647 case LOGIN_FAILED:
648 current_state_->ResetCryptohomeStatus();
649 BrowserThread::PostTask(BrowserThread::UI,
650 FROM_HERE,
651 base::Bind(
652 &ParallelAuthenticator::OnLoginFailure,
653 this,
654 current_state_->online_outcome()));
655 break;
656 case OWNER_REQUIRED: {
657 current_state_->ResetCryptohomeStatus();
658 bool success = false;
659 DBusThreadManager::Get()->GetCryptohomeClient()->Unmount(&success);
660 if (!success) {
661 // Maybe we should reboot immediately here?
662 LOG(ERROR) << "Couldn't unmount users home!";
664 BrowserThread::PostTask(BrowserThread::UI,
665 FROM_HERE,
666 base::Bind(
667 &ParallelAuthenticator::OnLoginFailure,
668 this,
669 LoginFailure(LoginFailure::OWNER_REQUIRED)));
670 break;
672 default:
673 NOTREACHED();
674 break;
678 // static.
679 std::string ParallelAuthenticator::HashPassword(const std::string& password,
680 const std::string& ascii_salt) {
681 // Update sha with ascii encoded salt, then update with ascii of password,
682 // then end.
683 // TODO(stevenjb/nkostylev): Handle empty system salt gracefully.
684 CHECK(!ascii_salt.empty());
685 char passhash_buf[kPasswordHashLength];
687 // Hash salt and password
688 crypto::SHA256HashString(ascii_salt + password,
689 &passhash_buf, sizeof(passhash_buf));
691 // Only want the top half for 'weak' hashing so that the passphrase is not
692 // immediately exposed even if the output is reversed.
693 const int encoded_length = sizeof(passhash_buf) / 2;
695 return StringToLowerASCII(base::HexEncode(
696 reinterpret_cast<const void*>(passhash_buf), encoded_length));
699 ParallelAuthenticator::~ParallelAuthenticator() {}
701 ParallelAuthenticator::AuthState ParallelAuthenticator::ResolveState() {
702 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
703 // If we haven't mounted the user's home dir yet or
704 // haven't got sanitized username value, we can't be done.
705 // We never get past here if any of these two cryptohome ops is still pending.
706 // This is an important invariant.
707 if (!current_state_->cryptohome_complete() ||
708 !current_state_->username_hash_obtained()) {
709 return CONTINUE;
712 AuthState state = CONTINUE;
714 if (current_state_->cryptohome_outcome() &&
715 current_state_->username_hash_valid()) {
716 state = ResolveCryptohomeSuccessState();
717 } else {
718 state = ResolveCryptohomeFailureState();
721 DCHECK(current_state_->cryptohome_complete()); // Ensure invariant holds.
722 migrate_attempted_ = false;
723 remove_attempted_ = false;
724 resync_attempted_ = false;
725 ephemeral_mount_attempted_ = false;
726 check_key_attempted_ = false;
728 if (state != POSSIBLE_PW_CHANGE &&
729 state != NO_MOUNT &&
730 state != OFFLINE_LOGIN)
731 return state;
733 if (current_state_->online_complete()) {
734 if (current_state_->online_outcome().reason() == LoginFailure::NONE) {
735 // Online attempt succeeded as well, so combine the results.
736 return ResolveOnlineSuccessState(state);
738 NOTREACHED() << "Using obsolete ClientLogin code path.";
740 // if online isn't complete yet, just return the offline result.
741 return state;
744 ParallelAuthenticator::AuthState
745 ParallelAuthenticator::ResolveCryptohomeFailureState() {
746 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
747 if (remove_attempted_ || resync_attempted_)
748 return FAILED_REMOVE;
749 if (ephemeral_mount_attempted_)
750 return FAILED_TMPFS;
751 if (migrate_attempted_)
752 return NEED_OLD_PW;
753 if (check_key_attempted_)
754 return LOGIN_FAILED;
756 if (current_state_->cryptohome_code() ==
757 cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
758 // Critical TPM error detected, reboot needed.
759 return FAILED_TPM;
762 // Return intermediate states in the following case:
763 // when there is an online result to use;
764 // This is the case after user finishes Gaia login;
765 if (current_state_->online_complete()) {
766 if (current_state_->cryptohome_code() ==
767 cryptohome::MOUNT_ERROR_KEY_FAILURE) {
768 // If we tried a mount but they used the wrong key, we may need to
769 // ask the user for her old password. We'll only know once we've
770 // done the online check.
771 return POSSIBLE_PW_CHANGE;
773 if (current_state_->cryptohome_code() ==
774 cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) {
775 // If we tried a mount but the user did not exist, then we should wait
776 // for online login to succeed and try again with the "create" flag set.
777 return NO_MOUNT;
781 if (!current_state_->username_hash_valid())
782 return FAILED_USERNAME_HASH;
784 return FAILED_MOUNT;
787 ParallelAuthenticator::AuthState
788 ParallelAuthenticator::ResolveCryptohomeSuccessState() {
789 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
790 if (resync_attempted_)
791 return CREATE_NEW;
792 if (remove_attempted_)
793 return REMOVED_DATA_AFTER_FAILURE;
794 if (migrate_attempted_)
795 return RECOVER_MOUNT;
796 if (check_key_attempted_)
797 return UNLOCK;
799 if (current_state_->user_type == User::USER_TYPE_GUEST)
800 return GUEST_LOGIN;
801 if (current_state_->user_type == User::USER_TYPE_RETAIL_MODE)
802 return DEMO_LOGIN;
803 if (current_state_->user_type == User::USER_TYPE_PUBLIC_ACCOUNT)
804 return PUBLIC_ACCOUNT_LOGIN;
805 if (current_state_->user_type == User::USER_TYPE_KIOSK_APP)
806 return KIOSK_ACCOUNT_LOGIN;
807 if (current_state_->user_type == User::USER_TYPE_LOCALLY_MANAGED)
808 return LOCALLY_MANAGED_USER_LOGIN;
810 if (!VerifyOwner())
811 return CONTINUE;
812 return user_can_login_ ? OFFLINE_LOGIN : OWNER_REQUIRED;
815 ParallelAuthenticator::AuthState
816 ParallelAuthenticator::ResolveOnlineSuccessState(
817 ParallelAuthenticator::AuthState offline_state) {
818 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
819 switch (offline_state) {
820 case POSSIBLE_PW_CHANGE:
821 return NEED_OLD_PW;
822 case NO_MOUNT:
823 return CREATE_NEW;
824 case OFFLINE_LOGIN:
825 return ONLINE_LOGIN;
826 default:
827 NOTREACHED();
828 return offline_state;
832 void ParallelAuthenticator::ResolveLoginCompletionStatus() {
833 // Shortcut online state resolution process.
834 current_state_->RecordOnlineLoginStatus(LoginFailure::LoginFailureNone());
835 Resolve();
838 void ParallelAuthenticator::SetOwnerState(bool owner_check_finished,
839 bool check_result) {
840 owner_is_verified_ = owner_check_finished;
841 user_can_login_ = check_result;
844 } // namespace chromeos