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
23class AuthFailure;
24class Profile;
25
26namespace chromeos {
27
28class 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//
55class 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