Chromium Code Reviews| Index: chrome/browser/chromeos/login/parallel_authenticator.h |
| diff --git a/chrome/browser/chromeos/login/parallel_authenticator.h b/chrome/browser/chromeos/login/parallel_authenticator.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..18c31ed84f0c3ad7f96287cf4d355eac00185187 |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/login/parallel_authenticator.h |
| @@ -0,0 +1,272 @@ |
| +// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_PARALLEL_AUTHENTICATOR_H_ |
| +#define CHROME_BROWSER_CHROMEOS_LOGIN_PARALLEL_AUTHENTICATOR_H_ |
| +#pragma once |
| + |
| +#include <string> |
| +#include <vector> |
| + |
| +#include "base/basictypes.h" |
| +#include "base/gtest_prod_util.h" |
| +#include "base/scoped_ptr.h" |
| +#include "base/ref_counted.h" |
| +#include "chrome/browser/chromeos/cros/cros_library.h" |
| +#include "chrome/browser/chromeos/cros/cryptohome_library.h" |
| +#include "chrome/browser/chromeos/login/authenticator.h" |
| +#include "chrome/browser/chromeos/login/auth_attempt_state.h" |
| +#include "chrome/browser/chromeos/login/auth_attempt_state_resolver.h" |
| +#include "chrome/browser/chromeos/login/test_attempt_state.h" |
| +#include "chrome/browser/chromeos/login/cryptohome_op.h" |
| +#include "chrome/browser/chromeos/login/online_attempt.h" |
| +#include "chrome/common/net/gaia/gaia_auth_consumer.h" |
| + |
| +class GaiaAuthenticator2; |
| +class Lock; |
| +class LoginFailure; |
| +class Profile; |
| + |
| +namespace chromeos { |
| + |
| +class LoginStatusConsumer; |
| +class ParallelAuthenticatorTest; |
| + |
| +// Authenticates a Chromium OS user against the Google Accounts ClientLogin API. |
| +// |
| +// Simultaneously attempts authentication both offline and online, failing over |
| +// to the "localaccount" in the event that authentication fails. |
| +// |
| +// At a high, level, here's what happens: |
| +// AuthenticateToLogin() creates an OnlineAttempt and a CryptohomeOp that |
| +// attempt to perform online and offline login simultaneously. When one of |
| +// these completes, it will store results in a AuthAttemptState owned by |
| +// ParallelAuthenticator and then call Resolve(). Resolve() will attempt to |
| +// determine which AuthState we're in, based on the info at hand. |
| +// It then triggers further action based on the calculated AuthState; this |
| +// further action might include calling back the passed-in LoginStatusConsumer |
| +// to signal that login succeeded or failed, waiting for more outstanding |
| +// operations to complete, or triggering some more CryptohomeOps. |
| +class ParallelAuthenticator : public Authenticator, |
| + public AuthAttemptStateResolver { |
| + public: |
| + enum AuthState { |
| + CONTINUE, // State indeterminate; try again when more info available. |
| + NO_MOUNT, // Cryptohome doesn't exist yet. |
| + FAILED_MOUNT, // Failed to mount existing cryptohome. |
| + FAILED_REMOVE, // Failed to remove existing cryptohome. |
| + FAILED_TMPFS, // Failed to mount tmpfs for guest user |
| + CREATE_NEW, // Need to create cryptohome for a new user. |
| + RECOVER_MOUNT, // After RecoverEncryptedData, mount cryptohome. |
| + POSSIBLE_PW_CHANGE, // Offline login failed, user may have changed pw. |
| + NEED_NEW_PW, // User changed pw, and we have the old one. |
| + NEED_OLD_PW, // User changed pw, and we have the new one. |
| + HAVE_NEW_PW, // We have verified new pw, time to migrate key. |
| + OFFLINE_LOGIN, // Login succeeded offline. |
| + ONLINE_LOGIN, // Offline and online login succeeded. |
| + UNLOCK, // Screen unlock succeeded. |
| + LOCAL_LOGIN, // Login with localaccount succeded. |
| + ONLINE_FAILED, // Online login disallowed, but offline succeeded. |
| + LOGIN_FAILED // Login denied. |
| + }; |
| + |
| + explicit ParallelAuthenticator(LoginStatusConsumer* consumer); |
| + virtual ~ParallelAuthenticator(); |
| + |
| + // Given a |username| and |password|, this method attempts to authenticate to |
| + // the Google accounts servers and your Chrome OS device simultaneously. |
|
Nikita (slow)
2010/10/07 16:20:16
nit: Chromium?
Chris Masone
2010/10/07 16:32:30
Done.
|
| + // As soon as we have successfully mounted the encrypted home directory for |
| + // |username|, we will call consumer_->OnLoginSuccess() with |username| and a |
| + // vector of authentication cookies. If we're still waiting for an online |
| + // result at that time, we'll also pass back a flag indicating that more |
| + // callbacks are on the way; if not, we pass back false. When the pending |
| + // request completes, either consumer_->OnLoginSuccess() with an indication |
| + // that no more requests are outstanding will be called, or |
| + // consumer_->OnLoginFailure() if appropriate. |
| + // |
| + // Upon failure to login (online fails, then offline fails; |
| + // offline fails, then online fails) consumer_->OnLoginFailure() is called |
| + // with an error message. |
| + // |
| + // In the event that we see an online success and then an offline failure, |
| + // consumer_->OnPasswordChangeDetected() is called. |
|
Nikita (slow)
2010/10/07 16:20:16
So in case offline ok, online failure OnPasswordCh
Chris Masone
2010/10/07 16:32:30
Exactly. You'll get OnLoginSuccess(..., ..., true
|
| + // |
| + // Uses |profile| when doing URL fetches. |
| + // Optionally could pass CAPTCHA challenge token - |login_token| and |
| + // |login_captcha| string that user has entered. |
| + // |
| + // Returns true if the attempt gets sent successfully and false if not. |
| + bool AuthenticateToLogin(Profile* profile, |
| + const std::string& username, |
| + const std::string& password, |
| + const std::string& login_token, |
| + const std::string& login_captcha); |
| + |
| + // Given a |username| and |password|, this method attempts to |
| + // authenticate to the cached credentials. This will never contact |
| + // the server even if it's online. The auth result is sent to |
| + // LoginStatusConsumer in a same way as AuthenticateToLogin does. |
| + bool AuthenticateToUnlock(const std::string& username, |
| + const std::string& password); |
| + |
| + // Initiates off the record ("browse without signing in") login. |
| + // Mounts tmpfs and notifies consumer on the success/failure. |
| + void LoginOffTheRecord(); |
| + |
| + // These methods must be called on the UI thread, as they make DBus calls |
| + // and also call back to the login UI. |
| + void OnLoginSuccess(const GaiaAuthConsumer::ClientLoginResult& credentials, |
| + bool request_pending); |
| + void OnOffTheRecordLoginSuccess(); |
| + void OnPasswordChangeDetected( |
| + const GaiaAuthConsumer::ClientLoginResult& credentials); |
| + void OnLoginFailure(const LoginFailure& error); |
| + |
| + void RecoverEncryptedData( |
| + const std::string& old_password, |
| + const GaiaAuthConsumer::ClientLoginResult& credentials); |
| + void ResyncEncryptedData( |
| + const GaiaAuthConsumer::ClientLoginResult& credentials); |
| + void RetryAuth(Profile* profile, |
| + const std::string& username, |
| + const std::string& password, |
| + const std::string& login_token, |
| + const std::string& login_captcha); |
| + |
| + // Call this on the FILE thread. |
| + void CheckLocalaccount(const LoginFailure& error); |
| + |
| + // Attempts to make a decision and call back |consumer_| based on |
| + // the state we have gathered at the time of call. If a decision |
| + // can't be made, defers until the next time this is called. |
| + // When a decision is made, will call back to |consumer_| on the UI thread. |
| + // |
| + // Must be called on the IO thread. |
| + void Resolve(); |
| + |
| + private: |
| + // Returns the AuthState we're in, given the status info we have at |
| + // the time of call. |
| + // Must be called on the IO thread. |
| + AuthState ResolveState(); |
| + |
| + // Helper for ResolveState(). |
| + // Given that we're attempting to auth the user again, with a new password, |
| + // determine which state we're in. Returns CONTINUE if no resolution. |
| + // Must be called on the IO thread. |
| + AuthState ResolveReauthState(); |
| + |
| + // Helper for ResolveState(). |
| + // Given that some cryptohome operation has failed, determine which of the |
| + // possible failure states we're in. |
| + // Must be called on the IO thread. |
| + AuthState ResolveCryptohomeFailureState(); |
| + |
| + // Helper for ResolveState(). |
| + // Given that some cryptohome operation has succeeded, determine which of |
| + // the possible states we're in. |
| + // Must be called on the IO thread. |
| + AuthState ResolveCryptohomeSuccessState(); |
| + |
| + // Helper for ResolveState(). |
| + // Given that some online auth operation has failed, determine which of the |
| + // possible failure states we're in. Handles both failure to complete and |
| + // actual failure responses from the server. |
| + // Must be called on the IO thread. |
| + AuthState ResolveOnlineFailureState(AuthState offline_state); |
| + |
| + // Helper for ResolveState(). |
| + // Given that some online auth operation has succeeded, determine which of |
| + // the possible success states we're in. |
| + // Must be called on the IO thread. |
| + AuthState ResolveOnlineSuccessState(AuthState offline_state); |
| + |
| + // Used for testing. |
| + void set_attempt_state(TestAttemptState* new_state) { // takes ownership. |
| + current_state_.reset(new_state); |
| + } |
| + |
| + // Resets |current_state_| and then posts a task to the UI thread to |
| + // Initiate() |to_initiate|. |
| + // Call this method on the IO thread. |
| + void ResyncRecoverHelper(CryptohomeOp* to_initiate); |
| + |
| + // If we don't have the system salt yet, loads it from the CryptohomeLibrary. |
| + void LoadSystemSalt(); |
| + |
| + // If we haven't already, looks in a file called |filename| next to |
| + // the browser executable for a "localaccount" name, and retrieves it |
| + // if one is present. If someone attempts to authenticate with this |
| + // username, we will mount a tmpfs for them and let them use the |
| + // browser. |
| + // Should only be called on the FILE thread. |
| + void LoadLocalaccount(const std::string& filename); |
| + |
| + void SetLocalaccount(const std::string& new_name); |
| + |
| + // Stores a hash of |password|, salted with the ascii of |system_salt_|. |
| + std::string HashPassword(const std::string& password); |
| + |
| + // Returns the ascii encoding of the system salt. |
| + std::string SaltAsAscii(); |
| + |
| + // Converts the binary data |binary| into an ascii hex string and stores |
| + // it in |hex_string|. Not guaranteed to be NULL-terminated. |
| + // Returns false if |hex_string| is too small, true otherwise. |
| + static bool BinaryToHex(const std::vector<unsigned char>& binary, |
| + const unsigned int binary_len, |
| + char* hex_string, |
| + const unsigned int len); |
| + |
| + // Name of a file, next to chrome, that contains a local account username. |
| + static const char kLocalaccountFile[]; |
| + |
| + // Milliseconds until we timeout our attempt to hit ClientLogin. |
| + static const int kClientLoginTimeoutMs; |
| + |
| + // Milliseconds until we re-check whether we've gotten the localaccount name. |
| + static const int kLocalaccountRetryIntervalMs; |
| + |
| + // Handles all net communications with Gaia. |
| + scoped_ptr<GaiaAuthenticator2> gaia_authenticator_; |
| + |
| + // Used when we need to try online authentication again, after successful |
| + // mount, but failed online login. |
| + scoped_ptr<AuthAttemptState> reauth_state_; |
| + |
| + scoped_ptr<AuthAttemptState> current_state_; |
| + scoped_refptr<OnlineAttempt> current_online_; |
| + scoped_refptr<CryptohomeOp> mounter_; |
| + scoped_refptr<CryptohomeOp> key_migrator_; |
| + scoped_refptr<CryptohomeOp> data_remover_; |
| + scoped_refptr<CryptohomeOp> guest_mounter_; |
| + scoped_refptr<CryptohomeOp> key_checker_; |
| + |
| + std::string ascii_hash_; |
| + chromeos::CryptohomeBlob system_salt_; |
| + |
| + // When the user has changed her password, but gives us the old one, we will |
| + // be able to mount her cryptohome, but online authentication will fail. |
| + // This allows us to present the same behavior to the caller, regardless |
| + // of the order in which we receive these results. |
| + bool already_reported_success_; |
| + Lock success_lock_; // a lock around already_reported_success_. |
| + |
| + // Status relating to the local "backdoor" account. |
| + std::string localaccount_; |
| + bool checked_for_localaccount_; // needed because empty localaccount_ is ok. |
| + Lock localaccount_lock_; // a lock around checked_for_localaccount_. |
| + |
| + friend class ParallelAuthenticatorTest; |
| + FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest, SaltToAscii); |
| + FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest, ReadLocalaccount); |
| + FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest, |
| + ReadLocalaccountTrailingWS); |
| + FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest, ReadNoLocalaccount); |
| + DISALLOW_COPY_AND_ASSIGN(ParallelAuthenticator); |
| +}; |
| + |
| +} // namespace chromeos |
| + |
| +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_PARALLEL_AUTHENTICATOR_H_ |