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

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"
(...skipping 15 matching lines...) Expand all
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698