• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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