1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Use of this source code is governed by a BSD-style license that can be 3731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// found in the LICENSE file. 4731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/login/parallel_authenticator.h" 6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <string> 8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <vector> 9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/file_path.h" 11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/file_util.h" 12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/logging.h" 13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/path_service.h" 14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/string_util.h" 153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/synchronization/lock.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/third_party/nss/blapi.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/third_party/nss/sha256.h" 18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/cros/cryptohome_library.h" 19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/login/auth_response_handler.h" 20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/login/authentication_notification_details.h" 21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/login/login_status_consumer.h" 22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/login/ownership_service.h" 234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/chromeos/login/user_manager.h" 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile_manager.h" 26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/chrome_paths.h" 274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/net/gaia/gaia_auth_fetcher.h" 28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/net/gaia/gaia_constants.h" 29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h" 31731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/load_flags.h" 32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/net_errors.h" 33731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/url_request/url_request_status.h" 34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "third_party/libjingle/source/talk/base/urlencode.h" 35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing base::Time; 37731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing base::TimeDelta; 38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing file_util::GetFileSize; 39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing file_util::PathExists; 40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing file_util::ReadFile; 41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing file_util::ReadFileToString; 42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 43731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace chromeos { 44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static 46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst char ParallelAuthenticator::kLocalaccountFile[] = "localaccount"; 47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static 49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst int ParallelAuthenticator::kClientLoginTimeoutMs = 10000; 50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static 51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst int ParallelAuthenticator::kLocalaccountRetryIntervalMs = 20; 52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst int kPassHashLen = 32; 54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 55731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::ParallelAuthenticator(LoginStatusConsumer* consumer) 56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : Authenticator(consumer), 57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick already_reported_success_(false), 58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick checked_for_localaccount_(false) { 59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CHECK(chromeos::CrosLibrary::Get()->EnsureLoaded()); 60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If not already owned, this is a no-op. If it is, this loads the owner's 61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // public key off of disk. 62731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick OwnershipService::GetSharedInstance()->StartLoadOwnerKeyAttempt(); 63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 65731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::~ParallelAuthenticator() {} 66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 67731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParallelAuthenticator::AuthenticateToLogin( 68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Profile* profile, 69731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& username, 70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& password, 71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& login_token, 72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& login_captcha) { 734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string canonicalized = Authenticator::Canonicalize(username); 74731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_state_.reset( 754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch new AuthAttemptState(canonicalized, 76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick password, 77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HashPassword(password), 78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick login_token, 794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch login_captcha, 804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch !UserManager::Get()->IsKnownUser(canonicalized))); 81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), 82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick this, 83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick false /* don't create */); 84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_online_ = new OnlineAttempt(current_state_.get(), this); 85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ 86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(mounter_.get(), &CryptohomeOp::Initiate)); 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_online_->Initiate(profile); 90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::FILE, FROM_HERE, 92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, 93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &ParallelAuthenticator::LoadLocalaccount, 94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string(kLocalaccountFile))); 95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParallelAuthenticator::AuthenticateToUnlock(const std::string& username, 99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& password) { 100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_state_.reset( 101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new AuthAttemptState(Authenticator::Canonicalize(username), 102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HashPassword(password))); 103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::FILE, FROM_HERE, 105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, 106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &ParallelAuthenticator::LoadLocalaccount, 107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string(kLocalaccountFile))); 108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick key_checker_ = CryptohomeOp::CreateCheckKeyAttempt(current_state_.get(), 109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick this); 110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ 111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(key_checker_.get(), &CryptohomeOp::Initiate)); 114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::LoginOffTheRecord() { 1184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch current_state_.reset(new AuthAttemptState("", "", "", "", "", false)); 119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick guest_mounter_ = 120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CryptohomeOp::CreateMountGuestAttempt(current_state_.get(), this); 121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick guest_mounter_->Initiate(); 123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::OnLoginSuccess( 126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GaiaAuthConsumer::ClientLoginResult& credentials, 127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool request_pending) { 128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen VLOG(1) << "Login success"; 130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Send notification of success 131731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AuthenticationNotificationDetails details(true); 132731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NotificationService::current()->Notify( 133731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NotificationType::LOGIN_AUTHENTICATION, 134731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NotificationService::AllSources(), 135731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Details<AuthenticationNotificationDetails>(&details)); 136731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick { 1373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::AutoLock for_this_block(success_lock_); 138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick already_reported_success_ = true; 139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick consumer_->OnLoginSuccess(current_state_->username, 141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch current_state_->password, 142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick credentials, 143731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick request_pending); 144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::OnOffTheRecordLoginSuccess() { 147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Send notification of success 149731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AuthenticationNotificationDetails details(true); 150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NotificationService::current()->Notify( 151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NotificationType::LOGIN_AUTHENTICATION, 152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NotificationService::AllSources(), 153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Details<AuthenticationNotificationDetails>(&details)); 154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick consumer_->OnOffTheRecordLoginSuccess(); 155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::OnPasswordChangeDetected( 158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GaiaAuthConsumer::ClientLoginResult& credentials) { 159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick consumer_->OnPasswordChangeDetected(credentials); 161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::CheckLocalaccount(const LoginFailure& error) { 164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick { 1653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::AutoLock for_this_block(localaccount_lock_); 16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen VLOG(2) << "Checking localaccount"; 167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!checked_for_localaccount_) { 168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostDelayedTask( 169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::FILE, FROM_HERE, 170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, 171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &ParallelAuthenticator::CheckLocalaccount, 172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick error), 173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick kLocalaccountRetryIntervalMs); 174731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!localaccount_.empty() && localaccount_ == current_state_->username) { 179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Success. Go mount a tmpfs for the profile, if necessary. 180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!current_state_->unlock) { 181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick guest_mounter_ = 182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CryptohomeOp::CreateMountGuestAttempt(current_state_.get(), this); 183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(guest_mounter_.get(), &CryptohomeOp::Initiate)); 186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, &ParallelAuthenticator::OnLoginSuccess, 190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GaiaAuthConsumer::ClientLoginResult(), false)); 191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Not the localaccount. Fail, passing along cached error info. 194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, &ParallelAuthenticator::OnLoginFailure, error)); 197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::OnLoginFailure(const LoginFailure& error) { 201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Send notification of failure 203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AuthenticationNotificationDetails details(false); 204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NotificationService::current()->Notify( 205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NotificationType::LOGIN_AUTHENTICATION, 206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NotificationService::AllSources(), 207731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Details<AuthenticationNotificationDetails>(&details)); 208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LOG(WARNING) << "Login failed: " << error.GetErrorString(); 209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick consumer_->OnLoginFailure(error); 210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::RecoverEncryptedData( 213731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& old_password, 214731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GaiaAuthConsumer::ClientLoginResult& credentials) { 215731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string old_hash = HashPassword(old_password); 216731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick key_migrator_ = CryptohomeOp::CreateMigrateAttempt(current_state_.get(), 217731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick this, 218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick true, 219731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick old_hash); 220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 221731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 222731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, 223731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &ParallelAuthenticator::ResyncRecoverHelper, 22421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen key_migrator_)); 225731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 226731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 227731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::ResyncEncryptedData( 228731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GaiaAuthConsumer::ClientLoginResult& credentials) { 229731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick data_remover_ = 230731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CryptohomeOp::CreateRemoveAttempt(current_state_.get(), this); 231731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 232731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, 234731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &ParallelAuthenticator::ResyncRecoverHelper, 23521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen data_remover_)); 236731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 237731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 238731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::ResyncRecoverHelper(CryptohomeOp* to_initiate) { 239731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 240731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_state_->ResetCryptohomeStatus(); 241731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 242731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 243731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(to_initiate, &CryptohomeOp::Initiate)); 244731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 245731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 246731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::RetryAuth(Profile* profile, 247731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& username, 248731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& password, 249731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& login_token, 250731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& login_captcha) { 251731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick reauth_state_.reset( 252731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new AuthAttemptState(Authenticator::Canonicalize(username), 253731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick password, 254731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HashPassword(password), 255731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick login_token, 2564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch login_captcha, 2574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch false /* not a new user */)); 258731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_online_ = new OnlineAttempt(reauth_state_.get(), this); 25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_online_->Initiate(profile); 260731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 261731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 262731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::Resolve() { 263731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 264731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool request_pending = false; 265731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool create = false; 26621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ParallelAuthenticator::AuthState state = ResolveState(); 26721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen VLOG(1) << "Resolved state to: " << state; 26821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen switch (state) { 269731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case CONTINUE: 270731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case POSSIBLE_PW_CHANGE: 271731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case NO_MOUNT: 272731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // These are intermediate states; we need more info from a request that 273731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // is still pending. 274731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 275731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case FAILED_MOUNT: 276731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // In this case, whether login succeeded or not, we can't log 277731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // the user in because their data is horked. So, override with 278731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // the appropriate failure. 279731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 280731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 281731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod( 282731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick this, 283731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &ParallelAuthenticator::OnLoginFailure, 284731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME))); 285731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 286731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case FAILED_REMOVE: 287731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // In this case, we tried to remove the user's old cryptohome at her 288731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // request, and the remove failed. 289731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 290731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 291731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, &ParallelAuthenticator::OnLoginFailure, 292731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LoginFailure(LoginFailure::DATA_REMOVAL_FAILED))); 293731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 294731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case FAILED_TMPFS: 295731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // In this case, we tried to mount a tmpfs for BWSI or the localaccount 296731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // user and failed. 297731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 298731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 299731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, &ParallelAuthenticator::OnLoginFailure, 300731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS))); 301731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 302731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case CREATE_NEW: 303731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick create = true; 304731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case RECOVER_MOUNT: 305731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_state_->ResetCryptohomeStatus(); 306731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), 307731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick this, 308731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick create); 309731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 310731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 311731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(mounter_.get(), &CryptohomeOp::Initiate)); 312731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 313731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case NEED_OLD_PW: 314731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 315731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 316731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, 317731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &ParallelAuthenticator::OnPasswordChangeDetected, 318731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_state_->credentials())); 319731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 320731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case ONLINE_FAILED: 321731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // In this case, we know online login was rejected because the account 322731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // is disabled or something similarly fatal. Sending the user through 323731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // the same path they get when their password is rejected is cleaner 324731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // for now. 325731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(cmasone): optimize this so that we don't send the user through 326731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // the 'changed password' path when we know doing so won't succeed. 327731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case NEED_NEW_PW: 328731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick { 3293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::AutoLock for_this_block(success_lock_); 330731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!already_reported_success_) { 331731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // This allows us to present the same behavior for "online: 332731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // fail, offline: ok", regardless of the order in which we 333731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // receive the results. There will be cases in which we get 334731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // the online failure some time after the offline success, 335731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // so we just force all cases in this category to present like this: 336731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // OnLoginSuccess(..., ..., true) -> OnLoginFailure(). 337731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 338731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 339731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, &ParallelAuthenticator::OnLoginSuccess, 340731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_state_->credentials(), true)); 341731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 342731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 343731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 344731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 345731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, &ParallelAuthenticator::OnLoginFailure, 34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (reauth_state_.get() ? 34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reauth_state_->online_outcome() : 34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_state_->online_outcome()))); 349731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 350731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case HAVE_NEW_PW: 351731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick key_migrator_ = 352731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CryptohomeOp::CreateMigrateAttempt(reauth_state_.get(), 353731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick this, 3544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch true, 3554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch current_state_->ascii_hash); 356731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 357731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 358731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(key_migrator_.get(), &CryptohomeOp::Initiate)); 359731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 360731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case OFFLINE_LOGIN: 36121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen VLOG(2) << "Offline login"; 362731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick request_pending = !current_state_->online_complete(); 363731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Fall through. 364731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case UNLOCK: 365731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Fall through. 366731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case ONLINE_LOGIN: 36721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen VLOG(2) << "Online login"; 368731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 369731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 370731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, &ParallelAuthenticator::OnLoginSuccess, 371731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_state_->credentials(), request_pending)); 372731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case LOCAL_LOGIN: 374731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 375731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 376731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod( 377731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick this, 378731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &ParallelAuthenticator::OnOffTheRecordLoginSuccess)); 379731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 380731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case LOGIN_FAILED: 381731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_state_->ResetCryptohomeStatus(); 382731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 383731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::FILE, FROM_HERE, 384731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NewRunnableMethod(this, &ParallelAuthenticator::CheckLocalaccount, 385731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick current_state_->online_outcome())); 386731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 387731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick default: 388731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NOTREACHED(); 389731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 390731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 391731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 392731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 393731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::AuthState ParallelAuthenticator::ResolveState() { 394731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 395731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If we haven't mounted the user's home dir yet, we can't be done. 396731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // We never get past here if a cryptohome op is still pending. 397731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // This is an important invariant. 398731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!current_state_->cryptohome_complete()) 399731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return CONTINUE; 400731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 401731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AuthState state = (reauth_state_.get() ? ResolveReauthState() : CONTINUE); 402731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (state != CONTINUE) 403731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return state; 404731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 405731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (current_state_->cryptohome_outcome()) 406731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick state = ResolveCryptohomeSuccessState(); 407731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick else 408731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick state = ResolveCryptohomeFailureState(); 409731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 410731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(current_state_->cryptohome_complete()); // Ensure invariant holds. 411731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick key_migrator_ = NULL; 412731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick data_remover_ = NULL; 413731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick guest_mounter_ = NULL; 414731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick key_checker_ = NULL; 415731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 416731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (state != POSSIBLE_PW_CHANGE && 417731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick state != NO_MOUNT && 418731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick state != OFFLINE_LOGIN) 419731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return state; 420731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 421731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (current_state_->online_complete()) { 422731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (current_state_->online_outcome().reason() == LoginFailure::NONE) { 423731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Online attempt succeeded as well, so combine the results. 424731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ResolveOnlineSuccessState(state); 425731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 426731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Online login attempt was rejected or failed to occur. 427731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ResolveOnlineFailureState(state); 428731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 429731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // if online isn't complete yet, just return the offline result. 430731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return state; 431731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 432731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 433731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::AuthState 434731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::ResolveReauthState() { 435731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 436731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (reauth_state_->cryptohome_complete()) { 437731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!reauth_state_->cryptohome_outcome()) { 438731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If we've tried to migrate and failed, log the error and just wait 439731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // til next time the user logs in to migrate their cryptohome key. 440731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LOG(ERROR) << "Failed to migrate cryptohome key: " 441731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << reauth_state_->cryptohome_code(); 442731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 443731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick reauth_state_.reset(NULL); 444731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ONLINE_LOGIN; 445731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 446731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Haven't tried the migrate yet, must be processing the online auth attempt. 447731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!reauth_state_->online_complete()) { 448731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NOTREACHED(); // Shouldn't be here at all, if online reauth isn't done! 449731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return CONTINUE; 450731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 451731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return (reauth_state_->online_outcome().reason() == LoginFailure::NONE) ? 452731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HAVE_NEW_PW : NEED_NEW_PW; 453731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 454731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 455731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::AuthState 456731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::ResolveCryptohomeFailureState() { 457731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 458731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (data_remover_.get()) 459731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return FAILED_REMOVE; 460731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (guest_mounter_.get()) 461731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return FAILED_TMPFS; 462731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (key_migrator_.get()) 463731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return NEED_OLD_PW; 464731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (key_checker_.get()) 465731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return LOGIN_FAILED; 466731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (current_state_->cryptohome_code() == 467731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick chromeos::kCryptohomeMountErrorKeyFailure) { 468731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If we tried a mount but they used the wrong key, we may need to 469731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // ask the user for her old password. We'll only know once we've 470731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // done the online check. 471731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return POSSIBLE_PW_CHANGE; 472731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 473731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (current_state_->cryptohome_code() == 474731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick chromeos::kCryptohomeMountErrorUserDoesNotExist) { 475731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If we tried a mount but the user did not exist, then we should wait 476731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // for online login to succeed and try again with the "create" flag set. 477731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return NO_MOUNT; 478731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 479731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return FAILED_MOUNT; 480731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 481731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 482731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::AuthState 483731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::ResolveCryptohomeSuccessState() { 484731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 485731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (data_remover_.get()) 486731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return CREATE_NEW; 487731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (guest_mounter_.get()) 488731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return LOCAL_LOGIN; 489731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (key_migrator_.get()) 490731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return RECOVER_MOUNT; 491731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (key_checker_.get()) 492731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return UNLOCK; 493731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return OFFLINE_LOGIN; 494731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 495731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 496731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::AuthState 497731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::ResolveOnlineFailureState( 498731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ParallelAuthenticator::AuthState offline_state) { 499731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 500731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (offline_state == OFFLINE_LOGIN) { 501731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (current_state_->online_outcome().error().state() == 502731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GoogleServiceAuthError::CONNECTION_FAILED) { 503731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Couldn't do an online check, so just go with the offline result. 504731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return OFFLINE_LOGIN; 505731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 506731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Otherwise, online login was rejected! 507731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (current_state_->online_outcome().error().state() == 508731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) { 509731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return NEED_NEW_PW; 510731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 511731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ONLINE_FAILED; 512731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 513731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return LOGIN_FAILED; 514731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 515731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 516731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::AuthState 517731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickParallelAuthenticator::ResolveOnlineSuccessState( 518731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ParallelAuthenticator::AuthState offline_state) { 519731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 520731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick switch (offline_state) { 521731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case POSSIBLE_PW_CHANGE: 522731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return NEED_OLD_PW; 523731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case NO_MOUNT: 524731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return CREATE_NEW; 525731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case OFFLINE_LOGIN: 526731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ONLINE_LOGIN; 527731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick default: 528731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NOTREACHED(); 529731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return offline_state; 530731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 531731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 532731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 533731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::LoadSystemSalt() { 534731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!system_salt_.empty()) 535731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 536731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick system_salt_ = CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(); 537731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CHECK(!system_salt_.empty()); 538731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CHECK_EQ(system_salt_.size() % 2, 0U); 539731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 540731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 541731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::LoadLocalaccount(const std::string& filename) { 542731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 543731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick { 5443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::AutoLock for_this_block(localaccount_lock_); 545731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (checked_for_localaccount_) 546731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 547731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 548731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick FilePath localaccount_file; 549731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string localaccount; 550731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (PathService::Get(base::DIR_EXE, &localaccount_file)) { 551731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick localaccount_file = localaccount_file.Append(filename); 55221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen VLOG(2) << "Looking for localaccount in " << localaccount_file.value(); 553731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 554731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ReadFileToString(localaccount_file, &localaccount); 555731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick TrimWhitespaceASCII(localaccount, TRIM_TRAILING, &localaccount); 556731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Loading localaccount: " << localaccount; 557731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 558731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Assuming no localaccount"; 559731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 560731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SetLocalaccount(localaccount); 561731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 562731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 563731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid ParallelAuthenticator::SetLocalaccount(const std::string& new_name) { 564731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick localaccount_ = new_name; 565731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick { // extra braces for clarity about AutoLock scope. 5663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::AutoLock for_this_block(localaccount_lock_); 567731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick checked_for_localaccount_ = true; 568731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 569731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 570731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 571731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 572731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::string ParallelAuthenticator::HashPassword(const std::string& password) { 573731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Get salt, ascii encode, update sha with that, then update with ascii 574731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // of password, then end. 575731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string ascii_salt = SaltAsAscii(); 576731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick unsigned char passhash_buf[kPassHashLen]; 577731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick char ascii_buf[kPassHashLen + 1]; 578731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 579731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Hash salt and password 580731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SHA256Context ctx; 581731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SHA256_Begin(&ctx); 582731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SHA256_Update(&ctx, 583731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick reinterpret_cast<const unsigned char*>(ascii_salt.data()), 584731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick static_cast<unsigned int>(ascii_salt.length())); 585731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SHA256_Update(&ctx, 586731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick reinterpret_cast<const unsigned char*>(password.data()), 587731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick static_cast<unsigned int>(password.length())); 588731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SHA256_End(&ctx, 589731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick passhash_buf, 590731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NULL, 591731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick static_cast<unsigned int>(sizeof(passhash_buf))); 592731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 593731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::vector<unsigned char> passhash(passhash_buf, 594731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick passhash_buf + sizeof(passhash_buf)); 595731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BinaryToHex(passhash, 596731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick passhash.size() / 2, // only want top half, at least for now. 597731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ascii_buf, 598731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick sizeof(ascii_buf)); 599731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return std::string(ascii_buf, sizeof(ascii_buf) - 1); 600731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 601731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 602731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::string ParallelAuthenticator::SaltAsAscii() { 603731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LoadSystemSalt(); // no-op if it's already loaded. 604731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick unsigned int salt_len = system_salt_.size(); 605731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick char ascii_salt[2 * salt_len + 1]; 606731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (ParallelAuthenticator::BinaryToHex(system_salt_, 607731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick salt_len, 608731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ascii_salt, 609731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick sizeof(ascii_salt))) { 610731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return std::string(ascii_salt, sizeof(ascii_salt) - 1); 611731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 612731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return std::string(); 613731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 614731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 615731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static 616731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool ParallelAuthenticator::BinaryToHex( 617731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::vector<unsigned char>& binary, 618731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const unsigned int binary_len, 619731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick char* hex_string, 620731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const unsigned int len) { 621731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (len < 2*binary_len) 622731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return false; 623731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick memset(hex_string, 0, len); 624731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (uint i = 0, j = 0; i < binary_len; i++, j+=2) 625731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick snprintf(hex_string + j, len - j, "%02x", binary[i]); 626731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 627731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 628731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 629731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} // namespace chromeos 630