| 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 |