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/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/file_path.h" | 11 #include "base/file_path.h" |
12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/path_service.h" | 14 #include "base/path_service.h" |
| 15 #include "base/rand_util.h" |
| 16 #include "base/string_number_conversions.h" |
15 #include "base/string_util.h" | 17 #include "base/string_util.h" |
16 #include "base/synchronization/lock.h" | 18 #include "base/synchronization/lock.h" |
17 #include "crypto/sha2.h" | |
18 #include "chrome/browser/chromeos/cros/cryptohome_library.h" | 19 #include "chrome/browser/chromeos/cros/cryptohome_library.h" |
19 #include "chrome/browser/chromeos/login/auth_response_handler.h" | 20 #include "chrome/browser/chromeos/login/auth_response_handler.h" |
20 #include "chrome/browser/chromeos/login/authentication_notification_details.h" | 21 #include "chrome/browser/chromeos/login/authentication_notification_details.h" |
21 #include "chrome/browser/chromeos/login/login_status_consumer.h" | 22 #include "chrome/browser/chromeos/login/login_status_consumer.h" |
22 #include "chrome/browser/chromeos/login/ownership_service.h" | 23 #include "chrome/browser/chromeos/login/ownership_service.h" |
23 #include "chrome/browser/chromeos/login/user_manager.h" | 24 #include "chrome/browser/chromeos/login/user_manager.h" |
24 #include "chrome/browser/profiles/profile.h" | 25 #include "chrome/browser/profiles/profile.h" |
25 #include "chrome/browser/profiles/profile_manager.h" | 26 #include "chrome/browser/profiles/profile_manager.h" |
26 #include "chrome/common/chrome_notification_types.h" | 27 #include "chrome/common/chrome_notification_types.h" |
27 #include "chrome/common/chrome_paths.h" | 28 #include "chrome/common/chrome_paths.h" |
28 #include "chrome/common/chrome_switches.h" | 29 #include "chrome/common/chrome_switches.h" |
29 #include "chrome/common/net/gaia/gaia_auth_fetcher.h" | 30 #include "chrome/common/net/gaia/gaia_auth_fetcher.h" |
30 #include "chrome/common/net/gaia/gaia_constants.h" | 31 #include "chrome/common/net/gaia/gaia_constants.h" |
31 #include "content/browser/browser_thread.h" | 32 #include "content/browser/browser_thread.h" |
32 #include "content/common/notification_service.h" | 33 #include "content/common/notification_service.h" |
| 34 #include "crypto/encryptor.h" |
| 35 #include "crypto/sha2.h" |
| 36 #include "crypto/symmetric_key.h" |
33 #include "net/base/load_flags.h" | 37 #include "net/base/load_flags.h" |
34 #include "net/base/net_errors.h" | 38 #include "net/base/net_errors.h" |
35 #include "net/url_request/url_request_status.h" | 39 #include "net/url_request/url_request_status.h" |
36 #include "third_party/libjingle/source/talk/base/urlencode.h" | 40 #include "third_party/libjingle/source/talk/base/urlencode.h" |
37 | 41 |
38 using base::Time; | 42 using base::Time; |
39 using base::TimeDelta; | 43 using base::TimeDelta; |
40 using file_util::GetFileSize; | 44 using file_util::GetFileSize; |
41 using file_util::PathExists; | 45 using file_util::PathExists; |
42 using file_util::ReadFile; | 46 using file_util::ReadFile; |
43 using file_util::ReadFileToString; | 47 using file_util::ReadFileToString; |
44 | 48 |
45 namespace chromeos { | 49 namespace chromeos { |
46 | 50 |
47 // static | 51 // static |
48 const char ParallelAuthenticator::kLocalaccountFile[] = "localaccount"; | 52 const char ParallelAuthenticator::kLocalaccountFile[] = "localaccount"; |
49 | 53 |
50 // static | 54 // static |
51 const int ParallelAuthenticator::kClientLoginTimeoutMs = 10000; | 55 const int ParallelAuthenticator::kClientLoginTimeoutMs = 10000; |
52 // static | 56 // static |
53 const int ParallelAuthenticator::kLocalaccountRetryIntervalMs = 20; | 57 const int ParallelAuthenticator::kLocalaccountRetryIntervalMs = 20; |
54 | 58 |
55 const int kPassHashLen = 32; | 59 const int kPassHashLen = 32; |
| 60 const size_t kKeySize = 16; |
56 | 61 |
57 ParallelAuthenticator::ParallelAuthenticator(LoginStatusConsumer* consumer) | 62 ParallelAuthenticator::ParallelAuthenticator(LoginStatusConsumer* consumer) |
58 : Authenticator(consumer), | 63 : Authenticator(consumer), |
59 already_reported_success_(false), | 64 already_reported_success_(false), |
60 checked_for_localaccount_(false), | 65 checked_for_localaccount_(false), |
61 using_oauth_( | 66 using_oauth_( |
62 CommandLine::ForCurrentProcess()->HasSwitch( | 67 CommandLine::ForCurrentProcess()->HasSwitch( |
63 switches::kWebUILogin) && | 68 switches::kWebUILogin) && |
64 !CommandLine::ForCurrentProcess()->HasSwitch( | 69 !CommandLine::ForCurrentProcess()->HasSwitch( |
65 switches::kSkipOAuthLogin)) { | 70 switches::kSkipOAuthLogin)) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 HashPassword(password), | 128 HashPassword(password), |
124 !UserManager::Get()->IsKnownUser(canonicalized))); | 129 !UserManager::Get()->IsKnownUser(canonicalized))); |
125 mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), | 130 mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), |
126 this, | 131 this, |
127 false /* don't create */); | 132 false /* don't create */); |
128 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ | 133 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ |
129 BrowserThread::PostTask( | 134 BrowserThread::PostTask( |
130 BrowserThread::UI, FROM_HERE, | 135 BrowserThread::UI, FROM_HERE, |
131 NewRunnableMethod(mounter_.get(), &CryptohomeOp::Initiate)); | 136 NewRunnableMethod(mounter_.get(), &CryptohomeOp::Initiate)); |
132 | 137 |
133 // For login completion, we just need to resolve the current auth, | 138 // For login completion of a new user, we just need to resolve the current |
134 // attempt state. | 139 // auth attempt state, the rest of OAuth related tasks will be done in |
135 // TODO(zelidrag): Investigate if this business be moved to UI thread instead. | 140 // parallel. |
136 BrowserThread::PostTask( | 141 if (!UserManager::Get()->IsKnownUser(canonicalized)) { |
137 BrowserThread::IO, FROM_HERE, | 142 BrowserThread::PostTask( |
138 NewRunnableMethod(this, | 143 BrowserThread::IO, FROM_HERE, |
139 &ParallelAuthenticator::ResolveLoginCompletionStatus)); | 144 NewRunnableMethod(this, |
| 145 &ParallelAuthenticator::ResolveLoginCompletionStatus)); |
| 146 } |
140 | 147 |
141 BrowserThread::PostTask( | 148 BrowserThread::PostTask( |
142 BrowserThread::FILE, FROM_HERE, | 149 BrowserThread::FILE, FROM_HERE, |
143 NewRunnableMethod(this, | 150 NewRunnableMethod(this, |
144 &ParallelAuthenticator::LoadLocalaccount, | 151 &ParallelAuthenticator::LoadLocalaccount, |
145 std::string(kLocalaccountFile))); | 152 std::string(kLocalaccountFile))); |
146 return true; | 153 return true; |
147 } | 154 } |
148 | 155 |
149 bool ParallelAuthenticator::AuthenticateToUnlock(const std::string& username, | 156 bool ParallelAuthenticator::AuthenticateToUnlock(const std::string& username, |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 } | 675 } |
669 | 676 |
670 void ParallelAuthenticator::SetLocalaccount(const std::string& new_name) { | 677 void ParallelAuthenticator::SetLocalaccount(const std::string& new_name) { |
671 localaccount_ = new_name; | 678 localaccount_ = new_name; |
672 { // extra braces for clarity about AutoLock scope. | 679 { // extra braces for clarity about AutoLock scope. |
673 base::AutoLock for_this_block(localaccount_lock_); | 680 base::AutoLock for_this_block(localaccount_lock_); |
674 checked_for_localaccount_ = true; | 681 checked_for_localaccount_ = true; |
675 } | 682 } |
676 } | 683 } |
677 | 684 |
| 685 std::string ParallelAuthenticator::EncryptToken(const std::string& token) { |
| 686 // TODO(zelidrag): Replace salt with |
| 687 scoped_ptr<crypto::SymmetricKey> key( |
| 688 crypto::SymmetricKey::DeriveKeyFromPassword( |
| 689 crypto::SymmetricKey::AES, UserSupplementalKeyAsAscii(), |
| 690 SaltAsAscii(), 1000, 256)); |
| 691 crypto::Encryptor encryptor; |
| 692 if (!encryptor.Init(key.get(), crypto::Encryptor::CTR, std::string())) |
| 693 return std::string(); |
| 694 |
| 695 std::string nonce = SaltAsAscii().substr(0, kKeySize); |
| 696 std::string encoded_token; |
| 697 CHECK(encryptor.SetCounter(nonce)); |
| 698 if (!encryptor.Encrypt(token, &encoded_token)) |
| 699 return std::string(); |
| 700 |
| 701 return StringToLowerASCII(base::HexEncode( |
| 702 reinterpret_cast<const void*>(encoded_token.data()), |
| 703 encoded_token.size())); |
| 704 } |
| 705 |
| 706 std::string ParallelAuthenticator::DecryptToken( |
| 707 const std::string& encrypted_token_hex) { |
| 708 std::vector<uint8> encrypted_token_bytes; |
| 709 if (!base::HexStringToBytes(encrypted_token_hex, &encrypted_token_bytes)) |
| 710 return std::string(); |
| 711 |
| 712 std::string encrypted_token( |
| 713 reinterpret_cast<char*>(encrypted_token_bytes.data()), |
| 714 encrypted_token_bytes.size()); |
| 715 scoped_ptr<crypto::SymmetricKey> key( |
| 716 crypto::SymmetricKey::DeriveKeyFromPassword( |
| 717 crypto::SymmetricKey::AES, UserSupplementalKeyAsAscii(), |
| 718 SaltAsAscii(), 1000, 256)); |
| 719 crypto::Encryptor encryptor; |
| 720 if (!encryptor.Init(key.get(), crypto::Encryptor::CTR, std::string())) |
| 721 return std::string(); |
| 722 |
| 723 std::string nonce = SaltAsAscii().substr(0, kKeySize); |
| 724 std::string token; |
| 725 CHECK(encryptor.SetCounter(nonce)); |
| 726 if (!encryptor.Decrypt(encrypted_token, &token)) |
| 727 return std::string(); |
| 728 return token; |
| 729 } |
| 730 |
678 | 731 |
679 std::string ParallelAuthenticator::HashPassword(const std::string& password) { | 732 std::string ParallelAuthenticator::HashPassword(const std::string& password) { |
680 // Get salt, ascii encode, update sha with that, then update with ascii | 733 // Get salt, ascii encode, update sha with that, then update with ascii |
681 // of password, then end. | 734 // of password, then end. |
682 std::string ascii_salt = SaltAsAscii(); | 735 std::string ascii_salt = SaltAsAscii(); |
683 unsigned char passhash_buf[kPassHashLen]; | 736 char passhash_buf[kPassHashLen]; |
684 char ascii_buf[kPassHashLen + 1]; | |
685 | 737 |
686 // Hash salt and password | 738 // Hash salt and password |
687 crypto::SHA256HashString(ascii_salt + password, | 739 crypto::SHA256HashString(ascii_salt + password, |
688 &passhash_buf, sizeof(passhash_buf)); | 740 &passhash_buf, sizeof(passhash_buf)); |
689 | 741 |
690 std::vector<unsigned char> passhash(passhash_buf, | 742 return StringToLowerASCII(base::HexEncode( |
691 passhash_buf + sizeof(passhash_buf)); | 743 reinterpret_cast<const void*>(passhash_buf), |
692 BinaryToHex(passhash, | 744 sizeof(passhash_buf) / 2)); |
693 passhash.size() / 2, // only want top half, at least for now. | |
694 ascii_buf, | |
695 sizeof(ascii_buf)); | |
696 return std::string(ascii_buf, sizeof(ascii_buf) - 1); | |
697 } | 745 } |
698 | 746 |
699 std::string ParallelAuthenticator::SaltAsAscii() { | 747 std::string ParallelAuthenticator::SaltAsAscii() { |
700 LoadSystemSalt(); // no-op if it's already loaded. | 748 LoadSystemSalt(); // no-op if it's already loaded. |
701 unsigned int salt_len = system_salt_.size(); | 749 return StringToLowerASCII(base::HexEncode( |
702 char ascii_salt[2 * salt_len + 1]; | 750 reinterpret_cast<const void*>(system_salt_.data()), |
703 if (ParallelAuthenticator::BinaryToHex(system_salt_, | 751 system_salt_.size())); |
704 salt_len, | |
705 ascii_salt, | |
706 sizeof(ascii_salt))) { | |
707 return std::string(ascii_salt, sizeof(ascii_salt) - 1); | |
708 } | |
709 return std::string(); | |
710 } | 752 } |
711 | 753 |
712 // static | 754 std::string ParallelAuthenticator::UserSupplementalKeyAsAscii() { |
713 bool ParallelAuthenticator::BinaryToHex( | 755 // TODO(zelidrag, wad): http://crosbug.com/18633 - Replace this with the real |
714 const std::vector<unsigned char>& binary, | 756 // user suplemental key gets exposed in from cryptolib. |
715 const unsigned int binary_len, | 757 return SaltAsAscii(); |
716 char* hex_string, | |
717 const unsigned int len) { | |
718 if (len < 2*binary_len) | |
719 return false; | |
720 memset(hex_string, 0, len); | |
721 for (uint i = 0, j = 0; i < binary_len; i++, j+=2) | |
722 snprintf(hex_string + j, len - j, "%02x", binary[i]); | |
723 return true; | |
724 } | 758 } |
725 | 759 |
726 void ParallelAuthenticator::ResolveLoginCompletionStatus() { | 760 void ParallelAuthenticator::ResolveLoginCompletionStatus() { |
727 // Shortcut online state resolution process. | 761 // Shortcut online state resolution process. |
728 current_state_->RecordOnlineLoginStatus(GaiaAuthConsumer::ClientLoginResult(), | 762 current_state_->RecordOnlineLoginStatus(GaiaAuthConsumer::ClientLoginResult(), |
729 LoginFailure::None()); | 763 LoginFailure::None()); |
730 Resolve(); | 764 Resolve(); |
731 } | 765 } |
732 | 766 |
733 } // namespace chromeos | 767 } // namespace chromeos |
OLD | NEW |