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