Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_PARALLEL_AUTHENTICATOR_H_
      6 #define CHROME_BROWSER_CHROMEOS_LOGIN_PARALLEL_AUTHENTICATOR_H_
      7 
      8 #include <string>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/compiler_specific.h"
     12 #include "base/gtest_prod_util.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/synchronization/lock.h"
     15 #include "chrome/browser/chromeos/login/auth_attempt_state.h"
     16 #include "chrome/browser/chromeos/login/auth_attempt_state_resolver.h"
     17 #include "chrome/browser/chromeos/login/authenticator.h"
     18 #include "chrome/browser/chromeos/login/online_attempt.h"
     19 #include "chrome/browser/chromeos/login/test_attempt_state.h"
     20 #include "chrome/browser/chromeos/settings/device_settings_service.h"
     21 #include "google_apis/gaia/gaia_auth_consumer.h"
     22 
     23 class LoginFailure;
     24 class Profile;
     25 
     26 namespace chromeos {
     27 
     28 class LoginStatusConsumer;
     29 
     30 // Authenticates a Chromium OS user against cryptohome.
     31 // Relies on the fact that online authentications has been already performed
     32 // (i.e. using_oauth_ is true).
     33 //
     34 // At a high, level, here's what happens:
     35 // AuthenticateToLogin() calls a Cryptohome's method to perform offline login.
     36 // Resultes are stored in a AuthAttemptState owned by ParallelAuthenticator
     37 // and then call Resolve().  Resolve() will attempt to
     38 // determine which AuthState we're in, based on the info at hand.
     39 // It then triggers further action based on the calculated AuthState; this
     40 // further action might include calling back the passed-in LoginStatusConsumer
     41 // to signal that login succeeded or failed, waiting for more outstanding
     42 // operations to complete, or triggering some more Cryptohome method calls.
     43 //
     44 // Typical flows
     45 // -------------
     46 // Add new user: CONTINUE > CONTINUE > CREATE_NEW > CONTINUE > ONLINE_LOGIN
     47 // Login as existing user: CONTINUE > OFFLINE_LOGIN
     48 // Login as existing user (failure): CONTINUE > FAILED_MOUNT
     49 // Change password detected:
     50 //   GAIA online ok: CONTINUE > CONTINUE > NEED_OLD_PW
     51 //     Recreate: CREATE_NEW > CONTINUE > ONLINE_LOGIN
     52 //     Old password failure: NEED_OLD_PW
     53 //     Old password ok: RECOVER_MOUNT > CONTINUE > ONLINE_LOGIN
     54 //
     55 // TODO(nkostylev): Rename ParallelAuthenticator since it is not doing
     56 // offline/online login operations in parallel anymore.
     57 class ParallelAuthenticator : public Authenticator,
     58                               public AuthAttemptStateResolver {
     59  public:
     60   enum AuthState {
     61     CONTINUE = 0,            // State indeterminate; try again with more info.
     62     NO_MOUNT = 1,            // Cryptohome doesn't exist yet.
     63     FAILED_MOUNT = 2,        // Failed to mount existing cryptohome.
     64     FAILED_REMOVE = 3,       // Failed to remove existing cryptohome.
     65     FAILED_TMPFS = 4,        // Failed to mount tmpfs for guest user.
     66     FAILED_TPM = 5,          // Failed to mount/create cryptohome, TPM error.
     67     CREATE_NEW = 6,          // Need to create cryptohome for a new user.
     68     RECOVER_MOUNT = 7,       // After RecoverEncryptedData, mount cryptohome.
     69     POSSIBLE_PW_CHANGE = 8,  // Offline login failed, user may have changed pw.
     70     NEED_NEW_PW = 9,         // Obsolete (ClientLogin): user changed pw,
     71                              // we have the old one.
     72     NEED_OLD_PW = 10,        // User changed pw, and we have the new one
     73                              // (GAIA auth is OK).
     74     HAVE_NEW_PW = 11,        // Obsolete (ClientLogin): We have verified new pw,
     75                              // time to migrate key.
     76     OFFLINE_LOGIN = 12,      // Login succeeded offline.
     77     DEMO_LOGIN = 13,         // Logged in as the demo user.
     78     ONLINE_LOGIN = 14,       // Offline and online login succeeded.
     79     UNLOCK = 15,             // Screen unlock succeeded.
     80     ONLINE_FAILED = 16,      // Obsolete (ClientLogin): Online login disallowed,
     81                              // but offline succeeded.
     82     GUEST_LOGIN = 17,        // Logged in guest mode.
     83     PUBLIC_ACCOUNT_LOGIN = 18,        // Logged into a public account.
     84     LOCALLY_MANAGED_USER_LOGIN = 19,  // Logged in as a locally managed user.
     85     LOGIN_FAILED = 20,       // Login denied.
     86     OWNER_REQUIRED = 21      // Login is restricted to the owner only.
     87   };
     88 
     89   explicit ParallelAuthenticator(LoginStatusConsumer* consumer);
     90 
     91   // Authenticator overrides.
     92   virtual void CompleteLogin(Profile* profile,
     93                              const UserContext& user_context) OVERRIDE;
     94 
     95   // Given |user_context|, this method attempts to authenticate to your
     96   // Chrome OS device. As soon as we have successfully mounted the encrypted
     97   // home directory for the user, we will call consumer_->OnLoginSuccess()
     98   // with the username.
     99   // Upon failure to login consumer_->OnLoginFailure() is called
    100   // with an error message.
    101   //
    102   // Uses |profile| when doing URL fetches.
    103   virtual void AuthenticateToLogin(Profile* profile,
    104                                    const UserContext& user_context) OVERRIDE;
    105 
    106   // Given |user_context|, this method attempts to authenticate to the cached
    107   // user_context. This will never contact the server even if it's online.
    108   // The auth result is sent to LoginStatusConsumer in a same way as
    109   // AuthenticateToLogin does.
    110   virtual void AuthenticateToUnlock(
    111       const UserContext& user_context) OVERRIDE;
    112 
    113   // Initiates locally managed user login.
    114   // Creates cryptohome if missing or mounts existing one and
    115   // notifies consumer on the success/failure.
    116   virtual void LoginAsLocallyManagedUser(
    117       const UserContext& user_context) OVERRIDE;
    118 
    119   // Initiates retail mode login.
    120   // Mounts tmpfs and notifies consumer on the success/failure.
    121   virtual void LoginRetailMode() OVERRIDE;
    122 
    123   // Initiates incognito ("browse without signing in") login.
    124   // Mounts tmpfs and notifies consumer on the success/failure.
    125   virtual void LoginOffTheRecord() OVERRIDE;
    126 
    127   // Initiates login into the public account identified by |username|.
    128   // Mounts an ephemeral cryptohome and notifies consumer on the
    129   // success/failure.
    130   virtual void LoginAsPublicAccount(const std::string& username) OVERRIDE;
    131 
    132   // These methods must be called on the UI thread, as they make DBus calls
    133   // and also call back to the login UI.
    134   virtual void OnRetailModeLoginSuccess() OVERRIDE;
    135   virtual void OnLoginSuccess(bool request_pending) OVERRIDE;
    136   virtual void OnLoginFailure(const LoginFailure& error) OVERRIDE;
    137   virtual void RecoverEncryptedData(
    138       const std::string& old_password) OVERRIDE;
    139   virtual void ResyncEncryptedData() OVERRIDE;
    140 
    141   // AuthAttemptStateResolver overrides.
    142   // Attempts to make a decision and call back |consumer_| based on
    143   // the state we have gathered at the time of call.  If a decision
    144   // can't be made, defers until the next time this is called.
    145   // When a decision is made, will call back to |consumer_| on the UI thread.
    146   //
    147   // Must be called on the UI thread.
    148   virtual void Resolve() OVERRIDE;
    149 
    150   void OnOffTheRecordLoginSuccess();
    151   void OnPasswordChangeDetected();
    152 
    153  protected:
    154   virtual ~ParallelAuthenticator();
    155 
    156  private:
    157   friend class ParallelAuthenticatorTest;
    158   FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest,
    159                            ResolveOwnerNeededDirectFailedMount);
    160   FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest, ResolveOwnerNeededMount);
    161   FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest,
    162                            ResolveOwnerNeededFailedMount);
    163 
    164   // Returns the AuthState we're in, given the status info we have at
    165   // the time of call.
    166   // Must be called on the IO thread.
    167   AuthState ResolveState();
    168 
    169   // Helper for ResolveState().
    170   // Given that some cryptohome operation has failed, determine which of the
    171   // possible failure states we're in.
    172   // Must be called on the IO thread.
    173   AuthState ResolveCryptohomeFailureState();
    174 
    175   // Helper for ResolveState().
    176   // Given that some cryptohome operation has succeeded, determine which of
    177   // the possible states we're in.
    178   // Must be called on the IO thread.
    179   AuthState ResolveCryptohomeSuccessState();
    180 
    181   // Helper for ResolveState().
    182   // Given that some online auth operation has succeeded, determine which of
    183   // the possible success states we're in.
    184   // Must be called on the IO thread.
    185   AuthState ResolveOnlineSuccessState(AuthState offline_state);
    186 
    187   // Used to disable oauth, used for testing.
    188   void set_using_oauth(bool value) {
    189     using_oauth_ = value;
    190   }
    191 
    192   // Used for testing.
    193   void set_attempt_state(TestAttemptState* new_state) {  // takes ownership.
    194     current_state_.reset(new_state);
    195   }
    196 
    197   // Sets an online attempt for testing.
    198   void set_online_attempt(OnlineAttempt* attempt) {
    199     current_online_.reset(attempt);
    200   }
    201 
    202   // Used for testing to set the expected state of an owner check.
    203   void SetOwnerState(bool owner_check_finished, bool check_result);
    204 
    205   // checks if the current mounted home contains the owner case and either
    206   // continues or fails the log-in. Used for policy lost mitigation "safe-mode".
    207   // Returns true if the owner check has been successful or if it is not needed.
    208   bool VerifyOwner();
    209 
    210   // Handles completion of the ownership check and continues login.
    211   void OnOwnershipChecked(DeviceSettingsService::OwnershipStatus status,
    212                           bool is_owner);
    213 
    214   // Signal login completion status for cases when a new user is added via
    215   // an external authentication provider (i.e. GAIA extension).
    216   void ResolveLoginCompletionStatus();
    217 
    218   scoped_ptr<AuthAttemptState> current_state_;
    219   scoped_ptr<OnlineAttempt> current_online_;
    220   bool migrate_attempted_;
    221   bool remove_attempted_;
    222   bool ephemeral_mount_attempted_;
    223   bool check_key_attempted_;
    224 
    225   // When the user has changed her password, but gives us the old one, we will
    226   // be able to mount her cryptohome, but online authentication will fail.
    227   // This allows us to present the same behavior to the caller, regardless
    228   // of the order in which we receive these results.
    229   bool already_reported_success_;
    230   base::Lock success_lock_;  // A lock around |already_reported_success_|.
    231 
    232   // Flags signaling whether the owner verification has been done and the result
    233   // of it.
    234   bool owner_is_verified_;
    235   bool user_can_login_;
    236 
    237   // True if we use OAuth-based authentication flow.
    238   bool using_oauth_;
    239 
    240   DISALLOW_COPY_AND_ASSIGN(ParallelAuthenticator);
    241 };
    242 
    243 }  // namespace chromeos
    244 
    245 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_PARALLEL_AUTHENTICATOR_H_
    246