| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/login/auth/parallel_authenticator.h" | 5 #include "chrome/browser/chromeos/login/auth/parallel_authenticator.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/logging.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" | 11 #include "chrome/browser/chrome_notification_types.h" |
| 14 #include "chrome/browser/chromeos/boot_times_loader.h" | 12 #include "chrome/browser/chromeos/boot_times_loader.h" |
| 15 #include "chrome/browser/chromeos/login/auth/authentication_notification_details
.h" | 13 #include "chrome/browser/chromeos/login/auth/authentication_notification_details
.h" |
| 14 #include "chrome/browser/chromeos/login/auth/key.h" |
| 16 #include "chrome/browser/chromeos/login/auth/login_status_consumer.h" | 15 #include "chrome/browser/chromeos/login/auth/login_status_consumer.h" |
| 17 #include "chrome/browser/chromeos/login/auth/user_context.h" | 16 #include "chrome/browser/chromeos/login/auth/user_context.h" |
| 18 #include "chrome/browser/chromeos/login/users/user.h" | 17 #include "chrome/browser/chromeos/login/users/user.h" |
| 19 #include "chrome/browser/chromeos/login/users/user_manager.h" | 18 #include "chrome/browser/chromeos/login/users/user_manager.h" |
| 20 #include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h" | 19 #include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h" |
| 21 #include "chrome/browser/chromeos/settings/cros_settings.h" | 20 #include "chrome/browser/chromeos/settings/cros_settings.h" |
| 22 #include "chrome/common/chrome_switches.h" | 21 #include "chrome/common/chrome_switches.h" |
| 23 #include "chromeos/cryptohome/async_method_caller.h" | 22 #include "chromeos/cryptohome/async_method_caller.h" |
| 24 #include "chromeos/cryptohome/system_salt_getter.h" | 23 #include "chromeos/cryptohome/system_salt_getter.h" |
| 25 #include "chromeos/dbus/cryptohome_client.h" | 24 #include "chromeos/dbus/cryptohome_client.h" |
| 26 #include "chromeos/dbus/dbus_thread_manager.h" | 25 #include "chromeos/dbus/dbus_thread_manager.h" |
| 27 #include "chromeos/login/login_state.h" | 26 #include "chromeos/login/login_state.h" |
| 28 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
| 29 #include "content/public/browser/notification_service.h" | 28 #include "content/public/browser/notification_service.h" |
| 30 #include "crypto/sha2.h" | |
| 31 #include "third_party/cros_system_api/dbus/service_constants.h" | 29 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 32 | 30 |
| 33 using content::BrowserThread; | 31 using content::BrowserThread; |
| 34 | 32 |
| 35 namespace chromeos { | 33 namespace chromeos { |
| 36 | 34 |
| 37 namespace { | 35 namespace { |
| 38 | 36 |
| 39 // Length of password hashed with SHA-256. | 37 // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN. |
| 40 const int kPasswordHashLength = 32; | 38 // Returns the keys unmodified otherwise. |
| 39 scoped_ptr<Key> TransformKeyIfNeeded(const Key& key, |
| 40 const std::string& system_salt) { |
| 41 scoped_ptr<Key> result(new Key(key)); |
| 42 if (result->GetKeyType() == Key::KEY_TYPE_PASSWORD_PLAIN) |
| 43 result->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, system_salt); |
| 44 |
| 45 return result.Pass(); |
| 46 } |
| 41 | 47 |
| 42 // Records status and calls resolver->Resolve(). | 48 // Records status and calls resolver->Resolve(). |
| 43 void TriggerResolve(AuthAttemptState* attempt, | 49 void TriggerResolve(AuthAttemptState* attempt, |
| 44 scoped_refptr<ParallelAuthenticator> resolver, | 50 scoped_refptr<ParallelAuthenticator> resolver, |
| 45 bool success, | 51 bool success, |
| 46 cryptohome::MountError return_code) { | 52 cryptohome::MountError return_code) { |
| 47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 48 attempt->RecordCryptohomeStatus(success, return_code); | 54 attempt->RecordCryptohomeStatus(success, return_code); |
| 49 resolver->Resolve(); | 55 resolver->Resolve(); |
| 50 } | 56 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 77 void Mount(AuthAttemptState* attempt, | 83 void Mount(AuthAttemptState* attempt, |
| 78 scoped_refptr<ParallelAuthenticator> resolver, | 84 scoped_refptr<ParallelAuthenticator> resolver, |
| 79 int flags, | 85 int flags, |
| 80 const std::string& system_salt) { | 86 const std::string& system_salt) { |
| 81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 87 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 82 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( | 88 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( |
| 83 "CryptohomeMount-Start", false); | 89 "CryptohomeMount-Start", false); |
| 84 // Set state that username_hash is requested here so that test implementation | 90 // Set state that username_hash is requested here so that test implementation |
| 85 // that returns directly would not generate 2 OnLoginSucces() calls. | 91 // that returns directly would not generate 2 OnLoginSucces() calls. |
| 86 attempt->UsernameHashRequested(); | 92 attempt->UsernameHashRequested(); |
| 93 |
| 94 scoped_ptr<Key> key = |
| 95 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt); |
| 87 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMount( | 96 cryptohome::AsyncMethodCaller::GetInstance()->AsyncMount( |
| 88 attempt->user_context.GetUserID(), | 97 attempt->user_context.GetUserID(), |
| 89 ParallelAuthenticator::HashPassword(attempt->user_context.GetPassword(), | 98 key->GetSecret(), |
| 90 system_salt), | |
| 91 flags, | 99 flags, |
| 92 base::Bind(&TriggerResolveWithLoginTimeMarker, | 100 base::Bind(&TriggerResolveWithLoginTimeMarker, |
| 93 "CryptohomeMount-End", | 101 "CryptohomeMount-End", |
| 94 attempt, | 102 attempt, |
| 95 resolver)); | 103 resolver)); |
| 96 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername( | 104 cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername( |
| 97 attempt->user_context.GetUserID(), | 105 attempt->user_context.GetUserID(), |
| 98 base::Bind(&TriggerResolveHash, | 106 base::Bind(&TriggerResolveHash, |
| 99 attempt, | 107 attempt, |
| 100 resolver)); | 108 resolver)); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 void Migrate(AuthAttemptState* attempt, | 160 void Migrate(AuthAttemptState* attempt, |
| 153 scoped_refptr<ParallelAuthenticator> resolver, | 161 scoped_refptr<ParallelAuthenticator> resolver, |
| 154 bool passing_old_hash, | 162 bool passing_old_hash, |
| 155 const std::string& old_password, | 163 const std::string& old_password, |
| 156 const std::string& system_salt) { | 164 const std::string& system_salt) { |
| 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 158 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( | 166 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( |
| 159 "CryptohomeMigrate-Start", false); | 167 "CryptohomeMigrate-Start", false); |
| 160 cryptohome::AsyncMethodCaller* caller = | 168 cryptohome::AsyncMethodCaller* caller = |
| 161 cryptohome::AsyncMethodCaller::GetInstance(); | 169 cryptohome::AsyncMethodCaller::GetInstance(); |
| 170 |
| 171 // TODO(bartfab): Retrieve the hashing algorithm and salt to use for |old_key| |
| 172 // from cryptohomed. |
| 173 scoped_ptr<Key> old_key = |
| 174 TransformKeyIfNeeded(Key(old_password), system_salt); |
| 175 scoped_ptr<Key> new_key = |
| 176 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt); |
| 162 if (passing_old_hash) { | 177 if (passing_old_hash) { |
| 163 caller->AsyncMigrateKey( | 178 caller->AsyncMigrateKey(attempt->user_context.GetUserID(), |
| 164 attempt->user_context.GetUserID(), | 179 old_key->GetSecret(), |
| 165 ParallelAuthenticator::HashPassword(old_password, system_salt), | 180 new_key->GetSecret(), |
| 166 ParallelAuthenticator::HashPassword(attempt->user_context.GetPassword(), | 181 base::Bind(&TriggerResolveWithLoginTimeMarker, |
| 167 system_salt), | 182 "CryptohomeMount-End", |
| 168 base::Bind(&TriggerResolveWithLoginTimeMarker, | 183 attempt, |
| 169 "CryptohomeMount-End", | 184 resolver)); |
| 170 attempt, | |
| 171 resolver)); | |
| 172 } else { | 185 } else { |
| 173 caller->AsyncMigrateKey( | 186 caller->AsyncMigrateKey(attempt->user_context.GetUserID(), |
| 174 attempt->user_context.GetUserID(), | 187 new_key->GetSecret(), |
| 175 ParallelAuthenticator::HashPassword(attempt->user_context.GetPassword(), | 188 old_key->GetSecret(), |
| 176 system_salt), | 189 base::Bind(&TriggerResolveWithLoginTimeMarker, |
| 177 ParallelAuthenticator::HashPassword(old_password, system_salt), | 190 "CryptohomeMount-End", |
| 178 base::Bind(&TriggerResolveWithLoginTimeMarker, | 191 attempt, |
| 179 "CryptohomeMount-End", | 192 resolver)); |
| 180 attempt, | |
| 181 resolver)); | |
| 182 } | 193 } |
| 183 } | 194 } |
| 184 | 195 |
| 185 // Calls cryptohome's remove method. | 196 // Calls cryptohome's remove method. |
| 186 void Remove(AuthAttemptState* attempt, | 197 void Remove(AuthAttemptState* attempt, |
| 187 scoped_refptr<ParallelAuthenticator> resolver) { | 198 scoped_refptr<ParallelAuthenticator> resolver) { |
| 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 189 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( | 200 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( |
| 190 "CryptohomeRemove-Start", false); | 201 "CryptohomeRemove-Start", false); |
| 191 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( | 202 cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove( |
| 192 attempt->user_context.GetUserID(), | 203 attempt->user_context.GetUserID(), |
| 193 base::Bind(&TriggerResolveWithLoginTimeMarker, | 204 base::Bind(&TriggerResolveWithLoginTimeMarker, |
| 194 "CryptohomeRemove-End", | 205 "CryptohomeRemove-End", |
| 195 attempt, | 206 attempt, |
| 196 resolver)); | 207 resolver)); |
| 197 } | 208 } |
| 198 | 209 |
| 199 // Calls cryptohome's key check method. | 210 // Calls cryptohome's key check method. |
| 200 void CheckKey(AuthAttemptState* attempt, | 211 void CheckKey(AuthAttemptState* attempt, |
| 201 scoped_refptr<ParallelAuthenticator> resolver, | 212 scoped_refptr<ParallelAuthenticator> resolver, |
| 202 const std::string& system_salt) { | 213 const std::string& system_salt) { |
| 203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 215 scoped_ptr<Key> key = |
| 216 TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt); |
| 204 cryptohome::AsyncMethodCaller::GetInstance()->AsyncCheckKey( | 217 cryptohome::AsyncMethodCaller::GetInstance()->AsyncCheckKey( |
| 205 attempt->user_context.GetUserID(), | 218 attempt->user_context.GetUserID(), |
| 206 ParallelAuthenticator::HashPassword(attempt->user_context.GetPassword(), | 219 key->GetSecret(), |
| 207 system_salt), | |
| 208 base::Bind(&TriggerResolve, attempt, resolver)); | 220 base::Bind(&TriggerResolve, attempt, resolver)); |
| 209 } | 221 } |
| 210 | 222 |
| 211 } // namespace | 223 } // namespace |
| 212 | 224 |
| 213 ParallelAuthenticator::ParallelAuthenticator(LoginStatusConsumer* consumer) | 225 ParallelAuthenticator::ParallelAuthenticator(LoginStatusConsumer* consumer) |
| 214 : Authenticator(consumer), | 226 : Authenticator(consumer), |
| 215 migrate_attempted_(false), | 227 migrate_attempted_(false), |
| 216 remove_attempted_(false), | 228 remove_attempted_(false), |
| 217 resync_attempted_(false), | 229 resync_attempted_(false), |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 this, | 665 this, |
| 654 LoginFailure(LoginFailure::OWNER_REQUIRED))); | 666 LoginFailure(LoginFailure::OWNER_REQUIRED))); |
| 655 break; | 667 break; |
| 656 } | 668 } |
| 657 default: | 669 default: |
| 658 NOTREACHED(); | 670 NOTREACHED(); |
| 659 break; | 671 break; |
| 660 } | 672 } |
| 661 } | 673 } |
| 662 | 674 |
| 663 // static. | |
| 664 std::string ParallelAuthenticator::HashPassword(const std::string& password, | |
| 665 const std::string& ascii_salt) { | |
| 666 // Update sha with ascii encoded salt, then update with ascii of password, | |
| 667 // then end. | |
| 668 // TODO(stevenjb/nkostylev): Handle empty system salt gracefully. | |
| 669 CHECK(!ascii_salt.empty()); | |
| 670 char passhash_buf[kPasswordHashLength]; | |
| 671 | |
| 672 // Hash salt and password | |
| 673 crypto::SHA256HashString(ascii_salt + password, | |
| 674 &passhash_buf, sizeof(passhash_buf)); | |
| 675 | |
| 676 // Only want the top half for 'weak' hashing so that the passphrase is not | |
| 677 // immediately exposed even if the output is reversed. | |
| 678 const int encoded_length = sizeof(passhash_buf) / 2; | |
| 679 | |
| 680 return StringToLowerASCII(base::HexEncode( | |
| 681 reinterpret_cast<const void*>(passhash_buf), encoded_length)); | |
| 682 } | |
| 683 | |
| 684 ParallelAuthenticator::~ParallelAuthenticator() {} | 675 ParallelAuthenticator::~ParallelAuthenticator() {} |
| 685 | 676 |
| 686 ParallelAuthenticator::AuthState ParallelAuthenticator::ResolveState() { | 677 ParallelAuthenticator::AuthState ParallelAuthenticator::ResolveState() { |
| 687 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 688 // If we haven't mounted the user's home dir yet or | 679 // If we haven't mounted the user's home dir yet or |
| 689 // haven't got sanitized username value, we can't be done. | 680 // haven't got sanitized username value, we can't be done. |
| 690 // We never get past here if any of these two cryptohome ops is still pending. | 681 // We never get past here if any of these two cryptohome ops is still pending. |
| 691 // This is an important invariant. | 682 // This is an important invariant. |
| 692 if (!current_state_->cryptohome_complete() || | 683 if (!current_state_->cryptohome_complete() || |
| 693 !current_state_->username_hash_obtained()) { | 684 !current_state_->username_hash_obtained()) { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 Resolve(); | 811 Resolve(); |
| 821 } | 812 } |
| 822 | 813 |
| 823 void ParallelAuthenticator::SetOwnerState(bool owner_check_finished, | 814 void ParallelAuthenticator::SetOwnerState(bool owner_check_finished, |
| 824 bool check_result) { | 815 bool check_result) { |
| 825 owner_is_verified_ = owner_check_finished; | 816 owner_is_verified_ = owner_check_finished; |
| 826 user_can_login_ = check_result; | 817 user_can_login_ = check_result; |
| 827 } | 818 } |
| 828 | 819 |
| 829 } // namespace chromeos | 820 } // namespace chromeos |
| OLD | NEW |