Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(449)

Side by Side Diff: chrome/browser/chromeos/login/parallel_authenticator.cc

Issue 8761016: Shaving parallel authenticator yak to remove unnecessary dependency on this class from OAuth spec... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/file_path.h" 12 #include "base/file_path.h"
13 #include "base/file_util.h" 13 #include "base/file_util.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/path_service.h" 15 #include "base/path_service.h"
16 #include "base/rand_util.h"
17 #include "base/string_number_conversions.h"
18 #include "base/string_util.h" 16 #include "base/string_util.h"
19 #include "base/synchronization/lock.h" 17 #include "base/synchronization/lock.h"
20 #include "chrome/browser/chromeos/cros/cert_library.h" 18 #include "chrome/browser/chromeos/cros/cert_library.h"
21 #include "chrome/browser/chromeos/cros/cryptohome_library.h" 19 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
22 #include "chrome/browser/chromeos/login/auth_response_handler.h" 20 #include "chrome/browser/chromeos/login/auth_response_handler.h"
23 #include "chrome/browser/chromeos/login/authentication_notification_details.h" 21 #include "chrome/browser/chromeos/login/authentication_notification_details.h"
24 #include "chrome/browser/chromeos/login/login_status_consumer.h" 22 #include "chrome/browser/chromeos/login/login_status_consumer.h"
25 #include "chrome/browser/chromeos/login/ownership_service.h" 23 #include "chrome/browser/chromeos/login/ownership_service.h"
26 #include "chrome/browser/chromeos/login/user_manager.h" 24 #include "chrome/browser/chromeos/login/user_manager.h"
27 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/profiles/profile_manager.h" 26 #include "chrome/browser/profiles/profile_manager.h"
29 #include "chrome/common/chrome_notification_types.h" 27 #include "chrome/common/chrome_notification_types.h"
30 #include "chrome/common/chrome_paths.h" 28 #include "chrome/common/chrome_paths.h"
31 #include "chrome/common/chrome_switches.h" 29 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/net/gaia/gaia_auth_fetcher.h" 30 #include "chrome/common/net/gaia/gaia_auth_fetcher.h"
33 #include "chrome/common/net/gaia/gaia_constants.h" 31 #include "chrome/common/net/gaia/gaia_constants.h"
34 #include "content/public/browser/browser_thread.h" 32 #include "content/public/browser/browser_thread.h"
35 #include "content/public/browser/notification_service.h" 33 #include "content/public/browser/notification_service.h"
36 #include "crypto/encryptor.h"
37 #include "crypto/sha2.h"
38 #include "crypto/symmetric_key.h"
39 #include "net/base/load_flags.h" 34 #include "net/base/load_flags.h"
40 #include "net/base/net_errors.h" 35 #include "net/base/net_errors.h"
41 #include "net/url_request/url_request_status.h" 36 #include "net/url_request/url_request_status.h"
42 #include "third_party/libjingle/source/talk/base/urlencode.h" 37 #include "third_party/libjingle/source/talk/base/urlencode.h"
43 38
44 using base::Time; 39 using base::Time;
45 using base::TimeDelta; 40 using base::TimeDelta;
46 using content::BrowserThread; 41 using content::BrowserThread;
47 using file_util::GetFileSize; 42 using file_util::GetFileSize;
48 using file_util::PathExists; 43 using file_util::PathExists;
49 using file_util::ReadFile; 44 using file_util::ReadFile;
50 using file_util::ReadFileToString; 45 using file_util::ReadFileToString;
51 46
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 { 47 namespace chromeos {
84 48
85 // static 49 // static
86 const char ParallelAuthenticator::kLocalaccountFile[] = "localaccount"; 50 const char ParallelAuthenticator::kLocalaccountFile[] = "localaccount";
87 51
88 // static 52 // static
89 const int ParallelAuthenticator::kClientLoginTimeoutMs = 10000; 53 const int ParallelAuthenticator::kClientLoginTimeoutMs = 10000;
90 // static 54 // static
91 const int ParallelAuthenticator::kLocalaccountRetryIntervalMs = 20; 55 const int ParallelAuthenticator::kLocalaccountRetryIntervalMs = 20;
92 56
(...skipping 15 matching lines...) Expand all
108 72
109 void ParallelAuthenticator::AuthenticateToLogin( 73 void ParallelAuthenticator::AuthenticateToLogin(
110 Profile* profile, 74 Profile* profile,
111 const std::string& username, 75 const std::string& username,
112 const std::string& password, 76 const std::string& password,
113 const std::string& login_token, 77 const std::string& login_token,
114 const std::string& login_captcha) { 78 const std::string& login_captcha) {
115 std::string canonicalized = Authenticator::Canonicalize(username); 79 std::string canonicalized = Authenticator::Canonicalize(username);
116 authentication_profile_ = profile; 80 authentication_profile_ = profile;
117 current_state_.reset( 81 current_state_.reset(
118 new AuthAttemptState(canonicalized, 82 new AuthAttemptState(
119 password, 83 canonicalized,
120 HashPassword(password), 84 password,
121 login_token, 85 CrosLibrary::Get()->GetCryptohomeLibrary()->HashPassword(password),
122 login_captcha, 86 login_token,
123 !UserManager::Get()->IsKnownUser(canonicalized))); 87 login_captcha,
88 !UserManager::Get()->IsKnownUser(canonicalized)));
124 mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), 89 mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(),
125 this, 90 this,
126 false /* don't create */); 91 false /* don't create */);
127 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ 92 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/
128 BrowserThread::PostTask( 93 BrowserThread::PostTask(
129 BrowserThread::UI, FROM_HERE, 94 BrowserThread::UI, FROM_HERE,
130 95
131 base::Bind(&CryptohomeOp::Initiate, mounter_.get())); 96 base::Bind(&CryptohomeOp::Initiate, mounter_.get()));
132 // ClientLogin authentication check should happen immediately here. 97 // ClientLogin authentication check should happen immediately here.
133 // We should not try OAuthLogin check until the profile loads. 98 // We should not try OAuthLogin check until the profile loads.
(...skipping 10 matching lines...) Expand all
144 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this, 109 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this,
145 std::string(kLocalaccountFile))); 110 std::string(kLocalaccountFile)));
146 } 111 }
147 112
148 void ParallelAuthenticator::CompleteLogin(Profile* profile, 113 void ParallelAuthenticator::CompleteLogin(Profile* profile,
149 const std::string& username, 114 const std::string& username,
150 const std::string& password) { 115 const std::string& password) {
151 std::string canonicalized = Authenticator::Canonicalize(username); 116 std::string canonicalized = Authenticator::Canonicalize(username);
152 authentication_profile_ = profile; 117 authentication_profile_ = profile;
153 current_state_.reset( 118 current_state_.reset(
154 new AuthAttemptState(canonicalized, 119 new AuthAttemptState(
155 password, 120 canonicalized,
156 HashPassword(password), 121 password,
157 !UserManager::Get()->IsKnownUser(canonicalized))); 122 CrosLibrary::Get()->GetCryptohomeLibrary()->HashPassword(password),
123 !UserManager::Get()->IsKnownUser(canonicalized)));
158 mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(), 124 mounter_ = CryptohomeOp::CreateMountAttempt(current_state_.get(),
159 this, 125 this,
160 false /* don't create */); 126 false /* don't create */);
161 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ 127 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/
162 BrowserThread::PostTask( 128 BrowserThread::PostTask(
163 BrowserThread::UI, FROM_HERE, 129 BrowserThread::UI, FROM_HERE,
164 base::Bind(&CryptohomeOp::Initiate, mounter_.get())); 130 base::Bind(&CryptohomeOp::Initiate, mounter_.get()));
165 131
166 if (!using_oauth_) { 132 if (!using_oauth_) {
167 // Test automation needs to disable oauth, but that leads to other 133 // Test automation needs to disable oauth, but that leads to other
(...skipping 15 matching lines...) Expand all
183 149
184 BrowserThread::PostTask( 150 BrowserThread::PostTask(
185 BrowserThread::FILE, FROM_HERE, 151 BrowserThread::FILE, FROM_HERE,
186 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this, 152 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this,
187 std::string(kLocalaccountFile))); 153 std::string(kLocalaccountFile)));
188 } 154 }
189 155
190 void ParallelAuthenticator::AuthenticateToUnlock(const std::string& username, 156 void ParallelAuthenticator::AuthenticateToUnlock(const std::string& username,
191 const std::string& password) { 157 const std::string& password) {
192 current_state_.reset( 158 current_state_.reset(
193 new AuthAttemptState(Authenticator::Canonicalize(username), 159 new AuthAttemptState(
194 HashPassword(password))); 160 Authenticator::Canonicalize(username),
161 CrosLibrary::Get()->GetCryptohomeLibrary()->HashPassword(password)));
195 BrowserThread::PostTask( 162 BrowserThread::PostTask(
196 BrowserThread::FILE, FROM_HERE, 163 BrowserThread::FILE, FROM_HERE,
197 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this, 164 base::Bind(&ParallelAuthenticator::LoadLocalaccount, this,
198 std::string(kLocalaccountFile))); 165 std::string(kLocalaccountFile)));
199 key_checker_ = CryptohomeOp::CreateCheckKeyAttempt(current_state_.get(), 166 key_checker_ = CryptohomeOp::CreateCheckKeyAttempt(current_state_.get(),
200 this); 167 this);
201 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/ 168 // Sadly, this MUST be on the UI thread due to sending DBus traffic :-/
202 BrowserThread::PostTask( 169 BrowserThread::PostTask(
203 BrowserThread::UI, FROM_HERE, 170 BrowserThread::UI, FROM_HERE,
204 base::Bind(&CryptohomeOp::Initiate, key_checker_.get())); 171 base::Bind(&CryptohomeOp::Initiate, key_checker_.get()));
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
304 DCHECK(using_oauth_); 271 DCHECK(using_oauth_);
305 // Mark this account's OAuth token state as invalid in the local state. 272 // Mark this account's OAuth token state as invalid in the local state.
306 UserManager::Get()->SaveUserOAuthStatus(user_name, 273 UserManager::Get()->SaveUserOAuthStatus(user_name,
307 User::OAUTH_TOKEN_STATUS_INVALID); 274 User::OAUTH_TOKEN_STATUS_INVALID);
308 } 275 }
309 276
310 void ParallelAuthenticator::RecoverEncryptedData( 277 void ParallelAuthenticator::RecoverEncryptedData(
311 const std::string& old_password, 278 const std::string& old_password,
312 const GaiaAuthConsumer::ClientLoginResult& credentials) { 279 const GaiaAuthConsumer::ClientLoginResult& credentials) {
313 std::string old_hash = HashPassword(old_password); 280 std::string old_hash =
281 CrosLibrary::Get()->GetCryptohomeLibrary()->HashPassword(old_password);
314 key_migrator_ = CryptohomeOp::CreateMigrateAttempt(current_state_.get(), 282 key_migrator_ = CryptohomeOp::CreateMigrateAttempt(current_state_.get(),
315 this, 283 this,
316 true, 284 true,
317 old_hash); 285 old_hash);
318 BrowserThread::PostTask( 286 BrowserThread::PostTask(
319 BrowserThread::IO, FROM_HERE, 287 BrowserThread::IO, FROM_HERE,
320 base::Bind(&ParallelAuthenticator::ResyncRecoverHelper, this, 288 base::Bind(&ParallelAuthenticator::ResyncRecoverHelper, this,
321 key_migrator_)); 289 key_migrator_));
322 } 290 }
323 291
(...skipping 14 matching lines...) Expand all
338 BrowserThread::UI, FROM_HERE, 306 BrowserThread::UI, FROM_HERE,
339 base::Bind(&CryptohomeOp::Initiate, to_initiate)); 307 base::Bind(&CryptohomeOp::Initiate, to_initiate));
340 } 308 }
341 309
342 void ParallelAuthenticator::RetryAuth(Profile* profile, 310 void ParallelAuthenticator::RetryAuth(Profile* profile,
343 const std::string& username, 311 const std::string& username,
344 const std::string& password, 312 const std::string& password,
345 const std::string& login_token, 313 const std::string& login_token,
346 const std::string& login_captcha) { 314 const std::string& login_captcha) {
347 reauth_state_.reset( 315 reauth_state_.reset(
348 new AuthAttemptState(Authenticator::Canonicalize(username), 316 new AuthAttemptState(
349 password, 317 Authenticator::Canonicalize(username),
350 HashPassword(password), 318 password,
351 login_token, 319 CrosLibrary::Get()->GetCryptohomeLibrary()->HashPassword(password),
352 login_captcha, 320 login_token,
353 false /* not a new user */)); 321 login_captcha,
322 false /* not a new user */));
354 // Always use ClientLogin regardless of using_oauth flag. This is because 323 // 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 324 // we are unable to renew oauth token on lock screen currently and will
356 // stuck with lock screen if we use OAuthLogin here. 325 // stuck with lock screen if we use OAuthLogin here.
357 // TODO(xiyuan): Revisit this after we support Gaia in lock screen. 326 // TODO(xiyuan): Revisit this after we support Gaia in lock screen.
358 current_online_ = new OnlineAttempt(false /* using_oauth */, 327 current_online_ = new OnlineAttempt(false /* using_oauth */,
359 reauth_state_.get(), 328 reauth_state_.get(),
360 this); 329 this);
361 current_online_->Initiate(profile); 330 current_online_->Initiate(profile);
362 } 331 }
363 332
364 333
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() { 334 void ParallelAuthenticator::Resolve() {
378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
379 bool request_pending = false; 336 bool request_pending = false;
380 bool create = false; 337 bool create = false;
381 ParallelAuthenticator::AuthState state = ResolveState(); 338 ParallelAuthenticator::AuthState state = ResolveState();
382 VLOG(1) << "Resolved state to: " << state; 339 VLOG(1) << "Resolved state to: " << state;
383 switch (state) { 340 switch (state) {
384 case CONTINUE: 341 case CONTINUE:
385 case POSSIBLE_PW_CHANGE: 342 case POSSIBLE_PW_CHANGE:
386 case NO_MOUNT: 343 case NO_MOUNT:
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 case NO_MOUNT: 627 case NO_MOUNT:
671 return CREATE_NEW; 628 return CREATE_NEW;
672 case OFFLINE_LOGIN: 629 case OFFLINE_LOGIN:
673 return ONLINE_LOGIN; 630 return ONLINE_LOGIN;
674 default: 631 default:
675 NOTREACHED(); 632 NOTREACHED();
676 return offline_state; 633 return offline_state;
677 } 634 }
678 } 635 }
679 636
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) { 637 void ParallelAuthenticator::LoadLocalaccount(const std::string& filename) {
698 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 638 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
699 { 639 {
700 base::AutoLock for_this_block(localaccount_lock_); 640 base::AutoLock for_this_block(localaccount_lock_);
701 if (checked_for_localaccount_) 641 if (checked_for_localaccount_)
702 return; 642 return;
703 } 643 }
704 FilePath localaccount_file; 644 FilePath localaccount_file;
705 std::string localaccount; 645 std::string localaccount;
706 if (PathService::Get(base::DIR_EXE, &localaccount_file)) { 646 if (PathService::Get(base::DIR_EXE, &localaccount_file)) {
(...skipping 10 matching lines...) Expand all
717 } 657 }
718 658
719 void ParallelAuthenticator::SetLocalaccount(const std::string& new_name) { 659 void ParallelAuthenticator::SetLocalaccount(const std::string& new_name) {
720 localaccount_ = new_name; 660 localaccount_ = new_name;
721 { // extra braces for clarity about AutoLock scope. 661 { // extra braces for clarity about AutoLock scope.
722 base::AutoLock for_this_block(localaccount_lock_); 662 base::AutoLock for_this_block(localaccount_lock_);
723 checked_for_localaccount_ = true; 663 checked_for_localaccount_ = true;
724 } 664 }
725 } 665 }
726 666
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() { 667 void ParallelAuthenticator::ResolveLoginCompletionStatus() {
777 // Shortcut online state resolution process. 668 // Shortcut online state resolution process.
778 current_state_->RecordOnlineLoginStatus(GaiaAuthConsumer::ClientLoginResult(), 669 current_state_->RecordOnlineLoginStatus(GaiaAuthConsumer::ClientLoginResult(),
779 LoginFailure::None()); 670 LoginFailure::None());
780 Resolve(); 671 Resolve();
781 } 672 }
782 673
783 } // namespace chromeos 674 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698