OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/parallel_authenticator.h" | 5 #include "chrome/browser/chromeos/login/parallel_authenticator.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 15 matching lines...) Expand all Loading... | |
26 #include "chrome/browser/chromeos/login/user_manager.h" | 26 #include "chrome/browser/chromeos/login/user_manager.h" |
27 #include "chrome/browser/profiles/profile.h" | 27 #include "chrome/browser/profiles/profile.h" |
28 #include "chrome/browser/profiles/profile_manager.h" | 28 #include "chrome/browser/profiles/profile_manager.h" |
29 #include "chrome/common/chrome_notification_types.h" | 29 #include "chrome/common/chrome_notification_types.h" |
30 #include "chrome/common/chrome_paths.h" | 30 #include "chrome/common/chrome_paths.h" |
31 #include "chrome/common/chrome_switches.h" | 31 #include "chrome/common/chrome_switches.h" |
32 #include "chrome/common/net/gaia/gaia_auth_fetcher.h" | 32 #include "chrome/common/net/gaia/gaia_auth_fetcher.h" |
33 #include "chrome/common/net/gaia/gaia_constants.h" | 33 #include "chrome/common/net/gaia/gaia_constants.h" |
34 #include "content/public/browser/browser_thread.h" | 34 #include "content/public/browser/browser_thread.h" |
35 #include "content/public/browser/notification_service.h" | 35 #include "content/public/browser/notification_service.h" |
36 #include "crypto/encryptor.h" | 36 #include "crypto/encryptor.h" |
Nikita (slow)
2011/12/01 14:34:13
Unused includes should be removed with this code m
zel
2011/12/02 02:35:23
yeah and few others got removed. done.
| |
37 #include "crypto/sha2.h" | 37 #include "crypto/sha2.h" |
38 #include "crypto/symmetric_key.h" | 38 #include "crypto/symmetric_key.h" |
39 #include "net/base/load_flags.h" | 39 #include "net/base/load_flags.h" |
40 #include "net/base/net_errors.h" | 40 #include "net/base/net_errors.h" |
41 #include "net/url_request/url_request_status.h" | 41 #include "net/url_request/url_request_status.h" |
42 #include "third_party/libjingle/source/talk/base/urlencode.h" | 42 #include "third_party/libjingle/source/talk/base/urlencode.h" |
43 | 43 |
44 using base::Time; | 44 using base::Time; |
45 using base::TimeDelta; | 45 using base::TimeDelta; |
46 using content::BrowserThread; | 46 using content::BrowserThread; |
47 using file_util::GetFileSize; | 47 using file_util::GetFileSize; |
48 using file_util::PathExists; | 48 using file_util::PathExists; |
49 using file_util::ReadFile; | 49 using file_util::ReadFile; |
50 using file_util::ReadFileToString; | 50 using file_util::ReadFileToString; |
51 | 51 |
52 namespace { | |
53 | |
54 const int kPassHashLen = 32; | |
55 const size_t kKeySize = 16; | |
56 | |
57 // Decrypts (AES) hex encoded encrypted token given |key| and |salt|. | |
58 std::string DecryptTokenWithKey( | |
59 crypto::SymmetricKey* key, | |
60 const std::string& salt, | |
61 const std::string& encrypted_token_hex) { | |
62 std::vector<uint8> encrypted_token_bytes; | |
63 if (!base::HexStringToBytes(encrypted_token_hex, &encrypted_token_bytes)) | |
64 return std::string(); | |
65 | |
66 std::string encrypted_token( | |
67 reinterpret_cast<char*>(encrypted_token_bytes.data()), | |
68 encrypted_token_bytes.size()); | |
69 crypto::Encryptor encryptor; | |
70 if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) | |
71 return std::string(); | |
72 | |
73 std::string nonce = salt.substr(0, kKeySize); | |
74 std::string token; | |
75 CHECK(encryptor.SetCounter(nonce)); | |
76 if (!encryptor.Decrypt(encrypted_token, &token)) | |
77 return std::string(); | |
78 return token; | |
79 } | |
80 | |
81 } // namespace | |
82 | |
83 namespace chromeos { | 52 namespace chromeos { |
84 | 53 |
85 // static | 54 // static |
86 const char ParallelAuthenticator::kLocalaccountFile[] = "localaccount"; | 55 const char ParallelAuthenticator::kLocalaccountFile[] = "localaccount"; |
87 | 56 |
88 // static | 57 // static |
89 const int ParallelAuthenticator::kClientLoginTimeoutMs = 10000; | 58 const int ParallelAuthenticator::kClientLoginTimeoutMs = 10000; |
90 // static | 59 // static |
91 const int ParallelAuthenticator::kLocalaccountRetryIntervalMs = 20; | 60 const int ParallelAuthenticator::kLocalaccountRetryIntervalMs = 20; |
92 | 61 |
(...skipping 15 matching lines...) Expand all Loading... | |
108 | 77 |
109 void ParallelAuthenticator::AuthenticateToLogin( | 78 void ParallelAuthenticator::AuthenticateToLogin( |
110 Profile* profile, | 79 Profile* profile, |
111 const std::string& username, | 80 const std::string& username, |
112 const std::string& password, | 81 const std::string& password, |
113 const std::string& login_token, | 82 const std::string& login_token, |
114 const std::string& login_captcha) { | 83 const std::string& login_captcha) { |
115 std::string canonicalized = Authenticator::Canonicalize(username); | 84 std::string canonicalized = Authenticator::Canonicalize(username); |
116 authentication_profile_ = profile; | 85 authentication_profile_ = profile; |
117 current_state_.reset( | 86 current_state_.reset( |
118 new AuthAttemptState(canonicalized, | 87 new AuthAttemptState( |
119 password, | 88 canonicalized, |
120 HashPassword(password), | 89 password, |
121 login_token, | 90 CrosLibrary::Get()->GetCryptohomeLibrary()->HashPassword(password), |
122 login_captcha, | 91 login_token, |
123 !UserManager::Get()->IsKnownUser(canonicalized))); | 92 login_captcha, |
93 !UserManager::Get()->IsKnownUser(canonicalized))); | |
124 mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), | 94 mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), |
125 this, | 95 this, |
126 false /* don't create */); | 96 false /* don't create */); |
127 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ | 97 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ |
128 BrowserThread::PostTask( | 98 BrowserThread::PostTask( |
129 BrowserThread::UI, FROM_HERE, | 99 BrowserThread::UI, FROM_HERE, |
130 | 100 |
131 base::Bind(&CryptohomeOp::Initiate, mounter_.get())); | 101 base::Bind(&CryptohomeOp::Initiate, mounter_.get())); |
132 // ClientLogin authentication check should happen immediately here. | 102 // ClientLogin authentication check should happen immediately here. |
133 // We should not try OAuthLogin check until the profile loads. | 103 // We should not try OAuthLogin check until the profile loads. |
(...skipping 10 matching lines...) Expand all Loading... | |
144 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this, | 114 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this, |
145 std::string(kLocalaccountFile))); | 115 std::string(kLocalaccountFile))); |
146 } | 116 } |
147 | 117 |
148 void ParallelAuthenticator::CompleteLogin(Profile* profile, | 118 void ParallelAuthenticator::CompleteLogin(Profile* profile, |
149 const std::string& username, | 119 const std::string& username, |
150 const std::string& password) { | 120 const std::string& password) { |
151 std::string canonicalized = Authenticator::Canonicalize(username); | 121 std::string canonicalized = Authenticator::Canonicalize(username); |
152 authentication_profile_ = profile; | 122 authentication_profile_ = profile; |
153 current_state_.reset( | 123 current_state_.reset( |
154 new AuthAttemptState(canonicalized, | 124 new AuthAttemptState( |
155 password, | 125 canonicalized, |
156 HashPassword(password), | 126 password, |
157 !UserManager::Get()->IsKnownUser(canonicalized))); | 127 CrosLibrary::Get()->GetCryptohomeLibrary()->HashPassword(password), |
128 !UserManager::Get()->IsKnownUser(canonicalized))); | |
158 mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), | 129 mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), |
159 this, | 130 this, |
160 false /* don't create */); | 131 false /* don't create */); |
161 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ | 132 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ |
162 BrowserThread::PostTask( | 133 BrowserThread::PostTask( |
163 BrowserThread::UI, FROM_HERE, | 134 BrowserThread::UI, FROM_HERE, |
164 base::Bind(&CryptohomeOp::Initiate, mounter_.get())); | 135 base::Bind(&CryptohomeOp::Initiate, mounter_.get())); |
165 | 136 |
166 if (!using_oauth_) { | 137 if (!using_oauth_) { |
167 // Test automation needs to disable oauth, but that leads to other | 138 // Test automation needs to disable oauth, but that leads to other |
(...skipping 15 matching lines...) Expand all Loading... | |
183 | 154 |
184 BrowserThread::PostTask( | 155 BrowserThread::PostTask( |
185 BrowserThread::FILE, FROM_HERE, | 156 BrowserThread::FILE, FROM_HERE, |
186 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this, | 157 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this, |
187 std::string(kLocalaccountFile))); | 158 std::string(kLocalaccountFile))); |
188 } | 159 } |
189 | 160 |
190 void ParallelAuthenticator::AuthenticateToUnlock(const std::string& username, | 161 void ParallelAuthenticator::AuthenticateToUnlock(const std::string& username, |
191 const std::string& password) { | 162 const std::string& password) { |
192 current_state_.reset( | 163 current_state_.reset( |
193 new AuthAttemptState(Authenticator::Canonicalize(username), | 164 new AuthAttemptState( |
194 HashPassword(password))); | 165 Authenticator::Canonicalize(username), |
166 CrosLibrary::Get()->GetCryptohomeLibrary()->HashPassword(password))); | |
195 BrowserThread::PostTask( | 167 BrowserThread::PostTask( |
196 BrowserThread::FILE, FROM_HERE, | 168 BrowserThread::FILE, FROM_HERE, |
197 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this, | 169 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this, |
198 std::string(kLocalaccountFile))); | 170 std::string(kLocalaccountFile))); |
199 key_checker_ = CryptohomeOp::CreateCheckKeyAttempt(current_state_.get(), | 171 key_checker_ = CryptohomeOp::CreateCheckKeyAttempt(current_state_.get(), |
200 this); | 172 this); |
201 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ | 173 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ |
202 BrowserThread::PostTask( | 174 BrowserThread::PostTask( |
203 BrowserThread::UI, FROM_HERE, | 175 BrowserThread::UI, FROM_HERE, |
204 base::Bind(&CryptohomeOp::Initiate, key_checker_.get())); | 176 base::Bind(&CryptohomeOp::Initiate, key_checker_.get())); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
304 DCHECK(using_oauth_); | 276 DCHECK(using_oauth_); |
305 // Mark this account's OAuth token state as invalid in the local state. | 277 // Mark this account's OAuth token state as invalid in the local state. |
306 UserManager::Get()->SaveUserOAuthStatus(user_name, | 278 UserManager::Get()->SaveUserOAuthStatus(user_name, |
307 User::OAUTH_TOKEN_STATUS_INVALID); | 279 User::OAUTH_TOKEN_STATUS_INVALID); |
308 } | 280 } |
309 | 281 |
310 void ParallelAuthenticator::RecoverEncryptedData( | 282 void ParallelAuthenticator::RecoverEncryptedData( |
311 const std::string& old_password, | 283 const std::string& old_password, |
312 const GaiaAuthConsumer::ClientLoginResult& credentials) { | 284 const GaiaAuthConsumer::ClientLoginResult& credentials) { |
313 std::string old_hash = HashPassword(old_password); | 285 std::string old_hash = |
286 CrosLibrary::Get()->GetCryptohomeLibrary()->HashPassword(old_password); | |
314 key_migrator_ = CryptohomeOp::CreateMigrateAttempt(current_state_.get(), | 287 key_migrator_ = CryptohomeOp::CreateMigrateAttempt(current_state_.get(), |
315 this, | 288 this, |
316 true, | 289 true, |
317 old_hash); | 290 old_hash); |
318 BrowserThread::PostTask( | 291 BrowserThread::PostTask( |
319 BrowserThread::IO, FROM_HERE, | 292 BrowserThread::IO, FROM_HERE, |
320 base::Bind(&ParallelAuthenticator::ResyncRecoverHelper, this, | 293 base::Bind(&ParallelAuthenticator::ResyncRecoverHelper, this, |
321 key_migrator_)); | 294 key_migrator_)); |
322 } | 295 } |
323 | 296 |
(...skipping 14 matching lines...) Expand all Loading... | |
338 BrowserThread::UI, FROM_HERE, | 311 BrowserThread::UI, FROM_HERE, |
339 base::Bind(&CryptohomeOp::Initiate, to_initiate)); | 312 base::Bind(&CryptohomeOp::Initiate, to_initiate)); |
340 } | 313 } |
341 | 314 |
342 void ParallelAuthenticator::RetryAuth(Profile* profile, | 315 void ParallelAuthenticator::RetryAuth(Profile* profile, |
343 const std::string& username, | 316 const std::string& username, |
344 const std::string& password, | 317 const std::string& password, |
345 const std::string& login_token, | 318 const std::string& login_token, |
346 const std::string& login_captcha) { | 319 const std::string& login_captcha) { |
347 reauth_state_.reset( | 320 reauth_state_.reset( |
348 new AuthAttemptState(Authenticator::Canonicalize(username), | 321 new AuthAttemptState( |
349 password, | 322 Authenticator::Canonicalize(username), |
350 HashPassword(password), | 323 password, |
351 login_token, | 324 CrosLibrary::Get()->GetCryptohomeLibrary()->HashPassword(password), |
352 login_captcha, | 325 login_token, |
353 false /* not a new user */)); | 326 login_captcha, |
327 false /* not a new user */)); | |
354 // Always use ClientLogin regardless of using_oauth flag. This is because | 328 // Always use ClientLogin regardless of using_oauth flag. This is because |
355 // we are unable to renew oauth token on lock screen currently and will | 329 // we are unable to renew oauth token on lock screen currently and will |
356 // stuck with lock screen if we use OAuthLogin here. | 330 // stuck with lock screen if we use OAuthLogin here. |
357 // TODO(xiyuan): Revisit this after we support Gaia in lock screen. | 331 // TODO(xiyuan): Revisit this after we support Gaia in lock screen. |
358 current_online_ = new OnlineAttempt(false /* using_oauth */, | 332 current_online_ = new OnlineAttempt(false /* using_oauth */, |
359 reauth_state_.get(), | 333 reauth_state_.get(), |
360 this); | 334 this); |
361 current_online_->Initiate(profile); | 335 current_online_->Initiate(profile); |
362 } | 336 } |
363 | 337 |
364 | 338 |
365 void ParallelAuthenticator::VerifyOAuth1AccessToken( | |
366 const std::string& oauth1_access_token, const std::string& oauth1_secret) { | |
367 DCHECK(using_oauth_); | |
368 current_state_->SetOAuth1Token(oauth1_access_token, oauth1_secret); | |
369 // Initiate ClientLogin-based post authentication. | |
370 current_online_ = new OnlineAttempt(using_oauth_, | |
371 current_state_.get(), | |
372 this); | |
373 current_online_->Initiate(authentication_profile()); | |
374 } | |
375 | |
376 | |
377 void ParallelAuthenticator::Resolve() { | 339 void ParallelAuthenticator::Resolve() { |
378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
379 bool request_pending = false; | 341 bool request_pending = false; |
380 bool create = false; | 342 bool create = false; |
381 ParallelAuthenticator::AuthState state = ResolveState(); | 343 ParallelAuthenticator::AuthState state = ResolveState(); |
382 VLOG(1) << "Resolved state to: " << state; | 344 VLOG(1) << "Resolved state to: " << state; |
383 switch (state) { | 345 switch (state) { |
384 case CONTINUE: | 346 case CONTINUE: |
385 case POSSIBLE_PW_CHANGE: | 347 case POSSIBLE_PW_CHANGE: |
386 case NO_MOUNT: | 348 case NO_MOUNT: |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
670 case NO_MOUNT: | 632 case NO_MOUNT: |
671 return CREATE_NEW; | 633 return CREATE_NEW; |
672 case OFFLINE_LOGIN: | 634 case OFFLINE_LOGIN: |
673 return ONLINE_LOGIN; | 635 return ONLINE_LOGIN; |
674 default: | 636 default: |
675 NOTREACHED(); | 637 NOTREACHED(); |
676 return offline_state; | 638 return offline_state; |
677 } | 639 } |
678 } | 640 } |
679 | 641 |
680 void ParallelAuthenticator::LoadSystemSalt() { | |
681 if (!system_salt_.empty()) | |
682 return; | |
683 system_salt_ = CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(); | |
684 CHECK(!system_salt_.empty()); | |
685 CHECK_EQ(system_salt_.size() % 2, 0U); | |
686 } | |
687 | |
688 bool ParallelAuthenticator::LoadSupplementalUserKey() { | |
689 if (!supplemental_user_key_.get()) { | |
690 supplemental_user_key_.reset( | |
691 CrosLibrary::Get()->GetCertLibrary()->GetSupplementalUserKey()); | |
692 } | |
693 return supplemental_user_key_.get() != NULL; | |
694 } | |
695 | |
696 | |
697 void ParallelAuthenticator::LoadLocalaccount(const std::string& filename) { | 642 void ParallelAuthenticator::LoadLocalaccount(const std::string& filename) { |
698 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 643 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
699 { | 644 { |
700 base::AutoLock for_this_block(localaccount_lock_); | 645 base::AutoLock for_this_block(localaccount_lock_); |
701 if (checked_for_localaccount_) | 646 if (checked_for_localaccount_) |
702 return; | 647 return; |
703 } | 648 } |
704 FilePath localaccount_file; | 649 FilePath localaccount_file; |
705 std::string localaccount; | 650 std::string localaccount; |
706 if (PathService::Get(base::DIR_EXE, &localaccount_file)) { | 651 if (PathService::Get(base::DIR_EXE, &localaccount_file)) { |
(...skipping 10 matching lines...) Expand all Loading... | |
717 } | 662 } |
718 | 663 |
719 void ParallelAuthenticator::SetLocalaccount(const std::string& new_name) { | 664 void ParallelAuthenticator::SetLocalaccount(const std::string& new_name) { |
720 localaccount_ = new_name; | 665 localaccount_ = new_name; |
721 { // extra braces for clarity about AutoLock scope. | 666 { // extra braces for clarity about AutoLock scope. |
722 base::AutoLock for_this_block(localaccount_lock_); | 667 base::AutoLock for_this_block(localaccount_lock_); |
723 checked_for_localaccount_ = true; | 668 checked_for_localaccount_ = true; |
724 } | 669 } |
725 } | 670 } |
726 | 671 |
727 std::string ParallelAuthenticator::EncryptToken(const std::string& token) { | |
728 if (!LoadSupplementalUserKey()) | |
729 return std::string(); | |
730 crypto::Encryptor encryptor; | |
731 if (!encryptor.Init(supplemental_user_key_.get(), crypto::Encryptor::CTR, | |
732 std::string())) | |
733 return std::string(); | |
734 | |
735 std::string nonce = SaltAsAscii().substr(0, kKeySize); | |
736 std::string encoded_token; | |
737 CHECK(encryptor.SetCounter(nonce)); | |
738 if (!encryptor.Encrypt(token, &encoded_token)) | |
739 return std::string(); | |
740 | |
741 return StringToLowerASCII(base::HexEncode( | |
742 reinterpret_cast<const void*>(encoded_token.data()), | |
743 encoded_token.size())); | |
744 } | |
745 std::string ParallelAuthenticator::DecryptToken( | |
746 const std::string& encrypted_token_hex) { | |
747 if (!LoadSupplementalUserKey()) | |
748 return std::string(); | |
749 return DecryptTokenWithKey(supplemental_user_key_.get(), | |
750 SaltAsAscii(), | |
751 encrypted_token_hex); | |
752 } | |
753 | |
754 std::string ParallelAuthenticator::HashPassword(const std::string& password) { | |
755 // Get salt, ascii encode, update sha with that, then update with ascii | |
756 // of password, then end. | |
757 std::string ascii_salt = SaltAsAscii(); | |
758 char passhash_buf[kPassHashLen]; | |
759 | |
760 // Hash salt and password | |
761 crypto::SHA256HashString(ascii_salt + password, | |
762 &passhash_buf, sizeof(passhash_buf)); | |
763 | |
764 return StringToLowerASCII(base::HexEncode( | |
765 reinterpret_cast<const void*>(passhash_buf), | |
766 sizeof(passhash_buf) / 2)); | |
767 } | |
768 | |
769 std::string ParallelAuthenticator::SaltAsAscii() { | |
770 LoadSystemSalt(); // no-op if it's already loaded. | |
771 return StringToLowerASCII(base::HexEncode( | |
772 reinterpret_cast<const void*>(system_salt_.data()), | |
773 system_salt_.size())); | |
774 } | |
775 | |
776 void ParallelAuthenticator::ResolveLoginCompletionStatus() { | 672 void ParallelAuthenticator::ResolveLoginCompletionStatus() { |
777 // Shortcut online state resolution process. | 673 // Shortcut online state resolution process. |
778 current_state_->RecordOnlineLoginStatus(GaiaAuthConsumer::ClientLoginResult(), | 674 current_state_->RecordOnlineLoginStatus(GaiaAuthConsumer::ClientLoginResult(), |
779 LoginFailure::None()); | 675 LoginFailure::None()); |
780 Resolve(); | 676 Resolve(); |
781 } | 677 } |
782 | 678 |
783 } // namespace chromeos | 679 } // namespace chromeos |
OLD | NEW |