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"
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
;
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
,
45 cryptohome::MountError return_code
) {
46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
47 attempt
->RecordCryptohomeStatus(success
, return_code
);
51 // Records get hash status and calls resolver->Resolve().
52 void TriggerResolveHash(AuthAttemptState
* attempt
,
53 scoped_refptr
<ParallelAuthenticator
> resolver
,
55 const std::string
& username_hash
) {
56 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
58 attempt
->RecordUsernameHash(username_hash
);
60 attempt
->RecordUsernameHashFailed();
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
,
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
,
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
,
91 base::Bind(&TriggerResolveWithLoginTimeMarker
,
92 "CryptohomeMount-End",
95 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
96 attempt
->user_context
.username
,
97 base::Bind(&TriggerResolveHash
,
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",
113 // Calls cryptohome's mount method for guest and also get the user hash from
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",
124 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
125 attempt
->user_context
.username
,
126 base::Bind(&TriggerResolveHash
,
131 // Calls cryptohome's MountPublic method
132 void MountPublic(AuthAttemptState
* attempt
,
133 scoped_refptr
<ParallelAuthenticator
> resolver
,
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
136 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountPublic(
137 attempt
->user_context
.username
,
139 base::Bind(&TriggerResolveWithLoginTimeMarker
,
140 "CryptohomeMountPublic-End",
143 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
144 attempt
->user_context
.username
,
145 base::Bind(&TriggerResolveHash
,
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
,
167 base::Bind(&TriggerResolveWithLoginTimeMarker
,
168 "CryptohomeMount-End",
172 caller
->AsyncMigrateKey(
173 attempt
->user_context
.username
,
174 ParallelAuthenticator::HashPassword(attempt
->user_context
.password
,
176 ParallelAuthenticator::HashPassword(old_password
, system_salt
),
177 base::Bind(&TriggerResolveWithLoginTimeMarker
,
178 "CryptohomeMount-End",
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",
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
,
207 base::Bind(&TriggerResolve
, attempt
, resolver
));
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(
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(
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(
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
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
,
303 User::USER_TYPE_LOCALLY_MANAGED
,
305 remove_user_data_on_failure_
= false;
306 SystemSaltGetter::Get()->GetSystemSalt(
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
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
,
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
,
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
,
357 remove_user_data_on_failure_
= false;
358 ephemeral_mount_attempted_
= true;
359 SystemSaltGetter::Get()->GetSystemSalt(
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(
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
,
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
);
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
));
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;
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
));
433 consumer_
->OnOffTheRecordLoginSuccess();
436 void ParallelAuthenticator::OnPasswordChangeDetected() {
437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
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();
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();
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(
470 current_state_
.get(),
471 scoped_refptr
<ParallelAuthenticator
>(this),
476 void ParallelAuthenticator::RemoveEncryptedData() {
477 remove_attempted_
= true;
478 current_state_
->ResetCryptohomeStatus();
479 BrowserThread::PostTask(
480 BrowserThread::UI
, FROM_HERE
,
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
,
492 current_state_
.get(),
493 scoped_refptr
<ParallelAuthenticator
>(this)));
496 bool ParallelAuthenticator::VerifyOwner() {
497 if (owner_is_verified_
)
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
);
503 // Now we can continue with the login and report mount success.
504 user_can_login_
= true;
505 owner_is_verified_
= 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));
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;
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
;
536 case POSSIBLE_PW_CHANGE
:
538 // These are intermediate states; we need more info from a request that
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
)));
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
)));
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
)));
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
)));
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
)));
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_
));
591 mount_flags
|= cryptohome::CREATE_IF_MISSING
;
593 current_state_
->ResetCryptohomeStatus();
594 SystemSaltGetter::Get()->GetSystemSalt(
596 current_state_
.get(),
597 scoped_refptr
<ParallelAuthenticator
>(this),
601 BrowserThread::PostTask(
602 BrowserThread::UI
, FROM_HERE
,
603 base::Bind(&ParallelAuthenticator::OnPasswordChangeDetected
, this));
608 NOTREACHED() << "Using obsolete ClientLogin code path.";
611 VLOG(2) << "Offline login";
617 VLOG(2) << "Online login";
618 BrowserThread::PostTask(
619 BrowserThread::UI
, FROM_HERE
,
620 base::Bind(&ParallelAuthenticator::OnLoginSuccess
, this));
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));
630 BrowserThread::PostTask(
631 BrowserThread::UI
, FROM_HERE
,
632 base::Bind(&ParallelAuthenticator::OnOffTheRecordLoginSuccess
, this));
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));
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));
648 current_state_
->ResetCryptohomeStatus();
649 BrowserThread::PostTask(BrowserThread::UI
,
652 &ParallelAuthenticator::OnLoginFailure
,
654 current_state_
->online_outcome()));
656 case OWNER_REQUIRED
: {
657 current_state_
->ResetCryptohomeStatus();
658 bool success
= false;
659 DBusThreadManager::Get()->GetCryptohomeClient()->Unmount(&success
);
661 // Maybe we should reboot immediately here?
662 LOG(ERROR
) << "Couldn't unmount users home!";
664 BrowserThread::PostTask(BrowserThread::UI
,
667 &ParallelAuthenticator::OnLoginFailure
,
669 LoginFailure(LoginFailure::OWNER_REQUIRED
)));
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,
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()) {
712 AuthState state
= CONTINUE
;
714 if (current_state_
->cryptohome_outcome() &&
715 current_state_
->username_hash_valid()) {
716 state
= ResolveCryptohomeSuccessState();
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
&&
730 state
!= OFFLINE_LOGIN
)
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.
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_
)
751 if (migrate_attempted_
)
753 if (check_key_attempted_
)
756 if (current_state_
->cryptohome_code() ==
757 cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT
) {
758 // Critical TPM error detected, reboot needed.
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.
781 if (!current_state_
->username_hash_valid())
782 return FAILED_USERNAME_HASH
;
787 ParallelAuthenticator::AuthState
788 ParallelAuthenticator::ResolveCryptohomeSuccessState() {
789 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
790 if (resync_attempted_
)
792 if (remove_attempted_
)
793 return REMOVED_DATA_AFTER_FAILURE
;
794 if (migrate_attempted_
)
795 return RECOVER_MOUNT
;
796 if (check_key_attempted_
)
799 if (current_state_
->user_type
== User::USER_TYPE_GUEST
)
801 if (current_state_
->user_type
== User::USER_TYPE_RETAIL_MODE
)
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
;
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
:
828 return offline_state
;
832 void ParallelAuthenticator::ResolveLoginCompletionStatus() {
833 // Shortcut online state resolution process.
834 current_state_
->RecordOnlineLoginStatus(LoginFailure::LoginFailureNone());
838 void ParallelAuthenticator::SetOwnerState(bool owner_check_finished
,
840 owner_is_verified_
= owner_check_finished
;
841 user_can_login_
= check_result
;
844 } // namespace chromeos