Home | History | Annotate | Download | only in auth
      1 // Copyright 2014 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 CHROMEOS_LOGIN_AUTH_CRYPTOHOME_AUTHENTICATOR_H_
      6 #define CHROMEOS_LOGIN_AUTH_CRYPTOHOME_AUTHENTICATOR_H_
      7 
      8 #include <string>
      9 
     10 #include "base/compiler_specific.h"
     11 #include "base/gtest_prod_util.h"
     12 #include "base/macros.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/synchronization/lock.h"
     15 #include "base/task_runner.h"
     16 #include "chromeos/chromeos_export.h"
     17 #include "chromeos/login/auth/auth_attempt_state.h"
     18 #include "chromeos/login/auth/auth_attempt_state_resolver.h"
     19 #include "chromeos/login/auth/authenticator.h"
     20 #include "chromeos/login/auth/test_attempt_state.h"
     21 #include "google_apis/gaia/gaia_auth_consumer.h"
     22 
     23 class AuthFailure;
     24 class Profile;
     25 
     26 namespace chromeos {
     27 
     28 class AuthStatusConsumer;
     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 CryptohomeAuthenticator
     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 AuthStatusConsumer
     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 class CHROMEOS_EXPORT CryptohomeAuthenticator
     56     : public Authenticator,
     57       public AuthAttemptStateResolver {
     58  public:
     59   enum AuthState {
     60     CONTINUE = 0,            // State indeterminate; try again with more info.
     61     NO_MOUNT = 1,            // Cryptohome doesn't exist yet.
     62     FAILED_MOUNT = 2,        // Failed to mount existing cryptohome.
     63     FAILED_REMOVE = 3,       // Failed to remove existing cryptohome.
     64     FAILED_TMPFS = 4,        // Failed to mount tmpfs for guest user.
     65     FAILED_TPM = 5,          // Failed to mount/create cryptohome, TPM error.
     66     CREATE_NEW = 6,          // Need to create cryptohome for a new user.
     67     RECOVER_MOUNT = 7,       // After RecoverEncryptedData, mount cryptohome.
     68     POSSIBLE_PW_CHANGE = 8,  // Offline login failed, user may have changed pw.
     69     NEED_NEW_PW = 9,         // Obsolete (ClientLogin): user changed pw,
     70                              // we have the old one.
     71     NEED_OLD_PW = 10,        // User changed pw, and we have the new one
     72                              // (GAIA auth is OK).
     73     HAVE_NEW_PW = 11,        // Obsolete (ClientLogin): We have verified new pw,
     74                              // time to migrate key.
     75     OFFLINE_LOGIN = 12,      // Login succeeded offline.
     76     DEMO_LOGIN = 13,         // Logged in as the demo user.
     77     ONLINE_LOGIN = 14,       // Offline and online login succeeded.
     78     UNLOCK = 15,             // Screen unlock succeeded.
     79     ONLINE_FAILED = 16,      // Obsolete (ClientLogin): Online login disallowed,
     80                              // but offline succeeded.
     81     GUEST_LOGIN = 17,        // Logged in guest mode.
     82     PUBLIC_ACCOUNT_LOGIN = 18,        // Logged into a public account.
     83     SUPERVISED_USER_LOGIN = 19,       // Logged in as a supervised user.
     84     LOGIN_FAILED = 20,                // Login denied.
     85     OWNER_REQUIRED = 21,              // Login is restricted to the owner only.
     86     FAILED_USERNAME_HASH = 22,        // Failed GetSanitizedUsername request.
     87     KIOSK_ACCOUNT_LOGIN = 23,         // Logged into a kiosk account.
     88     REMOVED_DATA_AFTER_FAILURE = 24,  // Successfully removed the user's
     89                                       // cryptohome after a login failure.
     90   };
     91 
     92   CryptohomeAuthenticator(scoped_refptr<base::TaskRunner> task_runner,
     93                           AuthStatusConsumer* consumer);
     94 
     95   // Authenticator overrides.
     96   virtual void CompleteLogin(Profile* profile,
     97                              const UserContext& user_context) OVERRIDE;
     98 
     99   // Given |user_context|, this method attempts to authenticate to your
    100   // Chrome OS device. As soon as we have successfully mounted the encrypted
    101   // home directory for the user, we will call consumer_->OnAuthSuccess()
    102   // with the username.
    103   // Upon failure to login consumer_->OnAuthFailure() is called
    104   // with an error message.
    105   //
    106   // Uses |profile| when doing URL fetches.
    107   virtual void AuthenticateToLogin(Profile* profile,
    108                                    const UserContext& user_context) OVERRIDE;
    109 
    110   // Given |user_context|, this method attempts to authenticate to the cached
    111   // user_context. This will never contact the server even if it's online.
    112   // The auth result is sent to AuthStatusConsumer in a same way as
    113   // AuthenticateToLogin does.
    114   virtual void AuthenticateToUnlock(const UserContext& user_context) OVERRIDE;
    115 
    116   // Initiates supervised user login.
    117   // Creates cryptohome if missing or mounts existing one and
    118   // notifies consumer on the success/failure.
    119   virtual void LoginAsSupervisedUser(const UserContext& user_context) OVERRIDE;
    120 
    121   // Initiates retail mode login.
    122   // Mounts tmpfs and notifies consumer on the success/failure.
    123   virtual void LoginRetailMode() OVERRIDE;
    124 
    125   // Initiates incognito ("browse without signing in") login.
    126   // Mounts tmpfs and notifies consumer on the success/failure.
    127   virtual void LoginOffTheRecord() OVERRIDE;
    128 
    129   // Initiates login into a public session.
    130   // Mounts an ephemeral cryptohome and notifies consumer on the
    131   // success/failure.
    132   virtual void LoginAsPublicSession(const UserContext& user_context) OVERRIDE;
    133 
    134   // Initiates login into the kiosk mode account identified by |app_user_id|.
    135   // Mounts an ephemeral guest cryptohome if |use_guest_mount| is |true|.
    136   // Otherwise, mounts a public cryptohome, which will be ephemeral if the
    137   // |DeviceEphemeralUsersEnabled| policy is enabled and non-ephemeral
    138   // otherwise.
    139   virtual void LoginAsKioskAccount(const std::string& app_user_id,
    140                                    bool use_guest_mount) OVERRIDE;
    141 
    142   // These methods must be called on the UI thread, as they make DBus calls
    143   // and also call back to the login UI.
    144   virtual void OnRetailModeAuthSuccess() OVERRIDE;
    145   virtual void OnAuthSuccess() OVERRIDE;
    146   virtual void OnAuthFailure(const AuthFailure& error) OVERRIDE;
    147   virtual void RecoverEncryptedData(const std::string& old_password) OVERRIDE;
    148   virtual void ResyncEncryptedData() OVERRIDE;
    149 
    150   // AuthAttemptStateResolver overrides.
    151   // Attempts to make a decision and call back |consumer_| based on
    152   // the state we have gathered at the time of call.  If a decision
    153   // can't be made, defers until the next time this is called.
    154   // When a decision is made, will call back to |consumer_| on the UI thread.
    155   //
    156   // Must be called on the UI thread.
    157   virtual void Resolve() OVERRIDE;
    158 
    159   void OnOffTheRecordAuthSuccess();
    160   void OnPasswordChangeDetected();
    161 
    162  protected:
    163   virtual ~CryptohomeAuthenticator();
    164 
    165   typedef base::Callback<void(bool is_owner)> IsOwnerCallback;
    166 
    167   // Method to be implemented in child. Return |true| if user specified in
    168   // |context| exists on device.
    169   virtual bool IsKnownUser(const UserContext& context) = 0;
    170 
    171   // Method to be implemented in child. Return |true| if device is running
    172   // in safe mode.
    173   virtual bool IsSafeMode() = 0;
    174 
    175   // Method to be implemented in child. Have to call |callback| with boolean
    176   // parameter that indicates if user in |context| can act as an owner in
    177   // safe mode.
    178   virtual void CheckSafeModeOwnership(const UserContext& context,
    179                                       const IsOwnerCallback& callback) = 0;
    180 
    181  private:
    182   friend class CryptohomeAuthenticatorTest;
    183   FRIEND_TEST_ALL_PREFIXES(CryptohomeAuthenticatorTest,
    184                            ResolveOwnerNeededDirectFailedMount);
    185   FRIEND_TEST_ALL_PREFIXES(CryptohomeAuthenticatorTest,
    186                            ResolveOwnerNeededMount);
    187   FRIEND_TEST_ALL_PREFIXES(CryptohomeAuthenticatorTest,
    188                            ResolveOwnerNeededFailedMount);
    189 
    190   // Removes the cryptohome of the user.
    191   void RemoveEncryptedData();
    192 
    193   // Returns the AuthState we're in, given the status info we have at
    194   // the time of call.
    195   // Must be called on the IO thread.
    196   AuthState ResolveState();
    197 
    198   // Helper for ResolveState().
    199   // Given that some cryptohome operation has failed, determine which of the
    200   // possible failure states we're in.
    201   // Must be called on the IO thread.
    202   AuthState ResolveCryptohomeFailureState();
    203 
    204   // Helper for ResolveState().
    205   // Given that some cryptohome operation has succeeded, determine which of
    206   // the possible states we're in.
    207   // Must be called on the IO thread.
    208   AuthState ResolveCryptohomeSuccessState();
    209 
    210   // Helper for ResolveState().
    211   // Given that some online auth operation has succeeded, determine which of
    212   // the possible success states we're in.
    213   // Must be called on the IO thread.
    214   AuthState ResolveOnlineSuccessState(AuthState offline_state);
    215 
    216   // Used for testing.
    217   void set_attempt_state(TestAttemptState* new_state) {  // takes ownership.
    218     current_state_.reset(new_state);
    219   }
    220 
    221   // Used for testing to set the expected state of an owner check.
    222   void SetOwnerState(bool owner_check_finished, bool check_result);
    223 
    224   // checks if the current mounted home contains the owner case and either
    225   // continues or fails the log-in. Used for policy lost mitigation "safe-mode".
    226   // Returns true if the owner check has been successful or if it is not needed.
    227   bool VerifyOwner();
    228 
    229   // Handles completion of the ownership check and continues login.
    230   void OnOwnershipChecked(bool is_owner);
    231 
    232   // Signal login completion status for cases when a new user is added via
    233   // an external authentication provider (i.e. GAIA extension).
    234   void ResolveLoginCompletionStatus();
    235 
    236   scoped_refptr<base::TaskRunner> task_runner_;
    237 
    238   scoped_ptr<AuthAttemptState> current_state_;
    239   bool migrate_attempted_;
    240   bool remove_attempted_;
    241   bool resync_attempted_;
    242   bool ephemeral_mount_attempted_;
    243   bool check_key_attempted_;
    244 
    245   // When the user has changed her password, but gives us the old one, we will
    246   // be able to mount her cryptohome, but online authentication will fail.
    247   // This allows us to present the same behavior to the caller, regardless
    248   // of the order in which we receive these results.
    249   bool already_reported_success_;
    250   base::Lock success_lock_;  // A lock around |already_reported_success_|.
    251 
    252   // Flags signaling whether the owner verification has been done and the result
    253   // of it.
    254   bool owner_is_verified_;
    255   bool user_can_login_;
    256 
    257   // Flag indicating to delete the user's cryptohome the login fails.
    258   bool remove_user_data_on_failure_;
    259 
    260   // When |remove_user_data_on_failure_| is set, we delay calling
    261   // consumer_->OnAuthFailure() until we removed the user cryptohome.
    262   const AuthFailure* delayed_login_failure_;
    263 
    264   DISALLOW_COPY_AND_ASSIGN(CryptohomeAuthenticator);
    265 };
    266 
    267 }  // namespace chromeos
    268 
    269 #endif  // CHROMEOS_LOGIN_AUTH_CRYPTOHOME_AUTHENTICATOR_H_
    270