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