google_authenticator.h revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
1// Copyright (c) 2010 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_GOOGLE_AUTHENTICATOR_H_
6#define CHROME_BROWSER_CHROMEOS_LOGIN_GOOGLE_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/scoped_ptr.h"
15#include "chrome/browser/chromeos/cros/cros_library.h"
16#include "chrome/browser/chromeos/cros/cryptohome_library.h"
17#include "chrome/browser/chromeos/login/authenticator.h"
18#include "chrome/common/net/gaia/gaia_auth_consumer.h"
19#include "chrome/common/net/gaia/gaia_auth_fetcher.h"
20
21// Authenticates a Chromium OS user against the Google Accounts ClientLogin API.
22
23class Lock;
24class Profile;
25class GoogleServiceAuthError;
26class LoginFailure;
27
28namespace chromeos {
29
30class GoogleAuthenticatorTest;
31class LoginStatusConsumer;
32class UserManager;
33
34class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer {
35 public:
36  explicit GoogleAuthenticator(LoginStatusConsumer* consumer);
37  virtual ~GoogleAuthenticator();
38
39  // Given a |username| and |password|, this method attempts to authenticate to
40  // the Google accounts servers.  The ultimate result is either a callback to
41  // consumer_->OnLoginSuccess() with the |username| and a vector of
42  // authentication cookies or a callback to consumer_->OnLoginFailure() with
43  // an error message.  Uses |profile| when doing URL fetches.
44  // Optionally could pass CAPTCHA challenge token - |login_token| and
45  // |login_captcha| string that user has entered.
46  //
47  // NOTE: We do not allow HOSTED accounts to log in.  In the event that
48  // we are asked to authenticate valid HOSTED account creds, we will
49  // call OnLoginFailure() with HOSTED_NOT_ALLOWED.
50  //
51  // Returns true if the attempt gets sent successfully and false if not.
52  bool AuthenticateToLogin(Profile* profile,
53                           const std::string& username,
54                           const std::string& password,
55                           const std::string& login_token,
56                           const std::string& login_captcha);
57
58  // Given a |username| and |password|, this method attempts to
59  // authenticate to the cached credentials. This will never contact
60  // the server even if it's online. The auth result is sent to
61  // LoginStatusConsumer in a same way as AuthenticateToLogin does.
62  bool AuthenticateToUnlock(const std::string& username,
63                            const std::string& password);
64
65  // Initiates off the record ("browse without signing in") login.
66  // Mounts tmpfs and notifies consumer on the success/failure.
67  void LoginOffTheRecord();
68
69  // Public for testing.
70  void set_system_salt(const chromeos::CryptohomeBlob& new_salt) {
71    system_salt_ = new_salt;
72  }
73  void set_username(const std::string& fake_user) { username_ = fake_user; }
74  void set_password(const std::string& fake_pass) { password_ = fake_pass; }
75  void set_password_hash(const std::string& fake_hash) {
76    ascii_hash_ = fake_hash;
77  }
78  void set_user_manager(UserManager* new_manager) {
79    user_manager_ = new_manager;
80  }
81  void SetLocalaccount(const std::string& new_name);
82
83  // These methods must be called on the UI thread, as they make DBus calls
84  // and also call back to the login UI.
85  void OnLoginSuccess(const GaiaAuthConsumer::ClientLoginResult& credentials,
86                      bool request_pending);
87  void CheckOffline(const LoginFailure& error);
88  void CheckLocalaccount(const LoginFailure& error);
89  void OnLoginFailure(const LoginFailure& error);
90
91  // Call these methods on the UI thread.
92  void RecoverEncryptedData(
93      const std::string& old_password,
94      const GaiaAuthConsumer::ClientLoginResult& credentials);
95  void ResyncEncryptedData(
96      const GaiaAuthConsumer::ClientLoginResult& credentials);
97  void RetryAuth(Profile* profile,
98                 const std::string& username,
99                 const std::string& password,
100                 const std::string& login_token,
101                 const std::string& login_captcha);
102
103  // Callbacks from GaiaAuthFetcher
104  virtual void OnClientLoginFailure(
105      const GoogleServiceAuthError& error);
106  virtual void OnClientLoginSuccess(
107      const GaiaAuthConsumer::ClientLoginResult& credentials);
108
109 private:
110
111  // If we don't have the system salt yet, loads it from the CryptohomeLibrary.
112  void LoadSystemSalt();
113
114  // If we haven't already, looks in a file called |filename| next to
115  // the browser executable for a "localaccount" name, and retrieves it
116  // if one is present.  If someone attempts to authenticate with this
117  // username, we will mount a tmpfs for them and let them use the
118  // browser.
119  // Should only be called on the FILE thread.
120  void LoadLocalaccount(const std::string& filename);
121
122  // Stores a hash of |password|, salted with the ascii of |system_salt_|.
123  std::string HashPassword(const std::string& password);
124
125  // Returns the ascii encoding of the system salt.
126  std::string SaltAsAscii();
127
128  // Save the current login attempt for use on the next TryClientLogin
129  // attempt.
130  void PrepareClientLoginAttempt(const std::string& password,
131                                 const std::string& login_token,
132                                 const std::string& login_captcha);
133  // Clear any cached credentials after we've given up trying to authenticate.
134  void ClearClientLoginAttempt();
135
136  // Start a client login attempt.  |hosted_policy_| governs whether we are
137  // willing to authenticate accounts that are HOSTED or not.
138  // You must set up |gaia_authenticator_| first.
139  // Reuses existing credentials from the last attempt. You must
140  // PrepareClientLoginAttempt before calling this.
141   void TryClientLogin();
142
143  // A callback for use on the UI thread. Cancel the current login
144  // attempt, and produce a login failure.
145  void CancelClientLogin();
146
147
148  // Converts the binary data |binary| into an ascii hex string and stores
149  // it in |hex_string|.  Not guaranteed to be NULL-terminated.
150  // Returns false if |hex_string| is too small, true otherwise.
151  static bool BinaryToHex(const std::vector<unsigned char>& binary,
152                          const unsigned int binary_len,
153                          char* hex_string,
154                          const unsigned int len);
155
156  void set_hosted_policy(GaiaAuthFetcher::HostedAccountsSetting policy) {
157    hosted_policy_ = policy;
158  }
159
160  // The format of said POST body when CAPTCHA token & answer are specified.
161  static const char kFormatCaptcha[];
162
163  // Magic string indicating that, while a second factor is still
164  // needed to complete authentication, the user provided the right password.
165  static const char kSecondFactor[];
166
167  // Name of a file, next to chrome, that contains a local account username.
168  static const char kLocalaccountFile[];
169
170  // Handles all net communications with Gaia.
171  scoped_ptr<GaiaAuthFetcher> gaia_authenticator_;
172
173  // Allows us to look up users of the device.
174  UserManager* user_manager_;
175
176  // Milliseconds until we timeout our attempt to hit ClientLogin.
177  static const int kClientLoginTimeoutMs;
178
179  // Milliseconds until we re-check whether we've gotten the localaccount name.
180  static const int kLocalaccountRetryIntervalMs;
181
182  // Whether or not we're accepting HOSTED accounts on this auth attempt.
183  GaiaAuthFetcher::HostedAccountsSetting hosted_policy_;
184
185  std::string username_;
186  // These fields are saved so we can retry client login.
187  std::string password_;
188  std::string login_token_;
189  std::string login_captcha_;
190
191  std::string ascii_hash_;
192  chromeos::CryptohomeBlob system_salt_;
193  bool unlock_;  // True if authenticating to unlock the computer.
194  bool try_again_;  // True if we're willing to retry the login attempt.
195
196  std::string localaccount_;
197  bool checked_for_localaccount_;  // needed because empty localaccount_ is ok.
198  Lock localaccount_lock_;  // a lock around checked_for_localaccount_.
199
200  friend class GoogleAuthenticatorTest;
201  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, SaltToAscii);
202  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, CheckTwoFactorResponse);
203  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, CheckNormalErrorCode);
204  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, EmailAddressNoOp);
205  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, EmailAddressIgnoreCaps);
206  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest,
207                           EmailAddressIgnoreDomainCaps);
208  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest,
209                           EmailAddressIgnoreOneUsernameDot);
210  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest,
211                           EmailAddressIgnoreManyUsernameDots);
212  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest,
213                           EmailAddressIgnoreConsecutiveUsernameDots);
214  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest,
215                           EmailAddressDifferentOnesRejected);
216  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest,
217                           EmailAddressIgnorePlusSuffix);
218  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest,
219                           EmailAddressIgnoreMultiPlusSuffix);
220  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, ReadSaltOnlyOnce);
221  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, LocalaccountLogin);
222  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, ReadLocalaccount);
223  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, ReadLocalaccountTrailingWS);
224  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, ReadNoLocalaccount);
225  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, LoginNetFailure);
226  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, LoginDenied);
227  FRIEND_TEST_ALL_PREFIXES(GoogleAuthenticatorTest, TwoFactorLogin);
228
229  DISALLOW_COPY_AND_ASSIGN(GoogleAuthenticator);
230};
231
232}  // namespace chromeos
233
234#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_GOOGLE_AUTHENTICATOR_H_
235