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