login_performer.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright 2014 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#include "chrome/browser/chromeos/login/auth/login_performer.h"
6
7#include "base/bind.h"
8#include "base/logging.h"
9#include "base/message_loop/message_loop.h"
10#include "base/metrics/histogram.h"
11#include "base/prefs/pref_service.h"
12#include "base/strings/utf_string_conversions.h"
13#include "base/threading/thread_restrictions.h"
14#include "chrome/browser/browser_process.h"
15#include "chrome/browser/chrome_notification_types.h"
16#include "chrome/browser/chromeos/boot_times_loader.h"
17#include "chrome/browser/chromeos/login/login_utils.h"
18#include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
19#include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
20#include "chrome/browser/chromeos/login/managed/supervised_user_login_flow.h"
21#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
22#include "chrome/browser/chromeos/login/users/user_manager.h"
23#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
24#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
25#include "chrome/browser/chromeos/profiles/profile_helper.h"
26#include "chrome/browser/chromeos/settings/cros_settings.h"
27#include "chrome/common/pref_names.h"
28#include "chromeos/dbus/dbus_thread_manager.h"
29#include "chromeos/dbus/session_manager_client.h"
30#include "chromeos/settings/cros_settings_names.h"
31#include "content/public/browser/browser_thread.h"
32#include "content/public/browser/notification_service.h"
33#include "content/public/browser/notification_types.h"
34#include "content/public/browser/user_metrics.h"
35#include "google_apis/gaia/gaia_auth_util.h"
36#include "grit/generated_resources.h"
37#include "net/cookies/cookie_monster.h"
38#include "net/cookies/cookie_store.h"
39#include "net/url_request/url_request_context.h"
40#include "net/url_request/url_request_context_getter.h"
41#include "ui/base/l10n/l10n_util.h"
42#include "ui/base/resource/resource_bundle.h"
43
44using base::UserMetricsAction;
45using content::BrowserThread;
46
47namespace chromeos {
48
49LoginPerformer::LoginPerformer(Delegate* delegate)
50    : online_attempt_host_(this),
51      last_login_failure_(LoginFailure::LoginFailureNone()),
52      delegate_(delegate),
53      password_changed_(false),
54      password_changed_callback_count_(0),
55      auth_mode_(AUTH_MODE_INTERNAL),
56      weak_factory_(this) {
57}
58
59LoginPerformer::~LoginPerformer() {
60  DVLOG(1) << "Deleting LoginPerformer";
61  if (authenticator_.get())
62    authenticator_->SetConsumer(NULL);
63  if (extended_authenticator_.get())
64    extended_authenticator_->SetConsumer(NULL);
65}
66
67////////////////////////////////////////////////////////////////////////////////
68// LoginPerformer, LoginStatusConsumer implementation:
69
70void LoginPerformer::OnLoginFailure(const LoginFailure& failure) {
71  content::RecordAction(UserMetricsAction("Login_Failure"));
72  UMA_HISTOGRAM_ENUMERATION("Login.FailureReason", failure.reason(),
73                            LoginFailure::NUM_FAILURE_REASONS);
74
75  DVLOG(1) << "failure.reason " << failure.reason();
76  DVLOG(1) << "failure.error.state " << failure.error().state();
77
78  last_login_failure_ = failure;
79  if (delegate_) {
80    delegate_->OnLoginFailure(failure);
81    return;
82  } else {
83    // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS:
84    // happens during offline auth only.
85    NOTREACHED();
86  }
87}
88
89void LoginPerformer::OnRetailModeLoginSuccess(
90    const UserContext& user_context) {
91  content::RecordAction(
92      UserMetricsAction("Login_DemoUserLoginSuccess"));
93  LoginStatusConsumer::OnRetailModeLoginSuccess(user_context);
94}
95
96void LoginPerformer::OnLoginSuccess(const UserContext& user_context) {
97  content::RecordAction(UserMetricsAction("Login_Success"));
98  VLOG(1) << "LoginSuccess hash: " << user_context.GetUserIDHash();
99  DCHECK(delegate_);
100  // After delegate_->OnLoginSuccess(...) is called, delegate_ releases
101  // LoginPerformer ownership. LP now manages it's lifetime on its own.
102  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
103  delegate_->OnLoginSuccess(user_context);
104}
105
106void LoginPerformer::OnOffTheRecordLoginSuccess() {
107  content::RecordAction(
108      UserMetricsAction("Login_GuestLoginSuccess"));
109
110  if (delegate_)
111    delegate_->OnOffTheRecordLoginSuccess();
112  else
113    NOTREACHED();
114}
115
116void LoginPerformer::OnPasswordChangeDetected() {
117  password_changed_ = true;
118  password_changed_callback_count_++;
119  if (delegate_) {
120    delegate_->OnPasswordChangeDetected();
121  } else {
122    NOTREACHED();
123  }
124}
125
126void LoginPerformer::OnChecked(const std::string& username, bool success) {
127  if (!delegate_) {
128    // Delegate is reset in case of successful offline login.
129    // See ExistingUserConstoller::OnLoginSuccess().
130    // Case when user has changed password and enters old password
131    // does not block user from sign in yet.
132    return;
133  }
134  delegate_->OnOnlineChecked(username, success);
135}
136
137////////////////////////////////////////////////////////////////////////////////
138// LoginPerformer, public:
139
140void LoginPerformer::PerformLogin(const UserContext& user_context,
141                                  AuthorizationMode auth_mode) {
142  auth_mode_ = auth_mode;
143  user_context_ = user_context;
144
145  CrosSettings* cros_settings = CrosSettings::Get();
146
147  // Whitelist check is always performed during initial login.
148  CrosSettingsProvider::TrustedStatus status =
149      cros_settings->PrepareTrustedValues(
150          base::Bind(&LoginPerformer::PerformLogin,
151                     weak_factory_.GetWeakPtr(),
152                     user_context_, auth_mode));
153  // Must not proceed without signature verification.
154  if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
155    if (delegate_)
156      delegate_->PolicyLoadFailed();
157    else
158      NOTREACHED();
159    return;
160  } else if (status != CrosSettingsProvider::TRUSTED) {
161    // Value of AllowNewUser setting is still not verified.
162    // Another attempt will be invoked after verification completion.
163    return;
164  }
165
166  bool wildcard_match = false;
167  std::string email = gaia::CanonicalizeEmail(user_context.GetUserID());
168  bool is_whitelisted = LoginUtils::IsWhitelisted(email, &wildcard_match);
169  if (is_whitelisted) {
170    switch (auth_mode_) {
171      case AUTH_MODE_EXTENSION: {
172        // On enterprise devices, reconfirm login permission with the server.
173        policy::BrowserPolicyConnectorChromeOS* connector =
174            g_browser_process->platform_part()
175                ->browser_policy_connector_chromeos();
176        if (connector->IsEnterpriseManaged() && wildcard_match &&
177            !connector->IsNonEnterpriseUser(email)) {
178          wildcard_login_checker_.reset(new policy::WildcardLoginChecker());
179          wildcard_login_checker_->Start(
180                  ProfileHelper::GetSigninProfile()->GetRequestContext(),
181                  base::Bind(&LoginPerformer::OnlineWildcardLoginCheckCompleted,
182                             weak_factory_.GetWeakPtr()));
183        } else {
184          StartLoginCompletion();
185        }
186        break;
187      }
188      case AUTH_MODE_INTERNAL:
189        StartAuthentication();
190        break;
191    }
192  } else {
193    if (delegate_)
194      delegate_->WhiteListCheckFailed(user_context.GetUserID());
195    else
196      NOTREACHED();
197  }
198}
199
200void LoginPerformer::LoginAsLocallyManagedUser(
201    const UserContext& user_context) {
202  DCHECK_EQ(UserManager::kLocallyManagedUserDomain,
203            gaia::ExtractDomainName(user_context.GetUserID()));
204
205  CrosSettings* cros_settings = CrosSettings::Get();
206  CrosSettingsProvider::TrustedStatus status =
207        cros_settings->PrepareTrustedValues(
208            base::Bind(&LoginPerformer::LoginAsLocallyManagedUser,
209                       weak_factory_.GetWeakPtr(),
210                       user_context_));
211  // Must not proceed without signature verification.
212  if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
213    if (delegate_)
214      delegate_->PolicyLoadFailed();
215    else
216      NOTREACHED();
217    return;
218  } else if (status != CrosSettingsProvider::TRUSTED) {
219    // Value of kAccountsPrefSupervisedUsersEnabled setting is still not
220    // verified. Another attempt will be invoked after verification completion.
221    return;
222  }
223
224  if (!UserManager::Get()->AreLocallyManagedUsersAllowed()) {
225    LOG(ERROR) << "Login attempt of locally managed user detected.";
226    delegate_->WhiteListCheckFailed(user_context.GetUserID());
227    return;
228  }
229
230  SupervisedUserLoginFlow* new_flow =
231      new SupervisedUserLoginFlow(user_context.GetUserID());
232  new_flow->set_host(
233      UserManager::Get()->GetUserFlow(user_context.GetUserID())->host());
234  UserManager::Get()->SetUserFlow(user_context.GetUserID(), new_flow);
235
236  SupervisedUserAuthentication* authentication = UserManager::Get()->
237      GetSupervisedUserManager()->GetAuthentication();
238
239  UserContext user_context_copy = authentication->TransformKey(user_context);
240
241  if (authentication->GetPasswordSchema(user_context.GetUserID()) ==
242      SupervisedUserAuthentication::SCHEMA_SALT_HASHED) {
243    if (extended_authenticator_.get()) {
244      extended_authenticator_->SetConsumer(NULL);
245    }
246    extended_authenticator_ = new ExtendedAuthenticator(this);
247    // TODO(antrim) : Replace empty callback with explicit method.
248    // http://crbug.com/351268
249    BrowserThread::PostTask(
250        BrowserThread::UI,
251        FROM_HERE,
252        base::Bind(&ExtendedAuthenticator::AuthenticateToMount,
253                   extended_authenticator_.get(),
254                   user_context_copy,
255                   ExtendedAuthenticator::ResultCallback()));
256
257  } else {
258    authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
259    BrowserThread::PostTask(
260        BrowserThread::UI,
261        FROM_HERE,
262        base::Bind(&Authenticator::LoginAsLocallyManagedUser,
263                   authenticator_.get(),
264                   user_context_copy));
265  }
266}
267
268void LoginPerformer::LoginRetailMode() {
269  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
270  BrowserThread::PostTask(
271      BrowserThread::UI, FROM_HERE,
272      base::Bind(&Authenticator::LoginRetailMode, authenticator_.get()));
273}
274
275void LoginPerformer::LoginOffTheRecord() {
276  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
277  BrowserThread::PostTask(
278      BrowserThread::UI, FROM_HERE,
279      base::Bind(&Authenticator::LoginOffTheRecord, authenticator_.get()));
280}
281
282void LoginPerformer::LoginAsPublicAccount(const std::string& username) {
283  // Login is not allowed if policy could not be loaded for the account.
284  policy::BrowserPolicyConnectorChromeOS* connector =
285      g_browser_process->platform_part()->browser_policy_connector_chromeos();
286  policy::DeviceLocalAccountPolicyService* policy_service =
287      connector->GetDeviceLocalAccountPolicyService();
288  if (!policy_service || !policy_service->IsPolicyAvailableForUser(username)) {
289    DCHECK(delegate_);
290    if (delegate_)
291      delegate_->PolicyLoadFailed();
292    return;
293  }
294
295  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
296  BrowserThread::PostTask(
297      BrowserThread::UI, FROM_HERE,
298      base::Bind(&Authenticator::LoginAsPublicAccount, authenticator_.get(),
299                 username));
300}
301
302void LoginPerformer::LoginAsKioskAccount(const std::string& app_user_id,
303                                         bool use_guest_mount) {
304  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
305  BrowserThread::PostTask(
306      BrowserThread::UI, FROM_HERE,
307      base::Bind(&Authenticator::LoginAsKioskAccount, authenticator_.get(),
308                 app_user_id, use_guest_mount));
309}
310
311void LoginPerformer::RecoverEncryptedData(const std::string& old_password) {
312  BrowserThread::PostTask(
313      BrowserThread::UI, FROM_HERE,
314      base::Bind(&Authenticator::RecoverEncryptedData, authenticator_.get(),
315                 old_password));
316}
317
318void LoginPerformer::ResyncEncryptedData() {
319  BrowserThread::PostTask(
320      BrowserThread::UI, FROM_HERE,
321      base::Bind(&Authenticator::ResyncEncryptedData, authenticator_.get()));
322}
323
324////////////////////////////////////////////////////////////////////////////////
325// LoginPerformer, private:
326
327void LoginPerformer::StartLoginCompletion() {
328  DVLOG(1) << "Login completion started";
329  BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false);
330  Profile* profile = ProfileHelper::GetSigninProfile();
331
332  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
333  BrowserThread::PostTask(
334      BrowserThread::UI, FROM_HERE,
335      base::Bind(&Authenticator::CompleteLogin, authenticator_.get(),
336                 profile,
337                 user_context_));
338  user_context_.ClearSecrets();
339}
340
341void LoginPerformer::StartAuthentication() {
342  DVLOG(1) << "Auth started";
343  BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false);
344  Profile* profile = ProfileHelper::GetSigninProfile();
345  if (delegate_) {
346    authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
347    BrowserThread::PostTask(
348        BrowserThread::UI, FROM_HERE,
349        base::Bind(&Authenticator::AuthenticateToLogin, authenticator_.get(),
350                   profile,
351                   user_context_));
352    // Make unobtrusive online check. It helps to determine password change
353    // state in the case when offline login fails.
354    online_attempt_host_.Check(profile, user_context_);
355  } else {
356    NOTREACHED();
357  }
358  user_context_.ClearSecrets();
359}
360
361void LoginPerformer::OnlineWildcardLoginCheckCompleted(
362    policy::WildcardLoginChecker::Result result) {
363  if (result == policy::WildcardLoginChecker::RESULT_ALLOWED) {
364    StartLoginCompletion();
365  } else {
366    if (delegate_)
367      delegate_->WhiteListCheckFailed(user_context_.GetUserID());
368  }
369}
370
371}  // namespace chromeos
372