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 |