1 // Copyright (c) 2011 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 #pragma once 8 9 #include <string> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "chrome/browser/chromeos/cros/cros_library.h" 17 #include "chrome/browser/chromeos/cros/cryptohome_library.h" 18 #include "chrome/browser/chromeos/login/authenticator.h" 19 #include "chrome/browser/chromeos/login/auth_attempt_state.h" 20 #include "chrome/browser/chromeos/login/auth_attempt_state_resolver.h" 21 #include "chrome/browser/chromeos/login/test_attempt_state.h" 22 #include "chrome/browser/chromeos/login/cryptohome_op.h" 23 #include "chrome/browser/chromeos/login/online_attempt.h" 24 #include "chrome/common/net/gaia/gaia_auth_consumer.h" 25 26 class GaiaAuthFetcher; 27 class LoginFailure; 28 class Profile; 29 30 namespace base { 31 class Lock; 32 } 33 34 namespace chromeos { 35 36 class LoginStatusConsumer; 37 class ParallelAuthenticator; 38 class ResolveChecker; 39 40 // Authenticates a Chromium OS user against the Google Accounts ClientLogin API. 41 // 42 // Simultaneously attempts authentication both offline and online, failing over 43 // to the "localaccount" in the event that authentication fails. 44 // 45 // At a high, level, here's what happens: 46 // AuthenticateToLogin() creates an OnlineAttempt and a CryptohomeOp that 47 // attempt to perform online and offline login simultaneously. When one of 48 // these completes, it will store results in a AuthAttemptState owned by 49 // ParallelAuthenticator and then call Resolve(). Resolve() will attempt to 50 // determine which AuthState we're in, based on the info at hand. 51 // It then triggers further action based on the calculated AuthState; this 52 // further action might include calling back the passed-in LoginStatusConsumer 53 // to signal that login succeeded or failed, waiting for more outstanding 54 // operations to complete, or triggering some more CryptohomeOps. 55 class ParallelAuthenticator : public Authenticator, 56 public AuthAttemptStateResolver { 57 public: 58 enum AuthState { 59 CONTINUE, // State indeterminate; try again when more info available. 60 NO_MOUNT, // Cryptohome doesn't exist yet. 61 FAILED_MOUNT, // Failed to mount existing cryptohome. 62 FAILED_REMOVE, // Failed to remove existing cryptohome. 63 FAILED_TMPFS, // Failed to mount tmpfs for guest user 64 CREATE_NEW, // Need to create cryptohome for a new user. 65 RECOVER_MOUNT, // After RecoverEncryptedData, mount cryptohome. 66 POSSIBLE_PW_CHANGE, // Offline login failed, user may have changed pw. 67 NEED_NEW_PW, // User changed pw, and we have the old one. 68 NEED_OLD_PW, // User changed pw, and we have the new one. 69 HAVE_NEW_PW, // We have verified new pw, time to migrate key. 70 OFFLINE_LOGIN, // Login succeeded offline. 71 ONLINE_LOGIN, // Offline and online login succeeded. 72 UNLOCK, // Screen unlock succeeded. 73 LOCAL_LOGIN, // Login with localaccount succeded. 74 ONLINE_FAILED, // Online login disallowed, but offline succeeded. 75 LOGIN_FAILED // Login denied. 76 }; 77 78 explicit ParallelAuthenticator(LoginStatusConsumer* consumer); 79 virtual ~ParallelAuthenticator(); 80 81 // Given a |username| and |password|, this method attempts to authenticate to 82 // the Google accounts servers and your Chrome OS device simultaneously. 83 // As soon as we have successfully mounted the encrypted home directory for 84 // |username|, we will call consumer_->OnLoginSuccess() with |username| and a 85 // vector of authentication cookies. If we're still waiting for an online 86 // result at that time, we'll also pass back a flag indicating that more 87 // callbacks are on the way; if not, we pass back false. When the pending 88 // request completes, either consumer_->OnLoginSuccess() with an indication 89 // that no more requests are outstanding will be called, or 90 // consumer_->OnLoginFailure() if appropriate. 91 // 92 // Upon failure to login (online fails, then offline fails; 93 // offline fails, then online fails) consumer_->OnLoginFailure() is called 94 // with an error message. 95 // 96 // In the event that we see an online success and then an offline failure, 97 // consumer_->OnPasswordChangeDetected() is called. 98 // 99 // Uses |profile| when doing URL fetches. 100 // Optionally could pass CAPTCHA challenge token - |login_token| and 101 // |login_captcha| string that user has entered. 102 // 103 // NOTE: We do not allow HOSTED accounts to log in. In the event that 104 // we are asked to authenticate valid HOSTED account creds, we will 105 // call OnLoginFailure() with HOSTED_NOT_ALLOWED. 106 // 107 // Returns true if the attempt gets sent successfully and false if not. 108 bool AuthenticateToLogin(Profile* profile, 109 const std::string& username, 110 const std::string& password, 111 const std::string& login_token, 112 const std::string& login_captcha); 113 114 // Given a |username| and |password|, this method attempts to 115 // authenticate to the cached credentials. This will never contact 116 // the server even if it's online. The auth result is sent to 117 // LoginStatusConsumer in a same way as AuthenticateToLogin does. 118 bool AuthenticateToUnlock(const std::string& username, 119 const std::string& password); 120 121 // Initiates incognito ("browse without signing in") login. 122 // Mounts tmpfs and notifies consumer on the success/failure. 123 void LoginOffTheRecord(); 124 125 // These methods must be called on the UI thread, as they make DBus calls 126 // and also call back to the login UI. 127 void OnLoginSuccess(const GaiaAuthConsumer::ClientLoginResult& credentials, 128 bool request_pending); 129 void OnOffTheRecordLoginSuccess(); 130 void OnPasswordChangeDetected( 131 const GaiaAuthConsumer::ClientLoginResult& credentials); 132 void OnLoginFailure(const LoginFailure& error); 133 134 void RecoverEncryptedData( 135 const std::string& old_password, 136 const GaiaAuthConsumer::ClientLoginResult& credentials); 137 void ResyncEncryptedData( 138 const GaiaAuthConsumer::ClientLoginResult& credentials); 139 void RetryAuth(Profile* profile, 140 const std::string& username, 141 const std::string& password, 142 const std::string& login_token, 143 const std::string& login_captcha); 144 145 // Call this on the FILE thread. 146 void CheckLocalaccount(const LoginFailure& error); 147 148 // Attempts to make a decision and call back |consumer_| based on 149 // the state we have gathered at the time of call. If a decision 150 // can't be made, defers until the next time this is called. 151 // When a decision is made, will call back to |consumer_| on the UI thread. 152 // 153 // Must be called on the IO thread. 154 void Resolve(); 155 156 private: 157 // Returns the AuthState we're in, given the status info we have at 158 // the time of call. 159 // Must be called on the IO thread. 160 AuthState ResolveState(); 161 162 // Helper for ResolveState(). 163 // Given that we're attempting to auth the user again, with a new password, 164 // determine which state we're in. Returns CONTINUE if no resolution. 165 // Must be called on the IO thread. 166 AuthState ResolveReauthState(); 167 168 // Helper for ResolveState(). 169 // Given that some cryptohome operation has failed, determine which of the 170 // possible failure states we're in. 171 // Must be called on the IO thread. 172 AuthState ResolveCryptohomeFailureState(); 173 174 // Helper for ResolveState(). 175 // Given that some cryptohome operation has succeeded, determine which of 176 // the possible states we're in. 177 // Must be called on the IO thread. 178 AuthState ResolveCryptohomeSuccessState(); 179 180 // Helper for ResolveState(). 181 // Given that some online auth operation has failed, determine which of the 182 // possible failure states we're in. Handles both failure to complete and 183 // actual failure responses from the server. 184 // Must be called on the IO thread. 185 AuthState ResolveOnlineFailureState(AuthState offline_state); 186 187 // Helper for ResolveState(). 188 // Given that some online auth operation has succeeded, determine which of 189 // the possible success states we're in. 190 // Must be called on the IO thread. 191 AuthState ResolveOnlineSuccessState(AuthState offline_state); 192 193 // Used for testing. set_attempt_state(TestAttemptState * new_state)194 void set_attempt_state(TestAttemptState* new_state) { // takes ownership. 195 current_state_.reset(new_state); 196 } 197 198 // Resets |current_state_| and then posts a task to the UI thread to 199 // Initiate() |to_initiate|. 200 // Call this method on the IO thread. 201 void ResyncRecoverHelper(CryptohomeOp* to_initiate); 202 203 // If we don't have the system salt yet, loads it from the CryptohomeLibrary. 204 void LoadSystemSalt(); 205 206 // If we haven't already, looks in a file called |filename| next to 207 // the browser executable for a "localaccount" name, and retrieves it 208 // if one is present. If someone attempts to authenticate with this 209 // username, we will mount a tmpfs for them and let them use the 210 // browser. 211 // Should only be called on the FILE thread. 212 void LoadLocalaccount(const std::string& filename); 213 214 void SetLocalaccount(const std::string& new_name); 215 216 // Stores a hash of |password|, salted with the ascii of |system_salt_|. 217 std::string HashPassword(const std::string& password); 218 219 // Returns the ascii encoding of the system salt. 220 std::string SaltAsAscii(); 221 222 // Converts the binary data |binary| into an ascii hex string and stores 223 // it in |hex_string|. Not guaranteed to be NULL-terminated. 224 // Returns false if |hex_string| is too small, true otherwise. 225 static bool BinaryToHex(const std::vector<unsigned char>& binary, 226 const unsigned int binary_len, 227 char* hex_string, 228 const unsigned int len); 229 230 // Name of a file, next to chrome, that contains a local account username. 231 static const char kLocalaccountFile[]; 232 233 // Milliseconds until we timeout our attempt to hit ClientLogin. 234 static const int kClientLoginTimeoutMs; 235 236 // Milliseconds until we re-check whether we've gotten the localaccount name. 237 static const int kLocalaccountRetryIntervalMs; 238 239 // Handles all net communications with Gaia. 240 scoped_ptr<GaiaAuthFetcher> gaia_authenticator_; 241 242 // Used when we need to try online authentication again, after successful 243 // mount, but failed online login. 244 scoped_ptr<AuthAttemptState> reauth_state_; 245 246 scoped_ptr<AuthAttemptState> current_state_; 247 scoped_refptr<OnlineAttempt> current_online_; 248 scoped_refptr<CryptohomeOp> mounter_; 249 scoped_refptr<CryptohomeOp> key_migrator_; 250 scoped_refptr<CryptohomeOp> data_remover_; 251 scoped_refptr<CryptohomeOp> guest_mounter_; 252 scoped_refptr<CryptohomeOp> key_checker_; 253 254 std::string ascii_hash_; 255 chromeos::CryptohomeBlob system_salt_; 256 257 // When the user has changed her password, but gives us the old one, we will 258 // be able to mount her cryptohome, but online authentication will fail. 259 // This allows us to present the same behavior to the caller, regardless 260 // of the order in which we receive these results. 261 bool already_reported_success_; 262 base::Lock success_lock_; // A lock around already_reported_success_. 263 264 // Status relating to the local "backdoor" account. 265 std::string localaccount_; 266 bool checked_for_localaccount_; // Needed because empty localaccount_ is ok. 267 base::Lock localaccount_lock_; // A lock around checked_for_localaccount_. 268 269 friend class ResolveChecker; 270 friend class ParallelAuthenticatorTest; 271 FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest, SaltToAscii); 272 FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest, ReadLocalaccount); 273 FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest, 274 ReadLocalaccountTrailingWS); 275 FRIEND_TEST_ALL_PREFIXES(ParallelAuthenticatorTest, ReadNoLocalaccount); 276 DISALLOW_COPY_AND_ASSIGN(ParallelAuthenticator); 277 }; 278 279 } // namespace chromeos 280 281 #endif // CHROME_BROWSER_CHROMEOS_LOGIN_PARALLEL_AUTHENTICATOR_H_ 282